| | |
| | | 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.position; |
| | | |
| | | // 获取目标节点的世界坐标(中心点) |
| | | Vector3 worldPos = target.TransformPoint(target.rect.center + offset); |
| | | // 如果需要加 offset,需考虑 scale |
| | | Vector3 offsetWorld = target.TransformVector(offset); |
| | | worldPos += offsetWorld; |
| | | |
| | | RectTransform canvasRect = transform.parent as RectTransform; |
| | | |
| | |
| | | null, |
| | | out localPoint); |
| | | |
| | | // 创建RawImage |
| | | float distance = Vector2.Distance(transform.anchoredPosition, localPoint); |
| | | |
| | | float duration = distance / speed; // 假设速度为1000单位/秒,可以根据需要调整 |
| | | float duration = distance / speed; |
| | | |
| | | 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; |
| | | } |
| | |
| | | var numChar = (char)GetDamageNumKey(config, basePowerStr[i]); |
| | | if (numChar > 0) |
| | | { |
| | | result += numChar; |
| | | result += numChar; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public static string DisplayDamageNum(BattleDmg damage) |
| | | { |
| | | var config = DamageNumConfig.Get(damage.attackType); |
| | | |
| | | string result = string.Empty; |
| | | |
| | | // 如果是闪避 则只显示闪避两个字 |
| | | if (damage.IsType(DamageType.Dodge)) |
| | | { |
| | | result += (char)config.prefix; |
| | | } |
| | | else |
| | | { |
| | | result = ConvertToArtFont(config, damage.damage); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | public static string ConvertToArtFont(DamageNumConfig config, float _num) |
| | | { |
| | | var stringBuild = new System.Text.StringBuilder(); |
| | | |
| | | if (0 != config.plus) |
| | | stringBuild.Append((char)config.plus); |
| | | if (0 != config.prefix) |
| | | stringBuild.Append((char)config.prefix); |
| | | |
| | | var chars = UIHelper.ReplaceLargeArtNum(_num); |
| | | for (var i = 0; i < chars.Length; i++) |
| | | { |
| | | int numChar = GetDamageNumKey(config, (int)chars[i]); |
| | | |
| | | if (numChar > 0) |
| | | { |
| | | stringBuild.Append((char)numChar); |
| | | } |
| | | } |
| | | |
| | | return stringBuild.ToString(); |
| | | } |
| | | |
| | | public static int GetMainTargetPositionNum(BattleObject caster, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> targetList, SkillConfig skillConfig) |
| | |
| | | break; |
| | | case 1: |
| | | // 1 对位: |
| | | // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B1,前排1、2、3号位置全部死亡之后才开始选择后排4、5、6号位置,对位只可选1个目标,即主目标 |
| | | // 默认只选1个,对位规则为A1优先打B1,A2优先打B2,A3优先打B3,对位目标死亡时,优先前排,比如B2已经死亡,那么A2将优先打B |
| | | if (targetList.Count > 0) |
| | | { |
| | | BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)targetList[0].ObjID); |
| | |
| | | |
| | | public static int GetDamageNumKey(DamageNumConfig config, int _num) |
| | | { |
| | | if (_num == 46) return config.nums[10]; // '.' |
| | | 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 == 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"); |
| | | Debug.LogError("damage config " + config.TypeID + " _num is " + _num + " out of range"); |
| | | return _num; |
| | | } |
| | | return config.nums[_num - 48]; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 将整个技能的总伤害按命中次数和分段配置分配 |
| | | /// </summary> |
| | | /// <param name="damageDivideList">整个技能的所有命中分段配置</param> |
| | | /// <param name="hitIndex">当前是第几击(从0开始)</param> |
| | | /// <param name="totalDamage">整个技能的总伤害</param> |
| | | /// <returns>这一击内每一段的伤害值列表</returns> |
| | | public static List<long> DivideDamageToList(int[][] damageDivideList, int hitIndex, long totalDamage) |
| | | { |
| | | if (totalDamage <= 0) |
| | | { |
| | | return new List<long>{}; |
| | | } |
| | | |
| | | if (damageDivideList == null || damageDivideList.Length == 0) |
| | | { |
| | | Debug.LogError("damageDivideList 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | if (hitIndex < 0 || hitIndex >= damageDivideList.Length) |
| | | { |
| | | Debug.LogError($"hitIndex={hitIndex} 超出范围, damageDivideList.Length={damageDivideList.Length}"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | int[] currentHitDivide = damageDivideList[hitIndex]; |
| | | if (currentHitDivide == null || currentHitDivide.Length == 0) |
| | | { |
| | | Debug.LogError($"damageDivide[{hitIndex}] 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | // ============ 第一步: 计算每一击应该造成的伤害 ============ |
| | | // 先计算所有击的总权重 |
| | | int totalWeight = 0; |
| | | for (int i = 0; i < damageDivideList.Length; i++) |
| | | { |
| | | if (damageDivideList[i] != null && damageDivideList[i].Length > 0) |
| | | { |
| | | // 每一击的权重是其所有分段之和 |
| | | for (int j = 0; j < damageDivideList[i].Length; j++) |
| | | { |
| | | totalWeight += damageDivideList[i][j]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (totalWeight == 0) |
| | | { |
| | | Debug.LogError("totalWeight 为 0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | // 计算当前这一击的权重 |
| | | int currentHitWeight = 0; |
| | | for (int i = 0; i < currentHitDivide.Length; i++) |
| | | { |
| | | currentHitWeight += currentHitDivide[i]; |
| | | } |
| | | |
| | | // 计算当前这一击应该造成的总伤害 |
| | | long currentHitTotalDamage; |
| | | bool isLastHit = hitIndex >= damageDivideList.Length - 1; |
| | | |
| | | if (isLastHit) |
| | | { |
| | | // 最后一击: 计算前面所有击已经造成的伤害,剩余的全部给最后一击 |
| | | long previousHitsDamage = 0; |
| | | for (int i = 0; i < hitIndex; i++) |
| | | { |
| | | if (damageDivideList[i] != null) |
| | | { |
| | | int hitWeight = 0; |
| | | for (int j = 0; j < damageDivideList[i].Length; j++) |
| | | { |
| | | hitWeight += damageDivideList[i][j]; |
| | | } |
| | | previousHitsDamage += (long)((float)totalDamage * (float)hitWeight / (float)totalWeight); |
| | | } |
| | | } |
| | | currentHitTotalDamage = totalDamage - previousHitsDamage; |
| | | } |
| | | else |
| | | { |
| | | // 非最后一击: 按权重计算 |
| | | currentHitTotalDamage = (long)((float)totalDamage * (float)currentHitWeight / (float)totalWeight); |
| | | } |
| | | |
| | | // ============ 第二步: 将当前这一击的伤害分配到各分段 ============ |
| | | List<long> fixedDamageList = new List<long>(); |
| | | long accumulatedDamage = 0; |
| | | |
| | | for (int i = 0; i < currentHitDivide.Length; i++) |
| | | { |
| | | long damage; |
| | | |
| | | // 当前击的最后一段进行误差补偿 |
| | | if (i == currentHitDivide.Length - 1) |
| | | { |
| | | damage = currentHitTotalDamage - accumulatedDamage; |
| | | } |
| | | else |
| | | { |
| | | // 按当前击的权重分配 |
| | | damage = (long)((float)currentHitTotalDamage * (float)currentHitDivide[i] / (float)currentHitWeight); |
| | | accumulatedDamage += damage; |
| | | } |
| | | |
| | | fixedDamageList.Add(damage); |
| | | } |
| | | |
| | | return fixedDamageList; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | public static List<long> DivideDamageToList(int[] damageDivide, long totalDamage) |
| | | { |
| | | if (damageDivide == null || damageDivide.Length == 0) |
| | | { |
| | | Debug.LogError("damageDivide 为空或长度为0"); |
| | | return new List<long> { totalDamage }; |
| | | } |
| | | |
| | | List<long> fixedDamageList = new List<long>(); |
| | | long accumulatedDamage = 0; // 累计已分配的伤害 |
| | | |
| | | for (int i = 0; i < damageDivide.Length; i++) |
| | | { |
| | | float fixedDamage = (float)totalDamage * (float)damageDivide[i] / 10000f; |
| | | fixedDamageList.Add((int)fixedDamage); |
| | | long damage; |
| | | |
| | | // 最后一次分配:用总伤害减去已分配的伤害,确保总和精确 |
| | | if (i == damageDivide.Length - 1) |
| | | { |
| | | damage = totalDamage - accumulatedDamage; |
| | | } |
| | | else |
| | | { |
| | | // 计算当前分段伤害(向下取整) |
| | | damage = (long)((float)totalDamage * (float)damageDivide[i] / 10000f); |
| | | accumulatedDamage += damage; |
| | | } |
| | | |
| | | fixedDamageList.Add(damage); |
| | | } |
| | | |
| | | |
| | | return fixedDamageList; |
| | | } |
| | | |
| | | public static HB419_tagSCObjHPRefresh FindObjHPRefreshPack(List<GameNetPackBasic> packList) |
| | | { |
| | | for (int i = 0; i < packList.Count; i++) |
| | | { |
| | | var pack = packList[i]; |
| | | if (pack is HB419_tagSCObjHPRefresh hpRefreshPack) |
| | | { |
| | | return hpRefreshPack; |
| | | } |
| | | else if (pack is CustomHB426CombinePack) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public static List<HB422_tagMCTurnFightObjDead> FindDeadPack(List<GameNetPackBasic> packList) |
| | | { |