Skip to content

Commit 488fdd7

Browse files
committed
Make non-return sokobans reskinnable
Also fix hurt animation
1 parent 929886d commit 488fdd7

4 files changed

Lines changed: 146 additions & 96 deletions

File tree

Code/Entities/NonReturnSokoban.cs

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,48 @@ namespace Celeste.Mod.CherryHelper
1111
public class NonReturnSokoban : Solid
1212
{
1313

14-
public NonReturnSokoban(Vector2 position, float width, float height, Axes axes, bool chillOut = false, bool altTexture = false) : base(position, width, height, false)
15-
{
16-
this.altTexture = altTexture;
17-
this.fill = altTexture ? Calc.HexToColor("C38A06"): Calc.HexToColor("242262");
18-
altTextureString = (altTexture ? "objects/noReturnSokoban/" : "objects/noReturnSokobanAlt/");
14+
private string spriteDirectory;
15+
public NonReturnSokoban(EntityData data, Vector2 offset) : base(data.Position + offset, data.Width, data.Height, false) {
16+
axes = data.Enum("axes", Axes.Both);
17+
chillOut = data.Bool("chillOut", false);
18+
19+
if (data.Bool("reskinnable")) {
20+
P_Crushing = new ParticleType(P_Crushing) {
21+
Color = Calc.HexToColor(data.Attr("crushParticleColor1", "ff66e2")),
22+
Color2 = Calc.HexToColor(data.Attr("crushParticleColor2", "68fcff")),
23+
};
24+
25+
P_Activate = new ParticleType(P_Activate) {
26+
Color = Calc.HexToColor(data.Attr("activateParticleColor1", "5fcde4")),
27+
Color2 = Calc.HexToColor(data.Attr("activateParticleColor2", "ffffff")),
28+
};
29+
30+
spriteDirectory = data.Attr("spriteDirectory", "objects/noReturnSokobanAlt");
31+
fill = Calc.HexToColor(data.Attr("fillColor", "242262"));
32+
} else if (data.Bool("altTexture", true)) {
33+
spriteDirectory = data.Attr("spriteDirectory", "objects/noReturnSokobanAlt");
34+
fill = Calc.HexToColor(data.Attr("fillColor", "242262"));
35+
} else {
36+
spriteDirectory = "objects/noReturnSokoban";
37+
fill = Calc.HexToColor("c38a06");
38+
}
39+
40+
1941
this.idleImages = new List<Image>();
2042
this.activeTopImages = new List<Image>();
2143
this.activeRightImages = new List<Image>();
2244
this.activeLeftImages = new List<Image>();
2345
this.activeBottomImages = new List<Image>();
2446
this.OnDashCollide = new DashCollision(this.OnDashed);
2547
this.returnStack = new List<NonReturnSokoban.MoveState>();
26-
this.chillOut = chillOut;
2748
this.giant = (Width >= 48f && Height >= 48f && chillOut);
2849
this.canActivate = true;
2950
this.attackCoroutine = new Coroutine(true);
3051
this.attackCoroutine.RemoveOnComplete = false;
3152
Add(this.attackCoroutine);
32-
List<MTexture> atlasSubtextures = GFX.Game.GetAtlasSubtextures(altTextureString + "block");
53+
List<MTexture> atlasSubtextures = GFX.Game.GetAtlasSubtextures(spriteDirectory + "/block");
3354
MTexture idle;
34-
switch (axes)
35-
{
55+
switch (axes) {
3656
default:
3757
idle = atlasSubtextures[3];
3858
this.canMoveHorizontally = (this.canMoveVertically = true);
@@ -48,21 +68,43 @@ public NonReturnSokoban(Vector2 position, float width, float height, Axes axes,
4868
this.canMoveVertically = true;
4969
break;
5070
}
51-
if (!altTexture)
52-
{
53-
Add(this.face = GFX.SpriteBank.Create("NoReturnSokobanAlt_face"));
54-
}
55-
else
56-
{
57-
Add(this.face = GFX.SpriteBank.Create("NoReturnSokoban_face"));
58-
}
59-
this.face.Position = new Vector2(Width, Height) / 2f;
60-
this.face.Play("idle", false, false);
61-
this.face.OnLastFrame = delegate (string f)
62-
{
71+
Add(face = new Sprite(GFX.Game, spriteDirectory + "/"));
72+
face.Position = new Vector2(Width, Height) / 2f;
73+
if (giant) {
74+
/*
75+
<Loop id="idle" path="giant_block" frames="0" delay="0.08"/>
76+
<Anim id="hurt" path="giant_block" frames="8-12" delay="0.08" goto="idle"/>
77+
<Anim id="hit" path="giant_block" frames="0-5" delay="0.08"/>
78+
<Loop id="right" path="giant_block" frames="6,7" delay="0.08"/>
79+
*/
80+
face.AddLoop("idle", "giant_block", 0.08f, 0);
81+
face.Add("hurt", "giant_block", 0.08f, "idle", 8, 9, 10, 11, 12);
82+
face.Add("hit", "giant_block", 0.08f, 0, 1, 2, 3, 4, 5);
83+
face.AddLoop("right", "giant_block", 0.08f, 6, 7);
84+
} else {
85+
/*
86+
<Loop id="idle" path="idle_face" delay="0.08"/>
87+
<Anim id="hurt" path="hurt" frames="3-12" delay="0.08" goto="idle"/>
88+
<Anim id="hit" path="hit" delay="0.08"/>
89+
<Loop id="left" path="hit_left" delay="0.08"/>
90+
<Loop id="right" path="hit_right" delay="0.08"/>
91+
<Loop id="up" path="hit_up" delay="0.08"/>
92+
<Loop id="down" path="hit_down" delay="0.08"/>
93+
*/
94+
95+
face.AddLoop("idle", "idle_face", 0.08f);
96+
face.Add("hurt", "hurt", 0.08f, "idle", 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
97+
face.Add("hit", "hit", 0.08f);
98+
face.AddLoop("left", "hit_left", 0.08f);
99+
face.AddLoop("right", "hit_right", 0.08f);
100+
face.AddLoop("up", "hit_up", 0.08f);
101+
face.AddLoop("down", "hit_down", 0.08f);
102+
}
103+
face.CenterOrigin();
104+
face.Play("idle");
105+
this.face.OnLastFrame = delegate (string f) {
63106
bool flag = f == "hit";
64-
if (flag)
65-
{
107+
if (flag) {
66108
this.face.Play(this.nextFaceDirection, false, false);
67109
}
68110
};
@@ -72,13 +114,11 @@ public NonReturnSokoban(Vector2 position, float width, float height, Axes axes,
72114
this.AddImage(idle, num, 0, 3, 0, 1, -1);
73115
this.AddImage(idle, 0, num2, 0, 3, -1, 1);
74116
this.AddImage(idle, num, num2, 3, 3, 1, 1);
75-
for (int i = 1; i < num; i++)
76-
{
117+
for (int i = 1; i < num; i++) {
77118
this.AddImage(idle, i, 0, Calc.Random.Choose(1, 2), 0, 0, -1);
78119
this.AddImage(idle, i, num2, Calc.Random.Choose(1, 2), 3, 0, 1);
79120
}
80-
for (int j = 1; j < num2; j++)
81-
{
121+
for (int j = 1; j < num2; j++) {
82122
this.AddImage(idle, 0, j, 0, Calc.Random.Choose(1, 2), -1, 0);
83123
this.AddImage(idle, num, j, 3, Calc.Random.Choose(1, 2), 1, 0);
84124
}
@@ -87,10 +127,6 @@ public NonReturnSokoban(Vector2 position, float width, float height, Axes axes,
87127
Add(new WaterInteraction(() => this.crushDir != Vector2.Zero));
88128
}
89129

90-
public NonReturnSokoban(EntityData data, Vector2 offset) : this(data.Position + offset, (float)data.Width, (float)data.Height, data.Enum<NonReturnSokoban.Axes>("axes", Axes.Both), data.Bool("chillout", false), data.Bool("altTexture", false))
91-
{
92-
}
93-
94130
public override void Added(Scene scene)
95131
{
96132
base.Added(scene);
@@ -191,7 +227,7 @@ public void AddImage(MTexture idle, int x, int y, int tx, int ty, int borderX =
191227
bool flag4 = borderX < 0;
192228
if (flag4)
193229
{
194-
Image image2 = new Image(GFX.Game[altTextureString + "lit_left"].GetSubtexture(0, ty * 8, 8, 8, null));
230+
Image image2 = new Image(GFX.Game[spriteDirectory + "/lit_left"].GetSubtexture(0, ty * 8, 8, 8, null));
195231
this.activeLeftImages.Add(image2);
196232
image2.Position = vector;
197233
image2.Visible = false;
@@ -202,7 +238,7 @@ public void AddImage(MTexture idle, int x, int y, int tx, int ty, int borderX =
202238
bool flag5 = borderX > 0;
203239
if (flag5)
204240
{
205-
Image image3 = new Image(GFX.Game[altTextureString + "lit_right"].GetSubtexture(0, ty * 8, 8, 8, null));
241+
Image image3 = new Image(GFX.Game[spriteDirectory + "/lit_right"].GetSubtexture(0, ty * 8, 8, 8, null));
206242
this.activeRightImages.Add(image3);
207243
image3.Position = vector;
208244
image3.Visible = false;
@@ -212,7 +248,7 @@ public void AddImage(MTexture idle, int x, int y, int tx, int ty, int borderX =
212248
bool flag6 = borderY < 0;
213249
if (flag6)
214250
{
215-
Image image4 = new Image(GFX.Game[altTextureString + "lit_top"].GetSubtexture(tx * 8, 0, 8, 8, null));
251+
Image image4 = new Image(GFX.Game[spriteDirectory + "/lit_top"].GetSubtexture(tx * 8, 0, 8, 8, null));
216252
this.activeTopImages.Add(image4);
217253
image4.Position = vector;
218254
image4.Visible = false;
@@ -223,7 +259,7 @@ public void AddImage(MTexture idle, int x, int y, int tx, int ty, int borderX =
223259
bool flag7 = borderY > 0;
224260
if (flag7)
225261
{
226-
Image image5 = new Image(GFX.Game[altTextureString + "lit_bottom"].GetSubtexture(tx * 8, 0, 8, 8, null));
262+
Image image5 = new Image(GFX.Game[spriteDirectory + "/lit_bottom"].GetSubtexture(tx * 8, 0, 8, 8, null));
227263
this.activeBottomImages.Add(image5);
228264
image5.Position = vector;
229265
image5.Visible = false;
@@ -647,7 +683,7 @@ private IEnumerator AttackSequence()
647683
}, Alarm.AlarmMode.Oneshot);
648684
this.crushDir = Vector2.Zero;
649685
this.TurnOffImages();
650-
this.face.Play("hurt", false, false);
686+
yield return this.face.PlayRoutine("hurt", false);
651687
this.face.Play("idle", false, false);
652688
yield break;
653689
}
@@ -767,8 +803,8 @@ private bool MoveVCheck(float amount)
767803

768804
// Token: 0x040007F0 RID: 2032
769805
public Color fill;
806+
public Axes axes;
770807
private bool altTexture;
771-
public string altTextureString;
772808

773809
// Token: 0x040007F1 RID: 2033
774810
private Level level;

Graphics/Sprites.xml

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<Sprites>
3-
<NoReturnSokoban_face path="objects/noReturnSokoban/" start="idle">
4-
<Center/>
5-
<Loop id="idle" path="idle_face" delay="0.08"/>
6-
<Anim id="hurt" path="hurt" frames="3-12" delay="0.08" goto="idle"/>
7-
<Anim id="hit" path="hit" delay="0.08"/>
8-
<Loop id="left" path="hit_left" delay="0.08"/>
9-
<Loop id="right" path="hit_right" delay="0.08"/>
10-
<Loop id="up" path="hit_up" delay="0.08"/>
11-
<Loop id="down" path="hit_down" delay="0.08"/>
12-
</NoReturnSokoban_face>
13-
<NoReturnSokobanAlt_face path="objects/noReturnSokobanAlt/" start="idle">
14-
<Center/>
15-
<Loop id="idle" path="idle_face" delay="0.08"/>
16-
<Anim id="hurt" path="hurt" frames="3-12" delay="0.08" goto="idle"/>
17-
<Anim id="hit" path="hit" delay="0.08"/>
18-
<Loop id="left" path="hit_left" delay="0.08"/>
19-
<Loop id="right" path="hit_right" delay="0.08"/>
20-
<Loop id="up" path="hit_up" delay="0.08"/>
21-
<Loop id="down" path="hit_down" delay="0.08"/>
22-
</NoReturnSokobanAlt_face>
233
<hat path="kidshat/" start="hat">
244
<Justify x=".5" y="1" />
255
<Loop id="hat" path="hat" delay="0.8"/>
Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local drawableNPatch = require("structs.drawable_nine_patch")
22
local drawableRectangle = require("structs.drawable_rectangle")
33
local drawableSprite = require("structs.drawable_sprite")
4+
local utils = require("utils")
45

56
local axisOptions = {
67
Both = "both",
@@ -12,14 +13,32 @@ local nonReturnSokoban = {}
1213

1314
nonReturnSokoban.name = "CherryHelper/NonReturnSokoban"
1415
nonReturnSokoban.depth = 0
15-
nonReturnSokoban.minimumSize = {24, 24}
16+
nonReturnSokoban.minimumSize = { 24, 24 }
1617
nonReturnSokoban.fieldInformation = {
1718
axes = {
1819
options = axisOptions,
1920
editable = false
21+
},
22+
crushParticleColor1 = {
23+
fieldType = "color"
24+
},
25+
crushParticleColor2 = {
26+
fieldType = "color"
27+
},
28+
activateParticleColor1 = {
29+
fieldType = "color"
30+
},
31+
activateParticleColor2 = {
32+
fieldType = "color"
33+
},
34+
fillColor = {
35+
fieldType = "color"
2036
}
2137
}
22-
nonReturnSokoban.placements = {}
38+
39+
nonReturnSokoban.ignoredFields = { "_name", "_id", "originX", "originY", "reskinnable" }
40+
41+
nonReturnSokoban.placements = { }
2342

2443
for _, axis in pairs(axisOptions) do
2544
table.insert(nonReturnSokoban.placements, {
@@ -36,46 +55,57 @@ end
3655

3756
for _, axis in pairs(axisOptions) do
3857
table.insert(nonReturnSokoban.placements, {
39-
name = "alt" .. axis,
58+
name = "reskinnable" .. axis,
4059
data = {
60+
reskinnable = true,
4161
width = 24,
4262
height = 24,
4363
axes = axis,
44-
altTexture = true,
45-
chillout = false
64+
chillout = false,
65+
spriteDirectory = "objects/noReturnSokobanAlt",
66+
crushParticleColor1 = "ff66e2",
67+
crushParticleColor2 = "68fcff",
68+
activateParticleColor1 = "5fcde4",
69+
activateParticleColor2 = "ffffff",
70+
fillColor = "242262",
4671
}
4772
})
4873
end
4974

5075
local frameTextures = {
51-
none = "objects/noReturnSokoban/block00",
52-
horizontal = "objects/noReturnSokoban/block01",
53-
vertical = "objects/noReturnSokoban/block02",
54-
both = "objects/noReturnSokoban/block03"
55-
}
56-
57-
local altFrameTextures = {
58-
none = "objects/noReturnSokobanAlt/block00",
59-
horizontal = "objects/noReturnSokobanAlt/block01",
60-
vertical = "objects/noReturnSokobanAlt/block02",
61-
both = "objects/noReturnSokobanAlt/block03"
76+
none = "/block00",
77+
horizontal = "/block01",
78+
vertical = "/block02",
79+
both = "/block03"
6280
}
6381

6482
local nPatchOptions = {
6583
mode = "border",
6684
borderMode = "repeat"
6785
}
6886

69-
local sokobanColor = {195 / 255, 138 / 255, 6 / 255}
70-
local smallFaceTexture = "objects/noReturnSokoban/idle_face"
71-
local giantFaceTexture = "objects/noReturnSokoban/giant_block00"
72-
73-
local altSokobanColor = {36 / 255, 34 / 255, 98 / 255}
74-
local altSmallFaceTexture = "objects/noReturnSokobanAlt/idle_face"
75-
local altGiantFaceTexture = "objects/noReturnSokobanAlt/giant_block00"
87+
local smallFaceTexture = "/idle_face"
88+
local giantFaceTexture = "/giant_block00"
7689

7790
function nonReturnSokoban.sprite(room, entity)
91+
local spriteDirectory = entity.spriteDirectory
7892
local altTexture = entity.altTexture or false
93+
if spriteDirectory == nil then
94+
if altTexture then
95+
spriteDirectory = "objects/noReturnSokobanAlt"
96+
else
97+
spriteDirectory = "objects/noReturnSokoban"
98+
end
99+
end
100+
101+
local fillColor = { 195 / 255, 138 / 255, 6 / 255 }
102+
103+
if entity.fillColor ~= nil then
104+
local success, r, g, b = utils.parseHexColor(entity.fillColor)
105+
fillColor = { r, g, b }
106+
elseif altTexture then
107+
fillColor = { 36 / 255, 34 / 255, 98 / 255 }
108+
end
79109

80110
local x, y = entity.x or 0, entity.y or 0
81111
local width, height = entity.width or 24, entity.height or 24
@@ -85,22 +115,13 @@ function nonReturnSokoban.sprite(room, entity)
85115

86116
local giant = height >= 48 and width >= 48 and chillout
87117

88-
local faceTexture = giant and giantFaceTexture or smallFaceTexture
89-
if altTexture then
90-
faceTexture = giant and altGiantFaceTexture or altSmallFaceTexture
91-
end
118+
local faceTexture = spriteDirectory .. (giant and giantFaceTexture or smallFaceTexture)
92119

93-
local frameTexture = frameTextures[axes] or frameTextures["both"]
94-
if altTexture then
95-
frameTexture = altFrameTextures[axes] or altFrameTextures["both"]
96-
end
120+
local frameTexture = spriteDirectory .. frameTextures[axes]
97121

98122
local ninePatch = drawableNPatch.fromTexture(frameTexture, nPatchOptions, x, y, width, height)
99123

100-
local rectangle = drawableRectangle.fromRectangle("fill", x + 2, y + 2, width - 4, height - 4, sokobanColor)
101-
if altTexture then
102-
rectangle = drawableRectangle.fromRectangle("fill", x + 2, y + 2, width - 4, height - 4, altSokobanColor)
103-
end
124+
local rectangle = drawableRectangle.fromRectangle("fill", x + 2, y + 2, width - 4, height - 4, fillColor)
104125

105126
local faceSprite = drawableSprite.fromTexture(faceTexture, entity)
106127
faceSprite:addPosition(math.floor(width / 2), math.floor(height / 2))
@@ -113,4 +134,4 @@ function nonReturnSokoban.sprite(room, entity)
113134
return sprites
114135
end
115136

116-
return nonReturnSokoban
137+
return nonReturnSokoban

0 commit comments

Comments
 (0)