using Core.Health;
using Core.Input;
using Core.Utilities;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using TMPro;
using TowerDefense.Level;
using TowerDefense.Towers;
using TowerDefense.Towers.Placement;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using TowerDefense.Nodes;
using KTGMGemClient;
namespace TowerDefense.UI.HUD
{
///
/// An object that manages user interaction with the game. Its responsibilities deal with
///
/// -
/// Building towers
///
/// -
/// Selecting towers and units
///
///
///
[RequireComponent(typeof(Camera))]
public class EndlessGameUI : Singleton
{
///
/// The states the UI can be in
///
public enum State
{
///
/// The game is in its normal state. Here the player can pan the camera, select units and towers
///
Normal,
///
/// The game is in 'build mode'. Here the player can pan the camera, confirm or deny placement
///
Building,
///
/// The game is Paused. Here, the player can restart the level, or quit to the main menu
///
Paused,
///
/// The game is over and the level was failed/completed
///
GameOver,
///
/// The game is in 'build mode' and the player is dragging the ghost tower
///
BuildingWithDrag
}
///
/// Gets the current UI state
///
public State state { get; private set; }
///
/// The currently selected tower
///
public LayerMask placementAreaMask;
///
/// 兵线层对应的Mask.
///
public LayerMask waveLineMask;
///
/// 战场区域Mask.
///
public LayerMask battleAreaMask;
///
/// The layer for tower selection
///
public LayerMask towerSelectionLayer;
///
/// The physics layer for moving the ghost around the world
/// when the placement is not valid
///
public LayerMask ghostWorldPlacementMask;
public readonly int MAX_TOWERNUM = 20;
///
/// The radius of the sphere cast
/// for checking ghost placement
///
public float sphereCastRadius = 1;
///
/// 随机购买塔防的按钮.
///
public Button randomTowerBtn;
public Button SkillTowerBtn;
///
/// 飘血数字对应的prefab.
///
public TextMoveDoTween bloodText;
///
/// 中毒飘字.
///
public TextMoveDoTween bloodPoison;
///
/// 暴击飘字.
///
public TextMoveDoTween bloodCrit;
///
/// 减速飘字
///
public Image SlowDownWord;
///
/// 暴击飘字
///
public Image CritWord;
///
/// 冰冻飘字
///
public Image FrostWord;
public Image RestrainWord;
///
/// 购买塔防按钮上的Text.
///
protected TextMeshProUGUI towerPriceText;
public bool tdBuyDisable { get; protected set; } = false;
///
/// 鼠标在移动一个Tower之前,要隐藏的Tower数据和指针。
///
protected Tower towerToMove = null;
///
/// Fires when the changes
/// should only allow firing when TouchUI is used
///
public event Action stateChanged;
///
/// Fires off when the ghost was previously not valid but now is due to currency amount change
///
public event Action ghostBecameValid;
///
/// Fires when a tower is selected/deselected
///
public event Action selectionChanged;
///
/// 成长骰子对应的Timer.
///
protected List listTowerTimer = new List();
protected Dictionary towerTimeDic = new Dictionary();
///
/// Placement area ghost tower is currently on
///
IPlacementArea m_CurrentArea;
///
/// Grid position ghost tower in on
///
IntVector2 m_GridPosition;
///
/// Our cached camera reference
///
Camera m_Camera;
//Camera m_CameraBG;
///
/// Current tower placeholder. Will be null if not in the state.
///
TowerPlacementGhost m_CurrentTower;
public bool HasTower
{
get
{
return m_CurrentTower != null;
}
}
// TowerList用于简单记录相关的数据
protected List m_listTower = new List();
///
/// Tracks if the ghost is in a valid location and the player can afford it
///
bool m_GhostPlacementPossible;
///
/// Gets the current selected tower
///
public Tower currentSelectedTower { get; private set; }
///
/// 拖动塔防时,原塔防的等级。
///
protected int dragTowerLevel = 0;
///
/// 选中Tower时候的鼠标点击坐标与Tower中心所在的屏幕坐标之间的偏移值.
///
protected Vector2 selTowerOffset = new Vector2();
// 测试屏幕显示相关的倒计时.
protected bool bLoaded = false;
private Timer overTimer;
///
/// 总兵线数
///
public int TotalWaveLines { get; } = 5;
public IntVector2 currentGrid
{
get { return m_GridPosition; }
}
///
/// Gets whether a tower has been selected
///
public bool isTowerSelected
{
get { return currentSelectedTower != null; }
}
///
/// 攻击塔位占的行数
///
public int AttackRowNumbers { get; set; } = 2;
///
/// 所有攻击塔位的摧毁信息,是否被摧毁,默认全部没有被摧毁
///
private bool[,] TowerDestroyArr;
public event Action GameOverEvent;
///
/// 塔升级特效预制体
///
public GameObject TowerUpgradeEffectPrefab;
///
/// 宝石出现特效预制体
///
public GameObject TowerAppearEffectPrefab;
public GameObject TowerUpgradeEffectPrefabGuide;//新手导航特效Layer是UI
public GameObject TowerAppearEffectPrefabGuide;//新手导航特效Layer是UI
//首次购买宝石特效
public GameObject fireAppearEffect1;
//public GameObject fireAppearEffect2;
public GameObject waterAppearEffect1;
//public GameObject waterAppearEffect2;
public GameObject woodAppearEffect1;
//public GameObject woodAppearEffect2;
///
/// 保存所有生成或合成的塔的最小等级
///
///
public int MinLevel;
public IPlacementArea selfTowerPlaceArea
{
get
{
if (m_CurrentArea == null)
{
GameObject placeObj = GameObject.FindGameObjectWithTag("PlaceTower");
if (placeObj != null)
m_CurrentArea = placeObj.GetComponent();
}
return m_CurrentArea;
}
}
private void UpdateMinLevelArr()
{
int min = -1;
for (int i = 0; i < m_listTower.Count; ++i)
{
if (min == -1 || m_listTower[i].currentLevel < min)
min = m_listTower[i].currentLevel;
}
MinLevel = Mathf.Max(min, 0);
}
///
/// 增加一个防塔的数据结构,测试数据
///
///
public void addTower(Tower t)
{
m_listTower.Add(t);
UpdateMinLevelArr();
// 当前所在的位置是否攻击位置,随手瞎写:2 或者 3也就是前两排是上阵的
if (t.gridPosition.y >= 2)
t.bInAttackMode = true;
// ATTENTION TO FIX: 先写死,有一个简单的逻辑再说:
if (m_listTower.Count >= MAX_TOWERNUM)
disableRandomTowerBtn();
}
public void PlayBuffPS(int get_buffID)
{
//Debug.Log("开始播放特效");
int targetID = 0;
switch (get_buffID)
{
case 0:
//无特效
break;
case 1:
for (int i = 0; i < m_listTower.Count; i++)
{
m_listTower[i].CurrentTowerLevel.ShowBuffPS();
}
break;
case 2:
targetID = 101;
break;
case 3:
targetID = 201;
break;
case 4:
targetID = 301;
break;
}
if (targetID > 1)
{
for (int i = 0; i < m_listTower.Count; i++)
{
if (m_listTower[i].ElfId == targetID)
{
m_listTower[i].CurrentTowerLevel.ShowBuffPS();
}
}
}
}
///
/// 根据塔位索引位置,查找位置上是否有对应的塔防数据。
///
///
///
///
public Tower FindTowerWithGridIdx(int x, int y)
{
foreach (Tower lt in m_listTower)
{
if ((lt.gridPosition.x == x) && (lt.gridPosition.y == y))
return lt;
}
return null;
}
///
/// 根据塔位索引位置,查找位置上是否有对应的塔防数据。
///
///
///
///
public int GetTowerNum()
{
int num = 0;
foreach (Tower lt in m_listTower)
{
if (lt.gridPosition.y == 0 || lt.gridPosition.y == 1)
{
num++;
}
}
return num;
}
public bool towerInList(Tower t)
{
return m_listTower.Contains(t);
}
///
/// 设置已经上阵的所有塔的攻击状态,是否可以攻击
///
///
public void SetAttackingTowerState(bool canAttack)
{
foreach (Tower tower in m_listTower)
{
tower.CanAttack = canAttack;
}
}
public void delTower(Tower t)
{
// 删除Tower有可能对应的Timer.
foreach (var tdata in towerTimeDic)
{
if (tdata.Value == t)
{
// 先删除对应的timer数据:
foreach (var timer in listTowerTimer)
{
if (tdata.Key == timer.timerID)
{
listTowerTimer.Remove(timer);
break;
}
}
// 删除字典并退出:
towerTimeDic.Remove(tdata.Key);
break;
}
}
int tcnt = m_listTower.Count;
m_listTower.Remove(t);
if (tcnt == MAX_TOWERNUM)
enableRandomTowerBtn();
}
///
/// 清空缓存数据
///
public void restartLevel()
{
m_listTower.Clear();
listTowerTimer.Clear();
towerTimeDic.Clear();
}
///
/// 查找相同类型,相同段位的Tower
///
///
public Tower findSameLvlTower(Tower t)
{
Tower rest = null;
foreach (Tower lt in m_listTower)
{
if (lt == t) continue;
if ((lt.currentLevel == t.currentLevel) &&
(lt.towerName == t.towerName))
{
return lt;
}
}
return rest;
}
///
/// Gets whether certain build operations are valid
///
public bool isBuilding
{
get
{
return state == State.Building || state == State.BuildingWithDrag;
}
}
///
/// Cancel placing the ghost
///
public void CancelGhostPlacement()
{
if (m_CurrentTower)
Destroy(m_CurrentTower.gameObject);
m_CurrentTower = null;
SetState(State.Normal);
DeselectTower();
}
///
/// Returns the GameUI to dragging mode with the curent tower
///
/// ///
/// Throws exception when not in build mode
///
public void ChangeToDragMode()
{
if (!isBuilding)
{
throw new InvalidOperationException("Trying to return to Build With Dragging Mode when not in Build Mode");
}
SetState(State.BuildingWithDrag);
}
///
/// Returns the GameUI to BuildMode with the current tower
///
///
/// Throws exception when not in Drag mode
///
public void ReturnToBuildMode()
{
if (!isBuilding)
{
throw new InvalidOperationException("Trying to return to Build Mode when not in Drag Mode");
}
SetState(State.Building);
}
///
/// Changes the state and fires
///
/// The state to change to
/// thrown on an invalid state
void SetState(State newState)
{
if (state == newState)
{
return;
}
if (state == State.GameOver)
{
CommonDebugHelper.DebugError("已经游戏结束了,为什么还在修改状态");
return;
}
CommonDebugHelper.Debug($"设置了状态 state:{state} newState:{newState} ");
State oldState = state;
if (oldState == State.Paused || oldState == State.GameOver)
{
Time.timeScale = 1f;
}
switch (newState)
{
case State.Normal:
break;
case State.Building:
break;
case State.BuildingWithDrag:
break;
case State.Paused:
case State.GameOver:
if (oldState == State.Building)
CancelGhostPlacement();
Time.timeScale = 1f;
break;
default:
throw new ArgumentOutOfRangeException("newState", newState, null);
}
state = newState;
if (stateChanged != null)
{
stateChanged(oldState, state);
}
}
///
/// Called when the game is over
///
public void GameOver()
{
CommonDebugHelper.Debug("游戏结束了");
SetState(State.GameOver);
}
///
/// Pause the game and display the pause menu
///
public void Pause()
{
SetState(State.Paused);
}
///
/// Resume the game and close the pause menu
///
public void Unpause()
{
SetState(State.Normal);
}
///
/// Changes the mode to drag
///
///
/// The tower to build
///
///
/// Throws exception when trying to change to Drag mode when not in Normal Mode
///
public void SetToDragMode([NotNull] Tower towerToBuild)
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to enter drag mode when not in Normal mode");
}
if (m_CurrentTower != null)
{
// Destroy current ghost
CancelGhostPlacement();
}
SetUpGhostTower(towerToBuild);
SetState(State.BuildingWithDrag);
}
///
/// 点击某一个塔防之后,开启拖动塔防的模式。
/// River: 修改为暂不删除原来的Tower,把原来的Tower隐藏掉.
///
///
public void startDragTower(Tower towerOld)
{
Tower newT = null;
foreach (Tower tower in EndlessLevelManager.instance.TowerLibrary)
{
if (tower.towerName != towerOld.towerName)
continue;
newT = tower;
break;
}
// 从列表中删除Tower.并破坏Tower的外形。
dragTowerLevel = towerOld.currentLevel;
// 尝试不再删除原来的Tower,而是尝试在合成成功后再删除原来的Tower
towerOld.showTower(false);
towerToMove = towerOld;
// 先删除,再设置移动相关。
SetToDragMode(newT);
if (towerOld.towerFeature == EFeatureTower.Skill_Bomb)
m_CurrentTower.SetAttackArea(dragTowerLevel, towerOld.ElfId);
}
///
/// Sets the UI into a build state for a given tower
/// River: 当界面上某一个塔防的按钮被按下后,需要调用的这个函数进入建造模式。
///
///
/// The tower to build
///
///
/// Throws exception trying to enter Build Mode when not in Normal Mode
///
public void SetToBuildMode([NotNull] Tower towerToBuild)
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to enter Build mode when not in Normal mode");
}
if (m_CurrentTower != null)
{
// Destroy current ghost
CancelGhostPlacement();
}
SetUpGhostTower(towerToBuild);
SetState(State.Building);
}
///
/// 目标位置是否是可攻击属性的空塔位
///
///
///
protected bool isFreeAttackGrid(PointerInfo pinfo)
{
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
if (sTower != null)
{
return false;
}
if ((m_GridPosition.x >= 0) && (m_GridPosition.y >= 0))
{
if ((m_CurrentArea as TowerPlacementGridEndless).isFreeAtackPos(m_GridPosition.x, m_GridPosition.y))
{
return true;
}
}
return false;
}
///
/// 是否是可开启的AttackGrid塔位.
///
///
///
protected bool isWaitBuyAttackGrid(PointerInfo pinfo)
{
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
if (sTower != null)
return false;
if ((m_GridPosition.x >= 0) && (m_GridPosition.y >= 0))
{
if (m_CurrentArea.isWaitBuyGrid(m_GridPosition.x, m_GridPosition.y))
return true;
}
return false;
}
///
/// 目标位置是否有同等级同类型的Tower.
///
///
///
protected bool isValidateCombineTarget(PointerInfo pinfo)
{
// 判断是否格子上重复放置塔防
if (!m_CurrentTower || !IsGhostAtValidPosition())
{
// 最大级别的Tower不能再合并了.
if (towerToMove.IsMaxLevel)
return false;
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
// 泡泡禁锢状态不允许合并
if (sTower && sTower.IsStartBondage) return false;
if (sTower && sTower != towerToMove)
{
int testLvl = dragTowerLevel;
if (towerToMove && sTower.currentLevel == testLvl && sTower.towerName == towerToMove.towerName)
return true;
}
}
return false;
}
///
/// 判断是否有不同类型的Tower,可以发生置换,仅限于火木水之间发生
///
///
///
protected bool IsSubstitute(PointerInfo pinfo)
{
if (!m_CurrentTower || !IsGhostAtValidPosition())
{
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
// 泡泡禁锢状态不允许置换
if (sTower && sTower.IsStartBondage) return false;
if (sTower && sTower != towerToMove)
{
if (towerToMove)
return true;
}
}
return false;
}
///
/// 判断是否有不同类型的Tower,可以发生置换,仅限于火木水之间发生
///
///
///
protected bool IsSubstituteGuide(PointerInfo pinfo)
{
if (!m_CurrentTower || !IsGhostAtValidPosition())
{
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
if (sTower && sTower != towerToMove)
{
if (towerToMove && sTower.towerFeature == EFeatureTower.NULL && towerToMove.towerFeature == EFeatureTower.NULL)
return true;
}
}
return false;
}
///
/// 获取目标格子上的塔防的名字数据
///
///
///
protected string getTargetTowerName(PointerInfo pinfo)
{
if (m_CurrentTower == null || !IsGhostAtValidPosition())
{
// 获取目标格子上的塔防指针:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
if ((sTower != null) && (sTower != towerToMove))
{
return sTower.towerName;
}
}
return "";
}
///
/// 提升所有塔的等级,如果现在塔的等级 < level,设置等级为 level,如果 > level 不做改变
///
/// 从0开始
public void UpgradeAllTowerMinLevel(int level)
{
if (level < 0 || level > ElfUpgradeData.MaxTowerLevel - 1) return;
for (int i = 0; i < m_listTower.Count; ++i)
{
if (m_listTower[i].currentLevel < level)
{
m_listTower[i].currentLevel = level;
m_listTower[i].CurrentTowerLevel.SetShowLevel(level + 1);
m_listTower[i].CurrentTowerLevel.SetScale(level + 1);
PlayUpgradeEffect(m_listTower[i]);
}
}
GameConfig.IsUpgradeTowerLevel = true;
UpdateMinLevelArr();
EndlessRandomTower.instance.UpdateDescDisplay();
}
///
/// 成长骰子升级为高一级别的随机骰子.
///
///
protected void growUpTower(Tower tower)
{
Tower newTower = EndlessRandomTower.instance.GetRandomTower(EFeatureTower.NULL);
// 所有的Tower不能升级成为FeatureTower.
int maxLoop = 20;
while (newTower.towerFeature != EFeatureTower.NULL)
{
newTower = EndlessRandomTower.instance.GetRandomTower(EFeatureTower.NULL);
maxLoop--;
if (maxLoop <= 0)
{
newTower = EndlessRandomTower.instance.getRTower();
Debug.LogError("超级循环发生了.");
break;
}
}
// 成长为高一级别的骰子
DisplaceTower(newTower, tower, 1);
}
///
/// 破坏某一列的塔位数据
///
///
///
public void DestroyTowerGrid(int xidx)
{
// 这里的逻辑已经不走了
for (int i = 0; i < AttackRowNumbers; ++i)
{
if (TowerDestroyArr[xidx, i]) continue;
Node newNode = EndlessLevelManager.instance.SwitchHomeBase(xidx);
WaveLineAgentInsMgr[] agentInsMgrs = AgentInsManager.instance.GetWaveLineList();
for (int j = 0; j < agentInsMgrs[xidx].listAgent.Count; ++j)
{
agentInsMgrs[xidx].listAgent[j].ChangeNextNode(newNode);
}
TowerDestroyArr[xidx, i] = true;
Tower tower = FindTowerWithGridIdx(xidx, 3 - i);
if (tower)
{
delTower(tower);
tower.Sell();
}
if (m_CurrentArea != null)
// 3 -> dimensions.y - 1
m_CurrentArea.SetDestroyedGrid(xidx, 3 - i);
break;
}
bool isAllDestroyed = true;
for (int i = 0; i < AttackRowNumbers; ++i)
{
if (!TowerDestroyArr[xidx, i])
{
isAllDestroyed = false;
break;
}
}
// 该兵线的所有基地都被摧毁完毕,目前的逻辑只要有一条兵线两个基地都被摧毁就算游戏结束
if (isAllDestroyed)
{
// 停止所有兵线的出兵
for (int i = 0; i < TotalWaveLines; ++i)
{
EndlessLevelManager.instance.StopWaveLine(i);
}
// 让所有兵线上已经生成的所有agent播放一个死亡动画然后销毁
WaveLineAgentInsMgr[] waveLineAgentIns = AgentInsManager.instance.GetWaveLineList();
for (int i = 0; i < waveLineAgentIns.Length; ++i)
{
while (waveLineAgentIns[i].listAgent.Count > 0)
{
waveLineAgentIns[i].listAgent[0].PlayDeath();
}
}
GameOver();
overTimer = new Timer(1.2f, SafelyCallGameOverEvent);
}
}
///
/// 爱心数量为0,游戏结束
///
private void AllHeartLose()
{
// 清理技能
EndlessBossSkillManager.instance.ClearSkillList();
EndlessBossHPManager.instance.SwitchHP(true);
EndlessBossHPManager.instance.SetCurrentHP(0);
EndlessLevelManager.instance.WaveManager.HideTunel();
// 停止所有兵线的出兵
for (int i = 0; i < TotalWaveLines; ++i)
{
EndlessLevelManager.instance.StopWaveLine(i);
}
// 让所有兵线上已经生成的所有agent播放一个死亡动画然后销毁
WaveLineAgentInsMgr[] waveLineAgentIns = AgentInsManager.instance.GetWaveLineList();
GameOver();
for (int i = 0; i < waveLineAgentIns.Length; ++i)
{
while (waveLineAgentIns[i].listAgent.Count > 0)
{
waveLineAgentIns[i].listAgent[0].PlayDeath();
}
}
overTimer = new Timer(1.2f, SafelyCallGameOverEvent);
}
private void SafelyCallGameOverEvent()
{
if (GameOverEvent != null)
GameOverEvent();
overTimer = null;
}
#region 拖动时候给塔位一个标识
public MeshRenderer temporaryMat;//移动时候的虚像材质
///
/// 查找可以合成的塔
///
public void CheckAllCanPlace()
{
if (m_CurrentTower != null)
{
if (m_CurrentTower.controller.towerFeature == EFeatureTower.NULL)
{
// if (m_CurrentArea != null && m_CurrentTower.controller.gridPosition.y >= 2)
// {
// //修改为只要开启格子都可以放
// (m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_CurrentTower.controller.gridPosition.x, m_CurrentTower.controller.gridPosition.y, false, "");
// //(m_CurrentArea as TowerPlacementGridEndless).PlayPS(allPSTowerP);
// }
return;
List allTowerP = null;//排除不能合成的
// List allPSTowerP = new List();//需要播放升级动画的
if (towerToMove)
{
if (towerToMove.gridPosition.y == 0 || towerToMove.gridPosition.y == 1)
{
allTowerP = new List();
for (int i = 0; i < m_listTower.Count; i++)
{
if (m_listTower[i].bInAttackMode && towerToMove && m_listTower[i].currentLevel == dragTowerLevel && m_listTower[i].towerName == towerToMove.towerName)
{
// if (towerToMove.gridPosition != m_listTower[i].gridPosition)
// //说明可以合成
// allPSTowerP.Add(m_listTower[i].gridPosition);
}
else
{
//把不符合条件的传进去
allTowerP.Add(m_listTower[i].gridPosition);
}
}
}
}
if (m_CurrentArea != null)
{
//修改为只要开启格子都可以放
(m_CurrentArea as TowerPlacementGridEndless).CheckAllCanPlace(allTowerP);
//(m_CurrentArea as TowerPlacementGridEndless).PlayPS(allPSTowerP);
}
}
else if (m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Fire || m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Bomb)
{
//Debug.Log("需要激活兵线下方绿色标识");
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.EndlessStartDragSkill, true);
}
}
}
///
/// 关闭所有标识
///
public void CloseCanPlaceRenderer()
{
if (m_CurrentTower && m_CurrentTower.controller && m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Fire || m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Bomb)
{
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.EndlessStartDragSkill, false);
}
if (m_CurrentArea != null)
(m_CurrentArea as TowerPlacementGridEndless).CloseCanPlaceRenderer();
else
{
GameObject placeObj = GameObject.FindGameObjectWithTag("PlaceTower");
if (placeObj != null)
(placeObj.GetComponent() as TowerPlacementGridEndless).CloseCanPlaceRenderer();
}
}
Tower checkTowerPlaceTower;//移动时候查看鼠标是否检测到有塔
Tower bInAttackModeTower;//在合成区的塔
///
/// 检查符合条件的塔
///
///
public void CheckTowerPlace(PointerInfo pointerInfo)
{
//return;
if (m_CurrentArea != null && m_CurrentArea is TowerPlacementGridEndless)
{
checkTowerPlaceTower = isFreeAttackGridOnDrag(pointerInfo);
//下面是为了设置一个虚拟的塔
if (checkTowerPlaceTower != null)
{
Debug.Log(checkTowerPlaceTower.name);
if (m_CurrentTower.controller.towerFeature == EFeatureTower.NULL)
{
if (checkTowerPlaceTower.bInAttackMode)
{
//鼠标检测到了塔
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, false, "");
}
else
{
if (!towerToMove.bInAttackMode)
{
//没有上阵
if (bInAttackModeTower == null)
{
bInAttackModeTower = checkTowerPlaceTower;
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(true);
}
else if (bInAttackModeTower != checkTowerPlaceTower)
{
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(false);
bInAttackModeTower = checkTowerPlaceTower;
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(true);
}
}
}
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(checkTowerPlaceTower.gridPosition, m_CurrentTower.controller.dimensions);
}
}
else if ((m_GridPosition.x >= 0) && (m_GridPosition.y >= 0))
{
//查看是否是一个空格子
if (m_CurrentArea.isFreeAtackPos(m_GridPosition.x, m_GridPosition.y))
{
if (m_CurrentTower.controller.towerFeature == EFeatureTower.NULL)
{
//空格子
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, true, towerToMove.towerName);
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(m_GridPosition, m_CurrentTower.controller.dimensions);
}
}
else
{
CloseCanPlace();
}
}
else
{
CloseCanPlace();
}
}
else
{
if (m_CurrentTower.controller.towerFeature == EFeatureTower.NULL)
{
dragTowerPlacement.CloseCanPlace();
}
}
}
public void CloseCanPlace()
{
dragTowerPlacement.CloseCanPlace();
if (bInAttackModeTower != null)
{
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(false);
bInAttackModeTower = null;
}
}
TowerPlacementGridEndless dragTowerPlacement;
public void CheckTowerPlaceNew(PointerInfo pointerInfo)
{
//return;
if (m_CurrentArea != null && m_CurrentArea is TowerPlacementGridEndless)
{
if ((m_GridPosition.x >= 0) && (m_GridPosition.y >= 0))
{
if (m_GridPosition.y == 0 || m_GridPosition.y == 1)
{
//Debug.Log("未上阵区域,不管有没有塔,都强行吸附");
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, true, "");
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(m_GridPosition, m_CurrentTower.controller.dimensions);
}
else if (m_GridPosition.y == 2 || m_GridPosition.y == 3)
{
//Debug.Log("已上阵区域,如果是空格子就强行吸附,先判断是否有塔");
//pointerInfo.currentPosition += new Vector2(0, -25f);
checkTowerPlaceTower = isFreeAttackGridOnDrag(pointerInfo);
if (checkTowerPlaceTower != null)
{
//Debug.Log(checkTowerPlaceTower.name);
//Debug.Log($"checkTowerPlaceTower.name:{checkTowerPlaceTower.name} m_GridPosition:{m_GridPosition}");
if (m_CurrentTower.controller.towerFeature == EFeatureTower.NULL)
{
if (checkTowerPlaceTower.bInAttackMode)
{
//Debug.Log("检测到了塔");
//鼠标检测到了塔
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(checkTowerPlaceTower.gridPosition.x, checkTowerPlaceTower.gridPosition.y, false, "");
}
else
{
if (!towerToMove.bInAttackMode)
{
//没有上阵
if (bInAttackModeTower == null)
{
bInAttackModeTower = checkTowerPlaceTower;
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(true);
}
else if (bInAttackModeTower != checkTowerPlaceTower)
{
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(false);
bInAttackModeTower = checkTowerPlaceTower;
bInAttackModeTower.CurrentTowerLevel.SetCanPlace(true);
}
}
}
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(checkTowerPlaceTower.gridPosition, m_CurrentTower.controller.dimensions);
}
}
else if ((m_CurrentArea as TowerPlacementGridEndless).isFreeAtackPos(m_GridPosition.x, m_GridPosition.y))
{
//Debug.Log("空格子");
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, true, towerToMove.towerName);
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(m_GridPosition, m_CurrentTower.controller.dimensions);
}
else
{
//Debug.Log($"上阵区域 m_GridPosition:{m_GridPosition.x} {m_GridPosition.y} m_CurrentTower.controller.gridPosition:{m_CurrentTower.controller.gridPosition.x} {m_CurrentTower.controller.gridPosition.y}");
if (m_GridPosition == towerToMove.gridPosition)
{
//Debug.Log("在原来的地方");
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, true, towerToMove.towerName);
m_CurrentTower.transform.position = towerToMove.position;
}
else
{
//CloseCanPlace();
//Debug.Log("上阵区域,没有开放的塔位");
(m_CurrentArea as TowerPlacementGridEndless).CheckCanPlaceUpdate(m_GridPosition.x, m_GridPosition.y, true, "");
m_CurrentTower.transform.position = (m_CurrentArea as TowerPlacementGridEndless).GridToWorld(m_GridPosition, m_CurrentTower.controller.dimensions);
}
}
}
}
}
else
{
dragTowerPlacement.CloseCanPlace();
}
}
///
/// 目标位置是否是可攻击属性的空塔位
///
///
///
protected Tower isFreeAttackGridOnDrag(PointerInfo pinfo)
{
// 判断格子上的塔防:
UIPointer pointer = WrapPointer(pinfo);
Tower sTower = PickTowerInGrid(pointer);
if (sTower != null)
{
if (towerToMove)
{
return sTower;
// if (towerToMove.bInAttackMode)
// {
// }
// else
// {
// if (sTower.currentLevel == dragTowerLevel && sTower.towerName == towerToMove.towerName)
// {
// //说明可以合成
// return sTower;
// }
// }
}
else
{
return null;
}
}
return null;
}
#endregion
///
/// 推拽结束,如果判断HasTower==true 就强行释放
///
public void EndDragCancelPlaceTower()
{
Debug.Log("强行释放了m_CurrentTower");
CancelPlaceTower(null);
}
///
/// 拖动一个Tower之后,松开鼠标或者EndDrag.
/// 1: 目标点可合成,则直接合成。
/// 2: 目标点不管是空白,还是不能放置Tower,都要让当前的Tower返回到原来的TowerPlace
///
///
public void onEndTowerDrag(PointerInfo pointerInfo)
{
if (temporaryMat != null)
{
//移动虚像隐藏
temporaryMat.material = null;
}
if (!m_CurrentTower || !m_CurrentTower.controller)
{
CancelPlaceTower(pointerInfo);
return;
}
if (m_CurrentTower.controller.towerFeature != EFeatureTower.NULL)
{
Debug.LogError("只能移动3种塔");
return;
}
if (GameConfig.IsNewbie)
{
bool isCanChange = false;
if (EndlessLevelManager.instanceExists && IsSubstituteGuide(pointerInfo))
{
isCanChange = CheckCanChangePos(pointerInfo);
}
if (isCanChange)
{
GuideCtrl.Ins.DragDone();
Debug.Log("交换了位置");
}
else
{
GuideCtrl.Ins.EndDrag5_1();
CancelPlaceTower(pointerInfo);
Debug.Log("没有放置在火塔上");
}
return;
}
// 判断目标位置是否有Tower且类型和等级一致,如果没有,则GhostTower删除,原Tower显示。
if (isValidateCombineTarget(pointerInfo))
{
//Debug.Log("isValidateCombineTarget");
TryPlaceTower(pointerInfo);
EndlessRandomTower.instance.UpdateDescDisplay();
}
else if (isFreeAttackGrid(pointerInfo))
{
//Debug.Log("isFreeAttackGrid:" + m_GridPosition);
if (!TryPlaceTower(pointerInfo, false))
{
CancelPlaceTower(pointerInfo);
Debug.Log("这里需要返回原位");
return;
}
// 删除towerToMove,确保塔防数据不再出现多个
if (towerToMove != null)
{
delTower(towerToMove);
towerToMove.showTower(true);
towerToMove.Sell();
towerToMove = null;
}
if (m_CurrentTower != null && m_CurrentTower.controller != null)
Destroy(m_CurrentTower.controller.gameObject);
}
else if (EndlessLevelManager.instanceExists && IsSubstitute(pointerInfo))
{
//Debug.Log("IsSubstitute");
CheckCanChangePos(pointerInfo);
}
else
CancelPlaceTower(pointerInfo);
}
private bool CheckCanChangePos(PointerInfo pointerInfo)
{
// 可以发生置换
UIPointer pointer = WrapPointer(pointerInfo);
// 格子上的塔
Tower sTower = PickTowerInGrid(pointer);
if (sTower == null)
return false;
//Debug.Log("开始检测是否可以交换塔");
//if (sTower.bInAttackMode == towerToMove.bInAttackMode)
{
IntVector2 v1 = new IntVector2(towerToMove.gridPosition.x, towerToMove.gridPosition.y);
IntVector2 v2 = new IntVector2(sTower.gridPosition.x, sTower.gridPosition.y);
if (m_CurrentArea == null)
{
CancelGhostPlacement();
towerToMove.showTower(true);
return false;
}
else
{
Tower newTower1 = PlaceTowerForce(EndlessRandomTower.instance.getTowerByName(sTower.towerName), v1, sTower.currentLevel + 1, false);
Tower newTower2 = PlaceTowerForce(m_CurrentTower.controller, v2, towerToMove.currentLevel + 1, false);
if (towerToMove != null)
{
delTower(towerToMove);
towerToMove.showTower(true);
towerToMove.Sell();
towerToMove = null;
}
delTower(sTower);
sTower.showTower(true);
sTower.Sell();
sTower = null;
CancelGhostPlacement();
newTower1.placementArea.Occupy(newTower1.gridPosition, newTower1.dimensions);
newTower2.placementArea.Occupy(newTower2.gridPosition, newTower2.dimensions);
//强制交换塔的时候检查自身充能条
newTower1.CheckCtrl();
newTower2.CheckCtrl();
//Debug.Log($"newTower1:{newTower1.towerName} newTower2:{newTower2.towerName}");
TowerPlacementGridEndless.instance.PlayPutPs(newTower2.gridPosition.x, newTower2.gridPosition.y);
return true;
}
}
return false;
}
///
/// 强制放置塔,主要是用于新手
///
///
///
/// 塔的等级
public Tower PlaceTowerForce(Tower newTower, IntVector2 pos, int level, bool playEffect = true)
{
TowerPlacementGhost currentTower = Instantiate(newTower.towerGhostPrefab);
currentTower.Initialize(newTower);
Tower controller = currentTower.controller;
Tower createdTower = Instantiate(controller);
createdTower.PlayWaveLineFlash = playEffect;
createdTower.Initialize(m_CurrentArea, pos, level - 1);
if (playEffect)
PlayUpgradeEffect(createdTower);
addTower(createdTower);
Destroy(currentTower.gameObject);
return createdTower;
}
protected bool SkillPlayEndDrag(PointerInfo pointer)
{
// 我操,终于可以了!ATTENTION TO OPP:
PointerInfo tp = new PointerActionInfo();
tp.currentPosition = pointer.currentPosition;
tp.previousPosition = pointer.previousPosition;
tp.delta = pointer.delta;
tp.startedOverUI = pointer.startedOverUI;
// River: 调整偏移值,用于鼠标移动塔防的时候,更加平滑。
tp.currentPosition.x += selTowerOffset.x;
tp.currentPosition.y += selTowerOffset.y;
UIPointer npt = new UIPointer
{
overUI = false,
pointer = tp,
overWaveLine = false,
ray = m_Camera.ScreenPointToRay(tp.currentPosition)
};
int sId = towerToMove.ElfId;
int sLevel = towerToMove.currentLevel;
// 火是列攻击:
if (m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Fire)
{
WavelineAreaRaycast(ref npt);
if (npt.overWaveLine)
{
WaveLineSelEffect selEff = npt.wavelineHit.Value.collider.GetComponent();
if (selEff)
{
// 播放特效,并处理伤害.
EndlessWaveLineManager.instance.PlayWaveLineEffect(selEff.waveLineId);
AgentInsManager.instance.ExecWavelineAttack(selEff.waveLineId, sId, sLevel, false);
++GameConfig.EndlessPortUseSkillTowerCount;
return true;
}
}
}
// 炸弹是区域攻击显示:
if (m_CurrentTower.controller.towerFeature == EFeatureTower.Skill_Bomb)
{
// 测试代码与战场区域碰撞,碰撞后显示攻击区域:
BattleAreaRaycast(ref npt);
if (npt.overWaveLine)
{
EndlessWaveLineManager.instance.PlayBattleAreaBombEffect(npt.wavelineHit.Value.point);
AgentInsManager.instance.ExecBombAttack(npt.wavelineHit.Value.point, sId, sLevel, false);
return true;
}
}
return false;
}
protected void CancelPlaceTower(PointerInfo pointerInfo)
{
CancelGhostPlacement();
if (towerToMove)
{
towerToMove.showTower(true);
towerToMove.CheckCtrl();
// 处理复制骰子:
if (towerToMove.towerFeature == EFeatureTower.CopyCat)
{
CopyTargetTower(pointerInfo);
}
else
{
// 升级目标位置的塔防.
currentSelectedTower = towerToMove;
}
towerToMove = null;
}
SetState(State.Normal);
}
///
/// 处理复制宝石塔防
///
///
protected void CopyTargetTower(PointerInfo pointerInfo)
{
string tstr = getTargetTowerName(pointerInfo);
Tower targetTower = null;
if (tstr.Length > 0)
targetTower = EndlessRandomTower.instance.getTowerByName(tstr);
currentSelectedTower = towerToMove;
if (targetTower)
{
// 1:记录当前Tower的Level,删除当前的Tower.
int towerLvl = currentSelectedTower.currentLevel + 1;
int posx = currentSelectedTower.gridPosition.x;
int posy = currentSelectedTower.gridPosition.y;
currentSelectedTower.Sell();
delTower(currentSelectedTower);
// 在目标位置放置新的Tower类型,只有零级。
RandomPlaceTower(targetTower, posx, posy, 0);
}
}
///
/// Attempt to position a tower at the given location
///
/// The pointer we're using to position the tower
public bool TryPlaceTower(PointerInfo pointerInfo, bool force = false)
{
UIPointer pointer = WrapPointer(pointerInfo);
// Do nothing if we're over UI
if (pointer.overUI && !force)
{
Debug.Log("在UI上了,直接返回");
return false;
}
return BuyTower(pointer, force);
}
///
/// 根据鼠标的点击信息来确认当前点击的位置是否有塔防模型。
///
///
///
protected Tower PickTowerInGrid(UIPointer pointer)
{
RaycastHit output;
bool hasHit = Physics.Raycast(pointer.ray, out output, float.MaxValue, towerSelectionLayer);
if (!hasHit || pointer.overUI)
{
return null;
}
var controller = output.collider.GetComponent();
return controller;
}
private Vector2 dragOffect = new Vector2(0, -55f);
///
/// Position the ghost tower at the given pointer
///
/// The pointer we're using to position the tower
/// Optional parameter for configuring if the ghost is hidden when in an invalid location
public void TryMoveGhost(PointerInfo pointerInfo, bool hideWhenInvalid = true)
{
if (m_CurrentTower == null)
{
return;
//throw new InvalidOperationException("Trying to move the tower ghost when we don't have one");
}
// 我操,终于可以了!ATTENTION TO OPP:
PointerInfo tp = new PointerActionInfo();
tp.currentPosition = pointerInfo.currentPosition + dragOffect;
tp.previousPosition = pointerInfo.previousPosition;
tp.delta = pointerInfo.delta;
tp.startedOverUI = pointerInfo.startedOverUI;
UIPointer npt = new UIPointer
{
overUI = false,
pointer = tp,
overWaveLine = false,
ray = m_Camera.ScreenPointToRay(tp.currentPosition)
};
//UIPointer pointer = WrapPointer(tp);
// Do nothing if we're over UI
if (npt.overUI && hideWhenInvalid)
{
m_CurrentTower.Hide();
return;
}
MoveGhost(npt, hideWhenInvalid);
}
///
/// Activates the tower controller UI with the specific information
///
///
/// The tower controller information to use
///
///
/// Throws exception when selecting tower when does not equal
///
public void SelectTower(Tower tower)
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to select whilst not in a normal state");
}
DeselectTower();
currentSelectedTower = tower;
if (currentSelectedTower != null)
{
currentSelectedTower.removed += OnTowerDied;
}
startDragTower(tower);
}
///
/// 在当前的PlaceArea内删除有相同LvL相同类型的防塔.
///
///
public bool deleteSameLvlTower(Tower tower)
{
Tower delTower = findSameLvlTower(tower);
if (delTower == null) return false;
Tower backT = currentSelectedTower;
currentSelectedTower = delTower;
SellSelectedTower();
currentSelectedTower = backT;
return true;
}
///
/// Upgrades , if possible
///
///
/// Throws exception when selecting tower when does not equal
/// or is null
///
public void UpgradeSelectedTower()
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to upgrade whilst not in Normal state");
}
if (currentSelectedTower == null)
{
throw new InvalidOperationException("Selected Tower is null");
}
if (currentSelectedTower.IsMaxLevel)
{
return;
}
currentSelectedTower.UpgradeTower();
DeselectTower();
}
///
/// 当前的塔防随机升级为另一种塔防的种类。
///
protected bool randomUpgradeTower()
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to upgrade whilst not in Normal state");
}
if (currentSelectedTower == null)
{
throw new InvalidOperationException("Selected Tower is null");
}
if (currentSelectedTower.IsMaxLevel)
return false;
// 直接随机升级,零成本。
// 1:记录当前Tower的Level,删除当前的Tower. 2:从TowerLib中随机找一个高一级别的Tower.
string towerName = currentSelectedTower.towerName;
if (currentSelectedTower.towerFeature == EFeatureTower.NULL && GameConfig.CreateRandomTower)
towerName = "";
int towerLvl = currentSelectedTower.currentLevel + 1;
int posx = currentSelectedTower.gridPosition.x;
int posy = currentSelectedTower.gridPosition.y;
currentSelectedTower.Sell();
delTower(currentSelectedTower);
// 随机放置一个新的Tower
EndlessRandomTower.instance.randomTower(posx, posy, towerLvl, towerName);
DeselectTower();
return true;
}
///
/// Sells if possible
///
///
/// Throws exception when selecting tower when does not equal
/// or is null
///
public void SellSelectedTower()
{
if (state != State.Normal)
{
throw new InvalidOperationException("Trying to sell tower whilst not in Normal state");
}
if (currentSelectedTower == null)
{
throw new InvalidOperationException("Selected Tower is null");
}
currentSelectedTower.Sell();
// 从列表中删除Tower.
delTower(currentSelectedTower);
DeselectTower();
}
///
/// Buys the tower and places it in the place that it currently is
///
///
/// Throws exception if trying to buy towers in Build Mode
///
public void BuyTower()
{
if (!isBuilding)
{
throw new InvalidOperationException("Trying to buy towers when not in Build Mode");
}
if (m_CurrentTower == null || !IsGhostAtValidPosition())
{
return;
}
PlaceTower();
}
///
/// Used to buy the tower during the build phase
/// Checks currency and calls
///
/// Throws exception when not in a build mode or when tower is not a valid position
///
///
public bool BuyTower(UIPointer pointer, bool force = false)
{
if (!isBuilding) return false;
//Debug.Log("开始造塔" + m_GridPosition);
// 判断是否格子上重复放置塔防
if (!m_CurrentTower || !IsGhostAtValidPosition())
{
// 判断格子上的塔防:
Tower sTower = PickTowerInGrid(pointer);
if (sTower)
{
Tower curTower = m_CurrentTower.controller;
int testLvl = dragTowerLevel;
if ((sTower.currentLevel == testLvl) &&
(sTower.towerName == curTower.towerName))
{
// 先释放掉当前的Ghost塔防.
CancelGhostPlacement();
// 升级目标位置的塔防.
currentSelectedTower = sTower;
SetState(State.Normal);
// 新的代码,合并升级为随机塔防类型.
randomUpgradeTower();
}
}
else
{
// 放置攻击塔位
PlacementAreaRaycast(ref pointer);
if (!pointer.raycast.HasValue || pointer.raycast.Value.collider == null)
{
CancelGhostPlacement();
return false;
}
PlaceGhost(pointer);
}
return true;
}
// 这是判断是否超出了格子
PlacementAreaRaycast(ref pointer, force);
if (!pointer.raycast.HasValue || pointer.raycast.Value.collider == null)
{
CancelGhostPlacement();
return false;
}
bool successfulPurchase = EndlessLevelManager.instance.Currency.TryPurchase(0);
if (successfulPurchase)
{
PlaceGhost(pointer);
}
return true;
}
///
/// 播放升级特效
///
///
public void PlayUpgradeEffect(Tower newTower)
{
newTower.CurrentTowerLevel.PlayUpGradeEffect();
AudioSourceManager.Ins.Play(AudioEnum.Upgrade);
}
///
/// Deselect the current tower and hides the UI
///
public void DeselectTower()
{
if (currentSelectedTower != null)
{
currentSelectedTower.removed -= OnTowerDied;
}
currentSelectedTower = null;
if (selectionChanged != null)
{
selectionChanged(null);
}
}
///
/// Checks the position of the
/// on the
///
///
/// True if the placement is valid
///
///
/// Throws exception if the check is done in state
///
public bool IsGhostAtValidPosition(bool opponent = false)
{
if (m_CurrentTower == null || m_CurrentArea == null)
return false;
TowerFitStatus fits = m_CurrentArea.Fits(m_GridPosition, m_CurrentTower.controller.dimensions);
return fits == TowerFitStatus.Fits;
}
///
/// Checks if buying the ghost tower is possible
///
///
/// True if can purchase
///
///
/// Throws exception if not in Build Mode or Build With Dragging mode
///
public bool IsValidPurchase()
{
if (!isBuilding)
{
throw new InvalidOperationException("Trying to check ghost position when not in a build mode");
}
if (m_CurrentTower == null || m_CurrentArea == null)
return false;
return true;
}
///
/// Places a tower where the ghost tower is
///
///
/// Throws exception if not in Build State or is not at a valid position
///
public void PlaceTower(int lvl = 0, bool isUpgrade = false, bool opponent = false, bool isFirstAppear = false)
{
if (!isBuilding)
throw new InvalidOperationException("Trying to place tower when not in a Build Mode");
if (lvl <= 0)
{
if (!IsGhostAtValidPosition(opponent))
throw new InvalidOperationException("Trying to place tower on an invalid area");
}
if (m_CurrentArea == null)
return;
Tower createdTower = Instantiate(m_CurrentTower.controller);
createdTower.opponentSide = opponent;
createdTower.Initialize(m_CurrentArea, m_GridPosition, lvl);
// River: 内部缓存数据,用于后期容易找到数据.
addTower(createdTower);
CancelGhostPlacement();
if (isFirstAppear)
{
PlayFirstAppearEffect(createdTower.towerName, createdTower.transform.position);
}
else if (!isUpgrade)
{
PlayAppearEffect(createdTower.transform.position);
}
else
{
PlayUpgradeEffect(createdTower);
}
// 处理成长骰子,复制骰子等等功能.
if (lvl == 0)
{
ProcessFeatureTower(createdTower);
}
}
///
/// 播放首次宝石出现特效
///
public void PlayFirstAppearEffect(string towerName, Vector3 worldPos)
{
if (towerName.StartsWith("GrowUpTower"))
{
//火元素
PlayAppearEffect(worldPos, fireAppearEffect1);
//PlayAppearEffect(worldPos, fireAppearEffect2);
if (Application.platform == RuntimePlatform.WindowsEditor)
{
//UnityEditor.EditorApplication.isPaused = true;
}
}
else if (towerName.StartsWith("BlinkTower"))
{
//木元素
PlayAppearEffect(worldPos, woodAppearEffect1);
//PlayAppearEffect(worldPos, woodAppearEffect2);
}
else if (towerName.StartsWith("CopyCatTower"))
{
//水元素
PlayAppearEffect(worldPos, waterAppearEffect1);
//PlayAppearEffect(worldPos, waterAppearEffect2);
}
}
void PlayAppearEffect(Vector3 worldPos, GameObject prefab)
{
GameObject obj = Instantiate(prefab);
obj.transform.position = worldPos;
Vector3 pos = obj.transform.position;
pos.y += 5f;
obj.transform.position = pos;
ParticleSystem ps = obj.GetComponent();
if (ps == null)
ps = obj.transform.GetChild(0).GetComponent();
ps.Play();
Destroy(obj, ps.main.duration);
}
public void PlayAppearEffectGuide(Vector3 worldPos)
{
GameObject obj = Instantiate(TowerAppearEffectPrefabGuide);
obj.transform.position = worldPos;
Vector3 pos = obj.transform.position;
pos.y += 5f;
obj.transform.position = pos;
ParticleSystem ps = obj.GetComponent();
if (ps == null)
ps = obj.transform.GetChild(0).GetComponent();
ps.Play();
Destroy(obj, ps.main.duration);
}
///
/// 播放宝石出现特效
///
public void PlayAppearEffect(Vector3 worldPos)
{
GameObject obj = Instantiate(TowerAppearEffectPrefab);
obj.transform.position = worldPos;
Vector3 pos = obj.transform.position;
pos.y += 5f;
obj.transform.position = pos;
ParticleSystem ps = obj.GetComponent();
if (ps == null)
ps = obj.transform.GetChild(0).GetComponent();
ps.Play();
Destroy(obj, ps.main.duration);
}
///
/// 播放升级特效
///
///
public void GuidePlayUpgradeEffect(Vector3 position)
{
// 在sTower的位置播放升级特效
GameObject obj = Instantiate(TowerUpgradeEffectPrefabGuide);
obj.transform.position = position;
Vector3 pos = obj.transform.position;
pos.y += 5f;
obj.transform.position = pos;
ParticleSystem ps = obj.GetComponent();
if (ps == null)
ps = obj.transform.GetChild(0).GetComponent();
ps.Play();
Destroy(obj, ps.main.duration);
}
protected void ProcessFeatureTower(Tower ctower)
{
if (ctower.towerFeature == EFeatureTower.GrowUp)
{
Timer timer = new Timer(10.0f, () => { growUpTower(ctower); });
listTowerTimer.Add(timer);
towerTimeDic.Add(timer.timerID, ctower);
}
else if (ctower.towerFeature == EFeatureTower.CopyCat)
{
}
return;
}
///
/// 成功购买塔防后,更新价格,更新按钮,更新按钮上的塔防价格等等.
///
protected void OnSuccessBuyTower()
{
var tpMgr = TowerPrice.instance;
if (!tpMgr) return;
// 价格更新
tpMgr.onTowerBuySuccess();
if (!towerPriceText)
{
towerPriceText = randomTowerBtn.transform.Find("cashText").GetComponent();
//towerPriceText1 = SkillTowerBtn.transform.Find("cashText").GetComponent();
if (towerPriceText)
towerPriceText.text = tpMgr.currentTowerPrice.ToString();
// if (towerPriceText1)
// towerPriceText1.text = tpMgr.currentTowerPrice.ToString();
}
else
{
towerPriceText.text = tpMgr.currentTowerPrice.ToString();
//towerPriceText1.text = tpMgr.currentTowerPrice.ToString();
}
// 无法支付新的塔防价格,按钮变灰.
if (tpMgr.currentTowerPrice > EndlessLevelManager.instance.Currency.currentCurrency)
{
disableRandomTowerBtn();
}
}
///
/// 随机放置Tower按钮禁止使用,灰掉.
///
public void disableRandomTowerBtn()
{
randomTowerBtn.GetComponent().ChangeBtnClick();
//randomTowerBtn.interactable = false;
if (towerPriceText)
{
towerPriceText.color = new Color(0.5f, 0.5f, 0.5f);
//towerPriceText1.color = new Color(0.5f, 0.5f, 0.5f);
}
tdBuyDisable = true;
}
///
/// 随机购买Tower的按钮重设置为有效.
///
public void enableRandomTowerBtn()
{
// ATTENTION TO FIX: 再次判断是因为有的地方是直接调用
if ((TowerPrice.instance.currentTowerPrice > EndlessLevelManager.instance.Currency.currentCurrency) ||
(m_listTower.Count >= MAX_TOWERNUM))
return;
if (towerPriceText)
{
towerPriceText.color = new Color(1.0f, 1.0f, 1.0f);
//towerPriceText1.color = new Color(1.0f, 1.0f, 1.0f);
}
if (randomTowerBtn)
{
randomTowerBtn.GetComponent().ChangeBtnClickNormal();
//randomTowerBtn.interactable = true;
}
tdBuyDisable = false;
}
///
/// 游戏内向上飘血
///
///
///
///
public void generateBloodText(Vector3 wpos, float val, bool crit = false, bool doubleHit = false, bool poison = false)
{
if (Mathf.FloorToInt(val) == 0) return;
Vector3 spos = m_Camera.WorldToScreenPoint(wpos);
TextMoveDoTween tm;
if (crit)
{
tm = Poolable.TryGetPoolable(bloodCrit.gameObject);
}
else if (poison)
{
tm = Poolable.TryGetPoolable(bloodPoison.gameObject);
}
else
{
tm = Poolable.TryGetPoolable(bloodText.gameObject);
}
if (tm)
{
tm.GetComponent().SetParent(GameObject.Find("MainUI/TextPanel").GetComponent(), true);
string bloodStr = "-";
bloodStr += ((Int64)val).ToString();
tm.moveBloodText(spos.x, spos.y, bloodStr, crit);
}
}
///
/// 减速飘字
///
public void FloatSlowDownWord(Vector3 worldPos)
{
Vector3 screenPos = m_Camera.WorldToScreenPoint(worldPos);
GameObject obj = Instantiate(SlowDownWord.gameObject);
obj.GetComponent().SetParent(GameObject.Find("MainUI/TextPanel").GetComponent(), false);
obj.GetComponent().FloatSlowDownWord(screenPos.x, screenPos.y);
}
///
/// 暴击飘字
///
public void FloatCritWord(Vector3 worldPos)
{
Vector3 screenPos = m_Camera.WorldToScreenPoint(worldPos);
GameObject obj = Instantiate(CritWord.gameObject);
obj.GetComponent().SetParent(GameObject.Find("MainUI/TextPanel").GetComponent(), false);
obj.GetComponent().FloatCritWord(screenPos.x, screenPos.y);
}
///
/// 冰冻飘字
///
///
public void FloatFrostWord(Vector3 worldPos)
{
Vector3 screenPos = m_Camera.WorldToScreenPoint(worldPos);
GameObject obj = Instantiate(FrostWord.gameObject);
obj.GetComponent().SetParent(GameObject.Find("MainUI/TextPanel").GetComponent(), false);
obj.GetComponent().FloatFrostWord(screenPos.x, screenPos.y);
}
///
/// 克制飘字
///
///
public void FloatRestrainWord(Vector3 worldPos)
{
Vector3 screenPos = m_Camera.WorldToScreenPoint(worldPos);
GameObject obj = Instantiate(RestrainWord.gameObject);
obj.GetComponent().SetParent(GameObject.Find("MainUI/TextPanel").GetComponent(), false);
obj.GetComponent().FloatRestrainWord(screenPos.x, screenPos.y);
}
private void Start()
{
// 获取相应的放置区域。
GameObject placeObj = GameObject.FindGameObjectWithTag("PlaceTower");
if (placeObj != null)
{
m_CurrentArea = placeObj.GetComponent();
dragTowerPlacement = placeObj.GetComponent() as TowerPlacementGridEndless;
}
//placeObj = GameObject.FindGameObjectWithTag("PlaceTowerOpponent");
EventCenter.Ins.Add((int)KTGMGemClient.EventType.EndlessHeartAllLose, AllHeartLose);
EventCenter.Ins.Add((int)KTGMGemClient.EventType.PlayBuffPS, PlayBuffPS);
}
///
/// 替换towerToMove的目标Tower,如果是使用towerToMove,则必须提前处理相应的指针。
///
///
public void DisplaceTower(Tower newTower, Tower oldTower, int lvl = 0)
{
// 先记录oldTower的位置信息:
int posx = oldTower.gridPosition.x;
int posy = oldTower.gridPosition.y;
bool opponent = oldTower.opponentSide;
int newLvl = oldTower.currentLevel + 1;
if (newLvl > 4) newLvl = 4;
delTower(oldTower);
oldTower.showTower(true);
oldTower.Sell();
// 减化成长塔位对应的代码,用于不再影响目前正处于建设状态的塔位.
if (m_CurrentArea == null)
return;
IntVector2 ivec;
ivec.x = posx;
ivec.y = posy;
Tower createdTower = Instantiate(newTower);
createdTower.opponentSide = opponent;
createdTower.Initialize(m_CurrentArea, ivec, newLvl);
// River: 内部缓存数据,用于后期容易找到数据.
addTower(createdTower);
}
///
/// 直接在IPlaceArea上随机放置一个Tower。这是随机放置塔防的入口类。这是入口的塔防类。
///
///
public bool RandomPlaceTower(Tower tow, int posx = -1, int posy = -1, int lvl = 0, int forceCost = -1, bool isUpgrade = false, bool isFirstAppear = false)
{
// 获取IPlaceArea.
if (m_CurrentArea == null)
{
GameObject placeObj = GameObject.FindGameObjectWithTag("PlaceTower");
if (placeObj == null) return false;
// 获取相应的放置区域。
m_CurrentArea = placeObj.GetComponent();
if (m_CurrentArea == null) return false;
}
bool zeroCost = false;
if (posx < 0 && posy < 0)
{
IntVector2 tvec = m_CurrentArea.getFreePos(1, 1);
if (tvec.x < 0 && tvec.y < 0)
return false;
m_GridPosition.x = tvec.x;
m_GridPosition.y = tvec.y;
}
else
{
m_GridPosition.x = posx;
m_GridPosition.y = posy;
zeroCost = true;
}
// 购买成功,才会继续放置塔防:
if (tow.towerGhostPrefab == null)
{
return false;
}
// River: 修改Cost为全局统一维护的数据
int cost = TowerPrice.instance.currentTowerPrice;
if (zeroCost)
cost = 0;
if (forceCost != -1)
cost = forceCost;
bool successfulPurchase = EndlessLevelManager.instance.Currency.TryPurchase(cost);
if (!successfulPurchase) return false;
SetUpGhostTower(tow);
//Debug.Log("设置影子塔防.");
m_CurrentTower.Show();
if (successfulPurchase)
{
++GameConfig.EndlessBuyTowerCount;
// 删除towerToMove,确保塔防数据不再出现多个
if (zeroCost && (towerToMove != null))
{
delTower(towerToMove);
towerToMove.showTower(true);
towerToMove.Sell();
towerToMove = null;
}
// 塔防购买成功后的相关更新:
if (!zeroCost)
OnSuccessBuyTower();
SetState(State.Building);
PlaceTower(lvl, isUpgrade, false, isFirstAppear);
}
return true;
}
///
/// Calculates whether the given pointer is over the current tower ghost
///
///
/// The information used to check against the
///
///
/// Throws an exception if not in Build Mode
///
public bool IsPointerOverGhost(PointerInfo pointerInfo)
{
if (state != State.Building)
{
throw new InvalidOperationException("Trying to tap on ghost tower when not in Build Mode");
}
UIPointer uiPointer = WrapPointer(pointerInfo);
RaycastHit hit;
return m_CurrentTower.ghostCollider.Raycast(uiPointer.ray, out hit, float.MaxValue);
}
///
/// Selects a tower beneath the given pointer if there is one
/// 选择塔防
///
///
/// The pointer information concerning the selector of the pointer
///
///
/// Throws an exception when not in
///
public void TrySelectTower(PointerInfo info)
{
if (state != State.Normal)
{
//throw new InvalidOperationException("Trying to select towers outside of Normal state");
return;
}
UIPointer uiPointer = WrapPointer(info);
RaycastHit output;
// River: Raycast的碰撞是游戏内物品的Collider进行碰撞检测的
bool hasHit = Physics.Raycast(uiPointer.ray, out output, float.MaxValue, towerSelectionLayer);
if (!hasHit || uiPointer.overUI)
{
//Debug.Log("没有点中或者点中了UI:" + hasHit.ToString() + "," + uiPointer.overUI.ToString());
return;
}
Tower controller = output.collider.GetComponent();
if (controller != null)
{
// 泡泡禁锢状态不允许拖动
if (controller.IsStartBondage) return;
SelectTower(controller);
}
// 计算偏移值.
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();
if (controller != null)
controller.OnPressed();
}
}
///
/// 鼠标选中一个Tower的时候,计算当前鼠标位置与当前Tower位置在屏幕上坐标位置的偏移量。
///
///
///
protected void CalSelTowerScreenOffset(PointerInfo info, Tower tower)
{
Vector3 towerCentPos = m_Camera.WorldToScreenPoint(tower.transform.position);
selTowerOffset.x = towerCentPos.x - info.currentPosition.x;
selTowerOffset.y = towerCentPos.y - info.currentPosition.y;
}
///
/// Gets the world position of the ghost tower
///
///
/// Throws an exception when not in the Build Mode or
/// When a ghost tower does not exist
///
public Vector3 GetGhostPosition()
{
if (!isBuilding)
{
throw new InvalidOperationException("Trying to get ghost position when not in a Build Mode");
}
if (m_CurrentTower == null)
{
throw new InvalidOperationException("Trying to get ghost position for an object that does not exist");
}
return m_CurrentTower.transform.position;
}
///
/// Moves the ghost to the center of the screen
///
///
/// Throws exception when not in build mode
///
public void MoveGhostToCenter()
{
if (state != State.Building)
{
throw new InvalidOperationException("Trying to move ghost when not in Build Mode");
}
// try to find a valid placement
Ray ray = m_Camera.ScreenPointToRay(new Vector2(Screen.width * 0.5f, Screen.height * 0.5f));
RaycastHit placementHit;
if (Physics.SphereCast(ray, sphereCastRadius, out placementHit, float.MaxValue, placementAreaMask))
{
MoveGhostWithRaycastHit(placementHit);
}
else
{
MoveGhostOntoWorld(ray, false);
}
}
///
/// Set initial values, cache attached components
/// and configure the controls
///
protected override void Awake()
{
base.Awake();
randomTowerBtn = transform.Find("BottomCanvas/Panel/TowerBuyBtn").GetComponent