using System.Diagnostics; using System.Timers; using System.Windows.Forms; using System.Xml; using LiveSplit.Model; using LiveSplit.UI; using LiveSplit.UI.Components; using SystemTimer = System.Timers.Timer; namespace LiveSplit.TZA; public class TzaComponent : LogicComponent { public override string ComponentName => "FFXII: The Zodiac Age"; internal TimerModel Timer { get; } internal GameMemory? GameMemory { get; set; } private TzaControl Control { get; } private SystemTimer UpdateTimer { get; } private SplitLogic Logic { get; set; } public TzaComponent(LiveSplitState state) { this.Timer = new TimerModel { CurrentState = state }; this.Control = new TzaControl(); this.Logic = new SplitLogic(); this.UpdateTimer = new SystemTimer(16f); this.UpdateTimer.Elapsed += this.UpdateTimeUpdate; this.UpdateTimer.Start(); this.Timer.CurrentState.OnStart += this.OnStart; this.Timer.CurrentState.OnReset += this.OnReset; } public override void Dispose() { this.Timer.CurrentState.OnReset -= this.OnReset; this.Timer.CurrentState.OnStart += this.OnStart; this.UpdateTimer.Stop(); this.UpdateTimer.Dispose(); } private void OnStart(object sender, EventArgs e) { this.Timer.InitializeGameTime(); } private void OnReset(object sender, TimerPhase value) { this.Logic = new SplitLogic(); } private void UpdateTimeUpdate(object? sender, ElapsedEventArgs? e) { // if (this.Timer.CurrentState.Run.GameName != "FFXII: The Zodiac Age") { // return; // } if (this.GameMemory == null) { var game = Process.GetProcessesByName("FFXII_TZA").FirstOrDefault(); if (game != null) { this.GameMemory = new GameMemory(game); } } if (this.GameMemory != null) { if (!this.GameMemory.Update()) { this.GameMemory = null; } } if (this.GameMemory == null) { this.Timer.CurrentState.IsGameTimePaused = false; return; } if (this.Timer.CurrentState.CurrentPhase is not (TimerPhase.NotRunning or TimerPhase.Ended) && this.GameMemory.Location.Current is 12 or 13) { // if timer is started and at main menu or credits, never count as paused this.Timer.CurrentState.IsGameTimePaused = false; } else { this.Timer.CurrentState.IsGameTimePaused = (this.GameMemory.IsLoaded.Current & 0x100) != 0; } switch (this.Logic.Tick(this.Control, this.Timer.CurrentState.CurrentPhase, this.GameMemory)) { case LogicResult.Start: this.Timer.Start(); break; case LogicResult.Split: this.Timer.Split(); break; case LogicResult.None: default: // do nothing break; } } public override Control GetSettingsControl(LayoutMode mode) { return this.Control; } public override XmlNode GetSettings(XmlDocument document) { return this.Control.GetSettings(document); } public override void SetSettings(XmlNode settings) { this.Control.SetSettings(settings); } public override void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { } }