using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Config; using Godot; /// <summary> /// Boss逻辑类 /// </summary> [Tool] public partial class Boss : AiRole { private long _attaclCoroutine = -1; private List<Vector2> _vertices; private float _targetRotation; private int state = 0; public override void OnInit() { base.OnInit(); WeaponPack.SetCapacity(0); Camp = CampEnum.Camp2; NoWeaponAttack = true; MountLookTarget = true; FiringStand = true; MaxHp = 2000; Hp = MaxHp; AnimatedSprite.Visible = false; StateController.Enable = false; } protected override RoleState OnCreateRoleState() { var roleState = base.OnCreateRoleState(); roleState.MoveSpeed = 45; return roleState; } protected override void Process(float delta) { if (Hp <= 0) { return; } base.Process(delta); LookTarget = World.Player; ViewArea.LookAt(LookTarget.Position); //UpdateFace(); var velocity = BasisVelocity; if ((Face == FaceDirection.Right && velocity.X > 0) || (Face == FaceDirection.Left && velocity.X < 0)) { _targetRotation = 10; } else if ((Face == FaceDirection.Right && velocity.X < 0) || (Face == FaceDirection.Left && velocity.X > 0)) { _targetRotation = -10; } else { _targetRotation = 0; } AnimatedSprite.RotationDegrees = Mathf.MoveToward(AnimatedSprite.RotationDegrees, _targetRotation, 25 * delta); } public override void HurtHandler(ActivityObject target, int damage, float angle) { base.HurtHandler(target, damage, angle); if (Hp <= 0) //死亡 { StateController.Enable = false; MoveController.Enable = false; MoveController.ClearForce(); Velocity = Vector2.Zero; AnimatedSprite.RotationDegrees = 0; StopCoroutine(_attaclCoroutine); } } public override void Attack() { if (_attaclCoroutine < 0) { if (World.Current.Player != null) //玩家快没有子弹了, 就生成小兵 { var total = 0; var itemSlot = World.Current.Player.WeaponPack.ItemSlot; for (var i = 0; i < itemSlot.Length; i++) { var item = itemSlot[i]; if (item != null) { total += item.TotalAmmon; break; } } if (total < 30) { var count = AffiliationArea.FindEnterItemsCount(o => o != this && o is AiRole aiRole && aiRole.IsEnemyWithPlayer()); if (count == 0) { _attaclCoroutine = StartCoroutine(RunAttack4()); return; } } } if (Hp / (float)MaxHp > 0.5f) //第一阶段 { switch (Utils.Random.RandomRangeInt(0, 4)) { case 0: _attaclCoroutine = StartCoroutine(RunAttack1()); break; case 1: _attaclCoroutine = StartCoroutine(RunAttack3()); break; case 2: _attaclCoroutine = StartCoroutine(RunAttack4()); break; case 3: _attaclCoroutine = StartCoroutine(RunAttack5()); break; case 4: _attaclCoroutine = StartCoroutine(RunAttack6()); break; } } else //第二阶段 { if (state == 0) // { state++; _attaclCoroutine = StartCoroutine(RunAttack2()); } else if (state == 1) { state++; _attaclCoroutine = StartCoroutine(RunAttack7()); } else { switch (Utils.Random.RandomRangeInt(0, 6)) { case 0: _attaclCoroutine = StartCoroutine(RunAttack1()); break; case 1: _attaclCoroutine = StartCoroutine(RunAttack2()); break; case 2: _attaclCoroutine = StartCoroutine(RunAttack3()); break; case 3: _attaclCoroutine = StartCoroutine(RunAttack4()); break; case 4: _attaclCoroutine = StartCoroutine(RunAttack5()); break; case 5: _attaclCoroutine = StartCoroutine(RunAttack6()); break; case 6: _attaclCoroutine = StartCoroutine(RunAttack7()); break; } } } } } //发射两个子弹圈 private IEnumerator RunAttack1() { var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]); bulletData.Altitude = 1; AnimatedSprite.Play("readyAttack1"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("attack2"); yield return new WaitForSeconds(0.4f); CreateBulletCircle(15, 0, bulletData, (shootBullet) => { if (shootBullet is Bullet bullet) { var twistMovement = bullet.MoveController.AddForce(new TwistForce()); twistMovement.MoveRotation = shootBullet.BulletData.Rotation; twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi); } }); yield return new WaitForSeconds(0.2f); CreateBulletCircle(60, 0, bulletData); yield return new WaitForSeconds(0.1f); CreateBulletCircle(60, 0, bulletData); yield return new WaitForSeconds(0.2f); CreateBulletCircle(15, Mathf.DegToRad(360 / 15f * 0.5f) , bulletData, (shootBullet) => { if (shootBullet is Bullet bullet) { var twistMovement = bullet.MoveController.AddForce(new TwistForce()); twistMovement.MoveRotation = shootBullet.BulletData.Rotation; twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi); } }); yield return new WaitForSeconds(0.5f); AttackTimer = 1.5f; _attaclCoroutine = -1; } //全屏发射子弹 private IEnumerator RunAttack2() { var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]); bulletData.Altitude = 1; AnimatedSprite.Play("readyAttack6"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("attack6"); var count = 18; var angle = Mathf.DegToRad(360f / count * 0.5f); for (int i = 0; i < 15; i++) { if (i == 13) { CreateBulletCircle(60, 0, bulletData); } CreateBulletCircle(count, angle * i, bulletData); yield return new WaitForSeconds(0.4f); } AnimatedSprite.Play("endAttack6"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 2.5f; _attaclCoroutine = -1; } //玩家方向发射扇形子弹 private IEnumerator RunAttack3() { var count = 100; var r = Mathf.Pi; var d = r / count; AnimatedSprite.Play("readyAttack5"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("attack5"); for (var j = 0; j < 3; j++) { var angle = Position.AngleToPoint(LookTarget.Position); var bulletData = FireManager.GetBulletData(this, angle - r * 0.5f, ExcelConfig.BulletBase_Map["0030"]); bulletData.Altitude = 1; for (var i = 0; i < 100; i++) { var clone = bulletData.Clone(); clone.Position = FirePoint.GlobalPosition; clone.Rotation += i * d; clone.FlySpeed *= Utils.Random.RandomRangeFloat(1, 1.5f); var shootBullet = FireManager.ShootBullet(clone, Camp); if (shootBullet is Bullet bullet) { bullet.HideShadowSprite(); var twistMovement = bullet.MoveController.AddForce(new TwistForce()); twistMovement.MoveRotation = clone.Rotation; twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi); } if (i % 2 == 0) { yield return null; } } yield return new WaitForSeconds(1.5f); } AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 2.5f; _attaclCoroutine = -1; } //随机生成敌人 private IEnumerator RunAttack4() { AnimatedSprite.Play("readyGenerate"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("generate"); yield return new WaitForSeconds(0.3f); var count = (Hp / (float)MaxHp) < 0.5f ? Utils.Random.RandomRangeInt(2, 3) : 1; var positionArray = GetRandomPoint(count); for (var i = 0; i < count; i++) { var summons = Create<Summons>(Ids.Id_summons0001); summons.InitTarget(World.Player); summons.ThrowToPosition(Position, 40, 0, AffiliationArea.RoomInfo.ToGlobalPosition(positionArray[i]), 150); summons.PutDown(RoomLayerEnum.YSortLayer); yield return new WaitForSeconds(0.5f); } yield return new WaitForSeconds(1f); AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 2f; _attaclCoroutine = -1; } //发射分裂子弹 private IEnumerator RunAttack5() { AnimatedSprite.Play("readyAttack1"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("attack1"); yield return new WaitForSeconds(0.2f); for (int i = 0; i < 5; i++) { var bulletData = FireManager.GetBulletData(this, Utils.Random.RandomRangeFloat(0, Mathf.Pi * 2), ExcelConfig.BulletBase_Map["0034"]); bulletData.Altitude = 1; var shootBullet = FireManager.ShootBullet(bulletData, Camp); if (shootBullet is Bullet bullet) { bullet.HideShadowSprite(); if (bullet is SplitBullet splitBullet) { var childBullet = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]); childBullet.Altitude = 1; splitBullet.SetSplitBullet(childBullet, 20); splitBullet.OnCreateSplitBulletEvent += iBullet => { if (iBullet is Bullet bullet1) { bullet1.HideShadowSprite(); } }; } } yield return new WaitForSeconds(0.5f); } yield return new WaitForSeconds(1f); AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 1.5f; _attaclCoroutine = -1; } //发射一堆低速子弹 private IEnumerator RunAttack6() { AnimatedSprite.Play("readyAttack1"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); AnimatedSprite.Play("attack1"); yield return new WaitForSeconds(0.2f); var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]); bulletData.Altitude = 1; var count = 50; for (var i = 0; i < count; i++) { var clone = bulletData.Clone(); clone.Position = Position; clone.Rotation = Utils.Random.RandomRangeFloat(0, Mathf.Pi * 2); clone.FlySpeed *= Utils.Random.RandomRangeFloat(0.2f, 0.9f); var shootBullet = FireManager.ShootBullet(clone, Camp); if (shootBullet is Bullet bullet) { bullet.HideShadowSprite(); } if (count % 5 == 0) { yield return null; } } yield return new WaitForSeconds(1f); AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 1f; _attaclCoroutine = -1; } //向上发射火箭炮(非常难躲避) private IEnumerator RunAttack7() { AnimatedSprite.Play("readyAttack4"); yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); var count = 3; _randomPosList = GetRandomPoint(count * 4).ToList(); for (int i = 0; i < count; i++) { AnimationPlayer.Play("attack4"); yield return ToSignal(AnimationPlayer, AnimationMixer.SignalName.AnimationFinished); } AnimatedSprite.Play(AnimatorNames.Idle); AttackTimer = 6f; _attaclCoroutine = -1; } private List<Vector2> _randomPosList; private void CreateMissileBullet(NodePath node) { if (_randomPosList == null || _randomPosList.Count == 0) { return; } var node2D = GetNode<Node2D>(node); var bullet = ObjectManager.GetActivityObject<SpecialBullet0001>(Ids.Id_special0001); bullet.InitBullet("0030", 10, this, AffiliationArea.RoomInfo.ToGlobalPosition(_randomPosList[_randomPosList.Count - 1])); _randomPosList.RemoveAt(_randomPosList.Count - 1); var localPos = node2D.Position; bullet.Position = Position + new Vector2(localPos.X, 0); bullet.Altitude = -localPos.Y; bullet.VerticalSpeed = 800; bullet.OnCreateSplitBulletEvent += b => { if (b is Bullet blt) { blt.Altitude = 1; blt.HideShadowSprite(); } }; bullet.PutDown(RoomLayerEnum.YSortLayer, false); bullet.UpdateFall((float)GetProcessDeltaTime()); bullet.HideShadowSprite(); } private Vector2[] GetRandomPoint(int count) { var tileInfo = AffiliationArea.RoomInfo.RoomSplit.TileInfo; if (_vertices == null) { var serializeVector2s = tileInfo.NavigationVertices; _vertices = new List<Vector2>(); foreach (var sv2 in serializeVector2s) { _vertices.Add(sv2.AsVector2()); } } var positionArray = World.Random.GetRandomPositionInPolygon(_vertices, tileInfo.NavigationPolygon, count); return positionArray; } private void CreateBulletCircle(int count, float offsetAngle, BulletData bulletData, Action<IBullet> callback = null) { var pos = FirePoint.GlobalPosition; for (var i = 0; i < count; i++) { var clone = bulletData.Clone(); clone.Position = pos; clone.Rotation = Mathf.Pi * 2 / count * i + offsetAngle; var shootBullet = FireManager.ShootBullet(clone, Camp); if (shootBullet is Bullet bullet) { bullet.HideShadowSprite(); } if (callback != null) { callback(shootBullet); } } } }