217 lines
8.7 KiB
C#
217 lines
8.7 KiB
C#
|
|
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;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 混乱表现逻辑
|
|||
|
|
/// Effect.txt 表格扩展参数说明
|
|||
|
|
/// Param1 :EffectParam.txt中id值 身体材质相关配置
|
|||
|
|
/// Param2 :粒子特效ID
|
|||
|
|
/// Param3 :粒子特效ID
|
|||
|
|
/// Param4 :粒子特效ID
|
|||
|
|
/// EffectParam.txt 表格扩展参数说明
|
|||
|
|
/// Param1 : 等待状态持续时间(/千分秒)
|
|||
|
|
/// Param2 : 最大索敌距离(/Unity单位)
|
|||
|
|
/// Param3 : 连续攻击最小次数
|
|||
|
|
/// Param4 : 连续攻击最大次数
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 混乱专用的目标检测方式
|
|||
|
|
/// </summary>
|
|||
|
|
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<ObjManager>.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<Obj_Character>();
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|