Skip to content

Commit c54c481

Browse files
committed
Southermost Combine support, additions and fixes
- Added support for Southernmost Combine. - Fixed a problem with storing current / old player states upon map load leading to potential premature Auto-starts. - Allowed variable precision on the Higher Precision Timer. - Fixed Game Process List Default button not working. - Added a description field for the various Timing Method options. - Modified the Custom Command handler to use binary exports for console printing functions. - Changed Death% split in Portal to only happen on the first map. - Fixed the default value for TSP's No Space Ending Custom Command.
1 parent 75016a4 commit c54c481

17 files changed

+632
-291
lines changed

GameMemory.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1010,10 +1010,10 @@ void UpdateGameState(GameState state)
10101010
// if it's the first tick, don't use stuff from the previous map
10111011
if (firstTick)
10121012
{
1013-
state.PlayerFlags.Current = state.PlayerFlags.Old;
1014-
state.PlayerPosition.Current = state.PlayerPosition.Old;
1015-
state.PlayerViewEntityIndex.Current = state.PlayerViewEntityIndex.Old;
1016-
state.PlayerParentEntityHandle.Current = state.PlayerParentEntityHandle.Old;
1013+
state.PlayerFlags.Current = state.PlayerFlags.Current;
1014+
state.PlayerPosition.Current = state.PlayerPosition.Current;
1015+
state.PlayerViewEntityIndex.Current = state.PlayerViewEntityIndex.Current;
1016+
state.PlayerParentEntityHandle.Current = state.PlayerParentEntityHandle.Current;
10171017
}
10181018
}
10191019
} // if (state.SignOnState.Current == SignOnState.Full)

GameSpecific/GameSupport.cs

+8-3
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ protected AutoStart AutoStartType
8989

9090
protected bool IsFirstMap { get; private set; }
9191
protected bool IsLastMap { get; private set; }
92-
92+
internal bool _mapsLowercase = false;
9393

9494
private bool _onceFlag;
9595

@@ -116,8 +116,10 @@ public virtual void OnSessionStart(GameState state)
116116
{
117117
_onceFlag = false;
118118

119-
this.IsFirstMap = FirstMap.Contains(state.CurrentMap);
120-
this.IsLastMap = LastMap.Contains(state.CurrentMap);
119+
string map = _mapsLowercase ? state.CurrentMap.ToLower() : state.CurrentMap;
120+
121+
this.IsFirstMap = FirstMap.Contains(map);
122+
this.IsLastMap = LastMap.Contains(map);
121123
}
122124

123125
// called when player no longer fully in the game (map changed, load started)
@@ -397,6 +399,9 @@ public static GameSupport FromGameDir(string gameDir)
397399
return new HL2Mods_DangerousWorld();
398400
case "se1":
399401
return new SiNEpisodes();
402+
case "southernmost":
403+
case "southernmostcombine":
404+
return new HL2Mods_SouthernmostCombine();
400405
}
401406

402407
return null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Diagnostics;
3+
4+
namespace LiveSplit.SourceSplit.GameSpecific
5+
{
6+
class HL2Mods_SouthernmostCombine : GameSupport
7+
{
8+
// start: when intro text entity is killed
9+
// ending: when the trigger for alyx to do her wake up animation is hit
10+
11+
private bool _onceFlag;
12+
13+
private int _startCamIndex;
14+
15+
private int _endCamIndex;
16+
17+
public HL2Mods_SouthernmostCombine()
18+
{
19+
this.GameTimingMethod = GameTimingMethod.EngineTicksWithPauses;
20+
this.AddFirstMap("smc_town01");
21+
this.AddLastMap("smc_powerplant03");
22+
this.RequiredProperties = PlayerProperties.ViewEntity;
23+
this._mapsLowercase = true;
24+
}
25+
26+
public override void OnSessionStart(GameState state)
27+
{
28+
base.OnSessionStart(state);
29+
if (this.IsFirstMap)
30+
{
31+
this._startCamIndex = state.GetEntIndexByName("cam");
32+
Debug.WriteLine("start camera index is " + this._startCamIndex);
33+
}
34+
35+
if (this.IsLastMap)
36+
{
37+
_endCamIndex = state.GetEntIndexByName("view_gman");
38+
Debug.WriteLine("ending camera index is " + this._endCamIndex);
39+
}
40+
41+
_onceFlag = false;
42+
}
43+
44+
45+
public override GameSupportResult OnUpdate(GameState state)
46+
{
47+
if (_onceFlag)
48+
return GameSupportResult.DoNothing;
49+
50+
if (IsFirstMap)
51+
{
52+
if (state.PlayerViewEntityIndex.ChangedFromTo(_startCamIndex, 1))
53+
{
54+
Debug.WriteLine("southernmost combine start");
55+
_onceFlag = true;
56+
return GameSupportResult.PlayerGainedControl;
57+
}
58+
}
59+
else if (IsLastMap)
60+
{
61+
if (state.PlayerViewEntityIndex.ChangedFromTo(1, _endCamIndex))
62+
{
63+
Debug.WriteLine("southernmost combine end");
64+
_onceFlag = true;
65+
return GameSupportResult.PlayerLostControl;
66+
}
67+
}
68+
return GameSupportResult.DoNothing;
69+
}
70+
}
71+
}

GameSpecific/Portal.cs

+10-9
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Portal : GameSupport
2525

2626
private CustomCommand _newStart = new CustomCommand("newstart", "0", "Start the timer upon portal open");
2727
private CustomCommand _elevSplit = new CustomCommand("elevsplit", "0", "Split when the elevator starts moving (limited)");
28-
private CustomCommand _deathSplit = new CustomCommand("death%", "0", "Death% ending");
28+
private CustomCommand _deathSplit = new CustomCommand("deathsplit", "0", "Death category extension ending");
2929
private CustomCommandHandler _ccHandler;
3030

3131
public Portal()
@@ -105,20 +105,21 @@ public override GameSupportResult OnUpdate(GameState state)
105105
finally { _elevSplitTime = splitTime; }
106106
}
107107

108-
if (_deathSplit.BValue)
109-
{
110-
if (_playerHP.Old > 0 && _playerHP.Current <= 0)
111-
{
112-
Debug.WriteLine("Death% end");
113-
return GameSupportResult.ManualSplit;
114-
}
115-
}
116108

117109
if (_onceFlag)
118110
return GameSupportResult.DoNothing;
119111

120112
if (IsFirstMap)
121113
{
114+
if (_deathSplit.BValue)
115+
{
116+
if (_playerHP.Old > 0 && _playerHP.Current <= 0)
117+
{
118+
Debug.WriteLine("Death% end");
119+
return GameSupportResult.ManualSplit;
120+
}
121+
}
122+
122123
bool isInside = state.PlayerPosition.Current.InsideBox(-636, -452, -412, -228, 383, 158);
123124

124125
if (_newStart.BValue)

GameSpecific/TheStanleyParable.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using LiveSplit.SourceSplit.Extensions;
33
using System;
44
using System.Diagnostics;
5+
using System.IO;
56
using System.Linq;
67
using System.Text;
78

@@ -121,7 +122,7 @@ class TheStanleyParable : GameSupport
121122
private MemoryWatcher<Vector3f> _modEndingMuseumPodPos;
122123
private Vector3f _modEndingApartmentSectorOrigin = new Vector3f(-3524f, 1368f, -620f);
123124

124-
private CustomCommand _noSpaceEnd = new CustomCommand("nospaceend", "Disable splitting on Space Ending");
125+
private CustomCommand _noSpaceEnd = new CustomCommand("nospaceend", "0", "Disable splitting on Space Ending");
125126
private CustomCommandHandler _ccHandler;
126127

127128
public TheStanleyParable()
@@ -202,6 +203,7 @@ public override void OnGameAttached(GameState state)
202203
{
203204
_ccHandler.Init(state);
204205

206+
205207
server = state.GetModule("server.dll");
206208
client = state.GetModule("client.dll");
207209
engine = state.GetModule("engine.dll");
@@ -242,6 +244,8 @@ public override void OnGenericUpdate(GameState state)
242244
{
243245
if (state.CurrentMap.ToString() == "map" && state.HostState.Current == HostState.GameShutdown)
244246
this.OnUpdate(state);
247+
248+
_ccHandler.Update(state);
245249
}
246250

247251
public override void OnSessionStart(GameState state)
@@ -333,8 +337,6 @@ public override GameSupportResult OnUpdate(GameState state)
333337
{
334338
_endingsWatcher.UpdateAll(state.GameProcess);
335339

336-
_ccHandler.Update(state);
337-
338340
if (_onceFlag)
339341
return GameSupportResult.DoNothing;
340342

LiveSplit.SourceSplit.csproj

+5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
</ItemGroup>
5757
<ItemGroup>
5858
<Compile Include="Extensions\Detour.cs" />
59+
<Compile Include="GameSpecific\HL2Mods\HL2Mods_SouthernmostCombine.cs" />
5960
<Compile Include="Utils\CustomCommand.cs" />
6061
<Compile Include="Extensions\NumericsExtensions.cs" />
6162
<Compile Include="Extensions\SignatureScannerExtensions.cs" />
@@ -166,6 +167,10 @@
166167
<None Include="license.txt" />
167168
<None Include="README.md" />
168169
</ItemGroup>
170+
<ItemGroup>
171+
<Content Include="update\update.xml" />
172+
</ItemGroup>
173+
<ItemGroup />
169174
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
170175
<PropertyGroup>
171176
<PostBuildEvent>if exist "$(ProjectDir)\update\Components\$(TargetFileName)\$(TargetPath)" del "$(ProjectDir)\update\$(TargetFileName)\$(TargetPath)"

Properties/AssemblyInfo.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
// You can specify all the values or you can default the Build and Revision Numbers
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
34-
[assembly: AssemblyVersion("3.2.0.1")]
35-
[assembly: AssemblyFileVersion("3.2.0.1")]
34+
[assembly: AssemblyVersion("3.2.1")]
35+
[assembly: AssemblyFileVersion("3.2.1")]

SourceSplitComponent.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ public void Update(IInvalidator invalidator, LiveSplitState state, float width,
255255
if (Settings.ShowAltTime)
256256
method = (TimingMethod)(((int)method + 1) % 2);
257257

258-
this.AltTimingComponent.SetText(state.CurrentTime[method]);
258+
this.AltTimingComponent.SetText(state.CurrentTime[method], Settings.GameTimeDecimalPlaces);
259259
this.AltTimingComponent.SetName(method == TimingMethod.RealTime ? "Real Time" : "Game Time");
260260

261261
_cache["TimeValue"] = this.AltTimingComponent.Component.ValueLabel.Text;

SourceSplitFactory.cs

+43-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using LiveSplit.UI.Components;
66
using System;
77
using LiveSplit.Model;
8+
using System.Linq;
89

910
[assembly: ComponentFactory(typeof(SourceSplitFactory))]
1011

@@ -25,18 +26,52 @@ public IComponent Create(LiveSplitState state)
2526
bool createAsLayoutComponent = (caller == "LoadLayoutComponent" || caller == "AddComponent");
2627

2728
// if component is already loaded somewhere else
29+
// layout editor takes precedent because its just better & i can't figure out how to unload
30+
// components from layout editor >:(
2831
if (_instance != null && !_instance.Disposed)
2932
{
30-
MessageBox.Show(
31-
"SourceSplit is already loaded in the " +
32-
(_instance.IsLayoutComponent ? "Layout Editor" : "Splits Editor") + "!",
33-
"SourceSplit Error",
34-
MessageBoxButtons.OK,
35-
MessageBoxIcon.Exclamation);
36-
37-
throw new Exception("Component already loaded.");
33+
void unloadSplitsInstance(bool fromLayout)
34+
{
35+
string msg = (fromLayout) ?
36+
"Deactivated SourceSplit from Splits Editor!" :
37+
"Cannot activate SourceSplit when it is already loaded in the Layout Editor!";
38+
39+
string source = fromLayout ?
40+
"Layout Editor" :
41+
"Splits Editor";
42+
43+
MessageBox.Show(msg, $"SourceSplit Warning | {source}", MessageBoxButtons.OK, MessageBoxIcon.Warning);
44+
Debug.WriteLine("unload splits instance");
45+
state.Run.AutoSplitter.Component?.Dispose();
46+
state.Run.AutoSplitter.Deactivate();
47+
state.Settings.ActiveAutoSplitters.Remove(state.Run.GameName);
48+
}
49+
50+
if (createAsLayoutComponent)
51+
{
52+
if (!_instance.IsLayoutComponent)
53+
unloadSplitsInstance(true);
54+
else
55+
throw new Exception($"Component already loaded");
56+
}
57+
else
58+
{
59+
if (_instance.IsLayoutComponent)
60+
{
61+
unloadSplitsInstance(false);
62+
return null;
63+
}
64+
else
65+
_instance.Dispose();
66+
}
3867
}
3968

69+
/*
70+
// if component is already loaded somewhere else
71+
if (_instance != null && !_instance.Disposed)
72+
throw new Exception($">:( )\n(Component already loaded in the {(_instance.IsLayoutComponent ? "Layout Editor" : "Splits Editor")}");
73+
*/
74+
4075
return (_instance = new SourceSplitComponent(state, createAsLayoutComponent));
4176
}
4277

0 commit comments

Comments
 (0)