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 TZPPlus v1.1.0
Miles.TZPPlus.dll
Decompiled 15 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Extensions; using CSync.Lib; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; 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("Miles.TZPPlus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("Miles.TZPPlus")] [assembly: AssemblyTitle("Miles.TZPPlus")] [assembly: AssemblyVersion("1.1.0.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 TZPPlus { internal static class BuffHud { private static readonly Color DefaultColor = new Color(1f, 0.76f, 0.2f); private static TextMeshProUGUI _text; private static string _colorSource; private static Color _color = DefaultColor; public static Color BuffColor { get { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) string text = ((TZPConfig.Instance != null) ? TZPConfig.Instance.BuffColor.Value : null); if (text != _colorSource) { _colorSource = text; if (string.IsNullOrEmpty(text) || !ColorUtility.TryParseHtmlString(text, ref _color)) { _color = DefaultColor; } } return _color; } } public static void Render(List<Effect> effects) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) TZPConfig instance = TZPConfig.Instance; if (instance == null || effects == null || effects.Count == 0) { if ((Object)(object)_text != (Object)null) { ((Behaviour)_text).enabled = false; } } else { if ((Object)(object)_text == (Object)null && !TryCreate()) { return; } ((Behaviour)_text).enabled = true; ((TMP_Text)_text).rectTransform.anchoredPosition = new Vector2(instance.BuffTextOffsetX.Value, instance.BuffTextOffsetY.Value); ((TMP_Text)_text).fontSize = instance.BuffTextSize.Value; ((Graphic)_text).color = Color.white; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < 2; i++) { foreach (Effect effect in effects) { if (effect.IsBuff == (i == 0)) { Color val = (effect.IsBuff ? effect.Color : Color.Lerp(effect.Color, Color.white, 0.35f)); int num = Mathf.RoundToInt(Mathf.Clamp01(effect.ValueAlpha) * 255f); if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } stringBuilder.Append("<color=#").Append(ColorUtility.ToHtmlStringRGB(val)).Append(">") .Append(effect.Title) .Append("</color>"); if (!string.IsNullOrEmpty(effect.Value)) { stringBuilder.Append(" <alpha=#").Append(num.ToString("X2")).Append(">") .Append(effect.Value) .Append("<alpha=#FF>"); } } } } ((TMP_Text)_text).text = stringBuilder.ToString(); } } private static bool TryCreate() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.weightCounter == (Object)null || (Object)(object)((Graphic)instance.weightCounter).canvas == (Object)null) { return false; } Canvas rootCanvas = ((Graphic)instance.weightCounter).canvas.rootCanvas; GameObject val = new GameObject("TZPPlus_ReductionText", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)rootCanvas).transform, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = new Vector2(1f, 0f); val2.anchorMax = new Vector2(1f, 0f); val2.pivot = new Vector2(1f, 0f); val2.sizeDelta = new Vector2(400f, 200f); _text = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)_text).font = ((TMP_Text)instance.weightCounter).font; ((TMP_Text)_text).alignment = (TextAlignmentOptions)1028; ((TMP_Text)_text).enableWordWrapping = false; ((Graphic)_text).raycastTarget = false; return true; } } internal static class EladsHudCompat { public const string EladsHudGuid = "me.eladnlg.customhud"; private const string AdvancedCompanyEladsPatchId = "AdvancedCompany.EladsHUDCompat"; private const float FadeSpeed = 2f; private static FieldInfo _healthBar; private static FieldInfo _healthGroup; private static FieldInfo _staminaBar; private static FieldInfo _staminaWarnColor; private static FieldInfo _colorLerp; private static object _lastHud; private static Color _originalHealthColor; private static float _intensity; private static float _withdrawal; public static void TryPatch(Harmony harmony) { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown try { if (Chainloader.PluginInfos.TryGetValue("me.eladnlg.customhud", out var value) && !((Object)(object)value.Instance == (Object)null)) { Type type = ((object)value.Instance).GetType().Assembly.GetType("CustomHUD_Mono"); if (type != null) { _healthBar = AccessTools.Field(type, "healthBar"); _healthGroup = AccessTools.Field(type, "healthGroup"); _staminaBar = AccessTools.Field(type, "staminaBar"); _staminaWarnColor = AccessTools.Field(type, "staminaWarnColor"); _colorLerp = AccessTools.Field(type, "colorLerp"); } MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "UpdateFromPlayer", (Type[])null, (Type[])null) : null); if (methodInfo == null || _healthBar == null || _healthGroup == null || _staminaBar == null || _staminaWarnColor == null || _colorLerp == null) { Plugin.Log.LogWarning((object)"Elad's HUD found, but its bar fields changed. Bar tint disabled."); return; } HarmonyMethod val = new HarmonyMethod(typeof(EladsHudCompat).GetMethod("UpdateFromPlayerPostfix", BindingFlags.Static | BindingFlags.NonPublic)); val.priority = 600; val.before = new string[1] { "AdvancedCompany.EladsHUDCompat" }; HarmonyMethod val2 = val; harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"Elad's HUD found: health and stamina bars fade to the reduction color while it is active."); } } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to hook Elad's HUD: " + ex)); } } private static void UpdateFromPlayerPostfix(object __instance) { //IL_003f: 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) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) try { TZPConfig instance = TZPConfig.Instance; if (instance == null) { return; } object? value = _healthBar.GetValue(__instance); Image val = (Image)((value is Image) ? value : null); if (val == null || (Object)(object)val == (Object)null) { return; } if (__instance != _lastHud) { _lastHud = __instance; _originalHealthColor = ((Graphic)val).color; } float num = Mathf.Clamp01(instance.MaxReductionPercent.Value / 100f); float num2 = ((num > 0f) ? Mathf.Clamp01(TZPState.Reduction / num) : 0f); _intensity = Mathf.MoveTowards(_intensity, num2, 2f * Time.deltaTime); Color buffColor = BuffHud.BuffColor; float num3 = (instance.TintEladsHealthBar.Value ? _intensity : 0f); ((Graphic)val).color = Color.Lerp(_originalHealthColor, buffColor, num3); if (num3 > 0f) { object? value2 = _healthGroup.GetValue(__instance); CanvasGroup val2 = (CanvasGroup)((value2 is CanvasGroup) ? value2 : null); if (val2 != null && (Object)(object)val2 != (Object)null) { val2.alpha = Mathf.Max(val2.alpha, num3); } } float num4 = (instance.TintEladsStaminaBar.Value ? _intensity : 0f); float num5 = ((instance.RedEladsStaminaWithdrawal.Value && LethalDose.InWithdrawal) ? 1f : 0f); _withdrawal = Mathf.MoveTowards(_withdrawal, num5, 2f * Time.deltaTime); if (!(num4 > 0f) && !(_withdrawal > 0f)) { return; } object? value3 = _staminaBar.GetValue(__instance); Image val3 = (Image)((value3 is Image) ? value3 : null); if (val3 != null && (Object)(object)val3 != (Object)null) { Color val4 = (Color)_staminaWarnColor.GetValue(__instance); float num6 = (float)_colorLerp.GetValue(__instance); if (num4 > 0f) { ((Graphic)val3).color = Color.Lerp(((Graphic)val3).color, Color.Lerp(buffColor, val4, num6), num4); } if (_withdrawal > 0f) { ((Graphic)val3).color = Color.Lerp(((Graphic)val3).color, StatusEffects.WithdrawalRed, _withdrawal); } } } catch { } } } internal static class FrailtyInjuries { private static readonly HashSet<string> Healed = new HashSet<string> { "BrokenLeg", "FracturedLeg", "BrokenArm", "FracturedArm" }; private static bool _checked; private static Type _manager; private static FieldInfo _conditions; private static FieldInfo _duration; private static FieldInfo _type; internal static void Tick(PlayerControllerB player, bool inhaling, float dt) { TZPConfig instance = TZPConfig.Instance; if (!inhaling || instance == null || (Object)(object)player == (Object)null || !instance.InjuryHealEnabled.Value) { return; } float value = instance.InjuryInhaleSpeed.Value; if (value <= 1f || !Find()) { return; } try { Component component = ((Component)player).GetComponent(_manager); if ((Object)(object)component == (Object)null || !(_conditions.GetValue(component) is IEnumerable enumerable)) { return; } float num = dt * (value - 1f); foreach (object item in enumerable) { if (item != null && Healed.Contains(_type.GetValue(item)?.ToString() ?? "")) { float num2 = Convert.ToSingle(_duration.GetValue(item)) - num; _duration.SetValue(item, Convert.ChangeType(num2, _duration.FieldType)); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Frailty injuries: " + ex.Message)); _manager = null; } } private static bool Find() { if (!_checked) { _checked = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { if (assembly.GetName().Name != "Frailty") { continue; } _manager = assembly.GetType("Frailty.Manager.ConditionManager", throwOnError: false); Type type = assembly.GetType("Frailty.Manager.Condition", throwOnError: false); if (_manager != null && type != null) { _conditions = AccessTools.Field(_manager, "conditions"); _duration = AccessTools.Field(type, "duration"); _type = AccessTools.Field(type, "type"); } break; } catch { } } if (_manager != null && (_conditions == null || _duration == null || _type == null)) { Plugin.Log.LogWarning((object)"Frailty changed: inhaling TZP no longer speeds up leg/arm injuries."); _manager = null; } } return _manager != null; } } public static class TZPLevels { public const int Rush = 0; public const int Slippery = 1; public const int Dizzy = 2; public const int Overdose = 3; public static readonly bool[] On = new bool[4]; public static readonly float[] Left = new float[4]; private static float _nextPredict; public static float SpeedCurve(float d) { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null) || instance.drunknessSpeedEffect == null) { return d; } return instance.drunknessSpeedEffect.Evaluate(d); } public static float SideCurve(float d) { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null) || instance.drunknessSideEffect == null) { return d; } return instance.drunknessSideEffect.Evaluate(d); } public static bool IsOn(int stage, float d) { switch (stage) { case 0: if (d > 0.02f) { return SpeedCurve(d) > 0.25f; } return false; case 1: return d > 0.3f; case 2: return d > 0.5f; default: return SideCurve(d) > 0.6f; } } public static bool IsRush(float d) { return IsOn(0, d); } internal static void Update(PlayerControllerB player) { float drunkness = player.drunkness; for (int i = 0; i < 4; i++) { On[i] = IsOn(i, drunkness); } if (!(Time.unscaledTime < _nextPredict)) { _nextPredict = Time.unscaledTime + 0.25f; Predict(player); } } private static void Predict(PlayerControllerB player) { float num = player.drunkness; float num2 = player.drunknessInertia; float drunknessSpeed = player.drunknessSpeed; for (int i = 0; i < 4; i++) { Left[i] = 0f; } float num3 = 0f; for (int j = 0; j < 9000; j++) { if (!(num > 0f)) { break; } float num4 = num; num = Mathf.Clamp01(num + 1f / 120f * drunknessSpeed * num2); if (num > 0f) { num2 = Mathf.Clamp(num2 - 1f / 30f * drunknessSpeed / Mathf.Clamp(Mathf.Abs(num2), 0.2f, 1f), -2.5f, 2.5f); } num3 += 0.1f; bool flag = false; for (int k = 0; k < 4; k++) { if (IsOn(k, num)) { Left[k] = num3; flag = true; } } if (!flag && num < num4) { break; } } } } public static class LethalDose { private static Volume _volume; private static VolumeProfile _profile; public static bool Active { get; private set; } public static float WithdrawalLeft { get; private set; } public static bool InWithdrawal => WithdrawalLeft > 0f; public static float InhaledThisHigh { get; private set; } internal static void Tick(PlayerControllerB player, bool inhaling, float dt) { TZPConfig instance = TZPConfig.Instance; if (instance == null || !instance.LethalEnabled.Value) { Reset(player); return; } if (inhaling) { InhaledThisHigh += dt; } else if (!Active && player.drunkness <= 0f) { InhaledThisHigh = 0f; } if (!Active && InhaledThisHigh >= instance.LethalSeconds.Value) { Active = true; WithdrawalLeft = 0f; Plugin.Log.LogInfo((object)"Lethal Dose: concussed until the TZP wears off, then withdrawal."); } if (Active && !inhaling && !TZPLevels.IsRush(player.drunkness)) { Active = false; InhaledThisHigh = 0f; WithdrawalLeft = instance.WithdrawalSeconds.Value; } else if (!Active && WithdrawalLeft > 0f) { float num = (inhaling ? Mathf.Max(1f, instance.WithdrawalInhaleSpeed.Value) : 1f); WithdrawalLeft = Mathf.Max(0f, WithdrawalLeft - dt * num); } UpdateVolume(Active, dt); } internal static void Reset(PlayerControllerB player) { Active = false; WithdrawalLeft = 0f; InhaledThisHigh = 0f; if ((Object)(object)_volume != (Object)null) { _volume.weight = 0f; } } private static void UpdateVolume(bool on, float dt) { //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) try { if ((Object)(object)_volume == (Object)null) { if (!on) { return; } _volume = new GameObject("TZPPlus Lethal Dose Volume") { layer = 0 }.AddComponent<Volume>(); _volume.isGlobal = true; _volume.priority = 36f; _volume.sharedProfile = ConcussionProfile(); _volume.weight = 0f; } _volume.weight = Mathf.Lerp(_volume.weight, on ? 1f : 0f, 2f * dt); if (!on && _volume.weight < 0.01f) { _volume.weight = 0f; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Lethal Dose concussion: " + ex.Message)); } } private static VolumeProfile ConcussionProfile() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_profile != (Object)null) { return _profile; } _profile = ScriptableObject.CreateInstance<VolumeProfile>(); ((Object)_profile).name = "TZPPlus Concussion"; MotionBlur obj = _profile.Add<MotionBlur>(false); ((VolumeParameter<float>)(object)obj.intensity).Override(15.98f); ((VolumeParameter<float>)(object)obj.maximumVelocity).Override(200f); ((VolumeParameter<float>)(object)obj.minimumVelocity).Override(0f); ((VolumeParameter<Color>)(object)_profile.Add<ColorAdjustments>(false).colorFilter).Override(new Color(1f, 0.8066038f, 0.8066038f, 1f)); ((VolumeParameter<float>)(object)_profile.Add<Bloom>(false).intensity).Override(1f); Vignette obj2 = _profile.Add<Vignette>(false); ((VolumeParameter<VignetteMode>)(object)obj2.mode).Override((VignetteMode)0); ((VolumeParameter<float>)(object)obj2.intensity).Override(0.433f); ((VolumeParameter<float>)(object)obj2.smoothness).Override(1f); ((VolumeParameter<float>)(object)obj2.roundness).Override(1f); ((VolumeParameter<bool>)(object)obj2.rounded).Override(false); return _profile; } } [BepInPlugin("Miles.TZPPlus", "TZPPlus", "1.1.0")] [BepInDependency("com.sigurd.csync", "5.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "Miles.TZPPlus"; public const string NAME = "TZPPlus"; public const string VERSION = "1.1.0"; internal static ManualLogSource Log; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; new TZPConfig(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("Miles.TZPPlus"); val.PatchAll(typeof(Plugin).Assembly); EladsHudCompat.TryPatch(val); Log.LogInfo((object)"TZPPlus 1.1.0 loaded: TZP heals, shows its gas, builds up damage reduction, and too much gives a Lethal Dose."); } } internal struct Effect { public string Key; public string Title; public string Description; public string Value; public Sprite Icon; public bool IsBuff; public Color Color; public float ValueAlpha; } internal static class StatusEffects { internal static readonly Color BuffGold = new Color(1f, 0.72f, 0.11f); internal static readonly Color DebuffRed = new Color(1f, 0f, 0.216f); internal static readonly Color WithdrawalRed = new Color(0.9f, 0.08f, 0.12f); private static readonly List<Effect> Effects = new List<Effect>(); internal static void Tick(PlayerControllerB player) { Effects.Clear(); TZPConfig instance = TZPConfig.Instance; if (instance != null && (Object)(object)player != (Object)null && !player.isPlayerDead && instance.DisplayMode.Value != EffectDisplay.Off) { try { Collect(instance, player); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Status effects: " + ex.Message)); Effects.Clear(); } } EffectDisplay effectDisplay = instance?.DisplayMode.Value ?? EffectDisplay.Off; bool flag = effectDisplay == EffectDisplay.Icons; bool flag2 = flag && EladBridge.Available; if (flag2) { foreach (Effect effect in Effects) { EladBridge.Show(effect); } } VanillaRow.Render((flag && !flag2) ? Effects : null); BuffHud.Render((effectDisplay == EffectDisplay.Text) ? Effects : null); } private static void Collect(TZPConfig cfg, PlayerControllerB player) { //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) if (cfg.ShowModEffects.Value && TZPState.Reduction > 0.0005f) { bool isHolding = TZPState.IsHolding; Effects.Add(new Effect { Key = "TZPPlus.DamageReduction", Icon = Icons.Reduction, IsBuff = true, Color = BuffHud.BuffColor, Value = $"{Mathf.CeilToInt(TZPState.Reduction * 100f - 0.001f)}%", ValueAlpha = (isHolding ? 1f : (0.45f + 0.55f * Mathf.Abs(Mathf.Sin(Time.time * 3f)))), Title = "Damage Reduction", Description = "You take less damage. Keep inhaling to build it up; it holds for a while after you stop, then fades." }); } TZPLevels.Update(player); if (cfg.ShowVanillaEffects.Value) { AddStage(0, "TZPPlus.Rush", Icons.Rush, buff: true, "TZP Rush", "You move faster and sprinting barely uses stamina, but stamina also refills slower."); AddStage(1, "TZPPlus.Slippery", Icons.Slippery, buff: false, "Slippery", "You're slow to start and stop moving and slide around."); AddStage(2, "TZPPlus.Dizzy", Icons.Dizzy, buff: false, "Dizzy", "Your camera lags behind your mouse."); AddStage(3, "TZPPlus.Overdose", Icons.Overdose, buff: false, "Overdose", "Your voice is pitched up, your vision is hazy and sounds are muffled."); } if (cfg.ShowModEffects.Value) { if (LethalDose.Active) { Effects.Add(Debuff("TZPPlus.LethalDose", Icons.LethalDose, "Lethal Dose", "You took way too much TZP. You're concussed until every TZP effect wears off, then withdrawal kicks in.", TZPLevels.Left[0])); } if (LethalDose.InWithdrawal) { Effects.Add(Debuff("TZPPlus.Withdrawal", Icons.Withdrawal, "Withdrawal", "You walk, run and jump a bit worse, your stamina refills slower and drains a little faster. Inhaling TZP makes it wear off faster.", LethalDose.WithdrawalLeft)); } } } private static void AddStage(int stage, string key, Sprite icon, bool buff, string title, string description) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (TZPLevels.On[stage]) { Effect item = Debuff(key, icon, title, description, TZPLevels.Left[stage]); if (buff) { item.IsBuff = true; item.Color = BuffGold; } Effects.Add(item); } } private static Effect Debuff(string key, Sprite icon, string title, string description, float secondsLeft) { //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) return new Effect { Key = key, Icon = icon, IsBuff = false, Color = DebuffRed, Title = title, Description = description, Value = ((secondsLeft > 0f) ? FormatTime(secondsLeft) : ""), ValueAlpha = ((secondsLeft > 0f && secondsLeft <= 5f) ? 0.55f : 1f) }; } internal static string FormatTime(float seconds) { int num = Mathf.CeilToInt(seconds); if (num < 60) { return $"{num}s"; } return $"{num / 60}:{num % 60:00}"; } } internal static class Icons { private static bool _loaded; private static Sprite _frame; private static Sprite _reduction; private static Sprite _rush; private static Sprite _slippery; private static Sprite _dizzy; private static Sprite _overdose; private static Sprite _lethal; private static Sprite _withdrawal; internal static Sprite Frame { get { Load(); return _frame; } } internal static Sprite Reduction { get { Load(); return _reduction; } } internal static Sprite Rush { get { Load(); return _rush; } } internal static Sprite Slippery { get { Load(); return _slippery; } } internal static Sprite Dizzy { get { Load(); return _dizzy; } } internal static Sprite Overdose { get { Load(); return _overdose; } } internal static Sprite LethalDose { get { Load(); return _lethal; } } internal static Sprite Withdrawal { get { Load(); return _withdrawal; } } private static void Load() { if (!_loaded) { _loaded = true; _frame = Sprite("BuffFrame.png"); _reduction = Sprite("TZP_Buff.png"); _rush = Sprite("TZPRush_Buff.png"); _slippery = Sprite("Slippery_Debuff.png"); _dizzy = Sprite("Dizzy_Debuff.png"); _overdose = Sprite("Overdose_Debuff.png"); _lethal = Sprite("LethalDose_Debuff.png"); _withdrawal = Sprite("Withdrawal_Debuff.png"); } } private static Sprite Sprite(string file) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) try { Assembly assembly = typeof(Icons).Assembly; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.EndsWith(file)) { using (Stream stream = assembly.GetManifestResourceStream(text)) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); ImageConversion.LoadImage(val, array); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)2; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Icon " + file + ": " + ex.Message)); } return null; } } internal static class EladBridge { private static bool _checked; private static Action<string, Sprite, bool, Color, string, Color, string, string> _show; private static PropertyInfo _available; internal static bool Available { get { if (!_checked) { _checked = true; try { if (Chainloader.PluginInfos.TryGetValue("me.eladnlg.customhud", out var value) && (Object)(object)value.Instance != (Object)null) { Type? type = ((object)value.Instance).GetType().Assembly.GetType("CustomHUD.StatusApi"); MethodInfo methodInfo = type?.GetMethod("Show", BindingFlags.Static | BindingFlags.Public); _available = type?.GetProperty("Available", BindingFlags.Static | BindingFlags.Public); if (methodInfo != null && _available != null) { _show = (Action<string, Sprite, bool, Color, string, Color, string, string>)Delegate.CreateDelegate(typeof(Action<string, Sprite, bool, Color, string, Color, string, string>), methodInfo); Plugin.Log.LogInfo((object)"Elad's HUD status row found: TZP icons go under its health bar."); } else { Plugin.Log.LogInfo((object)"Elad's HUD found without a status row (not the SleepyMiles fork): TZP icons go next to the vanilla HUD."); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Elad's HUD status row: " + ex.Message)); _show = null; } } try { return _show != null && (bool)_available.GetValue(null); } catch { return false; } } } internal static void Show(Effect e) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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) //IL_001f: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) Color arg = (e.IsBuff ? new Color(e.Color.r, e.Color.g, e.Color.b, 0.5f) : new Color(e.Color.r, e.Color.g, e.Color.b, 0.22f)); Color arg2 = (e.IsBuff ? new Color(e.Color.r, e.Color.g, e.Color.b, e.ValueAlpha) : new Color(1f, 1f, 1f, e.ValueAlpha)); _show(e.Key, e.Icon, e.IsBuff, arg, e.Value, arg2, e.Title, e.Description); } } internal static class VanillaRow { private class Slot { public RectTransform Rect; public Image Frame; public Image Icon; public TextMeshProUGUI Value; } private static readonly Vector3 FrailtyRow = new Vector3(15.85f, 23.4f, -5.55f); private const float IconSize = 35f; private const float Spacing = 3.38f; private const float ValueHeight = 14f; private const float FrameScale = 0.75f; private const float PictureScale = 0.75f; private static RectTransform _row; private static readonly Dictionary<string, Slot> Slots = new Dictionary<string, Slot>(); private static TMP_FontAsset _font; private static Material _fontMaterial; private static bool _frailtyChecked; private static FieldInfo _frailtyRow; internal static void Render(List<Effect> effects) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) if (effects == null || effects.Count == 0) { if ((Object)(object)_row != (Object)null) { ((Component)_row).gameObject.SetActive(false); } } else { if ((Object)(object)_row == (Object)null && !Create()) { return; } ((Component)_row).gameObject.SetActive(true); TZPConfig instance = TZPConfig.Instance; float value = instance.IconRowScale.Value; int num = FrailtyVisibleIcons(); _row.anchoredPosition3D = new Vector3(FrailtyRow.x + (float)num * 38.38f + instance.IconRowOffsetX.Value, FrailtyRow.y + instance.IconRowOffsetY.Value, FrailtyRow.z); ((Transform)_row).localScale = Vector3.one * value; foreach (Slot value2 in Slots.Values) { ((Component)value2.Rect).gameObject.SetActive(false); } float num2 = 0f; for (int i = 0; i < 2; i++) { foreach (Effect effect in effects) { if (effect.IsBuff == (i == 0)) { Slot slot = GetSlot(effect.Key); ((Component)slot.Rect).gameObject.SetActive(true); slot.Rect.anchoredPosition = new Vector2(num2, 0f); ((Graphic)slot.Frame).color = (effect.IsBuff ? new Color(effect.Color.r, effect.Color.g, effect.Color.b, 0.5f) : new Color(effect.Color.r, effect.Color.g, effect.Color.b, 0.22f)); slot.Icon.sprite = effect.Icon; ((Behaviour)slot.Icon).enabled = (Object)(object)effect.Icon != (Object)null; ((TMP_Text)slot.Value).text = effect.Value; Color val = ((effect.IsBuff && instance.ColoredBuffNumbers.Value) ? effect.Color : Color.white); ((Graphic)slot.Value).color = new Color(val.r, val.g, val.b, effect.ValueAlpha); num2 += 38.38f; } } } } } private static bool Create() { //IL_0037: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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) //IL_009c: 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_00c9: Unknown result type (might be due to invalid IL or missing references) HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.HUDContainer == (Object)null) { return false; } GameObject val = new GameObject("TZPPlus_StatusRow", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(instance.HUDContainer.transform, false); _row = (RectTransform)val.transform; RectTransform row = _row; Vector2 anchorMin = (_row.anchorMax = Vector2.zero); row.anchorMin = anchorMin; _row.pivot = new Vector2(0f, 0.5f); _row.sizeDelta = Vector2.zero; _row.anchoredPosition3D = FrailtyRow; ((Transform)_row).rotation = Quaternion.Euler(0f, -14.141f, 0f); if (instance.controlTipLines != null && instance.controlTipLines.Length != 0 && (Object)(object)instance.controlTipLines[0] != (Object)null) { _font = ((TMP_Text)instance.controlTipLines[0]).font; _fontMaterial = ((TMP_Text)instance.controlTipLines[0]).fontSharedMaterial; } else if ((Object)(object)instance.weightCounter != (Object)null) { _font = ((TMP_Text)instance.weightCounter).font; } Slots.Clear(); return true; } private static Slot GetSlot(string key) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) if (Slots.TryGetValue(key, out var value) && (Object)(object)value.Rect != (Object)null) { return value; } value = new Slot(); GameObject val = new GameObject(key, new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)_row, false); value.Rect = (RectTransform)val.transform; RectTransform rect = value.Rect; RectTransform rect2 = value.Rect; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); rect2.anchorMax = val2; rect.anchorMin = val2; value.Rect.pivot = new Vector2(0f, 0.5f); value.Rect.sizeDelta = new Vector2(35f, 35f); value.Frame = NewImage("Frame", value.Rect, Icons.Frame); ((Transform)((Graphic)value.Frame).rectTransform).localScale = Vector3.one * 0.75f; value.Icon = NewImage("Icon", ((Graphic)value.Frame).rectTransform, null); ((Transform)((Graphic)value.Icon).rectTransform).localScale = Vector3.one * 0.75f; value.Icon.preserveAspect = true; GameObject val3 = new GameObject("Value", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent((Transform)(object)value.Rect, false); RectTransform val4 = (RectTransform)val3.transform; val4.anchorMin = new Vector2(0.5f, 0.5f); val4.anchorMax = new Vector2(0.5f, 0.5f); val4.pivot = new Vector2(0.5f, 0f); val4.sizeDelta = new Vector2(55f, 14f); val4.anchoredPosition = new Vector2(0f, 14.125f); value.Value = val3.AddComponent<TextMeshProUGUI>(); if ((Object)(object)_font != (Object)null) { ((TMP_Text)value.Value).font = _font; } if ((Object)(object)_fontMaterial != (Object)null) { ((TMP_Text)value.Value).fontSharedMaterial = _fontMaterial; } ((TMP_Text)value.Value).fontSize = 11f; ((TMP_Text)value.Value).alignment = (TextAlignmentOptions)1026; ((TMP_Text)value.Value).enableWordWrapping = false; ((TMP_Text)value.Value).overflowMode = (TextOverflowModes)0; ((Graphic)value.Value).raycastTarget = false; Slots[key] = value; return value; } private static Image NewImage(string name, RectTransform parent, Sprite sprite) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_003c: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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) //IL_0054: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)parent, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; Vector2 offsetMin = (val2.offsetMax = Vector2.zero); val2.offsetMin = offsetMin; Image obj = val.AddComponent<Image>(); obj.sprite = sprite; ((Graphic)obj).raycastTarget = false; return obj; } private static int FrailtyVisibleIcons() { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) try { if (!_frailtyChecked) { _frailtyChecked = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { if (assembly.GetName().Name != "Frailty") { continue; } _frailtyRow = assembly.GetType("Frailty.Patches.HUDPatch", throwOnError: false)?.GetField("conditionHud", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); break; } catch { } } } object? obj2 = _frailtyRow?.GetValue(null); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { return 0; } CanvasGroup component = val.GetComponent<CanvasGroup>(); if ((Object)(object)component != (Object)null && component.alpha <= 0.01f) { return 0; } int num = 0; foreach (Transform item in val.transform) { if (((Component)item).gameObject.activeSelf) { num++; } } return num; } catch { return 0; } } } internal static class VanillaTint { private const float FadeSpeed = 2f; private static Image _meter; private static Color _original; private static float _intensity; private static float _withdrawal; internal static void Tick(PlayerControllerB player) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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) TZPConfig instance = TZPConfig.Instance; Image val = (((Object)(object)player != (Object)null) ? player.sprintMeterUI : null); if (instance != null && !((Object)(object)val == (Object)null)) { if (val != _meter) { _meter = val; _original = ((Graphic)val).color; _intensity = 0f; } float num = Mathf.Clamp01(instance.MaxReductionPercent.Value / 100f); float num2 = ((instance.TintVanillaStamina.Value && num > 0f) ? Mathf.Clamp01(TZPState.Reduction / num) : 0f); _intensity = Mathf.MoveTowards(_intensity, num2, 2f * Time.deltaTime); float num3 = ((instance.RedVanillaStaminaWithdrawal.Value && LethalDose.InWithdrawal) ? 1f : 0f); _withdrawal = Mathf.MoveTowards(_withdrawal, num3, 2f * Time.deltaTime); if (!(_intensity <= 0f) || !(_withdrawal <= 0f) || !(((Graphic)val).color == _original)) { Color buffColor = BuffHud.BuffColor; Color withdrawalRed = StatusEffects.WithdrawalRed; Color val2 = Color.Lerp(_original, new Color(buffColor.r, buffColor.g, buffColor.b, _original.a), _intensity); ((Graphic)val).color = Color.Lerp(val2, new Color(withdrawalRed.r, withdrawalRed.g, withdrawalRed.b, _original.a), _withdrawal); } } } } public enum EffectDisplay { Icons, Text, Off } public class TZPConfig : SyncedConfig2<TZPConfig> { private const string Healing = "1. Healing"; private const string Reduction = "2. Damage Reduction"; private const string Display = "3. Display UI"; private const string Lethal = "4. Lethal Dose"; private const string Injuries = "5. Frailty injuries"; private const string EladsHud = "6. EladsHUD compatibility"; public static TZPConfig Instance { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> HealEnabled { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> HealPerSecond { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> ReductionEnabled { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> MaxReductionPercent { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> GainPercentPerSecond { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> MinPuffSeconds { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> GraceSeconds { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> DecayPercentPerSecond { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> IncludeFallDamage { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> LethalEnabled { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> LethalSeconds { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> WithdrawalSeconds { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> WithdrawalPercent { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> WithdrawalDrainPercent { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> WithdrawalInhaleSpeed { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> InjuryHealEnabled { get; private set; } [field: SyncedEntryField] public SyncedEntry<float> InjuryInhaleSpeed { get; private set; } public ConfigEntry<bool> ShowFuelAsBattery { get; private set; } public ConfigEntry<EffectDisplay> DisplayMode { get; private set; } public ConfigEntry<bool> ShowModEffects { get; private set; } public ConfigEntry<bool> ShowVanillaEffects { get; private set; } public ConfigEntry<bool> ColoredBuffNumbers { get; private set; } public ConfigEntry<float> IconRowOffsetX { get; private set; } public ConfigEntry<float> IconRowOffsetY { get; private set; } public ConfigEntry<float> IconRowScale { get; private set; } public ConfigEntry<float> BuffTextOffsetX { get; private set; } public ConfigEntry<float> BuffTextOffsetY { get; private set; } public ConfigEntry<float> BuffTextSize { get; private set; } public ConfigEntry<bool> TintVanillaStamina { get; private set; } public ConfigEntry<bool> RedVanillaStaminaWithdrawal { get; private set; } public ConfigEntry<bool> RedEladsStaminaWithdrawal { get; private set; } public ConfigEntry<bool> TintEladsHealthBar { get; private set; } public ConfigEntry<bool> TintEladsStaminaBar { get; private set; } public ConfigEntry<string> BuffColor { get; private set; } public TZPConfig(ConfigFile cfg) : base("Miles.TZPPlus") { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Expected O, but got Unknown //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Expected O, but got Unknown //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Expected O, but got Unknown //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Expected O, but got Unknown //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Expected O, but got Unknown //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Expected O, but got Unknown //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Expected O, but got Unknown Instance = this; HealEnabled = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "1. Healing", "Enable healing", true, "Inhaling TZP heals you."); HealPerSecond = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "1. Healing", "Heal per second", 5f, new ConfigDescription("HP healed per second while inhaling (a full TZP tank lasts 38 seconds).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); ReductionEnabled = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "2. Damage Reduction", "Enable damage reduction", true, "Inhaling TZP builds up damage reduction against all damage (monsters, fall damage, etc.). Instant kills are not affected."); IncludeFallDamage = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "2. Damage Reduction", "Include fall damage", true, "Also reduce fall damage."); MaxReductionPercent = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "2. Damage Reduction", "Max damage reduction %", 40f, new ConfigDescription("The most damage reduction you can build up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f), Array.Empty<object>())); GainPercentPerSecond = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "2. Damage Reduction", "Reduction gained per second %", 2f, new ConfigDescription("Damage reduction gained per second of inhaling (2 = 20% after 10 s, 40% after 20 s).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 50f), Array.Empty<object>())); MinPuffSeconds = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "2. Damage Reduction", "Minimum puff seconds", 2.5f, new ConfigDescription("Only applies while you already have a buff: a new puff must last this long before the buff stacks again and the grace timer resets (stacking starts from that moment). With no buff, inhaling counts right away.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); GraceSeconds = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "2. Damage Reduction", "Grace seconds", 10f, new ConfigDescription("After a counted puff ends, the reduction stays this many seconds before it starts to decay. A new counted puff resets this timer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); DecayPercentPerSecond = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "2. Damage Reduction", "Decay % per second", 2f, new ConfigDescription("How many percent of reduction are lost per second after the grace time.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 100f), Array.Empty<object>())); ShowFuelAsBattery = cfg.Bind<bool>("3. Display UI", "Show TZP gas as battery", true, "Client side only (your own setting, not synced). Show the TZP's remaining gas in the battery meter (vanilla HUD and Elad's HUD; Elad's HUD also shows seconds left)."); DisplayMode = cfg.Bind<EffectDisplay>("3. Display UI", "Effect display", EffectDisplay.Icons, "Client side only (your own setting, not synced). How buffs and debuffs are shown.\nIcons - icons with a timer / value. With Elad's HUD (SleepyMiles fork) they go in its row under the health bar (with tooltips);\n otherwise next to the vanilla HUD, like Frailty's injury icons.\nText - small text lines in the bottom-right corner.\nOff - nothing."); ShowModEffects = cfg.Bind<bool>("3. Display UI", "Show TZPPlus effects", true, "Client side only (your own setting, not synced). Show the effects this mod adds: Damage Reduction (buff, with its %), Lethal Dose and Withdrawal (debuffs, with time left).\nWorks with both Effect display options: as icons when it is Icons, as text lines when it is Text. Nothing shows when Effect display is Off."); ShowVanillaEffects = cfg.Bind<bool>("3. Display UI", "Show vanilla TZP effects", false, "Client side only (your own setting, not synced). Show the effects the game's own TZP already has: TZP Rush (buff: faster, cheaper sprinting) and Slippery, Dizzy, Overdose (debuffs), each with the time until it wears off.\nWorks with both Effect display options: as icons when it is Icons, as text lines when it is Text. Nothing shows when Effect display is Off."); ColoredBuffNumbers = cfg.Bind<bool>("3. Display UI", "Buff icon numbers in buff color", false, "Client side only (your own setting, not synced). The number above each BUFF icon (the Damage Reduction % and the TZP Rush time left).\nOff: white, like the debuff numbers. On: the buff's own color (gold).\nOnly for the icons next to the vanilla HUD. Elad's HUD has its own setting for its row (ColoredBuffNumbers), and the Text display always colors the names."); IconRowOffsetX = cfg.Bind<float>("3. Display UI", "Icon row X offset", 0f, "Client side only (your own setting, not synced). Icons next to the vanilla HUD: move the row left/right (negative = left)."); IconRowOffsetY = cfg.Bind<float>("3. Display UI", "Icon row Y offset", 0f, "Client side only (your own setting, not synced). Icons next to the vanilla HUD: move the row up/down (negative = down)."); IconRowScale = cfg.Bind<float>("3. Display UI", "Icon row size", 1f, new ConfigDescription("Client side only (your own setting, not synced). Icons next to the vanilla HUD: size of the icons.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); BuffTextOffsetX = cfg.Bind<float>("3. Display UI", "Text X offset", -20f, "Client side only (your own setting, not synced). Text display: horizontal position, measured from the bottom-right corner of the screen (negative = left)."); BuffTextOffsetY = cfg.Bind<float>("3. Display UI", "Text Y offset", 20f, "Client side only (your own setting, not synced). Text display: vertical position, measured from the bottom-right corner of the screen (positive = up)."); BuffTextSize = cfg.Bind<float>("3. Display UI", "Text size", 16f, new ConfigDescription("Client side only (your own setting, not synced). Text display: font size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 60f), Array.Empty<object>())); TintVanillaStamina = cfg.Bind<bool>("3. Display UI", "Tint vanilla stamina meter", true, "Client side only (your own setting, not synced). Vanilla HUD: fade the stamina meter to the reduction color while the damage reduction is active (stronger buff = stronger color)."); RedVanillaStaminaWithdrawal = cfg.Bind<bool>("3. Display UI", "Red vanilla stamina meter during withdrawal", true, "Client side only (your own setting, not synced). Vanilla HUD: the stamina meter turns red while you have Withdrawal (red wins over the gold tint)."); BuffColor = cfg.Bind<string>("3. Display UI", "Reduction color", "#FFC233", "Client side only (your own setting, not synced). Color (hex) of the damage reduction: its text line, its icon number (if colored) and the stamina / health bar tint."); LethalEnabled = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "4. Lethal Dose", "Enable Lethal Dose", false, "Inhaling too much TZP in one go gives a Lethal Dose: you are concussed (motion blur, red tint and dark edges on the game view, not the HUD) until every TZP effect has worn off, then you go through withdrawal."); LethalSeconds = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "4. Lethal Dose", "Seconds of inhaling for Lethal Dose", 20f, new ConfigDescription("Total seconds of inhaling during one high (until the TZP has fully worn off) that cause a Lethal Dose. Short puffs add up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 38f), Array.Empty<object>())); WithdrawalSeconds = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "4. Lethal Dose", "Withdrawal seconds", 60f, new ConfigDescription("How long withdrawal lasts after the Lethal Dose ends.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); WithdrawalPercent = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "4. Lethal Dose", "Withdrawal strength %", 15f, new ConfigDescription("During withdrawal you walk and sprint this much slower, jump this much lower and stamina refills this much slower.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); WithdrawalDrainPercent = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "4. Lethal Dose", "Withdrawal stamina drain %", 8f, new ConfigDescription("During withdrawal stamina also drains this much faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); WithdrawalInhaleSpeed = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "4. Lethal Dose", "Withdrawal countdown while inhaling", 10f, new ConfigDescription("While you inhale TZP, withdrawal counts down this many times faster (10 = every 0.1 s of inhaling takes 1 s off).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); InjuryHealEnabled = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "5. Frailty injuries", "Enable Frailty compatibility", false, "Needs the Frailty mod. On: inhaling TZP makes Frailty's broken/fractured legs and arms heal faster (speed below)."); InjuryInhaleSpeed = SyncedBindingExtensions.BindSyncedEntry<float>(cfg, "5. Frailty injuries", "Leg/arm injury countdown while inhaling", 10f, new ConfigDescription("While you inhale TZP, broken/fractured legs and arms count down this many times faster (10 = every 0.1 s of inhaling takes 1 s off).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>())); TintEladsHealthBar = cfg.Bind<bool>("6. EladsHUD compatibility", "Tint EladsHUD health bar", true, "Client side only (your own setting, not synced). If Elad's HUD is installed: fade the health bar to the reduction color (stronger buff = stronger color) and keep it visible while the reduction is active."); TintEladsStaminaBar = cfg.Bind<bool>("6. EladsHUD compatibility", "Tint EladsHUD stamina bar", true, "Client side only (your own setting, not synced). If Elad's HUD is installed: fade the stamina bar to the reduction color too (it still turns red when stamina is low; AdvancedCompany's injector cyan shows on top while both are active)."); RedEladsStaminaWithdrawal = cfg.Bind<bool>("6. EladsHUD compatibility", "Red EladsHUD stamina bar during withdrawal", true, "Client side only (your own setting, not synced). If Elad's HUD is installed: its stamina bar turns red while you have Withdrawal (red wins over the gold tint)."); ConfigManager.Register<TZPConfig>((SyncedConfig2<TZPConfig>)this); } } internal static class TZPState { public const int MaxHealth = 100; private static bool _inhalingFlag; private static float _puffTime; private static bool _qualified; private static float _grace; private static float _healAccumulator; private static int _healNotSynced; private static float _healSyncTimer; public static float Reduction { get; private set; } public static bool IsHolding { get { if (Reduction > 0f) { if (!_qualified) { return _grace > 0f; } return true; } return false; } } public static void MarkInhaling() { _inhalingFlag = true; } public static void Tick(PlayerControllerB player, float dt) { TZPConfig instance = TZPConfig.Instance; bool inhalingFlag = _inhalingFlag; _inhalingFlag = false; if (instance != null) { if (player.isPlayerDead || !player.isPlayerControlled) { ResetAll(); LethalDose.Reset(player); return; } TickReduction(instance, inhalingFlag, dt); TickHealing(instance, player, inhalingFlag, dt); LethalDose.Tick(player, inhalingFlag, dt); FrailtyInjuries.Tick(player, inhalingFlag, dt); } } private static void TickReduction(TZPConfig cfg, bool inhaling, float dt) { if (!cfg.ReductionEnabled.Value) { Reduction = 0f; _puffTime = 0f; _qualified = false; _grace = 0f; return; } float num = Mathf.Clamp01(cfg.MaxReductionPercent.Value / 100f); float num2 = Mathf.Max(0f, cfg.GainPercentPerSecond.Value) / 100f; if (inhaling) { _puffTime += dt; if (!_qualified && (Reduction <= 0f || _puffTime >= cfg.MinPuffSeconds.Value)) { _qualified = true; } else if (_qualified) { Reduction += num2 * dt; } } else { _puffTime = 0f; _qualified = false; } if (_qualified) { _grace = cfg.GraceSeconds.Value; } else if (_grace > 0f) { _grace -= dt; } else if (Reduction > 0f) { Reduction -= cfg.DecayPercentPerSecond.Value / 100f * dt; } Reduction = Mathf.Clamp(Reduction, 0f, num); } private static void TickHealing(TZPConfig cfg, PlayerControllerB player, bool inhaling, float dt) { if (inhaling && cfg.HealEnabled.Value && player.health < 100) { _healAccumulator += cfg.HealPerSecond.Value * dt; int num = Mathf.FloorToInt(_healAccumulator); if (num > 0) { _healAccumulator -= num; ApplyHeal(player, num); } } else if (!inhaling) { _healAccumulator = 0f; } _healSyncTimer -= dt; if (_healNotSynced > 0 && (_healSyncTimer <= 0f || !inhaling)) { SyncHealth(player); } } private static void ApplyHeal(PlayerControllerB player, int amount) { int num = Mathf.Min(100, player.health + amount); int num2 = num - player.health; if (num2 > 0) { player.health = num; _healNotSynced += num2; if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.UpdateHealthUI(num, false); } if (player.criticallyInjured && num >= 10) { player.MakeCriticallyInjured(false); } } } private static void SyncHealth(PlayerControllerB player) { player.DamagePlayerServerRpc(-_healNotSynced, player.health); _healNotSynced = 0; _healSyncTimer = 0.5f; } public static void ResetAll() { Reduction = 0f; _puffTime = 0f; _qualified = false; _grace = 0f; _healAccumulator = 0f; _healNotSynced = 0; _inhalingFlag = false; LethalDose.Reset(null); } } } namespace TZPPlus.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal static class WithdrawalPatches { private static bool _applied; private static float _savedSpeed; private static float _reducedSpeed; private static float _savedJump; private static float _reducedJump; private static float _staminaBefore = -1f; private static float Strength => Mathf.Clamp01(TZPConfig.Instance.WithdrawalPercent.Value / 100f); [HarmonyPatch("Update")] [HarmonyPrefix] [HarmonyPriority(0)] private static void UpdatePrefix(PlayerControllerB __instance) { _applied = false; if (LethalDose.InWithdrawal && PlayerPatches.IsLocal(__instance)) { float strength = Strength; _savedSpeed = __instance.movementSpeed; _reducedSpeed = _savedSpeed * (1f - strength); __instance.movementSpeed = _reducedSpeed; _savedJump = __instance.jumpForce; _reducedJump = _savedJump * Mathf.Sqrt(1f - strength); __instance.jumpForce = _reducedJump; if (__instance.fallValueUncapped > _reducedJump) { __instance.fallValueUncapped = _reducedJump; } _applied = true; } } [HarmonyPatch("Update")] [HarmonyFinalizer] private static void UpdateFinalizer(PlayerControllerB __instance) { if (_applied) { _applied = false; __instance.movementSpeed = (Mathf.Approximately(__instance.movementSpeed, _reducedSpeed) ? _savedSpeed : (__instance.movementSpeed + (_savedSpeed - _reducedSpeed))); __instance.jumpForce = (Mathf.Approximately(__instance.jumpForce, _reducedJump) ? _savedJump : (__instance.jumpForce + (_savedJump - _reducedJump))); } } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] [HarmonyPriority(0)] private static void LateUpdatePrefix(PlayerControllerB __instance) { _staminaBefore = ((LethalDose.InWithdrawal && PlayerPatches.IsLocal(__instance)) ? __instance.sprintMeter : (-1f)); } [HarmonyPatch("LateUpdate")] [HarmonyPostfix] [HarmonyPriority(800)] private static void LateUpdatePostfix(PlayerControllerB __instance) { if (!(_staminaBefore < 0f)) { float num = __instance.sprintMeter - _staminaBefore; if (num > 0f) { __instance.sprintMeter = _staminaBefore + num * (1f - Strength); } else if (num < 0f) { __instance.sprintMeter = Mathf.Max(0f, _staminaBefore + num * (1f + Mathf.Max(0f, TZPConfig.Instance.WithdrawalDrainPercent.Value) / 100f)); } _staminaBefore = -1f; } } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerPatches { private static Item _changedItem; private static bool _savedRequiresBattery; private static float _savedBatteryUsage; private static bool _savedItemIsTrigger; internal static bool IsLocal(PlayerControllerB player) { GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)instance.localPlayerController; } return false; } [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(PlayerControllerB __instance) { if (IsLocal(__instance)) { TZPState.Tick(__instance, Time.deltaTime); StatusEffects.Tick(__instance); VanillaTint.Tick(__instance); } } [HarmonyPatch("DamagePlayer")] [HarmonyPrefix] [HarmonyPriority(200)] private static void DamagePlayerPrefix(PlayerControllerB __instance, ref int damageNumber, CauseOfDeath causeOfDeath, bool fallDamage) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 float reduction = TZPState.Reduction; if (!(reduction <= 0f) && damageNumber > 0 && IsLocal(__instance) && ((!fallDamage && (int)causeOfDeath != 2) || TZPConfig.Instance.IncludeFallDamage.Value)) { damageNumber = Mathf.Max(1, Mathf.RoundToInt((float)damageNumber * (1f - reduction))); } } [HarmonyPatch("DamageOnOtherClients")] [HarmonyPrefix] private static bool DamageOnOtherClientsPrefix(PlayerControllerB __instance, int damageNumber, int newHealthAmount) { if (damageNumber >= 0) { return true; } __instance.health = newHealthAmount; return false; } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyBefore(new string[] { "me.eladnlg.customhud" })] private static void LateUpdatePrefix(PlayerControllerB __instance) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown RestoreBatteryDisplay(); TZPConfig instance = TZPConfig.Instance; if (instance == null || !instance.ShowFuelAsBattery.Value || !IsLocal(__instance)) { return; } GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; TetraChemicalItem val = (TetraChemicalItem)(object)((currentlyHeldObjectServer is TetraChemicalItem) ? currentlyHeldObjectServer : null); if (val == null || (Object)(object)((GrabbableObject)val).itemProperties == (Object)null) { return; } Item itemProperties = ((GrabbableObject)val).itemProperties; if (!itemProperties.requiresBattery) { float num = Mathf.Clamp01(TZPItemPatches.Fuel.Invoke(val)); if (((GrabbableObject)val).insertedBattery == null) { ((GrabbableObject)val).insertedBattery = new Battery(num <= 0f, num); } else { ((GrabbableObject)val).insertedBattery.charge = num; ((GrabbableObject)val).insertedBattery.empty = num <= 0f; } _changedItem = itemProperties; _savedRequiresBattery = itemProperties.requiresBattery; _savedBatteryUsage = itemProperties.batteryUsage; _savedItemIsTrigger = itemProperties.itemIsTrigger; itemProperties.requiresBattery = true; itemProperties.batteryUsage = 38f; itemProperties.itemIsTrigger = false; } } [HarmonyPatch("LateUpdate")] [HarmonyFinalizer] private static void LateUpdateFinalizer() { RestoreBatteryDisplay(); } private static void RestoreBatteryDisplay() { if (!((Object)(object)_changedItem == (Object)null)) { _changedItem.requiresBattery = _savedRequiresBattery; _changedItem.batteryUsage = _savedBatteryUsage; _changedItem.itemIsTrigger = _savedItemIsTrigger; _changedItem = null; } } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePostfix() { TZPState.ResetAll(); } } [HarmonyPatch(typeof(TetraChemicalItem))] internal static class TZPItemPatches { internal static readonly FieldRef<TetraChemicalItem, bool> EmittingGas = AccessTools.FieldRefAccess<TetraChemicalItem, bool>("emittingGas"); internal static readonly FieldRef<TetraChemicalItem, float> Fuel = AccessTools.FieldRefAccess<TetraChemicalItem, float>("fuel"); internal const float SecondsPerTank = 38f; [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(TetraChemicalItem __instance) { GameNetworkManager instance = GameNetworkManager.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.localPlayerController == (Object)null) && ((GrabbableObject)__instance).isHeld && !((Object)(object)((GrabbableObject)__instance).playerHeldBy != (Object)(object)instance.localPlayerController) && EmittingGas.Invoke(__instance) && Fuel.Invoke(__instance) > 0f) { TZPState.MarkInhaling(); } } } }