Info and Updates
I've put together several options for round shadows that mimic Street Fighter 3's round shadows. These were all designed to be simple copy paste use, for perfect conversion you would probably want to reference a sprite table and not a universal math formula since some of the characters in SF3 don't stick to the same rules as others.
*IKEMEN users,
This version is still compatible with any version of IKEMEN since it uses classic mugen triggers and sctrls but Foobs has put together a really great version just for IKEMEN that you should checkout. (Only compatible with the nightly build as of April 1st, 2024)
https://github.com/RealFoobs/SF3-like-Shadows
* Two other versions that use M.U.G.E.N's actual shadow mechanics will be posted here soon.
Download SF3 Shadows sprites. I have each one set as their own animation starting at 8530 with time set to -1 for each in the air file. Pick the version you like and paste it in you characters. This code now uses explods so you can use fightfx.air now!
This goes in the characters Air file
*If you don't have a blank animation already
; Blank
[Begin Action 9741]
-1,0, 0,0, -1
This goes in [statedef -2] for players and in helpers for projectiles
*for projectiles, AssertSpecial noshadow will need to be in every state the projectile uses.
[state -2, shadow]
type = helper
trigger1 = !numhelper(33333399+ID)
name = "shadow"
ID = 33333399+ID
stateno = 33333399
postype = p1
ownpal = 1
keyctrl = 0
supermovetime = 2147483647
pausemovetime = 2147483647
ignorehitpause = 1
[State shadow]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
Your pick goes in CNS or data/common1.cns
Version 1 | Scale based round shadows
[Not how it’s actually done in sf3, this has smoother size transitions and only uses one sprite(8.png in the shadows download). There are some options in the 'scale' parameter of angledraw. You can use it as default and the shadow's size will be calculated based on the width in the character's constant or you can adjust your base shadow size manually. ]
;=========================================================================
;Scale based round shadows by Inktrebuchet
;=========================================================================
[Statedef 33333399]
type = A
movetype = I
physics = N
ctrl = 0
velset = 0, 0
anim = 9741 ; Blank Animation
[State 33333399, 1]
type = BindToParent
trigger1 = PlayerIdExist(parent,ID)
time = 1
facing = 1
pos =0,-Parent,Pos Y
ignorehitpause = 1
[State 33333399, 2]
type = RemoveExplod
trigger1 = 1
ignorehitpause = 1
[State 33333399, 3];Shadow for player
type = Explod
trigger1 = Time ;This is to correct a 1 frame delay in shadow pos when helper is first spawned
trigger1 = NumExplod(8530) = 0
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = !Parent,IsHelper
id = 8530
anim = 8530
postype = p1
pos = 0,0
;scale = (.47 - (((.47/(96/cond(abs(Parent,Pos Y)+.0001 < 96, abs(Parent,pos Y)+.00001, 96)))))) + .6 + (.0) * Const(size.xscale), (.3 - ( ( (.3/(96/cond(abs(Parent,Pos Y)+.0001 < 96, abs(Parent,Pos Y)+.00001, 96)))))) + .8 + (.0) * Const(size.yscale) ;The last float number in () is to adjust base shadow size. This number should be the same for x and y.
scale = ((.47 - (((.47/(96/cond(abs(Parent,Pos Y)+.0001 < 96, abs(Parent,pos Y)+.00001, 96)))))) + .6 )/(100.0/(Parent,Const(size.ground.back) + Parent,Const(size.ground.front))) * 2 * Const(size.xscale) , ((.3 - ( ( (.3/(96/cond(abs(Parent,Pos Y)+.0001 < 96, abs(Parent,Pos Y)+.00001, 96)))))) + .8)/(100.0/(Parent,Const(size.ground.back) + Parent,Const(size.ground.front))) * 2 * Const(size.yscale) ;Bases shadow size on character width
trans = addalpha
alpha = 128,128
removetime = -1
sprpriority = -4
ignorehitpause = 1
[State 33333399, 4];Shadow for projectile
type = Explod
trigger1 = Time ;This is to correct a 1 frame delay in shadow pos when helper is first spawned
trigger1 = NumExplod(8531) = 0
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = Parent,IsHelper
id = 8530
anim = 8530
postype = p1
pos = 0,0
scale = (.47 - (((.47/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,Pos Y)+.00001, 96)))))) + .6 + (-.3) * Const(size.xscale), (.3 - ( ( (.3/(96/cond(abs(Parent,Pos Y)+.0001 < 96, abs(Parent,Pos Y)+.00001, 96)))))) + .8 + (-.3) * Const(size.yscale) ;The last float number in () is to adjust base shadow size. This number should be the same for x and y.
trans = addalpha
alpha = 128,128
removetime = -1
sprpriority = -4
ignorehitpause = 1
[State 33333399, 5] ;*This may need to be adjusted for some projectiles
type = RemoveExplod
trigger1 = !PlayerIdExist(parent,ID)
trigger2 = PlayerIdExist(parent,ID)
trigger2 = Parent, IsHelper
trigger2 = Parent, MoveContact
trigger2 = Parent, Movetype != A
ignorehitpause = 1
[State 33333399, 6]
type = DestroySelf
trigger1 = Time
trigger1 = !NumExplod(8530)
ignorehitpause = 1
;----------------------------
Version 2 | Sprite based round shadows
[This is the more accurate to sf3 version to use. Base shadow sprite can be changed in the 'anim' parameter of changeanim. ]
;=========================================================================
;Sprite based round shadows by Inktrebuchet
;=========================================================================
[Statedef 33333399]
type = A
movetype = I
physics = N
ctrl = 0
velset = 0, 0
anim = 9741 ; Blank Animation
[State 33333399, 1]
type = BindToParent
trigger1 = PlayerIdExist(parent,ID)
time = 1
facing = 1
pos =0,-Parent,Pos Y
ignorehitpause = 1
[State 33333399, 2]
type = RemoveExplod
trigger1 = 1
ignorehitpause = 1
[State 33333399, 3];Shadow for projectile
type = Explod
trigger1 = Time ;This is to correct a 1 frame delay in shadow pos when helper is first spawned
trigger1 = NumExplod(8531) = 0
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = !Parent,IsHelper
id = 8530
anim = 8530 + ceil(cond(abs(Parent,pos y) < 96, abs(Parent,pos y +.00001), 96) / 12) + (7) ;The last number in () is to adjust base shadow size.
scale = Const(size.xscale), Const(size.yscale)
postype = p1
pos = 0,0
trans = addalpha
alpha = 128,128
shadow = -1
removetime = -1
sprpriority = -4
ignorehitpause = 1
[State 33333399, 4];Shadow for projectile
type = Explod
trigger1 = Time ;This is to correct a 1 frame delay in shadow pos when helper is first spawned
trigger1 = NumExplod(8531) = 0
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = Parent,IsHelper
id = 8530
anim = 8550 ;Projectiles only have one shadow size in sf3
scale = Const(size.xscale), Const(size.yscale)
postype = p1
pos = 0,0
trans = addalpha
alpha = 128,128
shadow = -1
removetime = -1
sprpriority = -4
ignorehitpause = 1
[State 33333399, 5] ;*This may need to be adjusted for some projectiles
type = RemoveExplod
trigger1 = !PlayerIdExist(parent,ID)
trigger2 = PlayerIdExist(parent,ID)
trigger2 = Parent, IsHelper
trigger2 = Parent, MoveContact
trigger2 = Parent, Movetype != A
ignorehitpause = 1
[state 33333399, 6]
type = DestroySelf
trigger1 = Time
trigger1 = !NumExplod(8530)
ignorehitpause = 1
;----------------------------
Old versions you shouldn't care about because compatibility is important:
Spoiler: helper based, compatible with 1.1b stages but can't use fight.sff sprites so harder to add to all characters (click to see content)
This goes in [statedef -2] for players and in helpers for projectiles[state -2, shadow]
type = helper
trigger1 = !numhelper(33333399+ID)
name = "shadow"
ID = 33333399+ID
stateno = 33333399
postype = p1
ownpal = 1
keyctrl = 0
supermovetime = 2147483647
pausemovetime = 2147483647
ignorehitpause = 1
[State shadow]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
Your pick goes in CNSVersion 1 | Scale based round shadows[Not how it’s actually done in sf3, this has smoother size transitions and only uses one sprite(8.png in the shadows download). There are some options in the 'scale' parameter of angledraw. You can use it as default and the shadow's size will be calculated based on the width in the character's constant or you can adjust your base shadow size manually. ];=========================================================================
;Scale based round shadows by Inktrebuchet
;=========================================================================
[Statedef 33333399]
type = A
movetype = I
physics = N
ctrl = 0
velset = 0, 0
anim = 8537 ;base shadow sprite. This one was chosen because it is between the largest and smallest size. (100px)
sprpriority = -4
[State 33333399, 0] ;This is to correct a 1 frame delay in shadow pos
type = AssertSpecial
trigger1 = !time
flag = invisible
ignorehitpause = 1
[State 33333399, 1]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
[State 33333399, 2] ;player shadow
type = angledraw
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = !Parent,ishelper
;scale = (.47 - ( ( (.47/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .6 + (.0), (.3 - ( ( (.3/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .8 + (.0) ;The last float number in () is to adjust base shadow size. This number should be the same for x and y.
scale = ((.47 - ( ( (.47/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .6 )/(100.0/(Parent,const(size.ground.back) + Parent,const(size.ground.front))) * 2 , ((.3 - ( ( (.3/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .8)/(100.0/(Parent,const(size.ground.back) + Parent,const(size.ground.front))) * 2 ; bases shadow size on character width
ignorehitpause = 1
[State 33333399, 3] ;projectile shadow
type = angledraw
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = Parent,ishelper
scale = (.47 - ( ( (.47/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .6 + (-.3), (.3 - ( ( (.3/(96/cond(abs(Parent,pos y)+.0001 < 96, abs(Parent,pos y)+.00001, 96)))))) + .8 + (-.3) ;The last float number in () is to adjust base shadow size. This number should be the same for x and y.
ignorehitpause = 1
[state 33333399, 4]
type = Trans
trigger1 = 1
trans = addalpha
alpha = 128, 128
ignorehitpause = 1
[state 33333399, 5] ;*this may need to be adjusted for some projectiles
type = destroyself
trigger1 = !PlayerIdExist(parent,ID)
trigger2 = PlayerIdExist(parent,ID)
trigger2 = parent, ishelper
trigger2 = parent, movecontact
trigger2 = parent, movetype != A
ignorehitpause = 1
[State 33333399, 6]
type = BindToParent
trigger1 = PlayerIdExist(Parent,ID)
time = 1
facing = 1
pos =0,-Parent,pos y
ignorehitpause = 1
;----------------------------
Version 2 | Sprite based round shadows[This is the more accurate to sf3 version to use. Base shadow sprite can be changed in the 'anim' parameter of changeanim. ];=========================================================================
;Sprite based round shadows by Inktrebuchet
;=========================================================================
[Statedef 33333399]
type = A
movetype = I
physics = N
ctrl = 0
velset = 0, 0
sprpriority = -4
[State 33333399, 0] ;This is to correct a 1 frame delay in shadow pos
type = AssertSpecial
trigger1 = !time
flag = invisible
ignorehitpause = 1
[State 33333399, 1]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
[State 33333399, 2] ;player shadow
type = changeanim
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = !parent, ishelper
value = 8530 + ceil(cond(abs(Parent,pos y) < 96, abs(Parent,pos y +.00001), 96) / 12) + (7) ; The last number in () is to adjust base shadow size.
ignorehitpause = 1
[State 33333399, 3] ;projectile shadow
type = changeanim
trigger1 = PlayerIdExist(Parent,ID)
trigger1 = parent, ishelper
value = 8550 ; projectiles only have one shadow size in sf3
ignorehitpause = 1
[state 33333399, 4]
type = Trans
trigger1 = 1
trans = addalpha
alpha = 128, 128
ignorehitpause = 1
[state 33333399, 5] ;*this may need to be adjusted for some projectiles
type = destroyself
trigger1 = !PlayerIdExist(parent,ID)
trigger2 = PlayerIdExist(parent,ID)
trigger2 = parent, ishelper
trigger2 = parent, movecontact
trigger2 = parent, movetype != A
ignorehitpause = 1
[State 33333399, 6]
type = BindToParent
trigger1 = PlayerIdExist(Parent,ID)
time = 1
facing = 1
pos =0,-Parent,pos y
ignorehitpause = 1
;----------------------------
Spoiler: no helper, only explod. no projectile support and not compatible with 1.1b stages with zoom! (click to see content)
Your pick goes in [statedef -2]Version 1 | Scale based round shadows[Not how it’s actually done in sf3, this has smoother size transitions and only uses one sprite(8.png in the shadows download). There are some options in the 'scale' parameter of modifyexplod. You can use it as default and the shadow's size will be calculated based on the width in the character's constant or you can adjust your base shadow size manually. ][code]
;Scale based round shadows by Inktrebuchet
[State shadow 1]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
[state shadow 2]
type = explod
trigger1 = numexplod(8530) = 0
id = 8530
anim = (8530 + 07) ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< this sprite is 100px wide
postype = left
pos = ceil(screenpos x), ceil(screenpos y) - ceil(pos y)
removetime = -1
bindtime = -1
sprpriority = -4
ignorehitpause = 1
[state shadow 3]
type = modifyexplod
trigger1 = numexplod(8530) = 1
id = 8530
postype = left
pos = ceil(screenpos x), ceil(screenpos y - pos y)
;scale = (.47 - ( ( (.47/(96/cond(abs(pos y)+.0001 < 96, abs(pos y)+.00001, 96)))))) + .6 + (.0), 1 ;The last float number in () is to adjust base shadow size.
scale = ((.47 - ( ( (.47/(96/cond(abs(pos y)+.0001 < 96, abs(pos y)+.00001, 96)))))) + .6 )/(100.0/(const(size.ground.back) + const(size.ground.front))) * 2 , 1 ; base shadow on character's width
trans = addalpha
alpha = 128,128
sprpriority = -4
ignorehitpause = 1
Version 2 | Sprite based round shadows[This is the more accurate to sf3 version to use. Base shadow sprite can be changed in the 'anim' parameter of the explod. ];Sprite based round shadows by Inktrebuchet
[State 2000, Assert]
type = AssertSpecial
trigger1 = 1
flag = noshadow
ignorehitpause = 1
[state shadow];
type = removeexplod
trigger1 = numexplod(8530)
id = 8530
ignorehitpause = 1
[state 6000, Effect]
type = explod
trigger1 = numexplod(8530) = 0
ID = 8530
anim = 8530 + (7) + ceil(cond(abs(pos y) < 96, abs(pos y +.00001), 96) / 12) ; (7) is the base shadow size
postype = left
pos = ceil(screenpos x), ceil(screenpos y - pos y)
bindtime = 1
removetime = -1
ownpal = 1
sprpriority = -4
ignorehitpause = 1