Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/ERZ/ERZShinobi.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: ERZShinobi Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectERZShinobi *ERZShinobi;
11
12
void ERZShinobi_Update(void)
13
{
14
RSDK_THIS(ERZShinobi);
15
16
if (self->invincibilityTimer > 0)
17
self->invincibilityTimer--;
18
19
StateMachine_Run(self->state);
20
21
self->rotStore = (self->rotStore + 8) & 0x1FF;
22
}
23
24
void ERZShinobi_LateUpdate(void) {}
25
26
void ERZShinobi_StaticUpdate(void) {}
27
28
void ERZShinobi_Draw(void)
29
{
30
RSDK_THIS(ERZShinobi);
31
32
if ((self->invincibilityTimer & 1))
33
RSDK.CopyPalette(2, 128, 0, 128, 128);
34
35
self->rotation = self->rotStore;
36
37
for (int32 i = 0; i < 8; ++i) {
38
Vector2 drawPos;
39
40
drawPos.x = self->finRadius * RSDK.Sin512(self->rotation) + self->position.x;
41
drawPos.y = self->position.y - self->finRadius * RSDK.Cos512(self->rotation);
42
self->finAnimator.frameID = ((self->rotation + 16) >> 5) & 0xF;
43
RSDK.DrawSprite(&self->finAnimator, &drawPos, false);
44
45
drawPos.x = ((5 * self->finRadius * RSDK.Sin512(self->rotation)) >> 3) + self->position.x;
46
drawPos.y = self->position.y - ((5 * self->finRadius * RSDK.Cos512(self->rotation)) >> 3);
47
RSDK.DrawSprite(&self->armAnimator, &drawPos, false);
48
49
self->rotation += 64;
50
}
51
52
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
53
54
if ((self->invincibilityTimer & 1))
55
RSDK.CopyPalette(1, 128, 0, 128, 128);
56
}
57
58
void ERZShinobi_Create(void *data)
59
{
60
RSDK_THIS(ERZShinobi);
61
62
if (!SceneInfo->inEditor) {
63
self->visible = true;
64
self->drawFX = FX_ROTATE | FX_FLIP;
65
self->drawGroup = Zone->objectDrawGroup[0];
66
self->active = ACTIVE_NORMAL;
67
self->updateRange.x = 0x800000;
68
self->updateRange.y = 0x800000;
69
self->collisionLayers = Zone->collisionLayers;
70
self->tileCollisions = TILECOLLISION_DOWN;
71
self->finRadius = 0x1600;
72
self->state = ERZShinobi_State_Moving;
73
74
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 0, &self->bodyAnimator, true, 0);
75
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 0, &self->armAnimator, true, 1);
76
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 1, &self->finAnimator, true, 0);
77
}
78
}
79
80
void ERZShinobi_StageLoad(void)
81
{
82
ERZShinobi->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomShinobi.bin", SCOPE_STAGE);
83
84
ERZShinobi->hitbox.left = -24;
85
ERZShinobi->hitbox.top = -24;
86
ERZShinobi->hitbox.right = 24;
87
ERZShinobi->hitbox.bottom = 24;
88
}
89
90
void ERZShinobi_CheckPlayerCollisions(void)
91
{
92
RSDK_THIS(ERZShinobi);
93
94
foreach_active(Player, playerLoop)
95
{
96
if (!self->invincibilityTimer && Player_CheckBadnikTouch(playerLoop, self, &ERZShinobi->hitbox) && Player_CheckBossHit(playerLoop, self)) {
97
ERZShinobi_Hit();
98
foreach_return;
99
}
100
}
101
102
int32 storeX = self->position.x;
103
int32 storeY = self->position.y;
104
int32 angle = self->rotStore;
105
foreach_active(Player, player)
106
{
107
for (int32 f = 0; f < 8; ++f) {
108
self->position.x = storeX + self->finRadius * RSDK.Sin512(angle);
109
self->position.y = storeY - self->finRadius * RSDK.Cos512(angle);
110
if (RSDK.CheckObjectCollisionTouchCircle(player, 0xC0000, self, 0x80000)) {
111
Player_Hurt(player, self);
112
}
113
angle += 0x40;
114
}
115
}
116
117
self->position.x = storeX;
118
self->position.y = storeY;
119
}
120
121
void ERZShinobi_Hit(void)
122
{
123
RSDK_THIS(ERZShinobi);
124
125
self->invincibilityTimer = 48;
126
RSDK.PlaySfx(ERZKing->sfxHit, false, 255);
127
}
128
129
void ERZShinobi_HandleTileCollisions(void)
130
{
131
RSDK_THIS(ERZShinobi);
132
133
if (self->onGround) {
134
self->finRadius += (0x1000 - self->finRadius) >> 3;
135
136
if (!self->prevOnGround) {
137
if (self->numBounces > 0) {
138
self->velocity.y = -0x30000;
139
self->numBounces--;
140
self->onGround = false;
141
}
142
}
143
}
144
else {
145
self->velocity.y += 0x3800;
146
if (self->velocity.y > 0xC0000)
147
self->velocity.y = 0xC0000;
148
149
self->finRadius += (0x1600 - self->finRadius) >> 3;
150
}
151
152
int32 size = self->finRadius / 88;
153
154
self->outerBox.left = -size;
155
self->outerBox.top = -size;
156
self->outerBox.right = size;
157
self->outerBox.bottom = size;
158
159
self->innerBox.left = 2 - size;
160
self->innerBox.top = -size;
161
self->innerBox.right = size - 2;
162
self->innerBox.bottom = size;
163
164
self->prevOnGround = self->onGround;
165
166
RSDK.ProcessObjectMovement(self, &self->outerBox, &self->innerBox);
167
}
168
169
void ERZShinobi_State_Moving(void)
170
{
171
RSDK_THIS(ERZShinobi);
172
173
ERZShinobi_HandleTileCollisions();
174
175
if (++self->timer == 60) {
176
self->timer = 0;
177
if (self->onGround) {
178
self->numBounces = 2;
179
self->velocity.y = -0x80000;
180
self->onGround = false;
181
}
182
}
183
184
ERZShinobi_CheckPlayerCollisions();
185
}
186
187
#if GAME_INCLUDE_EDITOR
188
void ERZShinobi_EditorDraw(void)
189
{
190
RSDK_THIS(ERZShinobi);
191
192
self->finRadius = 0x1600;
193
194
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 0, &self->bodyAnimator, false, 0);
195
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 0, &self->armAnimator, false, 1);
196
RSDK.SetSpriteAnimation(ERZShinobi->aniFrames, 1, &self->finAnimator, false, 0);
197
198
ERZShinobi_Draw();
199
}
200
201
void ERZShinobi_EditorLoad(void) { ERZShinobi->aniFrames = RSDK.LoadSpriteAnimation("Phantom/PhantomShinobi.bin", SCOPE_STAGE); }
202
#endif
203
204
void ERZShinobi_Serialize(void) {}
205
206