269 lines
7.0 KiB
C#
269 lines
7.0 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using DG.Tweening;
|
||
using DragonLi.Core;
|
||
using UnityEngine;
|
||
|
||
public class Tentacle : Enemy
|
||
{
|
||
public float upIndex;
|
||
private float downIndex=-7;
|
||
|
||
public GameObject model;
|
||
public GameObject atkEx;
|
||
|
||
public AnimationClip idleAnim;
|
||
public AnimationClip atkAnim;
|
||
public AnimationClip spikeAnim;
|
||
public AnimationClip dieAnim;
|
||
|
||
public Animation anim;
|
||
|
||
public EnemyBoneHit[] skill1BoneHits;
|
||
public EnemyBoneHit[] skill1ExBoneHits;
|
||
public EnemyBoneHit[] skill2BoneHits;
|
||
|
||
private Vector3 _startPos;
|
||
private bool isAttacking;
|
||
private Quaternion _originRot;
|
||
private float rotateSpeed = 360f; // 每秒旋转角度
|
||
|
||
private void Start()
|
||
{
|
||
_startPos = transform.position;
|
||
atkEx.SetActive(false);
|
||
foreach (var item in skill1BoneHits)
|
||
{
|
||
item.gameObject.SetActive(false);
|
||
}
|
||
foreach (var item in skill2BoneHits)
|
||
{
|
||
item.gameObject.SetActive(false);
|
||
}
|
||
foreach (var item in skill1ExBoneHits)
|
||
{
|
||
item.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
public override void SetData(EnemyData data)
|
||
{
|
||
base.SetData(data);
|
||
enemyState = EnemyState.Show;
|
||
health = Data.Hp_CS1;
|
||
maxHealth = Data.Hp_CS1;
|
||
bloodSlider.SetName("巨妖触手");
|
||
isDead = false;
|
||
isShowEnd = false;
|
||
}
|
||
|
||
public void EndShow()
|
||
{
|
||
enemyState = EnemyState.Idle;
|
||
}
|
||
|
||
void PlayIdle()
|
||
{
|
||
if(isDead)
|
||
return;
|
||
anim.clip = idleAnim;
|
||
anim.wrapMode = WrapMode.Loop;
|
||
anim.Play();
|
||
|
||
GameManager.Ins.PlaySound3D("1.18",transform);
|
||
}
|
||
|
||
public IEnumerator Attack(bool isFurious)
|
||
{
|
||
if (isAttacking||isDead)
|
||
yield break;
|
||
isAttacking = true;
|
||
|
||
// ⭐ 记录初始朝向
|
||
_originRot = transform.rotation;
|
||
GameManager.Ins.PlaySound3D("1.8",transform);
|
||
// 0️⃣ 攻击前转向玩家
|
||
yield return RotateToPlayer();
|
||
|
||
// 1️⃣ 前摇
|
||
yield return new WaitForSeconds(0.8f);
|
||
|
||
// 2️⃣ 播放攻击动画
|
||
anim.clip = atkAnim;
|
||
anim.wrapMode = WrapMode.Once;
|
||
anim.Play();
|
||
|
||
BeginAttack();
|
||
|
||
// 3️⃣ 等到第 45 帧
|
||
float hitTime = 45f / atkAnim.frameRate;
|
||
yield return new WaitForSeconds(hitTime);
|
||
GameManager.Ins.PlaySound3D("1.9",transform,true);
|
||
// 4️⃣ 攻击判定 / 特效
|
||
DoAttackHit(isFurious);
|
||
|
||
// 5️⃣ 等动画播完
|
||
float remainTime = atkAnim.length - hitTime;
|
||
if (remainTime > 0)
|
||
yield return new WaitForSeconds(remainTime);
|
||
|
||
// ⭐ 攻击结束后转回
|
||
yield return RotateBack();
|
||
|
||
// 6️⃣ 切回 Idle
|
||
PlayIdle();
|
||
EndAttack();
|
||
|
||
isAttacking = false;
|
||
}
|
||
|
||
IEnumerator RotateToPlayer()
|
||
{
|
||
Transform player = GameManager.Ins.player.transform;
|
||
|
||
Vector3 dir = player.position - transform.position;
|
||
dir.y = 0;
|
||
|
||
if (dir.sqrMagnitude < 0.01f)
|
||
yield break;
|
||
|
||
Quaternion targetRot = Quaternion.LookRotation(dir);
|
||
|
||
while (Quaternion.Angle(transform.rotation, targetRot) > 1f)
|
||
{
|
||
transform.rotation = Quaternion.RotateTowards(
|
||
transform.rotation,
|
||
targetRot,
|
||
rotateSpeed * Time.deltaTime
|
||
);
|
||
yield return null;
|
||
}
|
||
}
|
||
|
||
IEnumerator RotateBack()
|
||
{
|
||
while (Quaternion.Angle(transform.rotation, _originRot) > 1f)
|
||
{
|
||
transform.rotation = Quaternion.RotateTowards(
|
||
transform.rotation,
|
||
_originRot,
|
||
rotateSpeed * Time.deltaTime
|
||
);
|
||
yield return null;
|
||
}
|
||
}
|
||
|
||
public override void EndAttack()
|
||
{
|
||
base.EndAttack();
|
||
foreach (var item in skill1BoneHits)
|
||
{
|
||
item.gameObject.SetActive(false);
|
||
}
|
||
foreach (var item in skill1ExBoneHits)
|
||
{
|
||
item.gameObject.SetActive(true);
|
||
}
|
||
}
|
||
|
||
void DoAttackHit(bool isFurious)
|
||
{
|
||
// 开启攻击特效
|
||
atkEx.SetActive(true);
|
||
// 一小段时间后关闭特效
|
||
StartCoroutine(HideAtkEx(isFurious));
|
||
}
|
||
|
||
IEnumerator HideAtkEx(bool isFurious)
|
||
{
|
||
yield return new WaitForSeconds(1f);
|
||
foreach (var item in skill1BoneHits)
|
||
{
|
||
item.gameObject.SetActive(true);
|
||
item.SetDamage(isFurious? Data.Atk_1B: Data.Atk_1P);
|
||
}
|
||
foreach (var item in skill1ExBoneHits)
|
||
{
|
||
item.gameObject.SetActive(true);
|
||
item.SetDamage(isFurious? Data.Atk_1B: Data.Atk_1P);
|
||
//item.SetScale(new Vector3(0.5f,0,10),0.5f,new Vector3(1.77f,10,2.33f));
|
||
}
|
||
atkEx.SetActive(false);
|
||
}
|
||
public void Hide()
|
||
{
|
||
GameManager.Ins.PlaySound3D("1.15",transform,true);
|
||
bloodSlider.gameObject.SetActive(false);
|
||
model.transform.DOMoveY(downIndex, 1f).OnComplete(() =>
|
||
{
|
||
model.SetActive(false);
|
||
});
|
||
}
|
||
|
||
public void Spike(Vector3 pos)
|
||
{
|
||
model.SetActive(true);
|
||
model.transform.position = new Vector3(pos.x, downIndex, pos.z);
|
||
anim.clip = spikeAnim;
|
||
anim.wrapMode = WrapMode.Once;
|
||
anim.Play();
|
||
BeginAttack();
|
||
foreach (var item in skill2BoneHits)
|
||
{
|
||
item.SetDamage(Data.Atk_3);
|
||
}
|
||
model.transform.DOMoveY(upIndex,1).SetEase(Ease.OutBounce).OnComplete(() =>
|
||
{
|
||
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
||
{
|
||
if(isDead)
|
||
return;
|
||
EndAttack();
|
||
model.transform.DOMoveY(downIndex,1).SetEase(Ease.OutBounce).OnComplete(() =>
|
||
{
|
||
transform.position=new Vector3(_startPos.x,downIndex,_startPos.z);
|
||
model.transform.localPosition=Vector3.zero;
|
||
PlayIdle();
|
||
transform.DOMoveY(upIndex,1).SetEase(Ease.OutBounce);
|
||
});
|
||
}, 3f);
|
||
});
|
||
}
|
||
|
||
public void RefreshToBoss()
|
||
{
|
||
if(isDead)
|
||
return;
|
||
_startPos=transform.position;
|
||
|
||
model.SetActive(true);
|
||
model.transform.DOLocalMoveY(upIndex, 1).OnComplete(() =>
|
||
{
|
||
bloodSlider.gameObject.SetActive(true);
|
||
});
|
||
}
|
||
|
||
public override void ChangeHp(float value, object info, Transform _sender)
|
||
{
|
||
if(enemyState== EnemyState.Show)
|
||
return;
|
||
base.ChangeHp(value, info, _sender);
|
||
if(isDead)
|
||
return;
|
||
GameManager.Ins.PlaySound3D("1.10",transform);
|
||
}
|
||
|
||
public override void Dead()
|
||
{
|
||
base.Dead();
|
||
anim.clip = dieAnim;
|
||
anim.wrapMode = WrapMode.Once;
|
||
anim.Play();
|
||
GameManager.Ins.PlaySound3D("1.11",transform,true);
|
||
transform.parent = null;
|
||
StopAllCoroutines();
|
||
}
|
||
}
|
||
|