mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-01 04:14:22 +00:00
237 lines
8.8 KiB
C#
237 lines
8.8 KiB
C#
using Microsoft.Xna.Framework;
|
|
using ProjectZ.InGame.GameObjects.Base;
|
|
using ProjectZ.InGame.GameObjects.Base.Components;
|
|
using ProjectZ.InGame.GameObjects.Base.Components.AI;
|
|
using ProjectZ.InGame.GameObjects.Base.CObjects;
|
|
using ProjectZ.InGame.GameObjects.Things;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
using ProjectZ.InGame.Things;
|
|
|
|
namespace ProjectZ.InGame.GameObjects.Enemies
|
|
{
|
|
internal class EnemyMadBomber : GameObject
|
|
{
|
|
private readonly AiComponent _aiComponent;
|
|
private readonly Animator _animator;
|
|
private readonly CSprite _sprite;
|
|
private readonly AiDamageState _damageState;
|
|
private readonly AiStunnedState _aiStunnedState;
|
|
private readonly DamageFieldComponent _damageField;
|
|
|
|
private readonly Vector2[] _holeOffsets = {
|
|
new Vector2(0, 0), new Vector2(3, -1), new Vector2(-3, -1),
|
|
new Vector2(0, -3), new Vector2(-2, 2), new Vector2(2, 2)
|
|
};
|
|
|
|
private const string _leafSaveKey = "ow_goldLeafMadBomber";
|
|
|
|
private readonly Vector2 _spawnPosition;
|
|
private bool _wasHit;
|
|
|
|
public EnemyMadBomber() : base("madBomber") { }
|
|
|
|
public EnemyMadBomber(Map.Map map, int posX, int posY) : base(map)
|
|
{
|
|
// abort spawn if the player already has the leaf
|
|
if (Game1.GameManager.SaveManager.GetString(_leafSaveKey) == "1")
|
|
{
|
|
IsDead = true;
|
|
return;
|
|
}
|
|
|
|
Tags = Values.GameObjectTag.Enemy;
|
|
|
|
EntityPosition = new CPosition(posX + 8, posY + 15, 0);
|
|
EntitySize = new Rectangle(-8, -15, 16, 16);
|
|
|
|
_spawnPosition = new Vector2(posX + 8, posY + 15);
|
|
|
|
_animator = AnimatorSaveLoad.LoadAnimator("Enemies/mad bomber");
|
|
|
|
_sprite = new CSprite(EntityPosition) { IsVisible = false };
|
|
var animationComponent = new AnimationComponent(_animator, _sprite, new Vector2(-8, -15));
|
|
|
|
var body = new BodyComponent(EntityPosition, -7, -14, 14, 14, 8)
|
|
{
|
|
IgnoreHoles = true
|
|
};
|
|
|
|
var stateCooldown = new AiState();
|
|
stateCooldown.Trigger.Add(new AiTriggerRandomTime(() => _aiComponent.ChangeState("hidden"), 1000, 1500));
|
|
var stateHidden = new AiState(UpdateHidden);
|
|
var stateComing = new AiState(UpdateComing);
|
|
var stateLeaving = new AiState(UpdateLeaving);
|
|
|
|
_aiComponent = new AiComponent();
|
|
_aiComponent.States.Add("cooldown", stateCooldown);
|
|
_aiComponent.States.Add("hidden", stateHidden);
|
|
_aiComponent.States.Add("coming", stateComing);
|
|
_aiComponent.States.Add("leaving", stateLeaving);
|
|
_aiStunnedState = new AiStunnedState(_aiComponent, animationComponent, 3300, 900);
|
|
|
|
_aiComponent.ChangeState("hidden");
|
|
|
|
_damageState = new AiDamageState(this, body, _aiComponent, _sprite, 4, false)
|
|
{
|
|
IsActive = false,
|
|
SpawnItems = false,
|
|
HitMultiplierX = 0,
|
|
HitMultiplierY = 0,
|
|
OnDeath = OnDeath
|
|
};
|
|
|
|
var damageBox = new CBox(EntityPosition, -7, -14, 0, 14, 14, 8);
|
|
AddComponent(DamageFieldComponent.Index, _damageField = new DamageFieldComponent(damageBox, HitType.Enemy, 2));
|
|
AddComponent(HittableComponent.Index, new HittableComponent(body.BodyBox, OnHit));
|
|
AddComponent(BodyComponent.Index, body);
|
|
AddComponent(AiComponent.Index, _aiComponent);
|
|
AddComponent(BaseAnimationComponent.Index, animationComponent);
|
|
AddComponent(DrawComponent.Index, new BodyDrawComponent(body, _sprite, Values.LayerPlayer));
|
|
}
|
|
|
|
private void OnDeath(bool pieceofpower)
|
|
{
|
|
var playerDirection = MapManager.ObjLink.EntityPosition.Position - EntityPosition.Position;
|
|
if (playerDirection != Vector2.Zero)
|
|
playerDirection.Normalize();
|
|
playerDirection *= 2.25f;
|
|
|
|
// spawn the golden leaf jumping towards the player
|
|
var objLeaf = new ObjItem(Map, 0, 0, null, _leafSaveKey, "goldLeaf", null);
|
|
objLeaf.EntityPosition.Set(new Vector3(EntityPosition.X, EntityPosition.Y + 1, 1));
|
|
objLeaf.SetVelocity(new Vector3(playerDirection.X, playerDirection.Y, 1.5f));
|
|
objLeaf.Collectable = false;
|
|
Map.Objects.SpawnObject(objLeaf);
|
|
|
|
_damageState.BaseOnDeath(pieceofpower);
|
|
}
|
|
|
|
private Values.HitCollision OnHit(GameObject gameObject, Vector2 direction, HitType damageType, int damage, bool pieceOfPower)
|
|
{
|
|
if (_damageState.IsInDamageState())
|
|
return Values.HitCollision.None;
|
|
|
|
if (_aiComponent.CurrentStateId == "coming")
|
|
_wasHit = true;
|
|
|
|
// stun state
|
|
if (damageType == HitType.Hookshot)
|
|
{
|
|
_damageState.SetDamageState(false);
|
|
|
|
_aiStunnedState.StartStun();
|
|
_animator.Pause();
|
|
|
|
return Values.HitCollision.Enemy;
|
|
}
|
|
|
|
if (damageType == HitType.Bow || damageType == HitType.MagicRod)
|
|
damage = 1;
|
|
if (damageType == HitType.MagicPowder || damageType == HitType.Boomerang)
|
|
damage = 0;
|
|
|
|
var hitReturn = _damageState.OnHit(gameObject, direction, damageType, damage, pieceOfPower);
|
|
|
|
// make sure to not disapear while moving out of the hole with piece of power active
|
|
if (_damageState.CurrentLives <= 0)
|
|
{
|
|
_animator.Pause();
|
|
_damageState.HasDamageState = true;
|
|
}
|
|
|
|
return hitReturn;
|
|
}
|
|
|
|
private void ToCooldown()
|
|
{
|
|
_aiComponent.ChangeState("cooldown");
|
|
_sprite.IsVisible = false;
|
|
}
|
|
|
|
private void UpdateHidden()
|
|
{
|
|
// only spawn if the player is close enough
|
|
var playerDirection = MapManager.ObjLink.EntityPosition.Position - new Vector2(_spawnPosition.X, _spawnPosition.Y - 15);
|
|
if (playerDirection.Length() < 64)
|
|
ToComing();
|
|
}
|
|
|
|
private void ToComing()
|
|
{
|
|
// find a hole to come out
|
|
var tryCounter = 0;
|
|
while (tryCounter < 10)
|
|
{
|
|
tryCounter++;
|
|
|
|
var randomNum = Game1.RandomNumber.Next(0, _holeOffsets.Length);
|
|
var holePosition = _spawnPosition + _holeOffsets[randomNum] * 16;
|
|
|
|
// check the distance to not spawn next to the player
|
|
var direction = MapManager.ObjLink.EntityPosition.Position - holePosition;
|
|
if (direction.Length() > 48)
|
|
{
|
|
_aiComponent.ChangeState("coming");
|
|
|
|
EntityPosition.Set(holePosition);
|
|
|
|
var playerOnTheRight = EntityPosition.X < MapManager.ObjLink.EntityPosition.X;
|
|
_animator.Play(playerOnTheRight ? "come_1" : "come_0");
|
|
|
|
_sprite.IsVisible = true;
|
|
_damageState.IsActive = true;
|
|
_damageField.IsActive = true;
|
|
_wasHit = false;
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateComing()
|
|
{
|
|
// finished the enter animation
|
|
if (!_animator.IsPlaying)
|
|
{
|
|
if (!_wasHit)
|
|
ThrowBomb();
|
|
|
|
ToLeaving();
|
|
}
|
|
}
|
|
|
|
private void ToLeaving()
|
|
{
|
|
_aiComponent.ChangeState("leaving");
|
|
_animator.Play("leave");
|
|
_damageState.IsActive = false;
|
|
_damageField.IsActive = false;
|
|
}
|
|
|
|
private void ThrowBomb()
|
|
{
|
|
var throwDirection = MapManager.ObjLink.EntityPosition.Position - EntityPosition.Position;
|
|
if (throwDirection != Vector2.Zero)
|
|
throwDirection.Normalize();
|
|
throwDirection *= 0.8f;
|
|
|
|
// spawn a bomb
|
|
var bomb = new ObjBomb(Map, 0, 0, false, true);
|
|
bomb.EntityPosition.Set(new Vector3(EntityPosition.X, EntityPosition.Y + 1, 6));
|
|
bomb.Body.Velocity = new Vector3(throwDirection.X, throwDirection.Y, 1.5f);
|
|
bomb.Body.Gravity = -0.1f;
|
|
bomb.Body.DragAir = 1.0f;
|
|
bomb.Body.Bounciness = 0.25f;
|
|
Map.Objects.SpawnObject(bomb);
|
|
|
|
Game1.GameManager.PlaySoundEffect("D360-08-08");
|
|
}
|
|
|
|
private void UpdateLeaving()
|
|
{
|
|
if (!_animator.IsPlaying)
|
|
ToCooldown();
|
|
}
|
|
}
|
|
} |