using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SideLoader;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CustomEffects")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Custom Effects")]
[assembly: AssemblyTitle("CustomEffects")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 CustomEffects
{
[BepInPlugin("com.wrango.customeffects", "Custom Effects", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CustomEffectsPlugin : BaseUnityPlugin
{
public const string GUID = "com.wrango.customeffects";
public const string NAME = "Custom Effects";
public const string VERSION = "1.1.1";
public static CustomEffectsPlugin Instance;
public static Harmony harmony;
internal static ManualLogSource Log;
internal void Awake()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
harmony = new Harmony("com.wrango.customeffects");
harmony.PatchAll();
Log.LogMessage((object)"Custom Effects 1.1.1 loaded. Effects: SL_UseSkill, SL_Banish, SL_LearnSkillHidden, SL_PlayVFXOnWeapon, SL_PlayVFXOnChar, SL_PlayVFXPulsed, SL_PlayTimedSound, SL_ReliableVisuals.");
}
}
public class SL_Banish : SL_Effect, ICustomModel
{
public float Duration = 10f;
public Type SLTemplateModel => typeof(SL_Banish);
public Type GameModel => typeof(BanishEffect);
public override void ApplyToComponent<T>(T component)
{
(component as BanishEffect).Duration = Duration;
}
public override void SerializeEffect<T>(T effect)
{
Duration = (effect as BanishEffect).Duration;
}
}
public class BanishEffect : Effect
{
public float Duration = 10f;
internal static readonly HashSet<string> Banished = new HashSet<string>();
private static readonly Action<LocalCharacterControl> ControlReleaseTarget = AccessTools.MethodDelegate<Action<LocalCharacterControl>>(AccessTools.Method(typeof(LocalCharacterControl), "ReleaseTarget", (Type[])null, (Type[])null), (object)null, true);
internal static bool IsBanished(Character c)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)c))
{
HashSet<string> banished = Banished;
UID uID = c.UID;
return banished.Contains(((UID)(ref uID)).Value);
}
return false;
}
internal static bool IsLocallyControlled(Character c)
{
if (!Object.op_Implicit((Object)(object)c))
{
return false;
}
if (c.IsAI)
{
return PhotonNetwork.isMasterClient;
}
return c.IsLocalPlayer;
}
private static int ReleaseLocksOn(Character banished)
{
int num = 0;
if (!Object.op_Implicit((Object)(object)CharacterManager.Instance))
{
return num;
}
foreach (Character value in CharacterManager.Instance.Characters.Values)
{
if (!Object.op_Implicit((Object)(object)value) || !value.IsLocalPlayer)
{
continue;
}
TargetingSystem targetingSystem = value.TargetingSystem;
if (!((Object)(object)targetingSystem == (Object)null) && targetingSystem.Locked && !((Object)(object)targetingSystem.LockedCharacter != (Object)(object)banished))
{
LocalCharacterControl component = ((Component)value).GetComponent<LocalCharacterControl>();
if (Object.op_Implicit((Object)(object)component) && ControlReleaseTarget != null)
{
ControlReleaseTarget(component);
}
else
{
targetingSystem.ReleaseTarget();
}
num++;
}
}
return num;
}
internal static void BeginBanish(Character character, float duration, float delay, StatusEffect status)
{
//IL_000a: 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)
if (Object.op_Implicit((Object)(object)character))
{
UID uID = character.UID;
string value = ((UID)(ref uID)).Value;
if (!Banished.Contains(value) && Object.op_Implicit((Object)(object)CustomEffectsPlugin.Instance))
{
Banished.Add(value);
((MonoBehaviour)CustomEffectsPlugin.Instance).StartCoroutine(BanishRoutineFor(character, value, duration, delay, status));
}
}
}
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
if (Object.op_Implicit((Object)(object)_affectedCharacter))
{
BeginBanish(_affectedCharacter, Duration, 0f, ((Component)this).GetComponentInParent<StatusEffect>());
}
}
private static IEnumerator BanishRoutineFor(Character character, string uid, float duration, float delay, StatusEffect status)
{
try
{
if (delay > 0f)
{
yield return (object)new WaitForSeconds(delay);
}
if (!Object.op_Implicit((Object)(object)character))
{
yield break;
}
bool controls = IsLocallyControlled(character);
List<Renderer> hiddenRenderers = new List<Renderer>();
List<Behaviour> disabledHitboxes = new List<Behaviour>();
List<Collider> disabledColliders = new List<Collider>();
List<SoundPlayer> silencedSounds = new List<SoundPlayer>();
List<bool> silencedWasStopOnDisable = new List<bool>();
List<bool> silencedWasEnabled = new List<bool>();
bool moveBlockDisabled = false;
bool controllerDisabled = false;
Vector3 frozenPosition = ((Component)character).transform.position;
bool wasQuestNonTargetable = character.QuestNonTargetable;
CharacterAI ai = ((Component)character).GetComponent<CharacterAI>();
bool aiWasEnabled = Object.op_Implicit((Object)(object)ai) && ((Behaviour)ai).enabled;
bool aiRootWasActive = false;
if (Object.op_Implicit((Object)(object)character.VisualHolderTrans))
{
Renderer[] componentsInChildren = ((Component)character.VisualHolderTrans).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val in componentsInChildren)
{
if (Object.op_Implicit((Object)(object)val) && val.enabled)
{
val.enabled = false;
hiddenRenderers.Add(val);
}
}
}
if (character.Hitboxes != null)
{
Hitbox[] hitboxes = character.Hitboxes;
foreach (Hitbox val2 in hitboxes)
{
if (Object.op_Implicit((Object)(object)val2))
{
if (((Behaviour)val2).enabled)
{
((Behaviour)val2).enabled = false;
disabledHitboxes.Add((Behaviour)(object)val2);
}
Collider component = ((Component)val2).GetComponent<Collider>();
if (Object.op_Implicit((Object)(object)component) && component.enabled)
{
component.enabled = false;
disabledColliders.Add(component);
}
}
}
}
SoundPlayer[] componentsInChildren2 = ((Component)character).GetComponentsInChildren<SoundPlayer>(true);
foreach (SoundPlayer val3 in componentsInChildren2)
{
if (Object.op_Implicit((Object)(object)val3))
{
silencedSounds.Add(val3);
silencedWasStopOnDisable.Add(val3.StopOnDisable);
silencedWasEnabled.Add(((Behaviour)val3).enabled);
val3.StopOnDisable = true;
((Behaviour)val3).enabled = false;
}
}
if (Object.op_Implicit((Object)(object)character.CharMoveBlockCollider) && ((Collider)character.CharMoveBlockCollider).enabled)
{
((Collider)character.CharMoveBlockCollider).enabled = false;
moveBlockDisabled = true;
}
if (Object.op_Implicit((Object)(object)character.CharacterController) && ((Collider)character.CharacterController).enabled)
{
((Collider)character.CharacterController).enabled = false;
controllerDisabled = true;
}
character.QuestNonTargetable = true;
int num = ReleaseLocksOn(character);
if (controls)
{
if (controllerDisabled)
{
frozenPosition = ((Component)character).transform.position;
}
if (Object.op_Implicit((Object)(object)ai))
{
aiRootWasActive = Object.op_Implicit((Object)(object)ai.AIStatesRoot) && ((Component)ai.AIStatesRoot).gameObject.activeSelf;
if (aiRootWasActive)
{
ai.SetNPCActive(false);
}
((Behaviour)ai).enabled = false;
}
character.Stun(-1f);
if (Object.op_Implicit((Object)(object)character.Animator))
{
character.Animator.speed = 0f;
}
}
CustomEffectsPlugin.Log.LogMessage((object)("[Banish] t=" + Time.time.ToString("F2") + " " + character.Name + " for " + duration + "s | controls=" + controls + " renderers=" + hiddenRenderers.Count + " sounds=" + silencedSounds.Count + " hitboxes=" + disabledHitboxes.Count + " locksReleased=" + num + " aiRootStopped=" + aiRootWasActive));
float elapsed = 0f;
bool died = false;
bool followStatus = !controls && Object.op_Implicit((Object)(object)status);
while (Object.op_Implicit((Object)(object)character) && elapsed < duration)
{
if (!character.Alive)
{
died = true;
break;
}
if (followStatus && !Object.op_Implicit((Object)(object)status))
{
break;
}
if (controls && controllerDisabled)
{
((Component)character).transform.position = frozenPosition;
}
elapsed += Time.deltaTime;
yield return null;
}
if (!Object.op_Implicit((Object)(object)character))
{
yield break;
}
for (int j = 0; j < silencedSounds.Count; j++)
{
if (Object.op_Implicit((Object)(object)silencedSounds[j]))
{
((Behaviour)silencedSounds[j]).enabled = silencedWasEnabled[j];
silencedSounds[j].StopOnDisable = silencedWasStopOnDisable[j];
}
}
foreach (Renderer item in hiddenRenderers)
{
if (Object.op_Implicit((Object)(object)item))
{
item.enabled = true;
}
}
foreach (Behaviour item2 in disabledHitboxes)
{
if (Object.op_Implicit((Object)(object)item2))
{
item2.enabled = true;
}
}
foreach (Collider item3 in disabledColliders)
{
if (Object.op_Implicit((Object)(object)item3))
{
item3.enabled = true;
}
}
bool flag = died || !character.Alive;
if (controllerDisabled && Object.op_Implicit((Object)(object)character.CharacterController) && !flag)
{
if (controls)
{
((Component)character).transform.position = frozenPosition;
}
((Collider)character.CharacterController).enabled = true;
}
character.QuestNonTargetable = wasQuestNonTargetable;
ReleaseLocksOn(character);
if (controls)
{
character.StopStun();
if (Object.op_Implicit((Object)(object)ai))
{
if (aiWasEnabled)
{
((Behaviour)ai).enabled = true;
}
if (aiRootWasActive && !died && character.Alive)
{
ai.SetNPCActive(true);
}
}
}
if (moveBlockDisabled && Object.op_Implicit((Object)(object)character.CharMoveBlockCollider) && !flag)
{
((Collider)character.CharMoveBlockCollider).enabled = true;
}
CustomEffectsPlugin.Log.LogMessage((object)("[Banish] t=" + Time.time.ToString("F2") + " " + character.Name + (died ? " died while banished - restored as a body." : " returned.")));
}
finally
{
Banished.Remove(uid);
}
}
}
[HarmonyPatch(typeof(StatusEffectManager), "AddStatusEffect", new Type[]
{
typeof(StatusEffect),
typeof(Character),
typeof(string[])
})]
public class StatusEffectManager_AddStatusEffect
{
private static readonly FieldRef<StatusEffectManager, Character> ManagerCharacter = AccessTools.FieldRefAccess<StatusEffectManager, Character>("m_character");
private static bool s_loggedOnce;
[HarmonyPostfix]
public static void Postfix(StatusEffectManager __instance, StatusEffect __result)
{
if ((Object)(object)__result == (Object)null)
{
return;
}
BanishEffect componentInChildren = ((Component)__result).GetComponentInChildren<BanishEffect>(true);
if (!Object.op_Implicit((Object)(object)componentInChildren))
{
return;
}
Character val = ManagerCharacter.Invoke(__instance);
if (Object.op_Implicit((Object)(object)val) && (((Component)__result).gameObject.activeInHierarchy || !BanishEffect.IsLocallyControlled(val)))
{
if (!s_loggedOnce)
{
s_loggedOnce = true;
CustomEffectsPlugin.Log.LogMessage((object)"SL_Banish: status-arrival patch is live - banish now runs on every client.");
}
BanishEffect.BeginBanish(val, componentInChildren.Duration, ((Effect)componentInChildren).Delay, __result);
}
}
}
[HarmonyPatch(typeof(Character), "AnimSound")]
public class Character_AnimSound
{
[HarmonyPrefix]
public static bool Prefix(Character __instance)
{
return !BanishEffect.IsBanished(__instance);
}
}
[HarmonyPatch(typeof(Character), "AnimSoundRandom")]
public class Character_AnimSoundRandom
{
[HarmonyPrefix]
public static bool Prefix(Character __instance)
{
return !BanishEffect.IsBanished(__instance);
}
}
public class SL_LearnSkillHidden : SL_Effect, ICustomModel
{
public int SkillID;
public Type SLTemplateModel => typeof(SL_LearnSkillHidden);
public Type GameModel => typeof(HiddenLearnSkillEffect);
public override void ApplyToComponent<T>(T component)
{
HiddenLearnSkillEffect hiddenLearnSkillEffect = component as HiddenLearnSkillEffect;
Item itemPrefab = ResourcesPrefabManager.Instance.GetItemPrefab(SkillID);
Skill val = (Skill)(object)((itemPrefab is Skill) ? itemPrefab : null);
if (val != null)
{
hiddenLearnSkillEffect.LearntSkill = val;
HiddenSkills.Register(SkillID);
}
else
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_LearnSkillHidden: no skill found with ID " + SkillID + " - nothing will be taught."));
}
}
public override void SerializeEffect<T>(T effect)
{
SkillID = ((Item)((effect as HiddenLearnSkillEffect).LearntSkill?)).ItemID ?? (-1);
}
}
public static class HiddenSkills
{
private static readonly HashSet<int> IDs = new HashSet<int>();
public static bool Any => IDs.Count > 0;
public static void Register(int skillID)
{
if (IDs.Add(skillID))
{
CustomEffectsPlugin.Log.LogMessage((object)("SL_LearnSkillHidden: hiding skill " + skillID + " from the skill menu."));
}
}
public static bool IsHidden(int skillID)
{
if (IDs.Count > 0)
{
return IDs.Contains(skillID);
}
return false;
}
}
public class HiddenLearnSkillEffect : Effect
{
public Skill LearntSkill;
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
if (Object.op_Implicit((Object)(object)_affectedCharacter) && Object.op_Implicit((Object)(object)LearntSkill) && _affectedCharacter.IsLocalPlayer && !((CharacterKnowledge)_affectedCharacter.Inventory.SkillKnowledge).IsItemLearned((Item)(object)LearntSkill))
{
_affectedCharacter.Inventory.TryUnlockSkill(LearntSkill);
CustomEffectsPlugin.Log.LogMessage((object)("SL_LearnSkillHidden: taught " + ((Item)LearntSkill).Name + " (" + ((Item)LearntSkill).ItemID + ") to " + _affectedCharacter.Name + ", hidden from the menu."));
}
}
}
[HarmonyPatch(typeof(CharacterSkillKnowledge), "AddItem")]
public class CharacterSkillKnowledge_AddItem
{
private static readonly FieldRef<CharacterSkillKnowledge, List<string>> ActiveUIDs = AccessTools.FieldRefAccess<CharacterSkillKnowledge, List<string>>("m_activeSkillUIDs");
private static readonly FieldRef<CharacterSkillKnowledge, List<string>> PassiveUIDs = AccessTools.FieldRefAccess<CharacterSkillKnowledge, List<string>>("m_passiveSkillUIDs");
private static readonly FieldRef<CharacterSkillKnowledge, List<string>> CosmeticUIDs = AccessTools.FieldRefAccess<CharacterSkillKnowledge, List<string>>("m_cosmeticSkillUIDs");
[HarmonyPrefix]
public static void Prefix(Item _item)
{
if (HiddenSkills.Any)
{
Skill val = (Skill)(object)((_item is Skill) ? _item : null);
if (Object.op_Implicit((Object)(object)val) && HiddenSkills.IsHidden(((Item)val).ItemID))
{
val.IgnoreLearnNotification = true;
}
}
}
[HarmonyPostfix]
public static void Postfix(CharacterSkillKnowledge __instance, Item _item)
{
if (HiddenSkills.Any && Object.op_Implicit((Object)(object)_item))
{
Skill val = (Skill)(object)((_item is Skill) ? _item : null);
if (Object.op_Implicit((Object)(object)val) && HiddenSkills.IsHidden(((Item)val).ItemID))
{
string uID = _item.UID;
ActiveUIDs.Invoke(__instance).Remove(uID);
PassiveUIDs.Invoke(__instance).Remove(uID);
CosmeticUIDs.Invoke(__instance).Remove(uID);
}
}
}
}
public class SL_PlayTimedSound : SL_Effect, ICustomModel
{
public Sounds[] Sounds;
public bool Follow;
public float MinPitch = 1f;
public float MaxPitch = 1f;
public float StopAfter = 5f;
public float FadeIn;
public float FadeOut = 0.15f;
public Type SLTemplateModel => typeof(SL_PlayTimedSound);
public Type GameModel => typeof(PlayTimedSound);
public override void ApplyToComponent<T>(T component)
{
PlayTimedSound playTimedSound = component as PlayTimedSound;
playTimedSound.Sounds = (Sounds[])((Sounds == null) ? ((Array)new Sounds[0]) : ((Array)Sounds));
playTimedSound.Follow = Follow;
playTimedSound.MinPitch = MinPitch;
playTimedSound.MaxPitch = MaxPitch;
playTimedSound.StopAfter = StopAfter;
playTimedSound.FadeIn = FadeIn;
playTimedSound.FadeOut = FadeOut;
if (playTimedSound.Sounds.Length == 0)
{
CustomEffectsPlugin.Log.LogWarning((object)"SL_PlayTimedSound: no Sounds were read - nothing will play. Each entry must be a <Sounds> element inside <Sounds>.");
}
else if (StopAfter <= 0f)
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_PlayTimedSound (" + ((object)Unsafe.As<Sounds, Sounds>(ref playTimedSound.Sounds[0])/*cast due to .constrained prefix*/).ToString() + "): StopAfter is zero, so this behaves as SL_PlaySoundEffect - the sound ends with its clip or with the status. Set StopAfter to cut it earlier."));
}
}
public override void SerializeEffect<T>(T effect)
{
PlayTimedSound playTimedSound = effect as PlayTimedSound;
Sounds = playTimedSound.Sounds;
Follow = playTimedSound.Follow;
MinPitch = playTimedSound.MinPitch;
MaxPitch = playTimedSound.MaxPitch;
StopAfter = playTimedSound.StopAfter;
FadeIn = playTimedSound.FadeIn;
FadeOut = playTimedSound.FadeOut;
}
}
public class PlayTimedSound : Effect
{
public Sounds[] Sounds = (Sounds[])(object)new Sounds[0];
public bool Follow;
public float MinPitch = 1f;
public float MaxPitch = 1f;
public float StopAfter = 5f;
public float FadeIn;
public float FadeOut = 0.15f;
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Global.AudioManager == (Object)null || Sounds == null || Sounds.Length == 0)
{
return;
}
Sounds val = CharacterSoundManager.FindSound(Sounds);
if ((int)val != 0)
{
SplitableSoundSource val2 = ((!Follow) ? Global.AudioManager.PlaySoundAtPosition(val, ((Component)this).transform, FadeIn, 1f, 1f, MinPitch, MaxPitch) : Global.AudioManager.PlaySoundAndFollow(val, ((Component)this).transform, FadeIn, 1f, 1f, MinPitch, MaxPitch));
if ((Object)(object)val2 != (Object)null && StopAfter > 0f)
{
((MonoBehaviour)this).StartCoroutine(StopLater(val, val2));
}
}
}
private IEnumerator StopLater(Sounds sound, SplitableSoundSource source)
{
//IL_000e: 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)
yield return (object)new WaitForSeconds(StopAfter);
if (!((Object)(object)source == (Object)null) && !((Object)(object)Global.AudioManager == (Object)null))
{
Global.AudioManager.StopSound(sound, source, FadeOut, false);
}
}
}
public class SL_PlayVFXOnChar : SL_Effect, ICustomModel
{
public VFXPrefabs VFXPrefab;
public bool HitPos;
public e_ParentMode ParentMode;
public bool DontInstantiateNew;
public Vector3 Offset = Vector3.zero;
public PlayVFXOnChar.e_DetachMode Detach;
public float DetachLifetime = 5f;
public Type SLTemplateModel => typeof(SL_PlayVFXOnChar);
public Type GameModel => typeof(PlayVFXOnChar);
public override void ApplyToComponent<T>(T component)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//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_0055: Unknown result type (might be due to invalid IL or missing references)
PlayVFXOnChar playVFXOnChar = component as PlayVFXOnChar;
((PlayVFX)playVFXOnChar).HitPos = HitPos;
((PlayVFX)playVFXOnChar).ParentMode = ParentMode;
((PlayVFX)playVFXOnChar).VfxAlreadyInst = DontInstantiateNew;
playVFXOnChar.Offset = Offset;
playVFXOnChar.Detach = Detach;
playVFXOnChar.DetachLifetime = DetachLifetime;
GameObject vfxSystem = SL_PlayVFX.GetVfxSystem(VFXPrefab);
if (vfxSystem == null)
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_PlayVFXOnChar: no VFX prefab named " + ((object)Unsafe.As<VFXPrefabs, VFXPrefabs>(ref VFXPrefab)/*cast due to .constrained prefix*/).ToString() + " - nothing will play."));
return;
}
GameObject val = Object.Instantiate<GameObject>(vfxSystem);
Object.DontDestroyOnLoad((Object)(object)val);
val.SetActive(false);
((PlayVFX)playVFXOnChar).VFX = val.GetComponent<VFXSystem>();
}
public override void SerializeEffect<T>(T effect)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//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_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
PlayVFXOnChar playVFXOnChar = effect as PlayVFXOnChar;
HitPos = ((PlayVFX)playVFXOnChar).HitPos;
ParentMode = ((PlayVFX)playVFXOnChar).ParentMode;
DontInstantiateNew = ((PlayVFX)playVFXOnChar).VfxAlreadyInst;
Offset = playVFXOnChar.Offset;
Detach = playVFXOnChar.Detach;
DetachLifetime = playVFXOnChar.DetachLifetime;
VFXSystem vFX = ((PlayVFX)playVFXOnChar).VFX;
if (vFX != null && (int)SL_PlayVFX.GetVFXSystemEnum(vFX) != 0)
{
VFXPrefab = SL_PlayVFX.GetVFXSystemEnum(vFX);
}
}
}
public class PlayVFXOnChar : PlayVFX
{
public enum e_DetachMode
{
None,
Character,
World
}
public Vector3 Offset = Vector3.zero;
public e_DetachMode Detach;
public float DetachLifetime = 5f;
private static readonly FieldRef<PlayVFX, VFXSystem> StartVFXRef = AccessTools.FieldRefAccess<PlayVFX, VFXSystem>("m_startVFX");
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
((PlayVFX)this).ActivateLocally(_affectedCharacter, _infos);
if (!Object.op_Implicit((Object)(object)_affectedCharacter))
{
return;
}
VFXSystem val = StartVFXRef.Invoke((PlayVFX)(object)this);
if (Object.op_Implicit((Object)(object)val))
{
((Component)val).transform.position = ((Component)_affectedCharacter).transform.position + Offset;
if (Detach != e_DetachMode.None)
{
Transform val2 = ((Detach == e_DetachMode.Character) ? ((Component)_affectedCharacter).transform : null);
((Component)val).transform.SetParent(val2, true);
StartVFXRef.Invoke((PlayVFX)(object)this) = null;
Object.Destroy((Object)(object)((Component)val).gameObject, DetachLifetime);
}
}
}
}
public enum WeaponSlotOverride
{
Keep,
MainHand,
OffHand
}
public class SL_PlayVFXOnWeapon : SL_Effect, ICustomModel
{
public VFXPrefabs VFXPrefab;
public bool HitPos;
public e_ParentMode ParentMode;
public bool DontInstantiateNew;
public bool AllowSkinnedMesh = true;
public WeaponSlotOverride Slot;
public Type SLTemplateModel => typeof(SL_PlayVFXOnWeapon);
public Type GameModel => typeof(PlayVFXOnWeapon);
public override void ApplyToComponent<T>(T component)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
PlayVFXOnWeapon playVFXOnWeapon = component as PlayVFXOnWeapon;
((PlayVFX)playVFXOnWeapon).HitPos = HitPos;
((PlayVFX)playVFXOnWeapon).ParentMode = ParentMode;
((PlayVFX)playVFXOnWeapon).VfxAlreadyInst = DontInstantiateNew;
playVFXOnWeapon.AllowSkinnedMesh = AllowSkinnedMesh;
playVFXOnWeapon.SlotOverride = Slot;
GameObject vfxSystem = SL_PlayVFX.GetVfxSystem(VFXPrefab);
if (vfxSystem != null)
{
GameObject val = Object.Instantiate<GameObject>(vfxSystem);
Object.DontDestroyOnLoad((Object)(object)val);
val.SetActive(false);
((PlayVFX)playVFXOnWeapon).VFX = val.GetComponent<VFXSystem>();
Configure(val);
}
}
private void Configure(GameObject vfx)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
VFXParticlesOnWeapon[] componentsInChildren = vfx.GetComponentsInChildren<VFXParticlesOnWeapon>(true);
foreach (VFXParticlesOnWeapon val in componentsInChildren)
{
if (AllowSkinnedMesh)
{
val.CheckSkinnedMeshRenderer = true;
}
if (Slot == WeaponSlotOverride.MainHand)
{
val.Slot = (WeaponSlot)0;
}
else if (Slot == WeaponSlotOverride.OffHand)
{
val.Slot = (WeaponSlot)1;
}
}
}
public override void SerializeEffect<T>(T effect)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
PlayVFXOnWeapon playVFXOnWeapon = effect as PlayVFXOnWeapon;
HitPos = ((PlayVFX)playVFXOnWeapon).HitPos;
ParentMode = ((PlayVFX)playVFXOnWeapon).ParentMode;
DontInstantiateNew = ((PlayVFX)playVFXOnWeapon).VfxAlreadyInst;
AllowSkinnedMesh = playVFXOnWeapon.AllowSkinnedMesh;
Slot = playVFXOnWeapon.SlotOverride;
VFXSystem vFX = ((PlayVFX)playVFXOnWeapon).VFX;
if (vFX != null && (int)SL_PlayVFX.GetVFXSystemEnum(vFX) != 0)
{
VFXPrefab = SL_PlayVFX.GetVFXSystemEnum(vFX);
}
}
}
public class PlayVFXOnWeapon : PlayVFX
{
public bool AllowSkinnedMesh = true;
public WeaponSlotOverride SlotOverride;
}
public class SL_PlayVFXPulsed : SL_Effect, ICustomModel
{
public VFXPrefabs VFXPrefab;
public bool HitPos;
public e_ParentMode ParentMode;
public bool DontInstantiateNew;
public List<float> PulseAt = new List<float>();
public float PulseLength = 0.3f;
public bool HardClear = true;
public float StopAt;
public Type SLTemplateModel => typeof(SL_PlayVFXPulsed);
public Type GameModel => typeof(PlayVFXPulsed);
public override void ApplyToComponent<T>(T component)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
PlayVFXPulsed playVFXPulsed = component as PlayVFXPulsed;
((PlayVFX)playVFXPulsed).HitPos = HitPos;
((PlayVFX)playVFXPulsed).ParentMode = ParentMode;
((PlayVFX)playVFXPulsed).VfxAlreadyInst = DontInstantiateNew;
playVFXPulsed.PulseLength = PulseLength;
playVFXPulsed.HardClear = HardClear;
playVFXPulsed.StopAt = StopAt;
playVFXPulsed.PulseAt = ((PulseAt == null) ? new List<float>() : new List<float>(PulseAt));
if (playVFXPulsed.PulseAt.Count == 0 && StopAt <= 0f)
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_PlayVFXPulsed (" + ((object)Unsafe.As<VFXPrefabs, VFXPrefabs>(ref VFXPrefab)/*cast due to .constrained prefix*/).ToString() + "): no PulseAt times and no StopAt were read - it will behave as SL_PlayVFX. Each pulse must be a <float> element inside <PulseAt>."));
}
else
{
CustomEffectsPlugin.Log.LogMessage((object)("SL_PlayVFXPulsed (" + ((object)Unsafe.As<VFXPrefabs, VFXPrefabs>(ref VFXPrefab)/*cast due to .constrained prefix*/).ToString() + "): " + playVFXPulsed.PulseAt.Count + " pulse times, " + PulseLength + "s each, HardClear=" + HardClear + ((StopAt > 0f) ? (", stops at " + StopAt + "s") : "") + "."));
}
GameObject vfxSystem = SL_PlayVFX.GetVfxSystem(VFXPrefab);
if (vfxSystem != null)
{
GameObject val = Object.Instantiate<GameObject>(vfxSystem);
Object.DontDestroyOnLoad((Object)(object)val);
val.SetActive(false);
((PlayVFX)playVFXPulsed).VFX = val.GetComponent<VFXSystem>();
}
}
public override void SerializeEffect<T>(T effect)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: 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)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
PlayVFXPulsed playVFXPulsed = effect as PlayVFXPulsed;
HitPos = ((PlayVFX)playVFXPulsed).HitPos;
ParentMode = ((PlayVFX)playVFXPulsed).ParentMode;
DontInstantiateNew = ((PlayVFX)playVFXPulsed).VfxAlreadyInst;
PulseLength = playVFXPulsed.PulseLength;
HardClear = playVFXPulsed.HardClear;
StopAt = playVFXPulsed.StopAt;
PulseAt = ((playVFXPulsed.PulseAt == null) ? new List<float>() : new List<float>(playVFXPulsed.PulseAt));
VFXSystem vFX = ((PlayVFX)playVFXPulsed).VFX;
if (vFX != null && (int)SL_PlayVFX.GetVFXSystemEnum(vFX) != 0)
{
VFXPrefab = SL_PlayVFX.GetVFXSystemEnum(vFX);
}
}
}
public class PlayVFXPulsed : PlayVFX
{
public List<float> PulseAt = new List<float>();
public float PulseLength = 0.3f;
public bool HardClear = true;
public float StopAt;
private static readonly FieldRef<PlayVFX, VFXSystem> StartVFXRef = AccessTools.FieldRefAccess<PlayVFX, VFXSystem>("m_startVFX");
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
((PlayVFX)this).ActivateLocally(_affectedCharacter, _infos);
if ((PulseAt != null && PulseAt.Count > 0 && PulseLength > 0f) || StopAt > 0f)
{
((MonoBehaviour)this).StartCoroutine(PulseCoroutine());
}
}
private IEnumerator PulseCoroutine()
{
VFXSystem vfx = StartVFXRef.Invoke((PlayVFX)(object)this);
if (!Object.op_Implicit((Object)(object)vfx))
{
yield break;
}
ParticleSystem[] systems = ((Component)vfx).GetComponentsInChildren<ParticleSystem>(true);
if (systems.Length == 0)
{
yield break;
}
ParticleSystemStopBehavior stopBehaviour = (ParticleSystemStopBehavior)(!HardClear);
List<float> list = new List<float>(PulseAt);
list.Sort();
float elapsed = 0f;
ParticleSystem[] array;
foreach (float time in list)
{
if (StopAt > 0f && time >= StopAt)
{
break;
}
if (time < elapsed)
{
continue;
}
yield return (object)new WaitForSeconds(time - elapsed);
elapsed = time;
if (!Object.op_Implicit((Object)(object)vfx))
{
yield break;
}
array = systems;
foreach (ParticleSystem val in array)
{
if (Object.op_Implicit((Object)(object)val))
{
val.Stop(false, stopBehaviour);
}
}
yield return (object)new WaitForSeconds(PulseLength);
elapsed += PulseLength;
if (!Object.op_Implicit((Object)(object)vfx))
{
yield break;
}
array = systems;
foreach (ParticleSystem val2 in array)
{
if (Object.op_Implicit((Object)(object)val2))
{
val2.Play(false);
}
}
}
if (StopAt <= 0f)
{
yield break;
}
if (StopAt > elapsed)
{
yield return (object)new WaitForSeconds(StopAt - elapsed);
}
if (!Object.op_Implicit((Object)(object)vfx))
{
yield break;
}
array = systems;
foreach (ParticleSystem val3 in array)
{
if (Object.op_Implicit((Object)(object)val3))
{
val3.Stop(false, stopBehaviour);
}
}
}
}
public class SL_ReliableVisuals : SL_Effect, ICustomModel
{
public bool IncludeBlasts;
public Type SLTemplateModel => typeof(SL_ReliableVisuals);
public Type GameModel => typeof(ReliableVisuals);
public override void ApplyToComponent<T>(T component)
{
(component as ReliableVisuals).IncludeBlasts = IncludeBlasts;
}
public override void SerializeEffect<T>(T effect)
{
IncludeBlasts = (effect as ReliableVisuals).IncludeBlasts;
}
}
public class ReliableVisuals : Effect
{
public bool IncludeBlasts;
internal static readonly HashSet<string> Kicked = new HashSet<string>();
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
}
internal static bool IsLocallyControlled(Character c)
{
if (!Object.op_Implicit((Object)(object)c))
{
return false;
}
if (c.IsAI)
{
return PhotonNetwork.isMasterClient;
}
return c.IsLocalPlayer;
}
internal static bool IsVisual(Effect effect, bool includeBlasts)
{
if (effect is PlayVFX || effect is PlaySoundEffect || effect is PlayTimedSound)
{
return true;
}
if (includeBlasts && effect is ShootBlast)
{
return true;
}
return false;
}
}
[HarmonyPatch(typeof(StatusEffectManager), "AddStatusEffect", new Type[]
{
typeof(StatusEffect),
typeof(Character),
typeof(string[])
})]
public class StatusEffectManager_AddStatusEffect_Visuals
{
private static readonly FieldRef<StatusEffectManager, Character> ManagerCharacter = AccessTools.FieldRefAccess<StatusEffectManager, Character>("m_character");
private static bool s_loggedOnce;
[HarmonyPostfix]
public static void Postfix(StatusEffectManager __instance, StatusEffect __result)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)__result == (Object)null)
{
return;
}
ReliableVisuals componentInChildren = ((Component)__result).GetComponentInChildren<ReliableVisuals>(true);
if (!Object.op_Implicit((Object)(object)componentInChildren))
{
return;
}
Character val = ManagerCharacter.Invoke(__instance);
if (!Object.op_Implicit((Object)(object)val) || ReliableVisuals.IsLocallyControlled(val) || !((Component)__result).gameObject.activeInHierarchy)
{
return;
}
string item = UID.op_Implicit(__result.UID);
if (ReliableVisuals.Kicked.Add(item))
{
if (!s_loggedOnce)
{
s_loggedOnce = true;
CustomEffectsPlugin.Log.LogMessage((object)"SL_ReliableVisuals: arrival patch is live - marked statuses now play on every client.");
}
if (Object.op_Implicit((Object)(object)CustomEffectsPlugin.Instance))
{
((MonoBehaviour)CustomEffectsPlugin.Instance).StartCoroutine(PlayNextFrame(componentInChildren, __result, val));
}
}
}
private static IEnumerator PlayNextFrame(ReliableVisuals marker, StatusEffect status, Character affected)
{
yield return null;
Play(marker, status, affected);
}
private static void Play(ReliableVisuals marker, StatusEffect status, Character affected)
{
if (!Object.op_Implicit((Object)(object)marker) || !Object.op_Implicit((Object)(object)status) || !Object.op_Implicit((Object)(object)affected))
{
return;
}
int num = 0;
int num2 = 0;
Effect[] componentsInChildren = ((Component)status).GetComponentsInChildren<Effect>(true);
foreach (Effect val in componentsInChildren)
{
if (Object.op_Implicit((Object)(object)val) && ReliableVisuals.IsVisual(val, marker.IncludeBlasts))
{
try
{
val.Affect(affected);
num++;
}
catch (Exception ex)
{
num2++;
CustomEffectsPlugin.Log.LogWarning((object)("SL_ReliableVisuals: " + ((object)val).GetType().Name + " threw " + ex.GetType().Name + " - " + ex.Message));
}
}
}
CustomEffectsPlugin.Log.LogMessage((object)("SL_ReliableVisuals: played " + num + " visual effects for " + affected.Name + ((num2 > 0) ? (" (" + num2 + " FAILED)") : "") + " | isMaster=" + PhotonNetwork.isMasterClient + " isAI=" + affected.IsAI + " blasts=" + marker.IncludeBlasts));
}
}
[HarmonyPatch(typeof(StatusEffectManager), "OnReceiveActivatedStatusEffects")]
public class StatusEffectManager_OnReceiveActivatedStatusEffects
{
[HarmonyPrefix]
public static bool Prefix(string _statusUID)
{
if (string.IsNullOrEmpty(_statusUID))
{
return true;
}
if (ReliableVisuals.Kicked.Remove(_statusUID))
{
CustomEffectsPlugin.Log.LogMessage((object)("SL_ReliableVisuals: suppressed a duplicate activation message for " + _statusUID));
return false;
}
return true;
}
}
public enum SkillTarget
{
Owner,
AffectedCharacter
}
public class SL_UseSkill : SL_Effect, ICustomModel
{
public int SkillID = -1;
public SkillTarget Target;
public float MaxWait = 3f;
public Type SLTemplateModel => typeof(SL_UseSkill);
public Type GameModel => typeof(UseSkillEffect);
public override void ApplyToComponent<T>(T component)
{
UseSkillEffect obj = component as UseSkillEffect;
obj.SkillID = SkillID;
obj.Target = Target;
obj.MaxWait = MaxWait;
}
public override void SerializeEffect<T>(T effect)
{
UseSkillEffect useSkillEffect = effect as UseSkillEffect;
SkillID = useSkillEffect.SkillID;
Target = useSkillEffect.Target;
MaxWait = useSkillEffect.MaxWait;
}
}
public class UseSkillEffect : Effect
{
public int SkillID = -1;
public SkillTarget Target;
public float MaxWait = 3f;
private static bool IsFree(Character c)
{
if (Object.op_Implicit((Object)(object)c) && c.InLocomotion && c.NextIsLocomotion && !c.IsCasting && !c.IsHandlingBag)
{
return !c.IsHandlingWeapon;
}
return false;
}
protected override void ActivateLocally(Character _affectedCharacter, object[] _infos)
{
Character val = (((Object)(object)base.m_parentSynchronizer != (Object)null) ? base.m_parentSynchronizer.OwnerCharacter : null);
Character val2 = ((Target == SkillTarget.Owner) ? val : _affectedCharacter);
if (!Object.op_Implicit((Object)(object)val2))
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_UseSkill: no " + Target.ToString() + " character to cast skill " + SkillID + " - skipping."));
}
else if (IsLocallyControlled(val2))
{
Item itemFromItemID = ((CharacterKnowledge)val2.Inventory.SkillKnowledge).GetItemFromItemID(SkillID);
Skill val3 = (Skill)(object)((itemFromItemID is Skill) ? itemFromItemID : null);
if (!Object.op_Implicit((Object)(object)val3))
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_UseSkill: " + val2.Name + " does not know skill " + SkillID + " - nothing cast. Teach it first (see SL_LearnSkillHidden) or use a skill the character knows."));
}
else
{
((MonoBehaviour)CustomEffectsPlugin.Instance).StartCoroutine(CastWhenFree(val2, val3));
}
}
}
private static bool IsLocallyControlled(Character c)
{
if (!Object.op_Implicit((Object)(object)c))
{
return false;
}
if (c.IsAI)
{
return PhotonNetwork.isMasterClient;
}
return c.IsLocalPlayer;
}
private IEnumerator CastWhenFree(Character caster, Skill skill)
{
float waited = 0f;
while (Object.op_Implicit((Object)(object)caster) && !IsFree(caster) && waited < MaxWait)
{
waited += Time.deltaTime;
yield return null;
}
if (Object.op_Implicit((Object)(object)caster) && Object.op_Implicit((Object)(object)skill))
{
if (!IsFree(caster))
{
CustomEffectsPlugin.Log.LogWarning((object)("SL_UseSkill: " + caster.Name + " never became free within " + MaxWait + "s (InLocomotion=" + caster.InLocomotion + " NextIsLocomotion=" + caster.NextIsLocomotion + " IsCasting=" + caster.IsCasting + " HandlingBag=" + caster.IsHandlingBag + " HandlingWeapon=" + caster.IsHandlingWeapon + ") - skill " + SkillID + " not cast."));
}
else
{
((Item)skill).TryQuickSlotUse();
}
}
}
}
}