using System;
|
using System.Collections.Generic;
|
using UnityEngine;
|
using UnityEngine.UI;
|
using DG.Tweening;
|
using DG.Tweening.Core;
|
using System.Linq;
|
|
public static class BattleUtility
|
{
|
// 其他通用的战斗工具方法可以放在这里
|
|
|
public static void MarkStartAndEnd(RectTransform startNode, RectTransform endNode)
|
{
|
// 运行时才执行
|
if (!Application.isPlaying)
|
{
|
Debug.LogWarning("请在运行时使用该功能!");
|
return;
|
}
|
|
var battleField = BattleManager.Instance.storyBattleField;
|
if (battleField == null)
|
{
|
Debug.LogError("BattleManager.storyBattleField 未初始化!");
|
return;
|
}
|
|
|
BattleWin battleWin = UIManager.Instance.GetUI<BattleWin>();
|
|
RectTransform canvasRect = battleWin.transform as RectTransform;
|
|
CreateMarker(canvasRect, startNode, "StartMarker");
|
CreateMarker(canvasRect, endNode, "EndMarker");
|
}
|
|
private static void CreateMarker(RectTransform canvasRect, RectTransform targetNode, string markerName)
|
{
|
// 获取目标节点的世界坐标(中心点)
|
Vector3 worldPos = targetNode.TransformPoint(targetNode.rect.center);
|
|
// 转换到Canvas本地坐标
|
Vector2 localPoint;
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
canvasRect,
|
RectTransformUtility.WorldToScreenPoint(null, worldPos),
|
null,
|
out localPoint);
|
|
// 创建RawImage
|
GameObject marker = new GameObject(markerName, typeof(RawImage));
|
GameObject.Destroy(marker, 5f);
|
marker.transform.SetParent(canvasRect, false);
|
var rawImage = marker.GetComponent<RawImage>();
|
rawImage.color = Color.white;
|
rawImage.rectTransform.sizeDelta = new Vector2(100, 100);
|
rawImage.rectTransform.anchoredPosition = localPoint;
|
}
|
|
|
public static TweenerCore<Vector2, Vector2, DG.Tweening.Plugins.Options.VectorOptions> MoveToTarget(
|
RectTransform transform, RectTransform target, Vector2 offset, Action onComplete = null, float speed = 500f)
|
{
|
|
// 获取目标节点的世界坐标(中心点)
|
Vector3 worldPos = target.TransformPoint(target.rect.center + offset);
|
|
RectTransform canvasRect = transform.parent as RectTransform;
|
|
// 转换到Canvas本地坐标
|
Vector2 localPoint;
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
canvasRect,
|
RectTransformUtility.WorldToScreenPoint(null, worldPos),
|
null,
|
out localPoint);
|
|
// 创建RawImage
|
float distance = Vector2.Distance(transform.anchoredPosition, localPoint);
|
|
float duration = distance / speed; // 假设速度为1000单位/秒,可以根据需要调整
|
|
var tween = transform.DOAnchorPos(localPoint, duration).SetEase(Ease.Linear);
|
tween.onComplete += () =>
|
{
|
onComplete?.Invoke();
|
};
|
|
// MarkStartAndEnd(transform as RectTransform, target);
|
|
|
// // 1. 获取目标的世界坐标(加 offset)
|
// Vector3 targetWorldPos = target.TransformPoint(target.anchoredPosition + offset);
|
|
// // 2. 获取源节点的 parent
|
// RectTransform sourceParent = transform.parent as RectTransform;
|
// if (sourceParent == null)
|
// {
|
// BattleDebug.LogError("源节点没有父节点,无法转换坐标!");
|
// return null;
|
// }
|
|
// // 3. 把目标世界坐标转换到源 parent 的本地坐标
|
// Vector2 targetAnchoredPos;
|
// RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
// sourceParent,
|
// RectTransformUtility.WorldToScreenPoint(CameraManager.uiCamera, targetWorldPos),
|
// CameraManager.uiCamera,
|
// out targetAnchoredPos);
|
|
// // 4. DOTween 移动
|
// var tween = transform.DOAnchorPos(targetAnchoredPos, duration).SetEase(Ease.Linear);
|
// tween.onComplete += () =>
|
// {
|
// onComplete?.Invoke();
|
// };
|
|
return tween;
|
}
|
|
public static string DisplayDamageNum(long num, int attackType)
|
{
|
var config = DamageNumConfig.Get(attackType);
|
var basePowerStr = UIHelper.ReplaceLargeArtNum(num);
|
var result = string.Empty;
|
for (int i = 0; i < basePowerStr.Length; i++)
|
{
|
var numChar = (char)GetDamageNumKey(config, basePowerStr[i]);
|
if (numChar > 0)
|
{
|
result += numChar;
|
}
|
}
|
return result;
|
}
|
|
public static int GetMainTargetPositionNum(BattleObject caster, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> targetList, SkillConfig skillConfig)
|
{
|
int returnIndex = 0;
|
// 根据敌方血量阵营 存活人数来选择
|
BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
|
List<BattleObject> targetObjList = caster.battleField.battleObjMgr.GetBattleObjList(battleCamp);
|
|
|
// 瞄准的目标范围,如果目标个数为0则为范围内全部
|
// 0 全部范围
|
// 1 对位,默认只选1个
|
// 2 前排
|
// 3 后排
|
// 4 纵排,按对位规则选择纵排
|
// 5 自己,默认只选自己
|
|
switch (skillConfig.TagAim)
|
{
|
case 0:
|
// 0 全部范围:
|
// 若TagCount目标个数为0或6,根据TagFriendly敌我配置,代表作用于敌方全体或我方全体,此时主目标为敌我站位中的2号位置
|
// 若TagCount目标个数为1~5个,根据TagFriendly敌我+TagAffect细分目标配置,代表随机作用于敌方或我方x个武将,第一个为主目标
|
if (skillConfig.TagCount == 0 || skillConfig.TagCount == 6)
|
{
|
returnIndex = 1;
|
}
|
else
|
{
|
uint objId = targetList[0].ObjID;
|
BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
|
return target.teamHero.positionNum;
|
}
|
break;
|
case 1:
|
// 1 对位:
|
// 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B1,前排1、2、3号位置全部死亡之后才开始选择后排4、5、6号位置,对位只可选1个目标,即主目标
|
if (targetList.Count > 0)
|
{
|
BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)targetList[0].ObjID);
|
if (battleObject != null)
|
{
|
returnIndex = battleObject.teamHero.positionNum;
|
}
|
else
|
{
|
Debug.LogError("GetMainTargetPositionNum 找不到目标 ObjId : " + targetList[0].ObjID);
|
returnIndex = 0;
|
}
|
}
|
else
|
{
|
Debug.LogError("targetList 目标列表为空");
|
returnIndex = 0;
|
}
|
break;
|
case 2:
|
// 1、2、3号位为前排,默认2号位置为主目标,当1、2、3号位置角色全部死亡,前排将替换成后排,5号位置变更为主目标,
|
// 若配置TagAffect细分目标,且人数小于3,则所有被选择目标均为主目标(施法位置会用客户端配置)
|
// (即前排默认2号位或5号位规则无效,实际作用多少人就是多少个主目标) (YL : TagAffect>0 && TagAffect != 3就是全体都是主目标 后排一样 )
|
if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3)
|
{
|
uint objId = targetList[0].ObjID;
|
BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
|
returnIndex = target.teamHero.positionNum;
|
}
|
else
|
{
|
// 看看对面前排是否都活着
|
List<BattleObject> front = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum < 3 select bo);
|
if (front.Count > 0)
|
{
|
returnIndex = 1;
|
}
|
else
|
{
|
returnIndex = 4;
|
}
|
}
|
break;
|
case 3:
|
if (skillConfig.TagAffect != 0 || skillConfig.TagCount < 3)
|
{
|
uint objId = targetList[0].ObjID;
|
BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)objId);
|
returnIndex = target.teamHero.positionNum;
|
}
|
else
|
{
|
// 看看对面后排是否都活着
|
List<BattleObject> back = new List<BattleObject>(from bo in targetObjList where !bo.IsDead() && bo.teamHero.positionNum >= 3 select bo);
|
if (back.Count > 0)
|
{
|
returnIndex = 4;
|
}
|
else
|
{
|
returnIndex = 1;
|
}
|
}
|
break;
|
// 4 纵排,按对位规则选择纵排
|
case 4:
|
returnIndex = int.MaxValue;
|
for (int i = 0; i < targetList.Count; i++)
|
{
|
var hurt = targetList[i];
|
BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
|
if (target == null)
|
{
|
Debug.LogError("GetMainTargetPositionNum 找不到目标 ObjId : " + hurt.ObjID);
|
continue;
|
}
|
else
|
{
|
returnIndex = Mathf.Min(returnIndex, target.teamHero.positionNum);
|
}
|
}
|
break;
|
// 5 自己,默认只选自己
|
case 5:
|
returnIndex = caster.teamHero.positionNum;
|
break;
|
default:
|
Debug.LogError("暂时不支持其他的方式选择主目标 有需求请联系策划 技能id:" + skillConfig.SkillID + " TagAim " + skillConfig.TagAim);
|
returnIndex = 0;
|
break;
|
}
|
|
return returnIndex;
|
}
|
|
public static int GetDamageNumKey(DamageNumConfig config, int _num)
|
{
|
if (_num == 46) return config.nums[10]; // '.'
|
else if (_num == 107) return config.nums[11]; // 'k'
|
else if (_num == 109) return config.nums[12]; // 'm'
|
else if (_num == 98) return config.nums[13]; // 'b'
|
else if (_num == 116) return config.nums[14]; // 't'
|
int targetNum = _num - 48;
|
if (targetNum >= config.nums.Length || targetNum < 0)
|
{
|
Debug.LogError("damage config " + config.TypeID + " _num is " + _num + " out of range");
|
return _num;
|
}
|
return config.nums[_num - 48];
|
}
|
|
/// <summary>
|
/// 保证所有分配项加起来等于totalDamage,避免因整除导致的误差
|
/// </summary>
|
public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage)
|
{
|
List<long> fixedDamageList = new List<long>();
|
|
for (int i = 0; i < damageDivide.Length; i++)
|
{
|
float fixedDamage = (float)totalDamage * (float)damageDivide[i] / 10000f;
|
fixedDamageList.Add((int)fixedDamage);
|
}
|
|
return fixedDamageList;
|
}
|
|
public static List<HB422_tagMCTurnFightObjDead> FindDeadPack(List<GameNetPackBasic> packList)
|
{
|
List<HB422_tagMCTurnFightObjDead> deadPacks = new List<HB422_tagMCTurnFightObjDead>();
|
for (int i = 0; i < packList.Count; i++)
|
{
|
var pack = packList[i];
|
// 寻找死亡包 找到死亡包之后要找掉落包 不能超过技能包
|
if (pack is HB422_tagMCTurnFightObjDead)
|
{
|
var deadPack = pack as HB422_tagMCTurnFightObjDead;
|
deadPacks.Add(deadPack);
|
}
|
else if (pack is CustomHB426CombinePack)
|
{
|
// 找死亡包不要越过技能包
|
var combinePack = pack as CustomHB426CombinePack;
|
if (combinePack.startTag.Tag.StartsWith("Skill_"))
|
{
|
break;
|
}
|
}
|
}
|
return deadPacks;
|
}
|
|
|
public static List<HB423_tagMCTurnFightObjReborn> FindRebornPack(List<GameNetPackBasic> packList)
|
{
|
List<HB423_tagMCTurnFightObjReborn> rebornPack = new List<HB423_tagMCTurnFightObjReborn>();
|
for (int i = 0; i < packList.Count; i++)
|
{
|
var pack = packList[i];
|
// 寻找死亡包 找到死亡包之后要找掉落包 不能超过技能包
|
if (pack is HB423_tagMCTurnFightObjReborn)
|
{
|
var deadPack = pack as HB423_tagMCTurnFightObjReborn;
|
rebornPack.Add(deadPack);
|
}
|
else if (pack is CustomHB426CombinePack)
|
{
|
// 找死亡包不要越过技能包
|
var combinePack = pack as CustomHB426CombinePack;
|
if (combinePack.startTag.Tag.StartsWith("Skill_"))
|
{
|
break;
|
}
|
}
|
}
|
return rebornPack;
|
}
|
}
|