A while back, i made a method for SFIV damage scaling. This was unwise as it relied on AttackMulSet which isn't completely reliable. While studying HDBZ code (reasons) i decided to make a Sean character test out my current capabilities with making characters. While doing so i developed a method of calculating damage similar to SFIV. For those who don' know, in SFIV the first 2 hits are unscathed, with the next hit doing 80% damage, then 70% and so on. Unfortunately i haven't been able to figure out a good method for Life Scaling yet, so Fvar(9) is unused in this code for now. If anyone has a method, please let me know. With that out of the way, heres what ya need
4 Available Vars, in this example i use Fvars 8,10, 11 and 13.
In this example, Far(8) is used to see if the move is a counterhit, adding an additional 20% to the damage if it is. Fvar(10) is the damage scaling percent, Fvar(13) keeps track of how many hits are in the combo, and Fvar(11) is the final calculation. Finally, contained at the bottom if what should be put in to your hitdefs damage parameter for the scaling to work. It just checks if theres more than 2 hits in the combo, then applies the scaling. Otherwise its unscaled.
OLD, PLEASE REFER TO NEW CODE
Spoiler, click to toggle visibilty
;===============================================================================
; ------- Damage Dampener --------
;===============================================================================
;Used to add Counter Hit Scaling
[State -2, Counter Flag]
type = VarSet
trigger1 = NumEnemy
fvar(8) = (EnemyNear, MoveType = A)
ignoreHitPause = 1
;Keeps track of current combo count
[State -2, Hit Count]
type = VarAdd
trigger1 = !IsHelper
trigger1 = MoveHit = 1
trigger1 = !HitPauseTime
trigger1 = !(HitDefAttr = SCA, AT)
fvar(13) = 1
[State -2, Hit Count Reset]
type = VarSet
trigger1 = NumEnemy && fvar(13)
trigger1 = (EnemyNear, MoveType != H) && (EnemyNear, StateNo != 5300)
fvar(13) = 0
ignoreHitPause = 1
[State -2, Scaling]
type = VarSet
trigger1 = 1
fvar(10) = ifElse(fvar(13) > 2, 1 - 0.10 * (fvar(13) - 1), 1)
ignoreHitPause = 1
;This is my favourite bit of code. How it works is like this
;If Fvar(13) (Hit Count) is over 2, the value become 1 - 0.10 times Hit Count minus 1. This bascially means
;that the value is calculated by how many hits are in the combo minus 1, so at minimum the value becomes 2,so
;its really saying
;Ifelse(fvar(13) > 2, 1- 0.10 * 2, 1)
;And since the hit count rises as the combo continues, it becomes 3, 4, 5, etc basically subtracting 20, then
;30 percent and so on from the damage. So if you did say, LP,LP,LP, this is what happens
;LP = Fvar(13) = 1, no calculation, damage = 25
;LP = Fvar(13) = 2, no calculation, damage = 25
;LP = Fvar(13) = 3, - 20%, damage = 20
[State -2, Scaling Limit]
type = VarSet
trigger1 = fvar(10) < 0
fvar(10) = 0.10
ignoreHitPause = 1
;Minimum of 10%
[State -2, Root Dampener]
type = VarSet
trigger1 = 1
fvar(11) = fvar(10) * ifElse(fvar(8), 1.2, 1) ;* fvar(9)
ignoreHitPause = 1
;Hitdef
;damage = ceil(ifElse(fvar(13) > 2, fvar(11) * BASE_DAMAGE , BASE_DAMAGE))
This code isn't perfect, and i'd rather have total control over when damage scaling takes effect and how instead of relying on Movehit, but for now this code should serve as a great starting point for anyone wanting to add a lil bit of sophistication to their characters but have difficulty grasping damage scaling (i know i did) so if theres anything wrong with this code please let me know. With that have a good day and hope this helps!
EDIT
My sleep patterns been fucked recently, i apologise for my idiocy XD There are a bunch of flaws in that code. When i tested it it worked at the time, but now i see there are multiple errors, suchl as the scaling applying too late. I have not only fixed that issue, but have simplified the damage template, and have even added Life Scaling! Now when the opponent is at 50% or less, they have damage reduced by 10%, 15 at 30% and lower. Everything still applies, except the whole Fvar(9) stuff thats being used now.
NEW
Spoiler, click to toggle visibilty
;===============================================================================
; ------- Damage Dampener --------
;===============================================================================
;Used to add Counter Hit Scaling
[State -2, Counter Flag]
type = VarSet
trigger1 = (enemynear, movetype = A)
fvar(8) = 1
ignoreHitPause = 1
[State -2, Counter Flag Reset]
type = VarSet
trigger1 = (enemynear,movetype != A)
fvar(8) = 0
ignoreHitPause = 1
;Decreases damage if opponent has 50 0r 30% life
[State -2, Life Scaling]
type = varset
trigger1 = (enemynear, life > lifemax * 0.50) ;No scaling if over 50% life
fvar(9) = 1
ignorehitpause = 1
[State -2, Life Scaling reduction1]
type = varset
trigger1 = 1
fvar(9) = ifelse((enemynear, life <= lifemax * 0.50), (1 - 0.10), 1)
ignorehitpause = 1
[State -2, Life Scaling reduction2]
type = varset
trigger1 = fvar(9) < 1
fvar(9) = ifelse((enemynear, life <= lifemax * 0.30), (1 - 0.15), 0.90)
ignorehitpause = 1
;Keeps track of current combo count
[State -2, Hit Count]
type = VarAdd
trigger1 = !IsHelper
trigger1 = MoveHit = 1
trigger1 = !HitPauseTime
trigger1 = !(HitDefAttr = SCA, AT)
fvar(13) = 1
[State -2, Hit Count Reset]
type = VarSet
trigger1 = NumEnemy && fvar(13)
trigger1 = (EnemyNear, MoveType != H) && (EnemyNear, StateNo != 5300)
fvar(13) = 0
ignoreHitPause = 1
[State -2, Scaling]
type = VarSet
trigger1 = 1
fvar(10) = ifElse(fvar(13) >= 2, 1 - (0.10 * fvar(13)), 1)
ignoreHitPause = 1
[State -2, Scaling Limit]
type = VarSet
trigger1 = fvar(10) < 0
fvar(10) = 0.10
ignoreHitPause = 1
[State -2, Root Dampener]
type = VarSet
trigger1 = 1
fvar(11) = fvar(10) * ifElse(fvar(8) = 1, 1.2, 1) * fvar(9)
ignoreHitPause = 1
;Hitdef
;damage = ceil(fvar(11) * BASE_DAMAGE)
EVEN NEWER
Spoiler, click to toggle visibilty
;===============================================================================
; ------- Damage Dampener --------
;===============================================================================
;var(3) = Number of hits container
;var(4) = Counter Hit check
;fvar(9) = Life scaling var
;fvar(11) = root dampener
;Place this in hitdefs to apply scaling to moves
;damage = ceil(fvar(11) * BASE_DAMAGE)
;Keeps track of current combo count
[State -2, Hit Count]
type = VarAdd
trigger1 = !IsHelper
trigger1 = MoveHit = 1
trigger1 = !HitPauseTime
trigger1 = !(HitDefAttr = SCA, AT)
var(3) = 1
ignoreHitPause = 1
[State -2, Hit Count Reset]
type = Null
triggerall = NumEnemy
triggerall = (EnemyNear, MoveType != H) && (EnemyNear, StateNo != 5300)
trigger1 = 1 || var(3) := 0
trigger1 = 1 || fvar(10) := 1
ignoreHitPause = 1
[State -2, Track Vars]
type = Null
;Life Scaling
trigger1 = 1 || fvar(9) := 1 - (0.10*(enemynear,life<= enemynear,lifemax *0.50)) - (0.05*(enemynear,life<= enemynear,lifemax *0.30))
;Counter Hit check
trigger1 = 1 || var(4) := cond((enemynear, movetype = A), 1, 0)
ignorehitpause = 1
[State -2, Hit Scaling]
type = Null
;Hit Scaling
trigger1 = fvar(10) = 0 ^^ var(3) ;Sets initially once, and then only sets var if in a combo
trigger1 = 1 || fvar(10) := cond(var(3) < 2, 1, 1-(0.10*(var(3)-1)))
trigger1 = cond(fvar(10) < 0.1,1 || fvar(10) := 0.1,0)
;Root Dampender
trigger2 = 1 || fvar(11) := fvar(10) * cond(var(4) = 1, 1.2, 1) * fvar(9)
ignorehitpause = 1
Okay, I tried to look into the issue some more, and I found that changing the vars didn't do anything. I also looked into State 5900, I'm not sure what it could be that's preventing the damage scaling to just stop working after around one. I mean, nothing seems wrong here but I'm not 100% sure.
Here's the code for the character in State 5900:
; Initialize (at the start of the round)
[Statedef 5900]
type = S
[State 5900, 1] ;Clear all int variables
type = VarRangeSet
trigger1 = roundsexisted = 0
value = 0
[State 5900, 2] ;Clear all float variables
type = VarRangeSet
trigger1 = roundsexisted = 0
fvalue = 0
[State 5900, 3] ;Intro for round 1
type = ChangeState
trigger1 = roundno = 1
value = 190
At first glance there's a major issue with this code in that it's based on the current number of hits, when the main point of SF4 (and SF5's) damage scaling is that all moves are treated the same, no matter how many hits they do. It's not that the third hit should do 80% damage, but that the third attack should.
Also how do fireballs work with this code?
Other random observations that may help people who are learning how to code for Mugen:
[State -2, Hit Count]
type = VarAdd
trigger1 = !IsHelper
This check only makes a difference for player type helpers, which generally shouldn't be used anyway.
trigger1 = !HitPauseTime
trigger1 = !(HitDefAttr = SCA, AT)
var(3) = 1
ignoreHitPause = 1
If you removed the ignorehitpause line you wouldn't need to check if the hitpause was over.
triggerall = (EnemyNear, MoveType != H) && (EnemyNear, StateNo != 5300)
It's better to use the P2 triggers when possible (P2movetype and P2stateno), as Enemynear also checks dead enemies while P2 ignores them.
Also it's just easier to use an AttackMulSet than making expressions for all Hitdef damages. The only reason I did the latter at one point was to implement minimum damage in each Hitdef, which SF4 doesn't do.
Sorry if this all comes out the wrong way. I personally learned a lot when people first picked apart my codes (hello Winane).