327 lines
14 KiB
C#
327 lines
14 KiB
C#
|
/********************************************************************************
|
|||
|
* 文件名: SkillCore.cs
|
|||
|
* 全路径: \Script\GameManager\SkillCore.cs
|
|||
|
* 创建人: 罗勇
|
|||
|
* 创建时间:2013-11-06
|
|||
|
* 重构人: Blastom
|
|||
|
* 重构时间:2018-01-10
|
|||
|
*
|
|||
|
* 功能说明:客户端技能逻辑核心,负责客户端技能逻辑处理
|
|||
|
* 修改记录:重构,现SkillCore仅用于处理技能动画和特效等表现,技能判断
|
|||
|
* 功能(仅主角需要)移动到Obj_MainPlayer中。更好的结构是把这块搞在
|
|||
|
* 技能类本身,就可以让不同技能自己重载修改表现效果 - Blastom
|
|||
|
*********************************************************************************/
|
|||
|
|
|||
|
using Games.AnimationModule;
|
|||
|
using Games.GlobeDefine;
|
|||
|
using Games.LogicObj;
|
|||
|
using Games.Scene;
|
|||
|
using GCGame.Table;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Games.SkillModle
|
|||
|
{
|
|||
|
public class SkillCore
|
|||
|
{
|
|||
|
// 最大技能缓存时间,超过该时间会抛弃这个技能
|
|||
|
private const float _maxSkillCacheTime = 1f;
|
|||
|
|
|||
|
// SkillCore相当于Obj_Character的一个附件,肯定和Obj共存亡
|
|||
|
private readonly Obj_Character _owner;
|
|||
|
|
|||
|
private Vector2 _cachedFacePoint;
|
|||
|
|
|||
|
private Tab_SkillEx _cachedSkill;
|
|||
|
|
|||
|
// 模型加载前就在播放的技能 - 记录时间以判定是否超时
|
|||
|
// 实际模型加载完成后,角色位置和面向可能有差错
|
|||
|
private float _cachedSkillTime;
|
|||
|
|
|||
|
private bool _cachedSkipWindup;
|
|||
|
|
|||
|
private int _cachedTargetId;
|
|||
|
|
|||
|
// 技能是否处于播放阶段 - CurrentSkill 等参数需要缓存,因此不能用参数判断是否播放
|
|||
|
private bool _isPlaying;
|
|||
|
|
|||
|
public SkillCore(Obj_Character owner)
|
|||
|
{
|
|||
|
_owner = owner;
|
|||
|
}
|
|||
|
|
|||
|
// 当前正在使用的技能
|
|||
|
public Tab_SkillEx CurrentSkill { get; private set; }
|
|||
|
|
|||
|
// 当前正在使用的技能BaseInfo
|
|||
|
public Tab_SkillBase CurrentSkillBase { get; private set; }
|
|||
|
|
|||
|
// 当前技能开始时间
|
|||
|
public float CurrentSkillTime { get; private set; }
|
|||
|
|
|||
|
// 是否播放技能效果 - 不作为是否能够使用技能的判定
|
|||
|
// 其他组件无论先后顺序,都会在同一帧检测到技能释放结束
|
|||
|
public bool IsUsingSkill
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _isPlaying && CurrentSkillTime + Obj_Character.SkillDuration(CurrentSkill, CurrentSkillBase) >
|
|||
|
Time.time;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 释放一个技能
|
|||
|
/// </summary>
|
|||
|
public bool UseSkill(Tab_SkillEx skillEx, Tab_SkillBase skillBase, int targetId, Vector3 facePoint,
|
|||
|
bool skipWindup = false)
|
|||
|
{
|
|||
|
var result = false;
|
|||
|
if (_isPlaying)
|
|||
|
EndSkillByBaseId();
|
|||
|
// 按原来逻辑,使用动画机检查技能是否应该缓存
|
|||
|
if (_owner.AnimLogic == null || !_owner.AnimLogic.AnimPlayable())
|
|||
|
{
|
|||
|
_cachedSkillTime = Time.time;
|
|||
|
_cachedSkill = skillEx;
|
|||
|
_cachedTargetId = targetId;
|
|||
|
_cachedFacePoint = facePoint;
|
|||
|
_cachedSkipWindup = skipWindup;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
result = true;
|
|||
|
_isPlaying = true;
|
|||
|
ClearCacheSkill();
|
|||
|
var previousSkill = CurrentSkill;
|
|||
|
CurrentSkill = skillEx;
|
|||
|
CurrentSkillBase = skillBase;
|
|||
|
CurrentSkillTime = Time.time;
|
|||
|
// Hack:普攻跳过动画的情况,直接视为技能提前开始
|
|||
|
var animSkipTime = skipWindup ? CurrentSkill.CradleTime.ToClientTime() : 0f;
|
|||
|
CurrentSkillTime -= animSkipTime;
|
|||
|
// 不允许移动的技能停止角色移动
|
|||
|
if (CurrentSkillBase.IsMove < 1 || CurrentSkillBase.IsMoveBreak > 0)
|
|||
|
_owner.StopMove();
|
|||
|
var targetObjCharacter = Singleton<ObjManager>.GetInstance().FindObjCharacterInScene(targetId);
|
|||
|
if (!_owner.IsBindFace())
|
|||
|
if (targetObjCharacter == null || targetObjCharacter == _owner)
|
|||
|
_owner.FaceTo(facePoint);
|
|||
|
else if (targetObjCharacter.ServerID != _owner.ServerID)
|
|||
|
_owner.FaceTo(targetObjCharacter.Position);
|
|||
|
// 开始播放动画
|
|||
|
// 跳过其他人释放陷阱的动画,外加强制显示播放动画的人
|
|||
|
var playAnim = true;
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER)
|
|||
|
if (CurrentSkillBase.Id == (int) SKILLBASEID.HDWLID)
|
|||
|
playAnim = false;
|
|||
|
else
|
|||
|
ToggleShowBySkill(true);
|
|||
|
if (playAnim)
|
|||
|
{
|
|||
|
var transitionName = animSkipTime > 0 && previousSkill != null &&
|
|||
|
previousSkill.NextSkillId == CurrentSkill.SkillExID
|
|||
|
? AnimationLogic.GetTransitionName(previousSkill.SatrtMotionId, CurrentSkill.SatrtMotionId)
|
|||
|
: string.Empty;
|
|||
|
_owner.AnimLogic.Play(CurrentSkill.SatrtMotionId, transitionName);
|
|||
|
}
|
|||
|
|
|||
|
//子弹播放
|
|||
|
var bulletCount = CurrentSkill.getBulletEffectIDCount();
|
|||
|
for (var i = 0; i < bulletCount; i++)
|
|||
|
{
|
|||
|
var bullectId = CurrentSkill.GetBulletEffectIDbyIndex(i);
|
|||
|
if (bullectId > -1)
|
|||
|
IndependentEffectManager.Instance.ShowBullet(bullectId, _owner.ServerID, targetId,
|
|||
|
_owner.gameObject.layer, _owner.ObjType);
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// 显示技能名称
|
|||
|
if (CurrentSkillBase.IsShowSkillName > 0)
|
|||
|
DisplaySkillName(CurrentSkillBase, string.Empty);
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER)
|
|||
|
if (skillBase.SkillClass.ContainFlag((int) SKILLCLASS.DUTIAO))
|
|||
|
{
|
|||
|
//吟唱时间为当前动作的长度
|
|||
|
var fYinChangTime = skillEx.YinChangTime.ToClientTime();
|
|||
|
SkillProgressLogic.PlayProcess(SkillProgressLogic.ProgressModel.REVERSEDMODE, fYinChangTime,
|
|||
|
skillBase.Name,
|
|||
|
skillEx.SkillExID);
|
|||
|
}
|
|||
|
else if (skillBase.UseType.ContainFlag((int) SKILLUSETYPE.YINCHANG))
|
|||
|
{
|
|||
|
//吟唱时间为当前动作的长度
|
|||
|
var fYinChangTime = skillEx.YinChangTime.ToClientTime();
|
|||
|
SkillProgressLogic.PlayProcess(SkillProgressLogic.ProgressModel.ORDERMODEL, fYinChangTime,
|
|||
|
skillBase.Name,
|
|||
|
skillEx.SkillExID);
|
|||
|
}
|
|||
|
// 被攻击者是主角时,主角宠物试图攻击攻击者
|
|||
|
if (targetObjCharacter != null &&
|
|||
|
targetObjCharacter.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER)
|
|||
|
{
|
|||
|
var mainPlayer = targetObjCharacter.TryCastToType<Obj_MainPlayer>();
|
|||
|
if (mainPlayer != null)
|
|||
|
{
|
|||
|
int threadValue;
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER)
|
|||
|
threadValue = 1000;
|
|||
|
else if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_FELLOW)
|
|||
|
threadValue = 100;
|
|||
|
else
|
|||
|
threadValue = 1;
|
|||
|
mainPlayer.Controller.ThreadInfo.AddThreat(_owner, threadValue);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 摄像机效果
|
|||
|
CameraOpt(true);
|
|||
|
_owner.OnSwithObjAnimState(GameDefine_Globe.OBJ_ANIMSTATE.STATE_SKILL);
|
|||
|
// 显示技能警告
|
|||
|
if (skillEx.WarningText > 0)
|
|||
|
{
|
|||
|
var warningContent = TableManager.GetStrDictionaryByID(skillEx.WarningText, 0);
|
|||
|
var warningStart = Mathf.Max(0f, skillEx.WarningStart.ToClientTime());
|
|||
|
var warningDuration = (skillEx.WarningDuration > 0f
|
|||
|
? skillEx.WarningDuration
|
|||
|
: skillEx.SkillContinueTime).ToClientTime();
|
|||
|
CentreNoticeLogic.ShowSkillWarning(warningContent.StrDictionary, warningStart, warningDuration);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public void UserCacheSkill()
|
|||
|
{
|
|||
|
if (_cachedSkill != null)
|
|||
|
if (_cachedSkillTime + _maxSkillCacheTime > Time.time)
|
|||
|
{
|
|||
|
var skillBase =
|
|||
|
CommonUtility.TryGetTable(_cachedSkill.BaseId, a => TableManager.GetSkillBaseByID(a, 0));
|
|||
|
if (skillBase != null)
|
|||
|
UseSkill(_cachedSkill, skillBase, _cachedTargetId, _cachedFacePoint, _cachedSkipWindup);
|
|||
|
else
|
|||
|
ClearCacheSkill();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ClearCacheSkill();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ClearCacheSkill()
|
|||
|
{
|
|||
|
_cachedSkill = null;
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateSkill()
|
|||
|
{
|
|||
|
if (_isPlaying && !IsUsingSkill)
|
|||
|
EndSkillByBaseId();
|
|||
|
}
|
|||
|
|
|||
|
public void EndSkillByBaseId(int baseId = -1)
|
|||
|
{
|
|||
|
if (_isPlaying && (baseId < 0 || CurrentSkill.BaseId == baseId))
|
|||
|
{
|
|||
|
ClearCacheSkill();
|
|||
|
CameraOpt(false);
|
|||
|
_owner.EnableMovingRotation(true);
|
|||
|
// 如果技能动画是循环动画,需要切换到Idle动画
|
|||
|
if (CurrentSkill.SatrtMotionId > -1)
|
|||
|
{
|
|||
|
var idleId = _owner.GetIdleAnimId();
|
|||
|
if (_owner.AnimLogic != null)
|
|||
|
_owner.AnimLogic.SwitchLoopToIdle(CurrentSkill.SatrtMotionId, idleId);
|
|||
|
}
|
|||
|
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER ||
|
|||
|
_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER)
|
|||
|
{
|
|||
|
var player = _owner as Obj_OtherPlayer;
|
|||
|
if (null != player)
|
|||
|
player.UpdateVisualAfterSkill();
|
|||
|
}
|
|||
|
|
|||
|
//如果需要在技能结束的时候 停止对应的特效 则停止
|
|||
|
if (CurrentSkillBase.IsNeedStopEffectId > -1)
|
|||
|
_owner.StopEffect(CurrentSkillBase.IsNeedStopEffectId);
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER)
|
|||
|
ToggleShowBySkill(false);
|
|||
|
// 处理吟唱技能进度条
|
|||
|
else if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER)
|
|||
|
SkillProgressLogic.StopProcess(CurrentSkill.SkillExID);
|
|||
|
_isPlaying = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 控制摄像头 createInstance
|
|||
|
private void CameraOpt(bool isStart)
|
|||
|
{
|
|||
|
if (SceneLogic.CameraController != null)
|
|||
|
{
|
|||
|
if (CurrentSkill.CameraRockId > -1)
|
|||
|
if (isStart)
|
|||
|
{
|
|||
|
var priority = _owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER ? 1 : 0;
|
|||
|
if (CurrentSkill.CameraRockRate > Random.Range(0, 100))
|
|||
|
SceneLogic.CameraController.StartCameraRock(CurrentSkill.CameraRockId, _owner, priority);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SceneLogic.CameraController.StopCameraRock(CurrentSkill.CameraRockId, _owner.ServerID);
|
|||
|
}
|
|||
|
//XP技能拉高摄像机视角
|
|||
|
if (CurrentSkillBase.Id == (int) SKILLBASEID.YGSDID ||
|
|||
|
CurrentSkillBase.SkillClass.ContainFlag((int) SKILLCLASS.XP))
|
|||
|
SceneLogic.CameraController.FoVOverride = isStart ? 1.0f : -1.0f;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 动画机缓存无法解决特效问题,因此还是需要强制显示
|
|||
|
private void ToggleShowBySkill(bool isStart)
|
|||
|
{
|
|||
|
if (!_owner.ModelInViewPort)
|
|||
|
if (isStart)
|
|||
|
_owner.BecameVisible();
|
|||
|
else
|
|||
|
_owner.BecameInvisible();
|
|||
|
}
|
|||
|
|
|||
|
private void DisplaySkillName(Tab_SkillBase skillBase, string skillName)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(skillName))
|
|||
|
{
|
|||
|
if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_MAIN_PLAYER)
|
|||
|
_owner.ShowDamageBoard_SkillName(GameDefine_Globe.DAMAGEBOARD_TYPE.SKILL_NAME, skillBase.Name);
|
|||
|
else if (_owner.ObjType == GameDefine_Globe.OBJ_TYPE.OBJ_NPC)
|
|||
|
_owner.ShowDamageBoard_SkillName(GameDefine_Globe.DAMAGEBOARD_TYPE.SKILL_NAME_NPC, skillBase.Name,
|
|||
|
false);
|
|||
|
else if (_owner.ObjType != GameDefine_Globe.OBJ_TYPE.OBJ_OTHER_PLAYER)
|
|||
|
_owner.ShowDamageBoard_SkillName(GameDefine_Globe.DAMAGEBOARD_TYPE.SKILL_NAME, skillBase.Name,
|
|||
|
false);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_owner.ShowDamageBoard_SkillName(GameDefine_Globe.DAMAGEBOARD_TYPE.SKILL_NAME, skillName, false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//显示技能名字
|
|||
|
public static void ShowSkillName(int skillId, int senderId, string skillName)
|
|||
|
{
|
|||
|
var skillSender = Singleton<ObjManager>.GetInstance().FindObjCharacterInScene(senderId);
|
|||
|
if (skillSender != null)
|
|||
|
{
|
|||
|
var skillEx = TableManager.GetSkillExByID(skillId, 0);
|
|||
|
Tab_SkillBase skillBase = null;
|
|||
|
if (skillEx != null)
|
|||
|
skillBase = TableManager.GetSkillBaseByID(skillEx.BaseId, 0);
|
|||
|
if (skillBase != null && skillSender.SkillCore != null)
|
|||
|
skillSender.SkillCore.DisplaySkillName(skillBase, skillName);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|