mirror of
https://github.com/Phantop/LADXHD.git
synced 2025-09-01 03:14:56 +00:00
263 lines
10 KiB
C#
263 lines
10 KiB
C#
using Microsoft.Xna.Framework;
|
|
using ProjectZ.InGame.GameObjects.Base;
|
|
using ProjectZ.InGame.GameObjects.Base.Components;
|
|
using ProjectZ.InGame.GameObjects.Base.CObjects;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
using ProjectZ.InGame.Things;
|
|
using ProjectZ.InGame.GameObjects.Base.Components.AI;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.GameObjects.Enemies;
|
|
using ProjectZ.InGame.GameObjects.Things;
|
|
|
|
namespace ProjectZ.InGame.GameObjects.Bosses
|
|
{
|
|
class BossFinalBossFireball : GameObject
|
|
{
|
|
private readonly BossFinalBoss _finalBoss;
|
|
|
|
private readonly CSprite _sprite;
|
|
private readonly BodyComponent _body;
|
|
private readonly Animator _animator;
|
|
private readonly AiComponent _aiComponent;
|
|
private readonly CBox _damageBox;
|
|
|
|
private ObjAnimator _objTrail0;
|
|
private ObjAnimator _objTrail1;
|
|
|
|
private bool _isMoving;
|
|
private bool _isRepelled;
|
|
private double _moveTime = 0;
|
|
|
|
private const double BlinkTime = 2000 / 60.0;
|
|
private const float Speed = 1.5f;
|
|
|
|
private bool _isReady;
|
|
|
|
private bool _damageState;
|
|
|
|
public bool IsReady { get => _isReady; }
|
|
|
|
public BossFinalBossFireball(BossFinalBoss boss, Vector2 position) : base(boss.Map)
|
|
{
|
|
_finalBoss = boss;
|
|
|
|
Tags = Values.GameObjectTag.Enemy;
|
|
|
|
EntityPosition = new CPosition(position.X, position.Y, 0);
|
|
EntitySize = new Rectangle(-8, -8, 16, 16);
|
|
|
|
_animator = AnimatorSaveLoad.LoadAnimator("Nightmares/nightmare fireball");
|
|
|
|
_sprite = new CSprite(EntityPosition);
|
|
var animationComponent = new AnimationComponent(_animator, _sprite, Vector2.Zero);
|
|
|
|
_body = new BodyComponent(EntityPosition, -3, -3, 6, 6, 8)
|
|
{
|
|
IgnoresZ = true,
|
|
IgnoreHoles = true
|
|
};
|
|
|
|
_aiComponent = new AiComponent();
|
|
|
|
var state0 = new AiState() { Init = () => _animator.Play("idle_0") };
|
|
state0.Trigger.Add(new AiTriggerCountdown(1100, null, () => _aiComponent.ChangeState("idle1")));
|
|
var state1 = new AiState() { Init = () => _animator.Play("idle_1") };
|
|
state1.Trigger.Add(new AiTriggerCountdown(1100, null, () => _aiComponent.ChangeState("idle2")));
|
|
var state2 = new AiState() { Init = () => _animator.Play("idle_2") };
|
|
state2.Trigger.Add(new AiTriggerCountdown(1100, null, () => _isReady = true));
|
|
var stateMoving = new AiState();
|
|
|
|
_aiComponent.States.Add("idle0", state0);
|
|
_aiComponent.States.Add("idle1", state1);
|
|
_aiComponent.States.Add("idle2", state2);
|
|
_aiComponent.States.Add("moving", stateMoving);
|
|
|
|
_aiComponent.ChangeState("idle0");
|
|
|
|
var damageCollider = new CBox(EntityPosition, -3, -3, 0, 6, 6, 8);
|
|
var hittableBox = new CBox(EntityPosition, -4, -4, 0, 8, 8, 8);
|
|
_damageBox = new CBox(EntityPosition, -4, -4, 0, 8, 8, 8);
|
|
|
|
AddComponent(DamageFieldComponent.Index, new DamageFieldComponent(damageCollider, HitType.Enemy, 2));
|
|
AddComponent(AiComponent.Index, _aiComponent);
|
|
AddComponent(BodyComponent.Index, _body);
|
|
AddComponent(PushableComponent.Index, new PushableComponent(_body.BodyBox, OnPush));
|
|
AddComponent(HittableComponent.Index, new HittableComponent(hittableBox, OnHit));
|
|
AddComponent(BaseAnimationComponent.Index, animationComponent);
|
|
AddComponent(UpdateComponent.Index, new UpdateComponent(Update));
|
|
AddComponent(DrawComponent.Index, new DrawCSpriteComponent(_sprite, Values.LayerTop));
|
|
}
|
|
|
|
public void Fire()
|
|
{
|
|
Game1.GameManager.PlaySoundEffect("D378-56-38");
|
|
|
|
_isMoving = true;
|
|
_aiComponent.ChangeState("moving");
|
|
|
|
if (Game1.RandomNumber.Next(0, 4) == 0)
|
|
{
|
|
_damageState = true;
|
|
_body.MoveCollision = OnMoveCollision;
|
|
_animator.Play("idle_3");
|
|
}
|
|
else
|
|
{
|
|
EntityPosition.AddPositionListener(typeof(BossFinalBossFireball), UpdateTrail);
|
|
_body.CollisionTypes = Values.CollisionTypes.None;
|
|
_animator.Play("idle_2");
|
|
SpawnTrail();
|
|
}
|
|
|
|
var playerDirection = new Vector2(MapManager.ObjLink.EntityPosition.X, MapManager.ObjLink.EntityPosition.Y - 4) - EntityPosition.Position;
|
|
if (playerDirection != Vector2.Zero)
|
|
{
|
|
playerDirection.Normalize();
|
|
_body.VelocityTarget = playerDirection * Speed;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_isMoving)
|
|
{
|
|
_moveTime += Game1.DeltaTime;
|
|
|
|
if (_isRepelled && _finalBoss.HitBoss(this, _body.VelocityTarget * 0.75f, _damageBox))
|
|
_moveTime = 1300;
|
|
|
|
// fade away
|
|
if (_moveTime > 1300)
|
|
{
|
|
_sprite.Color = Color.White * MathHelper.Clamp(1 - ((float)_moveTime - 1300) / 100, 0, 1);
|
|
|
|
if (_objTrail0 != null)
|
|
_objTrail0.Sprite.Color = Color.White * MathHelper.Clamp(1 - ((float)_moveTime - 1350) / 100, 0, 1);
|
|
if (_objTrail1 != null)
|
|
_objTrail1.Sprite.Color = Color.White * MathHelper.Clamp(1 - ((float)_moveTime - 1400) / 100, 0, 1);
|
|
}
|
|
|
|
if (_moveTime > 1500)
|
|
{
|
|
DeleteObject();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// blink
|
|
var shader = Game1.TotalGameTime % (BlinkTime * 2) < BlinkTime ? Resources.DamageSpriteShader0 : null;
|
|
_sprite.SpriteShader = shader;
|
|
if (_objTrail0 != null)
|
|
_objTrail0.Sprite.SpriteShader = shader;
|
|
if (_objTrail1 != null)
|
|
_objTrail1.Sprite.SpriteShader = shader;
|
|
}
|
|
|
|
private void SpawnTrail()
|
|
{
|
|
_objTrail0 = new ObjAnimator(Map, (int)EntityPosition.X, (int)EntityPosition.Y, Values.LayerPlayer, "Nightmares/nightmare fireball", "idle_1", false);
|
|
_objTrail1 = new ObjAnimator(Map, (int)EntityPosition.X, (int)EntityPosition.Y, Values.LayerBottom, "Nightmares/nightmare fireball", "idle_0", false);
|
|
|
|
Map.Objects.SpawnObject(_objTrail0);
|
|
Map.Objects.SpawnObject(_objTrail1);
|
|
}
|
|
|
|
private void UpdateTrail(CPosition position)
|
|
{
|
|
var dist0 = _objTrail0.EntityPosition.Position - position.Position;
|
|
if (dist0.Length() > 7)
|
|
{
|
|
dist0.Normalize();
|
|
dist0 *= 7;
|
|
}
|
|
_objTrail0.EntityPosition.Set(EntityPosition.Position + dist0);
|
|
|
|
var dist1 = _objTrail1.EntityPosition.Position - _objTrail0.EntityPosition.Position;
|
|
if (dist1.Length() > 8)
|
|
{
|
|
dist1.Normalize();
|
|
dist1 *= 8;
|
|
}
|
|
_objTrail1.EntityPosition.Set(_objTrail0.EntityPosition.Position + dist1);
|
|
}
|
|
|
|
private void Repell()
|
|
{
|
|
Game1.GameManager.PlaySoundEffect("D378-56-38");
|
|
|
|
_isRepelled = true;
|
|
_moveTime = 0;
|
|
|
|
var playerDirection = EntityPosition.Position -
|
|
new Vector2(MapManager.ObjLink.EntityPosition.X, MapManager.ObjLink.EntityPosition.Y - 4);
|
|
if (playerDirection != Vector2.Zero)
|
|
playerDirection.Normalize();
|
|
|
|
_body.VelocityTarget = playerDirection * Speed;
|
|
}
|
|
|
|
private void OnMoveCollision(Values.BodyCollision collision)
|
|
{
|
|
OnDeath();
|
|
}
|
|
|
|
private Values.HitCollision OnHit(GameObject originObject, Vector2 direction, HitType type, int damage, bool pieceOfPower)
|
|
{
|
|
if ((type & HitType.Sword) == 0 || (type & HitType.SwordHold) != 0)
|
|
return Values.HitCollision.None;
|
|
|
|
// can not be hit before moving for a little while
|
|
if (_moveTime < 125)
|
|
return Values.HitCollision.None;
|
|
|
|
if (_damageState)
|
|
OnDeath();
|
|
else
|
|
Repell();
|
|
|
|
return Values.HitCollision.Enemy;
|
|
}
|
|
|
|
private bool OnPush(Vector2 direction, PushableComponent.PushType type)
|
|
{
|
|
if (_damageState && type == PushableComponent.PushType.Impact)
|
|
OnDeath();
|
|
|
|
return true;
|
|
}
|
|
|
|
private void OnDeath()
|
|
{
|
|
var posX = (int)EntityPosition.X;
|
|
var posY = (int)EntityPosition.Y;
|
|
var speed = 2.75f / 1.4f;
|
|
|
|
var objFireball0 = new EnemyFireball(Map, posX - 2, posY - 2, 1, false);
|
|
var objFireball1 = new EnemyFireball(Map, posX + 2, posY - 2, 1, false);
|
|
var objFireball2 = new EnemyFireball(Map, posX - 2, posY + 2, 1, false);
|
|
var objFireball3 = new EnemyFireball(Map, posX + 2, posY + 2, 1, false);
|
|
|
|
objFireball0.SetVelocity(new Vector2(-1, -1) * speed);
|
|
objFireball1.SetVelocity(new Vector2(1, -1) * speed);
|
|
objFireball2.SetVelocity(new Vector2(-1, 1) * speed);
|
|
objFireball3.SetVelocity(new Vector2(1, 1) * speed);
|
|
|
|
Map.Objects.SpawnObject(objFireball0);
|
|
Map.Objects.SpawnObject(objFireball1);
|
|
Map.Objects.SpawnObject(objFireball2);
|
|
Map.Objects.SpawnObject(objFireball3);
|
|
|
|
Map.Objects.DeleteObjects.Add(this);
|
|
}
|
|
|
|
private void DeleteObject()
|
|
{
|
|
if (_objTrail0 != null)
|
|
Map.Objects.DeleteObjects.Add(_objTrail0);
|
|
if (_objTrail1 != null)
|
|
Map.Objects.DeleteObjects.Add(_objTrail1);
|
|
|
|
Map.Objects.DeleteObjects.Add(this);
|
|
}
|
|
}
|
|
} |