-
Notifications
You must be signed in to change notification settings - Fork 0
/
SplitterComponent.cs
229 lines (215 loc) · 7.64 KB
/
SplitterComponent.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#if !Info
using LiveSplit.Model;
using LiveSplit.UI;
using LiveSplit.UI.Components;
#endif
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml;
namespace LiveSplit.Chronology {
#if !Info
public class SplitterComponent : UI.Components.IComponent {
public TimerModel Model { get; set; }
#else
public class SplitterComponent {
#endif
public string ComponentName { get { return "Chronology Autosplitter"; } }
public IDictionary<string, Action> ContextMenuControls { get { return null; } }
private static string LOGFILE = "_Chronology.log";
internal static string[] keys = { "CurrentSplit", "Loading", "Level", "HasControl", "ChrState", "Position" };
private SplitterMemory mem;
private int currentSplit = -1, lastLogCheck = 0;
private bool hasLog = false;
private Dictionary<string, string> currentValues = new Dictionary<string, string>();
#if !Info
private bool lastLoading = false;
private Level lastLevel;
public SplitterComponent(LiveSplitState state) {
#else
public SplitterComponent() {
#endif
mem = new SplitterMemory();
foreach (string key in keys) {
currentValues[key] = "";
}
#if !Info
if (state != null) {
Model = new TimerModel() { CurrentState = state };
Model.InitializeGameTime();
Model.CurrentState.IsGameTimePaused = true;
state.OnReset += OnReset;
state.OnPause += OnPause;
state.OnResume += OnResume;
state.OnStart += OnStart;
state.OnSplit += OnSplit;
state.OnUndoSplit += OnUndoSplit;
state.OnSkipSplit += OnSkipSplit;
}
#endif
}
public void GetValues() {
if (!mem.HookProcess()) { return; }
#if !Info
if (Model != null) {
HandleSplits();
}
#endif
LogValues();
}
#if !Info
private void HandleSplits() {
bool shouldSplit = false;
bool loading = mem.IsLoading();
Level level = mem.LevelID();
if (currentSplit == -1) {
shouldSplit = level == Level.Cutscene1 && loading && lastLevel != level;
} else if (Model.CurrentState.CurrentPhase == TimerPhase.Running) {
if (Model.CurrentState.Run.Count == 1) {
PointF pos = mem.Position();
shouldSplit = level == Level.Chapter8 && !loading && pos.X >= -4535 && pos.X < -3500 && pos.Y < 1280 && pos.Y > 1260 && !mem.HasControl();
} else {
switch (currentSplit) {
case 0: shouldSplit = level == Level.Cutscene2 && lastLevel != level; break;
case 1: shouldSplit = level == Level.Cutscene3 && lastLevel != level; break;
case 2: shouldSplit = level == Level.Cutscene4 && lastLevel != level; break;
case 3: shouldSplit = level == Level.Cutscene5 && lastLevel != level; break;
case 4: shouldSplit = level == Level.Cutscene6 && lastLevel != level; break;
case 5: shouldSplit = level == Level.Cutscene7 && lastLevel != level; break;
case 6: shouldSplit = level == Level.Chapter8 && lastLevel != level; break;
case 7:
PointF pos = mem.Position();
shouldSplit = level == Level.Chapter8 && !loading && pos.X >= -4535 && pos.X < -3500 && pos.Y < 1280 && pos.Y > 1260 && !mem.HasControl(); break;
}
}
}
Model.CurrentState.IsGameTimePaused = loading;
lastLoading = loading;
HandleSplit(shouldSplit, level == Level.MainMenu && lastLevel != level);
lastLevel = level;
}
private void HandleSplit(bool shouldSplit, bool shouldReset = false) {
if (shouldReset) {
if (currentSplit >= 0) {
Model.Reset();
}
} else if (shouldSplit) {
if (currentSplit < 0) {
Model.Start();
} else {
Model.Split();
}
}
}
#endif
private void LogValues() {
if (lastLogCheck == 0) {
hasLog = File.Exists(LOGFILE);
lastLogCheck = 300;
}
lastLogCheck--;
if (hasLog || !Console.IsOutputRedirected) {
string prev = string.Empty, curr = string.Empty;
foreach (string key in keys) {
prev = currentValues[key];
switch (key) {
case "CurrentSplit": curr = currentSplit.ToString(); break;
case "Loading": curr = mem.IsLoading().ToString(); break;
case "Level": curr = mem.LevelID().ToString(); break;
case "HasControl": curr = mem.HasControl().ToString(); break;
//case "Position":
// PointF pos = mem.Position();
// curr = pos.X.ToString("0") + ", " + pos.Y.ToString("0");
// break;
case "ChrState": curr = mem.CharacterState().ToString(); break;
default: curr = string.Empty; break;
}
if (prev == null) { prev = string.Empty; }
if (curr == null) { curr = string.Empty; }
if (!prev.Equals(curr)) {
WriteLogWithTime(key + ": ".PadRight(16 - key.Length, ' ') + prev.PadLeft(25, ' ') + " -> " + curr);
currentValues[key] = curr;
}
}
}
}
private void WriteLog(string data) {
if (hasLog || !Console.IsOutputRedirected) {
if (!Console.IsOutputRedirected) {
Console.WriteLine(data);
}
if (hasLog) {
using (StreamWriter wr = new StreamWriter(LOGFILE, true)) {
wr.WriteLine(data);
}
}
}
}
private void WriteLogWithTime(string data) {
#if !Info
WriteLog(DateTime.Now.ToString(@"HH\:mm\:ss.fff") + (Model != null && Model.CurrentState.CurrentTime.RealTime.HasValue ? " | " + Model.CurrentState.CurrentTime.RealTime.Value.ToString("G").Substring(3, 11) : "") + ": " + data);
#else
WriteLog(DateTime.Now.ToString(@"HH\:mm\:ss.fff") + ": " + data);
#endif
}
#if !Info
public void Update(IInvalidator invalidator, LiveSplitState lvstate, float width, float height, LayoutMode mode) {
//Remove duplicate autosplitter componenets
IList<ILayoutComponent> components = lvstate.Layout.LayoutComponents;
bool hasAutosplitter = false;
for (int i = components.Count - 1; i >= 0; i--) {
ILayoutComponent component = components[i];
if (component.Component is SplitterComponent) {
if ((invalidator == null && width == 0 && height == 0) || hasAutosplitter) {
components.Remove(component);
}
hasAutosplitter = true;
}
}
GetValues();
}
public void OnReset(object sender, TimerPhase e) {
currentSplit = -1;
Model.CurrentState.IsGameTimePaused = true;
WriteLog("---------Reset----------------------------------");
}
public void OnResume(object sender, EventArgs e) {
WriteLog("---------Resumed--------------------------------");
}
public void OnPause(object sender, EventArgs e) {
WriteLog("---------Paused---------------------------------");
}
public void OnStart(object sender, EventArgs e) {
currentSplit = 0;
Model.CurrentState.IsGameTimePaused = true;
Model.CurrentState.SetGameTime(TimeSpan.FromSeconds(0));
WriteLog("---------New Game-------------------------------");
}
public void OnUndoSplit(object sender, EventArgs e) {
currentSplit--;
}
public void OnSkipSplit(object sender, EventArgs e) {
currentSplit++;
}
public void OnSplit(object sender, EventArgs e) {
currentSplit++;
}
public Control GetSettingsControl(LayoutMode mode) { return null; }
public void SetSettings(XmlNode document) { }
public XmlNode GetSettings(XmlDocument document) { return document.CreateElement("Settings"); }
public void DrawHorizontal(Graphics g, LiveSplitState state, float height, Region clipRegion) { }
public void DrawVertical(Graphics g, LiveSplitState state, float width, Region clipRegion) { }
#endif
public float HorizontalWidth { get { return 0; } }
public float MinimumHeight { get { return 0; } }
public float MinimumWidth { get { return 0; } }
public float PaddingBottom { get { return 0; } }
public float PaddingLeft { get { return 0; } }
public float PaddingRight { get { return 0; } }
public float PaddingTop { get { return 0; } }
public float VerticalHeight { get { return 0; } }
public void Dispose() { }
}
}