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;
|
||
}
|
||
}
|
||
} |