;---
;sys::combo_indicate_nums
;; コンボ数計算
[state 0]
type=varset ;note the change from varadd
trigger1=(var(11)/10000)=(var(11)%10000) && (playerid(var(15)),stateno!=[120,159]) && (playerid(var(15)),ctrl=0)
;old; trigger1=var(40)>(playerid(var(15)),life) && (var(9)&16) ;;<-life changed && getting damage
trigger1=var(9)&16
;old; var(11)=1 +( var(12):=var(12)+(playerid(var(15)),stateno=[5000,5199]) )*0 ;;<-real combo set
var(12)=(var(12)/10000)*10000 + playerid(var(15)),GetHitVar(hitcount)
[state 0] ;this controller is new
type=varset
trigger1=var(12)%10000 != var(11)%10000
var(11)=(var(11)/10000)*10000 + var(12)%10000
Okay, after playing with this a bit more (and using more than one test character), I found a couple problems with this, which I have now fixed.
The first problem was that var(9)&16 (the "taking damage" flag) gets set whether or not the opponent actually took a hit, and GetHitVar(hitcount) never resets itself back to 0 (it just starts counting from 1 again the next time a combo starts), so if the opponent blocked your next attack after you pulled off a big combo, you'd get the combo result popup again without the combo counter ever appearing (and it would spam itself to fill up all available notification slots, too); a simple GetHitVar(guarded) check fixed that.
Secondly, however, GetHitVar(hitcount) obviously doesn't account for hitadd state controllers and and numhits attributes on hitdefs, so some way to manually tell the system that an extra hit has occurred in such a scenario is still needed; with a shrug, I adapted that code snippet @Shiyo Kakuge posted earlier (for manually incrementing the combo counter). I had to change the combo meter code to use an extra variable for it to work; I wound up giving var(11)'s old function to var(10) and making var(11) the "artificial combo inflation" variable since var(10) didn't seem to be in use, despite the _svc common1.cns claiming it is, and this way code can increment the counter in both the unmodified and modified versions of add004. Since the character I was testing this with started getting credit for combos involving hitadd controllers, I think this version of the code is ready for sharing.
Here's my current combo meter code in its entirety (note that I did my work in the base add004 common1.cns, so if there are differences in the combo meter code in the _bs or _svc versions, you'll need to adapt my changes accordingly):
;------------------------
;------------------------
; combo indicator, code by k' d(^-^)b
; modified by MageKing17
; コンボ数表示、K'さんより
; v10: nums Temp + Now ([0-9999]*1000 + [0-9999])
; v11: extra hits
; v12: real combo + timer (timer[0-9999]*1000 + [0-9999])
; v13: pos_x / timer
; v14: temp: combo_counter / hittype
;--- ---
; >03 hits: good
; >05 hits: great
; >10 hits: beautiful
; >15 hits: fantastic
; >20 hits: marvelous
; >25 hits: m.u.g.e.n
;;--- announcer.combine + msg_combo (opponent)
;sys::sound_announcer_combo
[state 0]
type=playsnd
trigger1=(roundstate=2) && var(38)<99999999 && numenemy
trigger1=(enemy,sysfvar(0)>0) && (playeridexist(floor(enemy,sysfvar(0))))
trigger1=(playerid(floor(enemy,sysfvar(0))),var(0)=90900) && (playerid(floor(enemy,sysfvar(0))),var(10)%10000<1) && var(14):=(playerid(floor(enemy,sysfvar(0))),var(12)%10000) + (playerid(floor(enemy,sysfvar(0))),var(11))
trigger1=var(14)>2 || playerid(floor(enemy,sysfvar(0))),cond(1, var(11):=0, 0)
trigger1=(var(38):=var(38)*100+10+(var(14)>4)+(var(14)>9)+(var(14)>14)+(var(14)>19)+(var(14)>24)) && (var(14)>4) && (var(7)&64) ;; system_switch
value=f10100,3 +(var(14)>9)
channel=1
abspan=ifelse(teamside=1,-1,1)*facing*320
;sys::combo_real_reset
[state 0]
type=varset
trigger1=!(var(10)%10000)
var(12)=0
;---
;sys::combo_indicate_nums
;; コンボ数計算
[state 0]
type=varset
trigger1=(var(10)/10000)=(var(10)%10000) && (playerid(var(15)),stateno!=[120,159]) && (playerid(var(15)),ctrl=0)
;old; trigger1=var(40)>(playerid(var(15)),life) && (var(9)&16) ;;<-life changed && getting damage
trigger1=var(9)&16
;old; var(10)=1 +( var(12):=var(12)+(playerid(var(15)),stateno=[5000,5199]) )*0 ;;<-real combo set
var(12)=(var(12)/10000)*10000 + playerid(var(15)),GetHitVar(hitcount)*(!playerid(var(15)),GetHitVar(guarded))
[state 0]
type=varset
trigger1=!(var(10)%10000)
var(11)=1-playerid(var(15)),GetHitVar(hitcount)
[state 0]
type=varset
trigger1=1
var(10)=(var(10)/10000)*10000 + cond(var(12)%10000, cond(var(12)%10000 + var(11) > 1, var(12)%10000 + var(11), 1), 0)
[state 0]
type=varset
trigger1=var(10)/10000 != var(10)%10000
var(12)=var(12)%10000
;sys::combo_indicate_init
[state 0]
type=varset
triggerall=(var(10)%10000)>0
trigger1=!(var(9)&16) ;;<-not getting damage
trigger2=(roundstate!=2) || (var(9)&4096) ;;<-bonus stage
trigger3=(playerid(var(15)),ctrl)||(playerid(var(15)),stateno=[0,159])||(playerid(var(15)),stateno=8200)
var(10)=0
;---
;;>>@Config.Combo.Pos>>
;sys::combo_d_pos ;; v13: pos x (240p)
[state 0]
type=null
trigger1=(var(10)%10000=2) && ((var(10)/10000)!=(var(10)%10000))
trigger1=1|| var(13):=ifelse(teamside=2,-150,floor(var(3)/fvar(0))+150) ;;<-init pos x
trigger2=(var(10)%10000>1) && (var(10)/10000)<(var(10)%10000) ;;<-combo update
trigger2=1|| var(13):=var(13)+4*ifelse(teamside=2,-1,1) ;;<-shake
;sys::combo_d_pos_x_shift
[state 0]
type=varadd
;op; trigger1=numexplod(97800)
trigger1=(teamside=2 && var(13)<50) || (teamside=1 && var(13)>270)
var(13)=(ifelse(teamside=2,50,floor(var(3)/fvar(0))-50)-var(13))/3+teamside*2-3
;---
;sys::combo_d_cls
[state 0]
type=removeexplod
trigger1=(var(10)%10000>1) && ((var(10)/10000)!=(var(10)%10000) || (var(12)/10000=0))
id=97800 +( var(12):= (var(12)%10000) +280000 )*0 ;;<-view time reset
[state 0]
type=removeexplod
trigger1=!numexplod(97800)
id=97801
[state 0]
type=removeexplod
trigger1=!numexplod(97800)
id=97802
[state 0]
type=removeexplod
trigger1=!numexplod(97800)
id=97803
[state 0]
type=removeexplod
trigger1=!numexplod(97800)
id=97804
[state 0]
type=removeexplod
trigger1=!numexplod(97800)
id=97805
;---
;sys::combo_d_bg
[state 0]
type=explod
id=97800
triggerall=(var(7)&4) ;; system_switch
trigger1=(var(10)%10000>1) && !numexplod(97800)
anim=f300155 +( var(14):=(playerid(var(15)),stateno!=[5000,5199]) ) ;;<-hit type
space=screen
postype=left
sprpriority=-1
ownpal=1
scale=0.5,0.15
facing=ifelse(teamside=1,-1,1)
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
;sys::combo_d_bg_shadow
[state 0]
type=explod
id=97800
trigger1=numexplod(97800)=1
anim=f300157
space=screen
postype=left
sprpriority=-3
ownpal=1
scale=0.7,1
facing=ifelse(teamside=1,-1,1)
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
;sys::combo_d_hits
[state 0]
type=explod
id=97801
trigger1=numexplod(97800) && !numexplod(97801)
anim=f300150+var(14)
space=screen
postype=left
sprpriority=0
ownpal=1
scale=0.5,0.5
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
;sys::combo_d_nums
[state 0]
type=explod
id=97802
trigger1=(var(10)%10000>1) && numexplod(97800) && !numexplod(97802)
anim=f300050+((var(10)%10000)%10) +var(14)*10
space=screen
postype=left
sprpriority=1
ownpal=1
scale=0.25,0.25
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
[state 0]
type=explod
id=97803
trigger1=(var(10)%10000>9) && numexplod(97800) && !numexplod(97803)
anim=f300050+(((var(10)%10000)/10)%10) +var(14)*10
space=screen
postype=left
sprpriority=1
ownpal=1
scale=0.25,0.25
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
[state 0]
type=explod
id=97804
trigger1=(var(10)%10000>99) && numexplod(97800) && !numexplod(97804)
anim=f300050+(((var(10)%10000)/100)%10) +var(14)*10
space=screen
postype=left
sprpriority=1
ownpal=1
scale=0.25,0.25
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
[state 0]
type=explod
id=97805
trigger1=(var(10)%10000>999) && numexplod(97800) && !numexplod(97805)
anim=f300050+(((var(10)%10000)/1000)%10) +var(14)*10
space=screen
postype=left
sprpriority=1
ownpal=1
scale=0.25,0.25
bindtime=-1
ignorehitpause=1
supermovetime=-1
pausemovetime=-1
;---
;sys::combo_d_changed
[state 0]
type=modifyexplod
trigger1=numexplod(97800)
id=97800
postype=left
pos=floor(var(13)*fvar(0)), floor(75*fvar(0))
[state 0]
type=modifyexplod
trigger1=numexplod(97801)
id=97801
postype=left
pos=floor((var(13)+(numexplod(97803)+numexplod(97804)+numexplod(97805))*7.5-17)*fvar(0)), floor(69*fvar(0))
[state 0]
type=modifyexplod
trigger1=numexplod(97802)
id=97802
postype=left
pos=floor((var(13)+(numexplod(97803)+numexplod(97804)+numexplod(97805))*7.5-9)*fvar(0)), floor(79*fvar(0))
[state 0]
type=modifyexplod
trigger1=numexplod(97803)
id=97803
postype=left
pos=floor((var(13)+(numexplod(97803)+numexplod(97804)+numexplod(97805))*7.5-24)*fvar(0)), floor(79*fvar(0))
[state 0]
type=modifyexplod
trigger1=numexplod(97804)
id=97804
postype=left
pos=floor((var(13)+(numexplod(97803)+numexplod(97804)+numexplod(97805))*7.5-39)*fvar(0)), floor(79*fvar(0))
[state 0]
type=modifyexplod
trigger1=numexplod(97805)
id=97805
postype=left
pos=floor((var(13)+(numexplod(97803)+numexplod(97804)+numexplod(97805))*7.5-54)*fvar(0)), floor(79*fvar(0))
;---
;sys::combo_update_counter
[state 0]
type=varset
trigger1=(var(10)/10000)!=(var(10)%10000)
var(10)=(var(10)%10000)*10001
;sys::combo_d_display_time
[state 0]
type=varadd
trigger1=(var(12)>=10000)
var(12)=-10000
;;--- ---
;[state 0] ; combo
; type=displaytoclipboard
; trigger1=1
; text="attack=[ %d ] gethit=[ %d ] extra_combo=[ %d ] real=[ %d ] type=[ %d ]"
; params=playerid(var(15)),gethitvar(hitcount), var(10),var(11),var(12),var(14)
; ignorehitpause=1
;;--- ---
You may have noticed I changed the sprpriority of the combo meter's explods; I found it weird that the combo meter would sometimes go behind characters' super backgrounds, so I bumped their priority up to match that of the power bars' explods. If you don't like that change, well, feel free to revert it; it's not like anybody's stopping you.
If you want the end-of-match ranking to also accommodate extra combo hits, you'll need to modify the relevant controller appropriately:
;sys::rank_get_hitcombo
[state 0]
type=varset
trigger1=numenemy && roundstate=2
trigger1=(enemy,sysfvar(0)>0) && (playeridexist(floor(enemy,sysfvar(0))))
trigger1=(playerid(floor(enemy,sysfvar(0))),var(0)=90900) && fvar(3)<((playerid(floor(enemy,sysfvar(0))),var(12)%10000)+(playerid(floor(enemy,sysfvar(0))),var(11)))
fvar(3)=(playerid(floor(enemy,sysfvar(0))),var(12)%10000)+(playerid(floor(enemy,sysfvar(0))),var(11)) ;;<-real combo
And here's the modified snippet I used as a base for manually incrementing the combo meter:
[state 0]
type=null
triggerall=numenemy
triggerall=(enemy,sysfvar(0)>0) && (playeridexist(floor(enemy,sysfvar(0))))
triggerall=playerid(floor(enemy,sysfvar(0))),var(0)=90900
trigger1=1|| playerid(floor(enemy,sysfvar(0))),cond(1,var(11):=var(11)+1,0)
I made the first three conditions triggerall because I had one condition that needed to be split into trigger1 and trigger2, so this was the most convenient way to do it. Yes, that is the only difference; it's still more convenient to have the code repeated here like this, for copy&pasting.
The way I used it was to find every hitadd controller and paste that controller under it, and then copy its trigger condition(s) over. For instance, if I had this:
[State 4001, hitadd]
type = hitadd
trigger1= animelem = 6 || animelem = 25
value = 1
I'd put this below it:
[state 0]
type=null
triggerall=numenemy
triggerall=(enemy,sysfvar(0)>0) && (playeridexist(floor(enemy,sysfvar(0))))
triggerall=playerid(floor(enemy,sysfvar(0))),var(0)=90900
trigger1=animelem = 6 || animelem = 25
trigger1=1|| playerid(floor(enemy,sysfvar(0))),cond(1,var(11):=var(11)+1,0)