Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/MSZ/EggLoco.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: EggLoco Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectEggLoco *EggLoco;
11
12
void EggLoco_Update(void)
13
{
14
RSDK_THIS(EggLoco);
15
16
RSDK.ProcessAnimation(&self->eggmanAnimator);
17
RSDK.ProcessAnimation(&self->lanternAnimator);
18
RSDK.ProcessAnimation(&self->smallWheelAnimator);
19
20
self->couplingAngle = (self->couplingAngle + 16) & 0x1FF;
21
22
StateMachine_Run(self->state);
23
24
if (!(Zone->timer & 0x3F)) {
25
RSDK.PlaySfx(EggLoco->sfxSmoke, false, 255);
26
CREATE_ENTITY(LocoSmoke, NULL, self->position.x + 0x450000, self->position.y - 0x480000);
27
}
28
}
29
30
void EggLoco_LateUpdate(void) {}
31
32
void EggLoco_StaticUpdate(void) {}
33
34
void EggLoco_Draw(void)
35
{
36
RSDK_THIS(EggLoco);
37
38
Vector2 drawPos;
39
drawPos.x = self->position.x;
40
drawPos.y = self->position.y - 2 * self->tootPullPos;
41
RSDK.DrawSprite(&self->eggmanTootAnimator, 0, false);
42
RSDK.DrawSprite(&self->whistleAnimator, &drawPos, false);
43
44
drawPos.x = self->position.x - 0x2D0000;
45
drawPos.y = self->position.y - 0x3F0000;
46
self->drawFX = FX_ROTATE;
47
self->rotation = -(self->tootPullPos >> 15);
48
self->whistleCableAnimator.frameID = 0;
49
RSDK.DrawSprite(&self->whistleCableAnimator, &drawPos, false);
50
51
drawPos.x = self->position.x - 0x5F0000;
52
drawPos.y = self->tootPullPos + self->position.y - 0x3F0000;
53
self->drawFX = FX_NONE;
54
self->whistleCableAnimator.frameID = 1;
55
RSDK.DrawSprite(&self->whistleCableAnimator, &drawPos, false);
56
57
self->whistleCableAnimator.frameID = 2;
58
RSDK.DrawSprite(&self->whistleCableAnimator, &drawPos, false);
59
RSDK.DrawSprite(&self->eggmanTootAnimator, NULL, false);
60
RSDK.DrawSprite(&self->eggmanAnimator, NULL, false);
61
RSDK.DrawSprite(&self->locomotiveAnimator, NULL, false);
62
63
drawPos.x = self->position.x - 0x680000;
64
drawPos.y = self->position.y + 0x380000;
65
self->rotation = self->couplingAngle;
66
self->drawFX = FX_ROTATE;
67
RSDK.DrawSprite(&self->bigWheelAnimator, &drawPos, false);
68
69
self->drawFX = FX_NONE;
70
RSDK.DrawSprite(&self->bigWheelEdgeAnimator, &drawPos, false);
71
72
drawPos.x += 0x4A0000;
73
self->drawFX = FX_ROTATE;
74
self->rotation = self->couplingAngle + 0x100;
75
RSDK.DrawSprite(&self->bigWheelAnimator, &drawPos, false);
76
77
self->drawFX = FX_NONE;
78
RSDK.DrawSprite(&self->bigWheelEdgeAnimator, &drawPos, false);
79
80
drawPos.x = self->position.x + 0x160000;
81
drawPos.y = self->position.y + 0x4B0000;
82
RSDK.DrawSprite(&self->smallWheelAnimator, &drawPos, false);
83
84
drawPos.x += 0x3E0000;
85
RSDK.DrawSprite(&self->smallWheelAnimator, &drawPos, false);
86
87
drawPos.x = (2304 * RSDK.Cos512(self->couplingAngle) + self->position.x - 0x680000) + 0x4C0000;
88
drawPos.y = ((9 * RSDK.Sin512(self->couplingAngle)) << 8) + self->position.y + 0x380000;
89
self->couplingAnimator.frameID = 1;
90
self->drawFX = FX_ROTATE;
91
self->rotation = RSDK.Sin512(-self->couplingAngle) / 18 - 4;
92
RSDK.DrawSprite(&self->couplingAnimator, &drawPos, false);
93
94
self->drawFX = FX_NONE;
95
drawPos.x -= 0x4C0000;
96
self->couplingAnimator.frameID = 0;
97
RSDK.DrawSprite(&self->couplingAnimator, &drawPos, false);
98
99
self->pistonRodAnimator.frameID = 0;
100
drawPos.x = self->position.x + ((RSDK.Cos512(self->couplingAngle) + 256) << 11);
101
drawPos.y = self->position.y;
102
RSDK.DrawSprite(&self->pistonRodAnimator, &drawPos, false);
103
104
self->pistonRodAnimator.frameID = 2;
105
RSDK.DrawSprite(&self->pistonRodAnimator, &drawPos, false);
106
107
self->pistonRodAnimator.frameID = 1;
108
RSDK.DrawSprite(&self->pistonRodAnimator, NULL, false);
109
RSDK.DrawSprite(&self->guardAnimator, NULL, false);
110
RSDK.DrawSprite(&self->lanternAnimator, NULL, false);
111
}
112
113
void EggLoco_Create(void *data)
114
{
115
RSDK_THIS(EggLoco);
116
117
if (!SceneInfo->inEditor) {
118
self->visible = true;
119
self->drawGroup = Zone->objectDrawGroup[0];
120
self->active = ACTIVE_BOUNDS;
121
self->updateRange.x = 0xA00000;
122
self->updateRange.y = 0x600000;
123
self->state = EggLoco_State_TootDelay;
124
self->timer = 60;
125
126
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 0, &self->locomotiveAnimator, true, 0);
127
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 6, &self->whistleAnimator, true, 0);
128
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 1, &self->bigWheelAnimator, true, 0);
129
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 1, &self->bigWheelEdgeAnimator, true, 1);
130
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 2, &self->smallWheelAnimator, true, 0);
131
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 3, &self->couplingAnimator, true, 0);
132
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 5, &self->guardAnimator, true, 0);
133
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 7, &self->lanternAnimator, true, 0);
134
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 4, &self->pistonRodAnimator, true, 0);
135
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 10, &self->eggmanAnimator, true, 0);
136
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 12, &self->eggmanTootAnimator, true, 0);
137
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 13, &self->whistleCableAnimator, true, 0);
138
}
139
}
140
141
void EggLoco_StageLoad(void)
142
{
143
EggLoco->aniFrames = RSDK.LoadSpriteAnimation("MSZ/Train.bin", SCOPE_STAGE);
144
145
EggLoco->sfxSmoke = RSDK.GetSfx("MSZ/LocoSmoke.wav");
146
EggLoco->sfxWhistle = RSDK.GetSfx("MSZ/LocoWhistle.wav");
147
Soundboard_LoadSfx("MSZ/LocoChugga.wav", true, EggLoco_SfxCheck_LocoChugga, EggLoco_SfxUpdate_LocoChugga);
148
}
149
150
bool32 EggLoco_SfxCheck_LocoChugga(void)
151
{
152
int32 count = 0;
153
int32 screenX = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
154
int32 screenY = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;
155
156
foreach_all(EggLoco, eggLoco)
157
{
158
if ((MathHelpers_Distance(eggLoco->position.x, eggLoco->position.y, screenX, screenY) >> 16) <= 840)
159
count++;
160
}
161
162
return count > 0;
163
}
164
165
void EggLoco_SfxUpdate_LocoChugga(int32 sfx)
166
{
167
int32 screenX = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;
168
int32 screenY = (ScreenInfo->position.y + ScreenInfo->center.y) << 16;
169
170
foreach_all(EggLoco, eggLoco)
171
{
172
int32 distX = abs(screenX - eggLoco->position.x) >> 16;
173
int32 distY = abs(screenY - eggLoco->position.y) >> 16;
174
int32 vol = MIN(MathHelpers_SquareRoot(distX * distX + distY * distY), 840);
175
176
RSDK.SetChannelAttributes(Soundboard->sfxChannel[sfx], 1.0 - (vol / 840.0), 0.0, 1.0);
177
foreach_break;
178
}
179
}
180
181
void EggLoco_State_TootDelay(void)
182
{
183
RSDK_THIS(EggLoco);
184
185
if (self->timer <= 0) {
186
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 11, &self->eggmanAnimator, true, 0);
187
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 12, &self->eggmanTootAnimator, true, 0);
188
self->state = EggLoco_State_Whistle;
189
}
190
else {
191
self->timer--;
192
}
193
}
194
195
void EggLoco_State_Whistle(void)
196
{
197
RSDK_THIS(EggLoco);
198
199
if (++self->timer == 4) {
200
RSDK.PlaySfx(EggLoco->sfxWhistle, false, 255);
201
self->timer = 0;
202
self->state = EggLoco_State_Tooting;
203
}
204
}
205
206
void EggLoco_State_Tooting(void)
207
{
208
RSDK_THIS(EggLoco);
209
210
RSDK.ProcessAnimation(&self->eggmanTootAnimator);
211
212
// How much eggman's pulled the "toot" down
213
self->tootPullPos = (RSDK.GetFrameID(&self->eggmanTootAnimator) - 'a') << 16;
214
215
if (self->tootPullPos >= 0x10000 && !(Zone->timer & 3)) {
216
EntityDust *dust = CREATE_ENTITY(Dust, NULL, self->position.x - 0x240000, self->position.y - 0x4E0000);
217
dust->state = Dust_State_DustPuff_Friction;
218
dust->velocity.x = 0x20000;
219
dust->velocity.y = -0x18000;
220
dust->drawGroup = Zone->objectDrawGroup[0];
221
}
222
223
if (self->eggmanAnimator.animationID == 11 && self->eggmanAnimator.frameID == self->eggmanAnimator.frameCount - 1)
224
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 10, &self->eggmanAnimator, true, 0);
225
226
if (self->eggmanTootAnimator.frameID == self->eggmanTootAnimator.frameCount - 1) {
227
self->timer = RSDK.Rand(60, 180);
228
self->state = EggLoco_State_TootDelay;
229
}
230
}
231
232
#if GAME_INCLUDE_EDITOR
233
void EggLoco_EditorDraw(void)
234
{
235
RSDK_THIS(EggLoco);
236
237
self->updateRange.x = 0xA00000;
238
self->updateRange.y = 0x600000;
239
240
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 0, &self->locomotiveAnimator, true, 0);
241
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 6, &self->whistleAnimator, true, 0);
242
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 1, &self->bigWheelAnimator, true, 0);
243
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 1, &self->bigWheelEdgeAnimator, true, 1);
244
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 2, &self->smallWheelAnimator, true, 0);
245
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 3, &self->couplingAnimator, true, 0);
246
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 5, &self->guardAnimator, true, 0);
247
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 7, &self->lanternAnimator, true, 0);
248
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 4, &self->pistonRodAnimator, true, 0);
249
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 10, &self->eggmanAnimator, true, 0);
250
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 12, &self->eggmanTootAnimator, true, 0);
251
RSDK.SetSpriteAnimation(EggLoco->aniFrames, 13, &self->whistleCableAnimator, true, 0);
252
253
EggLoco_Draw();
254
}
255
256
void EggLoco_EditorLoad(void) { EggLoco->aniFrames = RSDK.LoadSpriteAnimation("MSZ/Train.bin", SCOPE_STAGE); }
257
#endif
258
259
void EggLoco_Serialize(void) {}
260
261