少年修仙传客户端代码仓库
client_linchunjie
2018-09-21 bc4c0810d6442171dace2023b28c31b8347c46ae
Merge branch 'master' of http://192.168.0.87:10010/r/snxxz_scripts
20个文件已添加
8个文件已修改
2161 ■■■■■ 已修改文件
Core/GameEngine/Model/Config/DogzConfig.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/GameEngine/Model/Config/DogzConfig.cs.meta 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins.meta 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails.meta 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/CircularBuffer.cs 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/CircularBuffer.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/GizmosExtra.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/GizmosExtra.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/Range.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/Range.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmokePlume.cs 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmokePlume.cs.meta 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmokeTrail.cs 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmokeTrail.cs.meta 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmoothTrail.cs 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/SmoothTrail.cs.meta 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/Trail.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/Trail.cs.meta 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/TrailRenderer_Base.cs 666 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/TrailRenderer_Base.cs.meta 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/VersionInformation.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Plugins/Trails/VersionInformation.cs.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dogz/DogzActiveWin.cs 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dogz/DogzCell.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dogz/DogzModel.cs 383 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dogz/DogzPackWin.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/MainInterfacePanel/HighSettingFadeInFadeOut.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/MainInterfacePanel/SkillTaskWin.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/GameEngine/Model/Config/DogzConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:            第二世界
//    [  Date ]:           Friday, August 17, 2018
//    [  Date ]:           Friday, September 21, 2018
//--------------------------------------------------------
using UnityEngine;
@@ -17,7 +17,8 @@
        public int[] BaseAttrTypes;
        public int[] BaseAttrValues;
        public int[] HelpBattleSkills;
        public int[] EquipPlaceColorList;
        public int FightPowerEx { get ; private set ; }
        public string EquipPlaceColorList { get ; private set; }
        public override string getKey()
        {
@@ -54,12 +55,9 @@
                     int.TryParse(HelpBattleSkillsStringArray[i],out HelpBattleSkills[i]);
                }
            
                string[] EquipPlaceColorListStringArray = rawContents[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                EquipPlaceColorList = new int[EquipPlaceColorListStringArray.Length];
                for (int i=0;i<EquipPlaceColorListStringArray.Length;i++)
                {
                     int.TryParse(EquipPlaceColorListStringArray[i],out EquipPlaceColorList[i]);
                }
                FightPowerEx=IsNumeric(rawContents[6]) ? int.Parse(rawContents[6]):0;
                EquipPlaceColorList = rawContents[7].Trim();
            }
            catch (Exception ex)
            {
Core/GameEngine/Model/Config/DogzConfig.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 940b0f1e335cf3749bb18fbee7090526
timeCreated: 1534489434
timeCreated: 1537522814
licenseType: Pro
MonoImporter:
  serializedVersion: 2
Plugins.meta
New file
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: d463e02633381cd46902c21b8d51f83e
folderAsset: yes
timeCreated: 1537519875
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Plugins/Trails.meta
New file
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 77d1032b5eb62ce4da86e600bc8884c8
folderAsset: yes
timeCreated: 1537519883
licenseType: Pro
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Plugins/Trails/CircularBuffer.cs
New file
@@ -0,0 +1,287 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace PigeonCoopToolkit.Utillities
{
    public class CircularBuffer<T> : IList<T>, ICollection<T>,
                                IEnumerable<T>, IEnumerable
    {
      /// <summary>
      /// Creates a new instance of a <see cref="RingBuffer&lt;T&gt;"/> with a
      /// specified cache size.
      // http://florianreischl.blogspot.com/2010/01/generic-c-ringbuffer.html
      /// </summary>
      /// <param name="capacity">The maximal count of items to be stored within
      /// the ring buffer.</param>
        public CircularBuffer(int capacity)
        {
         // validate capacity
         if (capacity <= 0)
            throw new ArgumentException("Must be greater than zero", "capacity");
         // set capacity and init the cache
         Capacity = capacity;
         _buffer = new T[capacity];
      }
      /// <summary>
      /// the internal buffer
      /// </summary>
      T[] _buffer;
      /// <summary>
      /// The all-over position within the ring buffer. The position
      /// increases continously by adding new items to the buffer. This
      /// value is needed to calculate the current relative position within the
      /// buffer.
      /// </summary>
      int _position;
      /// <summary>
      /// The current version of the buffer, this is required for a correct
      /// exception handling while enumerating over the items of the buffer.
      /// </summary>
      long _version;
      /// <summary>
      /// Gets or sets an item for a specified position within the ring buffer.
      /// </summary>
      /// <param name="index">The position to get or set an item.</param>
      /// <returns>The fond item at the specified position within the ring buffer.
      /// </returns>
      /// <exception cref="IndexOutOfRangeException"></exception>
      public T this[int index] {
         get {
            // validate the index
            if (index < 0 || index >= Count)
               throw new IndexOutOfRangeException();
            // calculate the relative position within the rolling base array
            int index2 = (_position - Count + index) % Capacity;
            return _buffer[index2];
         }
         set { Insert(index, value); }
      }
      /// <summary>
      /// Gets the maximal count of items within the ring buffer.
      /// </summary>
      public int Capacity { get; private set; }
      /// <summary>
      /// Get the current count of items within the ring buffer.
      /// </summary>
      public int Count { get; private set; }
      /// <summary>
      /// Adds a new item to the buffer.
      /// </summary>
      /// <param name="item">The item to be added to the buffer.</param>
      public void Add(T item) {
         // add a new item to the current relative position within the
         // buffer and increase the position
         _buffer[_position++ % Capacity] = item;
         // increase the count if capacity is not yet reached
         if (Count < Capacity) Count++;
         // buffer changed; next version
         _version++;
      }
      /// <summary>
      /// Clears the whole buffer and releases all referenced objects
      /// currently stored within the buffer.
      /// </summary>
      public void Clear() {
         for (int i = 0; i < Count; i++)
            _buffer[i] = default(T);
         _position = 0;
         Count = 0;
         _version++;
      }
      /// <summary>
      /// Determines if a specified item is currently present within
      /// the buffer.
      /// </summary>
      /// <param name="item">The item to search for within the current
      /// buffer.</param>
      /// <returns>True if the specified item is currently present within
      /// the buffer; otherwise false.</returns>
      public bool Contains(T item) {
         int index = IndexOf(item);
         return index != -1;
      }
      /// <summary>
      /// Copies the current items within the buffer to a specified array.
      /// </summary>
      /// <param name="array">The target array to copy the items of
      /// the buffer to.</param>
      /// <param name="arrayIndex">The start position witihn the target
      /// array to start copying.</param>
      public void CopyTo(T[] array, int arrayIndex) {
         for (int i = 0; i < Count; i++) {
            array[i + arrayIndex] = _buffer[(_position - Count + i) % Capacity];
         }
      }
      /// <summary>
      /// Gets an enumerator over the current items within the buffer.
      /// </summary>
      /// <returns>An enumerator over the current items within the buffer.
      /// </returns>
      public IEnumerator<T> GetEnumerator() {
         long version = _version;
         for (int i = 0; i < Count; i++) {
            if (version != _version)
               throw new InvalidOperationException("Collection changed");
            yield return this[i];
         }
      }
      /// <summary>
      /// Gets the position of a specied item within the ring buffer.
      /// </summary>
      /// <param name="item">The item to get the current position for.</param>
      /// <returns>The zero based index of the found item within the
      /// buffer. If the item was not present within the buffer, this
      /// method returns -1.</returns>
      public int IndexOf(T item) {
         // loop over the current count of items
         for (int i = 0; i < Count; i++) {
            // get the item at the relative position within the internal array
            T item2 = _buffer[(_position - Count + i) % Capacity];
            // if both items are null, return true
            if (null == item && null == item2)
               return i;
            // if equal return the position
            if (item != null && item.Equals(item2))
               return i;
         }
         // nothing found
         return -1;
      }
      /// <summary>
      /// Inserts an item at a specified position into the buffer.
      /// </summary>
      /// <param name="index">The position within the buffer to add
      /// the new item.</param>
      /// <param name="item">The new item to be added to the buffer.</param>
      /// <exception cref="IndexOutOfRangeException"></exception>
      /// <remarks>
      /// If the specified index is equal to the current count of items
      /// within the buffer, the specified item will be added.
      ///
      /// <b>Warning</b>
      /// Frequent usage of this method might become a bad idea if you are
      /// working with a large buffer capacity. The insertion of an item
      /// at a specified position within the buffer causes causes all present
      /// items below the specified position to be moved one position.
      /// </remarks>
      public void Insert(int index, T item) {
         // validate index
         if (index < 0 || index > Count)
            throw new IndexOutOfRangeException();
         // add if index equals to count
         if (index == Count) {
            Add(item);
            return;
         }
         // get the maximal count of items to be moved
         int count = Math.Min(Count, Capacity - 1) - index;
         // get the relative position of the new item within the buffer
         int index2 = (_position - Count + index) % Capacity;
         // move all items below the specified position
         for (int i = index2 + count; i > index2; i--) {
            int to = i % Capacity;
            int from = (i - 1) % Capacity;
            _buffer[to] = _buffer[from];
         }
         // set the new item
         _buffer[index2] = item;
         // adjust storage information
         if (Count < Capacity) {
            Count++;
            _position++;
         }
         // buffer changed; next version
         _version++;
      }
      /// <summary>
      /// Removes a specified item from the current buffer.
      /// </summary>
      /// <param name="item">The item to be removed.</param>
      /// <returns>True if the specified item was successfully removed
      /// from the buffer; otherwise false.</returns>
      /// <remarks>
      /// <b>Warning</b>
      /// Frequent usage of this method might become a bad idea if you are
      /// working with a large buffer capacity. The removing of an item
      /// requires a scan of the buffer to get the position of the specified
      /// item. If the item was found, the deletion requires a move of all
      /// items stored abouve the found position.
      /// </remarks>
      public bool Remove(T item) {
         // find the position of the specified item
         int index = IndexOf(item);
         // item was not found; return false
         if (index == -1)
            return false;
         // remove the item at the specified position
         RemoveAt(index);
         return true;
      }
      /// <summary>
      /// Removes an item at a specified position within the buffer.
      /// </summary>
      /// <param name="index">The position of the item to be removed.</param>
      /// <exception cref="IndexOutOfRangeException"></exception>
      /// <remarks>
      /// <b>Warning</b>
      /// Frequent usage of this method might become a bad idea if you are
      /// working with a large buffer capacity. The deletion requires a move
      /// of all items stored abouve the found position.
      /// </remarks>
      public void RemoveAt(int index) {
         // validate the index
         if (index < 0 || index >= Count)
            throw new IndexOutOfRangeException();
         // move all items above the specified position one step
         // closer to zeri
         for (int i = index; i < Count - 1; i++) {
            // get the next relative target position of the item
            int to = (_position - Count + i) % Capacity;
            // get the next relative source position of the item
            int from = (_position - Count + i + 1) % Capacity;
            // move the item
            _buffer[to] = _buffer[from];
         }
         // get the relative position of the last item, which becomes empty
         // after deletion and set the item as empty
         int last = (_position - 1) % Capacity;
         _buffer[last] = default(T);
         // adjust storage information
         _position--;
         Count--;
         // buffer changed; next version
         _version++;
      }
      /// <summary>
      /// Gets if the buffer is read-only. This method always returns false.
      /// </summary>
      bool ICollection<T>.IsReadOnly { get { return false; } }
      /// <summary>
      /// See generic implementation of <see cref="GetEnumerator"/>.
      /// </summary>
      /// <returns>See generic implementation of <see cref="GetEnumerator"/>.
      /// </returns>
      IEnumerator IEnumerable.GetEnumerator() {
         return this.GetEnumerator();
      }
   }
}
Plugins/Trails/CircularBuffer.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 51a19be087405654c8b4b50c67fa9200
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Plugins/Trails/GizmosExtra.cs
New file
@@ -0,0 +1,33 @@
using UnityEngine;
namespace PigeonCoopToolkit.Utillities
{
    public static class GizmosExtra
    {
        public static void GizmosDrawCircle(Vector3 position, Vector3 up, float size, int divisions)
        {
            Vector3 offset = (Quaternion.Euler(90,0,0) * (up* size)) ;
            for (int i = 0; i < divisions; i++)
            {
                Vector3 newOffset = Quaternion.AngleAxis(360f / divisions, up) * offset;
                Gizmos.DrawLine(position + offset, position + newOffset);
                offset = newOffset;
            }
        }
        public static void GizmosDrawArrow(Vector3 from, Vector3 to, float arrowSize)
        {
            Gizmos.DrawLine(from, to);
            Vector3 dir = to - from;
            dir = dir.normalized*arrowSize;
            Gizmos.DrawLine(to, to - Quaternion.Euler(0, 0, 45)*dir);
            Gizmos.DrawLine(to, to - Quaternion.Euler(0, 0, -45)*dir);
        }
    }
}
Plugins/Trails/GizmosExtra.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac8be081485ba1141bd28334fe9eabec
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Plugins/Trails/Range.cs
New file
@@ -0,0 +1,15 @@
namespace PigeonCoopToolkit.Utillities
{
    [System.Serializable]
    public class Range
    {
        public float Min;
        public float Max;
        public bool WithinRange(float value)
        {
            return Min <= value && Max >= value;
        }
    }
}
Plugins/Trails/Range.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db4c92c149ebf004a83b3776345ca8d4
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
Plugins/Trails/SmokePlume.cs
New file
@@ -0,0 +1,74 @@
using UnityEngine;
namespace PigeonCoopToolkit.Effects.Trails
{
    [AddComponentMenu("Pigeon Coop Toolkit/Effects/Smoke Plume")]
    public class SmokePlume : TrailRenderer_Base
    {
        public float TimeBetweenPoints = 0.1f;
        public Vector3 ConstantForce = Vector3.up * 0.5f;
        public float RandomForceScale = 0.05f;
        public int MaxNumberOfPoints = 50;
        private float _timeSincePoint;
        protected override void Start()
        {
            base.Start();
            _timeSincePoint = 0;
        }
        protected override void OnStartEmit()
        {
            _timeSincePoint = 0;
        }
        protected override void Reset()
        {
            base.Reset();
            TrailData.SizeOverLife = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.5f, 0.2f), new Keyframe(1, 0.2f));
            TrailData.Lifetime = 6f;
            ConstantForce = Vector3.up*0.5f;
            TimeBetweenPoints = 0.1f;
            RandomForceScale = 0.05f;
            MaxNumberOfPoints = 50;
        }
        protected override void Update()
        {
            if (_emit)
            {
                _timeSincePoint += _noDecay ? 0 : Time.deltaTime;
                if (_timeSincePoint >= TimeBetweenPoints)
                {
                    AddPoint(new SmokeTrailPoint(), _t.position);
                    _timeSincePoint = 0;
                }
            }
            base.Update();
        }
        protected override void InitialiseNewPoint(PCTrailPoint newPoint)
        {
            ((SmokeTrailPoint)newPoint).RandomVec = Random.onUnitSphere * RandomForceScale;
        }
        protected override void UpdateTrail(PCTrail trail, float deltaTime)
        {
            if (_noDecay)
                return;
            foreach (PCTrailPoint point in trail.Points)
            {
                point.Position += ConstantForce * deltaTime;
            }
        }
        protected override int GetMaxNumberOfPoints()
        {
            return MaxNumberOfPoints;
        }
    }
}
Plugins/Trails/SmokePlume.cs.meta
New file
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: b5748bb800508004a81afe3d7526bcb1
labels:
- BetterTrails
- TrailRenderer
- Smoke
- Trail
- Effects
- skidmarks
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 1000
  icon: {fileID: 2800000, guid: 9c8d55a9e91d98e4e925cd09f877adc5, type: 3}
  userData:
Plugins/Trails/SmokeTrail.cs
New file
@@ -0,0 +1,76 @@
using UnityEngine;
namespace PigeonCoopToolkit.Effects.Trails
{
    [AddComponentMenu("Pigeon Coop Toolkit/Effects/Smoke Trail")]
    public class SmokeTrail : TrailRenderer_Base
    {
        public float MinVertexDistance = 0.1f;
        public int MaxNumberOfPoints = 50;
        private Vector3 _lastPosition;
        private float _distanceMoved;
        public float RandomForceScale = 1;
        protected override void Start()
        {
            base.Start();
            _lastPosition = _t.position;
        }
        protected override void Update()
        {
            if (_emit)
            {
                _distanceMoved += Vector3.Distance(_t.position, _lastPosition);
                if (_distanceMoved != 0 && _distanceMoved >= MinVertexDistance)
                {
                    AddPoint(new SmokeTrailPoint(), _t.position);
                    _distanceMoved = 0;
                }
                _lastPosition = _t.position;
            }
            base.Update();
        }
        protected override void OnStartEmit()
        {
            _lastPosition = _t.position;
            _distanceMoved = 0;
        }
        protected override void Reset()
        {
            base.Reset();
            MinVertexDistance = 0.1f;
            RandomForceScale = 1;
        }
        protected override void InitialiseNewPoint(PCTrailPoint newPoint)
        {
            ((SmokeTrailPoint)newPoint).RandomVec = Random.onUnitSphere * RandomForceScale;
        }
        protected override void OnTranslate(Vector3 t)
        {
            _lastPosition += t;
        }
        protected override int GetMaxNumberOfPoints()
        {
            return MaxNumberOfPoints;
        }
    }
    public class SmokeTrailPoint : PCTrailPoint
    {
        public Vector3 RandomVec;
        public override void Update(float deltaTime)
        {
            base.Update(deltaTime);
            Position += RandomVec * deltaTime;
        }
    }
}
Plugins/Trails/SmokeTrail.cs.meta
New file
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 98335f20237e3de42a9f0b6415312e23
labels:
- BetterTrails
- TrailRenderer
- Smoke
- Trail
- Effects
- skidmarks
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 1000
  icon: {fileID: 2800000, guid: f99224b2104474d47b91284e88f8af87, type: 3}
  userData:
Plugins/Trails/SmoothTrail.cs
New file
@@ -0,0 +1,313 @@
using PigeonCoopToolkit.Utillities;
using UnityEngine;
namespace PigeonCoopToolkit.Effects.Trails
{
    [AddComponentMenu("Pigeon Coop Toolkit/Effects/Smooth Trail")]
    public class SmoothTrail : TrailRenderer_Base
    {
        public float MinControlPointDistance = 0.1f;
        public int MaxControlPoints = 15;
        public int PointsBetweenControlPoints = 4;
        private Vector3 _lastPosition;
        private float _distanceMoved;
        private CircularBuffer<ControlPoint> _controlPoints;
        private class ControlPoint
        {
            public Vector3 p;
            public Vector3 forward;
        }
        protected override void Start()
        {
            base.Start();
            _lastPosition = _t.position;
        }
        protected override void Update()
        {
            if (_emit)
            {
                _distanceMoved += Vector3.Distance(_t.position, _lastPosition);
                if (!Mathf.Approximately(_distanceMoved, 0) && _distanceMoved >= MinControlPointDistance)
                {
                    AddControlPoint(_t.position);
                    _distanceMoved = 0;
                }
                else
                {
                    _controlPoints[_controlPoints.Count - 1].p = _t.position;
                    if (TrailData.UseForwardOverride)
                    {
                        _controlPoints[_controlPoints.Count - 1].forward = TrailData.ForwardOverrideRelative
                                       ? _t.TransformDirection(TrailData.ForwardOverride.normalized)
                                       : TrailData.ForwardOverride.normalized;
                    }
                }
                _lastPosition = _t.position;
            }
            base.Update();
        }
        /*
        void OnDrawGizmos()
        {
            if (Application.isPlaying && _controlPoints != null)
            {
                for (int i = 0; i < _controlPoints.Count; i++)
                {
                    Gizmos.color = Color.red;
                    Gizmos.DrawSphere(_controlPoints[i].p, 0.01f);
                    if (i < _controlPoints.Count - 1)
                    {
                        Vector3 Handle1, Handle2;
                        float distanceBetween = Vector3.Distance(_controlPoints[i].p, _controlPoints[i + 1].p) / 2;
                        if (i == 0)
                        {
                            Handle1 = _controlPoints[i].p + (_controlPoints[i + 1].p - _controlPoints[i].p).normalized * distanceBetween;
                        }
                        else
                        {
                            Handle1 = _controlPoints[i].p + (_controlPoints[i + 1].p - _controlPoints[i - 1].p).normalized * distanceBetween;
                        }
                        int nextI = i + 1;
                        if (nextI == _controlPoints.Count - 1)
                        {
                            Handle2 = _controlPoints[nextI].p + (_controlPoints[nextI - 1].p - _controlPoints[nextI].p).normalized * distanceBetween;
                        }
                        else
                        {
                            Handle2 = _controlPoints[nextI].p + (_controlPoints[nextI - 1].p - _controlPoints[nextI + 1].p).normalized * distanceBetween;
                        }
                        Gizmos.color = Color.green;
                        Gizmos.DrawSphere(Handle1, 0.01f);
                        Gizmos.DrawLine(_controlPoints[i].p, Handle1);
                        Gizmos.color = Color.blue;
                        Gizmos.DrawSphere(Handle2, 0.01f);
                        Gizmos.DrawLine(_controlPoints[nextI].p, Handle2);
                        Vector3 current = _controlPoints[i].p;
                        for (int pointBetween = 0; pointBetween < PointsBetweenControlPoints; pointBetween++)
                        {
                            Vector3 next = GetPointAlongCurve(_controlPoints[i].p, Handle1, _controlPoints[i + 1].p, Handle2, ((pointBetween + 1) / ((float)PointsBetweenControlPoints + 1f)), 0.3f);
                            Gizmos.DrawLine(current, next);
                            Gizmos.color = Color.yellow;
                            Gizmos.DrawSphere(next, 0.01f);
                            current = next;
                        }
                        Gizmos.color = Color.blue;
                        Gizmos.DrawLine(current, _controlPoints[i + 1].p);
                    }
                }
            }
        }
        */
        protected override void OnStartEmit()
        {
            _lastPosition = _t.position;
            _distanceMoved = 0;
            _controlPoints = new CircularBuffer<ControlPoint>(MaxControlPoints);
            _controlPoints.Add(new ControlPoint { p = _lastPosition });
            if (TrailData.UseForwardOverride)
            {
                _controlPoints[0].forward = TrailData.ForwardOverrideRelative
                               ? _t.TransformDirection(TrailData.ForwardOverride.normalized)
                               : TrailData.ForwardOverride.normalized;
            }
            AddPoint(new PCTrailPoint(), _lastPosition);
            AddControlPoint(_lastPosition);
        }
        protected override void UpdateTrail(PCTrail trail, float deltaTime)
        {
            if (trail.IsActiveTrail == false)
                return;
            //TODO Must optimize this further, I don't need to keep recalculating point positions unless we are
            //dealng with the points between the last and 2nd last CP (+ the last CP itself)
            int trailPointIndex = 0;
            for (int i = 0; i < _controlPoints.Count; i++)
            {
                trail.Points[trailPointIndex].Position = _controlPoints[i].p;
                if (TrailData.UseForwardOverride)
                {
                    trail.Points[trailPointIndex].Forward = _controlPoints[i].forward;
                }
                trailPointIndex++;
                if (i < _controlPoints.Count - 1)
                {
                    Vector3 Handle1, Handle2;
                    float distanceBetween = Vector3.Distance(_controlPoints[i].p, _controlPoints[i + 1].p) / 2;
                    if (i == 0)
                    {
                        Handle1 = _controlPoints[i].p + (_controlPoints[i + 1].p - _controlPoints[i].p).normalized * distanceBetween;
                    }
                    else
                    {
                        Handle1 = _controlPoints[i].p + (_controlPoints[i + 1].p - _controlPoints[i - 1].p).normalized * distanceBetween;
                    }
                    int nextI = i + 1;
                    if (nextI == _controlPoints.Count - 1)
                    {
                        Handle2 = _controlPoints[nextI].p + (_controlPoints[nextI - 1].p - _controlPoints[nextI].p).normalized * distanceBetween;
                    }
                    else
                    {
                        Handle2 = _controlPoints[nextI].p + (_controlPoints[nextI - 1].p - _controlPoints[nextI + 1].p).normalized * distanceBetween;
                    }
                    PCTrailPoint currentHandle = trail.Points[trailPointIndex-1];
                    PCTrailPoint nextHandle = trail.Points[(trailPointIndex-1) + PointsBetweenControlPoints+1];
                    for (int pointBetween = 0; pointBetween < PointsBetweenControlPoints; pointBetween++)
                    {
                        float t= (((float)pointBetween + 1f) / ((float)PointsBetweenControlPoints + 1f));
                        trail.Points[trailPointIndex].Position = GetPointAlongCurve(_controlPoints[i].p, Handle1, _controlPoints[i + 1].p, Handle2, t, 0.3f);
                        trail.Points[trailPointIndex].SetTimeActive(Mathf.Lerp(currentHandle.TimeActive(), nextHandle.TimeActive(), t));
                        if (TrailData.UseForwardOverride)
                        {
                            trail.Points[trailPointIndex].Forward = Vector3.Lerp(currentHandle.Forward, nextHandle.Forward, t);
                        }
                        trailPointIndex++;
                    }
                }
            }
            int lastControlPointPointIndex = ((_controlPoints.Count - 1) + ((_controlPoints.Count - 1) * PointsBetweenControlPoints));
            int prevControlPointPointIndex = lastControlPointPointIndex - PointsBetweenControlPoints - 1;
            int activePointCount = lastControlPointPointIndex + 1;
            /*
             *
             * This is that optimisation mentioned above..sort of works, but smoothing isn't working right so i am leaving it out for now
             *
             *
            int lastControlPointIndex = _controlPoints.Count - 1;
            int prevControlPointIndex = _controlPoints.Count - 2;
            Vector3 Handle1, Handle2;
            float distanceBetween = Vector3.Distance(_controlPoints[lastControlPointIndex].p, _controlPoints[prevControlPointIndex].p) / 2;
            if (prevControlPointIndex == 0)
                Handle1 = _controlPoints[prevControlPointIndex].p + (_controlPoints[lastControlPointIndex].p - _controlPoints[prevControlPointIndex].p).normalized * distanceBetween;
            else
                Handle1 = _controlPoints[prevControlPointIndex].p + (_controlPoints[lastControlPointIndex].p - _controlPoints[prevControlPointIndex - 1].p).normalized * distanceBetween;
            Handle2 = _controlPoints[lastControlPointIndex].p + (_controlPoints[prevControlPointIndex].p - _controlPoints[lastControlPointIndex].p).normalized * distanceBetween;
            float timeActiveLastControlPoint = trail.Points[lastControlPointPointIndex].TimeActive();
            float timeActivePrevControlPoint = trail.Points[prevControlPointPointIndex].TimeActive();
            for (int pointBetween = 0; pointBetween < PointsBetweenControlPoints; pointBetween++)
            {
                float t= (((float)pointBetween + 1f) / ((float)PointsBetweenControlPoints + 1f));
                trail.Points[prevControlPointPointIndex + pointBetween + 1].Position = GetPointAlongCurve(_controlPoints[prevControlPointIndex].p, Handle1, _controlPoints[lastControlPointIndex].p, Handle2, t, 0.3f);
                trail.Points[prevControlPointPointIndex + pointBetween + 1].SetTimeActive(Mathf.Lerp(timeActivePrevControlPoint, timeActiveLastControlPoint, t));
            }
            trail.Points[lastControlPointPointIndex].Position = _controlPoints[lastControlPointIndex].p;
            */
            float distanceFromStart = trail.Points[prevControlPointPointIndex].GetDistanceFromStart();
            for (int i = prevControlPointPointIndex + 1; i < activePointCount; i++)
            {
                distanceFromStart += Vector3.Distance(trail.Points[i - 1].Position, trail.Points[i].Position);
                trail.Points[i].SetDistanceFromStart(distanceFromStart);
            }
        }
        protected override void Reset()
        {
            base.Reset();
            MinControlPointDistance = 0.1f;
            MaxControlPoints = 15;
            PointsBetweenControlPoints = 4;
        }
        protected override void OnTranslate(Vector3 t)
        {
            _lastPosition += t;
            for (int i = 0; i < _controlPoints.Count; i++)
                _controlPoints[i].p += t;
        }
        private void AddControlPoint(Vector3 position)
        {
            for (int i = 0; i < PointsBetweenControlPoints; i++)
            {
                AddPoint(new PCTrailPoint(), position);
            }
            AddPoint(new PCTrailPoint(), position);
            ControlPoint newCP = new ControlPoint { p = position };
            if (TrailData.UseForwardOverride)
            {
                newCP.forward = TrailData.ForwardOverrideRelative
                               ? _t.TransformDirection(TrailData.ForwardOverride.normalized)
                               : TrailData.ForwardOverride.normalized;
            }
            _controlPoints.Add(newCP);
        }
        protected override int GetMaxNumberOfPoints()
        {
            return ((MaxControlPoints) + ((MaxControlPoints) * PointsBetweenControlPoints));
        }
        public Vector3 GetPointAlongCurve(Vector3 curveStart, Vector3 curveStartHandle, Vector3 curveEnd, Vector3 curveEndHandle, float t, float crease)
        {
            float oneMinT = 1 - t;
            float oneMinTPow3 = Mathf.Pow(oneMinT, 3);
            float oneMinTPow2 = Mathf.Pow(oneMinT, 2);
            float oneMinCrease = 1 - crease;
            return ((oneMinTPow3 * curveStart * oneMinCrease) + (3 * oneMinTPow2 * t * curveStartHandle * crease) + (3 * oneMinT * Mathf.Pow(t, 2) * curveEndHandle * crease) +
                   (Mathf.Pow(t, 3) * curveEnd * oneMinCrease))
                   /
                   ((oneMinTPow3 * oneMinCrease) + (3 * oneMinTPow2 * t * crease) + (3 * oneMinT * Mathf.Pow(t, 2) * crease) +
                   (Mathf.Pow(t, 3) * oneMinCrease));
        }
    }
}
Plugins/Trails/SmoothTrail.cs.meta
New file
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 62cd7e0b3a08cf84e82658d9a3eaeb32
labels:
- BetterTrails
- TrailRenderer
- Smoke
- Trail
- Effects
- skidmarks
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 1000
  icon: {fileID: 2800000, guid: 8d56c6f37ee95884baa3b4f7e4837399, type: 3}
  userData:
Plugins/Trails/Trail.cs
New file
@@ -0,0 +1,60 @@
using UnityEngine;
namespace PigeonCoopToolkit.Effects.Trails
{
    [AddComponentMenu("Pigeon Coop Toolkit/Effects/Trail")]
    public class Trail : TrailRenderer_Base
    {
        public float MinVertexDistance = 0.1f;
        public int MaxNumberOfPoints = 50;
        private Vector3 _lastPosition;
        private float _distanceMoved;
        protected override void Start()
        {
            base.Start();
            _lastPosition = _t.position;
        }
        protected override void Update()
        {
            if(_emit)
            {
                _distanceMoved += Vector3.Distance(_t.position, _lastPosition);
                if (_distanceMoved != 0 && _distanceMoved >= MinVertexDistance)
                {
                    AddPoint(new PCTrailPoint(), _t.position);
                    _distanceMoved = 0;
                }
                _lastPosition = _t.position;
            }
            base.Update();
        }
        protected override void OnStartEmit()
        {
            _lastPosition = _t.position;
            _distanceMoved = 0;
        }
        protected override void Reset()
        {
            base.Reset();
            MinVertexDistance = 0.1f;
        }
        protected override void OnTranslate(Vector3 t)
        {
            _lastPosition += t;
        }
        protected override int GetMaxNumberOfPoints()
        {
            return MaxNumberOfPoints;
        }
    }
}
Plugins/Trails/Trail.cs.meta
New file
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 5f742ccbd25717e438dd6fdea4d66bad
labels:
- BetterTrails
- TrailRenderer
- Smoke
- Trail
- Effects
- skidmarks
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 1000
  icon: {fileID: 2800000, guid: 888165c9c85ad6b429824b89f1f4f698, type: 3}
  userData:
Plugins/Trails/TrailRenderer_Base.cs
New file
@@ -0,0 +1,666 @@
using System.Collections.Generic;
using System.Linq;
using PigeonCoopToolkit.Utillities;
using UnityEngine;
using System;
namespace PigeonCoopToolkit.Effects.Trails
{
    public abstract class TrailRenderer_Base : MonoBehaviour
    {
        public PCTrailRendererData TrailData;
        public bool Emit = false;
        protected bool _emit;
        protected bool _noDecay;
        private PCTrail _activeTrail;
        private List<PCTrail> _fadingTrails;
        protected Transform _t;
        private static Dictionary<Material, List<PCTrail>> _matToTrailList;
        private static List<Mesh> _toClean;
        private static bool _hasRenderer = false;
        private static int GlobalTrailRendererCount = 0;
        protected virtual void Awake()
        {
            GlobalTrailRendererCount++;
            if(GlobalTrailRendererCount == 1)
            {
                _matToTrailList = new Dictionary<Material, List<PCTrail>>();
                _toClean = new List<Mesh>();
            }
            _fadingTrails = new List<PCTrail>();
            _t = transform;
            _emit = Emit;
            if (_emit)
            {
                _activeTrail = new PCTrail(GetMaxNumberOfPoints());
                _activeTrail.IsActiveTrail = true;
                OnStartEmit();
            }
        }
        protected virtual void Start()
        {
        }
        protected virtual void LateUpdate()
        {
            if(_hasRenderer)
                return;
            _hasRenderer = true;
            foreach (KeyValuePair<Material, List<PCTrail>> keyValuePair in _matToTrailList)
            {
                CombineInstance[] combineInstances = new CombineInstance[keyValuePair.Value.Count];
                for (int i = 0; i < keyValuePair.Value.Count; i++)
                {
                    combineInstances[i] = new CombineInstance
                    {
                        mesh = keyValuePair.Value[i].Mesh,
                        subMeshIndex = 0,
                        transform = Matrix4x4.identity
                    };
                }
                Mesh combinedMesh = new Mesh();
                combinedMesh.CombineMeshes(combineInstances, true, false);
                _toClean.Add(combinedMesh);
                DrawMesh(combinedMesh, keyValuePair.Key);
                keyValuePair.Value.Clear();
            }
        }
        protected virtual void Update()
        {
            if (_hasRenderer)
            {
                _hasRenderer = false;
                if (_toClean.Count > 0)
                {
                    foreach (Mesh mesh in _toClean)
                    {
                        if (Application.isEditor)
                            DestroyImmediate(mesh, true);
                        else
                            Destroy(mesh);
                    }
                }
                _toClean.Clear();
            }
            if (_matToTrailList.ContainsKey(TrailData.TrailMaterial) == false)
            {
                _matToTrailList.Add(TrailData.TrailMaterial, new List<PCTrail>());
            }
            if(_activeTrail != null)
            {
                UpdatePoints(_activeTrail, Time.deltaTime);
                UpdateTrail(_activeTrail, Time.deltaTime);
                GenerateMesh(_activeTrail);
                _matToTrailList[TrailData.TrailMaterial].Add(_activeTrail);
            }
            for (int i = _fadingTrails.Count-1; i >= 0; i--)
            {
                if (_fadingTrails[i] == null || _fadingTrails[i].Points.Any(a => a.TimeActive() < TrailData.Lifetime) == false)
                {
                    if (_fadingTrails[i] != null)
                        _fadingTrails[i].Dispose();
                    _fadingTrails.RemoveAt(i);
                    continue;
                }
                UpdatePoints(_fadingTrails[i], Time.deltaTime);
                UpdateTrail(_fadingTrails[i], Time.deltaTime);
                GenerateMesh(_fadingTrails[i]);
                _matToTrailList[TrailData.TrailMaterial].Add(_fadingTrails[i]);
            }
            CheckEmitChange();
        }
        protected virtual void OnDestroy()
        {
            GlobalTrailRendererCount--;
            if(GlobalTrailRendererCount == 0)
            {
                if(_toClean != null && _toClean.Count > 0)
                {
                    foreach (Mesh mesh in _toClean)
                    {
                        if (Application.isEditor)
                            DestroyImmediate(mesh, true);
                        else
                            Destroy(mesh);
                    }
                }
                _toClean = null;
                _matToTrailList.Clear();
                _matToTrailList = null;
            }
            if (_activeTrail != null)
            {
                _activeTrail.Dispose();
                _activeTrail = null;
            }
            if (_fadingTrails != null)
            {
                foreach (PCTrail fadingTrail in _fadingTrails)
                {
                    if (fadingTrail != null)
                        fadingTrail.Dispose();
                }
                _fadingTrails.Clear();
            }
        }
        protected virtual void OnStopEmit()
        {
        }
        protected virtual void OnStartEmit()
        {
        }
        protected virtual void OnTranslate(Vector3 t)
        {
        }
        protected abstract int GetMaxNumberOfPoints();
        protected virtual void Reset()
        {
            if(TrailData == null)
                TrailData = new PCTrailRendererData();
            TrailData.Lifetime = 1;
            TrailData.UsingSimpleColor = false;
            TrailData.UsingSimpleSize = false;
            TrailData.ColorOverLife = new Gradient();
            TrailData.SimpleColorOverLifeStart = Color.white;
            TrailData.SimpleColorOverLifeEnd = new Color(1, 1, 1, 0);
            TrailData.SizeOverLife = new AnimationCurve(new Keyframe(0, 1), new Keyframe(1, 0));
            TrailData.SimpleSizeOverLifeStart = 1;
            TrailData.SimpleSizeOverLifeEnd = 0;
        }
        protected virtual void InitialiseNewPoint(PCTrailPoint newPoint)
        {
        }
        protected virtual void UpdateTrail(PCTrail trail, float deltaTime)
        {
        }
        protected void AddPoint(PCTrailPoint newPoint, Vector3 pos)
        {
            if (_activeTrail == null)
                return;
            newPoint.Position = pos;
            newPoint.PointNumber = _activeTrail.Points.Count == 0 ? 0 : _activeTrail.Points[_activeTrail.Points.Count - 1].PointNumber + 1;
            InitialiseNewPoint(newPoint);
            newPoint.SetDistanceFromStart(_activeTrail.Points.Count == 0
                                              ? 0
                                              : _activeTrail.Points[_activeTrail.Points.Count - 1].GetDistanceFromStart() + Vector3.Distance(_activeTrail.Points[_activeTrail.Points.Count - 1].Position, pos));
            if(TrailData.UseForwardOverride)
            {
                newPoint.Forward = TrailData.ForwardOverrideRelative
                                       ? _t.TransformDirection(TrailData.ForwardOverride.normalized)
                                       : TrailData.ForwardOverride.normalized;
            }
            _activeTrail.Points.Add(newPoint);
        }
        private void GenerateMesh(PCTrail trail)
        {
            trail.Mesh.Clear(false);
            Vector3 camForward = Camera.main != null ? Camera.main.transform.forward : Vector3.forward;
            if(TrailData.UseForwardOverride)
            {
                camForward = TrailData.ForwardOverride.normalized;
            }
            trail.activePointCount = NumberOfActivePoints(trail);
            if (trail.activePointCount < 2)
                return;
            int vertIndex = 0;
            for (int i = 0; i < trail.Points.Count; i++)
            {
                PCTrailPoint p = trail.Points[i];
                float timeAlong = p.TimeActive()/TrailData.Lifetime;
                if(p.TimeActive() > TrailData.Lifetime)
                {
                    continue;
                }
                if (TrailData.UseForwardOverride && TrailData.ForwardOverrideRelative)
                    camForward = p.Forward;
                Vector3 cross = Vector3.zero;
                if (i < trail.Points.Count - 1)
                {
                    cross =
                        Vector3.Cross((trail.Points[i + 1].Position - p.Position).normalized, camForward).
                            normalized;
                }
                else
                {
                    cross =
                        Vector3.Cross((p.Position - trail.Points[i - 1].Position).normalized, camForward).
                            normalized;
                }
                //yuck! lets move these into their own functions some time
                Color c = TrailData.StretchColorToFit ?
                    (TrailData.UsingSimpleColor ? Color.Lerp(TrailData.SimpleColorOverLifeStart, TrailData.SimpleColorOverLifeEnd, 1 - ((float)vertIndex / (float)trail.activePointCount / 2f)) : TrailData.ColorOverLife.Evaluate(1 - ((float)vertIndex / (float)trail.activePointCount / 2f))) :
                    (TrailData.UsingSimpleColor ? Color.Lerp(TrailData.SimpleColorOverLifeStart,TrailData.SimpleColorOverLifeEnd,timeAlong) : TrailData.ColorOverLife.Evaluate(timeAlong));
                float s = TrailData.StretchSizeToFit ?
                    (TrailData.UsingSimpleSize ? Mathf.Lerp(TrailData.SimpleSizeOverLifeStart,TrailData.SimpleSizeOverLifeEnd,1 - ((float)vertIndex / (float)trail.activePointCount / 2f)) : TrailData.SizeOverLife.Evaluate(1 - ((float)vertIndex / (float)trail.activePointCount / 2f))) :
                    (TrailData.UsingSimpleSize ? Mathf.Lerp(TrailData.SimpleSizeOverLifeStart,TrailData.SimpleSizeOverLifeEnd, timeAlong) : TrailData.SizeOverLife.Evaluate(timeAlong));
                trail.verticies[vertIndex] = p.Position + cross * s;
                if(TrailData.MaterialTileLength <= 0)
                {
                    trail.uvs[vertIndex] = new Vector2((float)vertIndex / (float)trail.activePointCount / 2f, 0);
                }
                else
                {
                    trail.uvs[vertIndex] = new Vector2(p.GetDistanceFromStart() / TrailData.MaterialTileLength, 0);
                }
                trail.normals[vertIndex] = camForward;
                trail.colors[vertIndex] = c;
                vertIndex++;
                trail.verticies[vertIndex] = p.Position - cross * s;
                if (TrailData.MaterialTileLength <= 0)
                {
                    trail.uvs[vertIndex] = new Vector2((float)vertIndex / (float)trail.activePointCount / 2f, 1);
                }
                else
                {
                    trail.uvs[vertIndex] = new Vector2(p.GetDistanceFromStart() / TrailData.MaterialTileLength, 1);
                }
                trail.normals[vertIndex] = camForward;
                trail.colors[vertIndex] = c;
                vertIndex++;
            }
            Vector2 finalPosition = trail.verticies[vertIndex-1];
            for(int i = vertIndex; i < trail.verticies.Length; i++)
            {
                trail.verticies[i] = finalPosition;
            }
            int indIndex = 0;
            for (int pointIndex = 0; pointIndex < 2 * (trail.activePointCount - 1); pointIndex++)
            {
                if(pointIndex%2==0)
                {
                    trail.indicies[indIndex] = pointIndex;
                    indIndex++;
                    trail.indicies[indIndex] = pointIndex + 1;
                    indIndex++;
                    trail.indicies[indIndex] = pointIndex + 2;
                }
                else
                {
                    trail.indicies[indIndex] = pointIndex + 2;
                    indIndex++;
                    trail.indicies[indIndex] = pointIndex + 1;
                    indIndex++;
                    trail.indicies[indIndex] = pointIndex;
                }
                indIndex++;
            }
            int finalIndex = trail.indicies[indIndex-1];
            for (int i = indIndex; i < trail.indicies.Length; i++)
            {
                trail.indicies[i] = finalIndex;
            }
            trail.Mesh.vertices = trail.verticies;
            trail.Mesh.SetIndices(trail.indicies, MeshTopology.Triangles, 0);
            trail.Mesh.uv = trail.uvs;
            trail.Mesh.normals = trail.normals;
            trail.Mesh.colors = trail.colors;
        }
        private void DrawMesh(Mesh trailMesh, Material trailMaterial)
        {
            Graphics.DrawMesh(trailMesh, Matrix4x4.identity, trailMaterial, gameObject.layer);
        }
        private void UpdatePoints(PCTrail line, float deltaTime)
        {
            for (int i = 0; i < line.Points.Count; i++)
            {
                line.Points[i].Update(_noDecay ? 0 : deltaTime);
            }
        }
        [Obsolete("UpdatePoint is deprecated, you should instead override UpdateTrail and loop through the individual points yourself (See Smoke or Smoke Plume scripts for how to do this).", true)]
        protected virtual void UpdatePoint(PCTrailPoint pCTrailPoint, float deltaTime)
        {
        }
        private void CheckEmitChange()
        {
            if (_emit != Emit)
            {
                _emit = Emit;
                if (_emit)
                {
                    _activeTrail = new PCTrail(GetMaxNumberOfPoints());
                    _activeTrail.IsActiveTrail = true;
                    OnStartEmit();
                }
                else
                {
                    OnStopEmit();
                    _activeTrail.IsActiveTrail = false;
                    _fadingTrails.Add(_activeTrail);
                    _activeTrail = null;
                }
            }
        }
        private int NumberOfActivePoints(PCTrail line)
        {
            int count = 0;
            for (int index = 0; index < line.Points.Count; index++)
            {
                if (line.Points[index].TimeActive() < TrailData.Lifetime) count++;
            }
            return count;
        }
        [UnityEngine.ContextMenu("Toggle inspector size input method")]
        protected void ToggleSizeInputStyle()
        {
            TrailData.UsingSimpleSize = !TrailData.UsingSimpleSize;
        }
        [UnityEngine.ContextMenu("Toggle inspector color input method")]
        protected void ToggleColorInputStyle()
        {
            TrailData.UsingSimpleColor = !TrailData.UsingSimpleColor;
        }
        public void LifeDecayEnabled(bool enabled)
        {
            _noDecay = !enabled;
        }
        /// <summary>
        /// Translates every point in the vector t
        /// </summary>
        public void Translate(Vector3 t)
        {
            if (_activeTrail != null)
            {
                for (int i = 0; i < _activeTrail.Points.Count; i++)
                {
                    _activeTrail.Points[i].Position += t;
                }
            }
            if (_fadingTrails != null)
            {
                foreach (PCTrail fadingTrail in _fadingTrails)
                {
                    for (int i = 0; i < fadingTrail.Points.Count; i++)
                    {
                        fadingTrail.Points[i].Position += t;
                    }
                }
            }
            OnTranslate(t);
        }
        /// <summary>
        /// Insert a trail into this trail renderer.
        /// </summary>
        /// <param name="from">The start position of the trail.</param>
        /// <param name="to">The end position of the trail.</param>
        /// <param name="distanceBetweenPoints">Distance between each point on the trail</param>
        public void CreateTrail(Vector3 from, Vector3 to, float distanceBetweenPoints)
        {
            float distanceBetween = Vector3.Distance(from, to);
            Vector3 dirVector = to - from;
            dirVector = dirVector.normalized;
            float currentLength = 0;
            CircularBuffer<PCTrailPoint> newLine = new CircularBuffer<PCTrailPoint>(GetMaxNumberOfPoints());
            int pointNumber = 0;
            while (currentLength < distanceBetween)
            {
                PCTrailPoint newPoint = new PCTrailPoint();
                newPoint.PointNumber = pointNumber;
                newPoint.Position = from + dirVector*currentLength;
                newLine.Add(newPoint);
                InitialiseNewPoint(newPoint);
                pointNumber++;
                if (distanceBetweenPoints <= 0)
                    break;
                else
                    currentLength += distanceBetweenPoints;
            }
            PCTrailPoint lastPoint = new PCTrailPoint();
            lastPoint.PointNumber = pointNumber;
            lastPoint.Position = to;
            newLine.Add(lastPoint);
            InitialiseNewPoint(lastPoint);
            PCTrail newTrail = new PCTrail(GetMaxNumberOfPoints());
            newTrail.Points = newLine;
            _fadingTrails.Add(newTrail);
        }
        /// <summary>
        /// Clears all active trails from the system.
        /// </summary>
        /// <param name="emitState">Desired emit state after clearing</param>
        public void ClearSystem(bool emitState)
        {
            if(_activeTrail != null)
            {
                _activeTrail.Dispose();
                _activeTrail = null;
            }
            if (_fadingTrails != null)
            {
                foreach (PCTrail fadingTrail in _fadingTrails)
                {
                    if (fadingTrail != null)
                        fadingTrail.Dispose();
                }
                _fadingTrails.Clear();
            }
            Emit = emitState;
            _emit = !emitState;
            CheckEmitChange();
        }
        /// <summary>
        /// Get the number of active seperate trail segments.
        /// </summary>
        public int NumSegments()
        {
            int num = 0;
            if (_activeTrail != null && NumberOfActivePoints(_activeTrail) != 0)
                num++;
            num += _fadingTrails.Count;
            return num;
        }
    }
    public class PCTrail : System.IDisposable
    {
        public CircularBuffer<PCTrailPoint> Points;
        public Mesh Mesh;
        public Vector3[] verticies;
        public Vector3[] normals;
        public Vector2[] uvs;
        public Color[] colors;
        public int[] indicies;
        public int activePointCount;
        public bool IsActiveTrail = false;
        public PCTrail(int numPoints)
        {
            Mesh = new Mesh();
            Mesh.MarkDynamic();
            verticies = new Vector3[2 * numPoints];
            normals = new Vector3[2 * numPoints];
            uvs = new Vector2[2 * numPoints];
            colors = new Color[2 * numPoints];
            indicies = new int[2 * (numPoints) * 3];
            Points = new CircularBuffer<PCTrailPoint>(numPoints);
        }
        #region Implementation of IDisposable
        public void Dispose()
        {
            if(Mesh != null)
            {
                if(Application.isEditor)
                    UnityEngine.Object.DestroyImmediate(Mesh, true);
                else
                    UnityEngine.Object.Destroy(Mesh);
            }
            Points.Clear();
            Points = null;
        }
        #endregion
    }
    public class PCTrailPoint
    {
        public Vector3 Forward;
        public Vector3 Position;
        public int PointNumber;
        private float _timeActive = 0;
        private float _distance;
        public virtual void Update(float deltaTime)
        {
            _timeActive += deltaTime;
        }
        public float TimeActive()
        {
            return _timeActive;
        }
        public void SetTimeActive(float time)
        {
            _timeActive = time;
        }
        public void SetDistanceFromStart(float distance)
        {
            _distance = distance;
        }
        public float GetDistanceFromStart()
        {
            return _distance;
        }
    }
    [System.Serializable]
    public class PCTrailRendererData
    {
        public Material TrailMaterial;
        public float Lifetime = 1;
        public bool UsingSimpleSize = false;
        public float SimpleSizeOverLifeStart;
        public float SimpleSizeOverLifeEnd;
        public AnimationCurve SizeOverLife = new AnimationCurve();
        public bool UsingSimpleColor = false;
        public Color SimpleColorOverLifeStart;
        public Color SimpleColorOverLifeEnd;
        public Gradient ColorOverLife;
        public bool StretchSizeToFit;
        public bool StretchColorToFit;
        public float MaterialTileLength = 0;
        public bool UseForwardOverride;
        public Vector3 ForwardOverride;
        public bool ForwardOverrideRelative;
    }
}
Plugins/Trails/TrailRenderer_Base.cs.meta
New file
@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 87716fa8801130a4994e129a3b6b2fa6
labels:
- BetterTrails
- TrailRenderer
- Smoke
- Trail
- Effects
- skidmarks
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 1000
  icon: {instanceID: 0}
  userData:
Plugins/Trails/VersionInformation.cs
New file
@@ -0,0 +1,42 @@
namespace PigeonCoopToolkit.Generic
{
    [System.Serializable]
    public class VersionInformation
    {
        public string Name;
        public int Major = 1;
        public int Minor = 0;
        public int Patch = 0;
        public VersionInformation(string name, int major, int minor, int patch)
        {
            Name = name;
            Major = major;
            Minor = minor;
            Patch = patch;
        }
        public override string ToString()
        {
            return string.Format("{0} {1}.{2}.{3}", Name, Major, Minor, Patch);
        }
        public bool Match(VersionInformation other, bool looseMatch)
        {
            if(looseMatch)
            {
                return other.Name == Name &&
                       other.Major == Major &&
                       other.Minor == Minor;
            }
            else
            {
                return other.Name == Name &&
                       other.Major == Major &&
                       other.Minor == Minor &&
                       other.Patch == Patch;
            }
        }
    }
}
Plugins/Trails/VersionInformation.cs.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1d58a7e753bea0e4c84779d092563363
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
System/Dogz/DogzActiveWin.cs
@@ -16,7 +16,7 @@
        [SerializeField] ScrollerController m_Controller;
        [SerializeField] List<DogzSkillData> m_DogzSkills;
        [SerializeField] List<DogzEquip> m_DogzEquips;
        [SerializeField] List<Button> m_DogzUnEquipBtns;
        [SerializeField] List<DogzUnEquip> m_DogzUnEquipBtns;
        [SerializeField] List<Text> m_PropertyTypes;
        [SerializeField] List<Text> m_PropertyValues;
        [SerializeField] Image m_DogzHeadIcon;
@@ -25,6 +25,7 @@
        [SerializeField] Button m_TakeOffEquipBtn;
        [SerializeField] Button m_EquipPackBtn;
        [SerializeField] Button m_CallBackBtn;
        [SerializeField] RedpointBehaviour assistBtnRedBehav;
        [SerializeField] Text m_CallBackBtnTxt;
        DogzModel m_Model;
        DogzModel model
@@ -51,7 +52,7 @@
            for (int i = 0; i < m_DogzUnEquipBtns.Count; i++)
            {
                var _index = i;
                m_DogzUnEquipBtns[i].onClick.AddListener(() =>
                m_DogzUnEquipBtns[i].DogzUnEquipBtn.AddListener(() =>
                {
                    OpenDogzEquip(_index);
                });
@@ -106,6 +107,7 @@
            UpdateDogzEquip();
            UpdateDogzProperty();
            UpdateDogzBtn();
            assistBtnRedBehav.redpointId = model.GetDogzAssistRedpointById(model.presentSelectDogz).id;
        }
        private void UpdateDogzSkill()
        {
@@ -144,9 +146,12 @@
        private void RefreshDogzEquipEvent(int dogzId)
        {
            if (dogzId != model.presentSelectDogz) return;
            m_Controller.m_Scorller.RefreshActiveCellViews();
            UpdateDogzEquip();
            UpdateDogzProperty();
            UpdateDogzBtn();
        }
        private void UpdateDogzEquip()
@@ -158,7 +163,8 @@
            {
                ItemModel _data;
                bool _equiped = model.TryGetDogzEquip(model.presentSelectDogz, i+101, out _data);
                m_DogzUnEquipBtns[i].gameObject.SetActive(!_equiped);
                m_DogzUnEquipBtns[i].DogzUnEquipBtn.gameObject.SetActive(!_equiped);
                m_DogzUnEquipBtns[i].RedpointBeh.redpointId = model.GetDogzEquipPlaceRedpointById(model.presentSelectDogz,i).id;
                m_DogzEquips[i].gameObject.SetActive(_equiped);
                if (_equiped)
                {
@@ -302,6 +308,15 @@
            [SerializeField] Button m_SkillBtn;
            public Button SkillBtn { get { return m_SkillBtn; } }
        }
        [Serializable]
        public class DogzUnEquip
        {
            [SerializeField] Button m_DogzUnEquipBtn;
            public Button DogzUnEquipBtn { get { return m_DogzUnEquipBtn; } }
            [SerializeField] RedpointBehaviour m_RedpointBeh;
            public RedpointBehaviour RedpointBeh { get { return m_RedpointBeh; } }
        }
    }
}
System/Dogz/DogzCell.cs
@@ -14,6 +14,7 @@
        [SerializeField] Text m_DogzName;
        [SerializeField] Text m_DogzGrade;
        [SerializeField] Button m_DogzBtn;
        [SerializeField] RedpointBehaviour redpointBehav;
        DogzModel m_Model;
        DogzModel model
@@ -34,6 +35,7 @@
            bool isActive = (_dogzEquips == null || _dogzEquips.Count < 5) ? false : true;
            m_DogzName.text = _dogzCfg.Name;
            m_DogzGrade.text = StringUtility.Contact("评分:", 100);
            redpointBehav.redpointId = model.GetSingleDogzRedpointById(_dogzCfg.ID).id;
            if (isActive)
            {
                m_DogzIcon.material = MaterialUtility.GetUIDefaultGraphicMaterial();
System/Dogz/DogzModel.cs
@@ -14,6 +14,7 @@
        public override void Init()
        {
            ParseConfig();
            SetDogzAndEquipPlaceRedKey();
        }
        public void OnBeforePlayerDataInitialize()
@@ -37,6 +38,9 @@
            SetDogzEquipInfo();
            playerPack.RefreshItemCountAct -= RefreshDogzEquipInfo;
            playerPack.RefreshItemCountAct += RefreshDogzEquipInfo;
            UpdateDogzAssistRed();
            UpdateDogzEquipPlaceRed();
            UpdateAssistNumRed();
        }
        public override void UnInit()
@@ -164,6 +168,16 @@
            }
        }
        public bool CheckIsAddAssistNum()
        {
            var _itemConfig = Config.Instance.Get<ItemConfig>(AddAssistItem);
            if(GetAssistItemCnt() <= playerPack.GetItemCountByID(PackType.rptItem, AddAssistItem))
            {
                return true;
            }
            return false;
        }
        #region 协议
        public int addAssistCnt { get; private set; } //额外购买的助战数
@@ -175,6 +189,8 @@
            {
                UpdateAssistDogzEvent();
            }
            UpdateDogzAssistRed();
            UpdateDogzEquipPlaceRed();
        }
        public event Action UpdateAssistDogzEvent;
@@ -194,6 +210,9 @@
            {
                UpdateAssistDogzEvent();
            }
            UpdateDogzAssistRed();
            UpdateDogzEquipPlaceRed();
        }
        public int GetAssistDogzCount()
@@ -218,7 +237,7 @@
        public void SetDogzEquipInfo()
        {
            m_DogzEquipDict = new Dictionary<int, List<ItemModel>>();
            m_DogzEquipDict.Clear();
            SinglePackModel singlePack = playerPack.GetSinglePackModel(PackType.rptDogzEquip);
            if (singlePack == null) return;
@@ -244,63 +263,75 @@
        public Action<int> RefreshDogzEquipAct;
        private void RefreshDogzEquipInfo(PackType type, int index, int id)
        {
            if (type != PackType.rptDogzEquip) return;
            ItemModel itemModel = playerPack.GetItemModelByIndex(type, index);
            int dogzId = GetDogzIDByIndex(index);
            List<ItemModel> modellist = GetDogzEquips(dogzId);
            if(modellist != null)
            if(type == PackType.rptItem && id == AddAssistItem)
            {
                if (itemModel != null)
                UpdateAssistNumRed();
            }
            else if(type == PackType.rptDogzItem)
            {
                UpdateDogzAssistRed();
                UpdateDogzEquipPlaceRed();
            }
            else if(type == PackType.rptDogzEquip)
            {
                ItemModel itemModel = playerPack.GetItemModelByIndex(type, index);
                int dogzId = GetDogzIDByIndex(index);
                List<ItemModel> modellist = GetDogzEquips(dogzId);
                if (modellist != null)
                {
                    bool isAdd = true;
                    for (int i = 0; i < modellist.Count; i++)
                    if (itemModel != null)
                    {
                        if (modellist[i].itemInfo.ItemPlace == index)
                        bool isAdd = true;
                        for (int i = 0; i < modellist.Count; i++)
                        {
                            isAdd = false;
                            modellist[i] = itemModel;
                            break;
                            if (modellist[i].itemInfo.ItemPlace == index)
                            {
                                isAdd = false;
                                modellist[i] = itemModel;
                                break;
                            }
                        }
                        if (isAdd)
                        {
                            modellist.Add(itemModel);
                        }
                    }
                    if(isAdd)
                    else
                    {
                       modellist.Add(itemModel);
                        for (int i = 0; i < modellist.Count; i++)
                        {
                            if (modellist[i].itemInfo.ItemPlace == index)
                            {
                                modellist.RemoveAt(i);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < modellist.Count; i++)
                    if (itemModel != null)
                    {
                        if (modellist[i].itemInfo.ItemPlace == index)
                        {
                            modellist.RemoveAt(i);
                            break;
                        }
                        List<ItemModel> equipDatas = new List<ItemModel>();
                        equipDatas.Add(itemModel);
                        m_DogzEquipDict.Add(dogzId, equipDatas);
                    }
                }
            }
            else
            {
                if(itemModel != null)
                {
                    List<ItemModel> equipDatas = new List<ItemModel>();
                    equipDatas.Add(itemModel);
                    m_DogzEquipDict.Add(dogzId,equipDatas);
                }
            }
            if(RefreshDogzEquipAct != null)
            {
                RefreshDogzEquipAct(dogzId);
                if (RefreshDogzEquipAct != null)
                {
                    RefreshDogzEquipAct(dogzId);
                }
                UpdateDogzAssistRed();
                UpdateDogzEquipPlaceRed();
            }
        }
        /// <summary>
        /// 获得神兽穿戴的装备数据
        /// </summary>
        public Dictionary<int, List<ItemModel>> m_DogzEquipDict { get; private set; }
        private Dictionary<int, List<ItemModel>> m_DogzEquipDict = new Dictionary<int, List<ItemModel>>();
        public List<ItemModel> GetDogzEquips(int _dogzId)
        {
@@ -547,27 +578,6 @@
        }
        #endregion
        #region 装备详细信息
        public DogzEquipData viewDetailData { get; private set; }
        public bool viewDetailCompare { get; private set; }
        public void ViewDetail(int _itemId, bool compare = false)
        {
            //viewDetailData = new DogzEquipData(_itemId);
            //viewDetailCompare = compare;
            //if (!WindowCenter.Instance.CheckOpen<DogzDetailsWin>())
            //{
            //    WindowCenter.Instance.Open<DogzDetailsWin>();
            //}
        }
        public int DogzEquipScore(DogzEquipData data)
        {
            return 0;
        }
        #endregion
        #region 默认选择逻辑处理
        public void SetDefaultSelectDogz()
        {
@@ -585,6 +595,263 @@
            }
        }
        #endregion
        #region 红点逻辑处理
        public const int MAINDOGZ_REDKEY = 112;
        public const int DOGZFUNC_REDKEY = 11201;
        public const int ADDASSISTDOGZ_REDKEY = 1120100002;
        public Redpoint mainDogzRedpoint = new Redpoint(MainRedDot.RedPoint_key, MAINDOGZ_REDKEY);
        public Redpoint dogzFuncRedpoint = new Redpoint(MAINDOGZ_REDKEY,DOGZFUNC_REDKEY);
        public Redpoint addAssistDogzRedpoint = new Redpoint(DOGZFUNC_REDKEY,ADDASSISTDOGZ_REDKEY);
        private Dictionary<int, Redpoint> singleDogzRedDict = new Dictionary<int, Redpoint>();
        private Dictionary<int, Redpoint> dogzAssistRedDict = new Dictionary<int, Redpoint>();
        private Dictionary<int, Dictionary<int, Redpoint>> dogzEquipPlaceRedDict = new Dictionary<int, Dictionary<int, Redpoint>>();
        public void SetDogzAndEquipPlaceRedKey()
        {
            singleDogzRedDict.Clear();
            dogzEquipPlaceRedDict.Clear();
            dogzAssistRedDict.Clear();
            int i = 0;
            foreach(var dogzId in m_DogzEquipLimit.Keys)
            {
                i += 1;
                int dogzRedKey = DOGZFUNC_REDKEY * 100 + i;
                Redpoint dogzRedPoint = new Redpoint(DOGZFUNC_REDKEY,dogzRedKey);
                singleDogzRedDict.Add(dogzId, dogzRedPoint);
                int dogzAssistRedKey = dogzRedKey * 100 + i;
                Redpoint dogzAssistRedPoint = new Redpoint(dogzRedKey, dogzAssistRedKey);
                dogzAssistRedDict.Add(dogzId,dogzAssistRedPoint);
                Dictionary<int, Redpoint> equipPlaceRedDict = new Dictionary<int, Redpoint>();
                dogzEquipPlaceRedDict.Add(dogzId,equipPlaceRedDict);
                int equipPlaceNum = m_DogzEquipLimit[dogzId].Count;
                for (int j = 0; j < equipPlaceNum; j++)
                {
                    int equipPlaceRedKey = dogzRedKey * 10 + j;
                    Redpoint equipPlaceRedpoint = new Redpoint(dogzRedKey,equipPlaceRedKey);
                    equipPlaceRedDict.Add(j, equipPlaceRedpoint);
                }
            }
        }
        public Redpoint GetSingleDogzRedpointById(int dogzId)
        {
            Redpoint redpoint = null;
            singleDogzRedDict.TryGetValue(dogzId, out redpoint);
            return redpoint;
        }
        public Redpoint GetDogzAssistRedpointById(int dogzId)
        {
            Redpoint redpoint = null;
            dogzAssistRedDict.TryGetValue(dogzId,out redpoint);
            return redpoint;
        }
        public Redpoint GetDogzEquipPlaceRedpointById(int dogzId,int index)
        {
            Redpoint redpoint = null;
            if(dogzEquipPlaceRedDict.ContainsKey(dogzId))
            {
                dogzEquipPlaceRedDict[dogzId].TryGetValue(index, out redpoint);
            }
            return redpoint;
        }
        public void UpdateDogzAssistRed()
        {
            foreach(var value in dogzAssistRedDict.Values)
            {
                value.state = RedPointState.None;
            }
            bool isMaxAssistNum = GetAssistDogzCount() >= DogzAssistDefaultCnt ? true : false;
            if(!isMaxAssistNum)
            {
                int maxDogzId = 0;
                foreach(var dogzId in m_DogzEquipLimit.Keys)
                {
                    var equips = GetDogzEquips(dogzId);
                    int equipNum = equips == null ? 0 : equips.Count;
                    if(equipNum >= 5 && maxDogzId < dogzId
                        && !TryGetAssistDogzState(dogzId))
                    {
                        maxDogzId = dogzId;
                    }
                }
                if(maxDogzId > 0)
                {
                    Redpoint assistRedpoint = GetDogzAssistRedpointById(maxDogzId);
                    if(assistRedpoint.state == RedPointState.None)
                    {
                        assistRedpoint.state = RedPointState.Simple;
                    }
                }
            }
            else
            {
                foreach (var dogzId in m_DogzEquipLimit.Keys)
                {
                    var equips = GetDogzEquips(dogzId);
                    int equipNum = equips == null ? 0 : equips.Count;
                    if(!TryGetAssistDogzState(dogzId) && equipNum == 5)
                    {
                        Redpoint assistRedpoint = GetDogzAssistRedpointById(dogzId);
                        if (assistRedpoint.state == RedPointState.None)
                        {
                            assistRedpoint.state = RedPointState.Simple;
                        }
                        break;
                    }
                }
            }
        }
        public void UpdateDogzEquipPlaceRed()
        {
            foreach(var value in dogzEquipPlaceRedDict.Values)
            {
                foreach(var value2 in value.Values)
                {
                    value2.state = RedPointState.None;
                }
            }
            foreach(var value in dogzAssistRedDict.Values)
            {
                if(value.state == RedPointState.Simple)
                {
                    return;
                }
            }
            bool isMaxAssistNum = GetAssistDogzCount() >= DogzAssistDefaultCnt ? true : false;
            if (!isMaxAssistNum)
            {
                int maxEquipNum = 0;
                int spaceDogzId = 0;
                foreach (var dogzId in m_DogzEquipLimit.Keys)
                {
                    var equips = GetDogzEquips(dogzId);
                    int equipNum = equips == null ? 0 : equips.Count;
                    if (equipNum < 5)
                    {
                        if (spaceDogzId == 0)
                        {
                            if (maxEquipNum <= equipNum)
                            {
                                maxEquipNum = equipNum;
                                spaceDogzId = dogzId;
                            }
                        }
                        else
                        {
                            if (maxEquipNum < equipNum)
                            {
                                maxEquipNum = equipNum;
                                spaceDogzId = dogzId;
                            }
                        }
                    }
                }
                if(spaceDogzId != 0)
                {
                    for(int i = 0; i < 5; i++)
                    {
                        ItemModel _data;
                        bool _equiped = TryGetDogzEquip(spaceDogzId, i + 101, out _data);
                        if(!_equiped)
                        {
                            GetDogzItemListByIndex(i);
                            if (selectEquipPlacelist.Count > 0)
                            {
                                Redpoint equipPlaceRedpoint = GetDogzEquipPlaceRedpointById(spaceDogzId,i);
                                if(equipPlaceRedpoint.state == RedPointState.None)
                                {
                                    equipPlaceRedpoint.state = RedPointState.Simple;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                int minAlreadyAssistId = 0;
                foreach (var dogzId in m_DogzEquipLimit.Keys)
                {
                    if(TryGetAssistDogzState(dogzId)
                        && minAlreadyAssistId != 0
                        && minAlreadyAssistId < dogzId)
                    {
                        minAlreadyAssistId = dogzId;
                    }
                }
                foreach (var dogzId in m_DogzEquipLimit.Keys)
                {
                    var equips = GetDogzEquips(dogzId);
                    int equipNum = equips == null ? 0 : equips.Count;
                    bool isBetterDogz = true;
                    if(!TryGetAssistDogzState(dogzId) && dogzId > minAlreadyAssistId && equipNum < 5)
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            ItemModel _data;
                            bool _equiped = TryGetDogzEquip(dogzId, i + 101, out _data);
                            if (!_equiped)
                            {
                                GetDogzItemListByIndex(i);
                                if (selectEquipPlacelist.Count < 1)
                                {
                                    isBetterDogz = false;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        isBetterDogz = false;
                    }
                    if(isBetterDogz)
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            ItemModel _data;
                            bool _equiped = TryGetDogzEquip(dogzId, i + 101, out _data);
                            if (!_equiped)
                            {
                                Redpoint equipPlaceRedpoint = GetDogzEquipPlaceRedpointById(dogzId, i);
                                if (equipPlaceRedpoint.state == RedPointState.None)
                                {
                                    equipPlaceRedpoint.state = RedPointState.Simple;
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }
            }
        }
        public void UpdateAssistNumRed()
        {
          if(CheckIsAddAssistNum())
           {
                if(addAssistDogzRedpoint.state == RedPointState.None)
                {
                    addAssistDogzRedpoint.state = RedPointState.Simple;
                }
            }
          else
            {
                addAssistDogzRedpoint.state = RedPointState.None;
            }
        }
        #endregion
    }
}
System/Dogz/DogzPackWin.cs
@@ -16,7 +16,7 @@
    public class DogzPackWin : Window
    {
        [SerializeField] List<DogzEquip> m_DogzEquips;
        [SerializeField] List<Button> m_DogzUnEquipBtns;
        [SerializeField] List<DogzUnEquip> m_DogzUnEquipBtns;
        [SerializeField] List<Text> m_DogzUnEquipContents;
        [SerializeField] Image m_DogzHeadIcon;
        [SerializeField] Button m_CloseBtn;
@@ -106,7 +106,8 @@
                ItemModel _data;
                int index = i;
                bool _equiped = dogzModel.TryGetDogzEquip(dogzModel.presentSelectDogz, i+101, out _data);
                m_DogzUnEquipBtns[i].gameObject.SetActive(!_equiped);
                m_DogzUnEquipBtns[i].DogzUnEquipBtn.gameObject.SetActive(!_equiped);
                m_DogzUnEquipBtns[i].RedpointBeh.redpointId = dogzModel.GetDogzEquipPlaceRedpointById(dogzModel.presentSelectDogz,i).id;
                m_DogzEquips[i].gameObject.SetActive(_equiped);
                if (_equiped)
                {
@@ -118,8 +119,8 @@
                    m_DogzUnEquipContents[i].text = StringUtility.Contact(DogzModel.GetItemColorName(_itemColor),
                        DogzModel.GetDogzPartNameByIndex(i));
                    m_DogzUnEquipContents[i].color = UIHelper.GetUIColor(_itemColor);
                    m_DogzUnEquipBtns[i].RemoveAllListeners();
                    m_DogzUnEquipBtns[i].AddListener(() => { ClickEquipIndex(index); });
                    m_DogzUnEquipBtns[i].DogzUnEquipBtn.RemoveAllListeners();
                    m_DogzUnEquipBtns[i].DogzUnEquipBtn.AddListener(() => { ClickEquipIndex(index); });
                }
            }
        }
@@ -188,6 +189,15 @@
        {
            qualitySort.gameObject.SetActive(!qualitySort.gameObject.activeInHierarchy);
        }
        [Serializable]
        public class DogzUnEquip
        {
            [SerializeField] Button m_DogzUnEquipBtn;
            public Button DogzUnEquipBtn { get { return m_DogzUnEquipBtn; } }
            [SerializeField] RedpointBehaviour m_RedpointBeh;
            public RedpointBehaviour RedpointBeh { get { return m_RedpointBeh; } }
        }
    }
}
System/MainInterfacePanel/HighSettingFadeInFadeOut.cs
@@ -498,7 +498,7 @@
                        }
                        if (!AnimationFadeOutDicLow.ContainsKey(highBtnRecord.Index))
                        {
                            if (isPlayerUIeffect.RedPointId == 201 || isPlayerUIeffect.RedPointId == 210)
                            if (isPlayerUIeffect.RedPointId == 201 /*|| isPlayerUIeffect.RedPointId == 210*/)//201(福利),210(仙宝寻主)
                            {
                                if (RedpointCenter.Instance.GetRedpointState(isPlayerUIeffect.RedPointId) == RedPointState.GetReward)
                                {
System/MainInterfacePanel/SkillTaskWin.cs
@@ -22,6 +22,7 @@
        [SerializeField] Button m_OpenNowBtn;
        [SerializeField] Button m_GoToBtn;
        [SerializeField] Button m_ClaoseBtn;
        [SerializeField] Image m_Image;//孔数
        PlayerMainDate m_MainModel;
        PlayerMainDate mainModel { get { return m_MainModel ?? (m_MainModel = ModelCenter.Instance.GetModel<PlayerMainDate>()); } }
        PlayerTaskDatas m_TaskModel;
@@ -56,6 +57,7 @@
            {
                int Index = mainModel.TaskId_Skill.IndexOf(mainModel.TaskSkillID);
                m_Text_Reward_1.text = string.Format(Language.Get("PassiveSkillTask1"), (mainModel.SkillIndex[Index] + 1));
                SetImageSprite(mainModel.SkillIndex[Index] + 1);
                m_NeedMoney_Text.text = string.Format(Language.Get("PassiveSkillTask2"), mainModel.NeedFairyJade[Index]);
            }
        }
@@ -118,6 +120,32 @@
            m_Text_Condition_1.ExcuteHref();
            // Close();
        }
        private void SetImageSprite(int Index)
        {
            switch (Index)
            {
                case 1:
                    m_Image.SetSprite("Slot_1");
                    break;
                case 2:
                    m_Image.SetSprite("Slot_2");
                    break;
                case 3:
                    m_Image.SetSprite("Slot_3");
                    break;
                case 4:
                    m_Image.SetSprite("Slot_4");
                    break;
                case 5:
                    m_Image.SetSprite("Slot_5");
                    break;
                case 6:
                    m_Image.SetSprite("Slot_6");
                    break;
            }
        }
        #endregion