Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/GHZ/Batbrain.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Batbrain Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectBatbrain *Batbrain;
11
12
void Batbrain_Update(void)
13
{
14
RSDK_THIS(Batbrain);
15
StateMachine_Run(self->state);
16
}
17
18
void Batbrain_LateUpdate(void) {}
19
20
void Batbrain_StaticUpdate(void) {}
21
22
void Batbrain_Draw(void)
23
{
24
RSDK_THIS(Batbrain);
25
RSDK.DrawSprite(&self->animator, NULL, false);
26
}
27
28
void Batbrain_Create(void *data)
29
{
30
RSDK_THIS(Batbrain);
31
self->visible = true;
32
self->drawFX |= FX_FLIP;
33
self->drawGroup = Zone->objectDrawGroup[0];
34
self->startPos.x = self->position.x;
35
self->startPos.y = self->position.y;
36
self->active = ACTIVE_BOUNDS;
37
self->updateRange.x = 0x800000;
38
self->updateRange.y = 0x800000;
39
RSDK.SetSpriteAnimation(Batbrain->aniFrames, 0, &self->animator, true, 0);
40
self->state = Batbrain_State_Init;
41
}
42
43
void Batbrain_StageLoad(void)
44
{
45
if (RSDK.CheckSceneFolder("GHZ"))
46
Batbrain->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Batbrain.bin", SCOPE_STAGE);
47
48
Batbrain->hitboxBadnik.left = -12;
49
Batbrain->hitboxBadnik.top = -18;
50
Batbrain->hitboxBadnik.right = 12;
51
Batbrain->hitboxBadnik.bottom = 18;
52
53
Batbrain->sfxFlap = RSDK.GetSfx("Stage/Flap.wav");
54
55
DEBUGMODE_ADD_OBJ(Batbrain);
56
}
57
58
void Batbrain_DebugDraw(void)
59
{
60
RSDK.SetSpriteAnimation(Batbrain->aniFrames, 0, &DebugMode->animator, true, 0);
61
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
62
}
63
64
void Batbrain_DebugSpawn(void)
65
{
66
RSDK_THIS(DebugMode);
67
68
CREATE_ENTITY(Batbrain, NULL, self->position.x, self->position.y);
69
}
70
71
void Batbrain_CheckPlayerCollisions(void)
72
{
73
RSDK_THIS(Batbrain);
74
75
foreach_active(Player, player)
76
{
77
if (Player_CheckBadnikTouch(player, self, &Batbrain->hitboxBadnik))
78
Player_CheckBadnikBreak(player, self, true);
79
}
80
}
81
82
void Batbrain_CheckOffScreen(void)
83
{
84
RSDK_THIS(Batbrain);
85
86
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
87
self->position.x = self->startPos.x;
88
self->position.y = self->startPos.y;
89
Batbrain_Create(NULL);
90
}
91
}
92
93
void Batbrain_State_Init(void)
94
{
95
RSDK_THIS(Batbrain);
96
97
self->active = ACTIVE_NORMAL;
98
self->velocity.x = 0;
99
self->velocity.y = 0;
100
self->state = Batbrain_State_CheckPlayerInRange;
101
Batbrain_State_CheckPlayerInRange();
102
}
103
104
void Batbrain_State_CheckPlayerInRange(void)
105
{
106
RSDK_THIS(Batbrain);
107
108
int32 targetDistance = 0x7FFFFFFF;
109
EntityPlayer *backupPlayer = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
110
EntityPlayer *targetPlayer = NULL;
111
112
foreach_active(Player, player)
113
{
114
int32 distance = abs(player->position.x - self->position.x);
115
if (distance >= targetDistance) {
116
backupPlayer = player;
117
}
118
else {
119
backupPlayer = player;
120
targetDistance = distance;
121
}
122
123
if (distance < 0x800000) {
124
if (player->position.y >= self->position.y && (!targetPlayer || player->position.y < targetPlayer->position.y))
125
targetPlayer = player;
126
}
127
}
128
129
EntityPlayer *playerPtr = backupPlayer;
130
if (targetPlayer) {
131
playerPtr = targetPlayer;
132
int32 distance = targetPlayer->position.y - self->position.y;
133
if (distance >= 0 && distance <= 0x800000 && !RSDK.Rand(0, 8)) {
134
self->state = Batbrain_State_DropToPlayer;
135
self->targetY = playerPtr->position.y;
136
self->target = playerPtr;
137
RSDK.SetSpriteAnimation(Batbrain->aniFrames, 1, &self->animator, true, 0);
138
}
139
}
140
141
self->direction = playerPtr->position.x >= self->position.x;
142
143
Batbrain_CheckPlayerCollisions();
144
Batbrain_CheckOffScreen();
145
}
146
147
void Batbrain_State_DropToPlayer(void)
148
{
149
RSDK_THIS(Batbrain);
150
151
self->position.y += self->velocity.y;
152
self->velocity.y += 0x1800;
153
self->direction = self->target->position.x >= self->position.x;
154
155
if (self->targetY - self->position.y < 0x100000) {
156
self->velocity.y = 0;
157
if (self->direction == FLIP_NONE)
158
self->velocity.x = -0x10000;
159
else
160
self->velocity.x = 0x10000;
161
RSDK.SetSpriteAnimation(Batbrain->aniFrames, 2, &self->animator, true, 0);
162
self->state = Batbrain_State_Fly;
163
}
164
165
RSDK.ProcessAnimation(&self->animator);
166
167
Batbrain_CheckPlayerCollisions();
168
Batbrain_CheckOffScreen();
169
}
170
171
void Batbrain_State_Fly(void)
172
{
173
RSDK_THIS(Batbrain);
174
175
EntityPlayer *target = self->target;
176
self->position.x += self->velocity.x;
177
178
if (abs(target->position.x - self->position.x) >= 0x800000 && !RSDK.Rand(0, 8))
179
self->state = Batbrain_State_FlyToCeiling;
180
181
if (!(Zone->timer & 0xF))
182
RSDK.PlaySfx(Batbrain->sfxFlap, false, 255);
183
184
RSDK.ProcessAnimation(&self->animator);
185
186
Batbrain_CheckPlayerCollisions();
187
Batbrain_CheckOffScreen();
188
}
189
190
void Batbrain_State_FlyToCeiling(void)
191
{
192
RSDK_THIS(Batbrain);
193
194
self->position.x += self->velocity.x;
195
self->position.y += self->velocity.y;
196
self->velocity.y -= 0x1800;
197
198
// RWALL? shouldn't this be ROOF? is this a holdover from v4's weird id system?
199
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, 0, -0xC0000, true)) {
200
self->velocity.x = 0;
201
self->velocity.y = 0;
202
self->state = Batbrain_State_CheckPlayerInRange;
203
RSDK.SetSpriteAnimation(Batbrain->aniFrames, 0, &self->animator, true, 0);
204
}
205
206
if (!(Zone->timer & 0xF))
207
RSDK.PlaySfx(Batbrain->sfxFlap, false, 255);
208
209
RSDK.ProcessAnimation(&self->animator);
210
211
Batbrain_CheckPlayerCollisions();
212
Batbrain_CheckOffScreen();
213
}
214
215
#if GAME_INCLUDE_EDITOR
216
void Batbrain_EditorDraw(void) { Batbrain_Draw(); }
217
218
void Batbrain_EditorLoad(void) { Batbrain->aniFrames = RSDK.LoadSpriteAnimation("GHZ/Batbrain.bin", SCOPE_STAGE); }
219
#endif
220
221
void Batbrain_Serialize(void) {}
222
223