// ***********************************************************************
// Assembly : Unity
// Author : Kimch
// Created : 2018-2-29
// Description : 游戏Boss
// Last Modified By :
// Last Modified On :
// ***********************************************************************
//
//
// ***********************************************************************
using System.Collections;
using UnityEngine;
namespace G
{
///
/// 游戏Boss
///
public sealed class EntityBoss : EntityEnemy
{
private const int MAX_SKILL_COUNT = 3;
class SkillWrapper
{
///
///
///
public BossInfo.SkillInfo skillInfo;
///
///
///
public int power;
///
///
///
public float fireRange;
///
///
///
public Vector2 movingAttack;
///
///
///
public Transform skillClone;
}
#region Field
private bool _attackStart;
private float _attackDelay;
private int _attackKind;
private bool _setAttackKind;
private Transform _transform;
private bool _bossCutin;
///
///
///
private float _movingAttackDelay;
private bool _jump;
private ItemBoss _item;
private BossInfo _bossInfo;
///
///
///
private readonly SkillWrapper[] _skillWrappers = new SkillWrapper[MAX_SKILL_COUNT];
#endregion
#region Property
///
///
///
public override EntityType entityType
{
get { return EntityType.Boss; }
}
private Transform _secondSkill => _bossInfo.weapon_ef;
#endregion
#region Method
public override bool Init(EntityInfo info)
{
if (info != null)
{
_item = ItemProxy.Instance.GetStaticItem(info.itemId);
for (int i = 0; i < _skillWrappers.Length; i++)
{
_skillWrappers[i] = new SkillWrapper();
_skillWrappers[i].movingAttack = GlobalUtils.GetVector2(_item.moving_attack[i]);
_skillWrappers[i].fireRange = _item.fireRange[i];
}
SetLevel(info.factorA, info.factorB);
_scriptCha = EntityMainPlayer.Instance;
_cha1 = _scriptCha.transform;
_target = _cha1;
InitRigbody(_item.mass);
moveState = 0;
}
return base.Init(info);
}
protected override void OnViewInitCompleted()
{
base.OnViewInitCompleted();
var viewGO = entityView.gameObject;
_bossInfo = viewGO.GetComponent();
var orb = viewGO.GetComponent();
Destroy(orb);
_transform = this.transform;
EnemyHelper.Instance.CreateShadow(_transform, 2.2f);
SetModel(viewGO);
SetFloat(Hash_Speed_Attack1, _item.speed_attack[0]);
SetFloat(Hash_Speed_Attack1_I, _item.speed_attack_i[0]);
SetFloat(Hash_Speed_Attack2, _item.speed_attack[1]);
SetFloat(Hash_Speed_Attack2_I, _item.speed_attack_i[1]);
SetFloat(Hash_Speed_Attack3, _item.speed_attack[2]);
SetFloat(Hash_Speed_Attack3_I, _item.speed_attack_i[2]);
//
CreateHpBar();
//
_cloneArrow = Object.Instantiate(_bossInfo.direction_arrow);
_cloneArrow.gameObject.SetActive(false);
StartAI();
UI_Ingame.Instance.ShowEffect("UI_fx_Boss01");
//GlobalNotifier.PostNotification(GlobalDefine.EVENT_SHOW_EFFECT, "21539_", "");
}
public override void CreateHpBar()
{
_blood = BoardManager.Instance.CreateBloodBoard("BloodBoard1");
_blood.SetFixedPosition();
_blood.SetName(_item.name);
SetHpBar();
}
public override void DestroyHpBar()
{
if (_blood)
{
_blood.ReleaseWaitFinish();
_blood = null;
}
}
public override void SetHpBar(int cur, int max, float height, int index)
{
_blood.SetMultiHp(cur, max, 100);
}
///
///
///
///
public override void Dead(int kind)
{
moveState = -4;
EnemyHelper.Instance.SoundOn(4);
if (_bossInfo.weapon)
{
var dropWeapon = Object.Instantiate(_bossInfo.weapon);
dropWeapon.parent = null;
dropWeapon.GetComponent().Drop(true);
}
for (int i = 0; i < _skillWrappers.Length; i++)
{
if (_skillWrappers[i].skillClone)
Object.Destroy(_skillWrappers[i].skillClone.gameObject);
}
if (_secondSkill != null)
{
Object.Destroy(_secondSkill.gameObject);
}
EnemyHelper.Instance.EnemyDead(kind, transform.position, Vector3.one * 2.5f, -_transform.forward, _originTex);
GameLevel.Instance.BossKill(itemId);
base.Dead(kind);
}
///
///
///
///
public void SetMoveSpeed(float speedRate)
{
moveSpeed = _item.runSpeed * speedRate;
SetFloat(Hash_Speed_Move, speedRate);
}
///
///
///
public override void DropItems()
{
var dropBox = BoxProxy.Instance.GetBoxInfo(_item.boxDrop);
if (dropBox != null)
{
int dropCount = dropBox.item.typeArgs[0];
for (int i = 0; i < dropCount; i++)
{
Vector3 a = Random.onUnitSphere * Random.Range(0.18f, 0.26f);
var dropItem = dropBox.GetRndItem();
EnemyHelper.Instance.CreateBox(dropItem.id, dropItem.count, transform.position + a);
}
}
base.DropItems();
}
///
/// 设置等级
///
///
///
public void SetLevel(float[] a, float[] b)
{
for (int i = 0; i < _skillWrappers.Length; i++)
{
_skillWrappers[i].power = (int)(_item.power[i] * a[0] + b[0]);
}
defence = (int)(_item.defence * a[1] + b[1]);
maxHp = (int)(_item.hp * a[2] + b[2]);
curHp = maxHp;
block = (int)((_item.block * a[3] + b[3]) * 0.01f);
}
///
///
///
///
///
public float GetFireRange(int index)
{
return _skillWrappers[index].fireRange;
}
///
///
///
///
///
public int GetDamage(int index)
{
return _skillWrappers[index].power;
}
///
///
///
///
///
public Vector2 GetMovingAttack(int index)
{
return _skillWrappers[index].movingAttack;
}
///
/// 撞击
///
public void Impact()
{
_secondSkill?.GetComponent()?.PressDamage(GetDamage(_attackKind));
_secondSkill?.gameObject.SetActive(true);
}
///
/// 撞击
///
public void Impact2()
{
_secondSkill?.GetComponent()?.PressDamage(GetDamage(_attackKind));
_secondSkill?.gameObject.SetActive(true);
GameCamera.Instance.Hitcam();
}
///
///
///
private void TurnNormal()
{
this.invincible = false;
InvokeRepeating(nameof(SimpleAI), 0.3f, 0.5f);
}
///
/// 显示预警
///
///
public void ShowSkillWarningIndex(int index)
{
var skillInfo = _bossInfo.skillInfos[index];
//显示预警
if (skillInfo.warning != null)
{
var clone_decal = Instantiate(skillInfo.warning).transform;
var ef_tr = skillInfo.skill;
if (skillInfo.useTargetPosition)
{
clone_decal.position = _attackStartPosition;
clone_decal.rotation = Quaternion.LookRotation(_attackStartDirection);
}
else
{
Quaternion oldRotation = _transform.rotation;
_transform.rotation = Quaternion.LookRotation(_attackStartDirection);
clone_decal.parent = _transform;
var ef_position = ef_tr.transform.localPosition;
ef_position.y = 0f;
clone_decal.localPosition = ef_position;
clone_decal.localRotation = Quaternion.identity;
clone_decal.parent = null;
_transform.rotation = oldRotation;
}
var ef_col = ef_tr.GetComponent();
//Vector3 atk_mov = Vector3.zero;
//if (_movingAttack[_attackKind] != Vector2.zero)
//{
// atk_mov = _attackStartDirection * _movingAttack[_attackKind].x * _movingAttack[_attackKind].y;
//}
//clone_decal.forward = _attackDirection;
if (ef_col is SphereCollider sc)
{
clone_decal.localScale = Vector3.one * sc.radius;
}
else if (ef_col is BoxCollider bc)
{
clone_decal.localScale = bc.size;// new Vector3(bc.size.x, 1f, bc.size.z);
}
Destroy(clone_decal.gameObject, 1f);
}
}
///
/// 发动技能
///
///
public void LaunchSkill(int index)
{
var skillInfo = _bossInfo.skillInfos[index];
var ef_position = skillInfo.skill.transform.localPosition;
var ef_rotation = Quaternion.LookRotation(_attackStartDirection);
if (skillInfo.useTargetPosition)
{
ef_position += _attackStartPosition;
}
else
{
ef_position = _transform.TransformPoint(ef_position);
}
var skillWrapper = _skillWrappers[_attackKind];
if (!skillWrapper.skillClone)
{
if (!skillInfo.instance)
{
var skillClone = Instantiate(skillInfo.skill, ef_position, ef_rotation);
skillClone.SetActive(true);
skillWrapper.skillClone = skillClone.transform;
var attach_weaponEf = _item.attach_ef;
if (attach_weaponEf != null && attach_weaponEf[_attackKind] >= 1)
{
skillWrapper.skillClone.parent = _transform;
if (_secondSkill && attach_weaponEf[_attackKind] == 2)
{
Impact();
}
}
}
else
{
var skillClone = skillInfo.skill;
skillClone.SetActive(true);
skillWrapper.skillClone = skillClone.transform;
}
var mainDamageComp = skillWrapper.skillClone.GetComponent();
if (mainDamageComp)
mainDamageComp.SetDamage(GetDamage(_attackKind), 50);
else
Debug.Log("mainDamageComp = null" + this.itemId);
}
else
{
skillWrapper.skillClone.position = ef_position;
skillWrapper.skillClone.rotation = ef_rotation;
skillWrapper.skillClone.gameObject.SetActive(true);
}
}
///
///
///
///
///
public override void OnDamage(AllyDamage allyDamage, int damageLayer)
{
if (this.invincible)
{
return;
}
var sourceCha = allyDamage.source;
var myPosition = this.position;
_setAttackKind = true;
float damage = 0f;
float addDamage = sourceCha.伤害加深百分比 * 0.01f;
float realDefence = (defence - sourceCha.忽视防御固定值) * (100 - sourceCha.忽视防御百分比) * 0.01f;
float damageForce = 0f;
var damageDir = Vector3.zero;
if (damageLayer == GameLayer.PushAttack)
{
damageDir = myPosition - sourceCha.position;
damageDir.y = 0f;
damageDir = Vector3.Normalize(damageDir);
}
else
{
damageDir = myPosition - allyDamage.transform.position;
damageDir.y = 0f;
damageDir = Vector3.Normalize(damageDir);
}
if (damageDir == Vector3.zero)
{
damageDir = -Vector3.forward;
}
switch (damageLayer)
{
case GameLayer.NormalAttack:
//other.transform.root.GetComponent().AddForce(-_attackDirection * 80f);
GameCamera.Instance.Hitcam();
damageForce = 60f;
var sourceHitRate = sourceCha.sourceTotalHitRate;
int blockRate = (int)((block - sourceHitRate) * 1000f / Mathf.Max(block, sourceHitRate, 1) + 100);
if (moveState >= 0 && GlobalUtils.RndThousand < blockRate)
{
this.AddForce(damageDir * 10f);
sourceCha.Blocked(myPosition);
return;
}
damage = sourceCha.damage;
_target = _cha1;
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.PowerAttack:
damageForce = 100f;
realDefence *= 0.5f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam2(1f);
EnemyHelper.Instance.CreateBlood_Only(myPosition, damageDir);
break;
case GameLayer.SkillAttack:
GameCamera.Instance.Hitcam();
damageForce = 50f;
damage = allyDamage.physicsDamage;
_target = _cha1;
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.PoisonAttack:
{
damage = allyDamage.physicsDamage;
if (damage == 0.1f)
{
damage = 0f;
_poison = true;
_poisonDamage = sourceCha.damage * 0.6f;
_poisonDelay = 4f;
_target = _cha1;
return;
}
damageForce = 100f;
_poisonDamage = damage;
_poison = true;
_poisonDelay = 12f;
damage *= 2f;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
}
case GameLayer.DeathAttack:
damageForce = 100f;
//var petrifyRate = (int)(allyDamage.physicsDamage * 0.01f);
Petrify(0);
_target = _cha1;
GameCamera.Instance.Hitcam();
break;
case GameLayer.GeneralAttack:
damageForce = 60f;
damage = sourceCha.damage * EntityPet.Instance.bulletDamage;
_target = _cha1;
EnemyHelper.Instance.CreateBlood_Only(myPosition, damageDir);
break;
case GameLayer.PierceAttack:
damageForce = 10f;
damage = allyDamage.physicsDamage;
curHp -= (int)damage;
SetHpBar(0, maxHp);
_target = _cha1;
EnemyHelper.Instance.CreateBlood_Only(myPosition, damageDir);
PlayAnimation(Hash_Down, 0f);
break;
case GameLayer.PushAttack://
damageForce = 100f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.RiseupAttack2:
damageForce = 50f;
damage = sourceCha.damage * 0.4f;
_target = _cha1;
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.BurnAttack:
damageForce = 100f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.ColdAttack:
damageForce = 100f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.StunAttack:
damageForce = -50f;
damage = 0f;
_target = _cha1;
Stun((int)damage);
break;
case GameLayer.RiseupAttack:
damageForce = 40f;
damage = allyDamage.physicsDamage;
_target = _cha1;
GameCamera.Instance.Hitcam2(0.2f);
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.ShockAttack:
damageForce = 100f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
case GameLayer.DarkAttack:
damageForce = 100f;
damage = sourceCha.damage;
_target = _cha1;
GameCamera.Instance.Hitcam();
EnemyHelper.Instance.CreateBlood(myPosition, damageDir);
break;
}
if (!isLife)
{
EnemyHelper.Instance.SoundOn(1);
//myanimation.Stop();
return;
}
EnemyHelper.Instance.SoundOn(1);
damage -= realDefence;
damage += damage * addDamage;
damage = Mathf.Max(1, damage);
int num = Mathf.Max(1, (int)(maxHp * 0.3f));
int num2 = curHp / num;
if (curHp == maxHp)
{
num2--;
}
curHp -= (int)damage;
SetDamageNumber(_transform.position, (int)damage, damageDir, _scriptCha.critDamage);
SetHpBar();
if (curHp <= 0 && isLife)
{
Dead(2);
}
else if (curHp < num * num2)
{
GameLevel.Instance.Summon(4, transform.position);
damageForce = 300f;
PlayAnimation(Hash_Down);
var skillWrapper = _skillWrappers[_attackKind];
if (skillWrapper.skillClone)
{
skillWrapper.skillClone.gameObject.SetActive(false);
skillWrapper.skillClone.position = Vector3.one * 8f;
}
if (_secondSkill != null)
{
_secondSkill.gameObject.SetActive(false);
}
PlaySound(_bossInfo.snd_scream);
}
AddForce(damageDir * damageForce);
}
///
///
///
public override void UpdateState()
{
if (!entityView.initSuccess)
{
return;
}
if (!isLife)
{
return;
}
base.UpdateState();
_behaviourDelay -= deltaTime;
UpdateAnim();
//显示箭头
UpdateArrow();
//中毒
UpdatePoison();
//限制范围
UpdateRestrictArea();
}
private bool _isSkilling = false;
///
///
///
private void UpdateAnim()
{
if (_isSkilling)
{
var skillWrapper = _skillWrappers[_attackKind];
var director = skillWrapper.skillClone.GetComponent();
if (director.state != UnityEngine.Playables.PlayState.Playing)
{
_isSkilling = false;
_attackDelay = _item.attackCd;
skillWrapper.skillClone.gameObject.SetActive(false);
}
return;
}
var currentStateInfo = _animator.GetCurrentAnimatorStateInfo(0);
int stateNameHash = currentStateInfo.shortNameHash;
int stateTagHash = currentStateInfo.tagHash;
if (stateNameHash == Hash_Idle)
{
_attackDelay -= deltaTime;
if (_attackDelay < 0f)
{
_attackStart = false;
}
moveState = 1;
_transform.position += _direction * (deltaTime * moveSpeed);
if (_direction != Vector3.zero)
{
var lookrotation = Quaternion.LookRotation(_direction);
_transform.rotation = Quaternion.Lerp(_transform.rotation, lookrotation, deltaTime * 5f);
}
}
else if (stateTagHash == Hash_Attack)
{
if (_attackStartDirection != Vector3.zero)
{
var lookrotation = Quaternion.LookRotation(_attackStartDirection);
_transform.rotation = Quaternion.Lerp(_transform.rotation, lookrotation, deltaTime * _item.turnSpeed);
}
if (moveState != 11)
{
if (_item.colliderOff[_attackKind] != 0 && !_jump)
{
SetColliderEnabled(false);
_jump = true;
}
if (_secondSkill && _item.attach_ef[_attackKind] == 2)
{
_secondSkill.gameObject.SetActive(true);
}
ShowSkillWarningIndex(_attackKind);
}
//攻击动作带位移
var movingAttack = GetMovingAttack(_attackKind);
if (movingAttack != Vector2.zero)
{
if (_movingAttackDelay > movingAttack.x)
{
_transform.position += _direction * (deltaTime * movingAttack.y);
}
else
{
_movingAttackDelay += deltaTime;
}
}
moveState = 11;
}
else if (stateTagHash == Hash_Attack_I)
{
//冲击
if (moveState == 11)
{
if (_attackStartDirection != Vector3.zero)
{
var lookrotation = Quaternion.LookRotation(_attackStartDirection);
_transform.rotation = lookrotation;
}
if (_jump)
{
SetColliderEnabled(true);
_jump = false;
}
this.AddForwardForce(_item.dash[_attackKind]);
LaunchSkill(_attackKind);
_movingAttackDelay = 0f;
var position = _transform.position;
position.y = 0f;
_transform.position = position;
_attackDelay = _item.attackCd;
}
moveState = 12;
}
else if (stateNameHash == Hash_Down)
{
moveState = -1;
}
else
{
moveState = 1;
_attackDelay -= deltaTime;
if (_attackDelay < 0f)
{
_attackStart = false;
}
if (_direction != Vector3.zero)
{
var lookrotation = Quaternion.LookRotation(_direction);
_transform.rotation = Quaternion.Lerp(_transform.rotation, lookrotation, deltaTime * 5f);
}
}
}
///
///
///
private void UpdatePoison()
{
//中毒
if (_poison)
{
_poisonDelay -= deltaTime;
if (_poisonDelay < 0f)
{
_poison = false;
SetHpBar();
}
else if ((int)_poisonDelay != _lastPoisonDelay)
{
curHp -= (int)_poisonDamage;
SetHpBar();
_lastPoisonDelay = (int)_poisonDelay;
if (curHp <= 0)
{
Dead(1);
}
}
}
}
///
///
///
private void UpdateRestrictArea()
{
//if (Vector3.SqrMagnitude(transform.position) > _restrictArea)
//{
// AddForce(-transform.position * 20f);
//}
}
#endregion
#region For AI
///
///
///
public void SimpleAI()
{
if (!isLife)
{
return;
}
if (!_target)
{
_target = _cha1;
}
if (_bossCutin)
{
if (_behaviourDelay < 0f)
{
_behaviour = Random.Range(0, 6);
if (_behaviour == 0)
{
PlaySound(_bossInfo.snd_move);
}
_behaviourDelay = 1f;
}
}
else
{
GameLevel.Instance.BossCutin(itemId - 1);
_bossCutin = true;
_attackDelay = 2f;
_attackStart = true;
//_scriptCam.LookTarget(mytransform, 30, 0f);
}
//
Vector3 targetPosition = _target.position;
if (targetPosition.y > 2f)
{
//更换目标
_target = _cha1;
}
Vector3 myselfPosition = _transform.position;
var distance = 0f;
//
if (_attributeStatus == 2)
{
_direction = Vector3.zero;
distance = 2f;
}
else
{
_direction = targetPosition - myselfPosition;
distance = _direction.magnitude;
_direction.y = 0f;
_direction = Vector3.Normalize(_direction);
}
if (distance < GetFireRange(2))
{
ShowArrow(false);
if (_attackStart)
{
return;
}
if (moveState >= 0 && _scriptCha.moveState < MoveState.state50)
{
if (_setAttackKind)
{
_attackKind = Random.Range(0, _bossInfo.skillInfos.Length);
_setAttackKind = false;
}
var skillInfo = _bossInfo.skillInfos[_attackKind];
if (distance < GetFireRange(_attackKind))
{
if (!skillInfo.instance)
{
if (_attackKind == 0)
{
PlayAnimation(Hash_Attack1);
}
else if (_attackKind == 1)
{
PlayAnimation(Hash_Attack2);
}
else
{
PlayAnimation(Hash_Attack3);
}
}
else
{
_isSkilling = true;
LaunchSkill(_attackKind);
}
_attackStartDirection = _direction;
_attackStartPosition = targetPosition;
_setAttackKind = true;
_attackStart = true;
}
else
{
//move
SetMoveSpeed(1f);
//PlayAnim(Hash_Boss_Move);
}
}
else if (!_attackStart)
{
//PlayAnim(Hash_Boss_Idle);
SetMoveSpeed(0f);
_behaviour = 4;
_behaviourDelay = 1f;
}
}
else if (!_attackStart)
{
SetMoveSpeed(_behaviour < 5 ? 1f : 0f);
ShowArrow(true);
}
}
public override void StartAI()
{
//if (behaviorTree)
// StartCoroutine(nameof(AICoroutine));
//else
InvokeRepeating(nameof(SimpleAI), 0.3f, 0.5f);
}
public override void EndAI(bool pause)
{
CancelInvoke(nameof(SimpleAI));
//StopCoroutine(nameof(AICoroutine));
}
#endregion
}
}