D:\ValheimDev\Dumps\Old\assembly_valheim\Plant.cs D:\ValheimDev\Dumps\Latest\assembly_valheim\Plant.cs
using System; using System;
using UnityEngine; using UnityEngine;
   
public class Plant : SlowUpdate, Hoverable public class Plant : SlowUpdate, Hoverable
{ {
    public override void Awake()     public override void Awake()
    {     {
        base.Awake();         base.Awake();
        this.m_nview = base.gameObject.GetComponent<ZNetView>();         this.m_nview = base.gameObject.GetComponent<ZNetView>();
        if (this.m_nview.GetZDO() == null)         if (this.m_nview.GetZDO() == null)
        {         {
            return;             return;
        }         }
        this.m_seed = this.m_nview.GetZDO().GetInt(ZDOVars.s_seed, 0);         this.m_seed = this.m_nview.GetZDO().GetInt(ZDOVars.s_seed, 0);
        if (this.m_seed == 0)         if (this.m_seed == 0)
        {         {
            this.m_seed = (int)((ulong)this.m_nview.GetZDO().m_uid.ID + (ulong)this.m_nview.GetZDO().m_uid.UserID);             this.m_seed = (int)((ulong)this.m_nview.GetZDO().m_uid.ID + (ulong)this.m_nview.GetZDO().m_uid.UserID);
            this.m_nview.GetZDO().Set(ZDOVars.s_seed, this.m_seed, true);             this.m_nview.GetZDO().Set(ZDOVars.s_seed, this.m_seed, true);
        }         }
        if (this.m_nview.IsOwner() && this.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, 0L) == 0L)         if (this.m_nview.IsOwner() && this.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, 0L) == 0L)
        {         {
            this.m_nview.GetZDO().Set(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);             this.m_nview.GetZDO().Set(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);
        }         }
        this.m_spawnTime = Time.time;         this.m_spawnTime = Time.time;
    }     }
   
    public string GetHoverText()     public string GetHoverText()
    {     {
        switch (this.m_status)         switch (this.m_status)
        {         {
        case Plant.Status.Healthy:         case Plant.Status.Healthy:
            return Localization.instance.Localize(this.m_name + " ( $piece_plant_healthy )");             return Localization.instance.Localize(this.m_name + " ( $piece_plant_healthy )");
        case Plant.Status.NoSun:         case Plant.Status.NoSun:
            return Localization.instance.Localize(this.m_name + " ( $piece_plant_nosun )");             return Localization.instance.Localize(this.m_name + " ( $piece_plant_nosun )");
        case Plant.Status.NoSpace:         case Plant.Status.NoSpace:
            return Localization.instance.Localize(this.m_name + " ( $piece_plant_nospace )");             return Localization.instance.Localize(this.m_name + " ( $piece_plant_nospace )");
        case Plant.Status.WrongBiome:         case Plant.Status.WrongBiome:
            return Localization.instance.Localize(this.m_name + " ( $piece_plant_wrongbiome )");             return Localization.instance.Localize(this.m_name + " ( $piece_plant_wrongbiome )");
        case Plant.Status.NotCultivated:         case Plant.Status.NotCultivated:
            return Localization.instance.Localize(this.m_name + " ( $piece_plant_notcultivated )");             return Localization.instance.Localize(this.m_name + " ( $piece_plant_notcultivated )");
.          case Plant.Status.NoAttachPiece:
              return Localization.instance.Localize(this.m_name + " ( $piece_plant_nowall )");
          case Plant.Status.TooHot:
              return Localization.instance.Localize(this.m_name + " ( $piece_plant_toohot )");
          case Plant.Status.TooCold:
              return Localization.instance.Localize(this.m_name + " ( $piece_plant_toocold )");
        default:         default:
            return "";             return "";
        }         }
    }     }
   
    public string GetHoverName()     public string GetHoverName()
    {     {
        return Localization.instance.Localize(this.m_name);         return Localization.instance.Localize(this.m_name);
    }     }
   
    private double TimeSincePlanted()     private double TimeSincePlanted()
    {     {
        DateTime dateTime = new DateTime(this.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks));         DateTime dateTime = new DateTime(this.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks));
        return (ZNet.instance.GetTime() - dateTime).TotalSeconds;         return (ZNet.instance.GetTime() - dateTime).TotalSeconds;
    }     }
   
    public override void SUpdate()     public override void SUpdate()
    {     {
        if (!this.m_nview.IsValid())         if (!this.m_nview.IsValid())
        {         {
            return;             return;
        }         }
        if (Time.time - this.m_updateTime < 10f)         if (Time.time - this.m_updateTime < 10f)
        {         {
            return;             return;
        }         }
        this.m_updateTime = Time.time;         this.m_updateTime = Time.time;
        double num = this.TimeSincePlanted();         double num = this.TimeSincePlanted();
        this.UpdateHealth(num);         this.UpdateHealth(num);
        float growTime = this.GetGrowTime();         float growTime = this.GetGrowTime();
        if (this.m_healthyGrown)         if (this.m_healthyGrown)
        {         {
            bool flag = num > (double)(growTime * 0.5f);             bool flag = num > (double)(growTime * 0.5f);
            this.m_healthy.SetActive(!flag && this.m_status == Plant.Status.Healthy);             this.m_healthy.SetActive(!flag && this.m_status == Plant.Status.Healthy);
            this.m_unhealthy.SetActive(!flag && this.m_status > Plant.Status.Healthy);             this.m_unhealthy.SetActive(!flag && this.m_status > Plant.Status.Healthy);
            this.m_healthyGrown.SetActive(flag && this.m_status == Plant.Status.Healthy);             this.m_healthyGrown.SetActive(flag && this.m_status == Plant.Status.Healthy);
            this.m_unhealthyGrown.SetActive(flag && this.m_status > Plant.Status.Healthy);             this.m_unhealthyGrown.SetActive(flag && this.m_status > Plant.Status.Healthy);
        }         }
        else         else
        {         {
            this.m_healthy.SetActive(this.m_status == Plant.Status.Healthy);             this.m_healthy.SetActive(this.m_status == Plant.Status.Healthy);
            this.m_unhealthy.SetActive(this.m_status > Plant.Status.Healthy);             this.m_unhealthy.SetActive(this.m_status > Plant.Status.Healthy);
        }         }
        if (this.m_nview.IsOwner() && Time.time - this.m_spawnTime > 10f && num > (double)growTime)         if (this.m_nview.IsOwner() && Time.time - this.m_spawnTime > 10f && num > (double)growTime)
        {         {
            this.Grow();             this.Grow();
        }         }
    }     }
   
    private float GetGrowTime()     private float GetGrowTime()
    {     {
        UnityEngine.Random.State state = UnityEngine.Random.state;         UnityEngine.Random.State state = UnityEngine.Random.state;
        UnityEngine.Random.InitState(this.m_seed);         UnityEngine.Random.InitState(this.m_seed);
        float value = UnityEngine.Random.value;         float value = UnityEngine.Random.value;
        UnityEngine.Random.state = state;         UnityEngine.Random.state = state;
        return Mathf.Lerp(this.m_growTime, this.m_growTimeMax, value);         return Mathf.Lerp(this.m_growTime, this.m_growTimeMax, value);
    }     }
   
.    private void Grow()     public GameObject Grow()
    {     {
        if (this.m_status != Plant.Status.Healthy)         if (this.m_status != Plant.Status.Healthy)
        {         {
            if (this.m_destroyIfCantGrow)             if (this.m_destroyIfCantGrow)
            {             {
                this.Destroy();                 this.Destroy();
            }             }
.            return;             return null;
        }         }
        float num = 11.25f;         float num = 11.25f;
        GameObject gameObject = this.m_grownPrefabs[UnityEngine.Random.Range(0, this.m_grownPrefabs.Length)];         GameObject gameObject = this.m_grownPrefabs[UnityEngine.Random.Range(0, this.m_grownPrefabs.Length)];
.        Quaternion quaternion = Quaternion.Euler(base.transform.rotation.eulerAngles.x, base.transform.rotation.eulerAngles.y + UnityEngine.Random.Range(-num, num), base.transform.rotation.eulerAngles.z);         Vector3 vector = ((this.m_attachDistance > 0f) ? this.m_attachPos : base.transform.position); 
        GameObject gameObject2 = UnityEngine.Object.Instantiate<GameObject>(gameObject, base.transform.position, quaternion);         Quaternion quaternion = ((this.m_attachDistance > 0f) ? this.m_attachRot : Quaternion.Euler(base.transform.rotation.eulerAngles.x, base.transform.rotation.eulerAngles.y + UnityEngine.Random.Range(-num, num), base.transform.rotation.eulerAngles.z));
          GameObject gameObject2 = UnityEngine.Object.Instantiate<GameObject>(gameObject, vector, quaternion); 
          if (this.m_attachDistance > 0f) 
          { 
              this.PlaceAgainst(gameObject2, this.m_attachRot, this.m_attachPos, this.m_attachNormal); 
          } 
          string text = "Starting to grow plant with rotation: "; 
          Quaternion quaternion2 = quaternion; 
          ZLog.Log(text + quaternion2.ToString());
        ZNetView component = gameObject2.GetComponent<ZNetView>();         ZNetView component = gameObject2.GetComponent<ZNetView>();
        float num2 = UnityEngine.Random.Range(this.m_minScale, this.m_maxScale);         float num2 = UnityEngine.Random.Range(this.m_minScale, this.m_maxScale);
        component.SetLocalScale(new Vector3(num2, num2, num2));         component.SetLocalScale(new Vector3(num2, num2, num2));
        TreeBase component2 = gameObject2.GetComponent<TreeBase>();         TreeBase component2 = gameObject2.GetComponent<TreeBase>();
.        if (component2)         if (component2 != null)
        {         {
            component2.Grow();             component2.Grow();
        }         }
.        this.m_nview.Destroy();         if (this.m_nview) 
        this.m_growEffect.Create(base.transform.position, quaternion, null, num2, -1);         { 
              this.m_nview.Destroy();
              this.m_growEffect.Create(base.transform.position, quaternion, null, num2, -1);
          } 
          return gameObject2; 
    }     }
   
.    private void UpdateHealth(double timeSincePlanted)     public void UpdateHealth(double timeSincePlanted)
    {     {
        if (timeSincePlanted < 10.0)         if (timeSincePlanted < 10.0)
        {         {
            this.m_status = Plant.Status.Healthy;             this.m_status = Plant.Status.Healthy;
            return;             return;
        }         }
        Heightmap heightmap = Heightmap.FindHeightmap(base.transform.position);         Heightmap heightmap = Heightmap.FindHeightmap(base.transform.position);
        if (heightmap)         if (heightmap)
        {         {
.            if ((heightmap.GetBiome(base.transform.position) & this.m_biome) == Heightmap.Biome.None)             Heightmap.Biome biome = heightmap.GetBiome(base.transform.position, 0.02f, false); 
              if ((biome & this.m_biome) == Heightmap.Biome.None)
            {             {
                this.m_status = Plant.Status.WrongBiome;                 this.m_status = Plant.Status.WrongBiome;
                return;                 return;
            }             }
            if (this.m_needCultivatedGround && !heightmap.IsCultivated(base.transform.position))             if (this.m_needCultivatedGround && !heightmap.IsCultivated(base.transform.position))
            {             {
                this.m_status = Plant.Status.NotCultivated;                 this.m_status = Plant.Status.NotCultivated;
                return;                 return;
            }             }
.              if (!this.m_tolerateHeat && biome == Heightmap.Biome.AshLands && !ShieldGenerator.IsInsideShield(base.transform.position))
              {
                  this.m_status = Plant.Status.TooHot;
                  return;
              }
              if (!this.m_tolerateCold && (biome == Heightmap.Biome.DeepNorth || biome == Heightmap.Biome.Mountain) && !ShieldGenerator.IsInsideShield(base.transform.position))
              {
                  this.m_status = Plant.Status.TooCold;
                  return;
              }
        }         }
        if (this.HaveRoof())         if (this.HaveRoof())
        {         {
            this.m_status = Plant.Status.NoSun;             this.m_status = Plant.Status.NoSun;
            return;             return;
        }         }
        if (!this.HaveGrowSpace())         if (!this.HaveGrowSpace())
        {         {
            this.m_status = Plant.Status.NoSpace;             this.m_status = Plant.Status.NoSpace;
            return;             return;
        }         }
.          if (this.m_attachDistance > 0f && !this.GetClosestAttachPosRot(out this.m_attachPos, out this.m_attachRot, out this.m_attachNormal))
          {
              this.m_status = Plant.Status.NoAttachPiece;
              return;
          }
        this.m_status = Plant.Status.Healthy;         this.m_status = Plant.Status.Healthy;
    }     }
   
.      public Collider GetClosestAttachObject()
      {
          return this.GetClosestAttachObject(base.transform.position);
      }
   
      public Collider GetClosestAttachObject(Vector3 from)
      {
          if (Plant.m_pieceMask == 0)
          {
              Plant.m_pieceMask = LayerMask.GetMask(new string[] { "piece" });
          }
          int num = Physics.OverlapSphereNonAlloc(from, this.m_attachDistance, Plant.s_hits, Plant.m_pieceMask);
          Collider collider = null;
          float num2 = float.MaxValue;
          for (int i = 0; i < num; i++)
          {
              Collider collider2 = Plant.s_hits[i];
              float num3 = Vector3.Distance(from, collider2.bounds.center);
              if (num3 < num2)
              {
                  Piece componentInParent = collider2.GetComponentInParent<Piece>();
                  if (componentInParent != null && !componentInParent.m_noVines)
                  {
                      collider = collider2;
                      num2 = num3;
                  }
              }
          }
          return collider;
      }
   
      public bool GetClosestAttachPosRot(out Vector3 pos, out Quaternion rot, out Vector3 normal)
      {
          return this.GetClosestAttachPosRot(base.transform.position, out pos, out rot, out normal);
      }
   
      public bool GetClosestAttachPosRot(Vector3 from, out Vector3 pos, out Quaternion rot, out Vector3 normal)
      {
          Collider closestAttachObject = this.GetClosestAttachObject(from);
          if (closestAttachObject != null)
          {
              if (Plant.m_pieceMask == 0)
              {
                  Plant.m_pieceMask = LayerMask.GetMask(new string[] { "piece" });
              }
              if (from.y < closestAttachObject.bounds.min.y)
              {
                  from.y += closestAttachObject.bounds.min.y - from.y + 0.01f;
              }
              if (from.y > closestAttachObject.bounds.max.y)
              {
                  from.y += closestAttachObject.bounds.max.y - from.y - 0.01f;
              }
              Vector3 vector = closestAttachObject.ClosestPoint(from);
              RaycastHit raycastHit;
              if (Physics.Raycast(from, vector - from, out raycastHit, 50f, Plant.m_pieceMask) && raycastHit.collider && !raycastHit.collider.attachedRigidbody)
              {
                  pos = raycastHit.point;
                  rot = Quaternion.Euler(0f, 90f, 0f) * Quaternion.LookRotation(raycastHit.normal);
                  normal = raycastHit.normal;
                  Terminal.Log("Plant found grow normal: " + raycastHit.normal.ToString());
                  return true;
              }
              Terminal.Log("Plant ray didn't hit any valid colliders");
          }
          pos = (normal = Vector3.zero);
          rot = Quaternion.identity;
          Terminal.Log("Plant found no attach obj.");
          return false;
      }
   
      public void PlaceAgainst(GameObject obj, Quaternion rot, Vector3 hitPos, Vector3 hitNormal)
      {
          obj.transform.position = hitPos + hitNormal * 50f;
          obj.transform.rotation = rot;
          Vector3 vector = Vector3.zero;
          float num = 999999f;
          foreach (Collider collider in obj.GetComponentsInChildren<Collider>())
          {
              if (!collider.isTrigger && collider.enabled)
              {
                  MeshCollider meshCollider = collider as MeshCollider;
                  if (!(meshCollider != null) || meshCollider.convex)
                  {
                      Vector3 vector2 = collider.ClosestPoint(hitPos);
                      float num2 = Vector3.Distance(vector2, hitPos);
                      if (num2 < num)
                      {
                          vector = vector2;
                          num = num2;
                      }
                  }
              }
          }
          Vector3 vector3 = obj.transform.position - vector;
          obj.transform.position = hitPos + vector3;
          obj.transform.rotation = rot;
      }
   
    private void Destroy()     private void Destroy()
    {     {
        IDestructible component = base.GetComponent<IDestructible>();         IDestructible component = base.GetComponent<IDestructible>();
        if (component != null)         if (component != null)
        {         {
            HitData hitData = new HitData();             HitData hitData = new HitData();
            hitData.m_damage.m_damage = 9999f;             hitData.m_damage.m_damage = 9999f;
            component.Damage(hitData);             component.Damage(hitData);
        }         }
    }     }
   
    private bool HaveRoof()     private bool HaveRoof()
    {     {
        if (Plant.m_roofMask == 0)         if (Plant.m_roofMask == 0)
        {         {
            Plant.m_roofMask = LayerMask.GetMask(new string[] { "Default", "static_solid", "piece" });             Plant.m_roofMask = LayerMask.GetMask(new string[] { "Default", "static_solid", "piece" });
        }         }
        return Physics.Raycast(base.transform.position, Vector3.up, 100f, Plant.m_roofMask);         return Physics.Raycast(base.transform.position, Vector3.up, 100f, Plant.m_roofMask);
    }     }
   
    private bool HaveGrowSpace()     private bool HaveGrowSpace()
    {     {
        if (Plant.m_spaceMask == 0)         if (Plant.m_spaceMask == 0)
        {         {
            Plant.m_spaceMask = LayerMask.GetMask(new string[] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });             Plant.m_spaceMask = LayerMask.GetMask(new string[] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });
        }         }
.        Collider[] array = Physics.OverlapSphere(base.transform.position, this.m_growRadius, Plant.m_spaceMask);         int num = Physics.OverlapSphereNonAlloc(base.transform.position, this.m_growRadius, Plant.s_colliders, Plant.m_spaceMask);
        for (int i = 0; i < array.Length; i++)         for (int i = 0; i < num; i++)
        {         {
.            Plant component = array[i].GetComponent<Plant>();             Plant component = Plant.s_colliders[i].GetComponent<Plant>();
            if (!component || (!(component == this) && component.GetStatus() == Plant.Status.Healthy))             if (!component || (!(component == this) && component.GetStatus() == Plant.Status.Healthy))
            {             {
                return false;                 return false;
            }             }
        }         }
.          if (this.m_growRadiusVines > 0f)
          {
              num = Physics.OverlapSphereNonAlloc(base.transform.position, this.m_growRadiusVines, Plant.s_colliders, Plant.m_spaceMask);
              for (int j = 0; j < num; j++)
              {
                  if (Plant.s_colliders[j].GetComponentInParent<Vine>() != null)
                  {
                      return false;
                  }
              }
          }
        return true;         return true;
    }     }
   
.    private Plant.Status GetStatus()     public Plant.Status GetStatus()
    {     {
        return this.m_status;         return this.m_status;
    }     }
   
.      private static Collider[] s_colliders = new Collider[30];
   
      private static Collider[] s_hits = new Collider[10];
   
    public string m_name = "Plant";     public string m_name = "Plant";
   
    public float m_growTime = 10f;     public float m_growTime = 10f;
   
    public float m_growTimeMax = 2000f;     public float m_growTimeMax = 2000f;
   
    public GameObject[] m_grownPrefabs = new GameObject[0];     public GameObject[] m_grownPrefabs = new GameObject[0];
   
    public float m_minScale = 1f;     public float m_minScale = 1f;
   
    public float m_maxScale = 1f;     public float m_maxScale = 1f;
   
    public float m_growRadius = 1f;     public float m_growRadius = 1f;
   
.      public float m_growRadiusVines;
   
    public bool m_needCultivatedGround;     public bool m_needCultivatedGround;
   
    public bool m_destroyIfCantGrow;     public bool m_destroyIfCantGrow;
   
.      public bool m_tolerateHeat;
   
      public bool m_tolerateCold;
   
    [SerializeField]     [SerializeField]
    private GameObject m_healthy;     private GameObject m_healthy;
   
    [SerializeField]     [SerializeField]
    private GameObject m_unhealthy;     private GameObject m_unhealthy;
   
    [SerializeField]     [SerializeField]
    private GameObject m_healthyGrown;     private GameObject m_healthyGrown;
   
    [SerializeField]     [SerializeField]
    private GameObject m_unhealthyGrown;     private GameObject m_unhealthyGrown;
   
    [BitMask(typeof(Heightmap.Biome))]     [BitMask(typeof(Heightmap.Biome))]
    public Heightmap.Biome m_biome;     public Heightmap.Biome m_biome;
   
    public EffectList m_growEffect = new EffectList();     public EffectList m_growEffect = new EffectList();
   
.      [Header("Attach to buildpiece (Vines)")]
      public float m_attachDistance;
   
    private Plant.Status m_status;     private Plant.Status m_status;
   
    private ZNetView m_nview;     private ZNetView m_nview;
   
    private float m_updateTime;     private float m_updateTime;
   
    private float m_spawnTime;     private float m_spawnTime;
   
    private int m_seed;     private int m_seed;
   
.    private static int m_spaceMask;     private Vector3 m_attachPos; 
   
      private Vector3 m_attachNormal; 
   
      private Quaternion m_attachRot; 
   
      private Collider m_attachCollider; 
   
      private static int m_spaceMask = 0;
   
      private static int m_roofMask = 0; 
   
.    private static int m_roofMask;     private static int m_pieceMask = 0;
   
.    private enum Status     public enum Status
    {     {
        Healthy,         Healthy,
        NoSun,         NoSun,
        NoSpace,         NoSpace,
        WrongBiome,         WrongBiome,
.        NotCultivated          NotCultivated, 
          NoAttachPiece, 
          TooHot, 
          TooCold 
    }     }
} }