mirror of
https://github.com/ficed/Braver.git
synced 2025-02-17 10:38:39 +00:00
Field
Improve scrolling to only clamp scroll when player-initiated Implement SPLIT, JOIN, ANIME2 ops Fix TURA op rotation direction to be more resiliant Improve ANIMW to hopefully work better Add support for looping sfx, allow field SOUND op to stop them
This commit is contained in:
parent
72bcdf57f4
commit
eea0e11c22
62
F7/Audio.cs
62
F7/Audio.cs
@ -91,6 +91,20 @@ namespace Braver {
|
||||
}
|
||||
}
|
||||
|
||||
public void StopLoopingSfx() {
|
||||
foreach (var loop in _activeLoops) {
|
||||
loop.Stop();
|
||||
loop.Dispose();
|
||||
}
|
||||
_activeLoops.Clear();
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
var needsRestart = _activeLoops.Where(instance => instance.State != SoundState.Playing);
|
||||
foreach (var loop in needsRestart)
|
||||
loop.Play();
|
||||
}
|
||||
|
||||
private async Task RunMusic() {
|
||||
var contexts = new Stack<MusicContext>();
|
||||
contexts.Push(new MusicContext());
|
||||
@ -182,37 +196,59 @@ namespace Braver {
|
||||
_game.Net.Send(new Net.MusicMessage { Track = string.Empty, IsPop = popContext });
|
||||
}
|
||||
|
||||
private Dictionary<int, WeakReference<SoundEffect>> _sfx = new();
|
||||
private HashSet<SoundEffect> _recent0 = new(), _pinned = new(), _recent1;
|
||||
private class LoadedEffect {
|
||||
public SoundEffect Effect { get; set; }
|
||||
public bool ShouldLoop { get; set; }
|
||||
}
|
||||
|
||||
private Dictionary<int, WeakReference<LoadedEffect>> _sfx = new();
|
||||
private HashSet<LoadedEffect> _recent0 = new(), _pinned = new(), _recent1;
|
||||
private HashSet<SoundEffectInstance> _activeLoops = new();
|
||||
private DateTime _lastPromote = DateTime.MinValue;
|
||||
|
||||
public void Precache(Sfx which, bool pin) {
|
||||
byte[] raw = _sfxSource.ExportPCM((int)which, out int freq, out int channels);
|
||||
private LoadedEffect GetEffect(int which) {
|
||||
byte[] raw = _sfxSource.ExportPCM(which, out int freq, out int channels);
|
||||
var fx = new SoundEffect(raw, freq, channels == 1 ? AudioChannels.Mono : AudioChannels.Stereo);
|
||||
_sfx[(int)which] = new WeakReference<SoundEffect>(fx);
|
||||
return new LoadedEffect {
|
||||
Effect = fx,
|
||||
ShouldLoop = _sfxSource.GetExtraData(which)[0] != 0, //TODO - seems like it *might* be right?!
|
||||
};
|
||||
}
|
||||
|
||||
public void Precache(Sfx which, bool pin) {
|
||||
var effect = GetEffect((int)which);
|
||||
_sfx[(int)which] = new WeakReference<LoadedEffect>(effect);
|
||||
|
||||
if (pin)
|
||||
_pinned.Add(fx);
|
||||
_pinned.Add(effect);
|
||||
}
|
||||
|
||||
public void PlaySfx(Sfx which, float volume, float pan) => PlaySfx((int)which, volume, pan);
|
||||
public void PlaySfx(int which, float volume, float pan) {
|
||||
SoundEffect fx;
|
||||
LoadedEffect effect;
|
||||
|
||||
if (_sfx.TryGetValue(which, out var wr) && wr.TryGetTarget(out fx)) {
|
||||
if (_sfx.TryGetValue(which, out var wr) && wr.TryGetTarget(out effect)) {
|
||||
//
|
||||
} else {
|
||||
byte[] raw = _sfxSource.ExportPCM(which, out int freq, out int channels);
|
||||
fx = new SoundEffect(raw, freq, channels == 1 ? AudioChannels.Mono : AudioChannels.Stereo);
|
||||
_sfx[which] = new WeakReference<SoundEffect>(fx);
|
||||
effect = GetEffect(which);
|
||||
_sfx[which] = new WeakReference<LoadedEffect>(effect);
|
||||
}
|
||||
|
||||
if (effect.ShouldLoop) {
|
||||
var instance = effect.Effect.CreateInstance();
|
||||
instance.Pan = pan;
|
||||
instance.Volume = volume;
|
||||
instance.Play();
|
||||
_activeLoops.Add(instance);
|
||||
} else {
|
||||
effect.Effect.Play(volume, 0, pan);
|
||||
}
|
||||
|
||||
fx.Play(volume, 0, pan);
|
||||
if (_lastPromote < DateTime.Now.AddMinutes(-1)) {
|
||||
_recent1 = _recent0;
|
||||
_recent0 = new();
|
||||
}
|
||||
_recent0.Add(fx);
|
||||
_recent0.Add(effect);
|
||||
_game.Net.Send(new Net.SfxMessage { Which = which, Volume = volume, Pan = pan });
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,7 @@ namespace Braver {
|
||||
}
|
||||
|
||||
Net.Update();
|
||||
Audio.Update();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -142,6 +142,8 @@ namespace Braver.Field {
|
||||
g.Net.Listen<Net.FieldEntityModelMessage>(this);
|
||||
g.Net.Listen<Net.FieldBGScrollMessage>(this);
|
||||
|
||||
g.Audio.StopLoopingSfx();
|
||||
|
||||
Overlay = new Overlay(g, graphics);
|
||||
|
||||
g.Net.Send(new Net.FieldScreenMessage { Destination = _destination });
|
||||
@ -438,21 +440,23 @@ namespace Braver.Field {
|
||||
(int)(_view2D.CenterY / 3)
|
||||
);
|
||||
}
|
||||
public void BGScroll(float x, float y) {
|
||||
BGScrollOffset(x - (-_view2D.CenterX / 3), y - (_view2D.CenterY / 3));
|
||||
public void BGScroll(float x, float y, bool clampToViewport) {
|
||||
BGScrollOffset(x - (-_view2D.CenterX / 3), y - (_view2D.CenterY / 3), clampToViewport);
|
||||
}
|
||||
public void BGScrollOffset(float ox, float oy) {
|
||||
|
||||
int minYScroll = Background.MinY >= -120 ? 0 : -Background.MinY - 120,
|
||||
maxYScroll = Background.MaxY <= 120 ? 0 : Background.MaxY - 120,
|
||||
minXScroll = Background.MinX >= -213 ? 0 : -Background.MinX - 213,
|
||||
maxXScroll = Background.MaxX <= 213 ? 0 : Background.MaxX - 213;
|
||||
public void BGScrollOffset(float ox, float oy, bool clampToViewport) {
|
||||
|
||||
_view2D.CenterX -= 3 * ox;
|
||||
_view2D.CenterY += 3 * oy;
|
||||
|
||||
_view2D.CenterX = Math.Min(Math.Max(-3 * maxXScroll, _view2D.CenterX), 3 * minXScroll);
|
||||
_view2D.CenterY = Math.Min(Math.Max(-3 * minYScroll, _view2D.CenterY), 3 * maxYScroll);
|
||||
if (clampToViewport) {
|
||||
int minYScroll = Background.MinY >= -120 ? 0 : -Background.MinY - 120,
|
||||
maxYScroll = Background.MaxY <= 120 ? 0 : Background.MaxY - 120,
|
||||
minXScroll = Background.MinX >= -213 ? 0 : -Background.MinX - 213,
|
||||
maxXScroll = Background.MaxX <= 213 ? 0 : Background.MaxX - 213;
|
||||
|
||||
_view2D.CenterX = Math.Min(Math.Max(-3 * maxXScroll, _view2D.CenterX), 3 * minXScroll);
|
||||
_view2D.CenterY = Math.Min(Math.Max(-3 * minYScroll, _view2D.CenterY), 3 * maxYScroll);
|
||||
}
|
||||
|
||||
var newScroll = GetBGScroll();
|
||||
_view3D.ScreenOffset = new Vector2(newScroll.x * 3f * 2 / 1280, newScroll.y * -3f * 2 / 720);
|
||||
@ -509,7 +513,7 @@ namespace Braver.Field {
|
||||
|
||||
if (newScroll != scroll) {
|
||||
System.Diagnostics.Debug.WriteLine($"BringPlayerIntoView: Player at BG pos {posOnBG}, BG scroll is {scroll}, needs to be {newScroll}");
|
||||
BGScroll(newScroll.x, newScroll.y);
|
||||
BGScroll(newScroll.x, newScroll.y, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -594,88 +598,10 @@ namespace Braver.Field {
|
||||
if (_debugMode) {
|
||||
|
||||
if (input.IsDown(InputKey.PanLeft))
|
||||
BGScrollOffset(0, -1);
|
||||
BGScrollOffset(0, -1, false);
|
||||
else if (input.IsDown(InputKey.PanRight))
|
||||
BGScrollOffset(0, +1);
|
||||
BGScrollOffset(0, +1, false);
|
||||
|
||||
if (input.IsAnyDirectionDown() || input.IsJustDown(InputKey.Select)) {
|
||||
|
||||
if (input.IsDown(InputKey.Up))
|
||||
_view3D.CameraPosition += _view3D.CameraUp;
|
||||
else if (input.IsDown(InputKey.Down))
|
||||
_view3D.CameraPosition -= _view3D.CameraUp;
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"Player at {ModelToBGPosition(Player.Model.Translation, null, false)} WM0 {ModelToBGPosition(_walkmesh[0].V0.ToX(), null, false)}");
|
||||
|
||||
/*
|
||||
//Now calculate 3d scroll amount
|
||||
var _3dScrollAmount = new Vector2(_view3D.Width / 427f, _view3D.Height / 240f);
|
||||
System.Diagnostics.Debug.WriteLine($"To scroll 3d view by one BG pixel, it will move {_3dScrollAmount}");
|
||||
|
||||
if (input.IsJustDown(InputKey.Select)) {
|
||||
_view3D.CenterX += _3dScrollAmount.X * _view2D.CenterX / -3;
|
||||
_view3D.CenterY += _3dScrollAmount.Y * _view2D.CenterY / -3;
|
||||
}
|
||||
|
||||
if (input.IsDown(InputKey.OK)) {
|
||||
if (input.IsDown(InputKey.Up)) {
|
||||
_view2D.CenterY += 3;
|
||||
_view3D.CenterY += _3dScrollAmount.Y;
|
||||
}
|
||||
if (input.IsDown(InputKey.Down)) {
|
||||
_view2D.CenterY -= 3;
|
||||
_view3D.CenterY -= _3dScrollAmount.Y;
|
||||
}
|
||||
if (input.IsDown(InputKey.Left)) {
|
||||
_view2D.CenterX -= 3;
|
||||
_view3D.CenterX -= _3dScrollAmount.X;
|
||||
}
|
||||
if (input.IsDown(InputKey.Right)) {
|
||||
_view2D.CenterX += 3;
|
||||
_view3D.CenterX += _3dScrollAmount.X;
|
||||
}
|
||||
|
||||
} else if (input.IsDown(InputKey.Cancel)) {
|
||||
if (input.IsDown(InputKey.Up))
|
||||
_view2D.CenterY++;
|
||||
if (input.IsDown(InputKey.Down))
|
||||
_view2D.CenterY--;
|
||||
if (input.IsDown(InputKey.Left))
|
||||
_view2D.CenterX--;
|
||||
if (input.IsDown(InputKey.Right))
|
||||
_view2D.CenterX++;
|
||||
|
||||
} else {
|
||||
if (input.IsDown(InputKey.Menu)) {
|
||||
|
||||
if (input.IsDown(InputKey.Up))
|
||||
_view3D.Height++;
|
||||
if (input.IsDown(InputKey.Down))
|
||||
_view3D.Height--;
|
||||
if (input.IsDown(InputKey.Left))
|
||||
_view3D.Width--;
|
||||
if (input.IsDown(InputKey.Right))
|
||||
_view3D.Width++;
|
||||
|
||||
} else {
|
||||
if (input.IsDown(InputKey.Up)) {
|
||||
_view3D.CenterY++;
|
||||
}
|
||||
if (input.IsDown(InputKey.Down)) {
|
||||
_view3D.CenterY--;
|
||||
}
|
||||
if (input.IsDown(InputKey.Left)) {
|
||||
_view3D.CenterX--;
|
||||
}
|
||||
if (input.IsDown(InputKey.Right)) {
|
||||
_view3D.CenterX++;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine($"View2D Center: {_view2D.CenterX}/{_view2D.CenterY}");
|
||||
System.Diagnostics.Debug.WriteLine($"View3D: {_view3D}");
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
if (Dialog.IsActive) {
|
||||
@ -1200,7 +1126,7 @@ namespace Braver.Field {
|
||||
Background.SetParameter(message.Parm, message.Value);
|
||||
}
|
||||
public void Received(Net.FieldBGScrollMessage message) {
|
||||
BGScroll(message.X, message.Y);
|
||||
BGScroll(message.X, message.Y, false);
|
||||
}
|
||||
|
||||
public void Received(Net.FieldEntityModelMessage message) {
|
||||
|
174
F7/Field/VM.cs
174
F7/Field/VM.cs
@ -622,7 +622,7 @@ namespace Braver.Field {
|
||||
|
||||
internal static class FieldModels {
|
||||
|
||||
|
||||
|
||||
public static OpResult IDLCK(Fiber f, Entity e, FieldScreen s) {
|
||||
ushort triID = f.ReadU16();
|
||||
byte enabled = f.ReadU8();
|
||||
@ -672,6 +672,118 @@ namespace Braver.Field {
|
||||
return OpResult.Continue;
|
||||
}
|
||||
|
||||
public static OpResult SPLIT(Fiber f, Entity e, FieldScreen s) {
|
||||
byte bankAXY = f.ReadU8(), bankADBX = f.ReadU8(), bankBYD = f.ReadU8();
|
||||
short xa = f.ReadS16(), ya = f.ReadS16();
|
||||
byte da = f.ReadU8();
|
||||
short xb = f.ReadS16(), yb = f.ReadS16();
|
||||
byte db = f.ReadU8(), speed = f.ReadU8();
|
||||
|
||||
int frame = (int?)f.ResumeState ?? 0;
|
||||
|
||||
var entities = s.Entities
|
||||
.Where(e => e.Character != null)
|
||||
.Where(e => e.Character != s.Player.Character);
|
||||
|
||||
Entity entA = entities.ElementAtOrDefault(0),
|
||||
entB = entities.ElementAtOrDefault(1);
|
||||
|
||||
if ((entA == null) && (entB == null))
|
||||
throw new InvalidOperationException();
|
||||
|
||||
void Process(Entity ent, int x, int y, int d) {
|
||||
if (frame == 0) {
|
||||
ent.Model.Translation = s.Player.Model.Translation;
|
||||
ent.WalkmeshTri = s.Player.WalkmeshTri;
|
||||
ent.Model.Visible = true;
|
||||
|
||||
float rotation = (float)(Math.Atan2(x - s.Player.Model.Translation.X, -(y - s.Player.Model.Translation.Y)) * 180 / Math.PI);
|
||||
ent.Model.Rotation = new Vector3(0, 0, rotation);
|
||||
ent.Model.PlayAnimation(1, true, 1f, null); //TODO - should be run, depending on speed
|
||||
|
||||
} else if (frame == speed) {
|
||||
s.DropToWalkmesh(ent, new Vector2(x, y), ent.WalkmeshTri); //TODO - if it's blocked, this won't be right. But that probably shouldn't happen?
|
||||
float rotation = 360f * d / 255f;
|
||||
ent.Model.Rotation = new Vector3(0, 0, rotation);
|
||||
ent.Model.PlayAnimation(0, true, 1f, null);
|
||||
} else {
|
||||
var target = Vector2.Lerp(s.Player.Model.Translation.XY(), new Vector2(x, y), 1f * frame / speed);
|
||||
s.TryWalk(ent, new Vector3(target.X, target.Y, 0), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (entA != null)
|
||||
Process(entA,
|
||||
s.Game.Memory.Read(bankAXY >> 4, xa), s.Game.Memory.Read(bankAXY & 0xf, ya),
|
||||
s.Game.Memory.Read(bankADBX >> 4, da));
|
||||
if (entB != null)
|
||||
Process(entB,
|
||||
s.Game.Memory.Read(bankADBX & 0xf, ya), s.Game.Memory.Read(bankBYD >> 4, yb),
|
||||
s.Game.Memory.Read(bankBYD & 0xf, db));
|
||||
|
||||
if (frame < speed) {
|
||||
f.ResumeState = ++frame;
|
||||
return OpResult.Restart;
|
||||
} else
|
||||
return OpResult.Continue;
|
||||
|
||||
}
|
||||
|
||||
private class JoinState {
|
||||
public int Frame;
|
||||
public Vector2 EntAStart, EntBStart;
|
||||
}
|
||||
|
||||
public static OpResult JOIN(Fiber f, Entity e, FieldScreen s) {
|
||||
byte speed = f.ReadU8();
|
||||
|
||||
var entities = s.Entities
|
||||
.Where(e => e.Character != null)
|
||||
.Where(e => e.Character != s.Player.Character);
|
||||
|
||||
Entity entA = entities.ElementAtOrDefault(0),
|
||||
entB = entities.ElementAtOrDefault(1);
|
||||
|
||||
if ((entA == null) && (entB == null))
|
||||
throw new InvalidOperationException();
|
||||
|
||||
JoinState state;
|
||||
if (f.ResumeState == null) {
|
||||
f.ResumeState = state = new JoinState {
|
||||
Frame = 0,
|
||||
EntAStart = entA == null ? Vector2.Zero : entA.Model.Translation.XY(),
|
||||
EntBStart = entB == null ? Vector2.Zero : entB.Model.Translation.XY(),
|
||||
};
|
||||
} else
|
||||
state = (JoinState)f.ResumeState;
|
||||
|
||||
void Process(Entity ent, Vector2 start) {
|
||||
if (state.Frame == 0) {
|
||||
float rotation = (float)(Math.Atan2(s.Player.Model.Translation.X - ent.Model.Translation.X, -(s.Player.Model.Translation.Y - ent.Model.Translation.Y)) * 180 / Math.PI);
|
||||
ent.Model.Rotation = new Vector3(0, 0, rotation);
|
||||
ent.Model.PlayAnimation(1, true, 1f, null); //TODO - should be run, depending on speed
|
||||
} else if (state.Frame == speed) {
|
||||
ent.Model.Translation = s.Player.Model.Translation;
|
||||
ent.Model.Visible = false;
|
||||
} else {
|
||||
var target = Vector2.Lerp(start, s.Player.Model.Translation.XY(), 1f * state.Frame / speed);
|
||||
s.TryWalk(ent, new Vector3(target.X, target.Y, 0), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (entA != null)
|
||||
Process(entA, state.EntAStart);
|
||||
if (entB != null)
|
||||
Process(entB, state.EntBStart);
|
||||
|
||||
if (state.Frame < speed) {
|
||||
state.Frame++;
|
||||
return OpResult.Restart;
|
||||
} else
|
||||
return OpResult.Continue;
|
||||
|
||||
}
|
||||
|
||||
public static OpResult PDIRA(Fiber f, Entity e, FieldScreen s) {
|
||||
byte chr = f.ReadU8();
|
||||
var target = s.Entities
|
||||
@ -783,9 +895,11 @@ namespace Braver.Field {
|
||||
byte anim = f.ReadU8(), first = f.ReadU8(), last = f.ReadU8(), speed = f.ReadU8();
|
||||
f.Pause();
|
||||
var state = e.Model.AnimationState;
|
||||
f.OtherState["AnimPlaying"] = true;
|
||||
Action onComplete = () => {
|
||||
f.Resume();
|
||||
e.Model.AnimationState = state;
|
||||
f.OtherState["AnimPlaying"] = false;
|
||||
};
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, onComplete, first, last); //TODO is this speed even vaguely correct?
|
||||
return OpResult.Continue;
|
||||
@ -794,28 +908,50 @@ namespace Braver.Field {
|
||||
byte anim = f.ReadU8(), speed = f.ReadU8();
|
||||
f.Pause();
|
||||
var state = e.Model.AnimationState;
|
||||
f.OtherState["AnimPlaying"] = true;
|
||||
Action onComplete = () => {
|
||||
f.Resume();
|
||||
e.Model.AnimationState = state;
|
||||
f.OtherState["AnimPlaying"] = false;
|
||||
};
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, onComplete); //TODO is this speed even vaguely correct?
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult ANIME2(Fiber f, Entity e, FieldScreen s) {
|
||||
byte anim = f.ReadU8(), speed = f.ReadU8();
|
||||
var state = e.Model.AnimationState;
|
||||
f.OtherState["AnimPlaying"] = true;
|
||||
Action onComplete = () => {
|
||||
e.Model.AnimationState = state;
|
||||
f.OtherState["AnimPlaying"] = false;
|
||||
};
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, onComplete);
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult ANIM_2(Fiber f, Entity e, FieldScreen s) {
|
||||
byte anim = f.ReadU8(), speed = f.ReadU8();
|
||||
f.Pause();
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, f.Resume); //TODO is this speed even vaguely correct?
|
||||
f.OtherState["AnimPlaying"] = true;
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, () => {
|
||||
f.Resume();
|
||||
f.OtherState["AnimPlaying"] = false;
|
||||
}); //TODO is this speed even vaguely correct?
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult CANM_2(Fiber f, Entity e, FieldScreen s) {
|
||||
byte anim = f.ReadU8(), fstart = f.ReadU8(), fend = f.ReadU8(), speed = f.ReadU8();
|
||||
f.Pause();
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, f.Resume, fstart, fend);
|
||||
f.OtherState["AnimPlaying"] = true;
|
||||
e.Model.PlayAnimation(anim, false, 1f / speed, () => {
|
||||
f.Resume();
|
||||
f.OtherState["AnimPlaying"] = false;
|
||||
}, fstart, fend);
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult DFANM(Fiber f, Entity e, FieldScreen s) {
|
||||
byte anim = f.ReadU8(), speed = f.ReadU8();
|
||||
e.Model.PlayAnimation(anim, true, 1f / speed, null); //TODO is this speed even vaguely correct?
|
||||
//TODO - not setting AnimPlaying, is that reasonable?
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult ASPED(Fiber f, Entity e, FieldScreen s) {
|
||||
@ -835,6 +971,9 @@ namespace Braver.Field {
|
||||
private static OpResult DoTurn(Entity e, float rotation, float rotationSteps, byte rotateDir, byte rotateType) {
|
||||
float rotationAmount = rotationSteps == 0 ? 360f : 360f * rotationSteps / 255f;
|
||||
|
||||
if (rotateDir > 2)
|
||||
rotateDir = 2; //TODO - it's 10 in elevtr1, so we can expect to see values other than 0/1/2, but how to treat them?
|
||||
|
||||
float ccwAmount = rotation > e.Model.Rotation.Z ? (e.Model.Rotation.Z + 360 - rotation) : e.Model.Rotation.Z - rotation,
|
||||
cwAmount = rotation < e.Model.Rotation.Z ? (rotation + 360 - e.Model.Rotation.Z) : rotation - e.Model.Rotation.Z;
|
||||
if (rotateDir == 2) {
|
||||
@ -898,9 +1037,10 @@ namespace Braver.Field {
|
||||
return OpResult.Continue;
|
||||
}
|
||||
public static OpResult ANIMW(Fiber f, Entity e, FieldScreen s) {
|
||||
f.Pause();
|
||||
e.Model.AnimationState.AnimationComplete += f.Resume;
|
||||
return OpResult.Continue;
|
||||
if ((bool)f.OtherState["AnimPlaying"])
|
||||
return OpResult.Restart;
|
||||
else
|
||||
return OpResult.Continue;
|
||||
}
|
||||
|
||||
public static OpResult SLIDR(Fiber f, Entity e, FieldScreen s) {
|
||||
@ -1236,7 +1376,10 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
byte span = f.ReadU8();
|
||||
int sound = s.Game.Memory.Read(banks & 0xf, ssound) - 1;
|
||||
int pan = s.Game.Memory.Read(banks >> 4, span);
|
||||
s.Game.Audio.PlaySfx(sound, 1f, (pan - 64) / 64);
|
||||
if (sound < 0)
|
||||
s.Game.Audio.StopLoopingSfx();
|
||||
else
|
||||
s.Game.Audio.PlaySfx(sound, 1f, (pan - 64) / 64);
|
||||
return OpResult.Continue;
|
||||
}
|
||||
|
||||
@ -1270,7 +1413,7 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
int x = s.Game.Memory.Read(banks & 0xf, sx),
|
||||
y = s.Game.Memory.Read(banks >> 4, sy);
|
||||
|
||||
s.BGScroll(x, y);
|
||||
s.BGScroll(x, y, false);
|
||||
return OpResult.Continue;
|
||||
}
|
||||
|
||||
@ -1278,11 +1421,11 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
if (s.Player == null) {
|
||||
s.WhenPlayerSet += () => {
|
||||
var pos = s.ModelToBGPosition(s.Player.Model.Translation);
|
||||
s.BGScroll(pos.X, pos.Y);
|
||||
s.BGScroll(pos.X, pos.Y, true);
|
||||
};
|
||||
} else {
|
||||
var pos = s.ModelToBGPosition(s.Player.Model.Translation);
|
||||
s.BGScroll(pos.X, pos.Y);
|
||||
s.BGScroll(pos.X, pos.Y, true);
|
||||
}
|
||||
return OpResult.Continue;
|
||||
}
|
||||
@ -1312,11 +1455,11 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
var progress = Easings.QuadraticInOut(1f * state.Frame / speed); //TODO - is interpreting speed as framecount vaguely correct?
|
||||
|
||||
if (progress >= 1f) {
|
||||
s.BGScroll(x, y);
|
||||
s.BGScroll(x, y, false);
|
||||
return OpResult.Continue;
|
||||
} else {
|
||||
var pos = state.Start + (end - state.Start) * progress;
|
||||
s.BGScroll(pos.X, pos.Y);
|
||||
s.BGScroll(pos.X, pos.Y, false);
|
||||
state.Frame++;
|
||||
return OpResult.Restart;
|
||||
}
|
||||
@ -1350,13 +1493,14 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
var target = s.ClampBGScrollToViewport(s.ModelToBGPosition(s.Player.Model.Translation));
|
||||
|
||||
if (progress >= 1f) {
|
||||
s.BGScroll(target.X, target.Y);
|
||||
s.BGScroll(target.X, target.Y, true);
|
||||
s.Options &= ~FieldOptions.CameraIsAsyncScrolling;
|
||||
return true;
|
||||
} else {
|
||||
s.BGScroll(
|
||||
curX + (target.X - curX) * progress,
|
||||
curY + (target.Y - curY) * progress
|
||||
curY + (target.Y - curY) * progress,
|
||||
true
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@ -1381,7 +1525,7 @@ if (y + h + MIN_WINDOW_DISTANCE > GAME_HEIGHT) { y = GAME_HEIGHT - h - MIN_WINDO
|
||||
f.Pause();
|
||||
s.StartProcess(frame => {
|
||||
float progress = 1f * frame / numFrames;
|
||||
s.BGScroll(curX + (x - curX) * progress, curY + (y - curY) * progress);
|
||||
s.BGScroll(curX + (x - curX) * progress, curY + (y - curY) * progress, false);
|
||||
|
||||
if (progress >= 1) {
|
||||
f.Resume();
|
||||
|
@ -19,6 +19,8 @@ Field - model lighting looks a bit too bright
|
||||
|
||||
Music looping works but still a noticeable break at the loop point
|
||||
|
||||
Same with audio sfx looping!
|
||||
|
||||
Item menu: Icons, actually do arrange
|
||||
|
||||
Field Fade network msg, movie msg
|
||||
|
@ -224,7 +224,7 @@ namespace Ficedula.FF7 {
|
||||
private struct SoundEntry {
|
||||
public int Size;
|
||||
public int Offset;
|
||||
public byte[] UNK; //16
|
||||
public byte[] ExtraData; //16
|
||||
public byte[] WAVFORMATEX; //18
|
||||
public ushort SamplesPerBlock;
|
||||
public ushort NumCoef;
|
||||
@ -261,7 +261,7 @@ namespace Ficedula.FF7 {
|
||||
var entry = new SoundEntry {
|
||||
Size = size,
|
||||
Offset = s.ReadI32(),
|
||||
UNK = s.ReadBytes(16),
|
||||
ExtraData = s.ReadBytes(16),
|
||||
WAVFORMATEX = s.ReadBytes(18),
|
||||
SamplesPerBlock = s.ReadU16(),
|
||||
NumCoef = s.ReadU16(),
|
||||
@ -292,6 +292,7 @@ namespace Ficedula.FF7 {
|
||||
dest.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
public byte[] GetExtraData(int soundID) => _entries[soundID].ExtraData;
|
||||
public byte[] ExportPCM(int soundID, out int frequency, out int channels) {
|
||||
var entry = _entries[soundID];
|
||||
byte[] buffer = new byte[entry.Size];
|
||||
|
Loading…
x
Reference in New Issue
Block a user