LADXHD/InGame/GameObjects/Enemies/EnemyStalfosOrange.cs
2023-12-14 17:21:22 -05:00

163 lines
6.3 KiB
C#

using System;
using Microsoft.Xna.Framework;
using ProjectZ.InGame.Controls;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.GameObjects.Base.Components;
using ProjectZ.InGame.GameObjects.Base.CObjects;
using ProjectZ.InGame.GameObjects.Base.Components.AI;
using ProjectZ.InGame.Map;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
namespace ProjectZ.InGame.GameObjects.Enemies
{
internal class EnemyStalfosOrange : GameObject
{
private readonly BodyComponent _body;
private readonly AiComponent _aiComponent;
private readonly Animator _animator;
private readonly AiTriggerTimer _jumpSwitch;
private readonly bool _isBoneThrower;
private float _acceleration = 1.75f;
private float _walkSpeed = 0.5f;
private float _changeDirCount;
private int _dir;
private float _throwCounter;
private bool _throwBone;
public EnemyStalfosOrange() : base("stalfos orange") { }
public EnemyStalfosOrange(Map.Map map, int posX, int posY, bool isBoneThrower) : base(map)
{
Tags = Values.GameObjectTag.Enemy;
_isBoneThrower = isBoneThrower;
EntityPosition = new CPosition(posX + 8, posY + 16, 0);
EntitySize = new Rectangle(-8, -32, 16, 32);
_animator = AnimatorSaveLoad.LoadAnimator("Enemies/stalfos orange");
_animator.Play("walk");
var sprite = new CSprite(EntityPosition);
var animatorComponent = new AnimationComponent(_animator, sprite, new Vector2(-8, -16));
var fieldRectangle = map.GetField(posX, posY);
_body = new BodyComponent(EntityPosition, -6, -10, 11, 10, 8)
{
MoveCollision = OnCollision,
Gravity = -0.1f,
CollisionTypes = Values.CollisionTypes.Normal | Values.CollisionTypes.NPCWall,
AvoidTypes = Values.CollisionTypes.Hole | Values.CollisionTypes.NPCWall,
FieldRectangle = fieldRectangle
};
_aiComponent = new AiComponent();
var stateWalking = new AiState(UpdateWalking);
stateWalking.Trigger.Add(_jumpSwitch = new AiTriggerTimer(75));
var stateJumping = new AiState(UpdateJumping);
_aiComponent.States.Add("walking", stateWalking);
_aiComponent.States.Add("jumping", stateJumping);
new AiFallState(_aiComponent, _body, null, null, 200);
var damageState = new AiDamageState(this, _body, _aiComponent, sprite, 2) { OnBurn = () => _animator.Pause() };
_aiComponent.ChangeState("walking");
var damageBox = new CBox(EntityPosition, -7, -15, 2, 13, 15, 4);
var hittableBox = new CBox(EntityPosition, -7, -15, 2, 13, 15, 8);
var pushableBox = new CBox(EntityPosition, -6, -14, 2, 12, 14, 4);
AddComponent(DamageFieldComponent.Index, new DamageFieldComponent(damageBox, HitType.Enemy, 2));
AddComponent(HittableComponent.Index, new HittableComponent(hittableBox, damageState.OnHit));
AddComponent(AiComponent.Index, _aiComponent);
AddComponent(BodyComponent.Index, _body);
AddComponent(BaseAnimationComponent.Index, animatorComponent);
AddComponent(PushableComponent.Index, new PushableComponent(pushableBox, OnPush));
AddComponent(DrawComponent.Index, new BodyDrawComponent(_body, sprite, Values.LayerPlayer));
AddComponent(DrawShadowComponent.Index, new BodyDrawShadowComponent(_body, sprite) { ShadowWidth = 10 });
}
private void UpdateWalking()
{
_animator.Play("walk");
if (_throwBone)
{
_throwCounter -= Game1.DeltaTime;
if (_throwCounter < 0)
{
_throwBone = false;
// throw a bone towards the player
Map.Objects.SpawnObject(new EnemyBone(Map, (int)EntityPosition.X, (int)EntityPosition.Y - 8, 1.5f));
}
}
// jump away when the player is pressing the use key
var distance = EntityPosition.Position - MapManager.ObjLink.EntityPosition.Position;
if (_jumpSwitch.State && distance.Length() < 48)
for (var i = 0; i < 4; i++)
if (ControlHandler.ButtonPressed((CButtons)((int)CButtons.A * Math.Pow(2, i))))
{
ToJumping();
break;
}
_changeDirCount -= Game1.DeltaTime;
// change direction
if (_changeDirCount <= 0)
ChangeDirection();
}
private void ToJumping()
{
Game1.GameManager.PlaySoundEffect("D360-36-24");
_aiComponent.ChangeState("jumping");
// jump away from the player
var vecDirection = EntityPosition.Position - MapManager.ObjLink.EntityPosition.Position;
vecDirection.Normalize();
_body.Velocity = new Vector3(0, 0, _acceleration);
_body.VelocityTarget = new Vector2(vecDirection.X, vecDirection.Y);
_throwBone = _isBoneThrower;
_throwCounter = 300;
}
private void UpdateJumping()
{
_animator.Play("jump");
if (_body.IsGrounded)
_aiComponent.ChangeState("walking");
}
private void ChangeDirection()
{
_changeDirCount = Game1.RandomNumber.Next(200, 600);
_dir = Game1.RandomNumber.Next(0, 4);
_body.VelocityTarget = AnimationHelper.DirectionOffset[_dir] * _walkSpeed;
}
private bool OnPush(Vector2 direction, PushableComponent.PushType type)
{
if (type == PushableComponent.PushType.Impact)
_body.Velocity = new Vector3(direction.X * 1.75f, direction.Y * 1.75f, _body.Velocity.Z);
return true;
}
private void OnCollision(Values.BodyCollision collision)
{
if (_aiComponent.CurrentStateId == "walking")
ChangeDirection();
}
}
}