Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Unused/Wisp.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Wisp Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectWisp *Wisp = NULL;
11
12
void Wisp_Update(void)
13
{
14
RSDK_THIS(Wisp);
15
StateMachine_Run(self->state);
16
}
17
18
void Wisp_LateUpdate(void) {}
19
20
void Wisp_StaticUpdate(void) {}
21
22
void Wisp_Draw(void)
23
{
24
RSDK_THIS(Wisp);
25
26
RSDK.DrawSprite(&self->bodyAnimator, NULL, false);
27
28
self->inkEffect = INK_ALPHA;
29
RSDK.DrawSprite(&self->wingAnimator, NULL, false);
30
31
self->inkEffect = INK_NONE;
32
}
33
34
void Wisp_Create(void *data)
35
{
36
RSDK_THIS(Wisp);
37
38
self->visible = true;
39
self->drawGroup = Zone->objectDrawGroup[0];
40
self->drawFX |= FX_FLIP;
41
self->startPos = self->position;
42
self->active = ACTIVE_BOUNDS;
43
self->updateRange.x = 0x800000;
44
self->updateRange.y = 0x800000;
45
self->direction = FLIP_NONE;
46
self->target = NULL;
47
self->alpha = 0xC0;
48
self->timer = 16;
49
self->buzzCount = 4;
50
RSDK.SetSpriteAnimation(Wisp->aniFrames, 0, &self->bodyAnimator, true, 0);
51
RSDK.SetSpriteAnimation(Wisp->aniFrames, 1, &self->wingAnimator, true, 0);
52
53
self->state = Wisp_State_Init;
54
}
55
56
void Wisp_StageLoad(void)
57
{
58
Wisp->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/Wisp.bin", SCOPE_STAGE);
59
60
Wisp->hitboxBadnik.left = -8;
61
Wisp->hitboxBadnik.top = -8;
62
Wisp->hitboxBadnik.right = 8;
63
Wisp->hitboxBadnik.bottom = 8;
64
65
DEBUGMODE_ADD_OBJ(Wisp);
66
}
67
68
void Wisp_DebugSpawn(void)
69
{
70
RSDK_THIS(DebugMode);
71
72
CREATE_ENTITY(Wisp, NULL, self->position.x, self->position.y);
73
}
74
75
void Wisp_DebugDraw(void)
76
{
77
RSDK.SetSpriteAnimation(Wisp->aniFrames, 0, &DebugMode->animator, true, 0);
78
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
79
}
80
81
void Wisp_HandlePlayerInteractions(void)
82
{
83
RSDK_THIS(Wisp);
84
85
foreach_active(Player, player)
86
{
87
EntityPlayer *target = self->target;
88
if (target) {
89
if (abs(player->position.x - self->position.x) < abs(target->position.x - self->position.x))
90
self->target = player;
91
}
92
else {
93
self->target = player;
94
}
95
96
if (Player_CheckBadnikTouch(player, self, &Wisp->hitboxBadnik))
97
Player_CheckBadnikBreak(player, self, true);
98
}
99
}
100
101
void Wisp_CheckOffScreen(void)
102
{
103
RSDK_THIS(Wisp);
104
105
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
106
self->position.x = self->startPos.x;
107
self->position.y = self->startPos.y;
108
Wisp_Create(NULL);
109
}
110
}
111
112
void Wisp_State_Init(void)
113
{
114
RSDK_THIS(Wisp);
115
116
self->active = ACTIVE_NORMAL;
117
self->velocity.x = 0;
118
self->velocity.y = 0;
119
120
self->state = Wisp_State_Idle;
121
Wisp_State_Idle();
122
}
123
124
void Wisp_State_Idle(void)
125
{
126
RSDK_THIS(Wisp);
127
128
if (!--self->timer) {
129
if (--self->buzzCount) {
130
self->velocity.y = -0x10000;
131
self->timer = 96;
132
self->state = Wisp_State_FlyTowardTarget;
133
}
134
else {
135
self->velocity.x = -0x20000;
136
self->velocity.y = -0x20000;
137
self->state = Wisp_State_FlyAway;
138
}
139
}
140
141
RSDK.ProcessAnimation(&self->wingAnimator);
142
143
Wisp_HandlePlayerInteractions();
144
Wisp_CheckOffScreen();
145
}
146
147
void Wisp_State_FlyTowardTarget(void)
148
{
149
RSDK_THIS(Wisp);
150
151
self->position.x += self->velocity.x;
152
self->position.y += self->velocity.y;
153
154
EntityPlayer *target = self->target;
155
if (target) {
156
if (target->position.x >= self->position.x) {
157
self->velocity.x += 0x1000;
158
self->direction = FLIP_X;
159
if (self->velocity.x > 0x20000)
160
self->velocity.x = 0x20000;
161
}
162
else {
163
self->velocity.x -= 0x1000;
164
self->direction = FLIP_NONE;
165
if (self->velocity.x < -0x20000)
166
self->velocity.x = -0x20000;
167
}
168
169
if (target->position.y >= self->position.y) {
170
self->velocity.y += 0x1000;
171
if (self->velocity.y > 0x20000)
172
self->velocity.y = 0x20000;
173
}
174
else {
175
self->velocity.y -= 0x1000;
176
if (self->velocity.y < -0x20000)
177
self->velocity.y = -0x20000;
178
}
179
}
180
181
if (!--self->timer) {
182
self->timer = RSDK.Rand(0, 32);
183
self->state = Wisp_State_Idle;
184
self->velocity.x = 0;
185
self->velocity.y = 0;
186
self->direction = FLIP_NONE;
187
}
188
RSDK.ProcessAnimation(&self->wingAnimator);
189
190
Wisp_HandlePlayerInteractions();
191
Wisp_CheckOffScreen();
192
}
193
194
void Wisp_State_FlyAway(void)
195
{
196
RSDK_THIS(Wisp);
197
198
self->position.x += self->velocity.x;
199
self->position.y += self->velocity.y;
200
RSDK.ProcessAnimation(&self->wingAnimator);
201
202
Wisp_HandlePlayerInteractions();
203
Wisp_CheckOffScreen();
204
}
205
206
#if GAME_INCLUDE_EDITOR
207
void Wisp_EditorDraw(void) { Wisp_Draw(); }
208
209
void Wisp_EditorLoad(void)
210
{
211
Wisp->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/Wisp.bin", SCOPE_STAGE);
212
213
// despite being editable, this variable is set to FLIP_NONE on create, thereby making the editable var's value unused
214
RSDK_ACTIVE_VAR(Wisp, direction);
215
RSDK_ENUM_VAR("(Unused)", FLIP_NONE);
216
// RSDK_ENUM_VAR("No Flip", FLIP_NONE);
217
// RSDK_ENUM_VAR("Flip X", FLIP_X);
218
}
219
#endif
220
221
void Wisp_Serialize(void) { RSDK_EDITABLE_VAR(Wisp, VAR_UINT8, direction); }
222
223