From 2a23d8f09255b62befe4ffe4c3110f22f157c241 Mon Sep 17 00:00:00 2001 From: Sharivan Date: Mon, 27 Mar 2023 06:12:56 -0300 Subject: [PATCH] - Added Dig Labour enemy. --- .../Assets/Sprites/Enemies/X1/Dig Labour.png | Bin 4387 -> 5983 bytes .../Entities/Enemies/DigLabour/DigLabour.cs | 237 +++++++++++++++++- .../Enemies/DigLabour/DigLabourPickaxe.cs | 62 +++++ XSharp/Engine/Entities/Enemies/Enemy.cs | 14 ++ .../Entities/Enemies/GunVolt/GunVolt.cs | 1 - XSharp/Engine/Entities/Sprite.cs | 3 +- XSharp/Engine/GameEngine.cs | 13 + 7 files changed, 326 insertions(+), 4 deletions(-) create mode 100644 XSharp/Engine/Entities/Enemies/DigLabour/DigLabourPickaxe.cs diff --git a/XSharp/Assets/Sprites/Enemies/X1/Dig Labour.png b/XSharp/Assets/Sprites/Enemies/X1/Dig Labour.png index 3412e7ac6fe84d03f7f8978a957994cb056a5836..71774cb3dbf40d3691256b5d009d1645d93b0570 100644 GIT binary patch literal 5983 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 Q87U4R^iB2N={U#y2a)<-lK=n! literal 4387 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 +{ + #region StaticFields + public static readonly Color[] PALETTE = new Color[] + { + Color.Transparent, // 0 + Color.FromBgra(0xFF406830), // 1 + Color.FromBgra(0xFF70B888), // 2 + Color.FromBgra(0xFFD0E0B0), // 3 + Color.FromBgra(0xFFB85820), // 4 + Color.FromBgra(0xFFE8A040), // 5 + Color.FromBgra(0xFFF8D888), // 6 + Color.FromBgra(0xFF405880), // 7 + Color.FromBgra(0xFF6098C8), // 8 + Color.FromBgra(0xFFA0D8F8), // 9 + Color.FromBgra(0xFF705870), // A + Color.FromBgra(0xFFA090A0), // B + Color.FromBgra(0xFFE0D0E0), // C + Color.FromBgra(0xFF783830), // D + Color.FromBgra(0xFFF87858), // E + Color.FromBgra(0xFF302020) // F + }; + + public const int HEALTH = 8; + public static readonly FixedSingle CONTACT_DAMAGE = 2; + public static readonly Box HITBOX = ((0, 1), (-11, -17), (11, 17)); + public static readonly Box COLLISION_BOX = ((0, 0), (-11, -17), (11, 17)); + + public const int IDLE_AFTER_ATTACKING_FRAMES = 90; + public const int IDLE_AFTER_LAUGHING_FRAMES = 50; + public const int ATTACKING_FRAMES = 38; + public const int LAUGHING_FRAMES = 80; + public const int FRAME_TO_THROW_PICKAXE = 18; + + public static readonly FixedSingle PICKAXE_INITIAL_SPEED = 1536 / 256.0; + public static readonly Box PICKAXE_HITBOX = ((0, 0), (-11, -12), (11, 12)); + public const int PICKAXE_DAMAGE = 2; + public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_X = 20; + public static readonly FixedSingle PICKAXE_SPAWN_OFFSET_Y = -12; + #endregion + + #region Precache + [Precache] + new internal static void Precache() + { + var palette = Engine.PrecachePalette("DigLabourPalette", PALETTE); + var spriteSheet = Engine.CreateSpriteSheet("DigLabour", true, true); + + spriteSheet.CurrentTexture = Engine.CreateImageTextureFromEmbeddedResource("Sprites.Enemies.X1.Dig Labour.png"); + spriteSheet.CurrentPalette = palette; + + var sequence = spriteSheet.AddFrameSquence("Idle"); + sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins; + sequence.Hitbox = HITBOX; + sequence.AddFrame(4, 2, 4, 13, 32, 37, 1, true); + + sequence = spriteSheet.AddFrameSquence("Attacking"); + sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins; + sequence.Hitbox = HITBOX; + sequence.AddFrame(4, 2, 4, 13, 32, 37, 4); + sequence.AddFrame(3, 2, 150, 14, 32, 37, 5); + sequence.AddFrame(2, 2, 199, 13, 34, 37, 4); + sequence.AddFrame(6, 3, 247, 13, 38, 38, 4); + sequence.AddFrame(9, 4, 296, 12, 40, 39, 4); + sequence.AddFrame(13, 2, 345, 13, 41, 37, 17); // pickaxe spawn here, total of 38 frames + + sequence = spriteSheet.AddFrameSquence("Laughing"); + sequence.OriginOffset = -HITBOX.Origin - HITBOX.Mins; + sequence.Hitbox = HITBOX; + sequence.AddFrame(4, 2, 4, 13, 32, 37, 4, true); + sequence.AddFrame(4, 2, 54, 13, 32, 37, 4); + sequence.AddFrame(5, 3, 104, 13, 32, 38, 4); + sequence.AddFrame(4, 2, 54, 13, 32, 37, 4); // this cycle is repeated 5 times, totalizing 80 frames + + sequence = spriteSheet.AddFrameSquence("Pickaxe"); + sequence.OriginOffset = -PICKAXE_HITBOX.Origin - PICKAXE_HITBOX.Mins; + sequence.Hitbox = PICKAXE_HITBOX; + sequence.AddFrame(1, 0, 403, 34, 24, 24, 3, true); + sequence.AddFrame(2, -2, 456, 9, 21, 20, 3); + sequence.AddFrame(1, -2, 481, 7, 24, 24, 3); + sequence.AddFrame(1, -4, 431, 9, 21, 20, 3); + sequence.AddFrame(1, -1, 403, 7, 24, 24, 3); + sequence.AddFrame(-1, -4, 431, 36, 21, 20, 3); + sequence.AddFrame(1, -2, 481, 34, 24, 24, 3); + sequence.AddFrame(-3, -2, 456, 36, 21, 20, 3); + + spriteSheet.ReleaseCurrentTexture(); + } + #endregion + + private int idleFrames; + + public DigLabourState State + { + get => GetState(); + set => SetState(value); + } + + public DigLabour() + { + } + + protected override void OnCreate() + { + base.OnCreate(); + + DefaultDirection = Direction.LEFT; + SpawnFacedToPlayer = true; + AlwaysFaceToPlayer = true; + + PaletteName = "DigLabourPalette"; + SpriteSheetName = "DigLabour"; + + SetAnimationNames("Idle", "Attacking", "Laughing"); + + SetupStateArray(); + RegisterState(DigLabourState.IDLE, OnIdle, "Idle"); + RegisterState(DigLabourState.ATTACKING, OnAttacking, "Attacking"); + RegisterState(DigLabourState.LAUGHING, OnLaughing, "Laughing"); + } + + private void OnIdle(EntityState state, long frameCounter) + { + if (frameCounter >= idleFrames) + State = DigLabourState.ATTACKING; + } + + private void OnAttacking(EntityState state, long frameCounter) + { + if (frameCounter == FRAME_TO_THROW_PICKAXE) + { + ThrowPickaxe(); + } + else if (frameCounter >= ATTACKING_FRAMES) + { + idleFrames = IDLE_AFTER_ATTACKING_FRAMES; + State = DigLabourState.IDLE; + } + } + + private void OnLaughing(EntityState state, long frameCounter) + { + if (frameCounter >= LAUGHING_FRAMES) + { + idleFrames = IDLE_AFTER_LAUGHING_FRAMES; + State = DigLabourState.IDLE; + } + } + + private EntityReference ThrowPickaxe() + { + var player = Engine.Player; + if (player == null) + return null; + + var throwOrigin = Origin + (PICKAXE_SPAWN_OFFSET_X * Direction.GetHorizontalSignal(), PICKAXE_SPAWN_OFFSET_Y); + + double v = PICKAXE_INITIAL_SPEED; + double v2 = v * v; + double g = GRAVITY; + double dx = player.Origin.X - throwOrigin.X; + int dxs = System.Math.Sign(dx); + double dy = player.Origin.Y - throwOrigin.Y; + double alpha = v / (g * dx); + double alpha2 = alpha * alpha; + double delta = v2 + 2 * g * dy - 1 / alpha2; + + if (delta < 0) + delta = 0; + + double tanTheta = alpha * (-v - System.Math.Sqrt(delta)); + double theta = System.Math.Atan(tanTheta); + + FixedSingle vx = dxs * v * System.Math.Cos(theta); + FixedSingle vy = dxs * v * System.Math.Sin(theta); + + DigLabourPickaxe pickaxe = Engine.Entities.Create(new + { + Origin = throwOrigin, + Velocity = (vx.TruncFracPart(), vy.TruncFracPart()), + Direction + }); + + pickaxe.pitcher = this; + pickaxe.Spawn(); + return pickaxe; + } + + protected override Box GetHitbox() + { + return HITBOX; + } + + protected override Box GetCollisionBox() + { + return COLLISION_BOX; + } + + protected override void OnSpawn() + { + base.OnSpawn(); + + Health = HEALTH; + ContactDamage = CONTACT_DAMAGE; + + NothingDropOdd = 9000; // 90% + SmallHealthDropOdd = 300; // 3% + BigHealthDropOdd = 100; // 1% + SmallAmmoDropOdd = 400; // 4% + BigAmmoDropOdd = 175; // 1.75% + LifeUpDropOdd = 25; // 0.25% + + idleFrames = IDLE_AFTER_ATTACKING_FRAMES; + State = DigLabourState.IDLE; + } + + internal void NotifyPlayerDamagedByPickaxe() + { + State = DigLabourState.LAUGHING; + } } \ No newline at end of file diff --git a/XSharp/Engine/Entities/Enemies/DigLabour/DigLabourPickaxe.cs b/XSharp/Engine/Entities/Enemies/DigLabour/DigLabourPickaxe.cs new file mode 100644 index 0000000..b10cb71 --- /dev/null +++ b/XSharp/Engine/Entities/Enemies/DigLabour/DigLabourPickaxe.cs @@ -0,0 +1,62 @@ +using SharpDX; + +using XSharp.Engine.Graphics; +using XSharp.Math; +using XSharp.Math.Geometry; + +namespace XSharp.Engine.Entities.Enemies.DigLabour; + +public class DigLabourPickaxe : Enemy +{ + #region Precache + [Precache] + new internal static void Precache() + { + Engine.CallPrecacheAction(); + } + #endregion + + internal EntityReference pitcher; + + public DigLabour Pitcher => pitcher; + + public DigLabourPickaxe() + { + } + + protected override void OnCreate() + { + base.OnCreate(); + + DefaultDirection = Direction.LEFT; + SpawnFacedToPlayer = false; + + PaletteName = "DigLabourPalette"; + SpriteSheetName = "DigLabour"; + + SetAnimationNames("Pickaxe"); + InitialAnimationName = "Pickaxe"; + } + + protected override Box GetHitbox() + { + return DigLabour.PICKAXE_HITBOX; + } + + protected override void OnSpawn() + { + base.OnSpawn(); + + CheckCollisionWithWorld = false; + ContactDamage = DigLabour.PICKAXE_DAMAGE; + HitResponse = HitResponse.IGNORE; + Invincible = true; + } + + protected override void OnContactDamage(Player player) + { + base.OnContactDamage(player); + + Pitcher?.NotifyPlayerDamagedByPickaxe(); + } +} \ No newline at end of file diff --git a/XSharp/Engine/Entities/Enemies/Enemy.cs b/XSharp/Engine/Entities/Enemies/Enemy.cs index 7871fa2..49b6577 100644 --- a/XSharp/Engine/Entities/Enemies/Enemy.cs +++ b/XSharp/Engine/Entities/Enemies/Enemy.cs @@ -60,6 +60,12 @@ public bool SpawnFacedToPlayer set; } = true; + public bool AlwaysFaceToPlayer + { + get; + set; + } = false; + public HitResponse HitResponse { get; @@ -264,6 +270,14 @@ protected override void OnBroke() Engine.DropSmallAmmoRecover(Origin, ITEM_DURATION_FRAMES); } + protected override void OnThink() + { + base.OnThink(); + + if (AlwaysFaceToPlayer) + FaceToPlayer(); + } + protected override void OnDeath() { if (flashing && lastPaletteName != null) diff --git a/XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs b/XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs index d0e5987..eed8ee4 100644 --- a/XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs +++ b/XSharp/Engine/Entities/Enemies/GunVolt/GunVolt.cs @@ -44,7 +44,6 @@ public class GunVolt : Enemy, IStateEntity public static readonly Box HITBOX = ((0, 1), (-16, -29), (16, 29)); public static readonly Box COLLISION_BOX = ((0, 0), (-16, -29), (16, 29)); - public static readonly FixedSingle ATTACK_DISTANCE_X = 104; public const int SHORT_IDLE_FRAMES = 40; public const int LONG_IDLE_FRAMES = 100; public const int PRE_SHOOTING_FRAMES = 72; diff --git a/XSharp/Engine/Entities/Sprite.cs b/XSharp/Engine/Entities/Sprite.cs index 9a91963..b6d59c9 100644 --- a/XSharp/Engine/Entities/Sprite.cs +++ b/XSharp/Engine/Entities/Sprite.cs @@ -2008,7 +2008,8 @@ public void FaceToEntity(Entity entity) public void FaceToPlayer() { - FaceToEntity(Engine.Player); + if (Engine.Player != null) + FaceToEntity(Engine.Player); } public void FaceToScreenCenter() diff --git a/XSharp/Engine/GameEngine.cs b/XSharp/Engine/GameEngine.cs index bad7cef..bbb6841 100644 --- a/XSharp/Engine/GameEngine.cs +++ b/XSharp/Engine/GameEngine.cs @@ -24,6 +24,7 @@ using XSharp.Engine.Entities.Enemies.BombBeen; using XSharp.Engine.Entities.Enemies.Bosses; using XSharp.Engine.Entities.Enemies.Bosses.ChillPenguin; +using XSharp.Engine.Entities.Enemies.DigLabour; using XSharp.Engine.Entities.Enemies.Flammingle; using XSharp.Engine.Entities.Enemies.GunVolt; using XSharp.Engine.Entities.Enemies.RayBit; @@ -3941,6 +3942,7 @@ public Sprite AddObjectEvent(ushort id, ushort subid, Vector origin) 0x2C when mmx.Type == 1 => AddProbe8201U(subid, origin), 0x2D when mmx.Type == 0 => AddBattonBoneG(subid, origin), 0x2F => AddArmorSoldier(subid, origin), + 0x30 when mmx.Type == 0 => AddDigLabour(subid, origin), 0x36 when mmx.Type == 0 => AddJamminger(subid, origin), 0x3A when mmx.Type == 0 => AddTombot(subid, origin), 0x4D => AddCapsule(subid, origin), @@ -4327,6 +4329,17 @@ public ArmorSoldier AddArmorSoldier(ushort subid, Vector origin) return Entities.GetReferenceTo(entity); } + public EntityReference AddDigLabour(ushort subid, Vector origin) + { + DigLabour entity = Entities.Create(new + { + Origin = origin + }); + + entity.Place(); + return Entities.GetReferenceTo(entity); + } + public EntityReference AddJamminger(ushort subid, Vector origin) { Jamminger entity = Entities.Create(new