Skip to content

Commit

Permalink
fix(wrong split): prevent autosplitting all splits if a previous save…
Browse files Browse the repository at this point in the history
… was loaded
  • Loading branch information
vorban committed Nov 5, 2022
1 parent d991732 commit 17082d4
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 34 deletions.
11 changes: 11 additions & 0 deletions Livesplit.Salt/Components/LiveSplit.Salt.Updates.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<updates>
<update version="0.1.0">
<files>
<file path="Components/LiveSplit.Salt.dll" status="changed"/>
</files>
<changelog>
<change>
Restarting the game is no longer needed between runs. Condition checking for splits starts after
the game properly loads the character (after the intro text).
</change>
</changelog>
</update>
<update version="0.0.5">
<files>
<file path="Components/LiveSplit.Salt.dll" status="changed"/>
Expand Down
Binary file modified Livesplit.Salt/Components/LiveSplit.Salt.dll
Binary file not shown.
4 changes: 2 additions & 2 deletions Livesplit.Salt/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("7ca19d1e-048e-4883-8526-90fde279573b")]
[assembly: AssemblyVersion("0.0.5")]
[assembly: AssemblyFileVersion("0.0.5")]
[assembly: AssemblyVersion("0.1.0")]
[assembly: AssemblyFileVersion("0.1.0")]
[assembly: ComponentFactory(typeof(SaltFactory))]
55 changes: 48 additions & 7 deletions Livesplit.Salt/SaltComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ public class SaltComponent : IComponent
};

private readonly TimerModel _model;
public readonly SaltMemory _mem;
private readonly SaltMemory _mem;
private readonly Settings _settings = new Settings();

private readonly Dictionary<string, InvLoot> _bossItems = new Dictionary<string, InvLoot>();
private readonly List<EnemyHealthTracker> _enemyTrackers = new List<EnemyHealthTracker>();

private bool _playerRandomized;
private bool _playerOfNewRunLoaded;

public string ComponentName { get; }

Expand All @@ -64,6 +65,9 @@ public SaltComponent(LiveSplitState state, string name)
CurrentState = state
};

_model.CurrentState.OnStart -= SetPlayerOfNewRunLoaded;
_model.CurrentState.OnStart += SetPlayerOfNewRunLoaded;

_model.CurrentState.OnStart -= TimerStart;
_model.CurrentState.OnStart += TimerStart;

Expand All @@ -82,23 +86,30 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width,
_mem.Hook();
if (!_mem.IsHooked)
{
Console.WriteLine("----- Not Hooked yet -----");
return;
}

Console.WriteLine("Split: " + _model.CurrentState.CurrentSplitIndex);

if (_model.CurrentState.CurrentSplitIndex == -1)
{
CheckStart();
return;
}

if (_mem.GetGameState() != GameState.Playing)
//! The GameState is not stored at the same address anymore.
//! I now use a different approach to check for the loaded player.
//if (_mem.GetGameState() != GameState.Playing)
//{
// return;
//}

//! This is the new way of checking for the loaded player. Explanation:
if (!_playerOfNewRunLoaded)
{
//return;
CheckPlayerOfNewRunLoaded();
return;
}


//! This is executed on run start + on each split
if (_settings.RandomizeSkins && !_playerRandomized)
{
_mem.RandomizePlayerAppearance(0);
Expand Down Expand Up @@ -138,6 +149,31 @@ private void CheckStart()
}
}

private void CheckPlayerOfNewRunLoaded()
{
// When the game is launched, after the "do not shutdown when you see this icon" screen,
// it loads a default player (with animation "fly"). If you load a NG+ save,
// and then go back to the menu, your character is still loaded as the current player.
// If you then start a new game (thus beginning a new run), the autosplitter would start the timer
// because a fade to black transition happens, and then scan for the player's inventory (new boss item = split).
// But during the fade to black, the new character isn't loaded yet, and with the latter example,
// your NG+ character which is still in memory would trigger all the splits in 0.0s.

// As of 2022-11-05, I don't have the knowledge nor the resources to figure out the memory address of the
// game state (menu / loading / playing).
// My solution is simple: When a character is loaded, it has the "prayout" animation (the one when you exit the
// level up menu). It is the case when you start a new game, and when you load a save.

// So, when we start a run, we set _playerOfNewRunLoaded to false.
// Then, when we detect the prayout animation, we set the bool to true.
// While the bool is false, split checks are disabled (both inventory, game ending, and boss kill).

if (_mem.GetPlayerAnim(0) == "prayout" && !_playerOfNewRunLoaded)
{
_playerOfNewRunLoaded = true;
}
}

private void CheckItemSplits()
{
Console.WriteLine("Checking items");
Expand Down Expand Up @@ -193,6 +229,11 @@ private void SetPlayerNeedsRandomized(object sender, EventArgs e)
_playerRandomized = false;
}

private void SetPlayerOfNewRunLoaded(object sender, EventArgs e)
{
_playerOfNewRunLoaded = false;
}

public Control GetSettingsControl(LayoutMode mode)
{
return _settings;
Expand Down
42 changes: 26 additions & 16 deletions Livesplit.Salt/Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,37 @@ public static class Test
{
public static void Main()
{
var state = new Model.LiveSplitState(new Model.Run(new Model.Comparisons.StandardComparisonGeneratorsFactory()), null, null, null, null);
var state = new Model.LiveSplitState(
new Model.Run(new Model.Comparisons.StandardComparisonGeneratorsFactory()),
null, null, null, null);
using SaltComponent comp = new SaltComponent(state, "mine");


while (true)
{
Thread.Sleep(500);
//while (true)
//{
// Thread.Sleep(500);

//mem.UpdateInventory(0);
comp.Update(null, state, 0, 0, UI.LayoutMode.Horizontal);
//foreach (int i in mem._playerItems.Keys)
//{
// Console.WriteLine("ITEM " + i + "(" + mem._playerItems[i].Count + ")");
// foreach (string s in mem._playerItems[i].Keys)
// {
// var item = mem._playerItems[i][s];
// Console.WriteLine("===== New scan =====");
// comp._mem.Hook();
// if (!comp._mem.IsHooked)
// {
// Console.WriteLine("----- Not Hooked yet -----");
// continue;
// }

// Console.WriteLine("\t- " + s + " (" + item.count + ")");
// }
//}
}
// if (comp._mem.GetPlayerCount() == 0)
// {
// Console.WriteLine("----- 0 players -----");
// continue;
// }

// var player = comp._mem.GetPlayer(0);
// Console.WriteLine("Scanning player " + 0 + " (" + player + ")");

// comp._mem.UpdateInventory(0);
// Console.WriteLine("- Animation: " + comp._mem.GetPlayerAnim(0));
// Console.WriteLine("- Inventory: " + comp._mem._playerItems[0].Keys.Count);
//}
}
}
}
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The original autosplitter did not work anymore. This is my attempt to fix it.
- [Features](#features)
- [Ideas that may or may not see the light](#ideas-that-may-or-may-not-see-the-light)
- [Known issues](#known-issues)
- [The run auto-starts, but doesn't autosplit](#the-run-auto-starts-but-doesnt-autosplit)
- [When starting a new run, it autosplits until the last split.](#when-starting-a-new-run-it-autosplits-until-the-last-split)

## Installation
Expand Down Expand Up @@ -41,14 +42,9 @@ Reopen Livesplit and it should be available.

## Known issues

### When starting a new run, it autosplits until the last split.
### The run auto-starts, but doesn't autosplit

**What happens**: If you start a run, then reset (or finish), and start a new one,
there is a period of time when you start the new game, during which the
game keeps track of the previous character you played.
The autosplitter acknowledges the beginning of the new run and autostarts,
and at the same time it reads all the boss items in the inventory, and splits
accordingly.
This has been fixed in 0.0.6. Make sure your autosplitter is up-to-date.
### When starting a new run, it autosplits until the last split.

**Fix**: Restarting Livesplit and/or the game seems to do the trick.
A patch is in progress for this issue.
This has been fixed in 0.1.0. Make sure your autosplitter is up-to-date.

0 comments on commit 17082d4

Please sign in to comment.