From 14a2cd5a60f148a7eae3d0a68936836ff3ba33de Mon Sep 17 00:00:00 2001 From: Dalet Date: Thu, 28 Aug 2014 00:54:45 +0200 Subject: [PATCH 01/16] First attempt at starting the timer automatically --- GameMemory.cs | 40 ++++++++++++++++++++++++---------------- SkyrimComponent.cs | 13 +++++++------ 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 4dfad90..0bf61f8 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -16,7 +16,8 @@ class GameMemory public event EventHandler OnLoadFinished; public event EventHandler OnLoadScreenStarted; public event EventHandler OnLoadScreenFinished; - public event EventHandler OnAlduinDefeated; + public event EventHandler OnAlduinDefeated; + public event EventHandler OnPlayerGainedControl; private Task _thread; private CancellationTokenSource _cancelSource; @@ -25,7 +26,8 @@ class GameMemory // private DeepPointer _currentLevelPtr; private DeepPointer _isLoadingPtr; - private DeepPointer _isLoadingScreenPtr; + private DeepPointer _isLoadingScreenPtr; + private DeepPointer _isInLoadScreenFadeOutPtr; private DeepPointer _isAlduinDefeatedPtr; // private int _stringBase; @@ -39,8 +41,10 @@ public GameMemory() { _isLoadingPtr = new DeepPointer("TESV.exe", 0x17337CC); // == 1 if a loading is happening (any except loading screens in Helgen for some reason) _isLoadingScreenPtr = new DeepPointer("TESV.exe", 0xEE3561); // == 1 if in a loading screen - // _isPausedPtr = new DeepPointer("TESV.exe", 0x172E85F); // == 1 if in a menu or a loading screen - + // _isPausedPtr = new DeepPointer("TESV.exe", 0x172E85F); // == 1 if in a menu or a loading screen + + _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained + _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x12ACF78C); // == 1 when last blow is struck on alduin // possible: 0x12ACF78C, 0x12FD23DB @@ -95,7 +99,8 @@ void MemoryReadThread() // int prevCurrentLevel = 0; bool prevIsLoading = false; bool prevIsLoadingScreen = false; - bool prevIsAlduinDefeated = false; + bool prevIsAlduinDefeated = false; + bool prevIsInLoadScreenFadeOut = false; bool loadingStarted = false; bool loadingScreenStarted = false; @@ -113,7 +118,10 @@ void MemoryReadThread() _isLoadingScreenPtr.Deref(game, out isLoadingScreen); if (isLoadingScreen) - isLoading = true; + isLoading = true; + + bool isInLoadScreenFadeOut; + _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); bool isAlduinDefeated; _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); @@ -188,16 +196,15 @@ void MemoryReadThread() this.OnLoadScreenFinished(this, EventArgs.Empty); }, null); } - - // if (((currentMovie == "LoadingEmpressTower" || currentMovie == "INTRO_LOC") && currentLevelStr == "l_tower_p") - // || (currentMovie == "Loading" || currentMovie == "LoadingDLC06Tower") && currentLevelStr == "DLC06_Tower_P") // KoD - // { - // _uiThread.Post(d => { - // if (this.OnPlayerGainedControl != null) - // this.OnPlayerGainedControl(this, EventArgs.Empty); - // }, null); - // } } + } + + if (isInLoadScreenFadeOut == false && prevIsInLoadScreenFadeOut == true) //start the timer when we gained control after a fade out + { + _uiThread.Post(d => { + if (this.OnPlayerGainedControl != null) + this.OnPlayerGainedControl(this, EventArgs.Empty); + }, null); } //if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) @@ -211,7 +218,8 @@ void MemoryReadThread() // prevCurrentLevel = currentLevel; prevIsLoading = isLoading; prevIsLoadingScreen = isLoadingScreen; - prevIsAlduinDefeated = isAlduinDefeated; + prevIsAlduinDefeated = isAlduinDefeated; + prevIsInLoadScreenFadeOut = isInLoadScreenFadeOut; frameCounter++; Thread.Sleep(15); diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index d664964..efa4ded 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -43,7 +43,8 @@ public SkyrimComponent(LiveSplitState state) _gameMemory.OnLoadFinished += gameMemory_OnLoadFinished; _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; - _gameMemory.OnAlduinDefeated += gameMemory_OnAlduinDefeated; + _gameMemory.OnAlduinDefeated += gameMemory_OnAlduinDefeated; + _gameMemory.OnPlayerGainedControl += gameMemory_OnPlayerGainedControl; _gameMemory.StartMonitoring(); } @@ -96,11 +97,11 @@ void PrepareDraw(LiveSplitState state) // _timer.Reset(); // } - // void gameMemory_OnPlayerGainedControl(object sender, EventArgs e) - // { - // if (this.Settings.AutoStartEnd) - // _timer.Start(); - // } + void gameMemory_OnPlayerGainedControl(object sender, EventArgs e) + { + //if (this.Settings.AutoStartEnd) + _timer.Start(); + } void gameMemory_OnLoadStarted(object sender, EventArgs e) { From 130d5763abfe7e3e456e78c314f7671a379a7ecf Mon Sep 17 00:00:00 2001 From: Dalet Date: Thu, 28 Aug 2014 01:00:02 +0200 Subject: [PATCH 02/16] Added TESV.CT --- TESV.CT | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 TESV.CT diff --git a/TESV.CT b/TESV.CT new file mode 100644 index 0000000..b3c327a --- /dev/null +++ b/TESV.CT @@ -0,0 +1,62 @@ + + + + + 0 + "isPaused" + + 80000008 + Byte +
"TESV.exe"+172E85F
+
+ + 1 + "isLoading" + + 80000008 + Byte +
"TESV.exe"+17337CC
+
+ + 3 + "isLoadscreen" + + 80000008 + Byte +
"TESV.exe"+EE3561
+
+ + 4 + "AreHandsTied?" + + 80000008 + Byte +
TESV.exe+172EE2C
+
+ + 5 + "IsInFadeOut?" + + 80000008 + Byte +
TESV.exe+172EE2E
+
+ + 6 + "No description" + + 80000008 + Byte +
TESV.exe+1739DF9
+
+ + 7 + "No description" + + 80000008 + Byte +
TESV.exe+174045C
+
+
+ +
From 9e9c6888c4664c2f44f678a62cefd1570a653ca1 Mon Sep 17 00:00:00 2001 From: Dalet Date: Thu, 28 Aug 2014 02:52:11 +0200 Subject: [PATCH 03/16] Trying to get cell coordinates working --- GameMemory.cs | 70 ++++++++++++++++++++++++---------------------- SkyrimComponent.cs | 19 ++++++------- TESV.CT | 24 +++++++++++++++- 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 0bf61f8..89a0cd2 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -10,26 +10,25 @@ namespace LiveSplit.Skyrim { class GameMemory { - // public event EventHandler OnFirstLevelLoading; - // public event EventHandler OnPlayerGainedControl; + public event EventHandler OnFirstLevelLoading; + public event EventHandler OnPlayerGainedControl; public event EventHandler OnLoadStarted; public event EventHandler OnLoadFinished; public event EventHandler OnLoadScreenStarted; public event EventHandler OnLoadScreenFinished; - public event EventHandler OnAlduinDefeated; - public event EventHandler OnPlayerGainedControl; + public event EventHandler OnAlduinDefeated; private Task _thread; private CancellationTokenSource _cancelSource; private SynchronizationContext _uiThread; private List _ignorePIDs; - // private DeepPointer _currentLevelPtr; private DeepPointer _isLoadingPtr; private DeepPointer _isLoadingScreenPtr; - private DeepPointer _isInLoadScreenFadeOutPtr; + private DeepPointer _isInLoadScreenFadeOutPtr; + private DeepPointer _world_XPtr; + private DeepPointer _world_YPtr; private DeepPointer _isAlduinDefeatedPtr; - // private int _stringBase; private enum ExpectedDllSizes { @@ -43,8 +42,11 @@ public GameMemory() _isLoadingScreenPtr = new DeepPointer("TESV.exe", 0xEE3561); // == 1 if in a loading screen // _isPausedPtr = new DeepPointer("TESV.exe", 0x172E85F); // == 1 if in a menu or a loading screen - _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained - + _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained + + _world_XPtr = new DeepPointer("TESV.exe", 0x01B2E864, 0x64); // X world position (cell) + _world_YPtr = new DeepPointer("TESV.exe", 0x01B2E864, 0x68); // Y world position (cell) + _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x12ACF78C); // == 1 when last blow is struck on alduin // possible: 0x12ACF78C, 0x12FD23DB @@ -96,7 +98,6 @@ void MemoryReadThread() uint frameCounter = 0; - // int prevCurrentLevel = 0; bool prevIsLoading = false; bool prevIsLoadingScreen = false; bool prevIsAlduinDefeated = false; @@ -107,10 +108,6 @@ void MemoryReadThread() while (!game.HasExited) { - // int currentLevel; - // _currentLevelPtr.Deref(game, out currentLevel); - // string currentLevelStr = GetEngineStringByID(game, currentLevel); - bool isLoading; _isLoadingPtr.Deref(game, out isLoading); @@ -121,24 +118,17 @@ void MemoryReadThread() isLoading = true; bool isInLoadScreenFadeOut; - _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); + _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); + + int world_X; + _world_XPtr.Deref(game, out world_X); + + int world_Y; + _world_YPtr.Deref(game, out world_Y); bool isAlduinDefeated; _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); - // if (currentLevel != prevCurrentLevel) - // { - // Trace.WriteLine(String.Format("{0} [NoLoads] Level Changed - {1} -> {2} '{3}'", frameCounter, prevCurrentLevel, currentLevel, currentLevelStr)); - - // if (currentLevelStr == "l_tower_p" || currentLevelStr == "L_DLC07_BaseIntro_P" || currentLevelStr == "DLC06_Tower_P") - // { - // _uiThread.Post(d => { - // if (this.OnFirstLevelLoading != null) - // this.OnFirstLevelLoading(this, EventArgs.Empty); - // }, null); - // } - // } - if (isLoading != prevIsLoading) { if (isLoading) @@ -199,12 +189,25 @@ void MemoryReadThread() } } - if (isInLoadScreenFadeOut == false && prevIsInLoadScreenFadeOut == true) //start the timer when we gained control after a fade out + if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut) { - _uiThread.Post(d => { - if (this.OnPlayerGainedControl != null) - this.OnPlayerGainedControl(this, EventArgs.Empty); - }, null); + _uiThread.Send(d => MessageBox.Show("X:" + world_X.ToString() + " Y:" + world_Y.ToString(), "LiveSplit.Skyrim", + MessageBoxButtons.OK, MessageBoxIcon.Error), null); + if (isInLoadScreenFadeOut == false && prevIsInLoadScreenFadeOut == true) + { + _uiThread.Post(d => + { + if (this.OnPlayerGainedControl != null) + this.OnPlayerGainedControl(this, EventArgs.Empty); + }, null); + } + else if (isInLoadScreenFadeOut && world_X == 3 && world_Y == -20) + { + _uiThread.Post(d => { + if (this.OnFirstLevelLoading != null) + this.OnFirstLevelLoading(this, EventArgs.Empty); + }, null); + } } //if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) @@ -215,7 +218,6 @@ void MemoryReadThread() // }, null); //} - // prevCurrentLevel = currentLevel; prevIsLoading = isLoading; prevIsLoadingScreen = isLoadingScreen; prevIsAlduinDefeated = isAlduinDefeated; diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index efa4ded..28f0e14 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -37,14 +37,13 @@ public SkyrimComponent(LiveSplitState state) _state = state; _gameMemory = new GameMemory(); - // _gameMemory.OnFirstLevelLoading += gameMemory_OnFirstLevelLoading; - // _gameMemory.OnPlayerGainedControl += gameMemory_OnPlayerGainedControl; + _gameMemory.OnFirstLevelLoading += gameMemory_OnFirstLevelLoading; + _gameMemory.OnPlayerGainedControl += gameMemory_OnPlayerGainedControl; _gameMemory.OnLoadStarted += gameMemory_OnLoadStarted; _gameMemory.OnLoadFinished += gameMemory_OnLoadFinished; _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; - _gameMemory.OnAlduinDefeated += gameMemory_OnAlduinDefeated; - _gameMemory.OnPlayerGainedControl += gameMemory_OnPlayerGainedControl; + _gameMemory.OnAlduinDefeated += gameMemory_OnAlduinDefeated; _gameMemory.StartMonitoring(); } @@ -91,15 +90,15 @@ void PrepareDraw(LiveSplitState state) this.InternalComponent.NameLabel.HasShadow = this.InternalComponent.ValueLabel.HasShadow = state.LayoutSettings.DropShadows; } - // void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) - // { - // if (this.Settings.AutoStartEnd) - // _timer.Reset(); - // } + void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) + { + if (this.Settings.AutoStartEnd) + _timer.Reset(); + } void gameMemory_OnPlayerGainedControl(object sender, EventArgs e) { - //if (this.Settings.AutoStartEnd) + if (this.Settings.AutoStartEnd) _timer.Start(); } diff --git a/TESV.CT b/TESV.CT index b3c327a..c56a58e 100644 --- a/TESV.CT +++ b/TESV.CT @@ -4,7 +4,7 @@ 0 "isPaused" - + 80000008 Byte
"TESV.exe"+172E85F
@@ -57,6 +57,28 @@ Byte
TESV.exe+174045C
+ + 9 + "X world coord" + + 80000008 + 2 Bytes +
01B2E864
+ + 64 + +
+ + 11 + "Y world coord" + + 80000008 + 2 Bytes +
01B2E864
+ + 68 + +
From ac2967a1b9158f73857bbcc9d73a53b14031ad76 Mon Sep 17 00:00:00 2001 From: Dalet Date: Thu, 28 Aug 2014 03:42:06 +0200 Subject: [PATCH 04/16] Corrected the coordinates addresses --- GameMemory.cs | 23 +++++++++++------------ TESV.CT | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 89a0cd2..4f696e1 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -44,8 +44,8 @@ public GameMemory() _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained - _world_XPtr = new DeepPointer("TESV.exe", 0x01B2E864, 0x64); // X world position (cell) - _world_YPtr = new DeepPointer("TESV.exe", 0x01B2E864, 0x68); // Y world position (cell) + _world_XPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x64); // X world position (cell) + _world_YPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x68); // Y world position (cell) _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x12ACF78C); // == 1 when last blow is struck on alduin // possible: 0x12ACF78C, 0x12FD23DB @@ -189,25 +189,24 @@ void MemoryReadThread() } } - if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut) + if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut && world_X == 3 && world_Y == -20) { - _uiThread.Send(d => MessageBox.Show("X:" + world_X.ToString() + " Y:" + world_Y.ToString(), "LiveSplit.Skyrim", - MessageBoxButtons.OK, MessageBoxIcon.Error), null); if (isInLoadScreenFadeOut == false && prevIsInLoadScreenFadeOut == true) { + //reset + _uiThread.Post(d => + { + if (this.OnFirstLevelLoading != null) + this.OnFirstLevelLoading(this, EventArgs.Empty); + }, null); + + //start _uiThread.Post(d => { if (this.OnPlayerGainedControl != null) this.OnPlayerGainedControl(this, EventArgs.Empty); }, null); } - else if (isInLoadScreenFadeOut && world_X == 3 && world_Y == -20) - { - _uiThread.Post(d => { - if (this.OnFirstLevelLoading != null) - this.OnFirstLevelLoading(this, EventArgs.Empty); - }, null); - } } //if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) diff --git a/TESV.CT b/TESV.CT index c56a58e..72bcffd 100644 --- a/TESV.CT +++ b/TESV.CT @@ -63,7 +63,7 @@ 80000008 2 Bytes -
01B2E864
+
"TESV.exe"+0172E864
64 @@ -74,7 +74,7 @@ 80000008 2 Bytes -
01B2E864
+
"TESV.exe"+0172E864
68 From 30a2c5479f8a79b5e3e5edd5d197c3fe732ecf85 Mon Sep 17 00:00:00 2001 From: drtchops Date: Wed, 27 Aug 2014 22:58:46 -0400 Subject: [PATCH 05/16] Find alduin defeated and player has control pointers --- GameMemory.cs | 60 ++++++++++++++++++++++++++++++++++++--------------- TESV.CT | 27 +++++++++++++++++++---- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 4f696e1..911d620 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -28,7 +28,8 @@ class GameMemory private DeepPointer _isInLoadScreenFadeOutPtr; private DeepPointer _world_XPtr; private DeepPointer _world_YPtr; - private DeepPointer _isAlduinDefeatedPtr; + private DeepPointer _isAlduinDefeatedPtr; + private DeepPointer _playerHasControlPtr; private enum ExpectedDllSizes { @@ -47,10 +48,8 @@ public GameMemory() _world_XPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x64); // X world position (cell) _world_YPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x68); // Y world position (cell) - _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x12ACF78C); // == 1 when last blow is struck on alduin - // possible: 0x12ACF78C, 0x12FD23DB - - // possible for start of splits: 13682838 == 18A4A + _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x1711608); // == 1 when last blow is struck on alduin + _playerHasControlPtr = new DeepPointer("TESV.exe", 0x74814710); // == 1 when player has full control _ignorePIDs = new List(); } @@ -101,7 +100,8 @@ void MemoryReadThread() bool prevIsLoading = false; bool prevIsLoadingScreen = false; bool prevIsAlduinDefeated = false; - bool prevIsInLoadScreenFadeOut = false; + bool prevIsInLoadScreenFadeOut = false; + bool prevPlayerHasControl = false; bool loadingStarted = false; bool loadingScreenStarted = false; @@ -127,7 +127,10 @@ void MemoryReadThread() _world_YPtr.Deref(game, out world_Y); bool isAlduinDefeated; - _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); + _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); + + bool playerHasControl; + _playerHasControlPtr.Deref(game, out playerHasControl); if (isLoading != prevIsLoading) { @@ -137,6 +140,7 @@ void MemoryReadThread() loadingStarted = true; + // pause game timer _uiThread.Post(d => { if (this.OnLoadStarted != null) this.OnLoadStarted(this, EventArgs.Empty); @@ -150,6 +154,7 @@ void MemoryReadThread() { loadingStarted = false; + // unpause game timer _uiThread.Post(d => { if (this.OnLoadFinished != null) this.OnLoadFinished(this, EventArgs.Empty); @@ -184,7 +189,16 @@ void MemoryReadThread() { if (this.OnLoadScreenFinished != null) this.OnLoadScreenFinished(this, EventArgs.Empty); - }, null); + }, null); + + //if (!playerHasControl) + //{ + // _uiThread.Post(d => + // { + // if (this.OnFirstLevelLoading != null) + // this.OnFirstLevelLoading(this, EventArgs.Empty); + // }, null); + //} } } } @@ -207,20 +221,32 @@ void MemoryReadThread() this.OnPlayerGainedControl(this, EventArgs.Empty); }, null); } + } + + //if (playerHasControl != prevPlayerHasControl && playerHasControl && !isLoading) + //{ + // _uiThread.Post(d => + // { + // if (this.OnPlayerGainedControl != null) + // this.OnPlayerGainedControl(this, EventArgs.Empty); + // }, null); + //} + + if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) + { + // split + _uiThread.Post(d => + { + if (this.OnAlduinDefeated != null) + this.OnAlduinDefeated(this, EventArgs.Empty); + }, null); } - //if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) - //{ - // _uiThread.Post(d => { - // if (this.OnAlduinDefeated != null) - // this.OnAlduinDefeated(this, EventArgs.Empty); - // }, null); - //} - prevIsLoading = isLoading; prevIsLoadingScreen = isLoadingScreen; prevIsAlduinDefeated = isAlduinDefeated; - prevIsInLoadScreenFadeOut = isInLoadScreenFadeOut; + prevIsInLoadScreenFadeOut = isInLoadScreenFadeOut; + prevPlayerHasControl = playerHasControl; frameCounter++; Thread.Sleep(15); diff --git a/TESV.CT b/TESV.CT index 72bcffd..a460613 100644 --- a/TESV.CT +++ b/TESV.CT @@ -4,7 +4,7 @@ 0 "isPaused" - + 80000008 Byte
"TESV.exe"+172E85F
@@ -28,7 +28,7 @@ 4 "AreHandsTied?" - + 80000008 Byte
TESV.exe+172EE2C
@@ -41,6 +41,14 @@ Byte
TESV.exe+172EE2E
+ + 12 + "IsAlduinDead?" + + 80000008 + Byte +
TESV.exe+1711608
+
6 "No description" @@ -60,7 +68,7 @@ 9 "X world coord" - + 80000008 2 Bytes
"TESV.exe"+0172E864
@@ -71,7 +79,7 @@ 11 "Y world coord" - + 80000008 2 Bytes
"TESV.exe"+0172E864
@@ -79,6 +87,17 @@ 68
+ + 14 + "PlayerHasControl" + + 80000008 + Byte +
74814710
+ + 2 + +
From 1f0ca4dcb7272fd6c0e34194ff92ae0f0174a3cf Mon Sep 17 00:00:00 2001 From: Dalet Date: Thu, 28 Aug 2014 17:23:28 +0200 Subject: [PATCH 06/16] now starts and resets only in Helgen + position check at alduin --- GameMemory.cs | 12 +++++++++--- TESV.CT | 45 +++++++++++++-------------------------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 911d620..97b84ac 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -26,6 +26,7 @@ class GameMemory private DeepPointer _isLoadingPtr; private DeepPointer _isLoadingScreenPtr; private DeepPointer _isInLoadScreenFadeOutPtr; + private DeepPointer _isInTamriel; private DeepPointer _world_XPtr; private DeepPointer _world_YPtr; private DeepPointer _isAlduinDefeatedPtr; @@ -45,6 +46,7 @@ public GameMemory() _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained + _isInTamriel = new DeepPointer("TESV.exe", 0x173815C); // == 1 if the player is in the Tamriel world space _world_XPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x64); // X world position (cell) _world_YPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x68); // Y world position (cell) @@ -120,6 +122,9 @@ void MemoryReadThread() bool isInLoadScreenFadeOut; _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); + bool isInTamriel; + _isInTamriel.Deref(game, out isInTamriel); + int world_X; _world_XPtr.Deref(game, out world_X); @@ -203,9 +208,9 @@ void MemoryReadThread() } } - if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut && world_X == 3 && world_Y == -20) + if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut && isInTamriel && world_X == 3 && world_Y == -20) { - if (isInLoadScreenFadeOut == false && prevIsInLoadScreenFadeOut == true) + if (!isInLoadScreenFadeOut && prevIsInLoadScreenFadeOut) { //reset _uiThread.Post(d => @@ -232,7 +237,8 @@ void MemoryReadThread() // }, null); //} - if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated) + if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated + && !isInTamriel && ((world_X == 15 && world_Y == 19) || (world_X == 15 && world_Y == 20))) { // split _uiThread.Post(d => diff --git a/TESV.CT b/TESV.CT index a460613..bea16a6 100644 --- a/TESV.CT +++ b/TESV.CT @@ -4,7 +4,7 @@ 0 "isPaused" - + 80000008 Byte
"TESV.exe"+172E85F
@@ -12,7 +12,7 @@ 1 "isLoading" - + 80000008 Byte
"TESV.exe"+17337CC
@@ -20,7 +20,7 @@ 3 "isLoadscreen" - + 80000008 Byte
"TESV.exe"+EE3561
@@ -28,15 +28,15 @@ 4 "AreHandsTied?" - + 80000008 Byte
TESV.exe+172EE2C
5 - "IsInFadeOut?" - + "IsInFadeOut" + 80000008 Byte
TESV.exe+172EE2E
@@ -44,31 +44,15 @@ 12 "IsAlduinDead?" - + 80000008 Byte
TESV.exe+1711608
- - 6 - "No description" - - 80000008 - Byte -
TESV.exe+1739DF9
-
- - 7 - "No description" - - 80000008 - Byte -
TESV.exe+174045C
-
9 "X world coord" - + 80000008 2 Bytes
"TESV.exe"+0172E864
@@ -79,7 +63,7 @@ 11 "Y world coord" - + 80000008 2 Bytes
"TESV.exe"+0172E864
@@ -88,15 +72,12 @@
- 14 - "PlayerHasControl" - + 18 + "isInTamriel" + 80000008 Byte -
74814710
- - 2 - +
TESV.exe+173815C
From 8861f6470e96e44d74c978aacbc82b825275c520 Mon Sep 17 00:00:00 2001 From: Dalet Date: Fri, 29 Aug 2014 01:09:33 +0200 Subject: [PATCH 07/16] Added Helgen autosplit and double split protection --- GameMemory.cs | 45 ++++++++++++++++++++++++++++++++------ SkyrimComponent.cs | 10 +++++---- SkyrimSettings.Designer.cs | 21 ++++++++++++++---- SkyrimSettings.cs | 15 ++++++++----- TESV.CT | 22 +++++++++---------- 5 files changed, 82 insertions(+), 31 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 97b84ac..4fea8b8 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -9,14 +9,21 @@ namespace LiveSplit.Skyrim { class GameMemory - { + { + public enum SplitArea : int + { + Helgen, + AlduinDefeated + } + public event EventHandler OnFirstLevelLoading; public event EventHandler OnPlayerGainedControl; public event EventHandler OnLoadStarted; public event EventHandler OnLoadFinished; public event EventHandler OnLoadScreenStarted; - public event EventHandler OnLoadScreenFinished; - public event EventHandler OnAlduinDefeated; + public event EventHandler OnLoadScreenFinished; + public delegate void SplitCompletedEventHandler(object sender, SplitArea type); + public event SplitCompletedEventHandler OnSplitCompleted; private Task _thread; private CancellationTokenSource _cancelSource; @@ -36,6 +43,16 @@ private enum ExpectedDllSizes { SkyrimSteam = 27336704, SkyrimCracked = 26771456, + } + + private bool[] splitStates = new bool[(int)SplitArea.AlduinDefeated + 1]; + + public void resetSplitStates() + { + for (int i = 0; i <= (int)SplitArea.AlduinDefeated; i++) + { + splitStates[i] = false; + } } public GameMemory() @@ -51,7 +68,9 @@ public GameMemory() _world_YPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x68); // Y world position (cell) _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x1711608); // == 1 when last blow is struck on alduin - _playerHasControlPtr = new DeepPointer("TESV.exe", 0x74814710); // == 1 when player has full control + _playerHasControlPtr = new DeepPointer("TESV.exe", 0x74814710); // == 1 when player has full control + + resetSplitStates(); _ignorePIDs = new List(); } @@ -181,6 +200,17 @@ void MemoryReadThread() if (this.OnLoadScreenStarted != null) this.OnLoadScreenStarted(this, EventArgs.Empty); }, null); + + if (!isInTamriel && world_X == -2 && world_Y == -5 && !splitStates[(int)SplitArea.Helgen]) + { + // Helgen split + _uiThread.Post(d => + { + if (this.OnSplitCompleted != null) + this.OnSplitCompleted(this, SplitArea.Helgen); + }, null); + splitStates[(int)SplitArea.Helgen] = true; + } } else { @@ -237,15 +267,16 @@ void MemoryReadThread() // }, null); //} - if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated + if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated && !splitStates[(int)SplitArea.AlduinDefeated] && !isInTamriel && ((world_X == 15 && world_Y == 19) || (world_X == 15 && world_Y == 20))) { // split _uiThread.Post(d => { - if (this.OnAlduinDefeated != null) - this.OnAlduinDefeated(this, EventArgs.Empty); + if (this.OnSplitCompleted != null) + this.OnSplitCompleted(this, SplitArea.AlduinDefeated); }, null); + splitStates[(int)SplitArea.AlduinDefeated] = true; } prevIsLoading = isLoading; diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index 28f0e14..de22b79 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -43,7 +43,7 @@ public SkyrimComponent(LiveSplitState state) _gameMemory.OnLoadFinished += gameMemory_OnLoadFinished; _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; - _gameMemory.OnAlduinDefeated += gameMemory_OnAlduinDefeated; + _gameMemory.OnSplitCompleted += gameMemory_OnSplitCompleted; _gameMemory.StartMonitoring(); } @@ -91,7 +91,8 @@ void PrepareDraw(LiveSplitState state) } void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) - { + { + _gameMemory.resetSplitStates(); if (this.Settings.AutoStartEnd) _timer.Reset(); } @@ -122,9 +123,10 @@ void gameMemory_OnLoadScreenFinished(object sender, EventArgs e) // TODO } - void gameMemory_OnAlduinDefeated(object sender, EventArgs e) + void gameMemory_OnSplitCompleted(object sender, GameMemory.SplitArea split) { - if (this.Settings.AutoStartEnd) + if ((split == GameMemory.SplitArea.Helgen && this.Settings.Helgen) + || (split == GameMemory.SplitArea.AlduinDefeated && this.Settings.AutoStartEnd)) _timer.Split(); } diff --git a/SkyrimSettings.Designer.cs b/SkyrimSettings.Designer.cs index 99bb884..290457b 100644 --- a/SkyrimSettings.Designer.cs +++ b/SkyrimSettings.Designer.cs @@ -35,6 +35,7 @@ private void InitializeComponent() this.gbLoadRemoval = new System.Windows.Forms.GroupBox(); this.tlpLoadRemoval = new System.Windows.Forms.TableLayoutPanel(); this.chkDisplayWithoutLoads = new System.Windows.Forms.CheckBox(); + this.chkHelgen = new System.Windows.Forms.CheckBox(); this.tlpMain.SuspendLayout(); this.gbAutoSplit.SuspendLayout(); this.tlpAutoSplit.SuspendLayout(); @@ -72,6 +73,7 @@ private void InitializeComponent() // this.tlpAutoSplit.ColumnCount = 1; this.tlpAutoSplit.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpAutoSplit.Controls.Add(this.chkHelgen, 0, 5); this.tlpAutoSplit.Controls.Add(this.chkAutoStartEnd, 0, 0); this.tlpAutoSplit.Dock = System.Windows.Forms.DockStyle.Fill; this.tlpAutoSplit.Location = new System.Drawing.Point(3, 16); @@ -83,7 +85,7 @@ private void InitializeComponent() this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.Size = new System.Drawing.Size(464, 44); + this.tlpAutoSplit.Size = new System.Drawing.Size(464, 144); this.tlpAutoSplit.TabIndex = 0; // // chkAutoStartEnd @@ -93,9 +95,9 @@ private void InitializeComponent() this.chkAutoStartEnd.CheckState = System.Windows.Forms.CheckState.Checked; this.chkAutoStartEnd.Location = new System.Drawing.Point(3, 3); this.chkAutoStartEnd.Name = "chkAutoStartEnd"; - this.chkAutoStartEnd.Size = new System.Drawing.Size(203, 17); + this.chkAutoStartEnd.Size = new System.Drawing.Size(117, 17); this.chkAutoStartEnd.TabIndex = 4; - this.chkAutoStartEnd.Text = "Start / Reset / End (Not yet working!)"; + this.chkAutoStartEnd.Text = "Start / Reset / End"; this.chkAutoStartEnd.UseVisualStyleBackColor = true; // // gbLoadRemoval @@ -134,6 +136,16 @@ private void InitializeComponent() this.chkDisplayWithoutLoads.Text = "Enable"; this.chkDisplayWithoutLoads.UseVisualStyleBackColor = true; // + // chkHelgen + // + this.chkHelgen.AutoSize = true; + this.chkHelgen.Location = new System.Drawing.Point(3, 26); + this.chkHelgen.Name = "chkHelgen"; + this.chkHelgen.Size = new System.Drawing.Size(60, 17); + this.chkHelgen.TabIndex = 5; + this.chkHelgen.Text = "Helgen"; + this.chkHelgen.UseVisualStyleBackColor = true; + // // SkyrimSettings // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -160,6 +172,7 @@ private void InitializeComponent() private System.Windows.Forms.GroupBox gbLoadRemoval; private System.Windows.Forms.TableLayoutPanel tlpLoadRemoval; private System.Windows.Forms.TableLayoutPanel tlpAutoSplit; - private System.Windows.Forms.CheckBox chkAutoStartEnd; + private System.Windows.Forms.CheckBox chkAutoStartEnd; + private System.Windows.Forms.CheckBox chkHelgen; } } diff --git a/SkyrimSettings.cs b/SkyrimSettings.cs index 6a2be9a..0e918c8 100644 --- a/SkyrimSettings.cs +++ b/SkyrimSettings.cs @@ -8,18 +8,21 @@ namespace LiveSplit.Skyrim public partial class SkyrimSettings : UserControl { public bool DrawWithoutLoads { get; set; } - public bool AutoStartEnd { get; set; } + public bool AutoStartEnd { get; set; } + public bool Helgen { get; set; } public SkyrimSettings() { InitializeComponent(); this.chkDisplayWithoutLoads.DataBindings.Add("Checked", this, "DrawWithoutLoads", false, DataSourceUpdateMode.OnPropertyChanged); - this.chkAutoStartEnd.DataBindings.Add("Checked", this, "AutoStartEnd", false, DataSourceUpdateMode.OnPropertyChanged); + this.chkAutoStartEnd.DataBindings.Add("Checked", this, "AutoStartEnd", false, DataSourceUpdateMode.OnPropertyChanged); + this.chkHelgen.DataBindings.Add("Checked", this, "Helgen", false, DataSourceUpdateMode.OnPropertyChanged); // defaults this.DrawWithoutLoads = true; - this.AutoStartEnd = true; + this.AutoStartEnd = true; + this.Helgen = false; } public XmlNode GetSettings(XmlDocument doc) @@ -29,7 +32,8 @@ public XmlNode GetSettings(XmlDocument doc) settingsNode.AppendChild(ToElement(doc, "Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(3))); settingsNode.AppendChild(ToElement(doc, "DrawWithoutLoads", this.DrawWithoutLoads)); - settingsNode.AppendChild(ToElement(doc, "AutoStartEnd", this.AutoStartEnd)); + settingsNode.AppendChild(ToElement(doc, "AutoStartEnd", this.AutoStartEnd)); + settingsNode.AppendChild(ToElement(doc, "Helgen", this.Helgen)); return settingsNode; } @@ -37,7 +41,8 @@ public XmlNode GetSettings(XmlDocument doc) public void SetSettings(XmlNode settings) { this.DrawWithoutLoads = ParseBool(settings, "DrawWithoutLoads", true); - this.AutoStartEnd = ParseBool(settings, "AutoStartEnd", true); + this.AutoStartEnd = ParseBool(settings, "AutoStartEnd", true); + this.Helgen = ParseBool(settings, "Helgen", true); } static bool ParseBool(XmlNode settings, string setting, bool default_ = false) diff --git a/TESV.CT b/TESV.CT index bea16a6..85879d6 100644 --- a/TESV.CT +++ b/TESV.CT @@ -4,7 +4,7 @@ 0 "isPaused" - + 80000008 Byte
"TESV.exe"+172E85F
@@ -12,7 +12,7 @@ 1 "isLoading" - + 80000008 Byte
"TESV.exe"+17337CC
@@ -20,7 +20,7 @@ 3 "isLoadscreen" - + 80000008 Byte
"TESV.exe"+EE3561
@@ -28,7 +28,7 @@ 4 "AreHandsTied?" - + 80000008 Byte
TESV.exe+172EE2C
@@ -36,7 +36,7 @@ 5 "IsInFadeOut" - + 80000008 Byte
TESV.exe+172EE2E
@@ -44,7 +44,7 @@ 12 "IsAlduinDead?" - + 80000008 Byte
TESV.exe+1711608
@@ -52,9 +52,9 @@ 9 "X world coord" - + 80000008 - 2 Bytes + 4 Bytes
"TESV.exe"+0172E864
64 @@ -63,9 +63,9 @@ 11 "Y world coord" - + 80000008 - 2 Bytes + 4 Bytes
"TESV.exe"+0172E864
68 @@ -74,7 +74,7 @@ 18 "isInTamriel" - + 80000008 Byte
TESV.exe+173815C
From 38bdaf5f0ce072c7c1fe06c1fa22cb003b54fa87 Mon Sep 17 00:00:00 2001 From: Dalet Date: Fri, 29 Aug 2014 01:33:55 +0200 Subject: [PATCH 08/16] minor code clean up --- GameMemory.cs | 7 +++++-- SkyrimComponent.cs | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/GameMemory.cs b/GameMemory.cs index 4fea8b8..fe67717 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -46,6 +46,11 @@ private enum ExpectedDllSizes } private bool[] splitStates = new bool[(int)SplitArea.AlduinDefeated + 1]; + + public void setSplitState(SplitArea split, bool value) + { + splitStates[(int)split] = value; + } public void resetSplitStates() { @@ -209,7 +214,6 @@ void MemoryReadThread() if (this.OnSplitCompleted != null) this.OnSplitCompleted(this, SplitArea.Helgen); }, null); - splitStates[(int)SplitArea.Helgen] = true; } } else @@ -276,7 +280,6 @@ void MemoryReadThread() if (this.OnSplitCompleted != null) this.OnSplitCompleted(this, SplitArea.AlduinDefeated); }, null); - splitStates[(int)SplitArea.AlduinDefeated] = true; } prevIsLoading = isLoading; diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index de22b79..699309f 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -127,7 +127,10 @@ void gameMemory_OnSplitCompleted(object sender, GameMemory.SplitArea split) { if ((split == GameMemory.SplitArea.Helgen && this.Settings.Helgen) || (split == GameMemory.SplitArea.AlduinDefeated && this.Settings.AutoStartEnd)) + { _timer.Split(); + _gameMemory.setSplitState(split, true); + } } public XmlNode GetSettings(XmlDocument document) From 52ae96def9e34824cfbc04e40bf0ecb6b7a5bfbd Mon Sep 17 00:00:00 2001 From: Dalet Date: Fri, 29 Aug 2014 15:32:49 +0200 Subject: [PATCH 09/16] Implemented the state.OnReset event to reset splitStates on manual resets. --- SkyrimComponent.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index 699309f..6a6cb2b 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -43,7 +43,8 @@ public SkyrimComponent(LiveSplitState state) _gameMemory.OnLoadFinished += gameMemory_OnLoadFinished; _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; - _gameMemory.OnSplitCompleted += gameMemory_OnSplitCompleted; + _gameMemory.OnSplitCompleted += gameMemory_OnSplitCompleted; + state.OnReset += state_OnReset; _gameMemory.StartMonitoring(); } @@ -53,11 +54,15 @@ public void Dispose() _gameMemory.Stop(); } + void state_OnReset(object sender, TimerPhase e) + { + _gameMemory.resetSplitStates(); + } + public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { if (!this.Settings.DrawWithoutLoads) return; - this.InternalComponent.TimeValue = state.CurrentTime[state.CurrentTimingMethod == TimingMethod.GameTime ? TimingMethod.RealTime : TimingMethod.GameTime]; @@ -71,6 +76,8 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width, invalidator.Invalidate(0f, 0f, width, height); } + + public void DrawVertical(Graphics g, LiveSplitState state, float width, Region region) { this.PrepareDraw(state); @@ -92,9 +99,9 @@ void PrepareDraw(LiveSplitState state) void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) { - _gameMemory.resetSplitStates(); - if (this.Settings.AutoStartEnd) - _timer.Reset(); + state_OnReset(this, _state.CurrentPhase); + if (this.Settings.AutoStartEnd) + _timer.Reset(); } void gameMemory_OnPlayerGainedControl(object sender, EventArgs e) From bbd842f4f2723980f89aba4f10b636e6fb22cdbc Mon Sep 17 00:00:00 2001 From: Dalet Date: Fri, 29 Aug 2014 15:41:42 +0200 Subject: [PATCH 10/16] removed an useless call of state.OnReset --- SkyrimComponent.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index 6a6cb2b..362a245 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -99,7 +99,6 @@ void PrepareDraw(LiveSplitState state) void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) { - state_OnReset(this, _state.CurrentPhase); if (this.Settings.AutoStartEnd) _timer.Reset(); } From 4da4e50711bda281819ea1833d52d8b5e379465c Mon Sep 17 00:00:00 2001 From: Dalet Date: Fri, 29 Aug 2014 17:00:26 +0200 Subject: [PATCH 11/16] Added writing to trace for start reset and splits --- GameMemory.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/GameMemory.cs b/GameMemory.cs index fe67717..6775186 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -209,6 +209,7 @@ void MemoryReadThread() if (!isInTamriel && world_X == -2 && world_Y == -5 && !splitStates[(int)SplitArea.Helgen]) { // Helgen split + Trace.WriteLine(String.Format("[NoLoads] Helgen Split - {0}", frameCounter)); _uiThread.Post(d => { if (this.OnSplitCompleted != null) @@ -247,6 +248,7 @@ void MemoryReadThread() if (!isInLoadScreenFadeOut && prevIsInLoadScreenFadeOut) { //reset + Trace.WriteLine(String.Format("[NoLoads] Reset - {0}", frameCounter)); _uiThread.Post(d => { if (this.OnFirstLevelLoading != null) @@ -254,6 +256,7 @@ void MemoryReadThread() }, null); //start + Trace.WriteLine(String.Format("[NoLoads] Start - {0}", frameCounter)); _uiThread.Post(d => { if (this.OnPlayerGainedControl != null) @@ -274,7 +277,8 @@ void MemoryReadThread() if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated && !splitStates[(int)SplitArea.AlduinDefeated] && !isInTamriel && ((world_X == 15 && world_Y == 19) || (world_X == 15 && world_Y == 20))) { - // split + // AlduinDefeated split + Trace.WriteLine(String.Format("[NoLoads] AlduinDefeated Split - {0}", frameCounter)); _uiThread.Post(d => { if (this.OnSplitCompleted != null) From 7e6cdb1aa32ffd4e72c2c180b22a9eeb17c3445c Mon Sep 17 00:00:00 2001 From: Ian Robinson Date: Fri, 29 Aug 2014 19:05:44 -0400 Subject: [PATCH 12/16] code cleanup --- .gitignore | 1 + GameMemory.cs | 279 ++++++++++++------------ LiveSplit.Skyrim.csproj | 158 +++++++------- SkyrimComponent.cs | 59 ++--- SkyrimSettings.Designer.cs | 270 +++++++++++------------ SkyrimSettings.cs | 10 +- SkyrimSettings.resx | 240 ++++++++++---------- TESV.CT => config/TESV.CT | 168 +++++++------- config/livesplit.skyrim.sublime-project | 19 ++ 9 files changed, 619 insertions(+), 585 deletions(-) create mode 100644 .gitignore rename TESV.CT => config/TESV.CT (97%) create mode 100644 config/livesplit.skyrim.sublime-project diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ab1b2e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.sublime-workspace diff --git a/GameMemory.cs b/GameMemory.cs index 6775186..bd67014 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -9,11 +9,11 @@ namespace LiveSplit.Skyrim { class GameMemory - { - public enum SplitArea : int - { - Helgen, - AlduinDefeated + { + public enum SplitArea : int + { + Helgen, + AlduinDefeated, } public event EventHandler OnFirstLevelLoading; @@ -21,8 +21,8 @@ public enum SplitArea : int public event EventHandler OnLoadStarted; public event EventHandler OnLoadFinished; public event EventHandler OnLoadScreenStarted; - public event EventHandler OnLoadScreenFinished; - public delegate void SplitCompletedEventHandler(object sender, SplitArea type); + public event EventHandler OnLoadScreenFinished; + public delegate void SplitCompletedEventHandler(object sender, SplitArea type); public event SplitCompletedEventHandler OnSplitCompleted; private Task _thread; @@ -31,50 +31,38 @@ public enum SplitArea : int private List _ignorePIDs; private DeepPointer _isLoadingPtr; - private DeepPointer _isLoadingScreenPtr; - private DeepPointer _isInLoadScreenFadeOutPtr; - private DeepPointer _isInTamriel; - private DeepPointer _world_XPtr; + private DeepPointer _isLoadingScreenPtr; + private DeepPointer _isInLoadScreenFadeOutPtr; + private DeepPointer _isInTamriel; + private DeepPointer _world_XPtr; private DeepPointer _world_YPtr; - private DeepPointer _isAlduinDefeatedPtr; - private DeepPointer _playerHasControlPtr; + private DeepPointer _isAlduinDefeatedPtr; private enum ExpectedDllSizes { SkyrimSteam = 27336704, SkyrimCracked = 26771456, - } - - private bool[] splitStates = new bool[(int)SplitArea.AlduinDefeated + 1]; - - public void setSplitState(SplitArea split, bool value) - { - splitStates[(int)split] = value; } - public void resetSplitStates() - { - for (int i = 0; i <= (int)SplitArea.AlduinDefeated; i++) - { - splitStates[i] = false; - } - } + private bool[] splitStates = new bool[(int)SplitArea.AlduinDefeated + 1]; public GameMemory() { - _isLoadingPtr = new DeepPointer("TESV.exe", 0x17337CC); // == 1 if a loading is happening (any except loading screens in Helgen for some reason) + // Loads + _isLoadingPtr = new DeepPointer("TESV.exe", 0x17337CC); // == 1 if a load is happening (any except loading screens in Helgen for some reason) _isLoadingScreenPtr = new DeepPointer("TESV.exe", 0xEE3561); // == 1 if in a loading screen - // _isPausedPtr = new DeepPointer("TESV.exe", 0x172E85F); // == 1 if in a menu or a loading screen - - _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained - - _isInTamriel = new DeepPointer("TESV.exe", 0x173815C); // == 1 if the player is in the Tamriel world space - _world_XPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x64); // X world position (cell) + // _isPausedPtr = new DeepPointer("TESV.exe", 0x172E85F); // == 1 if in a menu or a loading screen + _isInLoadScreenFadeOutPtr = new DeepPointer("TESV.exe", 0x172EE2E); // == 1 from the fade out of a loading, it goes back to 0 once control is gained + + // Position + _isInTamriel = new DeepPointer("TESV.exe", 0x173815C); // == 1 if the player is in the Tamriel world space + _world_XPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x64); // X world position (cell) _world_YPtr = new DeepPointer("TESV.exe", 0x0172E864, 0x68); // Y world position (cell) - _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x1711608); // == 1 when last blow is struck on alduin - _playerHasControlPtr = new DeepPointer("TESV.exe", 0x74814710); // == 1 when player has full control - + // Game state + _isAlduinDefeatedPtr = new DeepPointer("TESV.exe", 0x1711608); // == 1 when last blow is struck on alduin + // _playerHasControlPtr = new DeepPointer("TESV.exe", 0x74814710); // == 1 when player has full control + resetSplitStates(); _ignorePIDs = new List(); @@ -83,9 +71,13 @@ public GameMemory() public void StartMonitoring() { if (_thread != null && _thread.Status == TaskStatus.Running) + { throw new InvalidOperationException(); + } if (!(SynchronizationContext.Current is WindowsFormsSynchronizationContext)) + { throw new InvalidOperationException("SynchronizationContext.Current is not a UI thread."); + } _uiThread = SynchronizationContext.Current; _cancelSource = new CancellationTokenSource(); @@ -95,12 +87,27 @@ public void StartMonitoring() public void Stop() { if (_cancelSource == null || _thread == null || _thread.Status != TaskStatus.Running) + { return; + } _cancelSource.Cancel(); _thread.Wait(); } + public void setSplitState(SplitArea split, bool value) + { + splitStates[(int)split] = value; + } + + public void resetSplitStates() + { + for (int i = 0; i <= (int)SplitArea.AlduinDefeated; i++) + { + splitStates[i] = false; + } + } + void MemoryReadThread() { Trace.WriteLine("[NoLoads] MemoryReadThread"); @@ -116,7 +123,9 @@ void MemoryReadThread() { Thread.Sleep(250); if (_cancelSource.IsCancellationRequested) + { return; + } } Trace.WriteLine("[NoLoads] Got TESV.exe!"); @@ -125,9 +134,8 @@ void MemoryReadThread() bool prevIsLoading = false; bool prevIsLoadingScreen = false; - bool prevIsAlduinDefeated = false; - bool prevIsInLoadScreenFadeOut = false; - bool prevPlayerHasControl = false; + bool prevIsAlduinDefeated = false; + bool prevIsInLoadScreenFadeOut = false; bool loadingStarted = false; bool loadingScreenStarted = false; @@ -141,25 +149,24 @@ void MemoryReadThread() _isLoadingScreenPtr.Deref(game, out isLoadingScreen); if (isLoadingScreen) - isLoading = true; - - bool isInLoadScreenFadeOut; - _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); - - bool isInTamriel; - _isInTamriel.Deref(game, out isInTamriel); - - int world_X; - _world_XPtr.Deref(game, out world_X); - - int world_Y; + { + isLoading = true; + } + + bool isInLoadScreenFadeOut; + _isInLoadScreenFadeOutPtr.Deref(game, out isInLoadScreenFadeOut); + + bool isInTamriel; + _isInTamriel.Deref(game, out isInTamriel); + + int world_X; + _world_XPtr.Deref(game, out world_X); + + int world_Y; _world_YPtr.Deref(game, out world_Y); bool isAlduinDefeated; - _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); - - bool playerHasControl; - _playerHasControlPtr.Deref(game, out playerHasControl); + _isAlduinDefeatedPtr.Deref(game, out isAlduinDefeated); if (isLoading != prevIsLoading) { @@ -172,7 +179,9 @@ void MemoryReadThread() // pause game timer _uiThread.Post(d => { if (this.OnLoadStarted != null) + { this.OnLoadStarted(this, EventArgs.Empty); + } }, null); } else @@ -186,7 +195,9 @@ void MemoryReadThread() // unpause game timer _uiThread.Post(d => { if (this.OnLoadFinished != null) + { this.OnLoadFinished(this, EventArgs.Empty); + } }, null); } } @@ -200,21 +211,27 @@ void MemoryReadThread() loadingScreenStarted = true; - _uiThread.Post(d => - { - if (this.OnLoadScreenStarted != null) - this.OnLoadScreenStarted(this, EventArgs.Empty); - }, null); + // nothing currently + // _uiThread.Post(d => + // { + // if (this.OnLoadScreenStarted != null) + // { + // this.OnLoadScreenStarted(this, EventArgs.Empty); + // } + // }, null); + // if loadscreen starts while leaving helgen if (!isInTamriel && world_X == -2 && world_Y == -5 && !splitStates[(int)SplitArea.Helgen]) { - // Helgen split - Trace.WriteLine(String.Format("[NoLoads] Helgen Split - {0}", frameCounter)); - _uiThread.Post(d => - { - if (this.OnSplitCompleted != null) - this.OnSplitCompleted(this, SplitArea.Helgen); - }, null); + // Helgen split + Trace.WriteLine(String.Format("[NoLoads] Helgen Split - {0}", frameCounter)); + _uiThread.Post(d => + { + if (this.OnSplitCompleted != null) + { + this.OnSplitCompleted(this, SplitArea.Helgen); + } + }, null); } } else @@ -225,78 +242,72 @@ void MemoryReadThread() { loadingScreenStarted = false; - _uiThread.Post(d => - { - if (this.OnLoadScreenFinished != null) - this.OnLoadScreenFinished(this, EventArgs.Empty); - }, null); - - //if (!playerHasControl) - //{ - // _uiThread.Post(d => - // { - // if (this.OnFirstLevelLoading != null) - // this.OnFirstLevelLoading(this, EventArgs.Empty); - // }, null); - //} + // nothing currently + // _uiThread.Post(d => + // { + // if (this.OnLoadScreenFinished != null) + // { + // this.OnLoadScreenFinished(this, EventArgs.Empty); + // } + // }, null); } } - } - - if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut && isInTamriel && world_X == 3 && world_Y == -20) - { - if (!isInLoadScreenFadeOut && prevIsInLoadScreenFadeOut) - { - //reset - Trace.WriteLine(String.Format("[NoLoads] Reset - {0}", frameCounter)); - _uiThread.Post(d => - { - if (this.OnFirstLevelLoading != null) - this.OnFirstLevelLoading(this, EventArgs.Empty); - }, null); - - //start - Trace.WriteLine(String.Format("[NoLoads] Start - {0}", frameCounter)); - _uiThread.Post(d => - { - if (this.OnPlayerGainedControl != null) - this.OnPlayerGainedControl(this, EventArgs.Empty); - }, null); - } - } - - //if (playerHasControl != prevPlayerHasControl && playerHasControl && !isLoading) - //{ - // _uiThread.Post(d => - // { - // if (this.OnPlayerGainedControl != null) - // this.OnPlayerGainedControl(this, EventArgs.Empty); - // }, null); - //} - - if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated && !splitStates[(int)SplitArea.AlduinDefeated] - && !isInTamriel && ((world_X == 15 && world_Y == 19) || (world_X == 15 && world_Y == 20))) - { - // AlduinDefeated split - Trace.WriteLine(String.Format("[NoLoads] AlduinDefeated Split - {0}", frameCounter)); - _uiThread.Post(d => - { - if (this.OnSplitCompleted != null) - this.OnSplitCompleted(this, SplitArea.AlduinDefeated); - }, null); + } + + // if loadscreen fadeout finishes in helgen + if (isInLoadScreenFadeOut != prevIsInLoadScreenFadeOut && isInTamriel && world_X == 3 && world_Y == -20) + { + if (!isInLoadScreenFadeOut && prevIsInLoadScreenFadeOut) + { + // reset + Trace.WriteLine(String.Format("[NoLoads] Reset - {0}", frameCounter)); + _uiThread.Post(d => + { + if (this.OnFirstLevelLoading != null) + { + this.OnFirstLevelLoading(this, EventArgs.Empty); + } + }, null); + + // start + Trace.WriteLine(String.Format("[NoLoads] Start - {0}", frameCounter)); + _uiThread.Post(d => + { + if (this.OnPlayerGainedControl != null) + { + this.OnPlayerGainedControl(this, EventArgs.Empty); + } + }, null); + } + } + + // if alduin is defeated in sovngarde + if (isAlduinDefeated != prevIsAlduinDefeated && isAlduinDefeated && !splitStates[(int)SplitArea.AlduinDefeated] + && !isInTamriel && ((world_X == 15 && world_Y == 19) || (world_X == 15 && world_Y == 20))) + { + // AlduinDefeated split + Trace.WriteLine(String.Format("[NoLoads] AlduinDefeated Split - {0}", frameCounter)); + _uiThread.Post(d => + { + if (this.OnSplitCompleted != null) + { + this.OnSplitCompleted(this, SplitArea.AlduinDefeated); + } + }, null); } prevIsLoading = isLoading; prevIsLoadingScreen = isLoadingScreen; - prevIsAlduinDefeated = isAlduinDefeated; - prevIsInLoadScreenFadeOut = isInLoadScreenFadeOut; - prevPlayerHasControl = playerHasControl; + prevIsAlduinDefeated = isAlduinDefeated; + prevIsInLoadScreenFadeOut = isInLoadScreenFadeOut; frameCounter++; Thread.Sleep(15); if (_cancelSource.IsCancellationRequested) + { return; + } } } catch (Exception ex) @@ -312,25 +323,19 @@ Process GetGameProcess() Process game = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.ToLower() == "tesv" && !p.HasExited && !_ignorePIDs.Contains(p.Id)); if (game == null) + { return null; + } if (game.MainModule.ModuleMemorySize != (int)ExpectedDllSizes.SkyrimSteam && game.MainModule.ModuleMemorySize != (int)ExpectedDllSizes.SkyrimCracked) { _ignorePIDs.Add(game.Id); _uiThread.Send(d => MessageBox.Show("Unexpected game version. Skyrim 1.9.32.0.8 is required.", "LiveSplit.Skyrim", - MessageBoxButtons.OK, MessageBoxIcon.Error), null); + MessageBoxButtons.OK, MessageBoxIcon.Error), null); return null; } return game; } - - // string GetEngineStringByID(Process p, int id) - // { - // string str; - // var ptr = new DeepPointer(_stringBase, (id*4), 0x10); - // ptr.Deref(p, out str, 32); - // return str; - // } } } diff --git a/LiveSplit.Skyrim.csproj b/LiveSplit.Skyrim.csproj index 5e2aa6b..a589f87 100644 --- a/LiveSplit.Skyrim.csproj +++ b/LiveSplit.Skyrim.csproj @@ -1,79 +1,79 @@ - - - - - Debug - AnyCPU - {21223220-7A12-4C57-9AC4-BA4277FF4220} - Library - Properties - LiveSplit.Skyrim - LiveSplit.Skyrim - v4.0 - 512 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - C:\Apps\LiveSplit 1.4\LiveSplit.Core.dll - False - - - - - - - - - C:\Apps\LiveSplit 1.4\UpdateManager.dll - False - - - - - - - - UserControl - - - SkyrimSettings.cs - - - - - - - - SkyrimSettings.cs - - - - - - - - - + + + + + Debug + AnyCPU + {21223220-7A12-4C57-9AC4-BA4277FF4220} + Library + Properties + LiveSplit.Skyrim + LiveSplit.Skyrim + v4.0 + 512 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + C:\Apps\LiveSplit 1.4\LiveSplit.Core.dll + False + + + + + + + + + C:\Apps\LiveSplit 1.4\UpdateManager.dll + False + + + + + + + + UserControl + + + SkyrimSettings.cs + + + + + + + + SkyrimSettings.cs + + + + + + + + + diff --git a/SkyrimComponent.cs b/SkyrimComponent.cs index 362a245..08f8172 100644 --- a/SkyrimComponent.cs +++ b/SkyrimComponent.cs @@ -41,9 +41,9 @@ public SkyrimComponent(LiveSplitState state) _gameMemory.OnPlayerGainedControl += gameMemory_OnPlayerGainedControl; _gameMemory.OnLoadStarted += gameMemory_OnLoadStarted; _gameMemory.OnLoadFinished += gameMemory_OnLoadFinished; - _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; - _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; - _gameMemory.OnSplitCompleted += gameMemory_OnSplitCompleted; + // _gameMemory.OnLoadScreenStarted += gameMemory_OnLoadScreenStarted; + // _gameMemory.OnLoadScreenFinished += gameMemory_OnLoadScreenFinished; + _gameMemory.OnSplitCompleted += gameMemory_OnSplitCompleted; state.OnReset += state_OnReset; _gameMemory.StartMonitoring(); } @@ -51,18 +51,23 @@ public SkyrimComponent(LiveSplitState state) public void Dispose() { if (_gameMemory != null) + { _gameMemory.Stop(); + } } - void state_OnReset(object sender, TimerPhase e) - { - _gameMemory.resetSplitStates(); + void state_OnReset(object sender, TimerPhase e) + { + _gameMemory.resetSplitStates(); } public void Update(IInvalidator invalidator, LiveSplitState state, float width, float height, LayoutMode mode) { if (!this.Settings.DrawWithoutLoads) + { return; + } + this.InternalComponent.TimeValue = state.CurrentTime[state.CurrentTimingMethod == TimingMethod.GameTime ? TimingMethod.RealTime : TimingMethod.GameTime]; @@ -73,11 +78,11 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width, _cache["TimeValue"] = this.InternalComponent.ValueLabel.Text; _cache["TimingMethod"] = state.CurrentTimingMethod; if (invalidator != null && _cache.HasChanged) + { invalidator.Invalidate(0f, 0f, width, height); + } } - - public void DrawVertical(Graphics g, LiveSplitState state, float width, Region region) { this.PrepareDraw(state); @@ -98,15 +103,19 @@ void PrepareDraw(LiveSplitState state) } void gameMemory_OnFirstLevelLoading(object sender, EventArgs e) - { + { if (this.Settings.AutoStartEnd) + { _timer.Reset(); + } } void gameMemory_OnPlayerGainedControl(object sender, EventArgs e) { if (this.Settings.AutoStartEnd) + { _timer.Start(); + } } void gameMemory_OnLoadStarted(object sender, EventArgs e) @@ -119,24 +128,24 @@ void gameMemory_OnLoadFinished(object sender, EventArgs e) _state.IsGameTimePaused = false; } - void gameMemory_OnLoadScreenStarted(object sender, EventArgs e) - { - // TODO - } + // void gameMemory_OnLoadScreenStarted(object sender, EventArgs e) + // { + // // Nothing to do + // } + + // void gameMemory_OnLoadScreenFinished(object sender, EventArgs e) + // { + // // Nothing to do + // } - void gameMemory_OnLoadScreenFinished(object sender, EventArgs e) + void gameMemory_OnSplitCompleted(object sender, GameMemory.SplitArea split) { - // TODO - } - - void gameMemory_OnSplitCompleted(object sender, GameMemory.SplitArea split) - { - if ((split == GameMemory.SplitArea.Helgen && this.Settings.Helgen) - || (split == GameMemory.SplitArea.AlduinDefeated && this.Settings.AutoStartEnd)) - { - _timer.Split(); - _gameMemory.setSplitState(split, true); - } + if ((split == GameMemory.SplitArea.Helgen && this.Settings.Helgen) || + (split == GameMemory.SplitArea.AlduinDefeated && this.Settings.AutoStartEnd)) + { + _timer.Split(); + _gameMemory.setSplitState(split, true); + } } public XmlNode GetSettings(XmlDocument document) diff --git a/SkyrimSettings.Designer.cs b/SkyrimSettings.Designer.cs index 290457b..ce5ed72 100644 --- a/SkyrimSettings.Designer.cs +++ b/SkyrimSettings.Designer.cs @@ -28,140 +28,140 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.tlpMain = new System.Windows.Forms.TableLayoutPanel(); - this.gbAutoSplit = new System.Windows.Forms.GroupBox(); - this.tlpAutoSplit = new System.Windows.Forms.TableLayoutPanel(); - this.chkAutoStartEnd = new System.Windows.Forms.CheckBox(); - this.gbLoadRemoval = new System.Windows.Forms.GroupBox(); - this.tlpLoadRemoval = new System.Windows.Forms.TableLayoutPanel(); - this.chkDisplayWithoutLoads = new System.Windows.Forms.CheckBox(); - this.chkHelgen = new System.Windows.Forms.CheckBox(); - this.tlpMain.SuspendLayout(); - this.gbAutoSplit.SuspendLayout(); - this.tlpAutoSplit.SuspendLayout(); - this.gbLoadRemoval.SuspendLayout(); - this.tlpLoadRemoval.SuspendLayout(); - this.SuspendLayout(); - // - // tlpMain - // - this.tlpMain.ColumnCount = 1; - this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tlpMain.Controls.Add(this.gbAutoSplit, 1, 0); - this.tlpMain.Controls.Add(this.gbLoadRemoval, 0, 1); - this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill; - this.tlpMain.Location = new System.Drawing.Point(0, 0); - this.tlpMain.Name = "tlpMain"; - this.tlpMain.RowCount = 2; - this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 75F)); - this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); - this.tlpMain.Size = new System.Drawing.Size(476, 226); - this.tlpMain.TabIndex = 0; - // - // gbAutoSplit - // - this.gbAutoSplit.Controls.Add(this.tlpAutoSplit); - this.gbAutoSplit.Dock = System.Windows.Forms.DockStyle.Fill; - this.gbAutoSplit.Location = new System.Drawing.Point(3, 3); - this.gbAutoSplit.Name = "gbAutoSplit"; - this.gbAutoSplit.Size = new System.Drawing.Size(470, 163); - this.gbAutoSplit.TabIndex = 5; - this.gbAutoSplit.TabStop = false; - this.gbAutoSplit.Text = "Auto-Split"; - // - // tlpAutoSplit - // - this.tlpAutoSplit.ColumnCount = 1; - this.tlpAutoSplit.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tlpAutoSplit.Controls.Add(this.chkHelgen, 0, 5); - this.tlpAutoSplit.Controls.Add(this.chkAutoStartEnd, 0, 0); - this.tlpAutoSplit.Dock = System.Windows.Forms.DockStyle.Fill; - this.tlpAutoSplit.Location = new System.Drawing.Point(3, 16); - this.tlpAutoSplit.Name = "tlpAutoSplit"; - this.tlpAutoSplit.RowCount = 6; - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpAutoSplit.Size = new System.Drawing.Size(464, 144); - this.tlpAutoSplit.TabIndex = 0; - // - // chkAutoStartEnd - // - this.chkAutoStartEnd.AutoSize = true; - this.chkAutoStartEnd.Checked = true; - this.chkAutoStartEnd.CheckState = System.Windows.Forms.CheckState.Checked; - this.chkAutoStartEnd.Location = new System.Drawing.Point(3, 3); - this.chkAutoStartEnd.Name = "chkAutoStartEnd"; - this.chkAutoStartEnd.Size = new System.Drawing.Size(117, 17); - this.chkAutoStartEnd.TabIndex = 4; - this.chkAutoStartEnd.Text = "Start / Reset / End"; - this.chkAutoStartEnd.UseVisualStyleBackColor = true; - // - // gbLoadRemoval - // - this.gbLoadRemoval.Controls.Add(this.tlpLoadRemoval); - this.gbLoadRemoval.Dock = System.Windows.Forms.DockStyle.Fill; - this.gbLoadRemoval.Location = new System.Drawing.Point(3, 172); - this.gbLoadRemoval.Name = "gbLoadRemoval"; - this.gbLoadRemoval.Size = new System.Drawing.Size(470, 51); - this.gbLoadRemoval.TabIndex = 6; - this.gbLoadRemoval.TabStop = false; - this.gbLoadRemoval.Text = "Show Alternate Timing Time"; - // - // tlpLoadRemoval - // - this.tlpLoadRemoval.ColumnCount = 1; - this.tlpLoadRemoval.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tlpLoadRemoval.Controls.Add(this.chkDisplayWithoutLoads, 0, 0); - this.tlpLoadRemoval.Dock = System.Windows.Forms.DockStyle.Fill; - this.tlpLoadRemoval.Location = new System.Drawing.Point(3, 16); - this.tlpLoadRemoval.Name = "tlpLoadRemoval"; - this.tlpLoadRemoval.RowCount = 1; - this.tlpLoadRemoval.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpLoadRemoval.Size = new System.Drawing.Size(464, 32); - this.tlpLoadRemoval.TabIndex = 0; - // - // chkDisplayWithoutLoads - // - this.chkDisplayWithoutLoads.AutoSize = true; - this.chkDisplayWithoutLoads.Checked = true; - this.chkDisplayWithoutLoads.CheckState = System.Windows.Forms.CheckState.Checked; - this.chkDisplayWithoutLoads.Location = new System.Drawing.Point(3, 3); - this.chkDisplayWithoutLoads.Name = "chkDisplayWithoutLoads"; - this.chkDisplayWithoutLoads.Size = new System.Drawing.Size(59, 17); - this.chkDisplayWithoutLoads.TabIndex = 0; - this.chkDisplayWithoutLoads.Text = "Enable"; - this.chkDisplayWithoutLoads.UseVisualStyleBackColor = true; - // - // chkHelgen - // - this.chkHelgen.AutoSize = true; - this.chkHelgen.Location = new System.Drawing.Point(3, 26); - this.chkHelgen.Name = "chkHelgen"; - this.chkHelgen.Size = new System.Drawing.Size(60, 17); - this.chkHelgen.TabIndex = 5; - this.chkHelgen.Text = "Helgen"; - this.chkHelgen.UseVisualStyleBackColor = true; - // - // SkyrimSettings - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.tlpMain); - this.Name = "SkyrimSettings"; - this.Size = new System.Drawing.Size(476, 226); - this.tlpMain.ResumeLayout(false); - this.gbAutoSplit.ResumeLayout(false); - this.tlpAutoSplit.ResumeLayout(false); - this.tlpAutoSplit.PerformLayout(); - this.gbLoadRemoval.ResumeLayout(false); - this.tlpLoadRemoval.ResumeLayout(false); - this.tlpLoadRemoval.PerformLayout(); - this.ResumeLayout(false); - + this.tlpMain = new System.Windows.Forms.TableLayoutPanel(); + this.gbAutoSplit = new System.Windows.Forms.GroupBox(); + this.tlpAutoSplit = new System.Windows.Forms.TableLayoutPanel(); + this.chkAutoStartEnd = new System.Windows.Forms.CheckBox(); + this.gbLoadRemoval = new System.Windows.Forms.GroupBox(); + this.tlpLoadRemoval = new System.Windows.Forms.TableLayoutPanel(); + this.chkDisplayWithoutLoads = new System.Windows.Forms.CheckBox(); + this.chkHelgen = new System.Windows.Forms.CheckBox(); + this.tlpMain.SuspendLayout(); + this.gbAutoSplit.SuspendLayout(); + this.tlpAutoSplit.SuspendLayout(); + this.gbLoadRemoval.SuspendLayout(); + this.tlpLoadRemoval.SuspendLayout(); + this.SuspendLayout(); + // + // tlpMain + // + this.tlpMain.ColumnCount = 1; + this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpMain.Controls.Add(this.gbAutoSplit, 1, 0); + this.tlpMain.Controls.Add(this.gbLoadRemoval, 0, 1); + this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpMain.Location = new System.Drawing.Point(0, 0); + this.tlpMain.Name = "tlpMain"; + this.tlpMain.RowCount = 2; + this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 75F)); + this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tlpMain.Size = new System.Drawing.Size(476, 226); + this.tlpMain.TabIndex = 0; + // + // gbAutoSplit + // + this.gbAutoSplit.Controls.Add(this.tlpAutoSplit); + this.gbAutoSplit.Dock = System.Windows.Forms.DockStyle.Fill; + this.gbAutoSplit.Location = new System.Drawing.Point(3, 3); + this.gbAutoSplit.Name = "gbAutoSplit"; + this.gbAutoSplit.Size = new System.Drawing.Size(470, 163); + this.gbAutoSplit.TabIndex = 5; + this.gbAutoSplit.TabStop = false; + this.gbAutoSplit.Text = "Auto-Split"; + // + // tlpAutoSplit + // + this.tlpAutoSplit.ColumnCount = 1; + this.tlpAutoSplit.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpAutoSplit.Controls.Add(this.chkHelgen, 0, 5); + this.tlpAutoSplit.Controls.Add(this.chkAutoStartEnd, 0, 0); + this.tlpAutoSplit.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpAutoSplit.Location = new System.Drawing.Point(3, 16); + this.tlpAutoSplit.Name = "tlpAutoSplit"; + this.tlpAutoSplit.RowCount = 6; + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpAutoSplit.Size = new System.Drawing.Size(464, 144); + this.tlpAutoSplit.TabIndex = 0; + // + // chkAutoStartEnd + // + this.chkAutoStartEnd.AutoSize = true; + this.chkAutoStartEnd.Checked = true; + this.chkAutoStartEnd.CheckState = System.Windows.Forms.CheckState.Checked; + this.chkAutoStartEnd.Location = new System.Drawing.Point(3, 3); + this.chkAutoStartEnd.Name = "chkAutoStartEnd"; + this.chkAutoStartEnd.Size = new System.Drawing.Size(117, 17); + this.chkAutoStartEnd.TabIndex = 4; + this.chkAutoStartEnd.Text = "Start / Reset / End"; + this.chkAutoStartEnd.UseVisualStyleBackColor = true; + // + // gbLoadRemoval + // + this.gbLoadRemoval.Controls.Add(this.tlpLoadRemoval); + this.gbLoadRemoval.Dock = System.Windows.Forms.DockStyle.Fill; + this.gbLoadRemoval.Location = new System.Drawing.Point(3, 172); + this.gbLoadRemoval.Name = "gbLoadRemoval"; + this.gbLoadRemoval.Size = new System.Drawing.Size(470, 51); + this.gbLoadRemoval.TabIndex = 6; + this.gbLoadRemoval.TabStop = false; + this.gbLoadRemoval.Text = "Show Alternate Timing Time"; + // + // tlpLoadRemoval + // + this.tlpLoadRemoval.ColumnCount = 1; + this.tlpLoadRemoval.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tlpLoadRemoval.Controls.Add(this.chkDisplayWithoutLoads, 0, 0); + this.tlpLoadRemoval.Dock = System.Windows.Forms.DockStyle.Fill; + this.tlpLoadRemoval.Location = new System.Drawing.Point(3, 16); + this.tlpLoadRemoval.Name = "tlpLoadRemoval"; + this.tlpLoadRemoval.RowCount = 1; + this.tlpLoadRemoval.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tlpLoadRemoval.Size = new System.Drawing.Size(464, 32); + this.tlpLoadRemoval.TabIndex = 0; + // + // chkDisplayWithoutLoads + // + this.chkDisplayWithoutLoads.AutoSize = true; + this.chkDisplayWithoutLoads.Checked = true; + this.chkDisplayWithoutLoads.CheckState = System.Windows.Forms.CheckState.Checked; + this.chkDisplayWithoutLoads.Location = new System.Drawing.Point(3, 3); + this.chkDisplayWithoutLoads.Name = "chkDisplayWithoutLoads"; + this.chkDisplayWithoutLoads.Size = new System.Drawing.Size(59, 17); + this.chkDisplayWithoutLoads.TabIndex = 0; + this.chkDisplayWithoutLoads.Text = "Enable"; + this.chkDisplayWithoutLoads.UseVisualStyleBackColor = true; + // + // chkHelgen + // + this.chkHelgen.AutoSize = true; + this.chkHelgen.Location = new System.Drawing.Point(3, 26); + this.chkHelgen.Name = "chkHelgen"; + this.chkHelgen.Size = new System.Drawing.Size(60, 17); + this.chkHelgen.TabIndex = 5; + this.chkHelgen.Text = "Helgen"; + this.chkHelgen.UseVisualStyleBackColor = true; + // + // SkyrimSettings + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tlpMain); + this.Name = "SkyrimSettings"; + this.Size = new System.Drawing.Size(476, 226); + this.tlpMain.ResumeLayout(false); + this.gbAutoSplit.ResumeLayout(false); + this.tlpAutoSplit.ResumeLayout(false); + this.tlpAutoSplit.PerformLayout(); + this.gbLoadRemoval.ResumeLayout(false); + this.tlpLoadRemoval.ResumeLayout(false); + this.tlpLoadRemoval.PerformLayout(); + this.ResumeLayout(false); + } #endregion @@ -172,7 +172,7 @@ private void InitializeComponent() private System.Windows.Forms.GroupBox gbLoadRemoval; private System.Windows.Forms.TableLayoutPanel tlpLoadRemoval; private System.Windows.Forms.TableLayoutPanel tlpAutoSplit; - private System.Windows.Forms.CheckBox chkAutoStartEnd; + private System.Windows.Forms.CheckBox chkAutoStartEnd; private System.Windows.Forms.CheckBox chkHelgen; } } diff --git a/SkyrimSettings.cs b/SkyrimSettings.cs index 0e918c8..08e6048 100644 --- a/SkyrimSettings.cs +++ b/SkyrimSettings.cs @@ -8,7 +8,7 @@ namespace LiveSplit.Skyrim public partial class SkyrimSettings : UserControl { public bool DrawWithoutLoads { get; set; } - public bool AutoStartEnd { get; set; } + public bool AutoStartEnd { get; set; } public bool Helgen { get; set; } public SkyrimSettings() @@ -16,12 +16,12 @@ public SkyrimSettings() InitializeComponent(); this.chkDisplayWithoutLoads.DataBindings.Add("Checked", this, "DrawWithoutLoads", false, DataSourceUpdateMode.OnPropertyChanged); - this.chkAutoStartEnd.DataBindings.Add("Checked", this, "AutoStartEnd", false, DataSourceUpdateMode.OnPropertyChanged); + this.chkAutoStartEnd.DataBindings.Add("Checked", this, "AutoStartEnd", false, DataSourceUpdateMode.OnPropertyChanged); this.chkHelgen.DataBindings.Add("Checked", this, "Helgen", false, DataSourceUpdateMode.OnPropertyChanged); // defaults this.DrawWithoutLoads = true; - this.AutoStartEnd = true; + this.AutoStartEnd = true; this.Helgen = false; } @@ -32,7 +32,7 @@ public XmlNode GetSettings(XmlDocument doc) settingsNode.AppendChild(ToElement(doc, "Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(3))); settingsNode.AppendChild(ToElement(doc, "DrawWithoutLoads", this.DrawWithoutLoads)); - settingsNode.AppendChild(ToElement(doc, "AutoStartEnd", this.AutoStartEnd)); + settingsNode.AppendChild(ToElement(doc, "AutoStartEnd", this.AutoStartEnd)); settingsNode.AppendChild(ToElement(doc, "Helgen", this.Helgen)); return settingsNode; @@ -41,7 +41,7 @@ public XmlNode GetSettings(XmlDocument doc) public void SetSettings(XmlNode settings) { this.DrawWithoutLoads = ParseBool(settings, "DrawWithoutLoads", true); - this.AutoStartEnd = ParseBool(settings, "AutoStartEnd", true); + this.AutoStartEnd = ParseBool(settings, "AutoStartEnd", true); this.Helgen = ParseBool(settings, "Helgen", true); } diff --git a/SkyrimSettings.resx b/SkyrimSettings.resx index 29dcb1b..58a9e20 100644 --- a/SkyrimSettings.resx +++ b/SkyrimSettings.resx @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/TESV.CT b/config/TESV.CT similarity index 97% rename from TESV.CT rename to config/TESV.CT index 85879d6..d0462fb 100644 --- a/TESV.CT +++ b/config/TESV.CT @@ -1,84 +1,84 @@ - - - - - 0 - "isPaused" - - 80000008 - Byte -
"TESV.exe"+172E85F
-
- - 1 - "isLoading" - - 80000008 - Byte -
"TESV.exe"+17337CC
-
- - 3 - "isLoadscreen" - - 80000008 - Byte -
"TESV.exe"+EE3561
-
- - 4 - "AreHandsTied?" - - 80000008 - Byte -
TESV.exe+172EE2C
-
- - 5 - "IsInFadeOut" - - 80000008 - Byte -
TESV.exe+172EE2E
-
- - 12 - "IsAlduinDead?" - - 80000008 - Byte -
TESV.exe+1711608
-
- - 9 - "X world coord" - - 80000008 - 4 Bytes -
"TESV.exe"+0172E864
- - 64 - -
- - 11 - "Y world coord" - - 80000008 - 4 Bytes -
"TESV.exe"+0172E864
- - 68 - -
- - 18 - "isInTamriel" - - 80000008 - Byte -
TESV.exe+173815C
-
-
- -
+ + + + + 0 + "isPaused" + + 80000008 + Byte +
"TESV.exe"+172E85F
+
+ + 1 + "isLoading" + + 80000008 + Byte +
"TESV.exe"+17337CC
+
+ + 3 + "isLoadscreen" + + 80000008 + Byte +
"TESV.exe"+EE3561
+
+ + 4 + "AreHandsTied?" + + 80000008 + Byte +
TESV.exe+172EE2C
+
+ + 5 + "IsInFadeOut" + + 80000008 + Byte +
TESV.exe+172EE2E
+
+ + 12 + "IsAlduinDead?" + + 80000008 + Byte +
TESV.exe+1711608
+
+ + 9 + "X world coord" + + 80000008 + 4 Bytes +
"TESV.exe"+0172E864
+ + 64 + +
+ + 11 + "Y world coord" + + 80000008 + 4 Bytes +
"TESV.exe"+0172E864
+ + 68 + +
+ + 18 + "isInTamriel" + + 80000008 + Byte +
TESV.exe+173815C
+
+
+ +
diff --git a/config/livesplit.skyrim.sublime-project b/config/livesplit.skyrim.sublime-project new file mode 100644 index 0000000..a9ec7d2 --- /dev/null +++ b/config/livesplit.skyrim.sublime-project @@ -0,0 +1,19 @@ +{ + "folders": + [ + { + "follow_symlinks": true, + "path": "../" + } + ], + "settings": + { + "tab_size": 4, + "rulers": [79], + "translate_tabs_to_spaces": true, + "ensure_newline_at_eof_on_save": true, + "trim_trailing_white_space_on_save": true, + "default_encoding": "UTF-8", + "default_line_ending": "unix" + } +} From f55f50ad6c346f9c7af2edc1d7c61d94409e55db Mon Sep 17 00:00:00 2001 From: Ian Robinson Date: Fri, 29 Aug 2014 19:09:49 -0400 Subject: [PATCH 13/16] update readme --- readme.txt | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/readme.txt b/readme.txt index 5404c57..94dfbf9 100644 --- a/readme.txt +++ b/readme.txt @@ -6,8 +6,7 @@ Features: Frame-accurate load time removal. - (Coming soon: Automatic reset, start, and split. Automatic splitting can - be done on mission end screens as well as at a few other common places.) + Automatic reset, start, and splits on Helgen and the final Alduin fight. Requirements: @@ -16,28 +15,24 @@ Requirements: Install: - Drop the LiveSplit.Skyrim.dll into LiveSplit's Components directory. - Add Skyrim to your layout. - Switch to the no loads timer by going to Compare Against -> Game Time. - - (Soon: Enter "The Elder Scrolls V: Skyrim" in LiveSplit's splits editor. - Click activate.) + Enter "The Elder Scrolls V: Skyrim" in LiveSplit's splits editor. + Click activate. + Open settings to enable / disable autosplitting. Source Code: https://github.com/drtchops/LiveSplit.Skyrim -Plugin code credit goes to: -@fatalis_ -twitch.tv/fatalis_ -Fatalis @ irc2.speedrunslive.com IRC -fatalis.twitch@gmail.com - -With original Skyrim compatibility by: +Skyrim compatibility by: Dalleth twitch.tv/dalleth_ - -1.4 Update by: +& DrTChops twitch.tv/drtchops + +Original Dishonored plugin by: +@fatalis_ +twitch.tv/fatalis_ +Fatalis @ irc2.speedrunslive.com IRC +fatalis.twitch@gmail.com From 3af266baf266c27ba3aa7de540e36a2bda6dc6d6 Mon Sep 17 00:00:00 2001 From: drtchops Date: Sat, 30 Aug 2014 01:57:09 -0400 Subject: [PATCH 14/16] 1.3 Update --- Components/LiveSplit.Skyrim.dll | Bin 25600 -> 28160 bytes Components/update.LiveSplit.Skyrim.xml | 10 ++ GameMemory.cs | 4 +- LiveSplit.Skyrim.csproj | 146 ++++++++++++------------- Properties/AssemblyInfo.cs | 4 +- readme.txt | 38 ------- 6 files changed, 87 insertions(+), 115 deletions(-) delete mode 100644 readme.txt diff --git a/Components/LiveSplit.Skyrim.dll b/Components/LiveSplit.Skyrim.dll index 9704c55136f70770a6bc0486f40938918a5a786c..f2f3a8de8d7b3c752f4fde1e913d4c7af389c7a6 100644 GIT binary patch literal 28160 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 diff --git a/Components/update.LiveSplit.Skyrim.xml b/Components/update.LiveSplit.Skyrim.xml index 2e6296e..410739e 100644 --- a/Components/update.LiveSplit.Skyrim.xml +++ b/Components/update.LiveSplit.Skyrim.xml @@ -1,4 +1,14 @@ + + + + + + + Added automatic reset / start / end and Helgen split. + + + diff --git a/GameMemory.cs b/GameMemory.cs index bd67014..50b4fcd 100644 --- a/GameMemory.cs +++ b/GameMemory.cs @@ -20,8 +20,8 @@ public enum SplitArea : int public event EventHandler OnPlayerGainedControl; public event EventHandler OnLoadStarted; public event EventHandler OnLoadFinished; - public event EventHandler OnLoadScreenStarted; - public event EventHandler OnLoadScreenFinished; + // public event EventHandler OnLoadScreenStarted; + // public event EventHandler OnLoadScreenFinished; public delegate void SplitCompletedEventHandler(object sender, SplitArea type); public event SplitCompletedEventHandler OnSplitCompleted; diff --git a/LiveSplit.Skyrim.csproj b/LiveSplit.Skyrim.csproj index a589f87..4d9d295 100644 --- a/LiveSplit.Skyrim.csproj +++ b/LiveSplit.Skyrim.csproj @@ -1,79 +1,79 @@ - - - - - Debug - AnyCPU - {21223220-7A12-4C57-9AC4-BA4277FF4220} - Library - Properties - LiveSplit.Skyrim - LiveSplit.Skyrim - v4.0 - 512 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - C:\Apps\LiveSplit 1.4\LiveSplit.Core.dll - False - - - - - - - - - C:\Apps\LiveSplit 1.4\UpdateManager.dll - False - - - - - - - - UserControl - - - SkyrimSettings.cs - - - - - - - - SkyrimSettings.cs - - - - - - - + + + + + Debug + AnyCPU + {21223220-7A12-4C57-9AC4-BA4277FF4220} + Library + Properties + LiveSplit.Skyrim + LiveSplit.Skyrim + v4.0 + 512 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + C:\Apps\LiveSplit 1.4\LiveSplit.Core.dll + False + + + + + + + + + C:\Apps\LiveSplit 1.4\UpdateManager.dll + False + + + + + + + + UserControl + + + SkyrimSettings.cs + + + + + + + + SkyrimSettings.cs + + + + + + + - + --> + \ No newline at end of file diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 9bc85d3..b7869b1 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] [assembly: ComponentFactory(typeof(SkyrimFactory))] diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 94dfbf9..0000000 --- a/readme.txt +++ /dev/null @@ -1,38 +0,0 @@ -This is a LiveSplit (livesplit.org) component for Skyrim. It removes load times -automatically and automates splitting. It is based on Fatalis' component for -Dishonored. - -Features: - - Frame-accurate load time removal. - - Automatic reset, start, and splits on Helgen and the final Alduin fight. - -Requirements: - - Skyrim (PC - latest) - LiveSplit 1.4+ - -Install: - - Enter "The Elder Scrolls V: Skyrim" in LiveSplit's splits editor. - Click activate. - Open settings to enable / disable autosplitting. - -Source Code: - - https://github.com/drtchops/LiveSplit.Skyrim - - -Skyrim compatibility by: -Dalleth -twitch.tv/dalleth_ -& -DrTChops -twitch.tv/drtchops - -Original Dishonored plugin by: -@fatalis_ -twitch.tv/fatalis_ -Fatalis @ irc2.speedrunslive.com IRC -fatalis.twitch@gmail.com From cf18d2fe92b6e276bc8448c616387e18aad969da Mon Sep 17 00:00:00 2001 From: drtchops Date: Sat, 30 Aug 2014 02:02:21 -0400 Subject: [PATCH 15/16] Rename doesn't add files =/ --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..94b06e6 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +LiveSplit.Skyrim v1.3 +===================== + +LiveSplit.Skyrim is a [LiveSplit] component for The Elder Scrolls V: Skyrim. + +Features +-------- + * Keeps track of Game Time to get rid of loading times. + * Auto start/stop/reset the timer. + * Splits when you finish Helgen and default Alduin 2. (configurable) + +Install +------- +Starting with LiveSplit 1.4, you can download and install LiveSplit.Skyrim automatically from within the Splits Editor with just one click. Just type in "The Elder Scrolls V: Skyrim" and click Activate. This downloads LiveSplit.Skyrim to the Components folder. + +Configure +--------- +Due to bugs in LiveSplit 1.4.0, it's recommended to deactivate LiveSplit.Skyrim in the Splits Editor after activating (downloading) it the first time. Instead, you should activate it in the Layout Editor, under the "Control" category. Double-click "Skyrim" after adding it to your layout to bring up the settings. + +After configuring everything you'll most likely want to turn on game time as primary timing, so that your splits will run off game time. You can do this by right-clicking LiveSplit and going to Compare Against->Game Time. + +#### Auto Split +The default settings are to automatically reset, start, and end the splits (the first and last splits). You can enable Helgen autosplitting here. + +#### Alternate Timing Method +This makes it show Real Time when comparing against Game Time, and vice versa. Doesn't work when LiveSplit.Skyrim is activated via the Splits Editor. + +Change Log +---------- +https://github.com/drtchops/LiveSplit.Skyrim/releases + +Credits +------- + * [DrTChops] + * [Dalleth] + * Plugin is based off [LiveSplit.Dishonored] by [Fatalis]. + + +[LiveSplit]:http://livesplit.org/ +[DrTChops]:http://twitch.tv/drtchops +[Dalleth]:http://twitch.tv/dalleth_ +[LiveSplit.Dishonored]:https://github.com/fatalis/LiveSplit.Dishonored +[Fatalis]:http://twitch.tv/fatalis_ From 1295fbb1307dd9b6fc438b183552f190092d4674 Mon Sep 17 00:00:00 2001 From: drtchops Date: Sat, 30 Aug 2014 02:06:16 -0400 Subject: [PATCH 16/16] How to markdown --- README.md | 73 +++++++++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 94b06e6..e1a98c6 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,36 @@ LiveSplit.Skyrim v1.3 ===================== -LiveSplit.Skyrim is a [LiveSplit] component for The Elder Scrolls V: Skyrim. - -Features --------- - * Keeps track of Game Time to get rid of loading times. - * Auto start/stop/reset the timer. - * Splits when you finish Helgen and default Alduin 2. (configurable) - -Install -------- -Starting with LiveSplit 1.4, you can download and install LiveSplit.Skyrim automatically from within the Splits Editor with just one click. Just type in "The Elder Scrolls V: Skyrim" and click Activate. This downloads LiveSplit.Skyrim to the Components folder. - -Configure ---------- -Due to bugs in LiveSplit 1.4.0, it's recommended to deactivate LiveSplit.Skyrim in the Splits Editor after activating (downloading) it the first time. Instead, you should activate it in the Layout Editor, under the "Control" category. Double-click "Skyrim" after adding it to your layout to bring up the settings. - -After configuring everything you'll most likely want to turn on game time as primary timing, so that your splits will run off game time. You can do this by right-clicking LiveSplit and going to Compare Against->Game Time. - -#### Auto Split -The default settings are to automatically reset, start, and end the splits (the first and last splits). You can enable Helgen autosplitting here. - -#### Alternate Timing Method -This makes it show Real Time when comparing against Game Time, and vice versa. Doesn't work when LiveSplit.Skyrim is activated via the Splits Editor. - -Change Log ----------- -https://github.com/drtchops/LiveSplit.Skyrim/releases - -Credits -------- - * [DrTChops] - * [Dalleth] - * Plugin is based off [LiveSplit.Dishonored] by [Fatalis]. - - -[LiveSplit]:http://livesplit.org/ -[DrTChops]:http://twitch.tv/drtchops -[Dalleth]:http://twitch.tv/dalleth_ -[LiveSplit.Dishonored]:https://github.com/fatalis/LiveSplit.Dishonored -[Fatalis]:http://twitch.tv/fatalis_ +LiveSplit.Skyrim is a [LiveSplit](http://livesplit.org/) component for The Elder Scrolls V: Skyrim. + +Features +-------- + * Keeps track of Game Time to get rid of loading times. + * Auto start/stop/reset the timer. + * Splits when you finish Helgen and default Alduin 2. (configurable) + +Install +------- +Starting with LiveSplit 1.4, you can download and install LiveSplit.Skyrim automatically from within the Splits Editor with just one click. Just type in "The Elder Scrolls V: Skyrim" and click Activate. This downloads LiveSplit.Skyrim to the Components folder. + +Configure +--------- +Due to bugs in LiveSplit 1.4.0, it's recommended to deactivate LiveSplit.Skyrim in the Splits Editor after activating (downloading) it the first time. Instead, you should activate it in the Layout Editor, under the "Control" category. Double-click "Skyrim" after adding it to your layout to bring up the settings. + +After configuring everything you'll most likely want to turn on game time as primary timing, so that your splits will run off game time. You can do this by right-clicking LiveSplit and going to Compare Against->Game Time. + +#### Auto Split +The default settings are to automatically reset, start, and end the splits (the first and last splits). You can enable Helgen autosplitting here. + +#### Alternate Timing Method +This makes it show Real Time when comparing against Game Time, and vice versa. Doesn't work when LiveSplit.Skyrim is activated via the Splits Editor. + +Change Log +---------- +https://github.com/drtchops/LiveSplit.Skyrim/releases + +Credits +------- + * [DrTChops](http://twitch.tv/drtchops) + * [Dalleth](http://twitch.tv/dalleth_) + * Plugin is based off [LiveSplit.Dishonored](https://github.com/fatalis/LiveSplit.Dishonored) by [Fatalis](http://twitch.tv/fatalis_).