Untitled left D:\ValheimDev\Dumps\Latest\assembly_valheim\ShieldGenerator.cs
.  using System;
  using System.Collections.Generic;
  using System.Text;
  using UnityEngine;
   
  public class ShieldGenerator : MonoBehaviour, Hoverable, Interactable
  {
      private void Start()
      {
          if (Player.IsPlacementGhost(base.gameObject))
          {
              base.enabled = false;
              this.m_isPlacementGhost = true;
              return;
          }
          ShieldGenerator.m_instances.Add(this);
          ShieldGenerator.m_instanceChangeID++;
          this.m_nview = base.GetComponent<ZNetView>();
          if (this.m_nview == null)
          {
              this.m_nview = base.GetComponentInParent<ZNetView>();
          }
          if (this.m_nview == null || this.m_nview.GetZDO() == null)
          {
              return;
          }
          if (this.m_addFuelSwitch)
          {
              Switch addFuelSwitch = this.m_addFuelSwitch;
              addFuelSwitch.m_onUse = (Switch.Callback)Delegate.Combine(addFuelSwitch.m_onUse, new Switch.Callback(this.OnAddFuel));
              this.m_addFuelSwitch.m_onHover = new Switch.TooltipCallback(this.OnHoverAddFuel);
          }
          this.m_nview.Register("RPC_AddFuel", new Action<long>(this.RPC_AddFuel));
          this.m_nview.Register("RPC_Attack", new Action<long>(this.RPC_Attack));
          this.m_nview.Register("RPC_HitNow", new Action<long>(this.RPC_HitNow));
          this.m_projectileMask = LayerMask.GetMask(Array.Empty<string>());
          if (!ShieldGenerator.m_shieldDomeEffect)
          {
              ShieldGenerator.m_shieldDomeEffect = UnityEngine.Object.FindFirstObjectByType<ShieldDomeImageEffect>();
          }
          if (!this.m_enableAttack && this.m_fuelItems.Count == 0)
          {
              this.m_addFuelSwitch.gameObject.SetActive(false);
          }
          this.m_particleFlareGradient = new Gradient();
          this.m_particleFlareGradient.colorKeys = new GradientColorKey[]
          {
              new GradientColorKey(Color.white, 0f)
          };
          this.m_particleFlareGradient.alphaKeys = new GradientAlphaKey[]
          {
              new GradientAlphaKey(0f, 0f)
          };
          this.m_propertyBlock = new MaterialPropertyBlock();
          this.m_meshRenderers = this.m_enabledObject.GetComponentsInChildren<MeshRenderer>();
          base.InvokeRepeating("UpdateShield", 0f, 0.22f);
      }
   
      public string GetHoverText()
      {
          if (!this.m_enableAttack)
          {
              return "";
          }
          if (this.m_attackCharge <= 0f)
          {
              return Localization.instance.Localize(this.m_name + "\n$piece_shieldgenerator_waiting");
          }
          if (this.m_attackCharge >= 1f)
          {
              return Localization.instance.Localize(this.m_name + "\n$piece_shieldgenerator_ready \n[<color=yellow><b>$KEY_Use</b></color>] $piece_shieldgenerator_use");
          }
          return Localization.instance.Localize(this.m_name + "\n$piece_shieldgenerator_charging " + (Terminal.m_showTests ? this.m_attackCharge.ToString("0.00") : ""));
      }
   
      public string GetHoverName()
      {
          return "";
      }
   
      public bool Interact(Humanoid user, bool repeat, bool alt)
      {
          if (!this.m_enableAttack)
          {
              return false;
          }
          if (repeat)
          {
              return false;
          }
          if (user == Player.m_localPlayer && this.m_attackCharge >= 1f)
          {
              this.m_nview.InvokeRPC("RPC_Attack", Array.Empty<object>());
          }
          return false;
      }
   
      public bool UseItem(Humanoid user, ItemDrop.ItemData item)
      {
          return false;
      }
   
      private void RPC_Attack(long sender)
      {
          this.m_attackCharge = 0f;
          if (!this.m_nview.IsOwner())
          {
              return;
          }
          this.SetFuel(0f);
          this.m_nview.GetZDO().Set(ZDOVars.s_startTime, 0L);
          this.UpdateAttackCharge();
          if (this.m_attackObject)
          {
              GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this.m_attackObject, base.transform.position, base.transform.rotation);
              if (!this.m_damagePlayers)
              {
                  Aoe componentInChildren = gameObject.GetComponentInChildren<Aoe>();
                  if (componentInChildren != null)
                  {
                      componentInChildren.Setup(Player.m_localPlayer, Vector3.zero, 1f, null, null, null);
                  }
              }
          }
          this.m_attackEffects.Create(base.transform.position, base.transform.rotation, null, 1f, -1);
          this.m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation, base.transform, 1f, -1);
      }
   
      private void RPC_HitNow(long sender)
      {
          this.m_lastHitTime = Time.time;
      }
   
      private void UpdateAttackCharge()
      {
          this.m_attackCharge = this.GetAttackCharge();
      }
   
      private float GetAttackCharge()
      {
          long @long = this.m_nview.GetZDO().GetLong(ZDOVars.s_startTime, 0L);
          if (@long <= 0L)
          {
              return 0f;
          }
          DateTime time = ZNet.instance.GetTime();
          DateTime dateTime = new DateTime(@long);
          return (float)((time - dateTime).TotalSeconds / (double)this.m_attackChargeTime);
      }
   
      private void OnDestroy()
      {
          if (this.m_isPlacementGhost)
          {
              return;
          }
          ShieldGenerator.m_shieldDomeEffect.RemoveShield(this);
          ShieldGenerator.m_instances.Remove(this);
          ShieldGenerator.m_instanceChangeID++;
          Character.SetupContinuousEffect(base.transform, base.transform.position, false, this.m_shieldLowLoop, ref this.m_lowLoopInstances);
      }
   
      private float GetFuel()
      {
          if (!this.m_nview.IsValid())
          {
              return 0f;
          }
          return this.m_nview.GetZDO().GetFloat(ZDOVars.s_fuel, (float)this.m_defaultFuel);
      }
   
      private void SetFuel(float fuel)
      {
          if (!this.m_nview.IsValid() || !this.m_nview.IsOwner())
          {
              return;
          }
          this.m_nview.GetZDO().Set(ZDOVars.s_fuel, Mathf.Max(fuel, 0f));
      }
   
      private bool OnAddFuel(Switch sw, Humanoid user, ItemDrop.ItemData item)
      {
          if (this.GetFuel() > (float)(this.m_maxFuel - 1))
          {
              user.Message(MessageHud.MessageType.Center, "$msg_itsfull", 0, null);
              return false;
          }
          if (item != null)
          {
              bool flag = false;
              foreach (ItemDrop itemDrop in this.m_fuelItems)
              {
                  if (item.m_shared.m_name == itemDrop.m_itemData.m_shared.m_name)
                  {
                      flag = true;
                      break;
                  }
              }
              if (!flag)
              {
                  user.Message(MessageHud.MessageType.Center, "$msg_wrongitem", 0, null);
                  return false;
              }
          }
          else
          {
              bool flag2 = false;
              foreach (ItemDrop itemDrop2 in this.m_fuelItems)
              {
                  if (user.GetInventory().HaveItem(itemDrop2.m_itemData.m_shared.m_name, true))
                  {
                      item = itemDrop2.m_itemData;
                      flag2 = true;
                      break;
                  }
              }
              if (!flag2)
              {
                  user.Message(MessageHud.MessageType.Center, "$msg_donthaveany $piece_shieldgenerator_fuelname", 0, null);
                  return false;
              }
          }
          user.Message(MessageHud.MessageType.Center, "$msg_added " + item.m_shared.m_name, 0, null);
          user.GetInventory().RemoveItem(item.m_shared.m_name, 1, -1, true);
          this.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
          return true;
      }
   
      private void RPC_AddFuel(long sender)
      {
          if (!this.m_nview.IsOwner())
          {
              return;
          }
          float fuel = this.GetFuel();
          this.SetFuel(fuel + 1f);
          this.m_fuelAddedEffects.Create(base.transform.position, base.transform.rotation, base.transform, 1f, -1);
      }
   
      private void Update()
      {
          if (this.m_shieldDome)
          {
              float num = this.m_shieldDome.transform.localScale.x + (this.m_radius - this.m_shieldDome.transform.localScale.x) * this.m_decreaseInertia;
              this.m_shieldDome.transform.localScale = new Vector3(num, num, num);
          }
          if (this.m_radiusTarget != this.m_radius)
          {
              if (!this.m_firstCheck)
              {
                  this.m_firstCheck = true;
                  this.m_radius = this.m_radiusTarget;
              }
              float num2 = this.m_radiusTarget - this.m_radius;
              this.m_radius += Mathf.Min(this.m_startStopSpeed * Time.deltaTime, Mathf.Abs(num2)) * (float)((num2 > 0f) ? 1 : (-1));
          }
          if (this.m_lastFuel != this.m_lastFuelSent || this.m_radius != this.m_radiusSent || this.m_lastHitTime != this.m_lastHitTimeSent)
          {
              ShieldGenerator.m_shieldDomeEffect.SetShieldData(this, this.m_shieldDome.transform.position, this.m_radius, this.m_lastFuel, this.m_lastHitTime);
              this.m_lastFuelSent = this.m_lastFuel;
              this.m_radiusSent = this.m_radius;
              this.m_lastHitTimeSent = this.m_lastHitTime;
          }
      }
   
      private void UpdateShield()
      {
          if (!this.m_nview.IsValid())
          {
              return;
          }
          float fuel = this.GetFuel();
          GameObject enabledObject = this.m_enabledObject;
          if (enabledObject != null)
          {
              enabledObject.SetActive(fuel > 0f);
          }
          GameObject disabledObject = this.m_disabledObject;
          if (disabledObject != null)
          {
              disabledObject.SetActive(fuel <= 0f);
          }
          float radius = this.m_radius;
          this.m_lastFuel = fuel / (float)this.m_maxFuel;
          float radiusTarget = this.m_radiusTarget;
          this.m_radiusTarget = this.m_minShieldRadius + this.m_lastFuel * (this.m_maxShieldRadius - this.m_minShieldRadius);
          Color domeColor = ShieldDomeImageEffect.GetDomeColor(this.m_lastFuel);
          foreach (ParticleSystem particleSystem in this.m_energyParticles)
          {
              particleSystem.main.startColor = domeColor;
              particleSystem.emission.rateOverTime = this.m_lastFuel * 5f;
          }
          this.m_energyParticlesFlare.customData.SetColor(ParticleSystemCustomData.Custom1, domeColor * Mathf.Pow(this.m_lastFuel, 0.5f));
          Light[] coloredLights = this.m_coloredLights;
          for (int i = 0; i < coloredLights.Length; i++)
          {
              coloredLights[i].color = domeColor;
          }
          this.m_propertyBlock.SetColor(ShieldGenerator.s_emissiveProperty, domeColor * 2f);
          MeshRenderer[] meshRenderers = this.m_meshRenderers;
          for (int i = 0; i < meshRenderers.Length; i++)
          {
              meshRenderers[i].SetPropertyBlock(this.m_propertyBlock);
          }
          if (this.m_offWhenNoFuel)
          {
              if (fuel <= 0f)
              {
                  this.m_radiusTarget = 0f;
                  if (radiusTarget > 0f && this.m_nview.IsOwner())
                  {
                      this.m_shieldStop.Create(this.m_shieldDome.transform.position, this.m_shieldDome.transform.rotation, null, 1f, -1);
                  }
              }
              if (fuel > 0f && radiusTarget <= 0f && this.m_nview.IsOwner())
              {
                  this.m_shieldStart.Create(this.m_shieldDome.transform.position, this.m_shieldDome.transform.rotation, null, 1f, -1);
              }
          }
          if (this.m_shieldLowLoopFuelStart > 0f && this.m_nview.IsOwner())
          {
              Character.SetupContinuousEffect(base.transform, base.transform.position, this.m_lastFuel > 0f && this.m_lastFuel < this.m_shieldLowLoopFuelStart, this.m_shieldLowLoop, ref this.m_lowLoopInstances);
          }
          if (this.m_nview.IsOwner() && fuel >= (float)this.m_maxFuel && this.m_nview.GetZDO().GetLong(ZDOVars.s_startTime, 0L) <= 0L)
          {
              DateTime time = ZNet.instance.GetTime();
              this.m_nview.GetZDO().Set(ZDOVars.s_startTime, time.Ticks);
          }
          this.UpdateAttackCharge();
      }
   
      public static void CheckProjectile(Projectile projectile)
      {
          if (!projectile.HasBeenOutsideShields)
          {
              int num = ShieldGenerator.m_instances.Count;
              foreach (ShieldGenerator shieldGenerator in ShieldGenerator.m_instances)
              {
                  if (Vector3.Distance(shieldGenerator.m_shieldDome.transform.position, projectile.transform.position) < shieldGenerator.m_radius || !ShieldGenerator.CheckShield(shieldGenerator))
                  {
                      num--;
                  }
              }
              if (num == 0)
              {
                  projectile.TriggerShieldsLeftFlag();
              }
          }
          else
          {
              foreach (ShieldGenerator shieldGenerator2 in ShieldGenerator.m_instances)
              {
                  if (ShieldGenerator.CheckShield(shieldGenerator2) && Vector3.Distance(shieldGenerator2.m_shieldDome.transform.position, projectile.m_startPoint) > shieldGenerator2.m_radius && Vector3.Distance(shieldGenerator2.m_shieldDome.transform.position, projectile.transform.position) < shieldGenerator2.m_radius)
                  {
                      shieldGenerator2.OnProjectileHit(projectile.gameObject);
                  }
              }
          }
          ShieldGenerator.ShieldCleanup();
      }
   
      public float GetFuelRatio()
      {
          return Mathf.Clamp01(this.m_lastFuel);
      }
   
      public static void CheckObjectInsideShield(Cinder zinder)
      {
          foreach (ShieldGenerator shieldGenerator in ShieldGenerator.m_instances)
          {
              if (ShieldGenerator.CheckShield(shieldGenerator) && Vector3.Distance(shieldGenerator.m_shieldDome.transform.position, zinder.transform.position) < shieldGenerator.m_radius)
              {
                  shieldGenerator.OnProjectileHit(zinder.gameObject);
              }
          }
          ShieldGenerator.ShieldCleanup();
      }
   
      public static bool IsInsideShield(Vector3 point)
      {
          foreach (ShieldGenerator shieldGenerator in ShieldGenerator.m_instances)
          {
              if (ShieldGenerator.CheckShield(shieldGenerator) && shieldGenerator && shieldGenerator.m_shieldDome && Vector3.Distance(shieldGenerator.m_shieldDome.transform.position, point) < shieldGenerator.m_radius)
              {
                  return true;
              }
          }
          ShieldGenerator.ShieldCleanup();
          return false;
      }
   
      public static bool IsInsideMaxShield(Vector3 point)
      {
          foreach (ShieldGenerator shieldGenerator in ShieldGenerator.m_instances)
          {
              if (ShieldGenerator.CheckShield(shieldGenerator) && shieldGenerator && shieldGenerator.m_shieldDome && Vector3.Distance(shieldGenerator.m_shieldDome.transform.position, point) < shieldGenerator.m_maxShieldRadius)
              {
                  return true;
              }
          }
          ShieldGenerator.ShieldCleanup();
          return false;
      }
   
      public static bool IsInsideShieldCached(Vector3 point, ref int changeID)
      {
          if (Mathf.Abs(changeID) <= ShieldGenerator.m_instanceChangeID)
          {
              if (!ShieldGenerator.IsInsideMaxShield(point))
              {
                  changeID = -ShieldGenerator.m_instanceChangeID;
                  return false;
              }
              changeID = ShieldGenerator.m_instanceChangeID;
              if (ShieldGenerator.IsInsideShield(point))
              {
                  return true;
              }
          }
          return changeID > 0 && ShieldGenerator.IsInsideShield(point);
      }
   
      private static bool CheckShield(ShieldGenerator shield)
      {
          if (!shield || !shield.m_shieldDome)
          {
              ShieldGenerator.s_cleanShields = true;
              return false;
          }
          return true;
      }
   
      private static void ShieldCleanup()
      {
          if (ShieldGenerator.s_cleanShields)
          {
              int num = ShieldGenerator.m_instances.RemoveAll((ShieldGenerator x) => x == null || x.m_shieldDome == null);
              if (num > 0)
              {
                  ZLog.LogWarning(string.Format("Removed {0} invalid shield instances. Some shields may be broken?", num));
              }
              ShieldGenerator.s_cleanShields = false;
          }
      }
   
      public void OnProjectileHit(GameObject obj)
      {
          Vector3 position = obj.transform.position;
          Projectile component = obj.GetComponent<Projectile>();
          if (component != null)
          {
              component.OnHit(null, position, false, -obj.transform.forward);
          }
          ZNetScene.instance.Destroy(obj.gameObject);
          if (this.m_fuelPerDamage > 0f)
          {
              float num = this.m_fuelPerDamage * (component ? component.m_damage.GetTotalDamage() : 10f);
              this.SetFuel(this.GetFuel() - num);
          }
          this.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_HitNow", Array.Empty<object>());
          this.m_shieldHitEffects.Create(position, Quaternion.LookRotation(base.transform.position.DirTo(position)), null, 1f, -1);
          this.UpdateShield();
      }
   
      private string OnHoverAddFuel()
      {
          float fuel = this.GetFuel();
          return Localization.instance.Localize(string.Format("{0} ({1}/{2})\n[<color=yellow><b>$KEY_Use</b></color>] {3}", new object[]
          {
              this.m_name,
              Mathf.Ceil(fuel),
              this.m_maxFuel,
              this.m_add
          }));
      }
   
      public static bool HasShields()
      {
          if (ShieldGenerator.m_instances == null)
          {
              return false;
          }
          using (List<ShieldGenerator>.Enumerator enumerator = ShieldGenerator.m_instances.GetEnumerator())
          {
              while (enumerator.MoveNext())
              {
                  if (enumerator.Current.m_lastFuel > 0f)
                  {
                      return true;
                  }
              }
          }
          return false;
      }
   
      private static float SDFSmoothMin(float a, float b, float k)
      {
          k *= 6f;
          float num = Mathf.Max(k - Mathf.Abs(a - b), 0f) / k;
          return Mathf.Min(a, b) - num * num * num * k * 0.16666667f;
      }
   
      public static Vector3 DirectionToShieldWall(Vector3 pos)
      {
          float num = 0.001f;
          return -Vector3.Normalize(new Vector3(ShieldGenerator.DistanceToShieldWall(pos + new Vector3(0f, num, 0f)), ShieldGenerator.DistanceToShieldWall(pos + new Vector3(0f, 0f, num)), ShieldGenerator.DistanceToShieldWall(pos + new Vector3(num, 0f, 0f))));
      }
   
      public static float DistanceToShieldWall(Vector3 pos)
      {
          float num = float.PositiveInfinity;
          foreach (ShieldGenerator shieldGenerator in ShieldGenerator.m_instances)
          {
              if (shieldGenerator.m_lastFuel != 0f)
              {
                  float num2 = Vector3.Distance(shieldGenerator.transform.position, pos) - shieldGenerator.m_radius;
                  num = ShieldGenerator.SDFSmoothMin(num, num2, ShieldDomeImageEffect.Smoothing);
              }
          }
          return num;
      }
   
      public static Vector3 GetClosestShieldPoint(Vector3 pos)
      {
          float num = ShieldGenerator.DistanceToShieldWall(pos);
          Vector3 vector = ShieldGenerator.DirectionToShieldWall(pos);
          return pos + vector * num;
      }
   
      public static ShieldGenerator GetClosestShieldGenerator(Vector3 pos, bool ignoreRadius = false)
      {
          ShieldGenerator shieldGenerator = null;
          float num = float.PositiveInfinity;
          foreach (ShieldGenerator shieldGenerator2 in ShieldGenerator.m_instances)
          {
              float num2 = (ignoreRadius ? 0f : shieldGenerator2.m_radius);
              float num3 = Mathf.Abs(Vector3.Distance(shieldGenerator2.transform.position, pos) - num2);
              if (num3 < num)
              {
                  num = num3;
                  shieldGenerator = shieldGenerator2;
              }
          }
          return shieldGenerator;
      }
   
      private static bool s_cleanShields = false;
   
      private static List<ShieldGenerator> m_instances = new List<ShieldGenerator>();
   
      private static int m_instanceChangeID = 0;
   
      private static ShieldDomeImageEffect m_shieldDomeEffect;
   
      public string m_name = "$piece_shieldgenerator";
   
      public string m_add = "$piece_shieldgenerator_add";
   
      public Switch m_addFuelSwitch;
   
      public GameObject m_enabledObject;
   
      public GameObject m_disabledObject;
   
      [Header("Fuel")]
      public List<ItemDrop> m_fuelItems = new List<ItemDrop>();
   
      public int m_maxFuel = 10;
   
      public int m_defaultFuel;
   
      public float m_fuelPerDamage = 0.01f;
   
      public EffectList m_fuelAddedEffects = new EffectList();
   
      [Header("Shield")]
      public GameObject m_shieldDome;
   
      public float m_minShieldRadius = 10f;
   
      public float m_maxShieldRadius = 30f;
   
      public float m_decreaseInertia = 0.98f;
   
      public float m_startStopSpeed = 0.5f;
   
      public bool m_offWhenNoFuel = true;
   
      [Header("Attack")]
      public bool m_enableAttack = true;
   
      public float m_attackChargeTime = 900f;
   
      public bool m_damagePlayers = true;
   
      public GameObject m_attackObject;
   
      public EffectList m_attackEffects = new EffectList();
   
      [Header("Effects")]
      public EffectList m_shieldHitEffects = new EffectList();
   
      public EffectList m_shieldStart = new EffectList();
   
      public EffectList m_shieldStop = new EffectList();
   
      public EffectList m_shieldLowLoop = new EffectList();
   
      public float m_shieldLowLoopFuelStart;
   
      public ParticleSystem[] m_energyParticles;
   
      public ParticleSystem m_energyParticlesFlare;
   
      public Light[] m_coloredLights;
   
      private static readonly int s_emissiveProperty = Shader.PropertyToID("_EmissionColor");
   
      private ZNetView m_nview;
   
      private StringBuilder m_sb = new StringBuilder();
   
      private bool m_firstCheck;
   
      private int m_projectileMask;
   
      private float m_radius;
   
      private float m_radiusTarget;
   
      private float m_radiusSent;
   
      private float m_lastFuel;
   
      private float m_lastFuelSent;
   
      private float m_lastHitTime;
   
      private float m_lastHitTimeSent;
   
      private float m_attackCharge;
   
      private bool m_isPlacementGhost;
   
      private GameObject[] m_lowLoopInstances;
   
      private Gradient m_particleFlareGradient;
   
      private MeshRenderer[] m_meshRenderers;
   
      private MaterialPropertyBlock m_propertyBlock;
  }