chenxin
2020-12-03 0bc89b87a59c3f1f394a54c0901868084463cf28
boss技能 泡泡禁锢
14 files added
16 files modified
49446 ■■■■■ changed files
Assets/Materials/UI/tileTowerVSMat.mat 2 ●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubble.prefab 14564 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubble.prefab.meta 7 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleBomb.prefab 29114 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleBomb.prefab.meta 7 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleTap.prefab 77 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleTap.prefab.meta 7 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleWarning.prefab 4813 ●●●●● patch | view | raw | blame | history
Assets/Resources/Prefabs/Endless/BondageBubbleWarning.prefab.meta 7 ●●●●● patch | view | raw | blame | history
Assets/Resources/UI/Endless/SkillTitle/4.png patch | view | raw | blame | history
Assets/Resources/UI/Endless/SkillTitle/4.png.meta 118 ●●●●● patch | view | raw | blame | history
Assets/Scenes/Levels/Battle/Endless2D.unity 46 ●●●●● patch | view | raw | blame | history
Assets/Scripts/Enum/EndlessBossSkillTowerType.cs 8 ●●●● patch | view | raw | blame | history
Assets/Scripts/Enum/EndlessBossSkillType.cs 5 ●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Input/EndlessTowerDefenseKeyboardMouseInput.cs 7 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Input/EndlessTowerDefenseTouchInput.cs 7 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Level/EndlessBuff/EndlessBuffManager.cs 22 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Level/EndlessWave.cs 2 ●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Towers/Placement/TowerPlacementGridEndless.cs 53 ●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Towers/Projectiles/BallisticAttack.cs 28 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/Towers/Tower.cs 177 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/BossSkillBondageBubble.cs 203 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/BossSkillBondageBubble.cs.meta 11 ●●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/EndlessBossSkillManager.cs 3 ●●●● patch | view | raw | blame | history
Assets/Scripts/TowerDefense/UI/HUD/EndlessGameUI.cs 30 ●●●● patch | view | raw | blame | history
Assets/StreamingAssets/Table/boss_skill.json 2 ●●● patch | view | raw | blame | history
Assets/StreamingAssets/Table/endless_boss.json 2 ●●● patch | view | raw | blame | history
Assets/UI/Endless/tap.png patch | view | raw | blame | history
Assets/UI/Endless/tap.png.meta 118 ●●●●● patch | view | raw | blame | history
ProjectSettings/TimeManager.asset 6 ●●●● patch | view | raw | blame | history
Assets/Materials/UI/tileTowerVSMat.mat
@@ -40,7 +40,7 @@
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _MainTex:
        m_Texture: {fileID: 2800000, guid: 93f40a01d57fbff418fc0b54b6ab7d9f, type: 3}
        m_Texture: {fileID: 2800000, guid: ea2ffef66c52dd14fbd46187be79f107, type: 3}
        m_Scale: {x: 1, y: 1}
        m_Offset: {x: 0, y: 0}
    - _MetallicGlossMap:
Assets/Resources/Prefabs/Endless/BondageBubble.prefab
New file
Diff too large
Assets/Resources/Prefabs/Endless/BondageBubble.prefab.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3442d54ae86843944bae75f590196642
PrefabImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Resources/Prefabs/Endless/BondageBubbleBomb.prefab
New file
Diff too large
Assets/Resources/Prefabs/Endless/BondageBubbleBomb.prefab.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8a4175f1ae3324a4e9d07e60252f89fc
PrefabImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Resources/Prefabs/Endless/BondageBubbleTap.prefab
New file
@@ -0,0 +1,77 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4273723483615356629
GameObject:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  serializedVersion: 6
  m_Component:
  - component: {fileID: 165075023513248063}
  - component: {fileID: 4054241748655817584}
  - component: {fileID: 1089038520371761158}
  m_Layer: 5
  m_Name: BondageBubbleTap
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!224 &165075023513248063
RectTransform:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 4273723483615356629}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 0
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
  m_AnchorMin: {x: 0.5, y: 0.5}
  m_AnchorMax: {x: 0.5, y: 0.5}
  m_AnchoredPosition: {x: 0, y: 0}
  m_SizeDelta: {x: 201, y: 131}
  m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4054241748655817584
CanvasRenderer:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 4273723483615356629}
  m_CullTransparentMesh: 0
--- !u!114 &1089038520371761158
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 4273723483615356629}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  m_Material: {fileID: 0}
  m_Color: {r: 1, g: 1, b: 1, a: 1}
  m_RaycastTarget: 1
  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
  m_Maskable: 1
  m_OnCullStateChanged:
    m_PersistentCalls:
      m_Calls: []
  m_Sprite: {fileID: 21300000, guid: c91756b0ff0a8314d96ace57ab462fff, type: 3}
  m_Type: 0
  m_PreserveAspect: 0
  m_FillCenter: 1
  m_FillMethod: 4
  m_FillAmount: 1
  m_FillClockwise: 1
  m_FillOrigin: 0
  m_UseSpriteMesh: 0
  m_PixelsPerUnitMultiplier: 1
Assets/Resources/Prefabs/Endless/BondageBubbleTap.prefab.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 382f43d68c7e0ce408b4b171e9750ea5
PrefabImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Resources/Prefabs/Endless/BondageBubbleWarning.prefab
New file
Diff too large
Assets/Resources/Prefabs/Endless/BondageBubbleWarning.prefab.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fe8accc18b93b514c83562642a595a93
PrefabImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Resources/UI/Endless/SkillTitle/4.png
Assets/Resources/UI/Endless/SkillTitle/4.png.meta
New file
@@ -0,0 +1,118 @@
fileFormatVersion: 2
guid: 96d41e925a38c304281c800db5e42a3c
TextureImporter:
  internalIDToNameTable: []
  externalObjects: {}
  serializedVersion: 11
  mipmaps:
    mipMapMode: 0
    enableMipMap: 0
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapsPreserveCoverage: 0
    alphaTestReferenceValue: 0.5
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  streamingMipmaps: 0
  streamingMipmapsPriority: 0
  vTOnly: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    serializedVersion: 2
    filterMode: -1
    aniso: -1
    mipBias: -100
    wrapU: 1
    wrapV: 1
    wrapW: -1
  nPOTScale: 0
  lightmap: 0
  compressionQuality: 50
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spritePixelsToUnits: 100
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spriteGenerateFallbackPhysicsShape: 1
  alphaUsage: 1
  alphaIsTransparency: 1
  spriteTessellationDetail: -1
  textureType: 8
  textureShape: 1
  singleChannelComponent: 0
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  ignorePngGamma: 0
  applyGammaDecoding: 0
  platformSettings:
  - serializedVersion: 3
    buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Standalone
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Android
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: 4
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 1
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
    physicsShape: []
    bones: []
    spriteID: 5e97eb03825dee720800000000000000
    internalID: 0
    vertices: []
    indices:
    edges: []
    weights: []
    secondaryTextures: []
  spritePackingTag:
  pSDRemoveMatte: 0
  pSDShowRemoveMatteOption: 0
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Scenes/Levels/Battle/Endless2D.unity
@@ -4284,6 +4284,50 @@
  m_AnchoredPosition: {x: 0, y: 0}
  m_SizeDelta: {x: 0, y: 0}
  m_Pivot: {x: 0, y: 0}
--- !u!1 &876637724
GameObject:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  serializedVersion: 6
  m_Component:
  - component: {fileID: 876637725}
  - component: {fileID: 876637726}
  m_Layer: 8
  m_Name: GridContainer
  m_TagString: PlaceTower
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!4 &876637725
Transform:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 876637724}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: -36.2}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 1765964312}
  m_RootOrder: 1
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!65 &876637726
BoxCollider:
  m_ObjectHideFlags: 2
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 876637724}
  m_Material: {fileID: 0}
  m_IsTrigger: 0
  m_Enabled: 1
  serializedVersion: 2
  m_Size: {x: 5.545, y: 0, z: 4.436}
  m_Center: {x: 2.7725, y: 0, z: 2.218}
--- !u!1001 &877647585
PrefabInstance:
  m_ObjectHideFlags: 0
@@ -7729,6 +7773,7 @@
    y: 4
  gridSize: 1.109
  TowerGridOpenObjArr: []
  GridContainer: {fileID: 876637724}
  energyEffectPrefab: {fileID: 2066080619878598796, guid: 7fa18b6afd896be469a09f44c4518b10,
    type: 3}
  towerBulletUIPrefab: {fileID: 649954434242370657, guid: f4c10f1b0e730384cacfe2c12ca92ade,
@@ -8769,6 +8814,7 @@
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children:
  - {fileID: 1632078502}
  - {fileID: 876637725}
  m_Father: {fileID: 0}
  m_RootOrder: 4
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
Assets/Scripts/Enum/EndlessBossSkillTowerType.cs
@@ -13,6 +13,12 @@
        All,
        // 单个塔,如果第一排塔被损坏,直接作用到第二排
        Single
        Single,
        // 某一赛道随机选择一个塔释放
        Random,
        // 某一赛道中攻击最高的塔
        MaxAttack
    }
}
Assets/Scripts/Enum/EndlessBossSkillType.cs
@@ -16,6 +16,9 @@
        BubbleBomb,
        // 召唤木桩
        WoodPile
        WoodPile,
        // 禁锢泡泡
        BondageBubble,
    }
}
Assets/Scripts/TowerDefense/Input/EndlessTowerDefenseKeyboardMouseInput.cs
@@ -41,6 +41,7 @@
                // River Add for Mouse Start Drag & Draged.
                controller.startedDrag += OnStartDrag;
                controller.dragged += this.OnDrag;
                controller.pressed += OnPressed;
                controller.released += this.OnEndDrag;
            }
        }
@@ -62,6 +63,7 @@
            controller.startedDrag -= this.OnStartDrag;
            controller.dragged -= this.OnDrag;
            controller.pressed -= OnPressed;
            controller.released -= this.OnEndDrag;
        }
@@ -215,6 +217,11 @@
            }
        }
        private void OnPressed(PointerActionInfo pointer)
        {
            m_GameUI.OnPressed(pointer);
        }
        /// <summary>
        /// Select towers or position ghosts
        /// </summary>
Assets/Scripts/TowerDefense/Input/EndlessTowerDefenseTouchInput.cs
@@ -86,6 +86,7 @@
            if (InputController.instanceExists)
            {
                InputController.instance.tapped += OnTap;
                InputController.instance.pressed += OnPressed;
                InputController.instance.startedDrag += OnStartDrag;
            }
@@ -115,6 +116,7 @@
            if (InputController.instanceExists)
            {
                InputController.instance.tapped -= OnTap;
                InputController.instance.pressed -= OnPressed;
                InputController.instance.startedDrag -= OnStartDrag;
            }
            if (m_GameUI != null)
@@ -124,6 +126,11 @@
            }
        }
        private void OnPressed(PointerActionInfo pointer)
        {
            m_GameUI.OnPressed(pointer);
        }
        /// <summary>
        /// Hide UI 
        /// </summary>
Assets/Scripts/TowerDefense/Level/EndlessBuff/EndlessBuffManager.cs
@@ -157,5 +157,27 @@
            return instanceList[(int)type - 1];
        }
        /// <summary>
        /// 处理PVE无尽模式buff增加的伤害
        /// </summary>
        /// <param name="finalDamage"></param>
        public float ProcessEndlessBuffAttack(float finalDamage, int elfId)
        {
            List<EndlessBuffConfig> list = EndlessBuffManager.instance.GetBuffListByEffectType(EndlessBuffEffectType.AttackAdd, elfId);
            if (list.Count == 0) return 0;
            float ratio = 0;
            float add = 0;
            for (int i = 0; i < list.Count; ++i)
            {
                ratio += list[i].Config.buff_effect[1];
                add += list[i].Config.buff_effect[2];
            }
            return finalDamage * (ratio / 100f) + add;
        }
    }
}
Assets/Scripts/TowerDefense/Level/EndlessWave.cs
@@ -230,7 +230,7 @@
        }
        /// <summary>
        /// 暂时先这么处理 cx test
        /// 暂时先这么处理
        /// </summary>
        /// <param name="resId">endless_enemy表的资源id</param>
        /// <returns>所有可选的agent列表的索引</returns>
Assets/Scripts/TowerDefense/Towers/Placement/TowerPlacementGridEndless.cs
@@ -5,7 +5,6 @@
using TowerDefense.Level;
using TowerDefense.UI.HUD;
using UnityEngine;
using UnityEngine.UI;
namespace TowerDefense.Towers.Placement
{
@@ -14,7 +13,7 @@
    /// Its origin is centered in the middle of the lower-right cell. It can be oriented in any direction
    /// </summary>
    [RequireComponent(typeof(BoxCollider))]
    public class TowerPlacementGridEndless : MonoBehaviour, IPlacementArea
    public class TowerPlacementGridEndless : Singleton<TowerPlacementGridEndless>, IPlacementArea
    {
        public static float GRID_OPENCASH = 200;
@@ -86,8 +85,15 @@
        private float[,] m_arrCoinGenTime;
        public GameObject GridContainer;
        /// <summary>
        /// 每一个Tile格子的中心店的世界坐标
        /// 所有格子对应的世界坐标
        /// </summary>
        private Vector3[,] GridWorldPosArr;
        /// <summary>
        /// 每一个Tile格子的中心店的屏幕坐标
        /// </summary>
        private Vector2[,] arrGridCentPos;
@@ -320,8 +326,6 @@
            return false;
        }
        /// <summary>
        /// 是否是等待购买的攻击塔位.
@@ -569,8 +573,9 @@
        /// <summary>
        /// Initialize values
        /// </summary>
        protected virtual void Awake()
        protected override void Awake()
        {
            base.Awake();
            ResizeCollider();
            // Initialize empty bool array (defaults are false, which is what we want)
@@ -586,6 +591,7 @@
        {
            // 初始化塔位类型.
            initTileGridType();
            InitGridWorldPos();
            // Precalculate inverted grid size, to save a division every time we translate coords
            m_InvGridSize = 1 / gridSize;
@@ -594,6 +600,35 @@
            Invoke("preCalculateGridUIPos", 0.3f);
            EventCenter.Ins.Add<int>((int)KTGMGemClient.EventType.EndlessCritBulletNumChange, OnCritBulletNumChange);
            EventCenter.Ins.Add((int)KTGMGemClient.EventType.OpenAllTowerGrid, OpenAllTowerGrid);
        }
        /// <summary>
        /// 初始化所有格子的世界坐标(中心)
        /// </summary>
        private void InitGridWorldPos()
        {
            GridWorldPosArr = new Vector3[dimensions.x, dimensions.y];
            for (int i = 0; i < dimensions.x; ++i)
            {
                for (int j = 0; j < dimensions.y; ++j)
                {
                    GridWorldPosArr[i, j] = GridToWorld(new IntVector2(i, j), new IntVector2(1, 1));
                }
            }
        }
        /// <summary>
        /// 根据坐标获取格子世界坐标(中心)
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Vector3 GetGridWorldPos(int x, int y)
        {
            if (x < 0 || x >= dimensions.x || y < 0 || y >= dimensions.y) return new Vector3();
            return GridWorldPosArr[x, y];
        }
        /// <summary>
@@ -620,7 +655,7 @@
        {
            arrGridCentPos = new Vector2[dimensions.x, dimensions.y];
            Vector3 targetPos = GridToWorld(new IntVector2(0, 0), new IntVector2(1, 1));
            Vector3 targetPos = GetGridWorldPos(0, 0);
            if (!ViewPortAdj.instance.bAdjViewPort)
                ViewPortAdj.instance.adjViewportRect();
@@ -915,11 +950,9 @@
            for (int tx = 0; tx < dimensions.x; tx++)
            {
                // cx test
                m_arrGridType[tx, sy - 1] = PlacementGridType.EGridWaitBuy;
                m_arrGridType[tx, sy] = PlacementGridType.EGridOpen;
            }
            // m_arrGridType[2, 3] = PlacementGridType.EGridOpen;
            ++GameConfig.EndlessOpenAttackTowerCount;
        }
@@ -1018,7 +1051,7 @@
                {
                    for (int x = 0; x < dimensions.x; x++)
                    {
                        Vector3 targetPos = GridToWorld(new IntVector2(x, y), new IntVector2(1, 1));
                        Vector3 targetPos = GetGridWorldPos(x, y);
                        targetPos.z -= 1.0f;
                        PlacementTile newTile = Instantiate(tileToUse);
                        newTile.transform.parent = tilesParent.transform;
Assets/Scripts/TowerDefense/Towers/Projectiles/BallisticAttack.cs
@@ -121,7 +121,8 @@
            elf_info info = ElfInfoData.GetDataById(TowerPtr.ElfId);
            // 处理PVE无尽模式,buff增加的伤害
            basicDamage += ProcessEndlessBuffAttack(basicDamage);
            if (EndlessBuffManager.instanceExists)
                basicDamage += EndlessBuffManager.instance.ProcessEndlessBuffAttack(basicDamage, TowerPtr.ElfId);
            bool crit = IsCrit();
@@ -178,31 +179,6 @@
                if (TowerPtr != null && isEnhancedBullet)
                    (enemy as Agent).AgentBeRepelled();
            }
        }
        /// <summary>
        /// 处理PVE无尽模式buff增加的伤害
        /// </summary>
        /// <param name="finalDamage"></param>
        protected float ProcessEndlessBuffAttack(float finalDamage)
        {
            // 非无尽模式
            if (!EndlessBuffManager.instanceExists) return 0;
            List<EndlessBuffConfig> list = EndlessBuffManager.instance.GetBuffListByEffectType(EndlessBuffEffectType.AttackAdd, TowerPtr.ElfId);
            if (list.Count == 0) return 0;
            float ratio = 0;
            float add = 0;
            for (int i = 0; i < list.Count; ++i)
            {
                ratio += list[i].Config.buff_effect[1];
                add += list[i].Config.buff_effect[2];
            }
            return finalDamage * (ratio / 100f) + add;
        }
        /// <summary>
Assets/Scripts/TowerDefense/Towers/Tower.cs
@@ -1,4 +1,6 @@
using KTGMGemClient;
using UnityEngine.UI;
using DG.Tweening;
using KTGMGemClient;
using System;
using ActionGameFramework.Health;
using Core.Utilities;
@@ -104,6 +106,38 @@
        public bool PlayWaveLineFlash { get; set; } = true;
        private bool isBondage;
        /// <summary>
        /// 是否是泡泡禁锢状态
        /// </summary>
        /// <value></value>
        public bool IsBondage
        {
            get { return isBondage; }
            set
            {
                isBondage = value;
                CanAttack = !value;
            }
        }
        /// <summary>
        /// 禁锢时间
        /// </summary>
        public float BondageTime { get; set; }
        /// <summary>
        /// 禁锢警告时间
        /// </summary>
        /// <value></value>
        public float BondageWarningTime { get; set; }
        /// <summary>
        /// 泡泡禁锢期间,点击一次减少的时间
        /// </summary>
        public float BondageClickDecreaseTime { get; set; } = 1f;
        /// <summary>
        /// 是否是木属性蓄力状态
        /// </summary>
@@ -139,6 +173,147 @@
        public bool opponentSide { get; set; }
        /// <summary>
        /// 禁锢警告
        /// </summary>
        protected GameObject bondageWarningObj;
        /// <summary>
        /// 禁锢泡泡
        /// </summary>
        protected GameObject bondageObj;
        private GameObject tapObj;
        /// <summary>
        /// 精灵被禁锢时点击次数
        /// </summary>
        public int BondageTapCount { get; private set; }
        private void Update()
        {
            HandleBondageBubble();
        }
        /// <summary>
        /// 处理禁锢泡泡技能
        /// </summary>
        private void HandleBondageBubble()
        {
            if (!IsBondage) return;
            if (BondageWarningTime > 0)
            {
                BondageWarningTime -= Time.deltaTime;
                if (BondageWarningTime <= 0)
                {
                    Destroy(bondageWarningObj);
                    bondageWarningObj = null;
                    StartBondage();
                    ShowTapPrompt();
                }
            }
            else
            {
                BondageTime -= Time.deltaTime;
                if (BondageTime <= 0)
                {
                    IsBondage = false;
                    Destroy(bondageObj);
                    bondageObj = null;
                    BondageBubbleBomb();
                }
            }
        }
        /// <summary>
        /// 展示连续点击提示
        /// </summary>
        private void ShowTapPrompt()
        {
            GameObject prefab = Resources.Load<GameObject>("Prefabs/Endless/BondageBubbleTap");
            tapObj = Instantiate(prefab);
            tapObj.transform.SetParent(GameObject.Find("MainUI/CoinPanel").transform, false);
            Vector3 worldPos = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, gridPosition.y);
            Camera camera = GameObject.Find("SceneCamera3D").GetComponent<Camera>();
            Vector3 screenPos = camera.WorldToScreenPoint(worldPos);
            screenPos.z = 0;
            screenPos.x += 100;
            screenPos.y += 85;
            tapObj.transform.position = screenPos;
            tapObj.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
            DOTween.To(() => tapObj.transform.localScale, (Vector3 v) => tapObj.transform.localScale = v, new Vector3(1f, 1f, 1f), 0.3f).SetEase(Ease.OutBack);
        }
        private void HideTapPrompt()
        {
            if (tapObj != null)
            {
                Image img = tapObj.GetComponent<Image>();
                DOTween.To(() => img.color, (Color v) => img.color = v, new Color(1f, 1f, 1f, 0f), 0.3f).OnComplete(() =>
                {
                    if (tapObj != null)
                    {
                        Destroy(tapObj);
                        tapObj = null;
                    }
                });
            }
        }
        public void OnPressed()
        {
            if (!IsBondage || BondageWarningTime > 0) return;
            ++BondageTapCount;
            if (BondageTapCount == 1)
                HideTapPrompt();
            BondageTime -= BondageClickDecreaseTime;
        }
        /// <summary>
        /// 禁锢泡泡爆炸
        /// </summary>
        private void BondageBubbleBomb()
        {
            GameObject prefab = Resources.Load<GameObject>("Prefabs/Endless/BondageBubbleBomb");
            GameObject obj = Instantiate(prefab);
            obj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
            obj.transform.position = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, gridPosition.y);
            obj.transform.GetChild(0).GetComponent<ParticleSystem>().Play();
            Destroy(obj, 1.2f);
        }
        /// <summary>
        /// 开始泡泡禁锢
        /// </summary>
        private void StartBondage()
        {
            BondageTapCount = 0;
            GameObject prefab = Resources.Load<GameObject>("Prefabs/Endless/BondageBubble");
            bondageObj = Instantiate(prefab);
            bondageObj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
            bondageObj.transform.position = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, gridPosition.y);
            bondageObj.transform.GetChild(0).GetComponent<ParticleSystem>().Play();
        }
        /// <summary>
        /// 禁锢警告
        /// </summary>
        /// <param name="tower"></param>
        public void BondageWarning()
        {
            GameObject prefab = Resources.Load<GameObject>("Prefabs/Endless/BondageBubbleWarning");
            bondageWarningObj = Instantiate(prefab);
            bondageWarningObj.transform.SetParent(TowerPlacementGridEndless.instance.GridContainer.transform, false);
            bondageWarningObj.transform.position = TowerPlacementGridEndless.instance.GetGridWorldPos(gridPosition.x, gridPosition.y);
            bondageWarningObj.transform.GetChild(0).GetComponent<ParticleSystem>().Play();
        }
        /// <summary>
        /// 播放充能状态特效.
        /// </summary>
        /// <param name="play"></param>
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/BossSkillBondageBubble.cs
New file
@@ -0,0 +1,203 @@
using System.Collections.Generic;
using UnityEngine;
using TowerDefense.Towers.Placement;
using TowerDefense.Towers;
using TowerDefense.UI.HUD;
/**
 * 禁锢泡泡
 * @Author: chenxin
 * @Date: 2020-12-03 10:54:12
 */
namespace KTGMGemClient
{
    public class BossSkillBondageBubble : EndlessBossSkill
    {
        public BossSkillBondageBubble(boss_skill param) : base(param) { }
        /// <summary>
        /// 禁锢警告时间
        /// </summary>
        private float BondageTime = 1f;
        public override void Init()
        {
            base.Init();
            Debug.Log("--------------------- 禁锢泡泡技能初始化 ---------------------");
        }
        /// <summary>
        /// 释放技能
        /// </summary>
        public override void ReleaseSkill()
        {
            base.ReleaseSkill();
            switch ((EndlessBossSkillUseTarget)SkillData.target[0])
            {
                case EndlessBossSkillUseTarget.Tower:
                    switch ((EndlessBossSkillTowerType)SkillData.target[1])
                    {
                        case EndlessBossSkillTowerType.All:
                            ReleaseAll();
                            break;
                        case EndlessBossSkillTowerType.Single:
                            ReleaseSingle();
                            break;
                        case EndlessBossSkillTowerType.Random:
                            ReleaseRandom();
                            break;
                        case EndlessBossSkillTowerType.MaxAttack:
                            ReleaseMaxAttack();
                            break;
                        default:
                            Debug.LogWarning($"---- 禁锢泡泡技能,目标参数不正确 Target[{SkillData.target[0]}, {SkillData.target[1]}] ----");
                            break;
                    }
                    break;
                default:
                    Debug.LogWarning("---- 禁锢泡泡技能只支持作用在精灵塔上 ----");
                    break;
            }
        }
        private void ReleaseAll()
        {
            List<int> tunelIdList = GetTunelList();
            int dy = TowerPlacementGridEndless.instance.dimensions.y;
            int attackRows = TowerPlacementGridEndless.instance.AttackRowNumbers;
            for (int i = 0; i < tunelIdList.Count; ++i)
            {
                for (int j = dy - attackRows; j < dy; ++j)
                {
                    Tower tower = EndlessGameUI.instance.FindTowerWithGridIdx(tunelIdList[i] - 1, j);
                    if (tower != null && !tower.IsBondage)
                    {
                        tower.IsBondage = true;
                        tower.BondageTime = SkillData.effect[0];
                        tower.BondageClickDecreaseTime = SkillData.effect[1];
                        tower.BondageWarningTime = BondageTime;
                        tower.BondageWarning();
                    }
                }
            }
        }
        private void ReleaseSingle()
        {
            List<int> tunelIdList = GetTunelList();
            int dy = TowerPlacementGridEndless.instance.dimensions.y;
            int attackRows = TowerPlacementGridEndless.instance.AttackRowNumbers;
            for (int i = 0; i < tunelIdList.Count; ++i)
            {
                // 倒着找,如果第一排塔被摧毁,再找第二排塔
                for (int j = dy - 1; j >= dy - attackRows; --j)
                {
                    Tower tower = EndlessGameUI.instance.FindTowerWithGridIdx(tunelIdList[i] - 1, j);
                    if (tower != null && !tower.IsBondage)
                    {
                        tower.IsBondage = true;
                        tower.BondageTime = SkillData.effect[0];
                        tower.BondageClickDecreaseTime = SkillData.effect[1];
                        tower.BondageWarningTime = BondageTime;
                        tower.BondageWarning();
                        break;
                    }
                }
            }
        }
        private void ReleaseRandom()
        {
            List<int> tunelIdList = GetTunelList();
            int dy = TowerPlacementGridEndless.instance.dimensions.y;
            int attackRows = TowerPlacementGridEndless.instance.AttackRowNumbers;
            for (int i = 0; i < tunelIdList.Count; ++i)
            {
                List<Tower> towerList = new List<Tower>();
                for (int j = dy - 1; j >= dy - attackRows; --j)
                {
                    Tower tower = EndlessGameUI.instance.FindTowerWithGridIdx(tunelIdList[i] - 1, j);
                    if (tower != null && !tower.IsBondage)
                        towerList.Add(tower);
                }
                if (towerList.Count > 0)
                {
                    int random = UnityEngine.Random.Range(0, towerList.Count);
                    towerList[random].IsBondage = true;
                    towerList[random].BondageTime = SkillData.effect[0];
                    towerList[random].BondageClickDecreaseTime = SkillData.effect[1];
                    towerList[random].BondageWarningTime = BondageTime;
                    towerList[random].BondageWarning();
                }
            }
        }
        private void ReleaseMaxAttack()
        {
            List<int> tunelIdList = GetTunelList();
            int dy = TowerPlacementGridEndless.instance.dimensions.y;
            int attackRows = TowerPlacementGridEndless.instance.AttackRowNumbers;
            for (int i = 0; i < tunelIdList.Count; ++i)
            {
                Tower tower = null;
                for (int j = dy - 1; j >= dy - attackRows; --j)
                {
                    Tower tmp = EndlessGameUI.instance.FindTowerWithGridIdx(tunelIdList[i] - 1, j);
                    if (tmp != null && !tmp.IsBondage)
                    {
                        if (tower == null)
                            tower = tmp;
                        else
                        {
                            float tmpDamage = GetTowerDamage(tmp);
                            float towerDamage = GetTowerDamage(tower);
                            if (tmpDamage > towerDamage)
                                tower = tmp;
                        }
                    }
                }
                if (tower != null)
                {
                    tower.IsBondage = true;
                    tower.BondageTime = SkillData.effect[0];
                    tower.BondageClickDecreaseTime = SkillData.effect[1];
                    tower.BondageWarningTime = BondageTime;
                    tower.BondageWarning();
                }
            }
        }
        /// <summary>
        /// 计算塔的攻击力
        /// </summary>
        /// <param name="tower"></param>
        /// <returns></returns>
        private float GetTowerDamage(Tower tower)
        {
            if (tower == null) return 0;
            // 基础伤害 = elf_info 基础攻击力 * elf_upgrade 攻击比率 / 1000f
            float basicDamage = ElfInfoData.GetBasicDamage(tower.ElfId, tower.currentLevel);
            // 处理PVE无尽模式,buff增加的伤害
            if (EndlessBuffManager.instanceExists)
                basicDamage += EndlessBuffManager.instance.ProcessEndlessBuffAttack(basicDamage, tower.ElfId);
            return basicDamage;
        }
    }
}
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/BossSkillBondageBubble.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48d8247e6c71f2f4685e1726526526af
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Scripts/TowerDefense/UI/EndlessBossSkill/EndlessBossSkillManager.cs
@@ -1,4 +1,3 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Core.Utilities;
@@ -264,6 +263,8 @@
                    return new BossSkillBubbleBomb(data);
                case EndlessBossSkillType.WoodPile:
                    return new BossSkillWoodPile(data);
                case EndlessBossSkillType.BondageBubble:
                    return new BossSkillBondageBubble(data);
            }
            return null;
Assets/Scripts/TowerDefense/UI/HUD/EndlessGameUI.cs
@@ -1,11 +1,8 @@
using System.Globalization;
using Core.Health;
using Core.Health;
using Core.Input;
using Core.Utilities;
using DG.Tweening;
using JetBrains.Annotations;
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using TowerDefense.Level;
@@ -15,7 +12,6 @@
using UnityEngine.EventSystems;
using UnityEngine.UI;
using TowerDefense.Nodes;
using TowerDefense.Affectors;
using KTGMGemClient;
namespace TowerDefense.UI.HUD
@@ -687,6 +683,10 @@
                // 判断格子上的塔防:
                UIPointer pointer = WrapPointer(pinfo);
                Tower sTower = PickTowerInGrid(pointer);
                // 泡泡禁锢状态不允许合并
                if (sTower.IsBondage) return false;
                if (sTower && sTower != towerToMove)
                {
                    int testLvl = dragTowerLevel;
@@ -710,6 +710,9 @@
                // 判断格子上的塔防:
                UIPointer pointer = WrapPointer(pinfo);
                Tower sTower = PickTowerInGrid(pointer);
                // 泡泡禁锢状态不允许置换
                if (sTower.IsBondage) return false;
                if (sTower && sTower != towerToMove)
                {
@@ -2218,6 +2221,9 @@
            var controller = output.collider.GetComponent<Tower>();
            if (controller != null)
            {
                // 泡泡禁锢状态不允许拖动
                if (controller.IsBondage) return;
                SelectTower(controller);
            }
@@ -2225,7 +2231,21 @@
            CalSelTowerScreenOffset(info, controller);
        }
        public void OnPressed(PointerInfo info)
        {
            UIPointer uiPointer = WrapPointer(info);
            RaycastHit output;
            bool hasHit = Physics.Raycast(uiPointer.ray, out output, float.MaxValue, towerSelectionLayer);
            if (uiPointer.overUI) return;
            if (hasHit)
            {
                Tower controller = output.collider.GetComponent<Tower>();
                if (controller != null)
                    controller.OnPressed();
            }
        }
        /// <summary>
        /// 鼠标选中一个Tower的时候,计算当前鼠标位置与当前Tower位置在屏幕上坐标位置的偏移量。
Assets/StreamingAssets/Table/boss_skill.json
@@ -1 +1 @@
[[10001,"泡泡炸弹",10002,15000,[3,1],[3],10001,2,[10,2]],[10002,"泡泡炸弹",10002,15000,[3,1],[1,3,5],10001,2,[15,2]],[10003,"泡泡炸弹",10002,15000,[3,1],[1,2,3,4,5],10001,2,[20,2]],[20001,"魔法护盾",10001,20000,[2,1],[3],10001,1,[0.1,10]],[20002,"魔法护盾",10001,20000,[2,1],[2,4],10001,1,[0.2,10]],[20003,"魔法护盾",10001,20000,[2,1],[1,3,5],10001,1,[0.3,10]],[30001,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[2,2.5]],[30002,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[3,2.5]],[30003,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[4,2.5]]]
[[10001,"泡泡炸弹",10002,15000,[3,1],[3],10001,2,[10,2]],[10002,"泡泡炸弹",10002,15000,[3,1],[1,3,5],10001,2,[15,2]],[10003,"泡泡炸弹",10002,15000,[3,1],[1,2,3,4,5],10001,2,[20,2]],[20001,"魔法护盾",10001,20000,[2,1],[3],10001,1,[0.1,10]],[20002,"魔法护盾",10001,20000,[2,1],[2,4],10001,1,[0.2,10]],[20003,"魔法护盾",10001,20000,[2,1],[1,3,5],10001,1,[0.3,10]],[30001,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[2,2.5]],[30002,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[3,2.5]],[30003,"召唤木桩",10003,20000,[3,2],[1,2,3,4,5],10001,3,[4,2.5]],[40001,"精灵禁锢",10004,20000,[1,3],[3],10001,4,[10,1]],[40002,"精灵禁锢",10004,20000,[1,3],[2,4],10001,4,[10,1]],[40003,"精灵禁锢",10004,20000,[1,3],[1,3,5],10001,4,[10,1]]]
Assets/StreamingAssets/Table/endless_boss.json
@@ -1 +1 @@
[[1,"鲨鱼lv1",1,1,[]],[2,"鲨鱼lv2",1,1,[]],[3,"鲨鱼lv3",1,1,[10001]],[4,"鲨鱼lv4",1,1,[30001]],[5,"鲨鱼lv5",1,1,[10002]],[6,"鲨鱼lv6",1,1,[30002]],[7,"鲨鱼lv7",1,1,[10003]],[8,"鲨鱼lv8",1,1,[30003]],[9,"木妖lv1",1,1,[]],[10,"木妖lv2",1,1,[10001]],[11,"木妖lv3",1,1,[10002]],[12,"木妖lv4",1,1,[10003]]]
[[1,"鲨鱼lv1",1,1,[]],[2,"鲨鱼lv2",1,1,[]],[3,"鲨鱼lv3",1,1,[40001]],[4,"鲨鱼lv4",1,1,[40002]],[5,"鲨鱼lv5",1,1,[40003]],[6,"鲨鱼lv6",1,1,[30002]],[7,"鲨鱼lv7",1,1,[10003]],[8,"鲨鱼lv8",1,1,[30003]],[9,"木妖lv1",1,1,[]],[10,"木妖lv2",1,1,[10001]],[11,"木妖lv3",1,1,[10002]],[12,"木妖lv4",1,1,[10003]]]
Assets/UI/Endless/tap.png
Assets/UI/Endless/tap.png.meta
New file
@@ -0,0 +1,118 @@
fileFormatVersion: 2
guid: c91756b0ff0a8314d96ace57ab462fff
TextureImporter:
  internalIDToNameTable: []
  externalObjects: {}
  serializedVersion: 11
  mipmaps:
    mipMapMode: 0
    enableMipMap: 0
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapsPreserveCoverage: 0
    alphaTestReferenceValue: 0.5
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  streamingMipmaps: 0
  streamingMipmapsPriority: 0
  vTOnly: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    serializedVersion: 2
    filterMode: -1
    aniso: -1
    mipBias: -100
    wrapU: 1
    wrapV: 1
    wrapW: -1
  nPOTScale: 0
  lightmap: 0
  compressionQuality: 50
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spritePixelsToUnits: 100
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spriteGenerateFallbackPhysicsShape: 1
  alphaUsage: 1
  alphaIsTransparency: 1
  spriteTessellationDetail: -1
  textureType: 8
  textureShape: 1
  singleChannelComponent: 0
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  ignorePngGamma: 0
  applyGammaDecoding: 0
  platformSettings:
  - serializedVersion: 3
    buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Standalone
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Android
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: 4
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 1
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
    physicsShape: []
    bones: []
    spriteID: 5e97eb03825dee720800000000000000
    internalID: 0
    vertices: []
    indices:
    edges: []
    weights: []
    secondaryTextures: []
  spritePackingTag:
  pSDRemoveMatte: 0
  pSDShowRemoveMatteOption: 0
  userData:
  assetBundleName:
  assetBundleVariant:
ProjectSettings/TimeManager.asset
@@ -3,7 +3,7 @@
--- !u!5 &1
TimeManager:
  m_ObjectHideFlags: 0
  Fixed Timestep: 0.016
  Maximum Allowed Timestep: 0.016
  Fixed Timestep: 0.02
  Maximum Allowed Timestep: 0.02
  m_TimeScale: 1
  Maximum Particle Timestep: 0.016
  Maximum Particle Timestep: 0.02