using System; using System.Collections.Generic; using kt.Utility; using UnityEngine; [Serializable] public class AutoKupaCtrl { public AutoKupaCtrl(TBody tgt_body, AutoKupaCtrl.MorphType morph_type) { this.body = tgt_body; this.morphType = morph_type; switch (this.morphType) { case AutoKupaCtrl.MorphType.Vagina: this.morphName = "openvagina"; this.MorphInsert.bone = tgt_body.GetBone("_IK_vagina"); break; case AutoKupaCtrl.MorphType.Anal: this.morphName = "openanal"; this.MorphInsert.bone = tgt_body.GetBone("_IK_anal"); break; case AutoKupaCtrl.MorphType.Kupa: this.morphName = "openkupa"; this.MorphInsert.bone = tgt_body.GetBone("_IK_vagina"); break; } this.isNotKupa = true; } public int morphIndex { get { return (this.BodySkin.morph == null) ? -1 : ((int)this.BodySkin.morph.hash[this.morphName]); } } private TBodySkin BodySkin { get { return this.body.GetSlot(0); } } public AutoKupaCtrl.MovementType movementType { get; private set; } public AutoKupaCtrl.KupaType kupaType { get; private set; } public bool isNotKupa { get; private set; } public float morphValue { get { return this.BodySkin.morph.GetBlendValues(this.morphIndex); } set { int num = MathUtility.RatioToPercentage(this.BodySkin.morph.GetBlendValues(this.morphIndex), false); int num2 = MathUtility.RatioToPercentage(value * this.morphValueMax, true); bool flag = num != num2; if (flag) { this.BodySkin.morph.FixBlendValues(); } } } public float morphValueMax { get { return this.MorphValueMax; } set { this.MorphValueMax = Mathf.Clamp01(value); } } public AutoKupaCtrl.TimerParam morphTime { get { return this.MorphTime; } } public AutoKupaCtrl.InsertParam morphInsert { get { return this.MorphInsert; } } public void KupaUpdate() { if (this.isNotKupa) { return; } if (!this.IsDoneSetUp) { this.SetKupaTimer(AutoKupaCtrl.KupaType.Close, this.body.motionBlendTime, 0f); } AutoKupaCtrl.MovementType movementType = this.movementType; if (movementType != AutoKupaCtrl.MovementType.Insert) { if (movementType == AutoKupaCtrl.MovementType.Timer) { this.MorphTime.curTime += Time.deltaTime; float morphValue = (this.kupaType != AutoKupaCtrl.KupaType.Open) ? (1f - this.MorphTime.ratio) : this.MorphTime.ratio; this.morphValue = morphValue; } } else { int chain_count = this.MorphInsert.chainBones.Length; Transform chainEndBone = this.MorphInsert.chainEndBone; if (!chainEndBone) { this.Finish(); return; } Vector3 lhs = chainEndBone.position - this.MorphInsert.bone.position; float end_length = Vector3.Dot(lhs, this.MorphInsert.worldInsertAxis); bool isInsert = this.MorphInsert.isInsert; if (this.MorphInsert.isInsert && this.kupaType == AutoKupaCtrl.KupaType.Open) { this.MorphInsert.isInsert = (end_length <= 0f); } else { this.MorphInsert.isInsert = (end_length <= 0f && this.IsKupaRangeIn(chainEndBone.position)); } if (!this.MorphInsert.isInsert) { this.kupaSpeed = this.MorphInsert.kupaSpeedIn; this.MorphInsert.lastInsertValue = 0f; this.MorphInsert.adjustVal = 0f; if (!this.MorphInsert.isTimeClose) { this.morphValue = 0f; if (this.kupaType == AutoKupaCtrl.KupaType.Close) { this.isNotKupa = true; this.kupaSpeed = -1f; } } else { AutoKupaCtrl.TimerParam timeCloseParam = this.MorphInsert.timeCloseParam; this.SetKupaTimer(AutoKupaCtrl.KupaType.Close, timeCloseParam.totalTime, timeCloseParam.waitTime); } return; } DebugUtility.DrawSquare(this.MorphInsert.bone.position, this.MorphInsert.bone.rotation, this.MorphInsert.checkInsertAxis, 0.05f); DebugUtility.DrawObjAxis(chainEndBone, 0.0625f); Func func = delegate(Vector3 pos) { float num5 = Vector3.Dot(pos - this.MorphInsert.bone.position, this.MorphInsert.worldInsertAxis); return (num5 <= 0f) ? 1f : (1f - num5 / (num5 + Mathf.Abs(end_length))); }; float num = func(this.MorphInsert.chainStartBone.position); float num2 = num - this.MorphInsert.lastInsertValue; bool flag = false; if (Mathf.Abs(num2) > 0.001f) { float num3 = (num2 <= 0f) ? this.MorphInsert.kupaSpeedOut : this.MorphInsert.kupaSpeedIn; flag = (num3 != this.kupaSpeed); this.kupaSpeed = num3; } Func func2 = delegate(float speed) { float num5 = Mathf.Floor(speed); float f = (float)chain_count * Mathf.Clamp01(num5 / 10f); int num6 = Mathf.Clamp(Mathf.FloorToInt(f) - 1, 0, chain_count - 1); int num7 = Mathf.Clamp(num6 + 1, 0, chain_count - 1); Vector3 position = this.MorphInsert.chainBones[num6].position; Vector3 position2 = this.MorphInsert.chainBones[num7].position; float t = speed - num5; return Vector3.Lerp(position, position2, t); }; this.MorphInsert.lastInsertValue = num; Vector3 vector = func2(this.kupaSpeed); float num4 = func(vector); if (flag) { this.morphInsert.adjustVal = this.morphValue - num4; } DebugUtility.DrawAxis(vector, chainEndBone.rotation, Color.cyan, Color.cyan, Color.cyan, 0.0625f); if (this.morphValue >= 1f) { if (num4 >= 1f) { this.morphInsert.adjustVal = 0f; } } else if (this.morphValue <= 0f && num4 <= 0f) { this.morphInsert.adjustVal = 0f; } if (this.MorphInsert.isValueFixed) { this.morphValue = this.MorphInsert.fixedValue; } else { if (this.MorphInsert.isTimeClose && this.morphValue > num4 + this.morphInsert.adjustVal) { return; } this.morphValue = num4 + this.morphInsert.adjustVal; } } if (this.kupaType == AutoKupaCtrl.KupaType.Close) { this.isNotKupa = (this.morphValue <= 0f); if (this.isNotKupa) { this.kupaSpeed = -1f; } } } public bool IsKupaRangeIn(Vector3 position) { Vector3 lhs = position - this.MorphInsert.bone.position; Quaternion rotation = Quaternion.FromToRotation(Vector3.forward, this.MorphInsert.worldInsertAxis); Vector3 rhs = rotation * Vector3.up; Vector3 rhs2 = rotation * Vector3.right; float num = Mathf.Abs(Vector3.Dot(lhs, rhs)); float num2 = Mathf.Abs(Vector3.Dot(lhs, rhs2)); return num <= 0.05f && num2 <= 0.05f; } public void SetInsertParamFromScript(KagTagSupport tag_data) { this.MorphInsert.isValueFixed = tag_data.IsValid("kupafixed"); if (this.MorphInsert.isValueFixed) { this.MorphInsert.fixedValue = MathUtility.PercentageToRatio(tag_data.GetTagProperty("kupafixed").AsInteger(), false); } else { if (tag_data.IsValid("kupaspeed")) { this.MorphInsert.kupaSpeedIn = (this.MorphInsert.kupaSpeedOut = MathUtility.PercentageToRatio(tag_data.GetTagProperty("kupaspeed").AsInteger(), false)); } else { if (tag_data.IsValid("kupaspeedin")) { this.MorphInsert.kupaSpeedIn = MathUtility.PercentageToRatio(tag_data.GetTagProperty("kupaspeedin").AsInteger(), false); } if (tag_data.IsValid("kupaspeedout")) { this.MorphInsert.kupaSpeedOut = MathUtility.PercentageToRatio(tag_data.GetTagProperty("kupaspeedout").AsInteger(), false); } } this.morphValueMax = ((!tag_data.IsValid("kupamax")) ? 1f : MathUtility.PercentageToRatio(tag_data.GetTagProperty("kupamax").AsInteger(), false)); } this.MorphInsert.isTimeClose = tag_data.IsValid("timeclose"); if (this.MorphInsert.isTimeClose) { string[] array = tag_data.GetTagProperty("timeclose").AsString().Split(new char[] { ' ' }); string[] array2 = array; int i = 0; while (i < array2.Length) { string text = array2[i]; string text2 = text.Split(new char[] { '=' })[0]; float num = MathUtility.MillisecondToSecond(int.Parse(text.Split(new char[] { '=' })[1])); if (text2 != null) { if (!(text2 == "time")) { if (text2 == "wait") { this.MorphInsert.timeCloseParam.waitTime = num; } } else { this.MorphInsert.timeCloseParam.totalTime = num; } } IL_213: i++; continue; goto IL_213; } } else { this.MorphInsert.timeCloseParam.Reset(); } } public void SetKupaInsert(AutoKupaCtrl.InsertObjType insert, TBody tgt_body, Vector3 insert_axis) { Transform[] kupaInsertObjs = tgt_body.GetKupaInsertObjs(insert); if (kupaInsertObjs != null) { this.MorphInsert.boneBody = tgt_body; this.isUpdateTBody = (this.MorphInsert.boneBody == this.body); if (!this.isUpdateTBody) { if (tgt_body.fullBodyIK.isIKExec) { tgt_body.fullBodyIK.onPostSolverUpdate.Add(new Action(this.KupaUpdate), false); } else { tgt_body.onLateUpdateEnd.Add(new Action(this.KupaUpdate), false); } } this.SetKupaInsert(kupaInsertObjs, insert_axis); } } public void SetKupaInsertFromBgItem(string item_name, Vector3 insert_axis) { GameObject prefabFromBg = GameMain.Instance.BgMgr.GetPrefabFromBg(item_name); if (!prefabFromBg) { return; } Transform transform = prefabFromBg.transform.Find("Bone_insert1"); Transform[] chain_bones = UnityUtility.GetAllChildren(transform, true).ToArray(); this.SetKupaInsert(chain_bones, insert_axis); } public void SetKupaInsert(Transform[] chain_bones, Vector3 insert_axis) { this.SetKupaInsert(AutoKupaCtrl.KupaType.Open, chain_bones, insert_axis); } public void SetKupaInsert(AutoKupaCtrl.KupaType kupa_type, Transform[] chain_bones, Vector3 insert_axis) { this.movementType = AutoKupaCtrl.MovementType.Insert; this.isNotKupa = false; this.IsDoneSetUp = true; this.kupaType = kupa_type; this.MorphInsert.chainBones = chain_bones; this.MorphInsert.checkInsertAxis = insert_axis; this.MorphInsert.isInsert = false; if (this.kupaSpeed < 0f) { this.kupaSpeed = ((this.kupaType != AutoKupaCtrl.KupaType.Open) ? this.MorphInsert.kupaSpeedOut : this.MorphInsert.kupaSpeedIn); } } public void SetKupaTimer(AutoKupaCtrl.KupaType kupa_type, float kupa_time, float wait = 0f) { this.movementType = AutoKupaCtrl.MovementType.Timer; this.isNotKupa = false; this.IsDoneSetUp = true; this.kupaType = kupa_type; this.MorphTime.Reset(); this.MorphTime.waitTime = wait; this.MorphTime.totalTime = kupa_time; } public void StopKupa() { this.isNotKupa = true; } public void DoneStateReset() { this.IsDoneSetUp = false; this.isUpdateTBody = true; this.MorphInsert.isValueFixed = false; if (this.MorphInsert.boneBody) { this.MorphInsert.boneBody.fullBodyIK.onPostSolverUpdate.Remove(new Action(this.KupaUpdate)); this.MorphInsert.boneBody.onLateUpdateEnd.Remove(new Action(this.KupaUpdate)); } this.MorphInsert.boneBody = null; } public void Finish() { this.isNotKupa = true; this.IsDoneSetUp = false; this.MorphTime.Reset(); this.MorphInsert.isInsert = false; if (this.BodySkin != null && this.BodySkin.morph != null) { this.BodySkin.morph.FixBlendValues(); } } private const float KUPA_RANGE_MAX = 0.05f; public static readonly Dictionary InsertBoneMorphDic = new Dictionary { { "_IK_vagina", AutoKupaCtrl.MorphType.Vagina }, { "_IK_anal", AutoKupaCtrl.MorphType.Anal } }; public readonly TBody body; public readonly AutoKupaCtrl.MorphType morphType; public readonly string morphName; private bool IsDoneSetUp; [SerializeField] [Range(0f, 1f)] private float MorphValueMax = 1f; [Range(1f, 10f)] public float kupaSpeed = -1f; [SerializeField] private AutoKupaCtrl.TimerParam MorphTime = new AutoKupaCtrl.TimerParam(); [SerializeField] private AutoKupaCtrl.InsertParam MorphInsert = new AutoKupaCtrl.InsertParam(); public bool isUpdateTBody = true; public enum MorphType { Vagina, Anal, Kupa } public enum MovementType { Insert, Timer } public enum KupaType { Open, Close } public enum InsertObjType { Penis, Finger_R0, Finger_R1, Finger_R2, Finger_R3, Finger_R4, Finger_L0, Finger_L1, Finger_L2, Finger_L3, Finger_L4, HandItem_R, HandItem_L, BgItem } [Serializable] public class TimerParam { public float ratio { get { return (this.totalTime <= 0f) ? 1f : Mathf.Clamp01(Mathf.Max(this.curTime - this.waitTime, 0f) / this.totalTime); } } public void Reset() { this.curTime = 0f; this.waitTime = 0f; } public float curTime; public float totalTime; public float waitTime; } [Serializable] public class InsertParam { public Transform chainStartBone { get { return (this.chainBones == null || this.chainBones.Length == 0) ? null : this.chainBones[0]; } } public Transform chainEndBone { get { return (this.chainBones == null || this.chainBones.Length == 0) ? null : this.chainBones[this.chainBones.Length - 1]; } } public Vector3 worldInsertAxis { get { return this.bone.rotation * this.checkInsertAxis; } } public TBody boneBody; public Transform[] chainBones; public Transform bone; public Vector3 checkInsertAxis; [ReadOnly] public bool isInsert; [Range(1f, 10f)] public float kupaSpeedIn = 1f; [Range(1f, 10f)] public float kupaSpeedOut = 1f; [ReadOnly] public float adjustVal; [HideInInspector] public float lastInsertValue; public bool isValueFixed; public float fixedValue = 1f; public bool isTimeClose; public AutoKupaCtrl.TimerParam timeCloseParam = new AutoKupaCtrl.TimerParam(); } }