Files
XMen/Assets/Scripts/Enemy/Boss/Boss.cs

431 lines
13 KiB
C#
Raw 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.
using System.Collections;
using System.Collections.Generic;
using BehaviorDesigner.Runtime;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.TeleTrust;
using DG.Tweening;
using DragonLi.Core;
using DragonLi.Frame;
using UnityEngine;
public class Boss : Enemy
{
public GameObject player;
public GameObject[] twoAttackObjs;
public GameObject oneAttackObj;
public GameObject bigXl;//大招蓄力特效
public GameObject mzObj;//瞄准特效
public GameObject damagableObj;//受伤特效
public GameObject qteTargetPre;
public Transform[] enemyPos;
private bool _startAttack;
private bool _isAttacking;
private bool _isShow;
public int attackMode;
public override void Init()
{
base.Init();
bigXl.SetActive(false);
mzObj.SetActive(false);
_isShow = true;
damagableObj.SetActive(false);
player = GameManager.Ins.player;
foreach (var item in components)
{
item.Stop();
}
components[^1].boxCollider.enabled = false;
bloodSlider.gameObject.SetActive(false);
enemyState = EnemyState.Show;
attackMode = 0;
}
public override void StopAttack()
{
base.StopAttack();
attackMode = 0;
components[0].Stop();
StopAllCoroutines();
_isAttacking = false;
userSillIng = false;
}
public override void ChangeHp(float value, object info, Transform _sender)
{
base.ChangeHp(value, info, _sender);
}
public void FirstShow(Vector3 enemyDoorPos)
{
enemyState = EnemyState.FirstShow;
isShield = true;
GameInit.Ins.PlayAudio("1.2",transform,true, () =>
{
StartCoroutine(FirstShowTor( enemyDoorPos));
});
}
IEnumerator FirstShowTor(Vector3 enemyDoorPos)
{
var go= GameManager.Ins.CreateEnemyDoor(enemyDoorPos, Vector3.zero,Vector3.one*3 );
go.GetComponent<EnemyDoor>().desTime = 10;
go.GetComponent<EnemyDoor>().InitData();
yield return new WaitForSeconds(2f);
transform.DORotate(new Vector3(0, 180, 0), 2f).OnComplete(() =>
{
AnimatorComponent.SetFloat("speedf",1);
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_Tansuozhongxin)
{
transform.DOMoveZ(-5, -10).OnComplete(() =>
{
Destroy(gameObject);
});
}
else
{
transform.DOMoveZ(-5, 4).OnComplete(() =>
{
Destroy(gameObject);
});
}
});
}
public override void Show()
{
base.Show();
isAttack = false;
isShield = true;
_isShow = true;
AnimatorComponent.SetFloat("speedf",1);
GameInit.Ins.PlayAudio("1.16",GameInit.Ins.self.transform,true);
float endValue = 10;
if (GameInit.Ins.gamePlace == GamePlace.HangZhouLongHuTianJie)
endValue = 20.5f;
if (GameInit.Ins.gamePlace == GamePlace.Yangzhou_Hanjiang_Tansuozhongxin)
endValue = -4.5f;
if (GameInit.Ins.gamePlace == GamePlace.Guangzhou_Panyv_Zhanting)
endValue = 3f;
if (GameInit.Ins.gamePlace == GamePlace.Anhui_Wuhu_Guanwei)
endValue = 4.5f;
if (GameInit.Ins.gamePlace == GamePlace.ShanDong_Langfang_QingzhouTaihuacheng)
endValue = 18f;
if(GameInit.Ins.gamePlace == GamePlace.Shandong_Jining_Wai)
{
transform.DOMove(new Vector3(22.5f,transform.position.y,-0.5f), 4).OnComplete(() =>
{
Both();
});
}
else
{
transform.DOMoveZ(endValue, 4).OnComplete(() =>
{
Both();
});
}
}
public void Both()
{
AnimatorComponent.SetFloat("speedf",0);
AnimatorComponent.SetBool("isBoth",true);
GameInit.Ins.PlayAudio("1.14",transform,true);
_isShow = false;
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
AnimatorComponent.SetBool("isBoth",false);
isAttack = true;
bloodSlider.gameObject.SetActive(true);
isShield = false;
},6f);
}
public override void Attack()
{
base.Attack();
if (!_isAttacking)
{
_isAttacking = true;
attackMode=Random.Range(1,4);
}
}
public override void OneAttackMode()
{
base.OneAttackMode();
PerformThrowShield();
}
[Header("盾牌投掷")]
[Tooltip("盾牌预制体")]
public GameObject shieldPrefab;
[Header("盾牌参数")]
public float shieldSpeed = 30f;
public float groundY = 0.5f;
public float stayTime = 2f;
private float hitRadius = 1f;
private float damageAmount = 3000f;
//// <summary>
/// 外部调用:让 Boss 执行投掷盾牌技能
/// </summary>
public void PerformThrowShield()
{
attackMode = 4;
AnimatorComponent.SetBool("isCastEnd",true);
}
/// <summary>
/// 盾牌飞回 Boss 手时自动调用,结束投掷动画
/// </summary>
private void OnShieldReturned()
{
AnimatorComponent.SetBool("isCastEnd",false);
components[1].GetComponent<MeshRenderer>().enabled = true;
attackMode = 0;
userSillIng = false;
}
public override void Show2()
{
base.Show2();
StopAllCoroutines();
}
//释放剑雨
public override void TwoAttackMode()
{
//base.TwoAttackMode();
userSillIng = true;
attackMode = 5;
AnimatorComponent.SetBool("isCastEnd",true);
}
public override void StartQteAttack()
{
attackMode = 6;
AnimatorComponent.SetBool("isCastEnd",false);
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
bigXl.SetActive(true);
mzObj.SetActive(true);
},2f);
}
public override void BossQteAttack()
{
base.BossQteAttack();
AnimatorComponent.SetBool("isCastEnd",true);
attackMode = 0;
bigXl.SetActive(false);
mzObj.SetActive(false);
}
public void QteAttack()
{
damagableObj.SetActive(true);
qteTargetPre.transform.position = player.transform.position;
player.GetComponent<IDamagable>().ApplyDamage(GameInit.Ins.self.maxHp/2,null,transform);
shieldObj.SetActive(false);
isShield = false;
}
public override void StopQteAttack()
{
base.StopQteAttack();
bigXl.SetActive(false);
mzObj.SetActive(false);
components[^1].StopQteAttack();
shieldObj.SetActive(false);
isShield = false;
attackMode = 0;
}
public override void Update()
{
base.Update();
AnimatorComponent.SetInteger("attackMode",attackMode);
if(_isShow) return;
// 平滑朝向玩家
Vector3 targetDir = GameManager.Ins.player.transform.position - transform.position;
targetDir.y = 0f;
if (targetDir != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(targetDir);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f);
}
curEnemyTime-=Time.deltaTime;
if (curEnemyTime <=0 )
{
if(GameManager.Ins.GetCurEnemyListCount()<=8)
ShowEnemy();
curEnemyTime = enemyTime;
}
}
private float enemyTime=45f;
private float curEnemyTime;
public void ShowEnemy()
{
List<int> enemyList = new List<int>(){1, 4, 6};
for (int i = 0; i < enemyPos.Length; i++)
{
Vector3 curEnemyPos = new Vector3(enemyPos[i].position.x, 0, enemyPos[i].position.z);
GameManager.Ins.CreateCallEnemyEffect(curEnemyPos);
}
MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
{
for (int i = 0; i < enemyPos.Length; i++)
{
int index = Random.Range(0, 3);
Vector3 curEnemyPos = new Vector3(enemyPos[i].position.x, 0, enemyPos[i].position.z);
GameManager.Ins.CreateEnemy(enemyList[index], curEnemyPos, Vector3.zero, false);
}
}, 2f);
}
public override void Dead()
{
base.Dead();
GameManager.Ins.WinEndGame();
GameInit.Ins.PlayAudio("1.15",GameInit.Ins.self.transform,true);
}
public void Play1Attack()
{
components[0].CmdFire2(player.transform.position);
GameInit.Ins.PlayAudio("2.32砸击",transform,false);
}
public void Play2Attack()
{
components[1].GetComponent<MeshRenderer>().enabled = false;
// 2. 实例化盾牌并初始化
GameObject shieldGO = Instantiate(shieldPrefab, components[1].transform.position, Quaternion.identity);
ShieldProjectile sp = shieldGO.GetComponent<ShieldProjectile>();
if (sp != null)
{
sp.Initialize(
player.transform,
components[1].transform,
shieldSpeed,
groundY,
stayTime,
hitRadius,
damageAmount);
// 3. 订阅盾牌返回完成事件
sp.OnReturnComplete += OnShieldReturned;
}
else
{
Debug.LogError("BossController: 盾牌预制体上缺少 ShieldProjectile 脚本");
}
}
[Header("剑雨攻击配置")]
[Tooltip("可飞行的剑预制体")]
public GameObject swordProjectilePrefab;
[Tooltip("剑飞行速度")]
public float swordFlySpeed = 15f;
[Tooltip("剑落地后停留时间")]
public float swordStayTime = 2f;
[Tooltip("剑击中玩家半径")]
public float swordHitRadius = 1f;
[Tooltip("剑造成的伤害")]
private float swordDamage = 500f;
[Tooltip("剑起飞时的高度偏移")]
public float swordHeightOffset = 5f;
/// <summary>
/// 对外调用:触发一次剑雨攻击
/// </summary>
public void SwordRainAttack()
{
isShield = true;
if (shieldObj)
shieldObj.SetActive(true);
StartCoroutine(FlySword());
}
IEnumerator FlySword()
{
int index = 0;
// 2. 每个挂点都取一个“剑模型”数据,实例化为可飞行的 SwordProjectile
foreach (var item in twoAttackObjs)
{
var anchor= item.GetComponent<Transform>();
// 2.1 如果挂点下有“子物体”是剑模型,先隐藏它
anchor.GetComponent<MeshRenderer>().enabled = false;
Transform showPos = anchor;
if (anchor.childCount > 0)
{
showPos= anchor.GetChild(0);
}
// 2.2 实例化一个 SwordProjectile 并初始化
Vector3 spawnPos = anchor.position + Vector3.up * swordHeightOffset;
GameObject swordGO = Instantiate(swordProjectilePrefab, spawnPos, Quaternion.identity);
SwordProjectile sp = swordGO.GetComponent<SwordProjectile>();
if (sp != null)
{
sp.Initialize(
player.transform,
showPos,
swordFlySpeed,
groundY,
swordStayTime,
swordHitRadius,
swordDamage);
sp.OnReturnComplete += () => OnSingleSwordReturned(anchor);
index++;
if(index%2==0)
yield return new WaitForSeconds(1.5f);
}
else
{
Debug.LogError("SwordRainAttack: 未在 swordProjectilePrefab 上找到 SwordProjectile 脚本");
}
}
}
/// <summary>
/// 某把剑返回到 backPoint挂点时调用
/// 我们在所有剑都返回完毕时,再结束投掷动画
/// </summary>
private int swordsReturnedCount = 0;
private void OnSingleSwordReturned(Transform anchor)
{
// 显示挂回到背部的“原始剑模型”:
anchor.GetComponent<MeshRenderer>().enabled = true;
swordsReturnedCount++;
// 如果所有挂点的剑都已经返回,则动画结束
if (swordsReturnedCount >= twoAttackObjs.Length)
{
OnAllSwordsReturned();
}
}
private void OnAllSwordsReturned()
{
// 重置计数
swordsReturnedCount = 0;
AnimatorComponent.SetBool("isCastEnd",false);
attackMode = 0;
userSillIng = false;
isShield = false;
if (shieldObj)
shieldObj.SetActive(false);
}
}