Skip to content

Commit 9f6d862

Browse files
committed
Initial impl. of Crystal Bomb Detonator field
The "it works" pass.
1 parent 238613b commit 9f6d862

File tree

4 files changed

+429
-0
lines changed

4 files changed

+429
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module SpringCollab2020CrystalBombDetonator
2+
3+
using ..Ahorn, Maple
4+
5+
@mapdef Entity "SpringCollab2020/crystalBombDetonator" CrystalBombDetonator(x::Integer, y::Integer, width::Integer=Maple.defaultBlockWidth, height::Integer=Maple.defaultBlockHeight)
6+
7+
const placements = Ahorn.PlacementDict(
8+
"Crystal Bomb Detonation Field (Spring Collab 2020)" => Ahorn.EntityPlacement(
9+
CrystalBombDetonator,
10+
"rectangle"
11+
),
12+
)
13+
14+
Ahorn.minimumSize(entity::CrystalBombDetonator) = 8, 8
15+
Ahorn.resizable(entity::CrystalBombDetonator) = true, true
16+
17+
function Ahorn.selection(entity::CrystalBombDetonator)
18+
x, y = Ahorn.position(entity)
19+
20+
width = Int(get(entity.data, "width", 8))
21+
height = Int(get(entity.data, "height", 8))
22+
23+
return Ahorn.Rectangle(x, y, width, height)
24+
end
25+
26+
function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::CrystalBombDetonator, room::Maple.Room)
27+
width = Int(get(entity.data, "width", 32))
28+
height = Int(get(entity.data, "height", 32))
29+
30+
Ahorn.drawRectangle(ctx, 0, 0, width, height, (0.45, 0.0, 0.45, 0.8), (0.0, 0.0, 0.0, 0.0))
31+
end
32+
33+
end

Entities/CrystalBombDetonator.cs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using Celeste.Mod.Entities;
5+
using Microsoft.Xna.Framework;
6+
using Monocle;
7+
8+
namespace Celeste.Mod.SpringCollab2020.Entities {
9+
[Tracked(false)]
10+
[CustomEntity("SpringCollab2020/crystalBombDetonator")]
11+
public class CrystalBombDetonator : Solid {
12+
public CrystalBombDetonator(Vector2 position, float width, float height) : base(position, width, height, false) {
13+
Flash = 0f;
14+
Solidify = 0f;
15+
Flashing = false;
16+
solidifyDelay = 0f;
17+
particles = new List<Vector2>();
18+
adjacent = new List<CrystalBombDetonator>();
19+
speeds = new float[]
20+
{
21+
12f,
22+
20f,
23+
40f
24+
};
25+
Collidable = false;
26+
int num = 0;
27+
while ((float) num < Width * Height / 16f) {
28+
particles.Add(new Vector2(Calc.Random.NextFloat(Width - 1f), Calc.Random.NextFloat(Height - 1f)));
29+
num++;
30+
}
31+
}
32+
33+
public CrystalBombDetonator(EntityData data, Vector2 offset) : this(data.Position + offset, (float) data.Width, (float) data.Height) {
34+
}
35+
36+
public override void Added(Scene scene) {
37+
base.Added(scene);
38+
scene.Tracker.GetEntity<CrystalBombDetonatorRenderer>().Track(this);
39+
}
40+
41+
public override void Removed(Scene scene) {
42+
base.Removed(scene);
43+
scene.Tracker.GetEntity<CrystalBombDetonatorRenderer>().Untrack(this);
44+
}
45+
46+
public override void Update() {
47+
bool flashing = Flashing;
48+
if (flashing) {
49+
Flash = Calc.Approach(Flash, 0f, Engine.DeltaTime * 4f);
50+
bool flag = Flash <= 0f;
51+
if (flag) {
52+
Flashing = false;
53+
}
54+
} else {
55+
bool flag2 = solidifyDelay > 0f;
56+
if (flag2) {
57+
solidifyDelay -= Engine.DeltaTime;
58+
} else {
59+
bool flag3 = Solidify > 0f;
60+
if (flag3) {
61+
Solidify = Calc.Approach(Solidify, 0f, Engine.DeltaTime);
62+
}
63+
}
64+
}
65+
int num = speeds.Length;
66+
float height = Height;
67+
int i = 0;
68+
int count = particles.Count;
69+
while (i < count) {
70+
Vector2 value = particles[i] + Vector2.UnitY * speeds[i % num] * Engine.DeltaTime;
71+
value.Y %= height - 1f;
72+
particles[i] = value;
73+
i++;
74+
}
75+
base.Update();
76+
77+
CheckForBombs();
78+
}
79+
80+
public void OnTriggerDetonation() {
81+
Flash = 1f;
82+
Solidify = 1f;
83+
solidifyDelay = 1f;
84+
Flashing = true;
85+
Scene.CollideInto<CrystalBombDetonator>(new Rectangle((int) X, (int) Y - 2, (int) Width, (int) Height + 4), adjacent);
86+
Scene.CollideInto<CrystalBombDetonator>(new Rectangle((int) X - 2, (int) Y, (int) Width + 4, (int) Height), adjacent);
87+
foreach (CrystalBombDetonator crystalBombDetonator in adjacent) {
88+
if(!crystalBombDetonator.Flashing)
89+
crystalBombDetonator.OnTriggerDetonation();
90+
}
91+
adjacent.Clear();
92+
}
93+
94+
public override void Render() {
95+
Color color = Color.Yellow * 0.6f;
96+
foreach (Vector2 value in particles) {
97+
Draw.Pixel.Draw(Position + value, Vector2.Zero, color);
98+
}
99+
if (Flashing)
100+
Draw.Rect(Collider, Color.Purple * Flash * 0.5f);
101+
}
102+
103+
private void CheckForBombs() {
104+
foreach (Entity bomb in CollideAll<Actor>()) {
105+
if (bomb.GetType().ToString().Contains("CrystalBomb")) {
106+
if (bombExplosionMethod == null)
107+
bombExplosionMethod = bomb.GetType().GetMethod("Explode", BindingFlags.Instance | BindingFlags.NonPublic);
108+
bombExplosionMethod.Invoke(bomb, null);
109+
if (!Flashing)
110+
OnTriggerDetonation();
111+
}
112+
}
113+
}
114+
115+
public float Flash;
116+
public float Solidify;
117+
public bool Flashing;
118+
private float solidifyDelay;
119+
private List<Vector2> particles;
120+
private List<CrystalBombDetonator> adjacent;
121+
private float[] speeds;
122+
123+
private static MethodInfo bombExplosionMethod;
124+
}
125+
}

0 commit comments

Comments
 (0)