Skip to content

Commit ec72d91

Browse files
authored
Merge pull request #3674 from potsmugen/push
fix: zoom lag, combo shake, empty bytecode crashes, incomplete preload; refactor: dizzy flag, darken
2 parents 368129d + 04f448e commit ec72d91

3 files changed

Lines changed: 99 additions & 37 deletions

File tree

src/compiler.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,9 @@ func (c *CharCompiler) expValue(out *BytecodeExp, in *string,
12941294
if err != nil {
12951295
return err
12961296
}
1297+
if bv2.IsNone() && len(be2) == 0 {
1298+
return Error("Missing value after ':=' operator")
1299+
}
12971300
be2.appendValue(bv2)
12981301
if rd {
12991302
out.appendI32Op(OC_nordrun, int32(len(be2)))
@@ -1416,10 +1419,12 @@ func (c *CharCompiler) expValue(out *BytecodeExp, in *string,
14161419
var err error
14171420
switch c.token {
14181421
case "":
1419-
if sys.ignoreMostErrors {
1420-
return bvNone(), nil
1421-
}
1422-
return bvNone(), Error("Nothing assigned")
1422+
// Because empty parameter values are not parsed at all, we don't need to ignore them here
1423+
// So it's safer to crash in case the value is accidentally empty
1424+
//if sys.ignoreMostErrors {
1425+
// return bvNone(), nil
1426+
//}
1427+
return bvNone(), Error("Empty expression")
14231428
// Redirections without arguments
14241429
case "root", "parent", "p2", "stateowner":
14251430
switch c.token {
@@ -1593,8 +1598,7 @@ func (c *CharCompiler) expValue(out *BytecodeExp, in *string,
15931598
out.append(be2...)
15941599
return bvNone(), nil
15951600
case "-":
1596-
if len(*in) > 0 && (((*in)[0] >= '0' && (*in)[0] <= '9') ||
1597-
(*in)[0] == '.') {
1601+
if len(*in) > 0 && (((*in)[0] >= '0' && (*in)[0] <= '9') || (*in)[0] == '.') {
15981602
c.token += c.tokenizer(in)
15991603
bv = c.number(c.token)
16001604
if bv.IsNone() {
@@ -1605,6 +1609,9 @@ func (c *CharCompiler) expValue(out *BytecodeExp, in *string,
16051609
if bv, err = c.expValue(&be1, in, false); err != nil {
16061610
return bvNone(), err
16071611
}
1612+
if bv.IsNone() && len(be1) == 0 {
1613+
return bvNone(), Error("Missing expression after '-'")
1614+
}
16081615
if bv.IsNone() {
16091616
if rd {
16101617
//out.append(OC_rdreset)
@@ -4902,6 +4909,9 @@ func (c *CharCompiler) expValue(out *BytecodeExp, in *string,
49024909
if err != nil {
49034910
return bvNone(), err
49044911
}
4912+
if bv2.IsNone() && len(be2) == 0 {
4913+
return bvNone(), Error("Missing value after ':=' operator")
4914+
}
49054915
be2.appendValue(bv2)
49064916
if rd {
49074917
out.appendI32Op(OC_nordrun, int32(len(be2)))

src/fightscreen.go

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,11 +1858,14 @@ func (fa *FightScreenFace) draw(layerno int16, charpn int, refFace *FightScreenF
18581858
refFace.face.PalTex = refFace.face.CachePalTex(charPal)
18591859
}
18601860

1861+
// Save current brightness
1862+
//oldBright := sys.brightness
1863+
18611864
// Reset system brightness if player initiated SuperPause (cancel "darken" parameter)
1862-
oldBright := sys.brightness
1863-
if refChar.ignoreDarkenTime > 0 {
1864-
sys.brightness = 1.0
1865-
}
1865+
// Update: This is an odd thing to do since the rest of the fight screen darkens
1866+
//if refChar.ignoreDarkenTime > 0 {
1867+
// sys.brightness = 1.0
1868+
//}
18661869

18671870
// Draw the actual face sprite
18681871
fa.face_lay.DrawFaceSprite((float32(fa.pos[0])+sys.fightScreen.offsetX)*sys.fightScreen.scale, float32(fa.pos[1])*sys.fightScreen.scale, layerno,
@@ -1874,7 +1877,7 @@ func (fa *FightScreenFace) draw(layerno int16, charpn int, refFace *FightScreenF
18741877
}
18751878

18761879
// Restore original system brightness
1877-
sys.brightness = oldBright
1880+
//sys.brightness = oldBright
18781881
}
18791882

18801883
// Draw top layer
@@ -1891,13 +1894,14 @@ func (fa *FightScreenFace) drawTeammates(layerno int16, charpn int) {
18911894
// return
18921895
//}
18931896

1894-
refChar := sys.chars[charpn][0]
1897+
// Save current brightness
1898+
oldBright := sys.brightness
18951899

18961900
// Reset system brightness if player initiated SuperPause (cancel "darken" parameter)
1897-
oldBright := sys.brightness
1898-
if refChar.ignoreDarkenTime > 0 {
1899-
sys.brightness = 1.0
1900-
}
1901+
//refChar := sys.chars[charpn][0]
1902+
//if refChar.ignoreDarkenTime > 0 {
1903+
// sys.brightness = 1.0
1904+
//}
19011905

19021906
teamSize := int32(len(fa.teammate_face))
19031907

@@ -2327,8 +2331,8 @@ type FightScreenCombo struct {
23272331
start_x float32
23282332
counter map[int32]*FSText
23292333
counter_shake bool
2330-
counter_time int32
2331-
counter_mult float32
2334+
counter_time int32 // Shake effect duration
2335+
counter_mult float32 // Shake effect scale correction factor
23322336
text map[int32]*FSText
23332337
bg AnimLayout
23342338
top AnimLayout
@@ -2343,7 +2347,7 @@ type FightScreenCombo struct {
23432347
shownPct float32
23442348
resttime int32
23452349
counterX float32
2346-
shaketime int32
2350+
curShaketime int32
23472351
autoalign bool
23482352
newCombo bool
23492353
}
@@ -2405,7 +2409,7 @@ func readFightScreenCombo(pre string, is IniSection,
24052409
return co
24062410
}
24072411

2408-
func (co *FightScreenCombo) step(hits, damage int32, percentage float32, dizzy bool) {
2412+
func (co *FightScreenCombo) step(hits, damage int32, percentage float32) {
24092413
co.bg.Action()
24102414
co.top.Action()
24112415

@@ -2422,22 +2426,31 @@ func (co *FightScreenCombo) step(hits, damage int32, percentage float32, dizzy b
24222426
// True hits are only updated by Char(). The live tally is only used for combo display behavior
24232427
//co.trueHits = hits
24242428

2429+
// Handle show/hide speed
24252430
if co.resttime > 0 {
2431+
// Slide in
24262432
co.counterX -= co.counterX / co.showspeed
2433+
// Snap to visible position
2434+
if Abs(co.counterX) < 1 {
2435+
co.counterX = 0
2436+
}
24272437
} else if co.trueHits < 2 {
2438+
// Slide out when combo ends
24282439
co.counterX -= sys.fightScreen.fnt_scale * co.hidespeed * float32(sys.fightScreen.localcoord[0]) / 320
2440+
// Snap to starting position
24292441
if co.counterX < co.start_x*2 {
24302442
co.counterX = co.start_x * 2
24312443
}
24322444
}
24332445

2434-
if co.shaketime > 0 {
2435-
co.shaketime--
2446+
if co.curShaketime > 0 {
2447+
co.curShaketime--
24362448
}
24372449

2438-
// TODO: Most commercial games don't rely on the dizzy flag
2439-
// They keep the combo active as long as hits >= 2
2440-
if Abs(co.counterX) < 1 && !dizzy {
2450+
// The displayed time only decrements when the counter is in the visible position
2451+
// Currently, the way the timer decrements while the combo is still ongoing can make it stay visible varying amounts of time past the end of the combo
2452+
// This makes it not always sync correctly with the "nice combo" actions
2453+
if co.counterX == 0 {
24412454
co.resttime--
24422455
}
24432456

@@ -2446,7 +2459,7 @@ func (co *FightScreenCombo) step(hits, damage int32, percentage float32, dizzy b
24462459
// Reset visuals when hits changed
24472460
if co.newCombo || co.shownHits != co.trueHits {
24482461
if co.counter_shake {
2449-
co.shaketime = co.counter_time
2462+
co.curShaketime = co.counter_time
24502463
}
24512464
for i := range co.counter {
24522465
co.counter[i].resetTxtPfx()
@@ -2495,7 +2508,7 @@ func (co *FightScreenCombo) reset() {
24952508
co.shownPct = 0
24962509
co.resttime = 0
24972510
co.counterX = co.start_x * 2
2498-
co.shaketime = 0
2511+
co.curShaketime = 0
24992512
}
25002513

25012514
func (co *FightScreenCombo) draw(layerno int16, f map[int]*Fnt, side int) {
@@ -2519,7 +2532,9 @@ func (co *FightScreenCombo) draw(layerno int16, f map[int]*Fnt, side int) {
25192532
}
25202533
}
25212534

2535+
// Replace operator with current combo value
25222536
counter := strings.Replace(co.counter[cv].text, "%i", fmt.Sprintf("%v", co.shownHits), 1)
2537+
25232538
x := float32(co.pos[0])
25242539
if side == 0 {
25252540
if co.start_x <= 0 {
@@ -2536,8 +2551,14 @@ func (co *FightScreenCombo) draw(layerno int16, f map[int]*Fnt, side int) {
25362551
x -= co.counterX
25372552
}
25382553
}
2554+
2555+
// BG
25392556
co.bg.Draw(x+sys.fightScreen.offsetX, float32(co.pos[1]), layerno, sys.fightScreen.scale)
2557+
2558+
// Track total string length
25402559
var length float32
2560+
2561+
// Text
25412562
if co.text[tv].font[0] >= 0 && getFont(f, co.text[tv].font[0]) != nil {
25422563
text := strings.Replace(co.text[tv].text, "%i", fmt.Sprintf("%v", co.shownHits), 1)
25432564
text = strings.Replace(text, "%d", fmt.Sprintf("%v", co.shownDmg), 1)
@@ -2574,17 +2595,26 @@ func (co *FightScreenCombo) draw(layerno int16, f map[int]*Fnt, side int) {
25742595
co.text[tv].palfx, co.text[tv].frgba)
25752596
}
25762597
}
2598+
2599+
// Counter
25772600
if co.counter[cv].font[0] >= 0 && getFont(f, co.counter[cv].font[0]) != nil {
25782601
if side == 0 && co.autoalign {
25792602
if ff := getFont(f, co.counter[cv].font[0]); ff != nil {
25802603
length = float32(ff.TextWidth(counter, co.counter[cv].font[1], 0)) * co.counter[cv].lay.scale[0] * sys.fightScreen.fnt_scale
25812604
}
25822605
}
25832606

2584-
z := 1 + float32(co.shaketime)*co.counter_mult*float32(math.Sin(float64(co.shaketime)*(math.Pi/2.5)))
2607+
// Shake effect
2608+
// TODO: More customizable parameters
2609+
// TODO: Maximum scale is currently determined by "time * correction factor". That seems especially odd
2610+
arg := float64(co.counter_time - co.curShaketime) * math.Pi / 2.5
2611+
z := 1 + float32(co.curShaketime)*co.counter_mult*float32(math.Cos(arg))
2612+
25852613
co.counter[cv].lay.DrawText((x-length+sys.fightScreen.offsetX)/z, float32(co.pos[1])/z, z*sys.fightScreen.scale, layerno,
25862614
counter, getFont(f, co.counter[cv].font[0]), co.counter[cv].font[1], co.counter[cv].font[2], co.counter[cv].palfx, co.counter[cv].frgba)
25872615
}
2616+
2617+
// Top
25882618
co.top.Draw(x+sys.fightScreen.offsetX, float32(co.pos[1]), layerno, sys.fightScreen.scale)
25892619
}
25902620

@@ -5156,7 +5186,7 @@ func (fs *FightScreen) step() {
51565186
}
51575187
// Time
51585188
fs.time.step()
5159-
cb, cd, cp, dz := [2]int32{}, [2]int32{}, [2]float32{}, [2]bool{}
5189+
cb, cd, cp := [2]int32{}, [2]int32{}, [2]float32{}
51605190
targets := [2]int32{}
51615191
// Combo
51625192
for _, ch := range sys.chars {
@@ -5169,9 +5199,6 @@ func (fs *FightScreen) step() {
51695199
// Perhaps helper percentages shouldn't be tracked, but ignoring them creates scenarios where the lifebars show 0% damage which looks wrong
51705200
cp[side] += float32(c.receivedDmg) / float32(c.lifeMax) * 100
51715201
targets[side]++
5172-
if c.scf(SCF_dizzy) {
5173-
dz[side] = true
5174-
}
51755202
}
51765203
}
51775204
}
@@ -5181,7 +5208,7 @@ func (fs *FightScreen) step() {
51815208
}
51825209
}
51835210
for i := range fs.combos {
5184-
fs.combos[i].step(cb[i], cd[i], cp[i], dz[i]) // Combo hits, combo damage, combo damage percentage, dizzy flag
5211+
fs.combos[i].step(cb[i], cd[i], cp[i]) // Combo hits, combo damage, combo damage percentage
51855212
}
51865213
// Action
51875214
for i := range fs.actions {

src/system.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,16 +2554,20 @@ func (s *System) action() {
25542554
s.zmin = s.stage.topbound * s.stage.localscl
25552555
s.zmax = s.stage.botbound * s.stage.localscl
25562556
//s.bgPalFX.step()
2557+
25572558
s.envShake.next()
25582559
if s.envcol_time > 0 {
25592560
s.envcol_time--
25602561
}
2561-
s.zoom.update()
2562+
2563+
// Step pause timers
25622564
if s.supertime > 0 {
25632565
s.supertime--
25642566
} else if s.pausetime > 0 {
25652567
s.pausetime--
25662568
}
2569+
2570+
// Start pause timers
25672571
if s.supertimebuffer < 0 {
25682572
s.supertimebuffer = ^s.supertimebuffer
25692573
s.supertime = s.supertimebuffer
@@ -2572,6 +2576,7 @@ func (s *System) action() {
25722576
s.pausetimebuffer = ^s.pausetimebuffer
25732577
s.pausetime = s.pausetimebuffer
25742578
}
2579+
25752580
// In Mugen 1.1, few global AssertSpecial flags persist during pauses. Seemingly only TimerFreeze
25762581
if s.supertime <= 0 && s.pausetime <= 0 {
25772582
s.specialFlag = 0
@@ -2580,9 +2585,14 @@ func (s *System) action() {
25802585
// "NoKOSlow" added to facilitate custom slowdown. In Mugen that flag only needs to be asserted in first frame of KO slowdown
25812586
s.specialFlag = (s.specialFlag&GSF_nokoslow | s.specialFlag&GSF_timerfreeze)
25822587
}
2588+
2589+
// Run the main character logic
25832590
s.charList.action()
2591+
2592+
// The following must be placed after char action or they will lag behind 1 frame
25842593
s.allPalFX.step()
25852594
s.bgPalFX.step()
2595+
s.zoom.update()
25862596
s.nomusic = s.gsf(GSF_nomusic) && !sys.postMatchFlg
25872597
}
25882598

@@ -4600,9 +4610,10 @@ func (s *Select) AddChar(def string) *SelectChar {
46004610
}
46014611
return nil
46024612
})
4613+
46034614
// preload animations
46044615
if len(anim_orig) > 0 {
4605-
LoadFile(&anim_orig, []string{sc.def, "", "data/"}, "", func(filename string) error {
4616+
err := LoadFile(&anim_orig, []string{sc.def, "", "data/"}, "", func(filename string) error {
46064617
str, err := LoadText(filename) // LoadText is zip-aware
46074618
if err != nil {
46084619
return err
@@ -4623,14 +4634,22 @@ func (s *Select) AddChar(def string) *SelectChar {
46234634
}
46244635
return nil
46254636
})
4637+
// Crash if we expected an AIR file but didn't find any
4638+
if err != nil {
4639+
panic(fmt.Sprintf("Cannot open air file for character %s: %v", def, err))
4640+
}
46264641
}
4627-
// preload portion of sff file
4642+
4643+
// Try to use the "_preload.sff" file if available
46284644
fp := fmt.Sprintf("%v_preload.sff", strings.TrimSuffix(sc.def, filepath.Ext(sc.def)))
46294645
if fp = FileExist(fp); len(fp) == 0 {
4646+
// Fall back to normal SFF
46304647
fp = sprite_orig
46314648
}
4649+
4650+
// preload portion of sff file
46324651
if len(fp) > 0 {
4633-
LoadFile(&fp, []string{sc.def, "", "data/"}, "", func(file string) error {
4652+
err := LoadFile(&fp, []string{sc.def, "", "data/"}, "", func(file string) error {
46344653
var selPal []int32
46354654
var err_sff error
46364655
sc.sff, selPal, err_sff = preloadSff(file, true, listSpr)
@@ -4677,13 +4696,19 @@ func (s *Select) AddChar(def string) *SelectChar {
46774696
}
46784697
return nil
46794698
})
4699+
// Crash if we expected a SFF file but didn't find any
4700+
if err != nil {
4701+
panic(fmt.Sprintf("Cannot open sprite file for character %s: %v", def, err))
4702+
}
46804703
} else {
4704+
// If we deliberately lack a SFF, then make a dummy one
46814705
sc.sff = newSff()
46824706
sc.anims.updateSff(sc.sff)
46834707
for k := range s.charSpritePreload {
46844708
sc.anims.addSprite(sc.sff, k[0], k[1])
46854709
}
46864710
}
4711+
46874712
return sc
46884713
}
46894714

0 commit comments

Comments
 (0)