グレージング
From M.U.G.E.N Wiki
Contents |
What is grazing?
Grazing is a game mechanic that comes from Touhou fighter games. It allows avoiding hits from projectiles by running through them so that they can't hit you properly. It is a way of evasion. Similar to dodges, however this one is meant for avoiding projectiles, not physical hits.
What is it good for?
If you are making a Touhou, or other heavy projectile user character, or full game, grazing can prevent the situation where you can't ever get close to the opponent from the projectiles fired, which would render all the normal physical attacks or any other short range attacks completely useless. If you are not making a projectile user, implementing grazing can give you a fair chance against projectile users, so it'd make your character a bit more versatile.
What types of grazing are possible?
There are three reasonable ways to do it.
- One that avoids all projectiles, which is how grazing worked in the original Touhou games.
- One that avoids normal and special projectiles, but not supers/hypers, which is a lot more balanced and reasonable way.
- One that only avoids normal projectiles, which is not very useful : a lot of characters have all their projectiles coded as specials.
How do I implement it?
Grazing is always implemented on moves where the character is moving quickly. This means the running, super jump and air dash 99% of time, but in a few cases, a rush/running attack can also have it. First of all, make a list of states you want grazing to be active in. In the simplest case, that'd be the states 100-119 (all running and air dash states), but it really depends on your coding. To implement grazing properly, you'll need to add three modifications to your character code, the evasion, the effect, and the reversal parts.
The evasion coding
This one is the most important, yet also the easiest. You have to add the appropriate Nothitby controller into your state -3. In case of grazing that doesn't work against hypers, that would look something like this :
[State -3] Type=NotHitBy Trigger1=StateNo=[100,119] value2=,NP,SP
Note that you have to add your own state numbers for the triggers. It must always be placed into state -3, we do not want to accidentally trigger it in a custom state of the opponent. Pay attention to the 2 in "value2"! It is there to prevent other Nothitby controllers executed in your character from overriding this one. Of course, if you already use both Nothitby slots, you have to be careful to combine the effects from various evasions properly.
The effect coding
While grazing, characters usually leave behind an afterimage. Add this (or the kind of afterimage you want instead) to all of your states that need grazing.
[State 100] Type = AfterImage Trigger1 = Time = 1 Trans = Add Time = 2 Length = 10 PalBright = 0,0,0 PalContrast = 0,0,150 PalAdd = 0,0,25 PalMul = .5,.5,.5
Then, add this to your state -3
[State -3] Type = AfterImageTime Trigger1 = Stateno=[100,119] Time = 2
Again, replace the trigger with your own state numbers. This lets you keep the afterimage on only while the character is still in the grazing state.
The reversal coding
Now, this part is optional, but recommended. In the original Touhou games, when a projectile was grazed, even though it wasn't hitting, most of the time, it was still removed anyway, and a sound was played, and an effect was displayed. This part of the code is responsible for that. Place this in your state -3 to create the helper necessary for this.
[State -3] Type = Helper Triggerall = NumHelper(162)=0 Trigger1 = Stateno=[100,119] StateNo = 162 ID = 162 Name = “GrazeEffect” Pos = 20,-40 PosType = P1 Ownpal = 1 IgnoreHitPause = 1 Persistent = 1 Size.XScale = 1 Size.YScale = 1 supermovetime=99999 pausemovetime=99999
Don't forget to replace the trigger with your own state number(s). Use whichever state you want for your helper, 162 was my choice, but it's not recommended as it is in the reserved range. Same goes for the animations.
For the helper, the general idea is to use ReversalDef to reverse the Hitdef on the projectiles, to signal that the projectile didn’t hit, wasn’t guarded, yet it still needs to be removed. Obviously, it assumes that the projectiles are coded to remove themselves when they are reversed, in characters coded taking grazing into account, that is the case. This gives you options while coding projectile moves to make ones that aren’t removed by grazing if you want, you just need to reactivate the hitdef on them when MoveReversed is not 0. Using MoveReversed>5 or higher is recommended though to avoid triggering the grazing effect too many times. ReversalDef, unfortunately doesn’t work on projectiles created by the projectile sctrl however. To detect those, we’ll need to create a projectile of our own, which, by colluding with the opposing projectile, gets canceled.
The code looks like this :
[Statedef 162] MoveType=I Physics=N anim=162 [State 162] Type=BindToParent Trigger1=1 [State 162] Type=StateTypeSet Trigger1=parent,StateType=S StateType=S [State 162] Type=StateTypeSet Trigger1=parent,StateType=A StateType=A [State 162] Type=ReversalDef Trigger1=1 reversal.attr = SCA,NP,SP sparkno=-1 hitsound = S0,14 hitonce=0 [State 162] Type = Explod Trigger1 = MoveHit = 1 Trigger2 = (Root,ProjCancelTime(162) = 1) Trigger3 = root,NumProjId(162)=0 Trigger3 = time>0 Anim = 6111 ID = 6010 Pos = random %21-10,-60+random %30 Scale = .5,.5 Facing = 1-2*(random %2) VFacing = 1-2*(random %2) SprPriority = 5 PauseMoveTime = 99 Supermovetime = 99 [State 162] Type = PlaySnd Trigger1 = root,NumProjId(162)=0 Trigger1 = time>0 value=S0,14 [State 162] Type = Projectile Trigger1 = 1 Attr = A, NP GetPower = 0 AnimType = Back PauseTime = 0,0 OffSet = 0,0 Velocity = 0,0 ProjAnim = 163 ProjRemAnim = -1 ProjHits = 0 ProjRemove = 1 ProjRemoveTime = 1 ProjPriority = 1 ProjID = 162 SuperMoveTime = 1 PauseMoveTime = 1 HitFlag = P GuardFlag = MA SparkNo = -1 GuardSparkNo = -1 SparkXY = 0,999 hitsound = S0,14 GuardSound = -1 Guard.Dist = 0 ID=162 [State 162] Type=Destroyself Trigger1=parent,stateno!=[100,115] Trigger1=parent,stateno!=13300
Anim 162 is an empty animation with a single clsn1 box on it, that covers the player. This one is used by the helper to activate ReversalDef. Anim 163 is the same as 162, but also has a clsn2 box on it of the same size. This one is used as the invisible projectile, that will be canceled out by the opponent’s projectiles. You can use
Trigger1 = MoveHit = 1 Trigger2 = (Root,ProjCancelTime(162) = 1) Trigger3 = root,NumProjId(162)=0 Trigger3 = time>0
as triggers to detect a grazed projectile. You can play a grazing sound, display an explod, or do something else, like gain power or build up a special bar when grazing happens, that part is up to you. The example code plays the sound S0,14 and displays explod 6111.
This guide was created by Seravy