Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MwSkinAdditions v1.0.3
MwSkinAdditions.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using EntityStates.Missions.BrotherEncounter; using HG; using IL.RoR2; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using On.EntityStates; using On.EntityStates.Missions.BrotherEncounter; using On.RoR2; using R2API.Networking; using R2API.Networking.Interfaces; using RoR2; using RoR2.Audio; using RoR2.ContentManagement; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MwSkinAdditions")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a643375e8062856baf9476ce1f7307d98b85e58b")] [assembly: AssemblyProduct("MwSkinAdditions")] [assembly: AssemblyTitle("MwSkinAdditions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MwSkinAdditions { public class BlendShapeAnimation { public string meshName; public string blendShapeName; public int feature; public int priority; public float fadeInDuration; public float holdDuration; public float fadeOutDuration; public bool blockBlinking; public BlendShapeAnimation(string meshName, string blendShapeName, int feature, int priority, float fadeInDuration, float holdDuration, float fadeOutDuration, bool blockBlinking = false) { this.meshName = meshName; this.blendShapeName = blendShapeName; this.feature = feature; this.priority = priority; this.fadeInDuration = fadeInDuration; this.holdDuration = holdDuration; this.fadeOutDuration = fadeOutDuration; this.blockBlinking = blockBlinking; } } public class BlinkBlendShapeAnimation : BlendShapeAnimation { public BlinkBlendShapeAnimation(string meshName, string blendShapeName, int feature = -1, int priority = 0, float fadeInDuration = 0.1f, float holdDuration = 0f, float fadeOutDuration = 0.1f, bool blockBlinking = false) : base(meshName, blendShapeName, feature, priority, fadeInDuration, holdDuration, fadeOutDuration, blockBlinking) { } } public class BoneTransformation { public string armaturePath; public Vector3 localScale; public Vector3 position; public string relativeBonePath; public BoneTransformation(string armaturePath, Vector3 localScale, Vector3 position, string relativeBonePath = null) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) this.armaturePath = armaturePath; this.localScale = localScale; this.position = position; this.relativeBonePath = relativeBonePath; } } internal class ContentPacks : IContentPackProvider { [CompilerGenerated] private sealed class <FinalizeAsync>d__9 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public FinalizeAsyncArgs args; public ContentPacks <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FinalizeAsync>d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; args.ReportProgress(1f); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <GenerateContentPackAsync>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GetContentPackAsyncArgs args; public ContentPacks <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GenerateContentPackAsync>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; ContentPack.Copy(<>4__this.contentPack, args.output); args.ReportProgress(1f); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadStaticContentAsync>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public LoadStaticContentAsyncArgs args; public ContentPacks <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadStaticContentAsync>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; <>4__this.contentPack.identifier = <>4__this.identifier; <>4__this.contentPack.networkSoundEventDefs.Add(networkSoundEventDefs.ToArray()); args.ReportProgress(1f); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal ContentPack contentPack = new ContentPack(); public static List<NetworkSoundEventDef> networkSoundEventDefs = new List<NetworkSoundEventDef>(); public string identifier => "mwmw.MwSkinAdditions"; internal static NetworkSoundEventDef CreateAndAddNetworkSoundEventDef(string eventName) { NetworkSoundEventDef val = ScriptableObject.CreateInstance<NetworkSoundEventDef>(); val.akId = AkSoundEngine.GetIDFromString(eventName); val.eventName = eventName; networkSoundEventDefs.Add(val); return val; } public void Initialize() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown ContentManager.collectContentPackProviders += new CollectContentPackProvidersDelegate(ContentManager_collectContentPackProviders); } private void ContentManager_collectContentPackProviders(AddContentPackProviderDelegate addContentPackProvider) { addContentPackProvider.Invoke((IContentPackProvider)(object)this); } [IteratorStateMachine(typeof(<LoadStaticContentAsync>d__7))] public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadStaticContentAsync>d__7(0) { <>4__this = this, args = args }; } [IteratorStateMachine(typeof(<GenerateContentPackAsync>d__8))] public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GenerateContentPackAsync>d__8(0) { <>4__this = this, args = args }; } [IteratorStateMachine(typeof(<FinalizeAsync>d__9))] public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FinalizeAsync>d__9(0) { <>4__this = this, args = args }; } } public class EventSub { public SkinDef skinDef; public BoneTransformation[] boneTransformations; public ExtraObject[] extraObjects; public bool useAnimations = false; public BlendShapeAnimation[] blinkAnimations; public IdleAnimation[] conditionalIdleAnimations; public VoiceGroup[] voiceGroups; public bool transformInCSS = true; public static Action<GameObject> DifferentSkinAppliedGlobal; public Action<GameObject> SkinAppliedLobby; public Action<GameObject> SkinAppliedRun; public Action<GameObject, DamageReport> TakeDamage; public Action<GameObject> Death; public Action<GameObject> DefeatBossGroup; public Action<GameObject> LeavePod; public Action<GameObject> UsePrimary; public Action<GameObject> UseSecondary; public Action<GameObject> UseUtility; public Action<GameObject> UseSpecial; public Action<GameObject> ShrineSuccess; public Action<GameObject> ShrineFailure; public Action<GameObject> TeleporterStart; public Action<GameObject> TeleporterEnd; public Action<GameObject> BearDamageBlock; public Action<GameObject> LevelUp; public Action<GameObject> MithrixDefeat; public Action<GameObject> UseEquipment; public Action<GameObject, float> Heal; public Action<GameObject> Jump; public Action<GameObject> LeaveStage; public Action<GameObject> Idle; public Action<GameObject, ItemIndex> GetItem; public Action<GameObject> HoldoutZoneCharged; [Obsolete("Provide an EventSubOptions object instead.")] public EventSub(SkinDef skinDef, BoneTransformation[] boneTransformations = null, ExtraObject[] extraObjects = null, bool useAnimations = false, BlendShapeAnimation[] blinkAnimations = null, IdleAnimation[] conditionalIdleAnimations = null, VoiceGroup[] voiceGroups = null) { this.skinDef = skinDef; this.boneTransformations = boneTransformations; this.extraObjects = extraObjects; this.useAnimations = useAnimations; this.blinkAnimations = blinkAnimations; this.conditionalIdleAnimations = conditionalIdleAnimations; this.voiceGroups = voiceGroups; } public EventSub(SkinDef skinDef, EventSubOptions eventSubOptions) { if (eventSubOptions == null) { eventSubOptions = new EventSubOptions(); } this.skinDef = skinDef; boneTransformations = eventSubOptions.boneTransformations; extraObjects = eventSubOptions.extraObjects; useAnimations = eventSubOptions.useAnimations; blinkAnimations = eventSubOptions.blinkAnimations; conditionalIdleAnimations = eventSubOptions.conditionalIdleAnimations; voiceGroups = eventSubOptions.voiceGroups; transformInCSS = eventSubOptions.transformInCSS; } public void Init() { SkinEvents.SubscribeEventSkin(this); if (boneTransformations != null) { SubscribeTransformEvents(); } if (extraObjects != null) { SubscribeExtraObjectEvents(); } if (useAnimations) { SubscribeAnimationEvents(); } if (voiceGroups != null) { SubscribeVoiceEvents(); } } private void SubscribeTransformEvents() { SkinAppliedRun = (Action<GameObject>)Delegate.Combine(SkinAppliedRun, new Action<GameObject>(AddTransformController)); SkinAppliedLobby = (Action<GameObject>)Delegate.Combine(SkinAppliedLobby, new Action<GameObject>(AddTransformController)); } private void AddTransformController(GameObject body) { if (!((Object)(object)Run.instance == (Object)null) || transformInCSS) { TransformController transformController = body.GetComponent<TransformController>(); if ((Object)(object)transformController == (Object)null || transformController.beingDeleted) { transformController = body.AddComponent<TransformController>(); } transformController.Init(this); } } private void SubscribeExtraObjectEvents() { SkinAppliedRun = (Action<GameObject>)Delegate.Combine(SkinAppliedRun, new Action<GameObject>(AddExtraObjects)); SkinAppliedLobby = (Action<GameObject>)Delegate.Combine(SkinAppliedLobby, new Action<GameObject>(AddExtraObjects)); } private void AddExtraObjects(GameObject body) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Transform transform = SkinEvents.GetModelFromEventBody(body).transform; ExtraObjectController extraObjectController = body.AddComponent<ExtraObjectController>(); ExtraObject[] array = extraObjects; foreach (ExtraObject extraObject in array) { GameObject val = Object.Instantiate<GameObject>(extraObject.prefab); val.transform.parent = transform.Find(extraObject.armatureParentPath); val.transform.localPosition = extraObject.localPosition; val.transform.localEulerAngles = extraObject.localEulerAngles; val.transform.localScale = extraObject.localScale; extraObjectController.extraObjs.Add(val); } } private void SubscribeAnimationEvents() { SkinAppliedRun = (Action<GameObject>)Delegate.Combine(SkinAppliedRun, new Action<GameObject>(AddExpressionController)); SkinAppliedLobby = (Action<GameObject>)Delegate.Combine(SkinAppliedLobby, new Action<GameObject>(AddExpressionController)); } private void AddExpressionController(GameObject body) { ExpressionController expressionController = body.GetComponent<ExpressionController>(); if ((Object)(object)expressionController == (Object)null) { expressionController = body.AddComponent<ExpressionController>(); } expressionController.Init(this); } private void SubscribeVoiceEvents() { SkinAppliedRun = (Action<GameObject>)Delegate.Combine(SkinAppliedRun, new Action<GameObject>(AddVoiceController)); SkinAppliedLobby = (Action<GameObject>)Delegate.Combine(SkinAppliedLobby, new Action<GameObject>(AddVoiceController)); } private void AddVoiceController(GameObject body) { VoiceController voiceController = body.GetComponent<VoiceController>(); if ((Object)(object)voiceController == (Object)null) { voiceController = body.AddComponent<VoiceController>(); } voiceController.Init(this); } } public class EventSubOptions { public BoneTransformation[] boneTransformations = null; public ExtraObject[] extraObjects = null; public bool useAnimations = false; public BlendShapeAnimation[] blinkAnimations = null; public IdleAnimation[] conditionalIdleAnimations = null; public VoiceGroup[] voiceGroups = null; public bool transformInCSS = true; } public class ExpressionController : MonoBehaviour { private class ExpressionState { public Coroutine coroutine; public BlendShapeAnimation animation; public SkinnedMeshRenderer skinnedMeshRenderer; public bool finished; } [CompilerGenerated] private sealed class <BlendToZero>d__21 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ExpressionState expressionState; public ExpressionController <>4__this; private int <index>5__1; private float <startWeight>5__2; private float <stopwatch>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <BlendToZero>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <index>5__1 = <>4__this.GetBlendShapeIndex(expressionState.animation, expressionState.skinnedMeshRenderer); <startWeight>5__2 = expressionState.skinnedMeshRenderer.GetBlendShapeWeight(<index>5__1); <stopwatch>5__3 = 0f; break; case 1: <>1__state = -1; break; } if (<stopwatch>5__3 < expressionState.animation.fadeOutDuration) { <stopwatch>5__3 += Time.deltaTime; expressionState.skinnedMeshRenderer.SetBlendShapeWeight(<index>5__1, Mathf.Lerp(<startWeight>5__2, 0f, <stopwatch>5__3 / expressionState.animation.fadeOutDuration)); <>2__current = null; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ExpressionRoutine>d__18 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BlendShapeAnimation animation; public SkinnedMeshRenderer renderer; public ExpressionState expressionState; public ExpressionController <>4__this; private float <stopwatch>5__1; private int <index>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExpressionRoutine>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <stopwatch>5__1 = 0f; <>4__this.featureActive[animation.feature] = true; <index>5__2 = <>4__this.GetBlendShapeIndex(animation, renderer); goto IL_00df; case 1: <>1__state = -1; goto IL_00df; case 2: <>1__state = -1; <stopwatch>5__1 = 0f; break; case 3: { <>1__state = -1; break; } IL_00df: if (<stopwatch>5__1 < animation.fadeInDuration) { <stopwatch>5__1 += Time.deltaTime; renderer.SetBlendShapeWeight(<index>5__2, Mathf.Lerp(0f, 100f, <stopwatch>5__1 / animation.fadeInDuration)); <>2__current = null; <>1__state = 1; return true; } renderer.SetBlendShapeWeight(<index>5__2, 100f); <>2__current = (object)new WaitForSeconds(animation.holdDuration); <>1__state = 2; return true; } if (<stopwatch>5__1 < animation.fadeOutDuration) { <stopwatch>5__1 += Time.deltaTime; renderer.SetBlendShapeWeight(<index>5__2, Mathf.Lerp(100f, 0f, <stopwatch>5__1 / animation.fadeOutDuration)); <>2__current = null; <>1__state = 3; return true; } renderer.SetBlendShapeWeight(<index>5__2, 0f); <>4__this.featureActive[animation.feature] = false; if (animation.blockBlinking) { <>4__this.blinkStoppers--; } expressionState.finished = true; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private EventSub eventSub; private CharacterBody cachedCharacterBody; private Dictionary<string, SkinnedMeshRenderer> cachedRenderers = new Dictionary<string, SkinnedMeshRenderer>(); private Dictionary<string, int> cachedBlendShapes = new Dictionary<string, int>(); private Dictionary<int, ExpressionState> featureStates = new Dictionary<int, ExpressionState>(); private Dictionary<int, bool> featureActive = new Dictionary<int, bool>(); public bool inDeathState; private float blinkInterval; private float blinkStopwatch; private bool doubleBlink; private int blinkStoppers; public CharacterBody characterBody { get { if ((Object)(object)cachedCharacterBody != (Object)null) { return cachedCharacterBody; } cachedCharacterBody = ((Component)this).GetComponent<CharacterBody>(); return cachedCharacterBody; } } public void Init(EventSub eventSub) { this.eventSub = eventSub; eventSub.Death = (Action<GameObject>)Delegate.Combine(eventSub.Death, (Action<GameObject>)delegate { inDeathState = true; }); } public void TryPlayAnimation(BlendShapeAnimation animation) { SkinnedMeshRenderer skinnedMeshRenderer = GetSkinnedMeshRenderer(animation.meshName); if ((Object)(object)skinnedMeshRenderer != (Object)null) { TrySetExpressionRoutine(animation, skinnedMeshRenderer); } } private SkinnedMeshRenderer GetSkinnedMeshRenderer(string meshName) { if (cachedRenderers.ContainsKey(meshName)) { SkinnedMeshRenderer val = cachedRenderers[meshName]; if (val != null) { return val; } } GameObject modelFromEventBody = SkinEvents.GetModelFromEventBody(((Component)this).gameObject); object obj; if (modelFromEventBody == null) { obj = null; } else { Transform obj2 = modelFromEventBody.transform.Find(meshName); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<SkinnedMeshRenderer>() : null); } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)obj; cachedRenderers[meshName] = val2; return val2; } private void TrySetExpressionRoutine(BlendShapeAnimation animation, SkinnedMeshRenderer renderer) { ExpressionState featureState = GetFeatureState(animation.feature); if (featureState != null && animation.priority > featureState.animation.priority) { CancelExpression(featureState); } if (!GetFeatureActive(animation.feature)) { ExpressionState expressionState = new ExpressionState { animation = animation, skinnedMeshRenderer = renderer }; expressionState.coroutine = ((MonoBehaviour)this).StartCoroutine(ExpressionRoutine(animation, renderer, expressionState)); featureStates[animation.feature] = expressionState; if (animation.blockBlinking) { blinkStoppers++; } } } [IteratorStateMachine(typeof(<ExpressionRoutine>d__18))] private IEnumerator ExpressionRoutine(BlendShapeAnimation animation, SkinnedMeshRenderer renderer, ExpressionState expressionState) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExpressionRoutine>d__18(0) { <>4__this = this, animation = animation, renderer = renderer, expressionState = expressionState }; } public void CancelCurrentExpressions() { foreach (ExpressionState value in featureStates.Values) { if (value != null) { CancelExpression(value); } } } private void CancelExpression(ExpressionState expressionState) { ((MonoBehaviour)this).StopCoroutine(expressionState.coroutine); featureActive[expressionState.animation.feature] = false; ((MonoBehaviour)this).StartCoroutine(BlendToZero(expressionState)); if (!expressionState.finished && expressionState.animation.blockBlinking) { blinkStoppers--; expressionState.finished = true; } } [IteratorStateMachine(typeof(<BlendToZero>d__21))] private IEnumerator BlendToZero(ExpressionState expressionState) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <BlendToZero>d__21(0) { <>4__this = this, expressionState = expressionState }; } private ExpressionState GetFeatureState(int feature) { if (featureStates.ContainsKey(feature)) { return featureStates[feature]; } return null; } private bool GetFeatureActive(int feature) { if (featureActive.ContainsKey(feature)) { return featureActive[feature]; } return false; } private int GetBlendShapeIndex(BlendShapeAnimation animation, SkinnedMeshRenderer skinnedMeshRenderer) { if (cachedBlendShapes.ContainsKey(animation.blendShapeName)) { return cachedBlendShapes[animation.blendShapeName]; } int blendShapeIndex = skinnedMeshRenderer.sharedMesh.GetBlendShapeIndex(animation.blendShapeName); cachedBlendShapes[animation.blendShapeName] = blendShapeIndex; return blendShapeIndex; } private void Update() { if (eventSub.blinkAnimations != null && blinkStoppers <= 0) { BlinkUpdate(); } if (eventSub.conditionalIdleAnimations != null) { IdleUpdate(); } } private void BlinkUpdate() { blinkStopwatch += Time.deltaTime; if (!(blinkStopwatch >= blinkInterval)) { return; } if (!inDeathState) { BlendShapeAnimation[] blinkAnimations = eventSub.blinkAnimations; foreach (BlendShapeAnimation animation in blinkAnimations) { TryPlayAnimation(animation); } if (doubleBlink) { doubleBlink = false; } else if (Random.value <= 0.1f) { doubleBlink = true; } } else { doubleBlink = false; } blinkStopwatch = 0f; if (doubleBlink) { blinkInterval = 0.3f; } else { blinkInterval = Random.Range(3f, 8f); } } private void IdleUpdate() { IdleAnimation[] conditionalIdleAnimations = eventSub.conditionalIdleAnimations; foreach (IdleAnimation idleAnimation in conditionalIdleAnimations) { if (idleAnimation == null || idleAnimation.condition == null) { continue; } if (idleAnimation.condition(this)) { BlendShapeAnimation[] animations = idleAnimation.animations; foreach (BlendShapeAnimation animation in animations) { TryPlayAnimation(animation); } } else { if (!idleAnimation.cancelOnConditionFalse) { continue; } BlendShapeAnimation[] animations2 = idleAnimation.animations; foreach (BlendShapeAnimation blendShapeAnimation in animations2) { ExpressionState featureState = GetFeatureState(blendShapeAnimation.feature); if (GetFeatureActive(blendShapeAnimation.feature) && featureState?.animation == blendShapeAnimation) { CancelExpression(featureState); } } } } } } public class ExtraObject { public GameObject prefab; public string armatureParentPath; public Vector3 localScale; public Vector3 localPosition; public Vector3 localEulerAngles; public ExtraObject(GameObject prefab, string armatureParentPath, Vector3 localScale, Vector3 localPosition, Vector3 localEulerAngles) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) this.prefab = prefab; this.armatureParentPath = armatureParentPath; this.localScale = localScale; this.localPosition = localPosition; this.localEulerAngles = localEulerAngles; } } public class ExtraObjectController : MonoBehaviour { public List<GameObject> extraObjs; public void Awake() { extraObjs = new List<GameObject>(); } } public class IdleAnimation { public BlendShapeAnimation[] animations; public Func<ExpressionController, bool> condition; public bool cancelOnConditionFalse; public IdleAnimation(BlendShapeAnimation[] animations, Func<ExpressionController, bool> condition, bool cancelOnConditionFalse = true) { this.animations = animations; this.condition = condition; this.cancelOnConditionFalse = cancelOnConditionFalse; } } internal static class Log { private static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("mwmw.MwSkinAdditions", "MwSkinAdditions", "1.0.3")] public class MwSkinAdditions : BaseUnityPlugin { public const string PluginGUID = "mwmw.MwSkinAdditions"; public const string PluginAuthor = "mwmw"; public const string PluginName = "MwSkinAdditions"; public const string PluginVersion = "1.0.3"; public static PluginInfo pluginInfo; public static MwSkinAdditions instance; public void Awake() { instance = this; pluginInfo = ((BaseUnityPlugin)this).Info; Log.Init(((BaseUnityPlugin)this).Logger); SkinEvents.Init(); RoR2Application.onStart = (Action)Delegate.Combine(RoR2Application.onStart, (Action)delegate { new ContentPacks().Initialize(); }); } } public static class MwUtils { [CompilerGenerated] private sealed class <ExecuteWhenNearPosition>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Action action; public GameObject gameObject; public Vector3 position; public float maxWait; private float <stopwatch>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ExecuteWhenNearPosition>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <stopwatch>5__1 = 0f; break; case 1: <>1__state = -1; break; } if (Vector3.Distance(gameObject.transform.position, position) > 0.5f && <stopwatch>5__1 < maxWait) { <stopwatch>5__1 += Time.deltaTime; <>2__current = null; <>1__state = 1; return true; } action?.Invoke(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static Random rand = new Random(); public static object RandomChoices(IEnumerable<object> choices, IEnumerable<float> weights) { List<float> list = new List<float>(); float num = 0f; foreach (float weight in weights) { num += weight; list.Add(num); } float num2 = (float)rand.NextDouble() * num; int num3 = 0; foreach (object choice in choices) { if (num2 <= list[num3]) { return choice; } num3++; } Log.Warning("RandomChoices: Couldn't make a choice - returning null!"); return null; } public static object RandomChoice(IEnumerable<object> choices) { IList<object> list = (choices as IList<object>) ?? choices.ToList(); if (list.Count > 0) { return list[rand.Next(list.Count)]; } Log.Warning("RandomChoice: Got passed an empty enumerable - returning null!"); return null; } public static object RandomChoice(object[] choices) { if (choices.Length != 0) { return choices[rand.Next(choices.Length)]; } Log.Warning("RandomChoice: Got passed an empty enumerable - returning null!"); return null; } [IteratorStateMachine(typeof(<ExecuteWhenNearPosition>d__4))] public static IEnumerator ExecuteWhenNearPosition(Action action, GameObject gameObject, Vector3 position, float maxWait = 1f) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ExecuteWhenNearPosition>d__4(0) { action = action, gameObject = gameObject, position = position, maxWait = maxWait }; } } public static class SkinEvents { public class SyncGetItem : INetMessage, ISerializableObject { private NetworkInstanceId netInstanceId; private int itemIndex; public SyncGetItem() { } public SyncGetItem(NetworkInstanceId netInstanceId, int itemIndex) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) this.netInstanceId = netInstanceId; this.itemIndex = itemIndex; } public void Serialize(NetworkWriter writer) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) writer.Write(netInstanceId); writer.Write(itemIndex); } public void Deserialize(NetworkReader reader) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) netInstanceId = reader.ReadNetworkId(); itemIndex = reader.ReadInt32(); } public void OnReceived() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject val = Util.FindNetworkObject(netInstanceId); if ((Object)(object)val != (Object)null) { InvokeGetItem(val, itemIndex); } } } public class SyncUseShrine : INetMessage, ISerializableObject { private NetworkInstanceId netInstanceId; private bool success; public SyncUseShrine() { } public SyncUseShrine(NetworkInstanceId netInstanceId, bool success) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) this.netInstanceId = netInstanceId; this.success = success; } public void Serialize(NetworkWriter writer) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) writer.Write(netInstanceId); writer.Write(success); } public void Deserialize(NetworkReader reader) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) netInstanceId = reader.ReadNetworkId(); success = reader.ReadBoolean(); } public void OnReceived() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject val = Util.FindNetworkObject(netInstanceId); if ((Object)(object)val != (Object)null) { InvokeUseShrine(val, success); } } } public class SyncHoldoutZoneCharged : INetMessage, ISerializableObject { public void Serialize(NetworkWriter writer) { } public void Deserialize(NetworkReader reader) { } public void OnReceived() { InvokeHoldoutZoneCharged(); } } [CompilerGenerated] private static class <>O { public static hook_ApplySkinAsync <0>__OnSkinAppliedBody; public static hook_OnInteractionBegin <1>__OnTeleporterStart; public static hook_OnDeathStart <2>__OnDeath; public static hook_EjectPassenger_GameObject <3>__OnLeavePod; public static hook_OnSkillActivated <4>__OnSkillActivated; public static hook_AddShrineStack <5>__OnChanceShrineInteract; public static Manipulator <6>__OnPickupAttemptGrant; public static Manipulator <7>__OnBearDamageBlock; public static Action<BossGroup> <8>__OnDefeatBossGroup; public static Action<TeleporterInteraction> <9>__OnTeleporterEnd; public static Action<DamageReport> <10>__OnTakeDamage; public static Action<CharacterBody> <11>__OnLevelUp; public static hook_OnEnter <12>__OnMithrixDefeat; public static Action<EquipmentSlot, EquipmentIndex> <13>__OnUseEquipment; public static Action<HealthComponent, float, ProcChainMask> <14>__OnHeal; public static hook_ApplyJumpVelocity <15>__OnJump; public static hook_Begin <16>__OnLeaveStage; public static hook_Update <17>__OnBodyUpdate; public static Action<GameObject> <18>__RemoveTransformController; public static Action<GameObject> <19>__RemoveExtraObjects; public static Action<GameObject> <20>__RemoveVoiceController; public static Action<GameObject> <21>__RemoveExpressionController; } [CompilerGenerated] private sealed class <HoldBodyFromIdleUpdate>d__32 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CharacterBody body; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HoldBodyFromIdleUpdate>d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; holdOffIdleInvocation?.Add(body); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; holdOffIdleInvocation?.Remove(body); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <OnSkinAppliedBody>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public orig_ApplySkinAsync orig; public ModelSkinController self; public int skinIndex; public AsyncReferenceHandleUnloadType unloadType; private GameObject <bodyObject>5__1; private EventSub <bodyEventSub>5__2; private SkinDef <skinDef>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <OnSkinAppliedBody>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <bodyObject>5__1 = null; <bodyEventSub>5__2 = null; <skinDef>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = orig.Invoke(self, skinIndex, unloadType); <>1__state = 1; return true; case 1: { <>1__state = -1; ModelSkinController obj = self; object obj2; if (obj == null) { obj2 = null; } else { CharacterModel characterModel = obj.characterModel; if (characterModel == null) { obj2 = null; } else { CharacterBody body = characterModel.body; obj2 = ((body != null) ? ((Component)body).gameObject : null); } } <bodyObject>5__1 = (GameObject)obj2; <bodyEventSub>5__2 = null; if ((Object)(object)<bodyObject>5__1 != (Object)null) { <bodyEventSub>5__2 = GetEventSubFromBody(<bodyObject>5__1); } if ((Object)(object)<bodyObject>5__1 != (Object)null && <bodyEventSub>5__2 != null) { <bodyEventSub>5__2.SkinAppliedRun?.Invoke(<bodyObject>5__1); goto IL_01c6; } if ((Object)(object)<bodyObject>5__1 == (Object)null) { <skinDef>5__3 = ArrayUtils.GetSafe<SkinDef>(self.skins, self.currentSkinIndex); if (<skinDef>5__3 != null && skinDefToEventSub.ContainsKey(<skinDef>5__3)) { <bodyEventSub>5__2 = GetEventSubFromSkinDef(<skinDef>5__3); <bodyEventSub>5__2.SkinAppliedLobby?.Invoke(((Component)self).gameObject); goto IL_01bf; } } if ((Object)(object)<bodyObject>5__1 != (Object)null) { EventSub.DifferentSkinAppliedGlobal?.Invoke(<bodyObject>5__1); } else { EventSub.DifferentSkinAppliedGlobal?.Invoke(((Component)self).gameObject); } goto IL_01bf; } IL_01c6: return false; IL_01bf: <skinDef>5__3 = null; goto IL_01c6; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Dictionary<SkinDef, EventSub> skinDefToEventSub = new Dictionary<SkinDef, EventSub>(); public static HashSet<CharacterBody> holdOffIdleInvocation = new HashSet<CharacterBody>(); public static void Init() { SubscribeGlobalEvents(); SubscribeGameEvents(); } public static void SubscribeEventSkin(EventSub eventSkin) { skinDefToEventSub.Add(eventSkin.skinDef, eventSkin); } private static void SubscribeGameEvents() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown object obj = <>O.<0>__OnSkinAppliedBody; if (obj == null) { hook_ApplySkinAsync val = OnSkinAppliedBody; <>O.<0>__OnSkinAppliedBody = val; obj = (object)val; } ModelSkinController.ApplySkinAsync += (hook_ApplySkinAsync)obj; object obj2 = <>O.<1>__OnTeleporterStart; if (obj2 == null) { hook_OnInteractionBegin val2 = OnTeleporterStart; <>O.<1>__OnTeleporterStart = val2; obj2 = (object)val2; } TeleporterInteraction.OnInteractionBegin += (hook_OnInteractionBegin)obj2; object obj3 = <>O.<2>__OnDeath; if (obj3 == null) { hook_OnDeathStart val3 = OnDeath; <>O.<2>__OnDeath = val3; obj3 = (object)val3; } CharacterBody.OnDeathStart += (hook_OnDeathStart)obj3; object obj4 = <>O.<3>__OnLeavePod; if (obj4 == null) { hook_EjectPassenger_GameObject val4 = OnLeavePod; <>O.<3>__OnLeavePod = val4; obj4 = (object)val4; } VehicleSeat.EjectPassenger_GameObject += (hook_EjectPassenger_GameObject)obj4; object obj5 = <>O.<4>__OnSkillActivated; if (obj5 == null) { hook_OnSkillActivated val5 = OnSkillActivated; <>O.<4>__OnSkillActivated = val5; obj5 = (object)val5; } CharacterBody.OnSkillActivated += (hook_OnSkillActivated)obj5; object obj6 = <>O.<5>__OnChanceShrineInteract; if (obj6 == null) { hook_AddShrineStack val6 = OnChanceShrineInteract; <>O.<5>__OnChanceShrineInteract = val6; obj6 = (object)val6; } ShrineChanceBehavior.AddShrineStack += (hook_AddShrineStack)obj6; object obj7 = <>O.<6>__OnPickupAttemptGrant; if (obj7 == null) { Manipulator val7 = OnPickupAttemptGrant; <>O.<6>__OnPickupAttemptGrant = val7; obj7 = (object)val7; } GenericPickupController.AttemptGrant += (Manipulator)obj7; object obj8 = <>O.<7>__OnBearDamageBlock; if (obj8 == null) { Manipulator val8 = OnBearDamageBlock; <>O.<7>__OnBearDamageBlock = val8; obj8 = (object)val8; } HealthComponent.TakeDamageProcess += (Manipulator)obj8; BossGroup.onBossGroupDefeatedServer += OnDefeatBossGroup; TeleporterInteraction.onTeleporterChargedGlobal += OnTeleporterEnd; GlobalEventManager.onServerDamageDealt += OnTakeDamage; GlobalEventManager.onCharacterLevelUp += OnLevelUp; object obj9 = <>O.<12>__OnMithrixDefeat; if (obj9 == null) { hook_OnEnter val9 = OnMithrixDefeat; <>O.<12>__OnMithrixDefeat = val9; obj9 = (object)val9; } EncounterFinished.OnEnter += (hook_OnEnter)obj9; EquipmentSlot.onServerEquipmentActivated += OnUseEquipment; HealthComponent.onCharacterHealServer += OnHeal; object obj10 = <>O.<15>__OnJump; if (obj10 == null) { hook_ApplyJumpVelocity val10 = OnJump; <>O.<15>__OnJump = val10; obj10 = (object)val10; } GenericCharacterMain.ApplyJumpVelocity += (hook_ApplyJumpVelocity)obj10; object obj11 = <>O.<16>__OnLeaveStage; if (obj11 == null) { hook_Begin val11 = OnLeaveStage; <>O.<16>__OnLeaveStage = val11; obj11 = (object)val11; } SceneExitController.Begin += (hook_Begin)obj11; object obj12 = <>O.<17>__OnBodyUpdate; if (obj12 == null) { hook_Update val12 = OnBodyUpdate; <>O.<17>__OnBodyUpdate = val12; obj12 = (object)val12; } CharacterBody.Update += (hook_Update)obj12; } public static void SubscribeGlobalEvents() { EventSub.DifferentSkinAppliedGlobal = (Action<GameObject>)Delegate.Combine(EventSub.DifferentSkinAppliedGlobal, new Action<GameObject>(RemoveTransformController)); EventSub.DifferentSkinAppliedGlobal = (Action<GameObject>)Delegate.Combine(EventSub.DifferentSkinAppliedGlobal, new Action<GameObject>(RemoveExtraObjects)); EventSub.DifferentSkinAppliedGlobal = (Action<GameObject>)Delegate.Combine(EventSub.DifferentSkinAppliedGlobal, new Action<GameObject>(RemoveVoiceController)); EventSub.DifferentSkinAppliedGlobal = (Action<GameObject>)Delegate.Combine(EventSub.DifferentSkinAppliedGlobal, new Action<GameObject>(RemoveExpressionController)); } public static EventSub GetEventSubFromBody(GameObject body) { try { SkinDef skinDef = SkinCatalog.FindCurrentSkinDefForBodyInstance(body); return GetEventSubFromSkinDef(skinDef); } catch (NullReferenceException) { Log.Error("GetEventSubFromBody NRE! Returning null..."); return null; } } public static EventSub GetEventSubFromSkinDef(SkinDef skinDef) { if ((Object)(object)skinDef == (Object)null || !skinDefToEventSub.ContainsKey(skinDef)) { return null; } return skinDefToEventSub[skinDef]; } [IteratorStateMachine(typeof(<OnSkinAppliedBody>d__8))] private static IEnumerator OnSkinAppliedBody(orig_ApplySkinAsync orig, ModelSkinController self, int skinIndex, AsyncReferenceHandleUnloadType unloadType) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <OnSkinAppliedBody>d__8(0) { orig = orig, self = self, skinIndex = skinIndex, unloadType = unloadType }; } private static void OnTeleporterStart(orig_OnInteractionBegin orig, TeleporterInteraction self, Interactor activator) { orig.Invoke(self, activator); TeleporterInteraction instance = TeleporterInteraction.instance; if (instance != null && !instance.isCharged) { GetEventSubFromBody(((Component)activator).gameObject)?.TeleporterStart?.Invoke(((Component)activator).gameObject); } } private static void OnDeath(orig_OnDeathStart orig, CharacterBody self) { orig.Invoke(self); GetEventSubFromBody(((Component)self).gameObject)?.Death?.Invoke(((Component)self).gameObject); } private static void OnLeavePod(orig_EjectPassenger_GameObject orig, VehicleSeat self, GameObject body) { orig.Invoke(self, body); if (self.isSurvivorPod) { GetEventSubFromBody(body)?.LeavePod?.Invoke(body); } } private static void OnSkillActivated(orig_OnSkillActivated orig, CharacterBody self, GenericSkill skill) { orig.Invoke(self, skill); EventSub eventSubFromBody = GetEventSubFromBody(((Component)self).gameObject); if (eventSubFromBody != null) { if ((Object)(object)skill == (Object)(object)self.skillLocator.primary) { eventSubFromBody.UsePrimary?.Invoke(((Component)self).gameObject); } else if ((Object)(object)skill == (Object)(object)self.skillLocator.secondary) { eventSubFromBody.UseSecondary?.Invoke(((Component)self).gameObject); } else if ((Object)(object)skill == (Object)(object)self.skillLocator.utility) { eventSubFromBody.UseUtility?.Invoke(((Component)self).gameObject); } else if ((Object)(object)skill == (Object)(object)self.skillLocator.special) { eventSubFromBody.UseSpecial?.Invoke(((Component)self).gameObject); } } } private static void OnChanceShrineInteract(orig_AddShrineStack orig, ShrineChanceBehavior self, Interactor activator) { int successfulPurchaseCount = self.successfulPurchaseCount; orig.Invoke(self, activator); EventSub eventSubFromBody = GetEventSubFromBody(((Component)self).gameObject); if (eventSubFromBody != null) { if (successfulPurchaseCount < self.successfulPurchaseCount) { eventSubFromBody.ShrineSuccess?.Invoke(((Component)activator).gameObject); } else { eventSubFromBody.ShrineFailure?.Invoke(((Component)activator).gameObject); } } } private static void OnBearDamageBlock(ILContext il) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) Action<HealthComponent> action = delegate(HealthComponent healthComponent) { GetEventSubFromBody(((Component)healthComponent.body).gameObject)?.BearDamageBlock?.Invoke(((Component)healthComponent.body).gameObject); }; ILCursor val = new ILCursor(il); int num4 = default(int); int num3 = default(int); if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, "RoR2.HealthComponent+AssetReferences", "bearEffectPrefab") }) && val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num4) }) && val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, ref num3) }) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, "RoR2.EffectManager", "SpawnEffect") })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Action<HealthComponent>>(action); int num2 = default(int); int num = default(int); if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, "RoR2.HealthComponent+AssetReferences", "bearVoidEffectPrefab") }) && val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdloc(x, ref num2) }) && val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, ref num) }) && val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, "RoR2.EffectManager", "SpawnEffect") })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Action<HealthComponent>>(action); } } else { Log.Error("OnBearDamageBlock ILHook failed. Tougher Times/Safer Spaces block events will not occur"); } } private static void OnLevelUp(CharacterBody characterBody) { GameObject val = ((characterBody != null) ? ((Component)characterBody).gameObject : null); GetEventSubFromBody(val)?.LevelUp?.Invoke(val); } private static void OnPickupAttemptGrant(ILContext il) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Action<CharacterBody, PickupDef> action = delegate(CharacterBody body, PickupDef pickupDef) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown EventSub eventSubFromBody = GetEventSubFromBody(((Component)body).gameObject); if (eventSubFromBody != null) { NetMessageExtensions.Send((INetMessage)(object)new SyncGetItem(body.master.bodyInstanceId, (int)pickupDef.itemIndex), (NetworkDestination)1); } }; ILCursor c = new ILCursor(il); int pickupLoc = 2; if (c.TryGotoNext(new Func<Instruction, bool>[2] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)typeof(PickupCatalog).GetMethod("GetPickupDef")), (Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref pickupLoc) }) && c.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdfld<GrantContext>(x, "shouldDestroy") && c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchStfld<GenericPickupController>(x, "consumed") }) })) { c.Emit(OpCodes.Ldarg_1); c.Emit(OpCodes.Ldloc, pickupLoc); c.EmitDelegate<Action<CharacterBody, PickupDef>>(action); } else { Log.Error("OnPickupAttemptGrant ILHook failed. Pickup interaction related events will not occur"); } } private static void OnDefeatBossGroup(BossGroup bossGroup) { if (!(((Object)((Component)bossGroup).gameObject).name != "BrotherEncounter, Phase 4")) { return; } foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) { GameObject val = ((readOnlyInstances != null) ? readOnlyInstances.GetBodyObject() : null); if ((Object)(object)val != (Object)null) { GetEventSubFromBody(val)?.DefeatBossGroup?.Invoke(val); } } } private static void OnTeleporterEnd(TeleporterInteraction teleporterInteraction) { foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) { GameObject val = ((readOnlyInstances != null) ? readOnlyInstances.GetBodyObject() : null); if ((Object)(object)val != (Object)null) { GetEventSubFromBody(val)?.TeleporterEnd?.Invoke(val); } } } private static void OnTakeDamage(DamageReport damageReport) { if (!((Object)(object)damageReport?.victimBody != (Object)null)) { return; } object body; if (damageReport == null) { body = null; } else { CharacterBody victimBody = damageReport.victimBody; body = ((victimBody != null) ? ((Component)victimBody).gameObject : null); } EventSub eventSubFromBody = GetEventSubFromBody((GameObject)body); if (eventSubFromBody == null) { return; } Action<GameObject, DamageReport> takeDamage = eventSubFromBody.TakeDamage; if (takeDamage != null) { object arg; if (damageReport == null) { arg = null; } else { CharacterBody victimBody2 = damageReport.victimBody; arg = ((victimBody2 != null) ? ((Component)victimBody2).gameObject : null); } takeDamage((GameObject)arg, damageReport); } } private static void OnMithrixDefeat(orig_OnEnter orig, EncounterFinished self) { orig.Invoke(self); foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) { GameObject val = ((readOnlyInstances != null) ? readOnlyInstances.GetBodyObject() : null); if ((Object)(object)val != (Object)null) { GetEventSubFromBody(val)?.MithrixDefeat?.Invoke(val); } } } private static void OnUseEquipment(EquipmentSlot self, EquipmentIndex index) { GetEventSubFromBody(((Component)self.characterBody).gameObject)?.UseEquipment?.Invoke(((Component)self.characterBody).gameObject); } private static void OnHeal(HealthComponent self, float amount, ProcChainMask procChainMaskn) { object obj; if (self == null) { obj = null; } else { CharacterBody body = self.body; obj = ((body != null) ? ((Component)body).gameObject : null); } GameObject val = (GameObject)obj; GetEventSubFromBody(val)?.Heal?.Invoke(val, amount); } private static void OnJump(orig_ApplyJumpVelocity orig, CharacterMotor characterMotor, CharacterBody characterBody, float horizontalBonus, float verticalBonus, bool vault) { orig.Invoke(characterMotor, characterBody, horizontalBonus, verticalBonus, vault); GetEventSubFromBody(((Component)characterBody).gameObject)?.Jump?.Invoke(((Component)characterBody).gameObject); } private static void OnLeaveStage(orig_Begin orig, SceneExitController self) { orig.Invoke(self); foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) { GameObject val = ((readOnlyInstances != null) ? readOnlyInstances.GetBodyObject() : null); if ((Object)(object)val != (Object)null) { GetEventSubFromBody(val)?.LeaveStage?.Invoke(val); } } } public static GameObject GetModelFromEventBody(GameObject body) { if ((Object)(object)Run.instance != (Object)null && Object.op_Implicit((Object)(object)body)) { ModelLocator component = body.GetComponent<ModelLocator>(); object result; if (component == null) { result = null; } else { Transform modelTransform = component.modelTransform; result = ((modelTransform != null) ? ((Component)modelTransform).gameObject : null); } return (GameObject)result; } return body; } public static ExpressionController GetExpressionController(GameObject body) { GameObject modelFromEventBody = GetModelFromEventBody(body); return (modelFromEventBody != null) ? modelFromEventBody.GetComponent<ExpressionController>() : null; } public static void RemoveExtraObjects(GameObject body) { ExtraObjectController component = body.GetComponent<ExtraObjectController>(); if (!((Object)(object)component != (Object)null)) { return; } foreach (GameObject extraObj in component.extraObjs) { Object.Destroy((Object)(object)extraObj); } Object.Destroy((Object)(object)component); } public static void RemoveTransformController(GameObject body) { TransformController transformController = ((body != null) ? body.GetComponent<TransformController>() : null); if ((Object)(object)transformController != (Object)null) { transformController.beingDeleted = true; Object.Destroy((Object)(object)transformController); } } public static void RemoveVoiceController(GameObject body) { VoiceController voiceController = ((body != null) ? body.GetComponent<VoiceController>() : null); if ((Object)(object)voiceController != (Object)null) { Object.Destroy((Object)(object)voiceController); } } public static void RemoveExpressionController(GameObject body) { ExpressionController expressionController = ((body != null) ? body.GetComponent<ExpressionController>() : null); if ((Object)(object)expressionController != (Object)null) { expressionController.CancelCurrentExpressions(); Object.Destroy((Object)(object)expressionController); } } private static void OnBodyUpdate(orig_Update orig, CharacterBody self) { orig.Invoke(self); if (!((Object)(object)self == (Object)null) && self.notMovingStopwatch > 10f) { EventSub eventSubFromBody = GetEventSubFromBody(((Component)self).gameObject); if (eventSubFromBody != null && self.notMovingStopwatch % 10f < 0.1f && !holdOffIdleInvocation.Contains(self)) { eventSubFromBody.Idle?.Invoke(((Component)self).gameObject); ((MonoBehaviour)RoR2Application.instance).StartCoroutine(HoldBodyFromIdleUpdate(self)); } } } [IteratorStateMachine(typeof(<HoldBodyFromIdleUpdate>d__32))] private static IEnumerator HoldBodyFromIdleUpdate(CharacterBody body) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HoldBodyFromIdleUpdate>d__32(0) { body = body }; } public static void InvokeGetItem(GameObject body, int itemIndex) { EventSub eventSubFromBody = GetEventSubFromBody(body.gameObject); eventSubFromBody.GetItem?.Invoke(body.gameObject, (ItemIndex)itemIndex); } public static void InvokeUseShrine(GameObject body, bool success) { EventSub eventSubFromBody = GetEventSubFromBody(body); if (success) { eventSubFromBody.ShrineSuccess?.Invoke(body); } else { eventSubFromBody.ShrineFailure?.Invoke(body); } } public static void InvokeHoldoutZoneCharged() { foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList) { GameObject val = ((readOnlyInstances != null) ? readOnlyInstances.GetBodyObject() : null); if ((Object)(object)val != (Object)null) { GetEventSubFromBody(val)?.HoldoutZoneCharged?.Invoke(val); } } } } public class TransformController : MonoBehaviour { private Transform[] boneTransforms; private Dictionary<Transform, Transform> boneRelativeTo = new Dictionary<Transform, Transform>(); private CharacterBody characterBody; private Animator animator; public bool beingDeleted = false; public BoneTransformation[] boneTransformations; public BoneTransformation rtiBoneTransformation; private int _rtiIndex = 0; private Vector3 _rtiPositionVector; private Vector3 _rtiLocalScaleVector; public int rtiIndex { get { return _rtiIndex; } set { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _rtiIndex = value; rtiBoneTransformation = boneTransformations[_rtiIndex]; _rtiPositionVector = rtiBoneTransformation.position; _rtiLocalScaleVector = rtiBoneTransformation.localScale; } } public Vector3 rtiPositionVector { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return _rtiPositionVector; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _rtiPositionVector = value; rtiBoneTransformation.position = _rtiPositionVector; } } public Vector3 rtiLocalScaleVector { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return _rtiLocalScaleVector; } set { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _rtiLocalScaleVector = value; rtiBoneTransformation.localScale = _rtiLocalScaleVector; } } public void Init(EventSub eventSub) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) boneTransformations = eventSub.boneTransformations; rtiBoneTransformation = boneTransformations[rtiIndex]; _rtiPositionVector = rtiBoneTransformation.position; _rtiLocalScaleVector = rtiBoneTransformation.localScale; AssignLimbs(); } private void Start() { characterBody = ((Component)this).GetComponent<CharacterBody>(); animator = SkinEvents.GetModelFromEventBody(((Component)this).gameObject).GetComponent<Animator>(); } private void AssignLimbs() { List<Transform> list = new List<Transform>(); for (int i = 0; i < boneTransformations.Length; i++) { Transform val = SkinEvents.GetModelFromEventBody(((Component)this).gameObject).transform.Find(boneTransformations[i].armaturePath); if ((Object)(object)val != (Object)null) { list.Add(SkinEvents.GetModelFromEventBody(((Component)this).gameObject).transform.Find(boneTransformations[i].armaturePath)); if (boneTransformations[i].relativeBonePath != null) { Transform val2 = SkinEvents.GetModelFromEventBody(((Component)this).gameObject).transform.Find(boneTransformations[i].relativeBonePath); if ((Object)(object)val2 != (Object)null) { boneRelativeTo[val] = val2; continue; } Log.Error("Received invalid relative bone path: " + boneTransformations[i].relativeBonePath); boneRelativeTo[val] = val; } else { boneRelativeTo[val] = val; } } else { Log.Error("Received invalid bone path: " + boneTransformations[i].armaturePath); } } boneTransforms = list.ToArray(); } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)characterBody?.currentVehicle)) { Animator obj = animator; if (obj != null && ((Behaviour)obj).enabled) { ApplyPosition(); } } ApplyScale(); } private void ApplyScale() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < boneTransforms.Length; i++) { boneTransforms[i].localScale = boneTransformations[i].localScale; } } private void ApplyPosition() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < boneTransforms.Length; i++) { Transform val = boneRelativeTo[boneTransforms[i]]; boneTransforms[i].position = val.TransformPoint(boneTransformations[i].position); } } } public class VoiceArray { public VoiceInfo[] voiceLines; public VoiceGroup group; public VoiceArray(VoiceInfo[] voiceLines) { this.voiceLines = voiceLines; } } public class VoiceController : MonoBehaviour { private float timeSinceLastRolledLine; private const float soundWaitPadding = 0.5f; private float currentSoundWait; private Dictionary<VoiceGroup, float> voiceGroupStopwatches; private Dictionary<VoiceArray, int> lastPlayedIndex = new Dictionary<VoiceArray, int>(); public void Init(EventSub eventSub) { voiceGroupStopwatches = new Dictionary<VoiceGroup, float>(); VoiceGroup[] voiceGroups = eventSub.voiceGroups; foreach (VoiceGroup key in voiceGroups) { voiceGroupStopwatches.Add(key, 0f); } } private void Awake() { if (!NetworkServer.active) { Object.Destroy((Object)(object)this); } } private void Update() { float deltaTime = Time.deltaTime; VoiceGroup[] array = voiceGroupStopwatches.Keys.ToArray(); foreach (VoiceGroup key in array) { voiceGroupStopwatches[key] += deltaTime; } timeSinceLastRolledLine += deltaTime; } public bool RollForSoundEvent(VoiceArray soundArray, float maxProbability = 1f) { if (timeSinceLastRolledLine < currentSoundWait) { return false; } float num = voiceGroupStopwatches[soundArray.group]; float num2 = soundArray.group.maxWait - soundArray.group.minWait; float num3 = ((num2 != 0f) ? Mathf.Min(maxProbability, (num - soundArray.group.minWait) / num2) : 1f); if (num > soundArray.group.minWait && Random.value <= num3) { voiceGroupStopwatches[soundArray.group] = 0f; timeSinceLastRolledLine = 0f; return true; } return false; } public void TryPlayRandomUniqueSoundServer(VoiceArray soundArray, GameObject source, float maxProbability = 1f) { if (!NetworkServer.active || !RollForSoundEvent(soundArray, maxProbability)) { return; } int num; if (lastPlayedIndex.ContainsKey(soundArray)) { num = MwUtils.rand.Next(soundArray.voiceLines.Length - 1); if (num >= lastPlayedIndex[soundArray]) { num++; num %= soundArray.voiceLines.Length; } } else { num = MwUtils.rand.Next(soundArray.voiceLines.Length); lastPlayedIndex.Add(soundArray, num); } lastPlayedIndex[soundArray] = num; PlaySoundServer(soundArray.voiceLines[num], source, this); } public void TryPlayRandomSoundServer(VoiceArray soundArray, GameObject source, float maxProbability = 1f) { if (NetworkServer.active && RollForSoundEvent(soundArray, maxProbability)) { PlayRandomSoundServer(soundArray, source, this); } } public void TryPlayRandomSoundServer(VoiceArray soundArray, Vector3 position, float maxProbability = 1f) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active && RollForSoundEvent(soundArray, maxProbability)) { PlayRandomSoundServer(soundArray, position, this); } } public void TryPlayRandomSound(VoiceArray soundArray, GameObject source, float maxProbability = 1f) { if (RollForSoundEvent(soundArray, maxProbability)) { PlayRandomSound(soundArray, source, this); } } public void TryPlayRandomSound(VoiceArray soundArray, Vector3 position, float maxProbability = 1f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (RollForSoundEvent(soundArray, maxProbability)) { PlayRandomSound(soundArray, position, this); } } public static void PlayRandomSoundServer(VoiceArray soundArray, GameObject source, VoiceController voiceController = null) { if (NetworkServer.active) { object[] voiceLines = soundArray.voiceLines; VoiceInfo voiceInfo = (VoiceInfo)MwUtils.RandomChoice(voiceLines); PlaySoundServer(voiceInfo, source, voiceController); } } public static void PlayRandomSoundServer(VoiceArray soundArray, Vector3 position, VoiceController voiceController = null) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { object[] voiceLines = soundArray.voiceLines; VoiceInfo voiceInfo = (VoiceInfo)MwUtils.RandomChoice(voiceLines); PlaySoundServer(voiceInfo, position, voiceController); } } public static void PlayRandomSound(VoiceArray soundArray, GameObject source, VoiceController voiceController = null) { object[] voiceLines = soundArray.voiceLines; VoiceInfo voiceInfo = (VoiceInfo)MwUtils.RandomChoice(voiceLines); PlaySound(voiceInfo, source, voiceController); } public static void PlayRandomSound(VoiceArray soundArray, Vector3 position, VoiceController voiceController = null) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) object[] voiceLines = soundArray.voiceLines; VoiceInfo voiceInfo = (VoiceInfo)MwUtils.RandomChoice(voiceLines); PlaySound(voiceInfo, position, voiceController); } public static void PlaySoundServer(VoiceInfo voiceInfo, GameObject source, VoiceController voiceController = null) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { EntitySoundManager.EmitSoundServer(AkEventIdArg.op_Implicit(voiceInfo.sound.akId), source); if ((Object)(object)voiceController != (Object)null) { voiceController.currentSoundWait = voiceInfo.approxDuration + 0.5f; } } } public static void PlaySoundServer(VoiceInfo voiceInfo, Vector3 position, VoiceController voiceController = null) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { EffectManager.SimpleSoundEffect(voiceInfo.sound.index, position, true); if ((Object)(object)voiceController != (Object)null) { voiceController.currentSoundWait = voiceInfo.approxDuration + 0.5f; } } } public static void PlaySound(VoiceInfo voiceInfo, GameObject source, VoiceController voiceController = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) EntitySoundManager.EmitSoundLocal(AkEventIdArg.op_Implicit(voiceInfo.sound.akId), source); if ((Object)(object)voiceController != (Object)null) { voiceController.currentSoundWait = voiceInfo.approxDuration + 0.5f; } } public static void PlaySound(VoiceInfo voiceInfo, Vector3 position, VoiceController voiceController = null) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) EffectManager.SimpleSoundEffect(voiceInfo.sound.index, position, false); if ((Object)(object)voiceController != (Object)null) { voiceController.currentSoundWait = voiceInfo.approxDuration + 0.5f; } } } public class VoiceGroup { public VoiceArray[] voiceArrays; public float minWait; public float maxWait; public VoiceGroup(VoiceArray[] voiceArrays, float minWait, float maxWait) { this.voiceArrays = voiceArrays; this.minWait = minWait; this.maxWait = maxWait; foreach (VoiceArray voiceArray in voiceArrays) { voiceArray.group = this; } } } public class VoiceInfo { public float approxDuration; public NetworkSoundEventDef sound; public VoiceInfo(string soundString, float approxDuration) { this.approxDuration = approxDuration; sound = ContentPacks.CreateAndAddNetworkSoundEventDef(soundString); } } }