628 lines
29 KiB
C#
628 lines
29 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description: 小兵逻辑
|
||
* @Date: 2025年04月01日 星期二 11:04:28
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Logic.Skill;
|
||
using UnityEngine;
|
||
using RuntimeData;
|
||
|
||
namespace Logic
|
||
{
|
||
public class UnitLogic : IUnitLogic
|
||
{
|
||
float[,] MoveInfoCostMap;
|
||
float[,] MoveInfoMap;
|
||
|
||
|
||
public UnitLogic()
|
||
{
|
||
MoveInfoCostMap = new float[Table.Instance.MaxMapSize,Table.Instance.MaxMapSize];
|
||
MoveInfoMap = new float[Table.Instance.MaxMapSize,Table.Instance.MaxMapSize];
|
||
}
|
||
|
||
public void Update()
|
||
{
|
||
|
||
}
|
||
|
||
|
||
//-------- 信息判断类 ---------//
|
||
//判断uid是不是selfplayer的unit
|
||
public bool CheckIsSelfPlayer(MapData mapData, uint uid)
|
||
{
|
||
mapData.GetPlayerDataByUnitId(uid, out var playerData);
|
||
return playerData == mapData.PlayerMap.SelfPlayerData;
|
||
}
|
||
|
||
|
||
//-------- 执行类 --------//
|
||
public bool MoveTo(MapData mapData, UnitData unitData, GridData gridData,bool passive = false)
|
||
{
|
||
mapData.SetUnitIdToGridId(unitData.Id,gridData.Id);
|
||
//如果主动移动会消耗所有类别的行动点数,被动挤出去的移动不算
|
||
if(!passive)
|
||
unitData.MP = unitData.CP = unitData.AP = 0;
|
||
|
||
//如果 land to port
|
||
if (unitData.GetLandType() == LandType.LandAndPort && gridData.Resource == ResourceType.Port)
|
||
LandToBoat(mapData, unitData);
|
||
//如果sea to land
|
||
else if (unitData.GetLandType() == LandType.WaterAndAshore && gridData.Terrain == TerrainType.Land)
|
||
BoatToLand(mapData, unitData);
|
||
//如果sea to sea或者land to land
|
||
else
|
||
//处理DASH等等技能情况,在Move结束时会触发的那些技能
|
||
unitData.OnMove(mapData, gridData);
|
||
|
||
if (!mapData.GetPlayerDataByUnitId(unitData.Id, out var playerData))
|
||
{
|
||
Debug.LogError("unit找不到player");
|
||
return false;
|
||
}
|
||
|
||
// 更新视野情况
|
||
int radius = unitData.GetSightRange();
|
||
if (gridData.Feature == TerrainFeature.Mountain)
|
||
radius = radius < 2 ? 2 : radius;
|
||
Main.PlayerLogic.UpdateSight(mapData,playerData,mapData.GridMap.GetAroundGridIdList(radius,gridData));
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool Attack(MapData mapData, UnitData unit1, UnitData unit2)
|
||
{
|
||
if (!mapData.GetPlayerDataByUnitId(unit1.Id, out var player1)) return false;
|
||
if (!mapData.GetPlayerDataByUnitId(unit2.Id, out var player2)) return false;
|
||
if (!mapData.GetCityDataByUnitId(unit1.Id, out var city1)) return false;
|
||
if (!mapData.GetCityDataByUnitId(unit2.Id, out var city2)) return false;
|
||
if (!mapData.GetGridDataByUnitId(unit1.Id, out var grid1)) return false;
|
||
if (!mapData.GetGridDataByUnitId(unit2.Id, out var grid2)) return false;
|
||
player1.TurnNoAttack = 0;
|
||
|
||
// 计算攻击伤害
|
||
int dmg1 = Table.Instance.CalcDamage(mapData, unit1, unit2);
|
||
int dmg2 = 0;
|
||
bool counter = !Table.Instance.QueryUnitHasSkill(unit2.UnitType, SkillType.STIFF) &&
|
||
mapData.GridMap.CalcDistance(grid1, grid2) <= unit2.GetAttackRange();
|
||
|
||
//计算反击伤害,要给calcDamage额外传入一个true TODO 这里设计可以优化,方法最好拆分
|
||
if (counter) dmg2 = Table.Instance.CalcDamage(mapData, unit1, unit2, true);
|
||
int hpA = unit1.Health;
|
||
int hpB = unit2.Health;
|
||
|
||
//攻击会消耗所有类别的行动点数
|
||
unit1.AP = unit1.CP = unit1.MP = 0;
|
||
|
||
//设置unit1 attackendermark和相关参数
|
||
unit1.AttackRenderMark = true;
|
||
unit1.AttackRenderMarkAttackAnimType = unit1.GetAttackRange() switch
|
||
{
|
||
1 => AttackAnimType.Melee, 2 => AttackAnimType.Arrow, 3 => AttackAnimType.Bomb,
|
||
_ => AttackAnimType.None
|
||
};
|
||
unit1.AttackRenderMarkWaitTime = 0f;
|
||
unit1.AttackRenderMarkTargetPos = Table.Instance.GridToWorld(grid2,"isUnit");
|
||
unit1.AttackRenderMarkNeedBack = true;
|
||
//判断对方能否反击的参数
|
||
bool canCounter;
|
||
canCounter = true;
|
||
//确认对方是否有STIFF技能,有的话无法反击
|
||
if (
|
||
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit2.UnitType,unit2.GiantType,out var info2)
|
||
&& info2.Skills.Contains(SkillType.STIFF))
|
||
canCounter = !unit2.IsLimitSelfCounterAttack(mapData);
|
||
|
||
//确认对方是否有我的视野,没有的话无法反击
|
||
if (!player2.Sight.CheckIsInSight(grid1.Id))
|
||
canCounter = false;
|
||
|
||
//如果对方攻击范围无法覆盖我,则无法反击
|
||
if (Table.Instance.CalcDistance(new Vector2Int(grid1.Pos.X,grid1.Pos.Y),new Vector2Int(grid2.Pos.X,grid2.Pos.Y))
|
||
> unit2.GetAttackRange())
|
||
canCounter = false;
|
||
|
||
if (dmg1 >= unit2.Health) //如果伤害直接够杀死对方
|
||
{
|
||
//关闭unit2的rendermark
|
||
canCounter = false;
|
||
//处理PERSIST技能
|
||
if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit1.UnitType, unit1.GiantType, out var info1)
|
||
&& info1.Skills.Contains(SkillType.PERSIST))
|
||
{
|
||
unit1.AP = 1;
|
||
Debug.Log("这么早就有PERSIST??!!!?");
|
||
}
|
||
unit2.Health -= dmg1;
|
||
//对方死亡 必须先处理死亡,再处理移动,不然gridToUnit的dict会出错
|
||
Main.UnitLogic.Die(mapData, unit2);
|
||
|
||
//如果是近战且目标位置不是山或者有山的科技,且目标不在水里
|
||
if (unit1.GetAttackRange() == 1 && grid2.Terrain == TerrainType.Land
|
||
&& (grid2.Feature != TerrainFeature.Mountain || player1.TechTree.CheckIfHasTech(TechType.Climbing)))
|
||
{
|
||
unit1.AttackRenderMark = false;
|
||
//移动过去并更新视野
|
||
MoveTo(mapData, unit1, grid2);
|
||
//关闭unit1的rendermakr中 攻击完需要移动回来的开关
|
||
//unit1.AttackRenderMarkNeedBack = false;
|
||
}
|
||
|
||
|
||
|
||
|
||
//权力奇观记录
|
||
player1.TotalKill++;
|
||
Main.PlayerLogic.UpdateWonderState(mapData, player1, 4);
|
||
//如果没有STATIC技能,那么就可以增加小兵经验
|
||
if (!Table.Instance.QueryUnitHasSkill(unit1.UnitType, SkillType.STATIC)) unit1.Exp++;
|
||
}
|
||
//如果杀不死对方
|
||
else
|
||
{
|
||
unit2.Health -= dmg1;
|
||
//在attackAnimTime之后,刷新unit2的血量,配合动画演出
|
||
Timer.Instance.TimerRegister(unit2,()=> { unit2.RenderMark = true; },
|
||
Table.Instance.AnimDataAssets.AttackAnimTime);
|
||
//处理反击情况,设置unit2的rendermark
|
||
unit2.AttackRenderMark = canCounter;
|
||
if (canCounter)
|
||
{
|
||
unit2.AttackRenderMarkWaitTime = 0.4f;
|
||
unit2.AttackRenderMarkAttackAnimType = unit2.GetAttackRange() switch
|
||
{
|
||
1 => AttackAnimType.Melee, 2 => AttackAnimType.Arrow, 3 => AttackAnimType.Bomb,
|
||
_ => AttackAnimType.None
|
||
};
|
||
unit2.AttackRenderMarkTargetPos = Table.Instance.GridToWorld(grid1,"isUnit");
|
||
unit2.AttackRenderMarkNeedBack = true;
|
||
|
||
//如果会被反击至死
|
||
if (dmg2 >= unit1.Health)
|
||
{
|
||
unit1.Health -= dmg2;
|
||
//我方死亡
|
||
float tt = Table.Instance.AnimDataAssets.AttackAnimTime +
|
||
Table.Instance.AnimDataAssets.BetweenAttackCounterAnimTime +
|
||
Table.Instance.AnimDataAssets.AttackReturnAnimTime;
|
||
//在tt时间之后,处理unit1的死亡
|
||
Timer.Instance.TimerRegister(Main.UnitLogic,()=> { Main.UnitLogic.Die(mapData, unit1);}, tt);
|
||
|
||
}
|
||
//否则,就是双方正常互相消耗血量
|
||
else
|
||
{
|
||
unit1.Health -= dmg2;
|
||
float tt = Table.Instance.AnimDataAssets.AttackAnimTime +
|
||
Table.Instance.AnimDataAssets.BetweenAttackCounterAnimTime +
|
||
Table.Instance.AnimDataAssets.AttackReturnAnimTime;
|
||
Timer.Instance.TimerRegister(unit1,()=> { unit1.RenderMark = true; }, tt);
|
||
}
|
||
}
|
||
|
||
}
|
||
//处理 ESCAPE 和 SPLASH 技能 OnAttack
|
||
unit1.OnAttack(mapData, unit2, dmg1);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 伤害
|
||
public void Damage(MapData mapData, UnitData unit1, UnitData unit2, int dmg)
|
||
{
|
||
if (!mapData.GetPlayerDataByUnitId(unit1.Id, out var player1)) return;
|
||
|
||
// 尝试击杀
|
||
if (TryKillUnit(mapData, unit1, unit2, dmg))
|
||
{
|
||
// 权力奇观记录
|
||
player1.TotalKill++;
|
||
// 尝试增加小兵经验
|
||
if (!unit1.IsExpLock(mapData))unit1.Exp++;
|
||
return;
|
||
}
|
||
|
||
// 尝试伤害
|
||
TryDamageUnit(mapData, unit1, unit2, dmg);
|
||
}
|
||
|
||
public bool TryKillUnit(MapData mapData, UnitData origin, UnitData target, int dmg)
|
||
{
|
||
if (dmg < target.Health) return false;
|
||
if (!target.CanBeKilled(mapData)) return false;
|
||
|
||
// 伤害超过血量时会溢出,伤害 = 总掉血量
|
||
dmg = target.Health;
|
||
target.Health = 0;
|
||
foreach (var skill in target.Skills) skill.OnDamage(target, origin, mapData, dmg);
|
||
foreach (var skill in target.Skills) skill.OnDeath(target, origin, mapData);
|
||
foreach (var skill in origin.Skills) skill.OnDamageOther(origin, target, mapData, dmg);
|
||
foreach (var skill in origin.Skills) skill.OnKill(origin, target, mapData);
|
||
mapData.OnUnitDamage(target);
|
||
Main.UnitLogic.Die(mapData, target);
|
||
return true;
|
||
}
|
||
|
||
public bool TryDamageUnit(MapData mapData, UnitData origin, UnitData target, int dmg)
|
||
{
|
||
target.Health -= dmg;
|
||
foreach (var skill in target.Skills) skill.OnDamage(target, origin, mapData, dmg);
|
||
foreach (var skill in origin.Skills) skill.OnDamageOther(origin, target, mapData, dmg);
|
||
mapData.OnUnitDamage(target);
|
||
return true;
|
||
}
|
||
|
||
public void DebugOutputMoveInfo(MapData mapData)
|
||
{
|
||
string t = "\n";
|
||
for (int i = (int)mapData.MapConfig.Width - 1; i >= 0; i--)
|
||
{
|
||
|
||
for (int j = (int)mapData.MapConfig.Height - 1; j >= 0; j--)
|
||
if (MoveInfoMap[i, j] < 0)
|
||
t += "@";
|
||
else t += ((int)MoveInfoMap[i, j]).ToString();
|
||
|
||
t += "\n";
|
||
}
|
||
|
||
Debug.Log(t);
|
||
}
|
||
|
||
// 判断我方单位是否可以移动到某个格子上, 不考虑视野信息
|
||
public bool CheckUnitCanMoveToGrid(MapData map, PlayerData self, GridData grid)
|
||
{
|
||
if (grid.Feature == TerrainFeature.Mountain && !self.TechTree.CheckIfHasTech(TechType.Climbing)) return false;
|
||
if (grid.Terrain == TerrainType.ShallowSea && !self.TechTree.CheckIfHasTech(TechType.Fishing)) return false;
|
||
if (grid.Terrain == TerrainType.DeepSea && !self.TechTree.CheckIfHasTech(TechType.Sailing)) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
//计算单位移动或者攻击的网格数组,存储在InfoMap中,方便后续判断使用,是一个需要立刻使用的,非长久存储的临时infomap
|
||
public void CalcUnitMoveInfo(MapData mapData, uint uid)
|
||
{
|
||
mapData.UnitMap.GetUnitDataByUnitId(uid, out var unitData);
|
||
mapData.GetPlayerDataByUnitId(uid, out var playerData);
|
||
mapData.GetGridDataByUnitId(uid, out var gridData);
|
||
int width = (int)mapData.MapConfig.Width;
|
||
int height = (int)mapData.MapConfig.Height;
|
||
|
||
//根据地形先设置好costMap基础信息,MoveInfoCostMap = -1表示不可抵达
|
||
foreach (var targetGridData in mapData.GridMap.GridList)
|
||
{
|
||
int i = targetGridData.Pos.X, j = targetGridData.Pos.Y;
|
||
if (playerData.Sight.CheckIsInSight(targetGridData.Id))
|
||
//如果是陆地单位
|
||
if (unitData.GetLandType() == LandType.LandAndPort)
|
||
{
|
||
MoveInfoCostMap[i, j] = 1;
|
||
if (targetGridData.Vegetation == Vegetation.Trees)
|
||
MoveInfoCostMap[i, j] = 2;
|
||
if (targetGridData.Feature == TerrainFeature.Mountain)
|
||
MoveInfoCostMap[i, j] = playerData.TechTree.CheckIfHasTech(TechType.Climbing) ? 3 : -1;
|
||
if (targetGridData.Terrain == TerrainType.ShallowSea)
|
||
{
|
||
if (!playerData.TechTree.CheckIfHasTech(TechType.Fishing))
|
||
MoveInfoCostMap[i, j] = -1;
|
||
else if (targetGridData.Resource == ResourceType.Port)
|
||
MoveInfoCostMap[i, j] = 999;
|
||
else if (targetGridData.Resource == ResourceType.Bridge)
|
||
MoveInfoCostMap[i, j] = 1;
|
||
else MoveInfoCostMap[i, j] = -1;
|
||
}
|
||
|
||
if (targetGridData.Terrain == TerrainType.DeepSea)
|
||
MoveInfoCostMap[i, j] = -1;
|
||
}
|
||
//如果是水上单位
|
||
else
|
||
{
|
||
if (targetGridData.Terrain == TerrainType.DeepSea)
|
||
MoveInfoCostMap[i, j] = playerData.TechTree.CheckIfHasTech(TechType.Sailing) ? 1 : -1;
|
||
else if (targetGridData.Terrain == TerrainType.ShallowSea)
|
||
MoveInfoCostMap[i, j] = 1;
|
||
else
|
||
{
|
||
MoveInfoCostMap[i, j] = 999;
|
||
if (targetGridData.Feature == TerrainFeature.Mountain && !playerData.TechTree.CheckIfHasTech(TechType.Climbing))
|
||
MoveInfoCostMap[i, j] = -1;
|
||
}
|
||
}
|
||
//没有视野,那就不可抵达
|
||
else
|
||
MoveInfoCostMap[i, j] = -1;
|
||
}
|
||
//将所有敌人的控制区的costMap设置为999
|
||
foreach (UnitData B in mapData.UnitMap.UnitList)
|
||
{
|
||
if (!B.Alive)
|
||
continue;
|
||
mapData.GetPlayerDataByUnitId(B.Id, out var playerDataB);
|
||
mapData.GetGridDataByUnitId(B.Id, out var gridDataB);
|
||
if (playerDataB == playerData)
|
||
continue;
|
||
var targetGridDataList = mapData.GridMap.GetAroundGridDataSet(1,1,gridDataB);
|
||
foreach (var targetGridData in targetGridDataList)
|
||
{
|
||
int x = targetGridData.Pos.X, y = targetGridData.Pos.Y;
|
||
MoveInfoCostMap[x, y] = (MoveInfoCostMap[x, y] < 0) ? -1 : 999;
|
||
}
|
||
}
|
||
|
||
//初始化infomap,<0表示不可达,<0.1则不再扩展,>0.1表示可以向附近扩展
|
||
for (int i = 0; i < width; i++)
|
||
for (int j = 0; j < height; j++)
|
||
MoveInfoMap[i, j] = -1;
|
||
|
||
MoveInfoMap[gridData.Pos.X,gridData.Pos.Y] = unitData.GetMoveRange();
|
||
|
||
//然后进行SPFA更新最短路
|
||
Queue<uint> q = new Queue<uint>();
|
||
//breakTime用来放置负边死循环情况
|
||
int breakTime = Mathf.Min(10000000, width * height * width * height);
|
||
q.Enqueue(gridData.Id);
|
||
while (breakTime > 0 && q.Count > 0)
|
||
{
|
||
breakTime--;
|
||
if (!mapData.GridMap.GetGridDataByGid(q.Dequeue(), out var gridDataX))
|
||
continue;
|
||
if (MoveInfoMap[gridDataX.Pos.X, gridDataX.Pos.Y] < 0.1f) continue;
|
||
var nearby = mapData.GridMap.GetAroundGridDataSet(1,1,gridDataX);
|
||
foreach (var gridDataY in nearby)
|
||
{
|
||
|
||
|
||
float cost = MoveInfoCostMap[gridDataY.Pos.X, gridDataY.Pos.Y];
|
||
//如果不可达区
|
||
if (cost <= 0)continue;
|
||
//如果是陆地单位,看是否需要减去道路或者桥梁的行动力加成。道路是非敌人领地才行
|
||
if (unitData.GetLandType() == LandType.LandAndPort &&
|
||
Main.PlayerLogic.HasRoadForUnit(mapData, gridDataX, gridDataY, unitData))
|
||
cost = 0.5f;
|
||
//cost -= 0.5f + (gridDataY.Vegetation == Vegetation.Trees ? 1f : 0f);
|
||
//如果能够发生更新
|
||
if (Mathf.Max(MoveInfoMap[gridDataX.Pos.X, gridDataX.Pos.Y] - cost, 0f) > MoveInfoMap[gridDataY.Pos.X, gridDataY.Pos.Y])
|
||
{
|
||
MoveInfoMap[gridDataY.Pos.X, gridDataY.Pos.Y] = Mathf.Max(MoveInfoMap[gridDataX.Pos.X, gridDataX.Pos.Y] - cost, 0f);
|
||
//如果xy不再队列里,并且还剩余有行动力,就加入队列
|
||
if (!q.Contains(gridDataY.Id) && MoveInfoMap[gridDataY.Pos.X, gridDataY.Pos.Y] > 0.1f)
|
||
q.Enqueue(gridDataY.Id);
|
||
}
|
||
}
|
||
}
|
||
|
||
//检测有没有特别离谱的MoveInfo
|
||
for (int i = 0; i < width; i++)
|
||
for (int j = 0; j < height; j++)
|
||
if(MoveInfoMap[i, j] >= 0 && Table.Instance.CalcDistance(new Vector2Int(gridData.Pos.X,gridData.Pos.Y),new Vector2Int(i,j)) > 5)
|
||
Debug.Log("OWATAA!@!!!!!");
|
||
//DebugOutputMoveInfo();
|
||
}
|
||
|
||
// 检查单位是否能攻击目标点
|
||
public bool CheckUnitCanAttackPos(MapData mapData, UnitData unitData, GridData gridData)
|
||
{
|
||
if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitData.UnitType,unitData.GiantType,out var info)
|
||
&& info.Attack <= 0) return false;
|
||
if (!mapData.GetGridDataByUnitId(unitData.Id, out var originGrid)) return false;
|
||
if (!mapData.GetUnitDataByGid(gridData.Id, out var targetUnit)) return false;
|
||
if(!mapData.GetPlayerDataByUnitId(unitData.Id, out var player)) return false;
|
||
if(!mapData.GetPlayerDataByUnitId(targetUnit.Id, out var targetPlayer)) return false;
|
||
if (player == targetPlayer) return false;
|
||
if (mapData.GridMap.CalcDistance(gridData, originGrid) > unitData.GetAttackRange()) return false;
|
||
return true;
|
||
}
|
||
|
||
// None, Move, Attack, MoveToPort, MoveAshore
|
||
public MoveAttackType CheckUnitCanMoveOrAttack(MapData mapData, UnitData unitDataA, GridData gridDataB)
|
||
{
|
||
//默认在调用这个函数前已经调用了 CalcUnitMoveInfo(A),计算好了。不组合使用是不行的
|
||
mapData.GetGridDataByUnitId(unitDataA.Id,out var gridDataA);
|
||
//如果目标位置有单位
|
||
if(mapData.GetUnitDataByGid(gridDataB.Id,out var unitDataB))
|
||
{
|
||
mapData.GetPlayerDataByUnitId(unitDataA.Id, out var playerDataA);
|
||
mapData.GetPlayerDataByUnitId(unitDataB.Id, out var playerDataB);
|
||
//如果目标位置上面有友军单位,那不可移动也不可攻击
|
||
if (playerDataA == playerDataB)
|
||
return MoveAttackType.None;
|
||
//如果目标位置上面有敌军单位,那不可移动,但是有可能可以攻击
|
||
else if (mapData.GridMap.CalcDistance(gridDataA, gridDataB) <= unitDataA.GetAttackRange() &&
|
||
Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitDataA.UnitType, unitDataA.GiantType,
|
||
out var info)
|
||
&& info.Attack > 0) //判断距离在攻击距离范围内,且攻击大于0,就可以攻击
|
||
{
|
||
if(mapData.GridMap.CalcDistance(gridDataA, gridDataB) > 3)
|
||
Debug.Log("异常的攻击距离");
|
||
return MoveAttackType.Attack; //返回可以攻击
|
||
}
|
||
|
||
else //不在攻击范围内,不可以攻击
|
||
return MoveAttackType.None;
|
||
}
|
||
//如果目标位置没有任何单位
|
||
else
|
||
{
|
||
if (MoveInfoMap[gridDataB.Pos.X, gridDataB.Pos.Y] < 0f) //去不了直接返回
|
||
return MoveAttackType.None;
|
||
if (gridDataB.Terrain == TerrainType.ShallowSea && unitDataA.GetLandType() == LandType.LandAndPort) //下港口
|
||
return MoveAttackType.MoveToPort;
|
||
if (gridDataB.Terrain == TerrainType.Land && unitDataA.GetLandType() == LandType.WaterAndAshore) //上岸
|
||
return MoveAttackType.MoveAshore;
|
||
return MoveAttackType.Move;
|
||
}
|
||
return MoveAttackType.None;
|
||
}
|
||
|
||
//判断当前 unit 附近有多少个单位可以攻击
|
||
public int AttackTargetCount(MapData mapData, UnitData unitData)
|
||
{
|
||
if (!mapData.GetGridDataByUnitId(unitData.Id, out var gridData)) return 0;
|
||
|
||
int ret = 0;
|
||
int r = Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitData.UnitType,unitData.GiantType,out var info)
|
||
? info.AttackRange : 0;
|
||
var aroundGridList = mapData.GridMap.GetAroundGridData(r, r, gridData);
|
||
foreach (var aroundGrid in aroundGridList)
|
||
{
|
||
if (CheckUnitCanAttackPos(mapData, unitData, aroundGrid)) ret++;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
// 找某个点位的 Unit
|
||
public UnitData FindUnitOnPos(MapData mapData, GridData gridData)
|
||
{
|
||
mapData.GetUnitDataByGid(gridData.Id, out var unitData);
|
||
return unitData;
|
||
}
|
||
|
||
public void Upgrade(MapData mapData, UnitData u)
|
||
{
|
||
/*
|
||
u.veteran = true;
|
||
u.health = u.maxHealth + 5;
|
||
RenderUpdateManager.Instance.AddUnitRUList(u.unitId);
|
||
*/
|
||
}
|
||
|
||
public void AddMPAPCP(MapData mapData, UnitData unitData)
|
||
{
|
||
unitData.MP = 1;
|
||
unitData.AP = 1;
|
||
unitData.CP = 1;
|
||
}
|
||
|
||
//判断该unit是不是selfPlayer的unit
|
||
|
||
//unit[uid]原地休息
|
||
public void Recover(MapData mapData, UnitData unitData) { }
|
||
|
||
//unit[uid]进阶成为shipType类型的单位
|
||
public void TransformToShip(MapData mapData, UnitData unitData, UnitType shipType) { }
|
||
|
||
//unit[uid]从陆地进入港口,变为boat
|
||
public void LandToBoat(MapData mapData, UnitData unitData)
|
||
{
|
||
unitData.CarryUnitType = unitData.UnitType;
|
||
unitData.UnitType = UnitType.Boat;
|
||
unitData.CarryExp = unitData.Exp;
|
||
unitData.Exp = 0;
|
||
unitData.CarryVeteran = unitData.Veteran;
|
||
unitData.Veteran = false;
|
||
//unitData.MoveRange = Table.Instance.UnitInfoDict[UnitType.Boat].MoveRange;
|
||
//unitData.AttackRange = Table.Instance.UnitInfoDict[UnitType.Boat].AttackRange;
|
||
unitData.RenderMark = true;
|
||
}
|
||
|
||
//unit[uid]从港口进入陆地,变为原来的单位
|
||
|
||
public void BoatToLand(MapData mapData, UnitData unitData)
|
||
{
|
||
unitData.UnitType = unitData.CarryUnitType;
|
||
unitData.GiantType = unitData.CarryGiantType;
|
||
unitData.Exp = unitData.CarryExp;
|
||
unitData.Veteran = unitData.CarryVeteran;
|
||
unitData.RenderMark = true;
|
||
}
|
||
|
||
//unit[uid]死亡
|
||
public void Die(MapData mapData, UnitData unitData)
|
||
{
|
||
mapData.SetUnitDataDie(unitData);
|
||
}
|
||
|
||
//unitData开启下一回合
|
||
public void StartNextTurn(MapData mapData, UnitData unitData)
|
||
{
|
||
if (!unitData.Alive)
|
||
return;
|
||
unitData.AP = 1;
|
||
unitData.MP = 1;
|
||
unitData.CP = 1;
|
||
unitData.RenderMark = true;
|
||
}
|
||
|
||
|
||
//unitData转换成另一个UnitType
|
||
public void UnitTypeTransform(UnitData unitData,UnitType targetType)
|
||
{
|
||
unitData.UnitType = targetType;
|
||
}
|
||
|
||
public void PassiveMoveAway(MapData mapData,UnitData unitData)
|
||
{
|
||
if (!mapData.GetGridDataByUnitId(unitData.Id, out var gridData))
|
||
return;
|
||
var gridList = mapData.GridMap.GetAroundGridData(1,1,gridData);
|
||
foreach (var targetGrid in gridList)
|
||
{
|
||
if (targetGrid == gridData)
|
||
continue;
|
||
if (!CheckUnitCanGoOnGrid(mapData, unitData, targetGrid))
|
||
continue;
|
||
//传一个true,表示被动移动,不会扣除MPAPCP
|
||
MoveTo(mapData,unitData,targetGrid,true);
|
||
return;
|
||
}
|
||
Die(mapData,unitData);
|
||
}
|
||
|
||
public bool CheckUnitCanGoOnGrid(MapData mapData, UnitData unitData, GridData gridData)
|
||
{
|
||
if (!mapData.GetPlayerDataByUnitId(unitData.Id, out var playerData))
|
||
return false;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unitData.UnitType, unitData.GiantType,
|
||
out var unitInfo))
|
||
return false;
|
||
//如果上面有人
|
||
if (mapData.GetUnitDataByGid(gridData.Id, out var tmp))
|
||
return false;
|
||
//如果是水域
|
||
if (gridData.Terrain != TerrainType.Land)
|
||
{
|
||
|
||
if (gridData.Resource == ResourceType.Bridge)
|
||
{
|
||
return true;
|
||
}
|
||
//如果有港口但不能下港口
|
||
if (gridData.Resource == ResourceType.Port)
|
||
{
|
||
if (unitInfo.LandType != LandType.WaterAndAshore
|
||
&& unitInfo.LandType == LandType.WaterOnly)
|
||
return false;
|
||
}
|
||
//如果没有港口,纯看能不能移动进入这片区域
|
||
if (gridData.Resource != ResourceType.Port)
|
||
{
|
||
if(gridData.Terrain == TerrainType.ShallowSea)
|
||
return unitData.Skills.Contains(SkillFactory.GetSkillBySkillType(SkillType.WATERMOVE));
|
||
if(gridData.Terrain == TerrainType.DeepSea)
|
||
return unitData.Skills.Contains(SkillFactory.GetSkillBySkillType(SkillType.OCEANMOVE));
|
||
}
|
||
|
||
}
|
||
//如果是陆地
|
||
if (gridData.Terrain == TerrainType.Land)
|
||
{
|
||
//如果是山脉
|
||
if (gridData.Feature == TerrainFeature.Mountain)
|
||
{
|
||
return unitData.Skills.Contains(SkillFactory.GetSkillBySkillType(SkillType.MOUNTAINMOVE));
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
}
|
||
}
|