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 MobThreat v1.0.2
plugins/Jarki-MobThreat/MobThreat.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MobThreat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2+4290106b332b8be71230f3163086c278272a925e")] [assembly: AssemblyProduct("MobThreat")] [assembly: AssemblyTitle("MobThreat")] [assembly: AssemblyVersion("1.0.2.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 MobThreat { [DefaultExecutionOrder(10000)] [BepInPlugin("local.mobthreat", "MobThreat", "1.0.2")] public sealed class Plugin : BaseUnityPlugin { private sealed class Label { internal Character Mob; internal int Hits = -1; internal TextMeshProUGUI Text; internal string Caption; internal Vector2 Screen; internal bool Visible; internal void Set(Character mob, int hits) { Mob = mob; if (Hits != hits) { Hits = hits; Caption = ((hits == 1) ? "~1 hit" : ("~" + hits + " hits")); if (Object.op_Implicit((Object)(object)Text)) { ((TMP_Text)Text).text = Caption; } } } } private readonly List<Character> nearby = new List<Character>(); private readonly List<Label> labels = new List<Label>(); private readonly ThreatEstimator estimator = new ThreatEstimator(); private ConfigEntry<bool> displayEnabled; private ConfigEntry<float> distance; private GameObject overlay; private TMP_FontAsset font; private float nextSample; private int active; private int wallMask; private void Awake() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown displayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show estimated unblocked hits to death above hostile mobs."); distance = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "MaxDistance", 35f, new ConfigDescription("Maximum label distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>())); wallMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" }); } private bool CanDisplay() { Player localPlayer = Player.m_localPlayer; if (displayEnabled != null && displayEnabled.Value && Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InCutscene() && Object.op_Implicit((Object)(object)Game.instance)) { return !Hud.IsUserHidden(); } return false; } private void LateUpdate() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) if (!CanDisplay()) { Clear(); nextSample = 0f; return; } Player localPlayer = Player.m_localPlayer; if (Time.unscaledTime >= nextSample) { nextSample = Time.unscaledTime + 0.25f; Sample(localPlayer); } Camera mainCamera = Utils.GetMainCamera(); for (int i = 0; i < active; i++) { Label label = labels[i]; label.Visible = false; if (Object.op_Implicit((Object)(object)mainCamera) && Object.op_Implicit((Object)(object)label.Mob) && !label.Mob.IsDead() && !label.Mob.m_hideHud) { Vector3 val = label.Mob.GetTopPoint() + Vector3.up * 0.45f; Vector3 val2 = Utils.WorldToScreenPointScaled(mainCamera, val); if (!(val2.z <= 0f) && !(val2.x < 0f) && !(val2.x > (float)Screen.width) && !(val2.y < 0f) && !(val2.y > (float)Screen.height) && !Physics.Linecast(((Component)mainCamera).transform.position, val, wallMask, (QueryTriggerInteraction)1)) { label.Screen = new Vector2(val2.x, val2.y); label.Visible = true; } } } DrawLabels(); } private void Sample(Player player) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) nearby.Clear(); Character.GetCharactersInRange(((Component)player).transform.position, distance.Value, nearby); DamageModifiers damageModifiers = ((Character)player).GetDamageModifiers((WeakSpot)null); float bodyArmor = ((Character)player).GetBodyArmor(); float difficultyDamageScalePlayer = Game.instance.GetDifficultyDamageScalePlayer(((Component)player).transform.position); int num = 0; for (int i = 0; i < nearby.Count; i++) { Character val = nearby[i]; if (!Object.op_Implicit((Object)(object)val) || val.IsPlayer() || val.IsDead() || val.m_hideHud || !Object.op_Implicit((Object)(object)val.GetBaseAI()) || !BaseAI.IsEnemy((Character)(object)player, val)) { continue; } Humanoid val2 = (Humanoid)(object)((val is Humanoid) ? val : null); int num2 = ((val2 != null) ? ThreatMath.HitsToDie(((Character)player).GetHealth(), estimator.Estimate(val2, damageModifiers, bodyArmor, difficultyDamageScalePlayer)) : 0); if (num2 > 0) { if (num == labels.Count) { labels.Add(new Label()); } labels[num++].Set(val, num2); } } for (int j = num; j < active; j++) { labels[j].Mob = null; labels[j].Visible = false; if (Object.op_Implicit((Object)(object)labels[j].Text)) { ((Component)labels[j].Text).gameObject.SetActive(false); } } active = num; nearby.Clear(); } private void DrawLabels() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0235: 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_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown if (active == 0) { if (Object.op_Implicit((Object)(object)overlay)) { overlay.SetActive(false); } return; } if (!Object.op_Implicit((Object)(object)overlay)) { GameObject val = (Object.op_Implicit((Object)(object)EnemyHud.instance) ? EnemyHud.instance.m_baseHud : null); Transform val2 = (Object.op_Implicit((Object)(object)val) ? val.transform.Find("Name") : null); TextMeshProUGUI val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<TextMeshProUGUI>() : null); if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)((TMP_Text)val3).font)) { return; } font = ((TMP_Text)val3).font; overlay = new GameObject("MobThreatOverlay", new Type[2] { typeof(RectTransform), typeof(Canvas) }); overlay.transform.SetParent(((Component)this).transform, false); Canvas component = overlay.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 30000; } overlay.SetActive(true); for (int i = 0; i < active; i++) { Label label = labels[i]; if (!Object.op_Implicit((Object)(object)label.Text)) { GameObject val4 = new GameObject("Threat", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val4.transform.SetParent(overlay.transform, false); label.Text = val4.GetComponent<TextMeshProUGUI>(); ((TMP_Text)label.Text).font = font; ((TMP_Text)label.Text).fontSharedMaterial = ((TMP_Asset)font).material; ((TMP_Text)label.Text).fontSize = 20f; ((TMP_Text)label.Text).fontStyle = (FontStyles)1; ((TMP_Text)label.Text).alignment = (TextAlignmentOptions)514; ((Graphic)label.Text).raycastTarget = false; ((TMP_Text)label.Text).richText = false; ((TMP_Text)label.Text).text = label.Caption; RectTransform rectTransform = ((TMP_Text)label.Text).rectTransform; Vector2 anchorMin = (rectTransform.anchorMax = Vector2.zero); rectTransform.anchorMin = anchorMin; rectTransform.pivot = new Vector2(0.5f, 0f); rectTransform.sizeDelta = new Vector2(180f, 32f); } bool flag = label.Visible && Object.op_Implicit((Object)(object)label.Mob) && !label.Mob.IsDead(); ((Component)label.Text).gameObject.SetActive(flag); if (flag) { ((TMP_Text)label.Text).rectTransform.anchoredPosition = label.Screen; ((Graphic)label.Text).color = ((label.Hits > 0 && label.Hits <= 2) ? Color.red : Color.white); } } } private void Clear() { for (int i = 0; i < active; i++) { labels[i].Mob = null; labels[i].Visible = false; if (Object.op_Implicit((Object)(object)labels[i].Text)) { ((Component)labels[i].Text).gameObject.SetActive(false); } } active = 0; nearby.Clear(); if (Object.op_Implicit((Object)(object)overlay)) { overlay.SetActive(false); } } private void OnDisable() { Clear(); } private void OnDestroy() { Clear(); if (Object.op_Implicit((Object)(object)overlay)) { Object.Destroy((Object)(object)overlay); } } } internal sealed class ThreatEstimator { private readonly HitData hit = new HitData(); internal float Estimate(Humanoid mob, DamageModifiers resistance, float armor, float difficulty) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) float num = 0f; List<ItemData> allItems = mob.GetInventory().GetAllItems(); for (int i = 0; i < allItems.Count; i++) { num = Mathf.Max(num, EstimateWeapon(mob, allItems[i], resistance, armor, difficulty)); } return Mathf.Max(num, EstimateWeapon(mob, mob.GetCurrentWeapon(), resistance, armor, difficulty)); } private float EstimateWeapon(Humanoid mob, ItemData weapon, DamageModifiers resistance, float armor, float difficulty) { //IL_0011: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (weapon == null || !weapon.IsWeapon() || (int)weapon.m_shared.m_aiTargetType != 0) { return 0f; } float num = EstimateAttack(mob, weapon, weapon.m_shared.m_attack, resistance, armor, difficulty); if (weapon.HaveSecondaryAttack()) { num = Mathf.Max(num, EstimateAttack(mob, weapon, weapon.m_shared.m_secondaryAttack, resistance, armor, difficulty)); } return num; } private float EstimateAttack(Humanoid mob, ItemData weapon, Attack attack, DamageModifiers resistance, float armor, float difficulty) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (attack == null) { return 0f; } hit.m_damage = weapon.GetDamage(); float num = attack.m_damageMultiplier * (1f + (float)Mathf.Max(0, ((Character)mob).GetLevel() - 1) * 0.5f); num *= 0.935f; if (attack.m_damageMultiplierPerMissingHP > 0f) { num *= 1f + (((Character)mob).GetMaxHealth() - ((Character)mob).GetHealth()) * attack.m_damageMultiplierPerMissingHP; } if (attack.m_damageMultiplierByTotalHealthMissing > 0f) { num *= 1f + (1f - ((Character)mob).GetHealthPercentage()) * attack.m_damageMultiplierByTotalHealthMissing; } ((DamageTypes)(ref hit.m_damage)).Modify(num); hit.m_damage.m_chop = (hit.m_damage.m_pickaxe = 0f); float extraDamage = ((Game.m_worldLevel > 0) ? ((float)(Game.m_worldLevel * Game.instance.m_worldLevelEnemyBaseDamage)) : 0f); return Mitigate(hit, resistance, armor, difficulty * Game.m_enemyDamageRate, Game.m_localDamgeTakenRate, extraDamage); } internal static float Mitigate(HitData incoming, DamageModifiers resistance, float armor, float difficultyAndEnemyRate, float localDamageRate, float extraDamage) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) incoming.ApplyModifier(difficultyAndEnemyRate); DamageModifier val = default(DamageModifier); incoming.ApplyResistance(resistance, ref val); incoming.ApplyArmor(armor); incoming.ApplyModifier(localDamageRate); float num = ((DamageTypes)(ref incoming.m_damage)).GetTotalDamage() + extraDamage; if (!(num > 0.1f)) { return 0f; } return num; } } internal static class ThreatMath { internal static int HitsToDie(float health, float damage) { if (float.IsNaN(health) || float.IsInfinity(health) || health <= 0f || float.IsNaN(damage) || float.IsInfinity(damage) || damage <= 0f) { return 0; } double num = Math.Ceiling((double)health / (double)damage); if (!(num > 2147483647.0)) { return (int)num; } return int.MaxValue; } } }