// *********************************************************************** // Assembly : Game // Author : Kimch // Created : 2021-01-09 // Description : // Last Modified By : // Last Modified On : // *********************************************************************** // // // *********************************************************************** using System.Collections; using System.Collections.Generic; using UnityEngine; namespace G { /// /// 敌人 /// public class EntityEnemy : EntityCha { #region Field private float _lifeTime; /// /// 毒药 /// protected bool _poison; protected float _poisonDamage; protected float _poisonDelay; protected int _lastPoisonDelay; /// /// 刺 /// protected bool _pierce; /// /// /// protected bool _risedrop; protected float _riseFactor; /// /// 狂暴 /// protected float _rampage; /// /// 狂暴 /// protected float _rampageDelay; /// /// /// protected bool _resetTarget; /// /// 固定目标 /// protected bool _fixedTarget; /// /// 约束范围 /// protected float _restrictArea; /// /// /// protected int _behaviour; protected float _behaviourDelay = 2f; /// /// /// protected Vector3 _direction; protected Vector3 _behitDirection; protected Vector3 _attackStartDirection; protected Vector3 _attackStartPosition; /// /// /// protected Transform _target; protected Transform _cha1; protected EntityMainPlayer _scriptCha; /// /// /// protected Renderer _mainRender; protected Texture _originTex; // protected int _attributeStatus; // protected bool _showArrow; /// /// 方向箭头 /// protected Transform _cloneArrow; #endregion #region Property /// /// /// public int attack { get; set; } /// /// /// public int defence { get; set; } /// /// /// public int block { get; set; } public float moveSpeed { get; set; } /// /// /// public int moveState { get; set; } float _timeTimeFactor = 1f; protected float deltaTime { get { return Time.deltaTime * _timeTimeFactor; } } #endregion #region Method protected override void OnViewInitCompleted() { base.OnViewInitCompleted(); _timeTimeFactor = 1f; var viewGO = entityView.gameObject; gameObject.layer = viewGO.layer; gameObject.tag = viewGO.tag; var viewTr = entityView.transform; _mainRender = viewTr.GetChild(0).GetComponent(); if (!_mainRender) _mainRender = viewTr.GetComponentInChildren(); _originTex = _mainRender.material.mainTexture; } protected void InitRigbody(float mass) { var rb = gameObject.AddComponent(); rb.mass = mass; rb.drag = 5f; rb.angularDrag = 5f; rb.useGravity = false; rb.constraints = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ; SetRigidbody(rb); } int _shadowIndex = -1; public override void SetShadowVisible(bool visible) { if (visible) { if (_shadowIndex == -1) _shadowIndex = EnemyHelper.Instance.CreateShadow(transform.GetChild(0), 1f); } else { if (_shadowIndex >= 0) EnemyHelper.Instance.DestroyShadow(_shadowIndex); _shadowIndex = -1; } } /// /// /// /// /// /// /// public void SetDamageNumber(Vector3 pos, int damage, Vector3 dir, int crit = 0) { var damageBoard = BoardManager.Instance.CreateDamageBoard(crit == 0 ? "DamageBoard2" : "DamageBoard1"); damageBoard.SetValue(damage, DamageBoardType.ENEMY_HP_SUB); damageBoard.SetPosition(pos); } /// /// /// /// public Transform GetDefaultTarget() { return _cha1; } /// /// /// /// public void ShowArrow(bool visible) { _showArrow = visible; if (_cloneArrow) _cloneArrow.gameObject.SetActive(visible); } /// /// /// public void DestroyArrow() { if (_cloneArrow) Destroy(_cloneArrow.gameObject); } /// /// /// public void UpdateArrow() { //显示箭头 if (_showArrow) { var arrowDir = Vector3.Normalize(this.position - _cha1.position); if (arrowDir != Vector3.zero) { _cloneArrow.rotation = Quaternion.LookRotation(arrowDir); } arrowDir = _cha1.position + Vector3.up * 0.02f + arrowDir * 0.3f; _cloneArrow.position = Vector3.Lerp(_cloneArrow.position, arrowDir, Time.deltaTime * 4f); //_cloneArrow.gameObject.SetActive(true); } } public virtual void Dead(int kind) { isLife = false; DestroyArrow(); DestroyHpBar(); DropItems(); EntityManager.Instance.RemoveEntity(this); } public virtual void DropItems() { if (EntityPet.Instance) { Vector3 a = Random.onUnitSphere * Random.Range(0.18f, 0.26f); EntityPet.Instance.OnEnemyDied(transform.position + a); } } /// /// baozou /// public virtual void Rampage() { _timeTimeFactor = 3f; _animator.speed = 3f; } /// /// /// public virtual void Grabed() { //无法抓取 } public virtual void OnDamage(AllyDamage allyDamage, int damageLayer) { } public bool Burn(int damage) { if (_attributeStatus != 2) { _attributeStatus = 1; StartCoroutine(BurnCO(damage)); } return false; } /// /// /// /// public IEnumerator BurnCO(int damage) { SetElementEffect(0); yield return new WaitForSeconds(0.5f); for (int i = 0; i < 5; i++) { BurnDamage(damage); yield return new WaitForSeconds(0.5f); } yield return null; _attributeStatus = 0; RestoreElementEffect(); } /// /// /// private void BurnDamage(int damage) { int dmg = Mathf.Max(1, damage / 20); curHp -= dmg; SetDamageNumber(transform.position, dmg, Vector3.zero); SetHpBar(curHp, maxHp, -1); if (curHp <= 0) { Dead(0); } } public bool Freeze(int damage) { if (_attributeStatus != 1) { _attributeStatus = 2; StartCoroutine(FreezeCO()); return true; } return false; } public IEnumerator FreezeCO() { _animator.enabled = false; SetElementEffect(1); yield return new WaitForSeconds(2f); _attributeStatus = 0; _animator.enabled = true; RestoreElementEffect(); } public bool Shock(int damage) { if (_attributeStatus != 3) { StartCoroutine(ShockCO(damage)); _attributeStatus = 3; return true; } return false; } public IEnumerator ShockCO(int damage) { SetElementEffect(2); yield return new WaitForSeconds(0.5f); for (int i = 0; i < 7; i++) { ShockDamage(); yield return new WaitForSeconds(0.1f); } yield return null; _attributeStatus = 0; RestoreElementEffect(); } /// /// /// private void ShockDamage() { PlayAnimation(Hash_Down, 0f); } /// /// 暗黑 /// /// public bool Darken(int damage) { if (_attributeStatus != 4) { StartCoroutine(DarkenCO()); _attributeStatus = 4; return true; } return false; } /// /// /// /// public IEnumerator DarkenCO() { SetElementEffect(3); yield return new WaitForSeconds(2f); _attributeStatus = 0; RestoreElementEffect(); } /// /// 击晕 /// /// public void Stun(int damage) { if (_attributeStatus != 1) { StartCoroutine(StunCO()); _attributeStatus = 2; } } public IEnumerator StunCO() { _animator.enabled = false; yield return new WaitForSeconds(2f); _animator.enabled = true; _attributeStatus = 0; } /// /// 石化攻击 有几率直接死亡 /// /// /// public bool Petrify(int damage) { StartCoroutine(PetrifyCO(damage)); return true; } /// /// 石化 /// /// public IEnumerator PetrifyCO(int rate) { isLife = false; SetHpBar(curHp, maxHp, 2); this.gameObject.layer = GameLayer.ObjectLayer; SetElementEffect(1); yield return new WaitForSeconds(2.5f); if (rate > 0 && rate > GlobalUtils.RndHundred) { Dead(0); yield break; } this.gameObject.layer = GameLayer.UnitLayer; RestoreElementEffect(); isLife = true; SetHpBar(curHp, maxHp, 0); } /// /// 穿刺攻击 /// /// /// /// public bool Pierced(int damage, Vector3 damageDir) { isLife = false; SetColliderEnabled(false); SetHpBar(0, maxHp, 9f, 0); StartCoroutine(PiercedCO(damageDir)); return true; } /// /// /// /// public IEnumerator PiercedCO(Vector3 damageDir) { yield return new WaitForSeconds(1.5f); if (curHp <= 0) { Dead(0); } else { SetHpBar(curHp, maxHp, 0); } CrossFade(Hash_Down_High, 0.1f, 0.49f); GameCamera.Instance.Hitcam(); EnemyHelper.Instance.CreateBlood_Only(transform.position, damageDir); //SetMoveSpeed(0f); EnemyHelper.Instance.SoundOn(1); SetColliderEnabled(true); isLife = true; } /// /// /// /// public void SetElementEffect(int index) { _mainRender.material.mainTexture = EnemyHelper.Instance.attribute_tex[index]; //if (!_elementFx) // _elementFx = Object.Instantiate(EnemyHelper.Instance.attribute_pt[element], this.transform); } /// /// /// public void RestoreElementEffect() { _mainRender.material.mainTexture = _originTex; //if (_elementFx) // Destroy(_elementFx); } public virtual void UpdateState() { _lifeTime += Time.deltaTime; //if (_lifeTime > 60f) //{ // Rampage(); //} if (GameLevel.Instance.isRampage) { Rampage(); } } #endregion #region Unity private void FixedUpdate() { UpdateState(); } private void OnTriggerEnter(Collider other) { int damageLayer = other.gameObject.layer; if (damageLayer < GameLayer.PlayerAttack) return; var allyDamage = other.gameObject.GetComponent(); if (!allyDamage) return; OnDamage(allyDamage, damageLayer); } public override void Dispose() { RestoreElementEffect(); base.Dispose(); } #endregion } }