Files
JJBB/Assets/Project/Script/Player/Skill/SkillCore.cs
2024-08-23 15:49:34 +08:00

327 lines
14 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************
* 文件名: 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);
}
}
}
}