Skip to content

Commit

Permalink
[COM3D2] Add Free mode support (closes #166)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sauceke committed Jun 4, 2024
1 parent fb6258d commit fe066c3
Showing 1 changed file with 39 additions and 8 deletions.
47 changes: 39 additions & 8 deletions src/LoveMachine.COM3D2/Com3d2Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ internal sealed class Com3d2Game : GameAdapter
{
private const string SpineF = "Bip01/Bip01 Spine/Bip01 Spine0a/Bip01 Spine1/Bip01 Spine1a";
private const string PelvisF = "Bip01/Bip01 Pelvis";
private const string FallbackPoseName = "???";

private readonly string[] idlePoseNames = { "taiki", "nade", "shaseigo" };
private readonly string[] idlePoseNames = { "taiki", "nade", "shaseigo", FallbackPoseName };
private readonly string[] climaxPoseNames = { "shasei_", "zeccyou_" };

private TimeUnlooper unlooper;
Expand Down Expand Up @@ -47,10 +48,20 @@ internal sealed class Com3d2Game : GameAdapter
protected override int AnimationLayer => throw new NotImplementedException();

protected override MethodInfo[] StartHMethods =>
new[] { AccessTools.Method("YotogiPlayManager, Assembly-CSharp:UIStartup") };
new[]
{
AccessTools.Method("YotogiPlayManager, Assembly-CSharp:UIStartup"),
AccessTools.Method("SceneFreeModeSelectManager, Assembly-CSharp:CallScenePlayMainStory"),
AccessTools.Method("SceneFreeModeSelectManager, Assembly-CSharp:CallScenePlayEveryday"),
AccessTools.Method("SceneFreeModeSelectManager, Assembly-CSharp:CallScenePlayVip")
};

protected override MethodInfo[] EndHMethods =>
new[] { AccessTools.Method("YotogiPlayManager, Assembly-CSharp:OnClickNext") };
new[]
{
AccessTools.Method("YotogiPlayManager, Assembly-CSharp:OnClickNext"),
AccessTools.Method("FreeModeInit, Assembly-CSharp:OnFinish")
};

protected override IEnumerator WaitAfterPoseChange()
{
Expand All @@ -64,19 +75,26 @@ protected override void GetAnimState(int girlIndex, out float normalizedTime,
out float length, out float speed)
{
var state = GetActiveState();
if (state == null)
{
normalizedTime = 0;
length = 1;
speed = 1;
return;
}
normalizedTime = unlooper.LoopingToMonotonic(state.normalizedTime);
length = state.length;
speed = state.speed;
}

private AnimationState GetActiveState() => player
private AnimationState GetActiveState() => player?
.GetComponentsInChildren<Animation>()
.SelectMany(animation => animation.Cast<AnimationState>()
.Where(state => animation.IsPlaying(state.name)))
.OrderBy(state => state.length)
.ThenBy(state => state.name)
.FirstOrDefault();

protected override GameObject GetFemaleRoot(int girlIndex) =>
FindCharaObject($"Maid[{girlIndex}]");

Expand All @@ -90,7 +108,8 @@ private static GameObject FindCharaObject(string pattern) =>
.FirstOrDefault()?
.gameObject;

protected override string GetPose(int girlIndex) => GetActiveState()?.name;
protected override string GetPose(int girlIndex) =>
GetActiveState()?.name ?? FallbackPoseName;

protected override bool IsIdle(int girlIndex) =>
idlePoseNames.Any(GetPose(girlIndex).Contains);
Expand All @@ -100,9 +119,21 @@ protected override bool IsOrgasming(int girlIndex) =>

protected override IEnumerator UntilReady(object instance)
{
yield return new WaitForSeconds(5f);
unlooper = new TimeUnlooper();
player = FindCharaObject("Man[0]");
HandleCoroutine(SeekPlayer());
yield return null;
}

private IEnumerator SeekPlayer()
{
while (true)
{
yield return new WaitForSeconds(5f);
if (player == null || !player.activeInHierarchy)
{
player = FindCharaObject("Man[0]");
}
}
}
}
}

0 comments on commit fe066c3

Please sign in to comment.