Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using ExIni;
- using System;
- using System.Linq;
- using System.Diagnostics;
- using UnityEngine;
- using UnityInjector.Attributes;
- // OH版はChu-BLipにしかないクラスを使っている1行のコメントアウトを外しているだけです(maid.onahole.motion.playedPistonSeType)
- // 1つのソースファイルで済ませたかったのですが、やり方が分かりませんでした…
- // コンパイル用コマンド "C:\Windows\Microsoft.NET\Framework\v3.5\csc" /t:library /lib:..\CM3D2x64_Data(環境に合わせて変更)\Managed /r:UnityEngine.dll /r:UnityInjector.dll /r:Assembly-CSharp.dll /r:Assembly-CSharp-firstpass.dll /r:ExIni.dll CM3D2.KissYourMaid.Plugin.cs
- namespace CM3D2.KissYourMaid.Plugin
- {
- [PluginFilter("CM3D2x64"), PluginFilter("CM3D2x86"), PluginFilter("CM3D2VRx64"),
- PluginFilter("CM3D2OHx64"), PluginFilter("CM3D2OHx86"), PluginFilter("CM3D2OHVRx64"),
- PluginName("KissYourMaid"), PluginVersion("0.2.0.0")]
- public class KissYourMaid : UnityInjector.PluginBase
- {
- //
- private bool bPluginEnabled = true; // 本プラグインの有効状態(下記キーでON/OFFトグル)
- private KeyCode keyPluginToggle = KeyCode.H; // 本プラグインの有効無効の切替キー(とりあえず被らなそうなHキーに)
- // 状態管理
- private int iState = 0; // ステート番号
- private int iStateMajor = 10; // 距離によるステート
- private int iStateMajorOld = 10; // 距離によるステート(前回値)
- private int iStateMinor = 0; // 時間経過によるステート
- // 10 … 離れている
- // 20 … 近い(キス前・遷移直後)
- // 21 … 近い(キス前・一定時間経過後)
- // 30 … とても近い(キス)
- // 40 … 近い(キス後・遷移直後)
- // 41 … 近い(キス後・一定時間経過後)
- // 距離判定
- private float fDistanceToMaidFace;
- private float fDistanceThreshold1;
- private float fDistanceThreshold2;
- private float fDistanceThresholdBase1 = 0.80f; // 「近い」の判定距離
- private float fDistanceThresholdBase2 = 0.50f; // 「とても近い」の距離距離
- private float fDistanceThresholdOffset = 0.20f; // 帰り方向で判定距離をずらす距離
- private float fDistanceThresholdBase1VR = 0.45f; // (VR時)「近い」の判定距離
- private float fDistanceThresholdBase2VR = 0.30f; // (VR時)「とても近い」の距離距離
- private float fDistanceThresholdOffsetVR = 0.10f; // (VR時)帰り方向で判定距離をずらす距離
- // 表情管理
- private int iStateHoldTime;
- private int iStateAltTime1;
- private int iStateAltTime2;
- private int iStateAltTime1Base = 2; // フェイスアニメの変化時間1(秒)(20→21、40→41)
- private int iStateAltTime2Base = 6; // フェイスアニメの変化時間2(秒)(30でのランダム選択)
- private int iStateAltTime1RandomExtend = 2; // 変化時間1へのランダム加算(秒)
- private int iStateAltTime2RandomExtend = 6; // 変化時間2へのランダム加算(秒)
- private float fAnimeFadeTime = 3.0f; // フェイスアニメ等のフェード時間(秒)
- private string sFaceAnimeBackup = "";
- private string sFaceBlendBackup = "";
- // 表情テーブル
- string[] sFaceAnime20 = new string[] { "変更しない" };
- string[] sFaceAnime21 = new string[] { "目口閉じ" };
- string[] sFaceAnime40 = new string[] { "困った"};
- string[] sFaceAnime41 = new string[] { "優しさ", "微笑み" };
- string[] sFaceAnime30Excite1 = new string[] { "接吻", "エロ羞恥2", "ダンスキス", "ダンス憂い", "エロ舐め通常", "閉じ舐め通常" };
- string[] sFaceAnime30Excite2 = new string[] { "閉じフェラ通常", "エロ好感3", "エロ羞恥3", "エロ舐め快楽", "閉じフェラ愛情", "閉じ舐め愛情" };
- string[] sFaceAnime30Excite3 = new string[] { "まぶたギュ", "エロ舌責", "エロ痛み3", "エロ舐め愛情", "エロ舐め嫌悪", "閉じ舐め快楽" };
- string[] sFaceAnime30Excite4 = new string[] { "エロ痛み我慢3", "エロ興奮3", "エロ舌責快楽", "閉じフェラ嫌悪", "閉じ舐め嫌悪", "エロ痛み2" };
- // 声管理
- private bool bVoiceOverrideEnabled = true; // キス時の音声オーバライド(上書き)機能を使う
- private bool bIsVoiceOverriding = false; // 音声オーバライド(上書き)を適用中
- private string sLoopVoiceOverriding = ""; // 音声オーバライド(上書き)を適用している音声ファイル名
- private bool bOverrideInterrupted = false; // 音声オーバライド(上書き)を適用したが、スキル変更などにより割りこまれた
- private string sLoopVoiceBackup = ""; // 音声オーバライド(上書き)を終了した時に、復元再生する音声ファイル名
- // 性格別声テーブル 通常版(興奮度別)
- string[] sLoopVoice30PrideExcite1 = new string[] { "s0_01276.ogg", "s0_01277.ogg", "s0_01278.ogg", "s0_01279.ogg" };
- string[] sLoopVoice30PrideExcite2 = new string[] { "s0_01280.ogg", "s0_01281.ogg", "s0_01282.ogg", "s0_01283.ogg" };
- string[] sLoopVoice30PrideExcite3 = new string[] { "s0_01284.ogg", "s0_01285.ogg", "s0_01286.ogg", "s0_01287.ogg" };
- string[] sLoopVoice30PrideExcite4 = new string[] { "s0_01288.ogg", "s0_01289.ogg", "s0_01290.ogg", "s0_01291.ogg" };
- string[] sLoopVoice30CoolExcite1 = new string[] { "s1_02349.ogg", "s1_02350.ogg", "s1_02351.ogg", "s1_02352.ogg" };
- string[] sLoopVoice30CoolExcite2 = new string[] { "s1_02353.ogg", "s1_02354.ogg", "s1_02355.ogg", "s1_02356.ogg" };
- string[] sLoopVoice30CoolExcite3 = new string[] { "s1_02357.ogg", "s1_02358.ogg", "s1_02359.ogg", "s1_02360.ogg" };
- string[] sLoopVoice30CoolExcite4 = new string[] { "s1_02361.ogg", "s1_02362.ogg", "s1_02363.ogg", "s1_02364.ogg" };
- string[] sLoopVoice30PureExcite1 = new string[] { "s2_01190.ogg", "s2_01191.ogg", "s2_01192.ogg", "s2_01193.ogg" };
- string[] sLoopVoice30PureExcite2 = new string[] { "s2_01194.ogg", "s2_01195.ogg", "s2_01196.ogg", "s2_01197.ogg" };
- string[] sLoopVoice30PureExcite3 = new string[] { "s2_01198.ogg", "s2_01199.ogg", "s2_01200.ogg", "s2_01201.ogg" };
- string[] sLoopVoice30PureExcite4 = new string[] { "s2_01202.ogg", "s2_01203.ogg", "s2_01204.ogg", "s2_01205.ogg" };
- // 性格別声テーブル Chu-BLip版(ピストン速度別) ※ 興奮度が存在しないので、ピストン速度で判定する
- // ※ Chu-BLip版では無いファイルが幾つかあったので、テーブルを別にした(こっちに合わせても良さそうだけど…)
- string[] sLoopVoice30PridePiston1 = new string[] { "s0_01278.ogg", "s0_01278.ogg", "s0_01279.ogg", "s0_01279.ogg" };
- string[] sLoopVoice30PridePiston2 = new string[] { "s0_01278.ogg", "s0_01278.ogg", "s0_01279.ogg", "s0_01279.ogg" };
- string[] sLoopVoice30PridePiston3 = new string[] { "s0_01280.ogg", "s0_01280.ogg", "s0_01281.ogg", "s0_01281.ogg" };
- string[] sLoopVoice30PridePiston4 = new string[] { "s0_01282.ogg", "s0_01282.ogg", "s0_01283.ogg", "s0_01283.ogg" };
- string[] sLoopVoice30CoolPiston1 = new string[] { "s1_02351.ogg", "s1_02351.ogg", "s1_02352.ogg", "s1_02352.ogg" };
- string[] sLoopVoice30CoolPiston2 = new string[] { "s1_02351.ogg", "s1_02351.ogg", "s1_02352.ogg", "s1_02352.ogg" };
- string[] sLoopVoice30CoolPiston3 = new string[] { "s1_02353.ogg", "s1_02353.ogg", "s1_02354.ogg", "s1_02354.ogg" };
- string[] sLoopVoice30CoolPiston4 = new string[] { "s1_02355.ogg", "s1_02355.ogg", "s1_02356.ogg", "s1_02356.ogg" };
- string[] sLoopVoice30PurePiston1 = new string[] { "s2_01192.ogg", "s2_01192.ogg", "s2_01193.ogg", "s2_01193.ogg" };
- string[] sLoopVoice30PurePiston2 = new string[] { "s2_01192.ogg", "s2_01192.ogg", "s2_01193.ogg", "s2_01193.ogg" };
- string[] sLoopVoice30PurePiston3 = new string[] { "s2_01194.ogg", "s2_01194.ogg", "s2_01195.ogg", "s2_01195.ogg" };
- string[] sLoopVoice30PurePiston4 = new string[] { "s2_01196.ogg", "s2_01196.ogg", "s2_01197.ogg", "s2_01197.ogg" };
- // 興奮度管理
- private int iExciteLevel = 1; // 0~300の興奮度を、1~4の興奮レベルに変換した値
- private int iExciteLevelThreshold1 = 150; // 興奮レベル1→2閾値
- private int iExciteLevelThreshold2 = 200; // 興奮レベル2→3閾値
- private int iExciteLevelThreshold3 = 250; // 興奮レベル3→4閾値
- // Chu-B Lip / VR
- private bool bChuBLip;
- private bool bOculusVR;
- private OVRDisplay ovrDisplay;
- private int iExciteLevelOld;
- private bool bPistonSpeedChanged;
- //
- private int iSceneLevel = 0;
- private bool bIsYotogiScene;
- private int iFrameCount = 0;
- private int iFpsMax = 60;
- private int iFpsMaxVR = 75;
- //
- private CameraMain mainCamera;
- private Maid maid;
- private Transform maidHead;
- void Awake()
- {
- GameObject.DontDestroyOnLoad(this);
- string path = Application.dataPath;
- // ChuBLip判別
- bChuBLip = path.Contains("CM3D2OHx64") || path.Contains("CM3D2OHx86") || path.Contains("CM3D2OHVRx64");
- if (bChuBLip)
- {
- sLoopVoice30CoolExcite1 = sLoopVoice30PridePiston1;
- sLoopVoice30CoolExcite2 = sLoopVoice30PridePiston2;
- sLoopVoice30CoolExcite3 = sLoopVoice30PridePiston3;
- sLoopVoice30CoolExcite4 = sLoopVoice30PridePiston4;
- }
- // VR判別
- bOculusVR = path.Contains("CM3D2OHVRx64") || path.Contains("CM3D2VRx64");
- if (bOculusVR)
- {
- fDistanceThresholdBase1 = fDistanceThresholdBase1VR;
- fDistanceThresholdBase2 = fDistanceThresholdBase2VR;
- fDistanceThresholdOffset = fDistanceThresholdOffsetVR;
- iFpsMax = iFpsMaxVR;
- ovrDisplay = new OVRDisplay();
- }
- fDistanceThreshold1 = fDistanceThresholdBase1;
- fDistanceThreshold2 = fDistanceThresholdBase2;
- }
- public void Start()
- {
- }
- void OnLevelWasLoaded(int level)
- {
- // レベルの取得
- iSceneLevel = level;
- // メインカメラの取得
- mainCamera = GameMain.Instance.MainCamera;
- // メイドさんの取得
- maid = GameMain.Instance.CharacterMgr.GetMaid(0);
- if (maid)
- {
- Transform[] objList = maid.transform.GetComponentsInChildren<Transform>();
- if (objList.Count() == 0)
- {
- }
- else
- {
- foreach (var gameobject in objList)
- {
- if (gameobject.name == "Bone_Face")
- {
- maidHead = gameobject;
- }
- }
- }
- }
- // 夜伽シーンに有るかチェック
- checkYotogiScene();
- // 設定ファイルの読込・初期化
- loadConfigIni();
- // 各バックアップ値の初期化
- sFaceAnimeBackup = "";
- sFaceBlendBackup = "";
- sLoopVoiceBackup = "";
- }
- void OnGUI()
- {
- #if DEBUG
- //GUIへのデバッグ表示
- if (maid)
- {
- GUI.Label(new Rect(0, 0, 900, 30),
- string.Format("Level={0}, Yotogi={1}, iState={2}, fDistanceToMaidFace={3} ",
- iSceneLevel, bIsYotogiScene, iState, fDistanceToMaidFace));
- if (maid.AudioMan != null && maid.AudioMan.FileName != null)
- {
- GUI.Label(new Rect(0, 30, 900, 60),
- string.Format("AudioClip={0}, IsLoop={1}, AudioTime={2} of {3}, ActiveFace={4}, ExciteLevel={5}",
- maid.AudioMan.FileName, maid.AudioMan.audiosource.loop, maid.AudioMan.audiosource.time, maid.AudioMan.audiosource.clip.length, maid.ActiveFace, iExciteLevel));
- GUI.Label(new Rect(0, 60, 900, 90),
- string.Format("bIsVoiceOverriding={0}, sLoopVoiceBackup={1}, iStateAltTime1={2}, iStateAltTime2={3}",
- bIsVoiceOverriding, sLoopVoiceBackup, iStateAltTime1, iStateAltTime2));
- }
- }
- #endif
- }
- void Update()
- {
- // 約1秒毎に呼び出す
- if (iFrameCount == iFpsMax)
- {
- iFrameCount = 0;
- // 表情等変更処理
- if (bPluginEnabled && bIsYotogiScene)
- {
- checkFaceDistance();
- }
- }
- else
- {
- iFrameCount++;
- }
- // 本プラグインの有効無効の切替
- if (Input.GetKeyDown(keyPluginToggle))
- {
- bPluginEnabled = !bPluginEnabled;
- //// プラグイン有効化時に設定ファイル読みなおし ※再起動しないとIni読みなおしてくれない??
- //if (bPluginEnabled)
- //{
- // // 設定ファイルの読込・初期化
- // loadConfigIni();
- //}
- // プラグイン無効化時の処理
- if (!bPluginEnabled && sFaceAnimeBackup != "")
- {
- // 表情の復元
- restoreFace();
- // 音声の復元もしくは停止
- if (bIsVoiceOverriding)
- {
- // オーバライド状態を解除
- bIsVoiceOverriding = false;
- bOverrideInterrupted = false;
- // 復元もしくは停止
- if (sLoopVoiceBackup != "")
- {
- maid.AudioMan.LoadPlay(sLoopVoiceBackup, 0f, true, true);
- debugPrintConsole("voice restore done. " + sLoopVoiceBackup);
- }
- else
- {
- maid.AudioMan.Stop();
- debugPrintConsole("voice stop done. " + sLoopVoiceBackup);
- }
- }
- }
- }
- }
- // カメラ(プレイヤーの視点)とメイドさんの頭との距離に応じて、
- // 表情など(フェイスアニメ、フェイスブレンド、顔目追従の状態)を変える
- private void checkFaceDistance()
- {
- // 距離取得
- if (bOculusVR)
- {
- OVRPose ovrPose;
- ovrPose = ovrDisplay.GetHeadPose(0d); //GetEyePoseの方がいい?要検討
- Vector3 displayPos = new Vector3(ovrPose.position.x, ovrPose.position.y, ovrPose.position.z);
- displayPos = Quaternion.Euler(0f, mainCamera.transform.localEulerAngles.y, 0f) * displayPos;
- fDistanceToMaidFace = Vector3.Distance(maidHead.transform.position, mainCamera.transform.position + displayPos);
- }
- else
- {
- fDistanceToMaidFace = Vector3.Distance(maidHead.transform.position, mainCamera.transform.position);
- }
- // 距離ステートの変更
- if (fDistanceToMaidFace < fDistanceThreshold2) // 「とても近い」
- {
- iStateMajor = 30;
- fDistanceThreshold1 = fDistanceThresholdBase1 + fDistanceThresholdOffset;
- fDistanceThreshold2 = fDistanceThresholdBase2 + fDistanceThresholdOffset;
- }
- else if (fDistanceToMaidFace < fDistanceThreshold1) // 「近い」
- {
- // 「離れている」から来た時と、「とても近い」から来た時を区別する
- if (iStateMajorOld < 20)
- {
- iStateMajor = 20;
- }
- else if (20 <= iStateMajorOld && iStateMajorOld < 30)
- {
- iStateMajor = 20;
- }
- else if (30 <= iStateMajorOld && iStateMajorOld < 40)
- {
- iStateMajor = 40;
- }
- else if (40 <= iStateMajorOld)
- {
- iStateMajor = 40;
- }
- fDistanceThreshold1 = fDistanceThresholdBase1 + fDistanceThresholdOffset;
- fDistanceThreshold2 = fDistanceThresholdBase2;
- }
- else // 「離れている」
- {
- iStateMajor = 10;
- fDistanceThreshold1 = fDistanceThresholdBase1;
- fDistanceThreshold2 = fDistanceThresholdBase2;
- }
- // 「離れている」から遷移してくる時には、その時点での表情などをバックアップしておく
- if (iStateMajor != 10 && iStateMajorOld == 10) backupFace();
- // 距離ステートが変わったら、時間カウンタをリセットする
- if (iStateMajor != iStateMajorOld)
- {
- // 時間カウンタのリセット
- iStateHoldTime = 0;
- // 表情変化時間のランダマイズ
- iStateAltTime1 = iStateAltTime1Base + UnityEngine.Random.Range(0, iStateAltTime1RandomExtend + 1);
- }
- // 時間ステートの変更
- if (iStateMajor == 10) iStateMinor = 0;
- if (iStateMajor == 20 || iStateMajor == 40)
- {
- // 時間経過により、一方通行で表情変化
- iStateMinor = 0;
- if (iStateAltTime1 <= iStateHoldTime) iStateMinor = 1;
- }
- if (iStateMajor == 30)
- {
- iStateMinor = 0;
- if (iStateAltTime2 <= iStateHoldTime)
- {
- // 時間カウンタのリセット
- iStateHoldTime = 0;
- // 表情変化時間のランダマイズ
- iStateAltTime2 = iStateAltTime2Base + UnityEngine.Random.Range(0, iStateAltTime2RandomExtend + 1);
- }
- }
- iState = iStateMajor + iStateMinor;
- // 興奮度の判定 (通常版用)
- int iCurrentExcite = maid.Param.status.cur_excite;
- if (iCurrentExcite < iExciteLevelThreshold1)
- {
- iExciteLevel = 1;
- }
- else if (iExciteLevelThreshold1 <= iCurrentExcite && iCurrentExcite < iExciteLevelThreshold2)
- {
- iExciteLevel = 2;
- }
- else if (iExciteLevelThreshold2 <= iCurrentExcite && iCurrentExcite < iExciteLevelThreshold3)
- {
- iExciteLevel = 3;
- }
- else if (iExciteLevelThreshold3 <= iCurrentExcite)
- {
- iExciteLevel = 4;
- }
- // ピストン速度の判定 (Chu-BLip版用)
- string sPistonSpeed = "";
- // 次の行はChu-BLip版でしか使えないので、通常版用にコンパイルするときはコメントアウトする。
- //sPistonSpeed = maid.onahole.motion.playedPistonSeType.ToString();
- if (bChuBLip)
- {
- if (sPistonSpeed == "低速")
- {
- iExciteLevel = 2;
- }
- else if (sPistonSpeed == "中速")
- {
- iExciteLevel = 3;
- }
- else if (sPistonSpeed == "高速")
- {
- iExciteLevel = 4;
- }
- else // "停止" or NO_DATA
- {
- iExciteLevel = 1;
- }
- // スピードが変わったら音声を改めて適用する
- if (iExciteLevel != iExciteLevelOld)
- {
- bPistonSpeedChanged = true;
- debugPrintConsole("piston speed has changed.");
- }
- iExciteLevelOld = iExciteLevel;
- }
- // ループ音声の適用
- // ループ音声が流れているときはバックアップする(オーバライドしたものは除く)
- // 夜伽前の会話シーンなど、ループ音声が拾えない時もあるので注意すること
- if (bVoiceOverrideEnabled)
- {
- // ループ音声のバックアップ(通常版)
- if (!bChuBLip && !bIsVoiceOverriding && maid.AudioMan.audiosource.loop && maid.AudioMan.audiosource.isPlaying)
- {
- bOverrideInterrupted = false;
- sLoopVoiceBackup = maid.AudioMan.FileName;
- debugPrintConsole("voice backup done. " + sLoopVoiceBackup);
- }
- // 一回再生音声のバックアップ(ChuBLip版)
- if (bChuBLip && !bIsVoiceOverriding)
- {
- bOverrideInterrupted = false;
- sLoopVoiceBackup = maid.AudioMan.FileName;
- debugPrintConsole("voice backup done. " + sLoopVoiceBackup);
- }
- // 音声オーバライド判定開始ここから
- bool bAllowVoiceOverride = false;
- // 「とても近い」
- if (iStateMajor == 30)
- {
- // 割り込みされた後、バックアップが拾えてない状況ではない
- if (!bOverrideInterrupted)
- {
- // 音声オーバライド未だ or 時間カウントリセット時
- if (!bIsVoiceOverriding || iStateHoldTime == 0)
- {
- // ループ音声を再生中、もしくは一回再生音声が再生済みなら介入してよい
- if (maid.AudioMan.audiosource.loop || (!maid.AudioMan.audiosource.loop && !maid.AudioMan.audiosource.isPlaying))
- {
- bAllowVoiceOverride = true;
- }
- // ChuBLip版では、ループ音声が夜伽で使われないので、上の条件によらず許可する
- if (bChuBLip)
- {
- bAllowVoiceOverride = true;
- }
- }
- // ChuBLip版では、ピストン速度に変化があった時に、強制的に新しい音声を再生しなおす
- if (bChuBLip & bPistonSpeedChanged)
- {
- bPistonSpeedChanged = false;
- bAllowVoiceOverride = true;
- iStateHoldTime = 0;
- }
- }
- }
- // 上記でオーバーライドが許可されたら実際に再生する
- if (bAllowVoiceOverride)
- {
- bIsVoiceOverriding = true;
- int iRandomVoice = UnityEngine.Random.Range(0, 4);
- string sPersonal = maid.Param.status.personal.ToString();
- if (sPersonal == "Pure")
- {
- if (iExciteLevel == 1)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PureExcite1[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 2)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PureExcite2[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 3)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PureExcite3[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 4)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PureExcite4[iRandomVoice], 0f, true, true);
- }
- }
- else if (sPersonal == "Cool")
- {
- if (iExciteLevel == 1)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30CoolExcite1[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 2)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30CoolExcite2[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 3)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30CoolExcite3[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 4)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30CoolExcite4[iRandomVoice], 0f, true, true);
- }
- }
- else if (sPersonal == "Pride")
- {
- if (iExciteLevel == 1)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PrideExcite1[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 2)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PrideExcite2[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 3)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PrideExcite3[iRandomVoice], 0f, true, true);
- }
- else if (iExciteLevel == 4)
- {
- maid.AudioMan.LoadPlay(sLoopVoice30PrideExcite4[iRandomVoice], 0f, true, true);
- }
- }
- // 再生を始めたファイル名を記憶
- sLoopVoiceOverriding = maid.AudioMan.FileName;
- }
- // 音声の割り込み判定
- // 音声オーバライド状態において、一回再生音声に割り込まれたら、
- // オーバライド状態を一度解除し、バックアップ音声を拾い直す(キスしながらイッてぐったりしたメイドさんに、イク前の発情ボイスを復元してしまうといった事故を防ぐ)
- if (bIsVoiceOverriding)
- {
- // 音を切り替えるタイミングではない
- if ((iStateMajor == 30 || iStateHoldTime != 0)
- || (iStateMajor == 20 || iStateHoldTime == iStateAltTime1)
- || (iStateMajor == 40 || iStateHoldTime == iStateAltTime1))
- {
- // 再生中の音声が、オーバライドした音声と一致しない
- if (maid.AudioMan.FileName != sLoopVoiceOverriding)
- {
- bOverrideInterrupted = true;
- bIsVoiceOverriding = false;
- sLoopVoiceBackup = "";
- debugPrintConsole("override interrupted." + sLoopVoiceBackup);
- }
- }
- }
- // 音声オーバライドの停止と復元
- if (iStateMajor != 30 && bIsVoiceOverriding)
- {
- // オーバライド状態を解除
- bIsVoiceOverriding = false;
- bOverrideInterrupted = false;
- if (!bChuBLip)
- {
- // 復元もしくは停止
- if (sLoopVoiceBackup != "")
- {
- maid.AudioMan.LoadPlay(sLoopVoiceBackup, 0f, true, true);
- debugPrintConsole("voice restore done. " + sLoopVoiceBackup);
- }
- else
- {
- maid.AudioMan.Stop();
- debugPrintConsole("voice stop done. " + sLoopVoiceBackup);
- }
- }
- else
- {
- // Chu-B Lip版は復元をしない(現状、音声セリフ付きの音を復元してしまい不自然になることがある)
- }
- }
- }
- // フェイスアニメの適用
- bool bAllowChangeFaceAnime = false;
- // 遷移直後かカウンタリセット時のタイミングで適用
- if ((iStateHoldTime == 0)
- || (iStateMajor == 20 && iStateHoldTime == iStateAltTime1)
- || (iStateMajor == 40 && iStateHoldTime == iStateAltTime1))
- {
- bAllowChangeFaceAnime = true;
- }
- int iRandomFace = 0;
- if (bAllowChangeFaceAnime)
- {
- string sFaceAnimeName = "";
- if (iState == 20)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime20.Length);
- sFaceAnimeName = sFaceAnime20[iRandomFace];
- }
- if (iState == 21)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime21.Length);
- sFaceAnimeName = sFaceAnime21[iRandomFace];
- }
- if (iState == 40)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime40.Length);
- sFaceAnimeName = sFaceAnime40[iRandomFace];
- }
- if (iState == 41)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime41.Length);
- sFaceAnimeName = sFaceAnime41[iRandomFace];
- }
- if (iState == 30)
- {
- if (iExciteLevel == 1)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime30Excite1.Length);
- sFaceAnimeName = sFaceAnime30Excite1[iRandomFace];
- }
- else if (iExciteLevel == 2)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime30Excite2.Length);
- sFaceAnimeName = sFaceAnime30Excite2[iRandomFace];
- }
- else if (iExciteLevel == 3)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime30Excite3.Length);
- sFaceAnimeName = sFaceAnime30Excite3[iRandomFace];
- }
- else if (iExciteLevel == 4)
- {
- iRandomFace = UnityEngine.Random.Range(0, sFaceAnime30Excite4.Length);
- sFaceAnimeName = sFaceAnime30Excite4[iRandomFace];
- }
- }
- // ""か"変更しない"でなければ、フェイスアニメを適用する
- if (sFaceAnimeName != "" && sFaceAnimeName != "変更しない")
- {
- maid.FaceAnime(sFaceAnimeName, fAnimeFadeTime, 0);
- }
- }
- // フェイスブレンドの適用
- // ステートに応じたフェイスブレンドに上書きする。
- // ただし、より強いものが適用されるなら、そちらを尊重して上書きしない
- string sFaceBlendCurrent = maid.FaceName3;
- if (sFaceBlendCurrent == "") sFaceBlendCurrent = "頬0涙0"; // 背景選択時、スキル選択時は、"" が返ってきてエラーが出るため
- string sCurrentCheek = "";
- string sCurrentTears = "";
- int iCurrentCheek = 0;
- int iCurrentTears = 0;
- bool bCurrentDrivel = false;
- string sChangeCheek = "";
- string sChangeTears = "";
- int iChangeCheek = 0;
- int iChangeTears = 0;
- string sChangeDrivel = "";
- string sChangeBlend = "";
- int iOverrideCheek = 0;
- int iOverrideTears = 0;
- bool bOverrideDrivel = false;
- // 暫定的に、どのステート対しても、同じフェイスブレンド・顔目追従を適用する
- iOverrideCheek = 2; //"頬2"
- iOverrideTears = 0; //"涙0"
- bOverrideDrivel = false; //よだれなし
- maid.EyeToCamera((Maid.EyeMoveType)5, fAnimeFadeTime); //顔も目もこっち見る
- sCurrentCheek = sFaceBlendCurrent.Substring(0, 2);
- if (sCurrentCheek == "頬0") iCurrentCheek = 0;
- if (sCurrentCheek == "頬1") iCurrentCheek = 1;
- if (sCurrentCheek == "頬2") iCurrentCheek = 2;
- if (sCurrentCheek == "頬3") iCurrentCheek = 3;
- iChangeCheek = iCurrentCheek;
- if (iOverrideCheek > iChangeCheek) iChangeCheek = iOverrideCheek;
- if (iChangeCheek == 0) sChangeCheek = "頬0";
- if (iChangeCheek == 1) sChangeCheek = "頬1";
- if (iChangeCheek == 2) sChangeCheek = "頬2";
- if (iChangeCheek == 3) sChangeCheek = "頬3";
- sCurrentTears = sFaceBlendCurrent.Substring(2, 2);
- if (sCurrentTears == "涙0") iCurrentTears = 0;
- if (sCurrentTears == "涙1") iCurrentTears = 1;
- if (sCurrentTears == "涙2") iCurrentTears = 2;
- if (sCurrentTears == "涙3") iCurrentTears = 3;
- iChangeTears = iCurrentTears;
- if (iOverrideTears > iChangeTears) iChangeTears = iOverrideTears;
- if (iChangeTears == 0) sChangeTears = "涙0";
- if (iChangeTears == 1) sChangeTears = "涙1";
- if (iChangeTears == 2) sChangeTears = "涙2";
- if (iChangeTears == 3) sChangeTears = "涙3";
- if (sFaceBlendCurrent.Substring(3) == "よだれ") bCurrentDrivel = true;
- if (bCurrentDrivel || bOverrideDrivel) sChangeDrivel = "よだれ";
- sChangeBlend = sChangeCheek + sChangeTears + sChangeDrivel;
- maid.FaceBlend(sChangeBlend);
- debugPrintConsole("FaceBlendLevel=" + iChangeCheek + " , " + iChangeTears + " , " + sChangeDrivel);
- //if (bDebug) Console.WriteLine("FaceBlendLevel : {0}, {1}, {2}", iChangeCheek, iChangeTears, sChangeDrivel);
- // 「離れている」に戻る時に、フェイスアニメ・フェイスブレンドを復元する(現在フェイスアニメのみ復元)
- if (iStateMajor == 10 && iStateMajorOld != 10) restoreFace();
- // 距離ステートの過去値を更新
- iStateMajorOld = iStateMajor;
- // 距離ステート保持時間を加算する(30でカンスト)
- if (iStateHoldTime++ > 30) iStateHoldTime = 30;
- debugPrintConsole("Level=" + iSceneLevel + " bIsYotogi=" + bIsYotogiScene +
- " iState=" + iState + " fDistanceToMaidFace=" + fDistanceToMaidFace);
- }
- // フェイスアニメ・フェイスブレンドのバックアップ
- private void backupFace()
- {
- sFaceAnimeBackup = maid.ActiveFace;
- sFaceBlendBackup = maid.FaceName3;
- // 頭の向き追従状態も保存したいが何処に保存されているか分からない
- debugPrintConsole("face backup done. " + sFaceAnimeBackup + " , " + sFaceBlendBackup);
- }
- // フェイスアニメ・フェイスブレンドの復元
- private void restoreFace()
- {
- if (sFaceAnimeBackup != "")
- {
- maid.FaceAnime(sFaceAnimeBackup, fAnimeFadeTime * 2, 0);
- }
- // 顔目追従も復元したいが、どの変数に保存されているか分からないので保留…
- //maid.EyeToCamera((Maid.EyeMoveType)0, 0f);
- //maid.FaceBlend(sFaceBlendBackup);
- // 近づいた時の状況を復元するので、離れた時にスキルが変わっていると表情が食い違って不自然になることがあるが、現状いい方法がないので保留…
- // フェイスブレンドも復元するつもりだったが、突然素に戻ったようになってしまうことが有ったので、戻さないようにした
- sFaceAnimeBackup = "";
- sFaceBlendBackup = "";
- debugPrintConsole("face restore done. " + sFaceAnimeBackup + " , " + sFaceBlendBackup);
- //if (bDebug) Console.WriteLine("face restore done. {0}, {1}", sFaceAnimeBackup, sFaceBlendBackup);
- }
- // 夜伽シーンにいるかをチェック
- private void checkYotogiScene()
- {
- // OH版は夜伽シーンでもSceneが14にならない(10のまま)ので、YotogiManagerの有無で判別する
- int iYotogiManagerCount = FindObjectsOfType<YotogiManager>().Length;
- bIsYotogiScene = false;
- if (iYotogiManagerCount > 0) bIsYotogiScene = true;
- }
- // 設定ファイルの読み込み
- private void loadConfigIni()
- {
- IniKey INIkeyPluginToggle = Preferences["Settings"]["keyPluginToggle"];
- IniKey INIbVoiceOverrideEnabled = Preferences["Settings"]["bVoiceOverrideEnabled"];
- readIniKey(ref keyPluginToggle, ref INIkeyPluginToggle);
- readIniBool(ref bVoiceOverrideEnabled, ref INIbVoiceOverrideEnabled);
- IniKey INIiExciteLevelThreshold1 = Preferences["Settings"]["iExciteLevelThreshold1"];
- IniKey INIiExciteLevelThreshold2 = Preferences["Settings"]["iExciteLevelThreshold2"];
- IniKey INIiExciteLevelThreshold3 = Preferences["Settings"]["iExciteLevelThreshold3"];
- readIniInt(ref iExciteLevelThreshold1, ref INIiExciteLevelThreshold1);
- readIniInt(ref iExciteLevelThreshold2, ref INIiExciteLevelThreshold2);
- readIniInt(ref iExciteLevelThreshold3, ref INIiExciteLevelThreshold3);
- IniKey INIfDistanceThresholdBase1 = Preferences["Settings"]["fDistanceThresholdBase1"];
- IniKey INIfDistanceThresholdBase2 = Preferences["Settings"]["fDistanceThresholdBase2"];
- IniKey INIfDistanceThresholdOffset = Preferences["Settings"]["fDistanceThresholdOffset"];
- readIniFloat(ref fDistanceThresholdBase1, ref INIfDistanceThresholdBase1);
- readIniFloat(ref fDistanceThresholdBase2, ref INIfDistanceThresholdBase2);
- readIniFloat(ref fDistanceThresholdOffset, ref INIfDistanceThresholdOffset);
- IniKey INIfDistanceThresholdBase1VR = Preferences["Settings"]["fDistanceThresholdBase1VR"];
- IniKey INIfDistanceThresholdBase2VR = Preferences["Settings"]["fDistanceThresholdBase2VR"];
- IniKey INIfDistanceThresholdOffsetVR = Preferences["Settings"]["fDistanceThresholdOffsetVR"];
- readIniFloat(ref fDistanceThresholdBase1VR, ref INIfDistanceThresholdBase1VR);
- readIniFloat(ref fDistanceThresholdBase2VR, ref INIfDistanceThresholdBase2VR);
- readIniFloat(ref fDistanceThresholdOffsetVR, ref INIfDistanceThresholdOffsetVR);
- IniKey INIiStateAltTime1Base = Preferences["Settings"]["iStateAltTime1Base"];
- IniKey INIiStateAltTime2Base = Preferences["Settings"]["iStateAltTime2Base"];
- IniKey INIiStateAltTime1RandomExtend = Preferences["Settings"]["iStateAltTime1RandomExtend"];
- IniKey INIiStateAltTime2RandomExtend = Preferences["Settings"]["iStateAltTime2RandomExtend"];
- IniKey INIfAnimeFadeTime = Preferences["Settings"]["fAnimeFadeTime"];
- readIniInt(ref iStateAltTime1Base, ref INIiStateAltTime1Base);
- readIniInt(ref iStateAltTime2Base, ref INIiStateAltTime2Base);
- readIniInt(ref iStateAltTime1RandomExtend, ref INIiStateAltTime1RandomExtend);
- readIniInt(ref iStateAltTime2RandomExtend, ref INIiStateAltTime2RandomExtend);
- readIniFloat(ref fAnimeFadeTime, ref INIfAnimeFadeTime);
- IniKey INIsFaceAnime20 = Preferences["FaceAnime"]["sFaceAnime20"];
- IniKey INIsFaceAnime21 = Preferences["FaceAnime"]["sFaceAnime21"];
- IniKey INIsFaceAnime40 = Preferences["FaceAnime"]["sFaceAnime40"];
- IniKey INIsFaceAnime41 = Preferences["FaceAnime"]["sFaceAnime41"];
- IniKey INIsFaceAnime30Excite1 = Preferences["FaceAnime"]["sFaceAnime30Excite1"];
- IniKey INIsFaceAnime30Excite2 = Preferences["FaceAnime"]["sFaceAnime30Excite2"];
- IniKey INIsFaceAnime30Excite3 = Preferences["FaceAnime"]["sFaceAnime30Excite3"];
- IniKey INIsFaceAnime30Excite4 = Preferences["FaceAnime"]["sFaceAnime30Excite4"];
- readIniStringArray(ref sFaceAnime20, ref INIsFaceAnime20);
- readIniStringArray(ref sFaceAnime21, ref INIsFaceAnime21);
- readIniStringArray(ref sFaceAnime40, ref INIsFaceAnime40);
- readIniStringArray(ref sFaceAnime41, ref INIsFaceAnime41);
- readIniStringArray(ref sFaceAnime30Excite1, ref INIsFaceAnime30Excite1);
- readIniStringArray(ref sFaceAnime30Excite2, ref INIsFaceAnime30Excite2);
- readIniStringArray(ref sFaceAnime30Excite3, ref INIsFaceAnime30Excite3);
- readIniStringArray(ref sFaceAnime30Excite4, ref INIsFaceAnime30Excite4);
- }
- // ExIniでキーを読みだす用の関数
- private void readIniKey(ref KeyCode keyTarget, ref IniKey sIniKey)
- {
- if (sIniKey == null || string.IsNullOrEmpty(sIniKey.Value))
- {
- sIniKey.Value = keyTarget.ToString();
- SaveConfig();
- }
- else
- {
- keyTarget = (KeyCode)Enum.Parse(typeof(KeyCode), sIniKey.Value, true);
- }
- }
- private void readIniBool(ref bool bTarget, ref IniKey sIniKey)
- {
- if (sIniKey == null || string.IsNullOrEmpty(sIniKey.Value))
- {
- sIniKey.Value = bTarget.ToString();
- SaveConfig();
- }
- else
- {
- bTarget = bool.Parse(sIniKey.Value);
- }
- }
- private void readIniInt(ref int iTarget, ref IniKey sIniKey)
- {
- if (sIniKey == null || string.IsNullOrEmpty(sIniKey.Value))
- {
- sIniKey.Value = iTarget.ToString();
- SaveConfig();
- }
- else
- {
- iTarget = int.Parse(sIniKey.Value);
- }
- }
- private void readIniFloat(ref float fTarget, ref IniKey sIniKey)
- {
- if (sIniKey == null || string.IsNullOrEmpty(sIniKey.Value))
- {
- sIniKey.Value = fTarget.ToString();
- sIniKey.Value.Replace("f", "");
- SaveConfig();
- }
- else
- {
- fTarget = float.Parse(sIniKey.Value);
- }
- }
- private void readIniStringArray(ref string[] sTarget, ref IniKey sIniKey)
- {
- if (sIniKey == null || string.IsNullOrEmpty(sIniKey.Value))
- {
- sIniKey.Value = string.Join(",", sTarget);
- SaveConfig();
- }
- else
- {
- sTarget = sIniKey.Value.Split(',');
- }
- }
- // デバッグ用コンソール出力メソッド
- [Conditional("DEBUG")]
- private void debugPrintConsole(string s)
- {
- Console.WriteLine(s);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment