using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OutwardModTemplate")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OutwardModTemplate")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace CustomAttributes;
[DisallowMultipleComponent]
public class CustomAttributeComponent : MonoBehaviour
{
public float safetyCritHit;
public float safetyCritHeal;
public float safetyAvoidance;
public static Dictionary<string, float> ManualCritRate = new Dictionary<string, float>();
public static Dictionary<string, float> ManualCritHeal = new Dictionary<string, float>();
public static Dictionary<string, float> ManualCritScaling = new Dictionary<string, float>();
public static Dictionary<string, float> ManualAvoidance = new Dictionary<string, float>();
public static Dictionary<string, float> ManualLeech = new Dictionary<string, float>();
public Character parentPlayer { get; private set; }
public virtual void Awake()
{
parentPlayer = ((Component)this).GetComponent<Character>();
}
public void ManualCritRateStore(string modID, float value)
{
if (ManualCritRate.ContainsKey(modID))
{
ManualCritRate.Remove(modID);
}
ManualCritRate.Add(modID, value);
}
public float GetManualCritRate()
{
float num = 0f;
foreach (KeyValuePair<string, float> item in ManualCritRate)
{
num += item.Value;
}
return num;
}
public float CalculateFinalCritRate(float additionalCrit = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return 0f + (GetManualCritRate() + CustomAttributeHelper.GetPassiveCritRate(parentPlayer) + CustomAttributeHelper.GetStatusCritRate(parentPlayer) + additionalCrit);
}
public bool ShouldCrit()
{
if (!CritAllowed())
{
return false;
}
float num = CalculateFinalCritRate();
if (num >= 1f)
{
if ((float)Random.Range(1, 101) <= num + safetyCritHit)
{
safetyCritHit = 0f;
return true;
}
float num2 = num * 0.1f;
safetyCritHit += num2;
}
return false;
}
public bool CritAllowed()
{
foreach (KeyValuePair<string, float> statusCritCanceler in CustomAttributeHelper.StatusCritCancelers)
{
if (statusCritCanceler.Key != null && parentPlayer.StatusEffectMngr.HasStatusEffect(statusCritCanceler.Key))
{
return false;
}
}
return true;
}
public void ManualCritHealStore(string modID, float value)
{
if (ManualCritHeal.ContainsKey(modID))
{
ManualCritHeal.Remove(modID);
}
ManualCritHeal.Add(modID, value);
}
public float GetManualCritHeal()
{
float num = 0f;
foreach (KeyValuePair<string, float> item in ManualCritHeal)
{
num += item.Value;
}
return num;
}
public float CalculateFinalCritHealRate(float additionalCritHeal = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return 0f + (GetManualCritHeal() + CustomAttributeHelper.GetPassiveCritHeal(parentPlayer) + CustomAttributeHelper.GetStatusCritHeal(parentPlayer) + additionalCritHeal);
}
public bool ShouldCritHeal(bool smallHeal = false)
{
float num = CalculateFinalCritHealRate();
if (smallHeal)
{
num *= 0.5f;
}
if (num >= 1f)
{
if ((float)Random.Range(1, 101) <= num + safetyCritHeal)
{
safetyCritHeal = 0f;
return true;
}
float num2 = num * 0.1f;
safetyCritHeal += num2;
}
return false;
}
public void ManualCritScalingStore(string modID, float value)
{
if (ManualCritScaling.ContainsKey(modID))
{
ManualCritScaling.Remove(modID);
}
ManualCritScaling.Add(modID, value);
}
public float GetManualCritScaling()
{
float num = 0f;
foreach (KeyValuePair<string, float> item in ManualCritScaling)
{
num += item.Value;
}
return num;
}
public float CalculateFinalScalingCrit(float extraScalingCrit = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return (CustomAttributeManager.BaseCritScaling + (GetManualCritScaling() + CustomAttributeHelper.GetPassiveCritScaling(parentPlayer) + CustomAttributeHelper.GetStatusCritScaling(parentPlayer) + extraScalingCrit)) / 100f + 1f;
}
public float ProcessCriticalScaling(float amount)
{
return CustomAttributeHelper.Rounder(amount * CalculateFinalScalingCrit());
}
public void ManualAvoidanceStore(string modID, float value)
{
if (ManualAvoidance.ContainsKey(modID))
{
ManualAvoidance.Remove(modID);
}
ManualAvoidance.Add(modID, value);
}
public float GetManualAvoidance()
{
float num = 0f;
foreach (KeyValuePair<string, float> item in ManualAvoidance)
{
num += item.Value;
}
return num;
}
public float CalculateFinalAvoidance(float additionalAvoidance = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return 0f + (GetManualAvoidance() + CustomAttributeHelper.GetPassiveAvoidance(parentPlayer) + CustomAttributeHelper.GetStatusAvoidance(parentPlayer) + additionalAvoidance);
}
public bool ShouldAvoid()
{
if (!AvoidAllowed())
{
return false;
}
float num = CalculateFinalAvoidance();
if (num >= 1f)
{
if ((float)Random.Range(1, 101) <= num + safetyAvoidance)
{
safetyAvoidance = 0f;
return true;
}
float num2 = num * 0.1f;
safetyAvoidance += num2;
}
return false;
}
public bool AvoidAllowed()
{
foreach (KeyValuePair<string, float> statusAvoidCanceler in CustomAttributeHelper.StatusAvoidCancelers)
{
if (statusAvoidCanceler.Key != null && parentPlayer.StatusEffectMngr.HasStatusEffect(statusAvoidCanceler.Key))
{
return false;
}
}
return true;
}
public void ManualLeechStore(string modID, float value)
{
if (ManualLeech.ContainsKey(modID))
{
ManualLeech.Remove(modID);
}
ManualLeech.Add(modID, value);
}
public float GetManualLeech()
{
float num = 0f;
foreach (KeyValuePair<string, float> item in ManualLeech)
{
num += item.Value;
}
return num;
}
public float CalculateFinalLeech(float additionalLeech = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return 0f + (GetManualLeech() + CustomAttributeHelper.GetPassiveLeech(parentPlayer) + CustomAttributeHelper.GetStatusLeech(parentPlayer) + additionalLeech);
}
public void DoLeech(float totalDamage)
{
float num = CalculateFinalLeech();
if (num <= 0f)
{
return;
}
float num2 = CustomAttributeHelper.Rounder(num / 100f * totalDamage);
float num3 = parentPlayer.Stats.CurrentStamina / parentPlayer.Stats.ActiveMaxStamina;
float num4 = parentPlayer.Stats.CurrentMana / parentPlayer.Stats.ActiveMaxMana;
if (num3 < num4 || parentPlayer.Stats.MaxMana <= 0f)
{
if (CustomAttributesBase.LeechNotif.Value)
{
parentPlayer.CharacterUI.ShowInfoNotification("Leech " + num2 + " to Stam");
}
parentPlayer.Stats.AffectStamina(num2);
}
else if (parentPlayer.Mana > 0f && num4 < num3)
{
if (CustomAttributesBase.LeechNotif.Value)
{
parentPlayer.CharacterUI.ShowInfoNotification("Leech " + num2 + " to Mana");
}
parentPlayer.Stats.RestaureMana((Tag[])(object)new Tag[3], num2);
}
}
public float CalculateFinalSelfCrit(float additionalSelfCrit = 0f)
{
if (!parentPlayer.IsLocalPlayer)
{
return 0f;
}
return 0f + (CustomAttributeHelper.GetPassiveSelfCrit(parentPlayer) + CustomAttributeHelper.GetStatusSelfCrit(parentPlayer) + additionalSelfCrit);
}
public bool ShouldSelfCritFromAI()
{
float num = CalculateFinalSelfCrit();
if (num >= 1f && (float)Random.Range(1, 101) <= num)
{
return true;
}
return false;
}
public float ProcessSelfCritical(float amount)
{
float num = CustomAttributeManager.AIcritScaling / 100f + 1f;
return CustomAttributeHelper.Rounder(amount * num);
}
}
public static class CustomAttributeHelper
{
public static Dictionary<int, float> PassivesCritRate = new Dictionary<int, float>();
public static Dictionary<string, float> StatusCritRate = new Dictionary<string, float>();
public static Dictionary<string, float> StatusCritCancelers = new Dictionary<string, float>();
public static Dictionary<int, float> PassivesCritHeal = new Dictionary<int, float>();
public static Dictionary<string, float> StatusCritHeal = new Dictionary<string, float>();
public static Dictionary<int, float> PassivesCritScaling = new Dictionary<int, float>();
public static Dictionary<string, float> StatusCritScaling = new Dictionary<string, float>();
public static Dictionary<int, float> PassivesAvoidance = new Dictionary<int, float>();
public static Dictionary<string, float> StatusAvoidance = new Dictionary<string, float>();
public static Dictionary<string, float> StatusAvoidCancelers = new Dictionary<string, float>();
public static Dictionary<int, float> PassivesLeech = new Dictionary<int, float>();
public static Dictionary<string, float> StatusLeech = new Dictionary<string, float>();
public static Dictionary<int, float> PassivesSelfCrit = new Dictionary<int, float>();
public static Dictionary<string, float> StatusSelfCrit = new Dictionary<string, float>();
public static float Rounder(float amount)
{
return (float)Math.Round(amount, 2);
}
public static void PassiveCritRateStore(int skillID, float value)
{
PassivesCritRate.Add(skillID, value);
}
public static float GetPassiveCritRate(Character player)
{
if (PassivesCritRate.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesCritRate)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusCritRateStore(string skillID, float value)
{
StatusCritRate.Add(skillID, value);
}
public static float GetStatusCritRate(Character player)
{
if (StatusCritRate.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusCritRate)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
public static void StatusCritCancelerStore(string skillID, float value = 0f)
{
StatusCritCancelers.Add(skillID, value);
}
public static void PassiveCritHealStore(int skillID, float value)
{
PassivesCritHeal.Add(skillID, value);
}
public static float GetPassiveCritHeal(Character player)
{
if (PassivesCritHeal.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesCritHeal)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusCritHealStore(string skillID, float value)
{
StatusCritHeal.Add(skillID, value);
}
public static float GetStatusCritHeal(Character player)
{
if (StatusCritHeal.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusCritHeal)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
public static void PassiveCritScalingStore(int skillID, float value)
{
PassivesCritScaling.Add(skillID, value);
}
public static float GetPassiveCritScaling(Character player)
{
if (PassivesCritScaling.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesCritScaling)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusCritScalingStore(string skillID, float value)
{
StatusCritScaling.Add(skillID, value);
}
public static float GetStatusCritScaling(Character player)
{
if (StatusCritScaling.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusCritScaling)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
public static void PassiveAvoidanceStore(int skillID, float value)
{
PassivesAvoidance.Add(skillID, value);
}
public static float GetPassiveAvoidance(Character player)
{
if (PassivesAvoidance.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesAvoidance)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusAvoidanceStore(string skillID, float value)
{
StatusAvoidance.Add(skillID, value);
}
public static float GetStatusAvoidance(Character player)
{
if (StatusAvoidance.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusAvoidance)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
public static void StatusAvoidCancelerStore(string skillID, float value = 0f)
{
StatusAvoidCancelers.Add(skillID, value);
}
public static void PassiveLeechStore(int skillID, float value)
{
PassivesLeech.Add(skillID, value);
}
public static float GetPassiveLeech(Character player)
{
if (PassivesLeech.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesLeech)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusLeechStore(string skillID, float value)
{
StatusLeech.Add(skillID, value);
}
public static float GetStatusLeech(Character player)
{
if (StatusLeech.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusLeech)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
public static void PassiveSelfCritStore(int skillID, float value)
{
PassivesSelfCrit.Add(skillID, value);
}
public static float GetPassiveSelfCrit(Character player)
{
if (PassivesSelfCrit.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<int, float> item in PassivesSelfCrit)
{
if (((CharacterKnowledge)player.Inventory.SkillKnowledge).IsItemLearned(item.Key))
{
num += item.Value;
}
}
return num;
}
public static void StatusSelfCritStore(string skillID, float value)
{
StatusSelfCrit.Add(skillID, value);
}
public static float GetStatusSelfCrit(Character player)
{
if (StatusSelfCrit.Count <= 0)
{
return 0f;
}
float num = 0f;
foreach (KeyValuePair<string, float> item in StatusSelfCrit)
{
if (item.Key != null && player.StatusEffectMngr.HasStatusEffect(item.Key))
{
num += (float)player.StatusEffectMngr.GetStatusLevel(item.Key) * item.Value;
}
}
return num;
}
}
public static class CustomAttributeManager
{
[HarmonyPatch(typeof(Character), "ReceiveHit", new Type[]
{
typeof(Object),
typeof(DamageList),
typeof(Vector3),
typeof(Vector3),
typeof(float),
typeof(float),
typeof(Character),
typeof(float),
typeof(bool)
})]
public class Character_ReceiveHit
{
[HarmonyPrefix]
public static void Prefix(Character __instance, Object _damageSource, ref DamageList _damage, Vector3 _hitDir, Vector3 _hitPoint, float _angle, float _angleDir, Character _dealerChar, ref float _knockBack, bool _hitInventory)
{
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0262: Unknown result type (might be due to invalid IL or missing references)
//IL_026c: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
//IL_035e: Unknown result type (might be due to invalid IL or missing references)
//IL_0363: Unknown result type (might be due to invalid IL or missing references)
//IL_036d: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)_dealerChar) || !Object.op_Implicit((Object)(object)__instance))
{
return;
}
if (_knockBack > 0f && _dealerChar.IsLocalPlayer && __instance.IsAI)
{
StatusEffect val = (StatusEffect)(object)((_damageSource is StatusEffect) ? _damageSource : null);
CustomAttributeComponent component = ((Component)_dealerChar).GetComponent<CustomAttributeComponent>();
if ((Object)(object)component == (Object)null)
{
Debug.LogError((object)"Hit AttComponent Null!");
}
else
{
if ((Object)(object)val != (Object)null)
{
return;
}
if (component.ShouldCrit())
{
foreach (DamageType item in _damage.List)
{
int num = _damage.IndexOf(item.Type);
if (_damage[num] != null && _damage[num].Damage > 0f)
{
float damage = component.ProcessCriticalScaling(_damage[num].Damage);
_damage[num].Damage = damage;
}
}
if (CustomAttributesBase.CritNotifs.Value)
{
_dealerChar.CharacterUI.ShowInfoNotification("CRIT! " + (int)_damage.TotalDamage);
}
if (CustomAttributesBase.CritPopup.Value)
{
TextDisplayManager.RegisterAttEvent(__instance.CenterPosition + new Vector3(0f, 0.4f, 0f), "CRIT!", Color.red);
}
CustomAttributesBase.Instance.OnCharacterCritEvent?.Invoke(_dealerChar, __instance, _damage.TotalDamage);
}
component.DoLeech(_damage.TotalDamage);
}
}
else
{
if (!(_knockBack > 0f) || !__instance.IsLocalPlayer || !_dealerChar.IsAI)
{
return;
}
CustomAttributeComponent component2 = ((Component)__instance).GetComponent<CustomAttributeComponent>();
if ((Object)(object)component2 == (Object)null)
{
Debug.LogError((object)"Hit AttComponent Null!");
}
else if (component2.ShouldAvoid())
{
if (CustomAttributesBase.AvoidNotifs.Value)
{
__instance.CharacterUI.ShowInfoNotification("Miss! " + _damage.TotalDamage);
}
CustomAttributesBase.Instance.OnCharacterAvoidEvent?.Invoke(__instance, _dealerChar, _damage.TotalDamage);
_damage.Clear();
_knockBack = 0f;
if (CustomAttributesBase.AvoidPopup.Value)
{
TextDisplayManager.RegisterAttEvent(__instance.CenterPosition + new Vector3(0f, 0.4f, 0f), "Miss!", Color.gray);
}
}
else
{
if (!component2.ShouldSelfCritFromAI())
{
return;
}
foreach (DamageType item2 in _damage.List)
{
int num2 = _damage.IndexOf(item2.Type);
if (_damage[num2] != null && _damage[num2].Damage > 0f)
{
float damage2 = component2.ProcessSelfCritical(_damage[num2].Damage);
_damage[num2].Damage = damage2;
}
}
if (CustomAttributesBase.CritNotifs.Value)
{
__instance.CharacterUI.ShowInfoNotification("Crushd!: " + (int)_damage.TotalDamage);
}
if (CustomAttributesBase.CritPopup.Value)
{
TextDisplayManager.RegisterAttEvent(__instance.CenterPosition + new Vector3(0f, 0.4f, 0f), "Crush!", Color.yellow);
}
CustomAttributesBase.Instance.OnCharacterSelfCritFromAI?.Invoke(__instance, _dealerChar, _damage.TotalDamage);
}
}
}
}
[HarmonyPatch(typeof(CharacterStats), "AffectHealth")]
public class CharacterStats_AffectHealth
{
[HarmonyPrefix]
public static void Prefix(CharacterStats __instance, ref float _quantity)
{
if (_quantity <= 0f || !Object.op_Implicit((Object)(object)__instance) || !__instance.m_character.IsLocalPlayer)
{
return;
}
CustomAttributeComponent component = ((Component)__instance.m_character).GetComponent<CustomAttributeComponent>();
if ((Object)(object)component == (Object)null)
{
Debug.LogError((object)"AffectHealth AttComponent Null!");
}
else if ((_quantity < 5f) ? component.ShouldCritHeal(smallHeal: true) : component.ShouldCritHeal())
{
float num = component.ProcessCriticalScaling(_quantity);
CustomAttributesBase.Instance.OnCharacterCritHealEvent?.Invoke(__instance.m_character, _quantity);
_quantity = num;
if (CustomAttributesBase.CritHealNotifs.Value)
{
__instance.m_character.CharacterUI.ShowInfoNotification("CritHeal! " + num);
}
}
}
}
public static float BaseCritScaling = 50f;
public static float AIcritScaling = 50f;
}
[BepInPlugin("iggy.customattributes", "Custom Attributes", "1.0.0")]
public class CustomAttributesBase : BaseUnityPlugin
{
[HarmonyPatch(typeof(Character), "Awake")]
public class CharacterAwakePatch
{
private static void Postfix(Character __instance)
{
if ((Object)(object)__instance != (Object)null)
{
((Component)__instance).gameObject.AddComponent<CustomAttributeComponent>();
}
}
}
public const string GUID = "iggy.customattributes";
public const string NAME = "Custom Attributes";
public const string VERSION = "1.0.0";
internal static ManualLogSource Log;
public static ConfigEntry<bool> ExampleConfig;
public static CustomAttributesBase Instance;
public Action<Character, Character, float> OnCharacterCritEvent;
public Action<Character, float> OnCharacterCritHealEvent;
public Action<Character, Character, float> OnCharacterAvoidEvent;
public Action<Character, Character, float> OnCharacterSelfCritFromAI;
public static ConfigEntry<bool> CritNotifs;
public static ConfigEntry<bool> CritHealNotifs;
public static ConfigEntry<bool> AvoidNotifs;
public static ConfigEntry<bool> LeechNotif;
public static ConfigEntry<bool> CritPopup;
public static ConfigEntry<bool> AvoidPopup;
internal void Awake()
{
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
Log.LogMessage((object)"Custom Attributes 1.0.0 Loaded");
Instance = this;
CritNotifs = ((BaseUnityPlugin)this).Config.Bind<bool>("Trigger Notifications", "Critical Hit Notifications", false, "Disable to: Hide notifications about dealing or receiving a critical hit.");
CritHealNotifs = ((BaseUnityPlugin)this).Config.Bind<bool>("Trigger Notifications", "Critical Heals Notifications", true, "Disable to: Hide notifications about your critical heals.");
AvoidNotifs = ((BaseUnityPlugin)this).Config.Bind<bool>("Trigger Notifications", "Avoidance Notifications", false, "Disable to: Hide notifications about avoiding a hit.");
LeechNotif = ((BaseUnityPlugin)this).Config.Bind<bool>("Trigger Notifications", "Leech Notifications", false, "Disable to: Hide notifications about the amount and resource leeched.");
CritPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("Flying Text", "Critical Hit Text", true, "Disable to: Hide flying text about dealing or receiving a critical hit.");
AvoidPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("Flying Text", "Avoidance text", true, "Disable to: Hide flying text about avoiding/missing a hit.");
new Harmony("iggy.customattributes").PatchAll();
TextDisplayManager.Init();
}
internal void Update()
{
TextDisplayManager.Update();
}
}
public class TextInfo
{
public Vector3 hitPos;
public float hitTime;
public Text[] refTexts = (Text[])(object)new Text[2];
public TextInfo(Vector3 pos)
{
//IL_0013: 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)
hitPos = pos;
hitTime = Time.time;
}
}
public class TextDisplayManager
{
private static Canvas Canvas;
private static readonly List<TextInfo> AttEvent = new List<TextInfo>();
private static readonly List<Text>[] TextPools = new List<Text>[2]
{
new List<Text>(),
new List<Text>()
};
private static Font DefaultFont;
public static void RegisterAttEvent(Vector3 position, string attEventText, Color attEventColor)
{
//IL_0000: 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)
TextInfo textInfo = new TextInfo(position);
AttEvent.Add(textInfo);
textInfo.refTexts = BorrowOrCreateTexts(attEventText, attEventColor);
}
internal static void Init()
{
//IL_0005: 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)
//IL_0010: Expected O, but got Unknown
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("CustomAttCanvas");
Object.DontDestroyOnLoad((Object)val);
Canvas = val.AddComponent<Canvas>();
Canvas.renderMode = (RenderMode)0;
Canvas.sortingOrder = 999;
Canvas.referencePixelsPerUnit = 100f;
CanvasScaler obj = val.AddComponent<CanvasScaler>();
obj.referenceResolution = new Vector2(1920f, 1080f);
obj.screenMatchMode = (ScreenMatchMode)1;
DefaultFont = Resources.FindObjectsOfTypeAll<Font>().First((Font it) => ((Object)it).name.Contains("Philosopher"));
}
internal static void Update()
{
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
for (int num = AttEvent.Count - 1; num >= 0; num--)
{
TextInfo textInfo = AttEvent[num];
if (Time.time - textInfo.hitTime > 1.5f)
{
ReturnTexts(textInfo);
AttEvent.RemoveAt(num);
}
else
{
for (int i = 0; i < SplitScreenManager.Instance.LocalPlayerCount; i++)
{
Text val = textInfo.refTexts[i];
SplitPlayer val2 = SplitScreenManager.Instance.LocalPlayers[i];
int num2;
if (!MenuManager.Instance.IsMapDisplayed)
{
MenuPanel currentMenu = val2.AssignedCharacter.CharacterUI.GetCurrentMenu();
num2 = ((currentMenu != null && ((UIElement)currentMenu).IsDisplayed) ? 1 : 0);
}
else
{
num2 = 1;
}
Camera cameraScript = val2.CameraScript;
if (num2 != 0 || Vector3.Distance(((Component)val2.AssignedCharacter).transform.position, textInfo.hitPos) > 50f)
{
((Component)val).gameObject.SetActive(false);
continue;
}
Vector3 val3 = textInfo.hitPos + Vector3.up * (Time.time - textInfo.hitTime) * 0.5f;
Vector3 screenPos = cameraScript.WorldToViewportPoint(val3);
if (IsScreenPosVisible(ref screenPos, i))
{
((Component)val).transform.position = new Vector3(screenPos.x, screenPos.y, 0f);
((Component)val).gameObject.SetActive(true);
}
}
}
}
}
internal static Text[] BorrowOrCreateTexts(string attEventText, Color attColor)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: 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_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
Text[] array = (Text[])(object)new Text[2];
for (int i = 0; i < 2; i++)
{
List<Text> list = TextPools[i];
if (list.Any())
{
Text val = list.First();
list.RemoveAt(0);
((Component)val).gameObject.SetActive(true);
array[i] = val;
val.text = attEventText;
((Graphic)val).color = attColor;
continue;
}
GameObject val2 = new GameObject("Text");
val2.transform.parent = ((Component)Canvas).transform;
RectTransform obj = val2.AddComponent<RectTransform>();
obj.pivot = new Vector2(0.5f, 0.5f);
obj.anchorMin = obj.pivot;
obj.anchorMax = obj.pivot;
obj.sizeDelta = new Vector2(200f, 50f);
Text val3 = val2.AddComponent<Text>();
val3.text = attEventText;
val3.font = DefaultFont;
val3.fontSize = 20;
val3.alignment = (TextAnchor)4;
array[i] = val3;
((Graphic)val3).color = attColor;
}
return array;
}
internal static void ReturnTexts(TextInfo attEvent)
{
for (int i = 0; i < 2; i++)
{
Text val = attEvent.refTexts[i];
((Component)val).gameObject.SetActive(false);
TextPools[i].Add(val);
}
}
private static bool IsScreenPosVisible(ref Vector3 screenPos, int splitID)
{
float num = 0f;
float num2 = 1080f;
screenPos.x *= Relative(1920f);
if (SplitScreenManager.Instance.LocalPlayerCount == 1)
{
screenPos.y *= Relative(1080f, height: true);
if (screenPos.z > 0f && screenPos.x >= 0f && screenPos.x <= 1920f && screenPos.y >= num)
{
return screenPos.y <= num2;
}
return false;
}
screenPos.y *= Relative(540f, height: true);
if (splitID == 0)
{
num = Relative(540f, height: true);
screenPos.y += num;
if (screenPos.z > 0f && screenPos.x >= 0f && screenPos.x <= Relative(1920f) && screenPos.y >= num)
{
return screenPos.y <= num2;
}
return false;
}
num2 = Relative(540f, height: true);
if (screenPos.z > 0f && screenPos.x >= 0f && screenPos.x <= Relative(1920f) && screenPos.y >= num)
{
return screenPos.y <= num2;
}
return false;
}
public static float Relative(float offset, bool height = false)
{
return offset * (float)(height ? Screen.height : Screen.width) * 100f / (height ? 1080f : 1920f) * 0.01f;
}
}