Files
XMen/Assets/Scripts/Enemys/RobotMech/RobotMech.cs
2025-07-10 14:49:53 +08:00

337 lines
8.8 KiB
C#

using DragonLi.Frame;
using UnityEngine;
using DragonLi.Core;
using DG.Tweening;
using BehaviorDesigner.Runtime;
using Mirror;
public class RobotMech : XAgent
{
private const float kRotationDuring = 1.1f;
private static readonly int kShootHash = Animator.StringToHash("shoot");
private static readonly int kRotationHash = Animator.StringToHash("rotation");
private static readonly int kNeedRotationHash = Animator.StringToHash("needRotate");
private Transform player;
private Vector3 faceTarget;
private bool Shooting = false;
public BloodSlider BloodSlider;
public RobotGun[] launchers;
public GameObject zadi;
public float height = 10f;
public GameObject speak;
public Animator gunAnimator;
public Animator gunAnimator2;
public BehaviorTree behavior;
public GameObject explosion_prefab;
public float explosion_despawn_time = 4f;
public float xSpeed = 10f;
public float xAcc = 30f;
public float xHealth = 50000f;
public float xAtk = 10;
public Vector3 XPatrol_position = new Vector3(0, 0, 0);
//public int Id;
/// <summary>
/// 落地
/// </summary>
public AudioClip lanOn;
/// <summary>
/// 架枪
/// </summary>
public AudioClip stackArms;
/// <summary>
/// 说话
/// </summary>
public AudioClip speack;
///
public AudioSource audioSource;
[SyncVar]
public float blood;
[Server]
public void StackArms()
{
audioSource.PlayOneShot(stackArms, 0.8f);
}
public override void InitData()
{
base.InitData();
type = (int)EnemyType.RobotMech;
EnemyInfo enemyInfo = GameManager.Ins.EnemyDescInfos[(int)EnemyType.RobotMech];
DifficultyInfo difficultyInfo = GameManager.Ins.DifficultyescInfos[StoryManager.Ins.gameDifficulty];
BloodSlider.SetName(enemyInfo.NameCN);
xHealth = enemyInfo.Hp * difficultyInfo.enemyHpCoefficient * MRNetworkManager.Ins.roomSlots.Count * 0.7f;
xAtk = enemyInfo.Atk * difficultyInfo.damageCoefficient;
Data["health"].FloatValue = xHealth;
blood = xHealth;
Data["acc"].FloatValue = xAcc;
Data["speed"].FloatValue = xSpeed;
Data["atk"].FloatValue = xAtk;
Data["patrol_position"].Vector3Value = XPatrol_position;
Data.Add("explosion_despawn_time", new DataRow(SupportDataType.Float)
{
Name = "explosion_despawn_time",
FloatValue = explosion_despawn_time
});
Data.Add("nature_recoil", new DataRow(SupportDataType.Boolean)
{
Name = "nature_recoil",
BooleanValue = true
}); ;
}
[Server]
public override void OnSpawn()
{
base.OnSpawn();
Data["nature_recoil"].BooleanValue = true;
EventDispatcher.TriggerEvent("SpwanPoint", transform);
player = GameManager.Ins.GetPlayer1();
NavAgent.enabled = false;
behavior.enabled = true;
ColliderComponent.enabled = true;
Data["attackmode"].BooleanValue = false;
Data["rotating"].BooleanValue = false;
behavior.RegisterEvent("RotateToPlayer", RotateToPlayer);
behavior.RegisterEvent("Attack", Attack);
behavior.RegisterEvent("StopAttack", StopAttack);
behavior.RegisterEvent("RotateToNext", RotateToNext);
Vector3 nowPos = transform.position;
transform.position = new Vector3(nowPos.x, height, nowPos.z);
transform.DOMove(nowPos, 0.5f).SetEase(Ease.InBack).OnComplete(() =>
{
Debug.Log("移动结束");
audioSource.PlayOneShot(speack, 1f);
zadi.SetActive(true);
ZadiOpen();
audioSource.PlayOneShot(lanOn);
NavAgent.enabled = transform;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NavAgent.enabled = true;
speak.SetActive(true);
}, 1.5f);
});
}
[ClientRpc]
public void ZadiOpen()
{
zadi.SetActive(true);
}
public void RotateToPlayer()
{
RotateToTarget(player.position);
}
public void RotateToNext()
{
Debug.Log("RotateToNext");
RotateToTarget(player.position);
}
protected override void OnUpdate()
{
if (!IsAlive)
return;
Shoot();
}
//protected override void OnReceiveMessage(string msg, object info)
//{
// switch (msg)
// {
// case "Attack":
// Attack();
// break;
// case "StopAttack":
// StopAttack();
// break;
// case "RotateToPlayer":
// RotateToTarget(player.position);
// break;
// case "RotateToNext":
// RotateToTarget(Data["patrol_position"].Vector3Value);
// break;
// }
//}
[Server]
public override void OnHeathChanged(float currentHealth)
{
base.OnHeathChanged(currentHealth);
HealthChange(currentHealth);
}
[ClientRpc]
public void HealthChange(float currentHealth)
{
if (BloodSlider != null)
{
BloodSlider.SetValue2(currentHealth, blood);
}
}
[Server]
public override void ApplyDamage(float value, object info, Transform _sender)
{
base.ApplyDamage(value, info, _sender);
if (_sender != null)
{
int ownerIndx = _sender.GetComponent<Bullet>().ownerIndex;
RpcDamage(value, (bool)info, ownerIndx);
}
}
[ClientRpc]
public void RpcDamage(float value, bool info, int ownerIndx)
{
if (GameInit.Ins.self.index == ownerIndx)
{
BloodSlider.CreateDamagePre(value, info);
Debug.Log("收到伤害 ClientRpc:");
}
}
[Server]
public override void OnDeath(object info, Transform _sender)
{
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(transform.gameObject);
SpawnExplosion();
GameManager.Ins.CreateItemDrop(index, transform.position);
if (GameManager.Ins.EnemyDie())
{
StoryManager.Ins.CreateStoryItem();
GameManager.Ins.ShowLandmark(8, 9);
}
}, 0.5f);
}
[Server]
public void SpawnExplosion()
{
if (explosion_prefab != null)
{
GameObject explosion = Instantiate(explosion_prefab);
explosion.transform.position = transform.position;
NetworkServer.Spawn(explosion);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
NetworkServer.Destroy(explosion);
}, Data["explosion_despawn_time"].FloatValue);
}
}
public void RotateToTarget(Vector3 target)
{
faceTarget = target;
SetRotateState(GetAngleStep());
}
private void RotateToPlayerIfShooting()
{
if (Shooting)
RotateToTarget(player.transform.position);
}
[Server]
private void Shoot()
{
gunAnimator.SetBool("shoot",Shooting);
gunAnimator2.SetBool("shoot",Shooting);
if (!Shooting)
return;
Shot();
}
private void Shot()
{
launchers[0].Shoot(launchers[0].LaunchPoint.position + launchers[0].LaunchPoint.forward * 1.0f, -1);
launchers[1].Shoot(launchers[1].LaunchPoint.position + launchers[0].LaunchPoint.forward * 1.0f, -1);
}
private void Attack()
{
AnimatorComponent.SetBool(kShootHash, true);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
Shooting = true;
}, 2.0f);
}
private void StopAttack()
{
// set animator
AnimatorComponent.SetBool(kShootHash, false);
// stop shooting
Shooting = false;
}
private void SetRotateState(float angle)
{
bool state = Mathf.Abs(angle) > 5.0f;
AnimatorComponent.SetBool(kNeedRotationHash, state);
AnimatorComponent.SetFloat(kRotationHash, angle);
}
private void OnRotateFinishedCallback()
{
// start to rotate
SetRotateState(GetAngleStep());
}
private float GetAngleStep()
{
//Debug.Log("faceTarget" + faceTarget);
// get target direction
Vector3 direction = (faceTarget - transform.position).ReflectVectorXOZ();
// get angle (0, 180]
float angle = Vector3.Angle(transform.forward.ReflectVectorXOZ(), direction);
// angle
if (Mathf.Abs(angle) > 90.0f)
angle /= 2.0f;
// left or right?
if (Vector3.Cross(transform.forward.ReflectVectorXOZ(), direction).y < 0)
angle *= -1;
return angle;
}
private bool IsRotating()
{
return Data["rotating"].BooleanValue;
}
}