Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Ahorn/entities/boomBoxZip.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
module FactoryHelperBoomBoxZip
using ..Ahorn, Maple

@mapdef Entity "FactoryHelper/BoomBoxZip" BoomBoxZip(x::Integer, y::Integer, activationId::String="", initialDelay::Number=0.0, startActive::Bool=false)

const placements = Ahorn.PlacementDict(
"Boom Box Zip (Factory Helper)" => Ahorn.EntityPlacement(
BoomBoxZip,
"point",
Dict{String, Any}(
"startActive" => true
),
function(entity)
entity.data["nodes"] = [(Int(entity.data["x"]) + 32, Int(entity.data["y"]))]
end
),
)
activeSprite = "objects/FactoryHelper/boomBox/active00"

Ahorn.nodeLimits(entity::BoomBoxZip) = 1,1

ropeColor = (77, 60, 34) ./ 255
function Ahorn.renderAbs(ctx::Ahorn.Cairo.CairoContext, entity::BoomBoxZip, room::Maple.Room)
x, y = Ahorn.position(entity)

Ahorn.drawSprite(ctx, activeSprite, x + 12, y + 12)

nx, ny = Int.(entity.data["nodes"][1])

cx, cy = x + 12, y + 12
cnx,cny = nx + 12, ny + 12
length = sqrt((x - nx)^2 + (y - ny)^2)
theta = atan(cny - cy, cnx - cx)
Ahorn.Cairo.save(ctx)

Ahorn.translate(ctx, cx, cy)
Ahorn.rotate(ctx, theta)

Ahorn.setSourceColor(ctx, ropeColor)
Ahorn.set_antialias(ctx, 1)
Ahorn.set_line_width(ctx, 1);

# Offset for rounding errors
Ahorn.move_to(ctx, 0, 4 + (theta <= 0))
Ahorn.line_to(ctx, length, 4 + (theta <= 0))

Ahorn.move_to(ctx, 0, -4 - (theta > 0))
Ahorn.line_to(ctx, length, -4 - (theta > 0))

Ahorn.stroke(ctx)

Ahorn.Cairo.restore(ctx)

Ahorn.drawSprite(ctx, "objects/zipmover/cog", cnx, cny)

end

function Ahorn.selection(entity::BoomBoxZip)
x, y = Ahorn.position(entity)
nx, ny = Int.(entity.data["nodes"][1])

width = Int(get(entity.data, "width", 8))
height = Int(get(entity.data, "height", 8))

return [Ahorn.Rectangle(x, y, 24, 24), Ahorn.Rectangle(nx + floor(Int, width / 2) - 5, ny + floor(Int, height / 2) - 5, 10, 10)]
end


end
5 changes: 5 additions & 0 deletions Ahorn/lang/en_gb.lang
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ placements.entities.FactoryHelper/BoomBox.tooltips.activationId=String value of
placements.entities.FactoryHelper/BoomBox.tooltips.initialDelay=The time it takes before the box starts turning on in seconds after activated.
placements.entities.FactoryHelper/BoomBox.tooltips.startActive=If `true` the boom box will initially be active.

# Boom Box Zip
placements.entities.FactoryHelper/BoomBoxZip.tooltips.activationId=String value of the entity's activator ID. When a factory activator with this ID is turned on, the entity will toggle state.
placements.entities.FactoryHelper/BoomBoxZip.tooltips.initialDelay=The time it takes before the box starts turning on in seconds after activated.
placements.entities.FactoryHelper/BoomBoxZip.tooltips.startActive=If `true` the boom box will initially be active.

# Conveyor Belt
placements.entities.FactoryHelper/Conveyor.tooltips.activationId=String value of the entity's activator ID. When a factory activator with this ID is turned on, the entity will toggle state.
placements.entities.FactoryHelper/Conveyor.tooltips.startLeft=If `true` the conveyor will initially be moving left.
Expand Down
21 changes: 11 additions & 10 deletions Code/Entities/BoomBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ public class BoomBox : Solid {
SpeedMax = 24f
};

protected Circle _boomCollider;

private readonly float _initialDelay;
private readonly Sprite _sprite;
private readonly Sprite _boomSprite;
private readonly BoomCollider _boomCollider;
private readonly SoundSource _sfx;
private readonly float _startupTime = 1.5f;
private float _angryResetTimer = 0f;
Expand Down Expand Up @@ -63,7 +64,7 @@ public BoomBox(Vector2 position, string activationId, float initialDelay, bool s
_boomSprite.CenterOrigin();
_boomSprite.Position = new Vector2(Width / 2, Height / 2);

_boomCollider = new BoomCollider(position + new Vector2(Width / 2, Height / 2));
_boomCollider = new Circle(40f, X + Width / 2, Y + Height / 2);
Add(_sfx = new SoundSource());
_sfx.Position = new Vector2(Width / 2, Height / 2);
Add(new LightOcclude(0.2f));
Expand Down Expand Up @@ -145,7 +146,6 @@ private IEnumerator WindDownSequence() {

public override void Added(Scene scene) {
base.Added(scene);
scene.Add(_boomCollider);
Activator.HandleStartup(scene);
}

Expand All @@ -172,6 +172,13 @@ public override void Update() {
}
}

public override void DebugRender(Camera camera) {
base.DebugRender(camera);
if (Activator.IsOn) {
_boomCollider.Render(camera, Color.HotPink);
}
}

private void HandleAngryMode() {
CheckForAngryMode();
if (_angryMode) {
Expand Down Expand Up @@ -216,7 +223,7 @@ private void Explode() {
(Scene as Level).Displacement.AddBurst(Center, 0.35f, 4f, 64f, 0.5f);
Player player = Scene.Tracker.GetEntity<Player>();
Collidable = false;
if (player != null && player.CollideCheck(_boomCollider) && !Scene.CollideCheck<Solid>(player.Center, Center)) {
if (player != null && _boomCollider.Collide(player) && !Scene.CollideCheck<Solid>(player.Center, Center)) {
if (player.Bottom < Top && player.Top > Bottom) {
player.ExplodeLaunch(Center, false, true);
} else {
Expand All @@ -226,11 +233,5 @@ private void Explode() {

Collidable = true;
}

private class BoomCollider : Entity {
public BoomCollider(Vector2 position) : base(position) {
Collider = new Circle(40f, 0, 0);
}
}
}
}
201 changes: 201 additions & 0 deletions Code/Entities/BoomBoxZip.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
using Celeste;
using Celeste.Mod.Entities;
using Microsoft.Xna.Framework;
using Monocle;
using System;
using System.Collections;

namespace FactoryHelper.Entities {
[CustomEntity("FactoryHelper/BoomBoxZip")]
public class BoomBoxZip : BoomBox {
public float percent;
public Vector2 start, target;
private ZipMoverPathRenderer pathRenderer;

public BoomBoxZip(EntityData data, Vector2 offset)
: this(data.Position + offset, data.Attr("activationId", ""), data.Float("initialDelay", 0f), data.Bool("startActive", false), data.Nodes[0] + offset) {
}

public BoomBoxZip(Vector2 position, string activationId, float initialDelay, bool startActive, Vector2 target)
: base(position, activationId, initialDelay, startActive) {
Add(new Coroutine(ZipMoverSequence()));
this.start = this.Position;
this.target = target;
}

public override void Added(Scene scene) {
base.Added(scene);
scene.Add(pathRenderer = new ZipMoverPathRenderer(this));
}

private IEnumerator ZipMoverSequence() {
start = Position;
while (true) {
if (!HasPlayerRider()) {
yield return null;
continue;
}
Input.Rumble(RumbleStrength.Medium, RumbleLength.Short);
StartShaking(0.1f);
yield return 0.1f;
StopPlayerRunIntoAnimation = false;
float at2 = 0f;
while (at2 < 1f) {
yield return null;
at2 = Calc.Approach(at2, 1f, 2f * Engine.DeltaTime);
percent = Ease.SineIn(at2);
Vector2 vector = Vector2.Lerp(start, target, percent);
ScrapeParticlesCheck(vector);
if (Scene.OnInterval(0.1f)) {
pathRenderer.CreateSparks();
}

MoveTo(vector);
_boomCollider.Position = vector + new Vector2(Width / 2, Height / 2);
}

StartShaking(0.2f);
Input.Rumble(RumbleStrength.Strong, RumbleLength.Medium);
SceneAs<Level>().Shake();
StopPlayerRunIntoAnimation = true;
yield return 0.5f;
StopPlayerRunIntoAnimation = false;
at2 = 0f;
while (at2 < 1f) {
yield return null;
at2 = Calc.Approach(at2, 1f, 0.5f * Engine.DeltaTime);
percent = 1f - Ease.SineIn(at2);
Vector2 position = Vector2.Lerp(target, start, Ease.SineIn(at2));
MoveTo(position);
_boomCollider.Position = position + new Vector2(Width / 2, Height / 2);
}

StopPlayerRunIntoAnimation = true;
StartShaking(0.2f);
yield return 0.5f;
}
}

private void ScrapeParticlesCheck(Vector2 to) {
if (!base.Scene.OnInterval(0.03f)) {
return;
}

bool flag = to.Y != base.ExactPosition.Y;
bool flag2 = to.X != base.ExactPosition.X;
if (flag && !flag2) {
int num = Math.Sign(to.Y - base.ExactPosition.Y);
Vector2 value = (num != 1) ? base.TopLeft : base.BottomLeft;
int num2 = 4;
if (num == 1) {
num2 = Math.Min((int)base.Height - 12, 20);
}

int num3 = (int)base.Height;
if (num == -1) {
num3 = Math.Max(16, (int)base.Height - 16);
}

if (base.Scene.CollideCheck<Solid>(value + new Vector2(-2f, num * -2))) {
for (int i = num2; i < num3; i += 8) {
SceneAs<Level>().ParticlesFG.Emit(ZipMover.P_Scrape, base.TopLeft + new Vector2(0f, (float)i + (float)num * 2f), (num == 1) ? (-(float)Math.PI / 4f) : ((float)Math.PI / 4f));
}
}

if (base.Scene.CollideCheck<Solid>(value + new Vector2(base.Width + 2f, num * -2))) {
for (int j = num2; j < num3; j += 8) {
SceneAs<Level>().ParticlesFG.Emit(ZipMover.P_Scrape, base.TopRight + new Vector2(-1f, (float)j + (float)num * 2f), (num == 1) ? ((float)Math.PI * -3f / 4f) : ((float)Math.PI * 3f / 4f));
}
}
} else {
if (!flag2 || flag) {
return;
}

int num4 = Math.Sign(to.X - base.ExactPosition.X);
Vector2 value2 = (num4 != 1) ? base.TopLeft : base.TopRight;
int num5 = 4;
if (num4 == 1) {
num5 = Math.Min((int)base.Width - 12, 20);
}

int num6 = (int)base.Width;
if (num4 == -1) {
num6 = Math.Max(16, (int)base.Width - 16);
}

if (base.Scene.CollideCheck<Solid>(value2 + new Vector2(num4 * -2, -2f))) {
for (int k = num5; k < num6; k += 8) {
SceneAs<Level>().ParticlesFG.Emit(ZipMover.P_Scrape, base.TopLeft + new Vector2((float)k + (float)num4 * 2f, -1f), (num4 == 1) ? ((float)Math.PI * 3f / 4f) : ((float)Math.PI / 4f));
}
}

if (base.Scene.CollideCheck<Solid>(value2 + new Vector2(num4 * -2, base.Height + 2f))) {
for (int l = num5; l < num6; l += 8) {
SceneAs<Level>().ParticlesFG.Emit(ZipMover.P_Scrape, base.BottomLeft + new Vector2((float)l + (float)num4 * 2f, 0f), (num4 == 1) ? ((float)Math.PI * -3f / 4f) : (-(float)Math.PI / 4f));
}
}
}
}

private class ZipMoverPathRenderer : Entity {
private static readonly Color ropeColor = Calc.HexToColor("4d3c22");
private static readonly Color ropeLightColor = Calc.HexToColor("766c49");

public BoomBoxZip zipMover;

private MTexture cog;
private Vector2 from;
private Vector2 to;
private Vector2 sparkAdd;
private float sparkDirFromA;
private float sparkDirFromB;
private float sparkDirToA;
private float sparkDirToB;

public ZipMoverPathRenderer(BoomBoxZip zipMover) {
base.Depth = 5000;
this.zipMover = zipMover;
from = this.zipMover.start + new Vector2(this.zipMover.Width / 2f, this.zipMover.Height / 2f);
to = this.zipMover.target + new Vector2(this.zipMover.Width / 2f, this.zipMover.Height / 2f);
sparkAdd = (from - to).SafeNormalize(5f).Perpendicular();
float num = (from - to).Angle();
sparkDirFromA = num + (float)Math.PI / 8f;
sparkDirFromB = num - (float)Math.PI / 8f;
sparkDirToA = num + (float)Math.PI - (float)Math.PI / 8f;
sparkDirToB = num + (float)Math.PI + (float)Math.PI / 8f;
cog = GFX.Game["objects/zipmover/cog"];
}

public void CreateSparks() {
SceneAs<Level>().ParticlesBG.Emit(ZipMover.P_Sparks, from + sparkAdd + Calc.Random.Range(-Vector2.One, Vector2.One), sparkDirFromA);
SceneAs<Level>().ParticlesBG.Emit(ZipMover.P_Sparks, from - sparkAdd + Calc.Random.Range(-Vector2.One, Vector2.One), sparkDirFromB);
SceneAs<Level>().ParticlesBG.Emit(ZipMover.P_Sparks, to + sparkAdd + Calc.Random.Range(-Vector2.One, Vector2.One), sparkDirToA);
SceneAs<Level>().ParticlesBG.Emit(ZipMover.P_Sparks, to - sparkAdd + Calc.Random.Range(-Vector2.One, Vector2.One), sparkDirToB);
}

public override void Render() {
DrawCogs(Vector2.UnitY, Color.Black);
DrawCogs(Vector2.Zero);
}

private void DrawCogs(Vector2 offset, Color? colorOverride = null) {
Vector2 vector = (to - from).SafeNormalize();
Vector2 value = vector.Perpendicular() * 3f;
Vector2 value2 = -vector.Perpendicular() * 4f;
float rotation = zipMover.percent * (float)Math.PI * 2f;
Draw.Line(from + value + offset, to + value + offset, colorOverride.HasValue ? colorOverride.Value : ropeColor);
Draw.Line(from + value2 + offset, to + value2 + offset, colorOverride.HasValue ? colorOverride.Value : ropeColor);
for (float num = 4f - zipMover.percent * (float)Math.PI * 8f % 4f; num < (to - from).Length(); num += 4f) {
Vector2 value3 = from + value + vector.Perpendicular() + vector * num;
Vector2 value4 = to + value2 - vector * num;
Draw.Line(value3 + offset, value3 + vector * 2f + offset, colorOverride.HasValue ? colorOverride.Value : ropeLightColor);
Draw.Line(value4 + offset, value4 - vector * 2f + offset, colorOverride.HasValue ? colorOverride.Value : ropeLightColor);
}

cog.DrawCentered(from + offset, colorOverride.HasValue ? colorOverride.Value : Color.White, 1f, rotation);
cog.DrawCentered(to + offset, colorOverride.HasValue ? colorOverride.Value : Color.White, 1f, rotation);
}
}
}
}
Loading
Loading