Skip to content

Commit

Permalink
KK POV improvements (#23)
Browse files Browse the repository at this point in the history
* Fixed POV not working properly in KK story mode H; Hide character head when entering POV

* [KK] Added Hide character head setting; also adjusted default values of fov and offset

* [KK] Remember original camera position and when entering pov set initial camera rotation to current character head rotation

* [KK] Don't enter male pov in H scenes without male involvement

* KK POV ver up to 1.1
  • Loading branch information
ManlyMarco committed Mar 2, 2021
1 parent ab28ad3 commit 07214c6
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 30 deletions.
7 changes: 5 additions & 2 deletions src/RealPOV.Core/RealPOVCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ public abstract class RealPOVCore : BaseUnityPlugin
private static float backupFOV;
private static float backupNearClip;

protected static float defaultViewOffset = 0.03f;
protected static float defaultFov = 70f;

protected virtual void Awake()
{
Logger = base.Logger;

POVHotkey = Config.Bind(SECTION_HOTKEYS, "Toggle POV", new KeyboardShortcut(KeyCode.Backspace));
DefaultFOV = Config.Bind(SECTION_GENERAL, "Default FOV", 70f, new ConfigDescription("", new AcceptableValueRange<float>(20f, 120f)));
DefaultFOV = Config.Bind(SECTION_GENERAL, "Default FOV", defaultFov, new ConfigDescription("", new AcceptableValueRange<float>(20f, 120f)));
MouseSens = Config.Bind(SECTION_GENERAL, "Mouse sensitivity", 1f, new ConfigDescription("", new AcceptableValueRange<float>(0.1f, 2f)));
ViewOffset = Config.Bind(SECTION_GENERAL, "View offset", 0.03f);
ViewOffset = Config.Bind(SECTION_GENERAL, "View offset", defaultViewOffset);
}

private void Update()
Expand Down
88 changes: 60 additions & 28 deletions src/RealPOV.Koikatu/RealPOV.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Studio;
using System.Collections.Generic;
using System.Linq;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.SceneManagement;

Expand All @@ -14,68 +15,93 @@ namespace RealPOV.Koikatu
[BepInPlugin(GUID, PluginName, Version)]
public class RealPOV : RealPOVCore
{
public const string Version = "1.0.4." + BuildNumber.Version;
public const string Version = "1.1.0." + BuildNumber.Version;

internal ConfigEntry<bool> HideHead { get; set; }

private static int backupLayer;
private static ChaControl currentChara;
private static Queue<ChaControl> charaQueue;
private bool isStudio = Paths.ProcessName == "CharaStudio";
private readonly bool isStudio = Paths.ProcessName == "CharaStudio";
private bool prevVisibleHeadAlways;
private HFlag hFlag;

protected override void Awake()
{
defaultFov = 90;
defaultViewOffset = 0.001f;
base.Awake();

HideHead = Config.Bind(SECTION_GENERAL, "Hide character head", true, "Whene entering POV, hide the character's head. Prevents accessories and hair from obstructing the view.");

Harmony.CreateAndPatchAll(GetType());

SceneManager.activeSceneChanged += (arg0, scene) => charaQueue = null;
SceneManager.sceneLoaded += (arg0, scene) =>
{
hFlag = FindObjectOfType<HFlag>();
charaQueue = null;
};
SceneManager.sceneUnloaded += arg0 => charaQueue = null;
}

internal override void EnablePOV()
{

if(isStudio)
if (isStudio)
{
var selectedCharas = GuideObjectManager.Instance.selectObjectKey.Select(x => Studio.Studio.GetCtrlInfo(x) as OCIChar).Where(x => x != null).ToList();
if(selectedCharas.Count > 0)
if (selectedCharas.Count > 0)
currentChara = selectedCharas.First().charInfo;
else
Logger.LogMessage("Select a character in workspace to enter its POV");
}
else
{
void CreateQueue()
Queue<ChaControl> CreateQueue()
{
charaQueue = new Queue<ChaControl>();
foreach (ChaControl chara in FindObjectsOfType<ChaControl>())
charaQueue.Enqueue(chara);
if (charaQueue.Count > 0)
return new Queue<ChaControl>(FindObjectsOfType<ChaControl>());
}
ChaControl GetCurrentChara()
{
for (int i = 0; i < charaQueue.Count; i++)
{
currentChara = charaQueue.Dequeue();
charaQueue.Enqueue(currentChara);
var chaControl = charaQueue.Dequeue();

// Remove destroyed
if (chaControl == null)
continue;

// Rotate the queue
charaQueue.Enqueue(chaControl);
if (chaControl.sex == 0 && hFlag != null && (hFlag.mode == HFlag.EMode.aibu || hFlag.mode == HFlag.EMode.lesbian || hFlag.mode == HFlag.EMode.masturbation)) continue;
// Found a valid character, otherwise skip (needed for story mode H because roam mode characters are in the queue too, just disabled)
if (chaControl.objTop.activeInHierarchy) return chaControl;
}
return null;
}

currentChara = null;
if(charaQueue == null)
{
CreateQueue();
}
else
{
while (charaQueue.Count > 0 && (currentChara = charaQueue.Dequeue()) == null) {}
if (charaQueue == null) charaQueue = CreateQueue();

if (currentChara != null)
charaQueue.Enqueue(currentChara);
else
CreateQueue();
currentChara = GetCurrentChara();
if (currentChara == null)
{
charaQueue = CreateQueue();
currentChara = GetCurrentChara();
}
}

if(currentChara)
if (currentChara)
{
//foreach(var bone in currentChara.neckLookCtrl.neckLookScript.aBones)
// bone.neckBone.rotation = new Quaternion();

prevVisibleHeadAlways = currentChara.fileStatus.visibleHeadAlways;
if (HideHead.Value) currentChara.fileStatus.visibleHeadAlways = false;

GameCamera = Camera.main;
var cc = (MonoBehaviour)GameCamera.GetComponent<CameraControl_Ver2>() ?? GameCamera.GetComponent<Studio.CameraControl>();
if (cc) cc.enabled = false;

LookRotation = currentChara.objHeadBone.transform.rotation.eulerAngles;

base.EnablePOV();

Expand All @@ -86,16 +112,22 @@ void CreateQueue()

internal override void DisablePOV()
{
currentChara.fileStatus.visibleHeadAlways = prevVisibleHeadAlways;

var cc = (MonoBehaviour)GameCamera.GetComponent<CameraControl_Ver2>() ?? GameCamera.GetComponent<Studio.CameraControl>();
if (cc) cc.enabled = true;

base.DisablePOV();

GameCamera.gameObject.layer = backupLayer;
}

[HarmonyPrefix, HarmonyPatch(typeof(NeckLookControllerVer2), "LateUpdate")]
private static bool ApplyRotation(NeckLookControllerVer2 __instance)
{
if(POVEnabled)
if (POVEnabled)
{
if(__instance.neckLookScript && currentChara.neckLookCtrl == __instance)
if (__instance.neckLookScript && currentChara.neckLookCtrl == __instance)
{
__instance.neckLookScript.aBones[0].neckBone.rotation = Quaternion.identity;
__instance.neckLookScript.aBones[1].neckBone.rotation = Quaternion.identity;
Expand Down

0 comments on commit 07214c6

Please sign in to comment.