using Adon.Game.Data.StructData; using Adon.Game.Helper; using Adon.Game.Manager; using AdonGameKit; using BehaviorDesigner.Runtime; using Chronos; using Cinemachine; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using WarReport; namespace Adon.Game.BO { /// /// 基础怪 /// public class BaseMonsterAdon : BaseCharacterAdon { /// /// 血条类 /// public MonHpBarAdon m_HpBar; protected NavMeshAgent m_NavMeshAgent; /// /// 时间器刚体 /// public RigidbodyTimeline3D m_RigidbodyTimeline3D; /// /// 推力方向 /// public Vector3 m_ForceDirection; /// /// 推力 /// public float m_Force; /// /// 暂停时间 /// private float pauseTime = 0; private bool isPause = false; //protected BehaviorTreeManager m_BehaviorTreeManager;//行为树管理器 public Behavior CurrentBehaviorTree; public float m_damageFlashScale;//损伤材质闪光强度 public BaseHero m_TargetHero; public GameObject m_Lock;//锁定标识 BaseHero _hero; Dictionary buffnum = new Dictionary();//buff计数 //buff效果对象列表 private GameObject[] buffs = new GameObject[20]; /// /// 是否被击 /// public bool isAttacked; public BaseHero m_Hero { get { if (_hero == null) { _hero = RoleManager.Instance.GetPlayer() as BaseHero; } else if (_hero.gameObject.activeSelf == false) { _hero = RoleManager.Instance.GetPlayer() as BaseHero; } return _hero; } } private Clock m_Clock; private bool IsDieEff;//是否在播放特效 //动作参数字符哈希值 protected static readonly int hashMoveX = Animator.StringToHash("MoveX"); protected static readonly int hashMoveZ = Animator.StringToHash("MoveZ"); protected static readonly int hashHit = Animator.StringToHash("Hit");//受击击 //protected static readonly int hashHitX = Animator.StringToHash("HitX");//打击 //protected static readonly int hashHitZ = Animator.StringToHash("HitZ");//打击 protected static readonly int hashHitAngle = Animator.StringToHash("HitAngle");//受击方向 protected static readonly int hashHitDown = Animator.StringToHash("HitDown");//击倒 protected static readonly int hashDie = Animator.StringToHash("Die");//死亡 protected static readonly int hashDieDown = Animator.StringToHash("DieDown");//击飞死亡 private static readonly int hashFind = Animator.StringToHash("Find");//发现目标 protected override void Awake() { base.Awake(); m_WeaponCol = transform.Find("WeaponCollider").GetComponent(); m_WeaponCol.gameObject.AddComponent().SetMonster(this); ;//添加武器碰撞器脚本 CurrentBehaviorTree = GetComponent(); m_Lock = transform.Find("FBX/Effect_ZhongXin/Lock").gameObject; m_FxManagerAdon = GetComponent(); m_CinemachineImpulseSource = GetComponent(); //Name = "Mob01"; //ObjectManagerAdon.AddMobObject(Name, this.gameObject); m_CurState = eState.Idle; } protected virtual void Start() { //m_Hero = RoleManager.Instance.GetPlayer(0) as BaseHero; m_fbx.gameObject.GetComponent().SetOwner(this.gameObject); m_Clock = Timekeeper.instance.Clock("Enemy"); m_NavMeshAgent = time.navMeshAgent.component; m_RigidbodyTimeline3D = time.rigidbody; m_NavMeshAgent.radius = 0;//去掉怪物寻路组件的碰撞范围 m_CapsuleCollider.isTrigger = true;//去掉物理碰撞启用触发方式 } // Update is called once per frame protected virtual void Update() { if (isPause) { pauseTime -= Time.deltaTime; if (pauseTime <= 0) { isPause = false; CurrentBehaviorTree.EnableBehavior(); if (m_NavMeshAgent && isDie == false) { m_NavMeshAgent.isStopped = false; } } } //受击闪光效果 if (isAttacked) { m_damageFlashScale -= time.deltaTime * 20; if (m_damageFlashScale <= 0) { m_damageFlash.gameObject.SetActive(false); m_damageFlashScale = 0; isAttacked = false; } else { m_damageFlash.gameObject.SetActive(true); } for (int l = 0; l < m_damageFlashMaterial.Length; l++) { m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); } } } /// /// 行为树暂停 /// /// 暂停时间 /// public void BehaviorTreePause(float _pauseTime) { isPause = true; pauseTime = _pauseTime; m_NavMeshAgent.isStopped = true; CurrentBehaviorTree.DisableBehavior(true); } #region ============================================ 消息触发 MSG ====================================================== /// /// 受击消息接收 /// /// public override void OnMsg_Attacked(Attacked_MsgData data) { //Debug.Log("怪物受击消息"); if (m_CurState == eState.Die) { return; } m_TargetHero = data.sender.GetComponent(); m_ForceDirection = data.forceDirection; Vector3 hitDir = data.forceDirection; //计算怪角度偏移 //float HitAngle = PlayerHelperAdon.Angle_360(transform.forward, hitDir); float HitAngle = data.HitAngle; HpbarManager.Instance.CreateHpTip(this, data.dmg, data.isCR, data.weakness);//血条及数字显示 if (data.resultHp <= 0)//死亡 { OnMsg_Die(data.attackedEffType);//发送死亡消息 } else { if (data.attackedEffType == EnumDefine.AttackedEffT.DWN)//击倒击飞 { // 只有普通怪 才播放播放受击动画 if (roleType == RoleType.Common) { BehaviorTreePause(2.5f); m_Animator.SetTrigger(hashHitDown);//播放击倒动作 SetCameraShake(transform.position, 3f, 0.1f, 0.4f);//震屏 //转向玩家 transform.LookAt(data.sender.transform); } } else if (data.attackedEffType == EnumDefine.AttackedEffT.STF) { //SetCameraShake(transform.position, 1f, 0.1f, 0.2f);//震屏 } else if (data.attackedEffType == EnumDefine.AttackedEffT.INHALE) { //SetCameraShake(transform.position, 1f, 0.1f, 0.2f);//震屏 m_Animator.SetFloat(hashMoveZ, 1);//更新移动动作 } else { // 只有普通怪 才播放播放受击动画 if (roleType == RoleType.Common) { BehaviorTreePause(1.0f); m_Animator.Play("HitTree"); m_Animator.SetFloat(hashHitAngle, HitAngle);//根据受击方向播受击动作 } } } //实例化克隆被击光效 if (data.AttackedEff && m_HitObj != null) { GameObject effobj = Instantiate(data.AttackedEff); if (!effobj.GetComponent()) effobj.gameObject.AddComponent();//添加延迟销毁脚本 effobj.transform.position = m_HitObj.position; effobj.transform.rotation = m_TargetHero.transform.rotation; effobj.SetActive(true); } if (data.SkillId == "6010221")//冰冻技 { m_freezeFlashs.gameObject.SetActive(true);//冰冻效果 //for (int l = 0; l < m_freezeFlashMaterial.Length; l++) //{ // m_freezeFlashMaterial[l].SetFloat("_Power", 2.5f); //} } else { m_damageFlash.gameObject.SetActive(true);//受击高亮材质显示 m_damageFlashScale = 3f; for (int l = 0; l < m_damageFlashMaterial.Length; l++) { m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); } } isAttacked = true; } /// /// 执行死亡指令 /// /// public void OnMsg_Die(EnumDefine.AttackedEffT attackedEffType, bool isImmDie = false) { //Debug.Log("播放死亡销毁光效"); //m_FxManagerAdon.PlayDieEff(0, false, this.m_HitObj); //RoleManager.Instance.DeleteRole(this); print("死亡"); //播放死亡特效和音效 if (isImmDie) { //RoleManager.Instance.DeleteRole(this); } else if (attackedEffType == EnumDefine.AttackedEffT.DWN)//击倒 { m_Animator.SetTrigger(hashDieDown);//播放击倒死亡动作 SetCameraShake(transform.position, 2f, 0.1f, 0.3f);//震屏 } else if (attackedEffType == EnumDefine.AttackedEffT.NOR) { //m_Animator.SetTrigger(hashDieDown);//播放击倒死亡动作 //SetCameraShake(transform.position, 2f, 0.1f, 0.3f);//震屏 } else { //死亡动作 m_Animator.SetTrigger(hashDie); m_NavMeshAgent.baseOffset = 0; SetCameraShake(transform.position, 0.8f, 0.1f, 0.2f);//震屏 } //禁用碰撞盒,寻路组件 m_CapsuleCollider.enabled = false; m_NavMeshAgent.enabled = false; //CurrentBehaviorTree.SendEvent("DieEvent"); m_CurState = eState.Die; Invoke("OnDieEnd", 2); } /// /// 发现目标消息 /// /// public override void OnMsgFindTarget() { m_Animator.SetTrigger(hashFind); } /// /// 普通打击 /// /// /// public virtual void OnMsgAttackHit(ReportDataAdon report) { //foreach (WarReportUnit heroData in report.UnitDataTarget)//遍历目标者列表 //{ m_TargetHero = RoleManager.Instance.GetRole(report.TargetId) as BaseHero; //targetHero = hero.gameObject; Attacked_MsgData data = new Attacked_MsgData();//受击消息数据 data.SkillId = report.SkillId; data.sender = this.gameObject; Vector3 force = m_Hero.transform.position - transform.position;//推力方向 force.Normalize(); data.attackedEffType = EnumDefine.AttackedEffT.STF; data.forceDirection = force;//推力方向 //计算敌人剩余血量 data.resultHp = report.resultHP; data.dmg = report.dmg; data.isCR = report.isCR;//是否暴击 data.weakness = report.weakness; if (m_FxManagerAdon.m_AttackedEff != null && m_FxManagerAdon.m_AttackedEff.Length > 0) data.AttackedEff = m_FxManagerAdon.m_AttackedEff[0].gameObject;//被击特效 m_Hero.OnMsg_Attacked(data); //if (data.resultHp <= 0)//目标死亡 //{ // //释放目标 // ReleaseTarget(); //} //} } /// /// 打击发动Debuff /// /// /// public void FireMsgDebuffNew(ReportDataAdon report) { Debug.Log("新Debuff战报触发"); Attacked_MsgData data = new Attacked_MsgData();//受击消息数据 data.buffType = report.buffType; //data.valueMove = report.BuffDataInfo.mo.moveSpeed; data.dmg = report.dmg; data.resultHp = report.resultHP; data.sender = this.gameObject; //data.AttackedEff = part.GetAttackedEff().gameObject; //data.DieEff = part.GetDieEff().gameObject; BaseHero hero = RoleManager.Instance.GetRole(report.TargetId) as BaseHero; hero.OnMsgDebuff(data); } float buffPower = 1; /// /// 执行debuff /// /// public void OnMsgDebuff(Attacked_MsgData data) { int damage; //debuff计数 if (buffnum.ContainsKey(data.buffType)) { int num = buffnum[data.buffType]; num++; buffnum[data.buffType] = num; } else { buffnum[data.buffType] = 1; } //处理buff特效资源挂载 if(buffs[data.buffType] == null) { ResourceHelper.Instance.LoadAssetBundle(data.buffResStr, ab => { if (ab != null) { GameObject model = (GameObject)Instantiate(ab.LoadAsset(data.buffResStr)); model.transform.SetParent(transform); switch(data.buffPoi) { case 0: model.transform.position = m_TopObj.position; break; case 1: model.transform.position = m_HitObj.position; break; case 2: model.transform.position = m_HitObj.position; break; case 3: model.transform.position = m_FootObj.position; break; } buffs[data.buffType] = model; } }); } //1眩晕 2静止 3护盾 4沉默 5麻痹 6灼烧 7冰冻 8中毒 switch (data.buffType) { case 6://灼烧 damage = data.dmg; ///灼烧 HpbarManager.Instance.CreateHpTip(this, -damage, false, 1.0f);//血条及数字显示 break; case 7: if (data.resultHp <= 0) { ///死亡 Debug.Log("冰冻死亡"); //播放死亡光效 if(data.DieEff) { GameObject difeff = Instantiate(data.DieEff); difeff.SetActive(true); difeff.transform.position = m_HitObj.position; } OnMsg_Die(data.attackedEffType, true);//发送死亡消息 } else { damage = data.dmg; buffPower = buffPower - 0.2f; if (buffPower <= 0) { buffPower = 0; CurrentBehaviorTree.DisableBehavior(true); } //float targetATK = report.BuffDataInfo.target.GetProperty(YLBattle.EBattleProperty.ATTACKSPEED); //float targetMove = report.BuffDataInfo.target.GetProperty(YLBattle.EBattleProperty.MOVESPEED); ///执行debuff ///缓速 ///冻结效果 SetLocalClockTimeScale(buffPower); //开启冻结网格材质 //根据冻结强度设置材质参数 float _PowerMin = 0.3f; float _PowerMax = 2.5f; float _PowerDiff = _PowerMax - _PowerMin; float materialPower = _PowerMin + _PowerDiff * buffPower; m_freezeFlashs.gameObject.SetActive(true); //m_freezeFlashPower = 5; for (int l = 0; l < m_freezeFlashMaterial.Length; l++) { m_freezeFlashMaterial[l].SetFloat("_Power", materialPower); } HpbarManager.Instance.CreateHpTip(this, -damage, false, 1.0f);//血条及数字显示 } break; case 8://中毒 damage = data.dmg; HpbarManager.Instance.CreateHpTip(this, -damage, false, 1.0f);//血条及数字显示 break; } } /// /// 关闭debuff /// /// public void OffMsgDebuff(ReportDataAdon reportData) { //debuff计数减 if (buffnum.ContainsKey(reportData.buffType)) { int num = buffnum[reportData.buffType]; num--; buffnum[reportData.buffType] = num; } if (buffnum[reportData.buffType] > 0) return; //1眩晕 2静止 3护盾 4沉默 5麻痹 6灼烧 7冰冻 8黯 switch (reportData.buffType) { case 6: break; case 7: buffPower = 1; SetLocalClockTimeScale(buffPower); for (int l = 0; l < m_freezeFlashMaterial.Length; l++) { m_freezeFlashMaterial[l].SetFloat("_Power", 2.5f); } m_freezeFlashs.gameObject.SetActive(false); CurrentBehaviorTree.EnableBehavior(); break; } buffs[reportData.buffType] = null;//销毁光效对象 } #endregion #region ============================================ 动作事件 MSB ====================================================== /// /// 移动进入 /// public void MSB_Move_Enter() { m_CurState = eState.Move; m_WeaponCol.enabled = false; //SendBehaviorVariable("IsAttacked", false); //m_RigidbodyTimeline3D.velocity = Vector3.zero; } Vector3 LastPosition; public void MSB_Move_Update(AnimatorStateInfo stateInfo) { Vector3 direction = transform.localPosition - LastPosition;//方向 float angle = PlayerHelperAdon.Angle_360(direction, transform.forward); //float angle = Vector3.Angle(direction, transform.forward); Vector3 cc = Vector3.zero; cc.x = -Mathf.Sin(angle * Mathf.Deg2Rad); cc.z = Mathf.Cos(angle * Mathf.Deg2Rad); //cc.Normalize(); m_Animator.SetFloat(hashMoveX, cc.x * m_NavMeshAgent.velocity.magnitude / m_Clock.localTimeScale * 0.5f);//更新移动动作 m_Animator.SetFloat(hashMoveZ, cc.z * m_NavMeshAgent.velocity.magnitude / m_Clock.localTimeScale * 0.5f);//更新移动动作 LastPosition = transform.localPosition; } public void MSB_Move_Exit() { m_damageFlash.gameObject.SetActive(false); m_RigidbodyTimeline3D.velocity = Vector3.zero; } /// /// 受击进入 /// public void MSB_Hit_Enter() { m_CurState = eState.Attacked; m_WeaponCol.enabled = false; } public void MSB_Hit_Update(AnimatorStateInfo stateInfo) { m_RigidbodyTimeline3D.velocity = GetForce(); //Debug.Log("推力" + m_RigidbodyTimeline3D.velocity); } public void MSB_Hit_Exit() { m_ForceDirection = Vector3.zero; m_RigidbodyTimeline3D.velocity = GetForce(); } /// /// 击飞倒进入 /// public void MSB_Down_Enter() { m_CurState = eState.Down; m_WeaponCol.enabled = false; } /// /// 击倒更新 /// /// public void MSB_Down_Update(AnimatorStateInfo stateInfo) { m_damageFlashScale -= time.deltaTime * 5; if (m_damageFlashScale <= 0) { m_damageFlash.gameObject.SetActive(false); m_damageFlashScale = 0; } for (int l = 0; l < m_damageFlashMaterial.Length; l++) { m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); } m_RigidbodyTimeline3D.velocity = GetForce(); //Debug.Log("推力" + m_RigidbodyTimeline3D.velocity); } public void MSB_Down_Exit() { m_ForceDirection = Vector3.zero; m_RigidbodyTimeline3D.velocity = GetForce(); } /// /// 死亡状态更新 /// /// public void MSB_Die_Enter() { m_CurState = eState.Die; m_WeaponCol.enabled = false; } /// /// 死亡状态更新 /// /// public void MSB_Die_Update(AnimatorStateInfo stateInfo) { m_damageFlashScale -= time.deltaTime * 5; if (m_damageFlashScale <= 0) { m_damageFlash.gameObject.SetActive(false); m_damageFlashScale = 0; } for (int l = 0; l < m_damageFlashMaterial.Length; l++) { m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); } if (stateInfo.normalizedTime > 0.9f) { GetComponent().enabled = false; } m_RigidbodyTimeline3D.velocity = GetForce(); //死亡效果 if (stateInfo.normalizedTime >= 1 && IsDieEff == false) { IsDieEff = true; //GetComponent().enabled = false; //GetComponent().enabled = false; //Destroy(GetComponent());//移除刚体 //m_RigidbodyTimeline3D.velocity = Vector3.zero; ////播放死亡光效 //m_FxManagerAdon.PlayDieEff(); ////闪红 //m_damageFlash.gameObject.SetActive(true);//受击高亮材质显示 //m_damageFlashScale = 2.5f; //for (int l = 0; l < m_damageFlashMaterial.Length; l++) //{ // m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); //} ////销毁 //Destroy(this.gameObject, 0.3f); } } /// /// 死亡状态离开 /// /// public void MSB_Die_Exit() { } public void MSB_Attack_Enter() { m_CurState = eState.Attack; transform.LookAt(new Vector3(m_Hero.transform.position.x, 0, m_Hero.transform.position.z));//看向目标 } public void MSB_Attack_Update(AnimatorStateInfo stateInfo) { //受击闪光逐渐消失 m_damageFlashScale -= time.deltaTime * 10; if (m_damageFlashScale <= 0) { m_damageFlash.gameObject.SetActive(false); m_damageFlashScale = 0; } for (int l = 0; l < m_damageFlashMaterial.Length; l++) { m_damageFlashMaterial[l].SetFloat("_Scale", m_damageFlashScale); } m_RigidbodyTimeline3D.velocity = GetForce(); } public void MSB_Attack_Exit() { } /// /// 发现目标进入 /// public void MSB_Find_Enter() { m_CurState = eState.Find; m_WeaponCol.enabled = false; } public void MSB_Find_Update(AnimatorStateInfo stateInfo) { } public void MSB_Find_Exit() { } #endregion #region Animation Event /// /// 普通攻击开始 /// public virtual void OnAttackStart(int attackId) { } /// /// 普通攻击触发 /// /// 技能id /// 子连击id public virtual void OnAttackOn(string attackId) { List list = new List(attackId.Split(',')); m_SkillId = int.Parse(list[0]); if (list.Count > 1) { m_CurAttackIdx = int.Parse(list[1]); } else { m_CurAttackIdx = 1; } m_WeaponCol.transform.localEulerAngles = Vector3.zero; m_WeaponCol.enabled = true; } /// /// 普通攻击结束 /// public virtual void OnAttackOff() { this.m_WeaponCol.enabled = false;//关闭武器碰撞 } /// /// 攻击移动触发 /// public virtual void OnAttackMoveStart(float num) { Debug.Log("执行OnAttackMoveStart.SendMessage"); Vector3 velocity = transform.forward.normalized * num; time.rigidbody.velocity = velocity; } /// /// 攻击移动触发 /// public virtual void OnAttackMoveEnd() { time.rigidbody.velocity = Vector3.zero; } /// /// 打击移动结束 /// public void OnHitMoveEnd() { m_RigidbodyTimeline3D.velocity = Vector3.zero; } /// /// 可进入极限闪避 /// public void OnExtremeDodge(float _time) { //播放可极限闪避光效 m_FxManagerAdon.PlayExtermePointEff(); //设置可进入极限闪避 m_Hero.SetExtermeTimeZone(_time); } /// /// 死亡结束,开始销毁 /// public void OnDieEnd() { Debug.Log("播放死亡销毁光效"); if (m_FxManagerAdon != null) { m_FxManagerAdon.PlayDieEff(0, false, this.transform); } RoleManager.Instance.DeleteRole(this); } #endregion ///// ///// 发送行为树参数 ///// ///// ///// //private void SendBehaviorVariable(string VariabelName,object value) //{ // if(m_BehaviorTreeManager.CurrentBehaviorTree) // //m_BehaviorTreeManager.CurrentBehaviorTree.SetVariableValue(VariabelName, value); //} /// /// 震屏 /// public void OnShake(float _velocity = 1) { //判断震屏等级 Vector3 velocity = Vector3.one * _velocity; //发送震屏消息 m_CinemachineImpulseSource.GenerateImpulseAt(this.transform.position, velocity); } //设置刚力 public void SetForce(float _Force) { m_Force = _Force; } /// /// 获取推力 /// /// public Vector3 GetForce() { Vector3 force = m_ForceDirection * m_Force; return force; } /// /// 被锁定效果 /// public void Lock() { m_Lock.SetActive(true); } /// /// 解除被锁定效果 /// public void ReleaseLock() { m_Lock.SetActive(false); if( BattleCanvas.Instance != null) { BattleCanvas.Instance.HideLockMonsterHP(); } } } }