Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/LRZ/LRZConvDropper.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: LRZConvDropper Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLRZConvDropper *LRZConvDropper;
11
12
void LRZConvDropper_Update(void)
13
{
14
RSDK_THIS(LRZConvDropper);
15
16
self->visible = DebugMode->debugActive;
17
18
switch (self->triggerMode) {
19
case LRZCONVDROP_TRIGGER_BUTTON:
20
if (!((Zone->timer + self->intervalOffset) % self->interval))
21
LRZConvDropper_HandleButtonDrop(self);
22
break;
23
24
case LRZCONVDROP_TRIGGER_PLAYER: {
25
bool32 shouldDrop = false;
26
bool32 playerEntered = false;
27
28
self->position.x += self->detectOffset.x;
29
self->position.y += self->detectOffset.y;
30
foreach_active(Player, player)
31
{
32
int32 playerID = RSDK.GetEntitySlot(player);
33
34
bool32 triggered = false;
35
if (Player_CheckCollisionTouch(player, self, &self->hitbox)) {
36
triggered = true;
37
}
38
39
if (!((1 << playerID) & self->activePlayers) && triggered) {
40
if (!player->sidekick)
41
playerEntered = true;
42
self->activePlayers |= 1 << playerID;
43
}
44
45
if ((1 << playerID) & self->activePlayers) {
46
if (!player->sidekick)
47
shouldDrop = true;
48
49
if (!triggered)
50
self->activePlayers &= ~(1 << playerID);
51
}
52
}
53
self->position.x -= self->detectOffset.x;
54
self->position.y -= self->detectOffset.y;
55
56
if (playerEntered) {
57
if (!self->timerStore || Zone->timer - self->timerStore > self->interval)
58
self->timerStore = Zone->timer;
59
}
60
61
if (shouldDrop) {
62
int32 timer = Zone->timer - self->timerStore;
63
if (!((timer + self->intervalOffset) % self->interval))
64
LRZConvDropper_HandleButtonDrop(self);
65
}
66
break;
67
}
68
}
69
}
70
71
void LRZConvDropper_LateUpdate(void) {}
72
73
void LRZConvDropper_StaticUpdate(void) {}
74
75
void LRZConvDropper_Draw(void)
76
{
77
RSDK_THIS(LRZConvDropper);
78
79
RSDK.DrawSprite(&self->animator, NULL, false);
80
81
if (self->triggerMode == LRZCONVDROP_TRIGGER_PLAYER) {
82
int32 x = self->detectOffset.x + self->position.x;
83
int32 y = self->detectOffset.y + self->position.y;
84
RSDK.DrawLine(self->position.x, self->position.y, x, y, 0xFFFFFF, 0x7F, INK_NONE, false);
85
DrawHelpers_DrawHitboxOutline(x, y, &self->hitbox, 0, 0xFFFFFF);
86
}
87
}
88
89
void LRZConvDropper_Create(void *data)
90
{
91
RSDK_THIS(LRZConvDropper);
92
93
self->active = ACTIVE_BOUNDS;
94
self->drawGroup = Zone->objectDrawGroup[0];
95
self->visible = true;
96
self->drawFX = FX_FLIP;
97
self->updateRange.x = 0x800000;
98
self->updateRange.y = 0x800000;
99
100
if (self->triggerMode == LRZCONVDROP_TRIGGER_PLAYER) {
101
self->updateRange.x = (self->detectSize.x >> 1) + 0x1000000;
102
self->updateRange.y = (self->detectSize.y >> 1) + 0x1000000;
103
}
104
105
self->hitbox.left = -(self->detectSize.x >> 17);
106
self->hitbox.top = -(self->detectSize.y >> 17);
107
self->hitbox.right = self->detectSize.x >> 17;
108
self->hitbox.bottom = self->detectSize.y >> 17;
109
110
LRZConvDropper_SetupDropperChildren();
111
112
RSDK.SetSpriteAnimation(LRZConvDropper->aniFrames, 0, &self->animator, true, 0);
113
}
114
115
void LRZConvDropper_StageLoad(void) { LRZConvDropper->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConvDropper.bin", SCOPE_STAGE); }
116
117
void LRZConvDropper_SetupDropperChildren(void)
118
{
119
RSDK_THIS(LRZConvDropper);
120
121
int32 slot = RSDK.GetEntitySlot(self) - self->seqCount;
122
for (int32 i = 0; i < self->seqCount; ++i) {
123
EntityLRZConvItem *child = RSDK_GET_ENTITY(slot++, LRZConvItem);
124
child->active = ACTIVE_NEVER;
125
child->visible = false;
126
}
127
}
128
129
void LRZConvDropper_HandleButtonDrop(EntityLRZConvDropper *entity)
130
{
131
if (entity->seqCount && entity->seqPos < entity->seqCount) {
132
int32 slot = RSDK.GetEntitySlot(entity);
133
int32 seqPos = entity->seqPos - entity->seqCount;
134
EntityLRZConvItem *seqEnt = RSDK_GET_ENTITY(slot + seqPos, LRZConvItem);
135
136
if (seqEnt->classID == LRZConvItem->classID) {
137
EntityLRZConvItem *item = CREATE_ENTITY(LRZConvItem, INT_TO_VOID(seqEnt->type), entity->position.x, entity->position.y);
138
item->active = ACTIVE_NORMAL;
139
item->velocity.x = 0;
140
item->velocity.y = 0;
141
}
142
else if (seqEnt->classID == Iwamodoki->classID) {
143
EntityIwamodoki *iwamadoki = CREATE_ENTITY(Iwamodoki, NULL, entity->position.x, entity->position.y);
144
iwamadoki->active = ACTIVE_NORMAL;
145
iwamadoki->state = Iwamodoki_State_AwaitPlayer;
146
iwamadoki->velocity.x = 0;
147
iwamadoki->velocity.y = 0;
148
iwamadoki->lrzConvPhys = true;
149
}
150
else if (seqEnt->classID == ItemBox->classID) {
151
EntityItemBox *seqBox = (EntityItemBox *)seqEnt;
152
153
EntityItemBox *itembox = CREATE_ENTITY(ItemBox, INT_TO_VOID(seqBox->type), entity->position.x, entity->position.y);
154
itembox->active = ACTIVE_NORMAL;
155
itembox->velocity.x = 0;
156
itembox->velocity.y = 0;
157
itembox->lrzConvPhys = true;
158
itembox->direction = seqEnt->direction;
159
itembox->state = ItemBox_State_Conveyor;
160
}
161
162
if (++entity->seqPos >= entity->seqCount) {
163
if (entity->seqLoop)
164
entity->seqPos %= entity->seqCount;
165
}
166
}
167
}
168
169
#if GAME_INCLUDE_EDITOR
170
void LRZConvDropper_EditorDraw(void)
171
{
172
RSDK_THIS(LRZConvDropper);
173
174
RSDK.DrawSprite(&self->animator, NULL, false);
175
176
if (self->triggerMode == LRZCONVDROP_TRIGGER_PLAYER && showGizmos()) {
177
RSDK_DRAWING_OVERLAY(true);
178
179
int32 x = self->detectOffset.x + self->position.x;
180
int32 y = self->detectOffset.y + self->position.y;
181
182
RSDK.DrawLine(self->position.x, self->position.y, x, y, 0xFFFFFF, 0x7F, INK_NONE, false);
183
DrawHelpers_DrawHitboxOutline(x, y, &self->hitbox, 0, 0xFFFFFF);
184
185
int32 slot = RSDK.GetEntitySlot(self) - self->seqCount;
186
for (int32 i = 0; i < self->seqCount; ++i) {
187
EntityLRZConvItem *child = RSDK_GET_ENTITY(slot++, LRZConvItem);
188
189
if (child)
190
DrawHelpers_DrawArrow(self->position.x, self->position.y, child->position.x, child->position.y, 0xFFFF00, INK_NONE, 0xFF);
191
}
192
193
RSDK_DRAWING_OVERLAY(false);
194
}
195
}
196
197
void LRZConvDropper_EditorLoad(void)
198
{
199
LRZConvDropper->aniFrames = RSDK.LoadSpriteAnimation("LRZ2/LRZConvDropper.bin", SCOPE_STAGE);
200
201
RSDK_ACTIVE_VAR(LRZConvDropper, triggerMode);
202
RSDK_ENUM_VAR("Button", LRZCONVDROP_TRIGGER_BUTTON);
203
RSDK_ENUM_VAR("Player", LRZCONVDROP_TRIGGER_PLAYER);
204
}
205
#endif
206
207
void LRZConvDropper_Serialize(void)
208
{
209
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_UINT8, triggerMode);
210
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_ENUM, interval);
211
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_ENUM, intervalOffset);
212
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_VECTOR2, detectOffset);
213
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_VECTOR2, detectSize);
214
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_UINT8, seqCount);
215
RSDK_EDITABLE_VAR(LRZConvDropper, VAR_BOOL, seqLoop);
216
}
217
218