245 lines
5.7 KiB
C#
245 lines
5.7 KiB
C#
using BehaviorDesigner.Runtime;
|
|
using DG.Tweening;
|
|
using DragonLi.Core;
|
|
using DragonLi.Frame;
|
|
using Mirror;
|
|
using System.Collections.Generic;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
|
|
public class Shadow : XAgent
|
|
{
|
|
public BehaviorTree behavior;
|
|
|
|
public float xSpeed = 10f;
|
|
public float xAcc = 30f;
|
|
public float xHealth = 100f;
|
|
public float xAtk = 10;
|
|
public float attackArea = 2.0f;
|
|
|
|
public SkinnedMeshRenderer[] models;
|
|
public MeshRenderer[] swords;
|
|
|
|
public BloodSlider BloodSlider;
|
|
|
|
public GameObject explosion_prefab;
|
|
public float explosion_despawn_time = 4f;
|
|
private List<GameObject> casts = new List<GameObject>();
|
|
|
|
public AudioSource enemyAudio;
|
|
public AudioClip atkClip;
|
|
|
|
[Server]
|
|
public override void OnSpawn()
|
|
{
|
|
base.OnSpawn();
|
|
NavAgent.enabled = true;
|
|
behavior.enabled = true;
|
|
ColliderComponent.enabled = true;
|
|
behavior.RegisterEvent("Attack", Attack);
|
|
behavior.RegisterEvent("Cast", Cast);
|
|
DOVirtual.Float(0, 255, 1f, (res) =>
|
|
{
|
|
UpdateFade(res);
|
|
});
|
|
}
|
|
|
|
public void SetPathId(string pathid)
|
|
{
|
|
transform.GetComponent<BehaviorTree>().SetVariableValue("pathId", pathid);
|
|
}
|
|
|
|
[Server]
|
|
internal override void Update()
|
|
{
|
|
base.Update();
|
|
if (IsAlive && NavAgent.isActiveAndEnabled)
|
|
{
|
|
//UpdateFade(NavAgent.velocity);
|
|
//UpdateUI(NavAgent.velocity);
|
|
}
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (IsAlive && isServer)
|
|
{
|
|
UpdateRotation();
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
public void Attack()
|
|
{
|
|
Debug.Log("Attack");
|
|
Shield shield = GameManager.Ins.GetCanAttackShield(transform.position, LockPlayer, attackArea);
|
|
if (shield != null)
|
|
{
|
|
shield.ApplyDamage(xAtk, null, null);
|
|
}
|
|
else
|
|
{
|
|
if (GameManager.Ins.IsCanAttackPlayer(transform, LockPlayer, attackArea))
|
|
{
|
|
IDamagable damagable = MRNetworkManager.Ins.roomSlots[LockPlayer].GetComponent<IDamagable>();
|
|
if (damagable != null)
|
|
{
|
|
damagable.ApplyDamage(xAtk, null, transform);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
[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 void Cast()
|
|
{
|
|
if (IsAlive)
|
|
{
|
|
Debug.Log("召唤");
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
Vector3 pos = DragonLi.Frame.Utils.GetNearRandomPositionOnNavmesh(transform.position, 2f);
|
|
GameObject cast = GameManager.Ins.GenerateEnemy(EnemyType.ShadowCast, pos, Vector3.zero, new Vector3(0.85F, 0.85F, 0.85F));
|
|
casts.Add(cast);
|
|
}
|
|
}
|
|
}
|
|
|
|
[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 override void InitData()
|
|
{
|
|
base.InitData();
|
|
type = (int)EnemyType.Shadow;
|
|
EnemyInfo enemyInfo = GameManager.Ins.EnemyDescInfos[(int)EnemyType.Shadow];
|
|
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;
|
|
//xHealth *= GameManager.Ins.difficulty[GameManager.Ins.players.Count - 1];
|
|
Data["health"].FloatValue = xHealth;
|
|
OriginHealth = xHealth;
|
|
Data["acc"].FloatValue = xAcc;
|
|
Data["speed"].FloatValue = xSpeed;
|
|
Data["atk"].FloatValue = xAtk;
|
|
Data.Add("explosion_despawn_time", new DataRow(SupportDataType.Float)
|
|
{
|
|
Name = "explosion_despawn_time",
|
|
FloatValue = explosion_despawn_time
|
|
});
|
|
}
|
|
|
|
private void UpdateFade(float fadeRate)
|
|
{
|
|
for (int i = 0; i < models.Length; i++)
|
|
{
|
|
models[i].material.SetFloat("_RongJieIntensity", fadeRate / 255f);
|
|
}
|
|
for (int i = 0; i < swords.Length; i++)
|
|
{
|
|
swords[i].material.SetFloat("_RongJieIntensity", fadeRate / 255f);
|
|
}
|
|
}
|
|
|
|
private void UpdateRotation()
|
|
{
|
|
if (IsAlive && (bool)(behavior.GetVariable("face2Player").GetValue()))
|
|
{
|
|
Transform player = MRNetworkManager.Ins.roomSlots[LockPlayer].transform;
|
|
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(player.position - transform.position), 20 * Time.deltaTime);
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
public override void OnHeathChanged(float currentHealth)
|
|
{
|
|
base.OnHeathChanged(currentHealth);
|
|
HealthChange(currentHealth);
|
|
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void HealthChange(float currentHealth)
|
|
{
|
|
if (BloodSlider != null)
|
|
{
|
|
// Debug.Log("当前血量" + currentHealth);
|
|
BloodSlider.SetValue2(currentHealth, OriginHealth);
|
|
}
|
|
}
|
|
|
|
[Server]
|
|
public override void OnDeath(object info, Transform _sender)
|
|
{
|
|
ColliderComponent.enabled = false;
|
|
AnimatorComponent.SetBool("Dead", true);
|
|
DisappearCasts();
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
// DisappearCasts();
|
|
NetworkServer.Destroy(transform.gameObject);
|
|
SpawnExplosion();
|
|
GameManager.Ins.CreateItemDrop(index, transform.position);
|
|
if (GameManager.Ins.EnemyDie())
|
|
{
|
|
StoryManager.Ins.CreateStoryItem();
|
|
GameManager.Ins.ShowLandmark(10, 11);
|
|
}
|
|
}, 3.5f);
|
|
}
|
|
|
|
public void DisappearCasts()
|
|
{
|
|
foreach (GameObject cast in casts)
|
|
{
|
|
if (cast != null && !cast.IsDestroyed())
|
|
{
|
|
cast.GetComponent<IDamagable>().ApplyDamage(9999999f, true, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PlayAttackClip()
|
|
{
|
|
enemyAudio.clip = atkClip;
|
|
enemyAudio.Play();
|
|
}
|
|
}
|