using System; using System.Collections.Generic; using Games.AI_Logic; using Games.Events; using Games.GlobeDefine; using Games.LogicObj; using Games.SkillModle; using GCGame.Table; using Module.Log; using UnityEngine; using System.Linq; using Games.ImpactModle; using Random = UnityEngine.Random; /// /// 混乱表现逻辑 /// Effect.txt 表格扩展参数说明 /// Param1 :EffectParam.txt中id值 身体材质相关配置 /// Param2 :粒子特效ID /// Param3 :粒子特效ID /// Param4 :粒子特效ID /// EffectParam.txt 表格扩展参数说明 /// Param1 : 等待状态持续时间(/千分秒) /// Param2 : 最大索敌距离(/Unity单位) /// Param3 : 连续攻击最小次数 /// Param4 : 连续攻击最大次数 /// public class Impact_Chaos : ImpactEffectBase { public override EffectLogic.EffectType ImpactEffectType { get { return EffectLogic.EffectType.TYPE_CHAOS; } } // 试图接近目标时,更新周期 private float _walkUpdateInterval = 0.2f; // 优先搜索距离 private float _searchDistanceSqr0; // 次要搜索距离 private float _searchDistanceSqr1; // 执行行动间隔时间 // 下次执行行动的时间 private float _nextActionTime; private Obj_MainPlayer _mainPlayer; // 最小连续攻击次数 private int _comboMin; // 最大连续攻击次数 private int _comboMax; // 当前锁定目标 private Obj_Character _target; // 当前已经执行的Combo数目 private int _currentExecuteCombo; // 当前试图执行的Combo数目 private int _currentCombo; public override void StartEffect() { base.StartEffect(); _mainPlayer = objCharacter as Obj_MainPlayer; if (_mainPlayer != null) { var paramid = Data.GetParamValuebyIndex(0); var effectparam = TableManager.GetEffectParamByID(paramid, 0); if (effectparam == null) _mainPlayer = null; else { // 如果出现错误,将无法正常运行 if (float.TryParse(effectparam.GetParamValuebyIndex(0), out _searchDistanceSqr0) && float.TryParse(effectparam.GetParamValuebyIndex(1), out _searchDistanceSqr1) && int.TryParse(effectparam.GetParamValuebyIndex(2), out _comboMin) && int.TryParse(effectparam.GetParamValuebyIndex(3), out _comboMax)) { _searchDistanceSqr0 = _searchDistanceSqr0.ToSquare(); _searchDistanceSqr1 = _searchDistanceSqr1.ToSquare(); } else { _mainPlayer = null; LogModule.ErrorLog(string.Format("特效参数{0}数据无法被Impact_Chaos读取", effectparam.EffectParamID)); } } if (_mainPlayer != null) { _mainPlayer.AddDisableState(((int)Games.ImpactModle.DISABLESTATE.Chaos).ToFlag()); for (var i = 1; i < 4; i++) { paramid = Data.GetParamValuebyIndex(i); if (paramid > -1) _mainPlayer.PlayEffect(paramid); } } } } protected override void UpdateInherited() { if (_mainPlayer != null) { if (Time.time > _nextActionTime && GameManager.gameManager.PlayerDataPool.AllowSimpleInput) { _nextActionTime = Time.time + _walkUpdateInterval; if (_target == null || !ValidTarget(_target)) { _target = SearchTarget(); _currentCombo = 0; _currentExecuteCombo = 0; } if (_target != null) { if (_currentCombo == 0) _currentCombo = Random.Range(_comboMin, _comboMax + 1); var moveToTarget = true; // 当前允许使用普攻时,试图使用普攻 // 特殊处理,不打断自动连续技能 if (_mainPlayer.SkillAllowSimpleAttack && _mainPlayer.IsDisableState(DISABLESTATE.Disable_Select) && (!_mainPlayer.IsPredictSkill || !_mainPlayer.PredictSkillBase.SkillClass.ContainFlag((int)SKILLCLASS.AUTOREPEAT)) && (!_mainPlayer.IsUsingSkill || !_mainPlayer.SkillCore.CurrentSkillBase.SkillClass.ContainFlag((int)SKILLCLASS.AUTOREPEAT))) { var attackSkill = _mainPlayer.GetNextSimpleAttack(); if (attackSkill != null && _mainPlayer.CheckSkillCastable(attackSkill.SkillBaseTable, attackSkill.SkillExTable, attackSkill.IsCooldownFinish(), false) == SkillCastableCheckResult.Success && _mainPlayer.ValidSkillRangeOnTarget(attackSkill.ComboExTableFinal, attackSkill.ComboBaseTable, _target, rangeReduce: Obj_MainPlayer.skillCastOverwalk)) { moveToTarget = false; if (_mainPlayer.ProcessSkill(attackSkill, _target, Vector2.zero)) _currentExecuteCombo++; // 执行1-4次普攻后,休息并强制切换目标 if (_currentExecuteCombo >= _currentCombo) { _target = SearchTarget(_target.ServerID); _currentCombo = 0; _currentExecuteCombo = 0; } } } // 无法攻击时,试图向目标移动 if (moveToTarget && (_mainPlayer.Position - _target.Position).RemoveY().sqrMagnitude > AI_PlayerCombat.minCloseInDistance.ToSquare()) { _mainPlayer.MainPlayMoveToTarget(_target, new Obj_MainPlayer.MoveToTargetTillDistance(AI_PlayerCombat.minCloseInDistance), isMoveOrder: false); } } } } } /// /// 混乱专用的目标检测方式 /// private bool ValidTarget(Obj_Character target) { var result = false; if (!target.IsDie() && !target.isInvisible && !target.IsDisableState(DISABLESTATE.Disable_BeSelect) && target.ObjType != GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER) { if (target.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER) { if (_mainPlayer.ValidPkProtection(target, false)) result = true; } else if (target.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_NPC) { if (Reputation.CanAttack(target)) result = true; } } return result; } // 注:特殊扫描方式 - 仅搜索敌对NPC和任意阵营OtherPlayer,忽略其他类型目标 // 尽量忽略上一次攻击的目标 private Obj_Character SearchTarget(int excludeId = -1) { var targets = (from keyValue in Singleton.GetInstance().ObjPools let character = keyValue.Value as Obj_Character where character != null && ValidTarget(character) select character).ToArray(); var result = GetRandomTargetInRange(targets, _searchDistanceSqr0, excludeId); if (result == null) result = GetRandomTargetInRange(targets, _searchDistanceSqr1, excludeId); return result; } private Obj_Character GetRandomTargetInRange(Obj_Character[] characters, float rangeSqr, int excludeId = -1) { Obj_Character excludeTarget = null; var targetList = new List(); for (var i = 0; i < characters.Length; i++) { if ((characters[i].Position - _mainPlayer.Position).RemoveY().sqrMagnitude < rangeSqr) { if (characters[i].ServerID == excludeId) excludeTarget = characters[i]; else targetList.Add(characters[i]); } } // 尽量不选择excludeTarget var result = targetList.Count > 0 ? targetList[Random.Range(0, targetList.Count)] : excludeTarget; return result; } public override void StopEffect() { base.StopEffect(); if (_mainPlayer != null) { _mainPlayer.DelDisableState(((int)Games.ImpactModle.DISABLESTATE.Chaos).ToFlag()); _mainPlayer = null; } } }