Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/PathInverter.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: PathInverter Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectPathInverter *PathInverter;
11
12
void PathInverter_Update(void)
13
{
14
RSDK_THIS(PathInverter);
15
16
StateMachine_Run(self->state);
17
}
18
19
void PathInverter_LateUpdate(void) {}
20
21
void PathInverter_StaticUpdate(void) {}
22
23
void PathInverter_Draw(void)
24
{
25
RSDK_THIS(PathInverter);
26
27
RSDK.DrawSprite(&self->animator, NULL, false);
28
}
29
30
void PathInverter_Create(void *data)
31
{
32
RSDK_THIS(PathInverter);
33
34
RSDK.SetSpriteAnimation(PathInverter->aniFrames, self->type, &self->animator, true, 0);
35
36
if (!SceneInfo->inEditor) {
37
self->active = ACTIVE_BOUNDS;
38
Hitbox *hitbox = RSDK.GetHitbox(&self->animator, 0);
39
self->size.x = hitbox->right;
40
self->size.y = hitbox->bottom;
41
self->size2x.x = 2 * self->size.x;
42
self->size2x.y = 2 * self->size.y;
43
self->updateRange.x = 0x800000;
44
self->updateRange.y = 0x800000;
45
self->visible = true;
46
self->drawGroup = Zone->objectDrawGroup[0];
47
48
switch (self->type) {
49
default: break;
50
case PATHINVERTER_H: self->state = PathInverter_State_Horizontal; break;
51
case PATHINVERTER_V: self->state = PathInverter_State_Vertical; break;
52
}
53
}
54
}
55
56
void PathInverter_StageLoad(void)
57
{
58
if (RSDK.CheckSceneFolder("SPZ2"))
59
PathInverter->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/PathInverter.bin", SCOPE_STAGE);
60
}
61
62
void PathInverter_HandlePathSwitch(EntityPlayer *player)
63
{
64
RSDK_THIS(PathInverter);
65
66
if (!self->playerPtrs[player->playerID]) {
67
Hitbox *playerHitbox = Player_GetHitbox(player);
68
69
if (player->position.y > self->position.y == player->position.x > self->position.x)
70
self->playerFlipFlags[player->playerID] = (self->size.y + playerHitbox->bottom) << 7;
71
else
72
self->playerFlipFlags[player->playerID] = -((self->size.y << 7) + (playerHitbox->bottom << 7));
73
74
if (player->collisionMode == CMODE_ROOF)
75
player->direction ^= FLIP_X;
76
77
self->playerPtrs[player->playerID] = player;
78
player->tileCollisions = TILECOLLISION_NONE;
79
player->velocity.x = player->groundVel * RSDK.Cos256(player->angle) >> 8;
80
player->velocity.y = player->groundVel * RSDK.Sin256(player->angle) >> 8;
81
self->groundVelStore[player->playerID] = player->groundVel;
82
83
int32 topSpeed = player->state == Player_State_Roll ? 0xC0000 : 0x80000;
84
player->velocity.x = CLAMP(player->velocity.x, -topSpeed, topSpeed);
85
86
player->state = Player_State_Static;
87
player->nextAirState = StateMachine_None;
88
player->nextGroundState = StateMachine_None;
89
}
90
91
int32 pos = self->size.x + ((self->position.x - player->position.x) >> 16);
92
int32 frameAngle = 4 * (3 * pos) / self->size2x.x;
93
int32 angle = (pos << 8) / self->size2x.x;
94
if (player->animator.animationID != ANI_JUMP || !player->groundedStore) {
95
int32 frame = 12 - frameAngle;
96
if (player->collisionMode != CMODE_ROOF * (self->playerFlipFlags[player->playerID] >= 0))
97
frame = frameAngle;
98
99
if (frame >= 0)
100
frame %= 24;
101
else
102
frame += 24;
103
104
if (player->collisionMode)
105
player->direction &= ~FLIP_Y;
106
else
107
player->direction |= FLIP_Y;
108
109
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_CS, &player->animator, true, frame);
110
}
111
112
player->onGround = true;
113
player->position.y = self->playerFlipFlags[player->playerID] * RSDK.Cos512(angle) + self->position.y;
114
}
115
void PathInverter_State_Horizontal(void)
116
{
117
RSDK_THIS(PathInverter);
118
119
foreach_active(Player, player)
120
{
121
if (player->collisionMode == CMODE_FLOOR || player->collisionMode == CMODE_ROOF) {
122
if (abs(self->position.x - player->position.x) >> 16 >= self->size.x
123
|| abs(self->position.y - player->position.y) >> 16 >= self->size.y + 32) {
124
int32 playerID = player->playerID;
125
126
if (self->playerPtrs[playerID]) {
127
self->playerPtrs[playerID] = NULL;
128
129
player->groundVel = self->groundVelStore[player->playerID];
130
player->groundVel = -player->groundVel;
131
player->velocity.x = -player->velocity.x;
132
if (player->collisionMode == CMODE_ROOF)
133
player->direction ^= FLIP_X;
134
135
player->collisionMode = (player->collisionMode - 2) & 3;
136
player->angle = (player->angle + 0x80) & 0xFF;
137
player->controlLock = 30;
138
139
if (player->animator.animationID == ANI_JUMP) {
140
player->state = Player_State_Roll;
141
}
142
else {
143
player->direction &= FLIP_X;
144
player->direction ^= FLIP_X;
145
player->state = Player_State_Ground;
146
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JOG, &player->animator, false, 0);
147
player->rotation = player->angle << 1;
148
}
149
150
player->tileCollisions = TILECOLLISION_DOWN;
151
}
152
}
153
else if (player->state == Player_State_Static) {
154
PathInverter_HandlePathSwitch(player);
155
}
156
else {
157
if (!player->onGround) {
158
if (self->playerPtrs[player->playerID])
159
PathInverter_HandlePathSwitch(player);
160
}
161
else {
162
if (abs(player->groundVel) < 0x40000) {
163
if (self->playerPtrs[player->playerID])
164
PathInverter_HandlePathSwitch(player);
165
}
166
else {
167
bool32 noInteractions = false;
168
if (player->velocity.x <= 0)
169
noInteractions = player->position.x <= self->position.x + 0x80000;
170
else
171
noInteractions = player->position.x >= self->position.x - 0x80000;
172
173
if (noInteractions)
174
self->playerPtrs[player->playerID] = NULL;
175
else
176
PathInverter_HandlePathSwitch(player);
177
}
178
}
179
}
180
}
181
}
182
}
183
void PathInverter_State_Vertical(void)
184
{
185
// Nothing !
186
}
187
188
#if GAME_INCLUDE_EDITOR
189
void PathInverter_EditorDraw(void)
190
{
191
RSDK_THIS(PathInverter);
192
RSDK.SetSpriteAnimation(PathInverter->aniFrames, self->type, &self->animator, true, 0);
193
194
PathInverter_Draw();
195
}
196
197
void PathInverter_EditorLoad(void)
198
{
199
PathInverter->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/PathInverter.bin", SCOPE_STAGE);
200
201
RSDK_ACTIVE_VAR(PathInverter, type);
202
RSDK_ENUM_VAR("Horizontal", PATHINVERTER_H);
203
RSDK_ENUM_VAR("Vertical (Unused)", PATHINVERTER_V);
204
}
205
#endif
206
207
void PathInverter_Serialize(void) { RSDK_EDITABLE_VAR(PathInverter, VAR_UINT8, type); }
208
209