Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
HeartBlock.c
Go to the documentation of this file.
1#include "common.h"
2#include "effects.h"
3#include "inventory.h"
4#include "vars_access.h"
5#include "message_ids.h"
6#include "ld_addrs.h"
7#include "entity.h"
8
9#if VERSION_JP // TODO remove once segments are split
10extern Addr entity_model_HeartBlockContent_ROM_END;
11extern Addr entity_model_HeartBlockContent_ROM_START;
12extern Addr entity_model_HeartBlock_ROM_END;
13extern Addr entity_model_HeartBlock_ROM_START;
14#endif
15
19
21
22extern Gfx Entity_HeartBlock_Render[];
26
28
30 s32 bufIdx = data->yawBufferPos - lagTime;
31 if (bufIdx < 0) {
32 bufIdx += ARRAY_COUNT(data->yawBuffer);
33 }
34 return data->yawBuffer[bufIdx];
35}
36
37void entity_HeartBlockContent__setupGfx(s32 entityIndex, Gfx* arg1) {
38 Entity* entity = get_entity_by_index(entityIndex);
40 Gfx* gfxPos = gMainGfxPos;
41 s32 alpha;
42 Matrix4f sp18;
43 Gfx* dlist;
44
45 dlist = ENTITY_ADDR(entity, Gfx*, arg1);
46
47 gDPSetCombineMode(gfxPos++, PM_CC_01, PM_CC_02);
48 gDPSetPrimColor(gfxPos++, 0, 0, 0, 0, 0, entity->alpha);
49
50 alpha = 92;
51 if (entity->alpha < alpha) {
52 alpha = entity->alpha;
53 }
54
55 guRotateF(sp18, entity_HeartBlockContent_get_previous_yaw(data, 2), 0.0f, 1.0f, 0.0f);
56 guMtxF2L(sp18, &data->unk_58);
58 gSPMatrix(gfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
59 gDPSetRenderMode(gfxPos++, AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | ZMODE_OPA | FORCE_BL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA), AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA));
60 gSPDisplayList(gfxPos++, dlist);
61 gDPPipeSync(gfxPos++);
62 gDPSetCombineMode(gfxPos++, PM_CC_01, PM_CC_02);
63 gDPSetPrimColor(gfxPos++, 0, 0, 0, 0, 0, alpha);
64 gSPPopMatrix(gfxPos++, G_MTX_MODELVIEW);
65
66 alpha = 72;
67 if (entity->alpha < alpha) {
68 alpha = entity->alpha;
69 }
70
71 guRotateF(sp18, entity_HeartBlockContent_get_previous_yaw(data, 3), 0.0f, 1.0f, 0.0f);
72 guMtxF2L(sp18, &data->unk_98);
74 gSPMatrix(gfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
75 gDPSetRenderMode(gfxPos++, AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | ZMODE_OPA | FORCE_BL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA), AA_EN | Z_CMP | IM_RD | CVG_DST_SAVE | ZMODE_OPA | FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA));
76 gSPDisplayList(gfxPos++, dlist);
77 gDPPipeSync(gfxPos++);
78 gDPSetCombineMode(gfxPos++, PM_CC_01, PM_CC_02);
79 gDPSetPrimColor(gfxPos++, 0, 0, 0, 0, 0, alpha);
80 gSPPopMatrix(gfxPos++, G_MTX_MODELVIEW);
81
82 gMainGfxPos = gfxPos;
83}
84
88
91 Entity* entityTemp = get_entity_by_index(temp->parentEntityIndex);
92
93 entity->pos.x = entityTemp->pos.x;
94 entity->pos.y = entityTemp->pos.y + 14.0f;
95 entity->pos.z = entityTemp->pos.z;
96}
97
100 Entity* blockEntity;
101
103 entity->alpha = 255;
104 data = entity->dataBuf.heartBlockContent;
106 blockEntity = get_entity_by_index(data->parentEntityIndex);
107
108 if (data->unk_09 == 0) {
109 data->unk_09 = 1;
110 data->state = 2;
111 entity->scale.x = 1.0f;
112 } else {
113 data->state = 0;
114 entity->scale.x = 0.0f;
115 }
116
117 data->unk_0C = 0;
118 data->unk_10 = 0;
119 entity->rot.x = 0.0f;
120 entity->rot.y = 0.0f;
121 entity->rot.z = 0.0f;
122 entity->scale.y = entity->scale.x;
123 entity->scale.z = entity->scale.x;
124
126}
127
130 switch (data->state) {
131 case 0:
132 entity->scale.x = 0.0f;
133 entity->scale.y = 0.0f;
134 entity->scale.z = 0.0f;
135 if (arg1 == 0) {
136 data->state++;
137 break;
138 }
139 return;
140 case 1:
141 entity->scale.x += 0.01;
142 if (entity->scale.x >= 1.0) {
143 entity->scale.x = 1.0f;
144 data->sparkleTimer = 0;
145 data->state++;
146 }
147 entity->scale.z = entity->scale.x;
148 entity->scale.y = entity->scale.x;
149 break;
150 case 2:
152 data->state++;
153 // fallthrough
154 case 3:
155 if (gOverrideFlags == 0) {
156 // create an effect every 50 frames
157 data->sparkleTimer--;
158 if (data->sparkleTimer <= 0) {
159 data->sparkleTimer = 50;
160 fx_stars_shimmer(data->sparkleEffectType, entity->pos.x, entity->pos.y, entity->pos.z, 22.0f, 8.0f, 4, 20);
161 }
162 }
163 break;
164 }
165
173 }
174}
175
178
179 data->state = 0;
180 entity->scale.x = 1.0f;
181 entity->scale.y = 1.0f;
182 entity->scale.z = 1.0f;
183 entity->rot.z = 0.0f;
184}
185
187 PlayerStatus* playerStatus = &gPlayerStatus;
189 f32 offsetX, offsetY, offsetZ;
190
191 switch (data->state) {
192 case 0:
193 fx_sparkles(FX_SPARKLES_0, entity->pos.x, entity->pos.y, entity->pos.z, 2.0f);
194 data->bouncePhase = 0.0f;
195 data->state++;
196 data->riseVel = 6.0f;
197 break;
198 case 1:
199 entity->pos.y = entity->pos.y + data->riseVel;
200 data->riseVel -= 1.0f;
201 if (data->riseVel <= 2.0f) {
202 data->state++;
203 entity->flags &= ~ENTITY_FLAG_ALWAYS_FACE_CAMERA;
204 data->rotRate = -10.0f;
207 }
208 break;
209 case 2:
210 entity->pos.y += sin_rad(DEG_TO_RAD(data->bouncePhase)) * 0.5f;
211 data->bouncePhase -= 30.0f;
212 if (data->bouncePhase < 0.0f) {
213 data->bouncePhase += 360.0f;
214 }
215 entity->rot.y += data->rotRate;
216 data->rotRate += 2.0f;
217 if (data->rotRate >= 0.0f) {
218 data->sparkleTrailAngle = 0.0f;
219 data->sparkleTrailRadius = 0.0f;
220 data->state++;
221 data->sparkleTrailPosY = playerStatus->colliderHeight + 5;
222 data->sparkleTrailTimer = 0;
223 recover_hp(-1);
224 recover_fp(-1);
226 }
227 data->yawBuffer[data->yawBufferPos] = entity->rot.y;
228 data->yawBufferPos++;
229 if (data->yawBufferPos > ARRAY_COUNT(data->yawBuffer)) {
230 data->yawBufferPos = 0;
231 }
232 break;
233 case 3:
234 data->sparkleTrailRadius += 2.0;
235 if (data->sparkleTrailRadius >= 10.0f) {
236 data->sparkleTrailRadius = 10.0f;
237 }
238 data->sparkleTrailAngle += 18.0f;
239 if (data->sparkleTrailAngle >= 360.0f) {
240 data->sparkleTrailAngle -= 360.0f;
241 }
242 offsetX = data->sparkleTrailRadius * sin_rad(DEG_TO_RAD(data->sparkleTrailAngle));
243 offsetZ = data->sparkleTrailRadius * cos_rad(DEG_TO_RAD(data->sparkleTrailAngle));
244 offsetY = data->sparkleTrailPosY;
245
246 data->sparkleTrailPosY -= 0.7;
247
248 if ((data->sparkleTrailTimer++ & 1) != 0) {
249 fx_sparkles(FX_SPARKLES_3, playerStatus->pos.x + offsetX,
250 playerStatus->pos.y + offsetY,
251 playerStatus->pos.z - offsetZ,
252 8.0f
253 );
254 }
255 if (data->sparkleTrailPosY < 20.0f) {
256 data->sparkleTrailPosY = 20.0f;
257 data->state++;
258 }
259 // fallthrough
260 case 4:
261 entity->pos.y += sin_rad(DEG_TO_RAD(data->bouncePhase)) * 0.5f;
262 data->bouncePhase -= 30.0f;
263 if (data->bouncePhase < 0.0f) {
264 data->bouncePhase += 360.0f;
265 }
266 data->rotRate += 1.0;
267 if (data->rotRate > 30.0f) {
268 data->rotRate = 30.0f;
269 }
270 entity->rot.y += data->rotRate;
271 if (entity->rot.y >= 360.0f) {
272 entity->rot.y -= 360.0f;
273 }
274 entity->alpha -= 5;
275 if (entity->alpha < 7) {
276 entity->alpha = 5;
277 if (data->state == 4) {
278 data->state++;
279 }
280 }
281 data->yawBuffer[data->yawBufferPos] = entity->rot.y;
282 data->yawBufferPos++;
283 if (data->yawBufferPos > ARRAY_COUNT(data->yawBuffer)) {
284 data->yawBufferPos = 0;
285 }
286 break;
287 case 5:
288 playerStatus->animFlags &= ~PA_FLAG_RAISED_ARMS;
291 gOverrideFlags &= ~GLOBAL_OVERRIDES_40;
293 break;
294 }
295}
296
299}
300
303
305
306 if (entity->scale.x < 1.0) {
307 return;
308 }
309
310 switch (data->heartbeatTimer) {
311 case 0:
312 entity->scale.x += 0.1;
313 data->heartbeatTimer++;
314 break;
315 case 1:
316 entity->scale.x -= 0.02;
317 if (entity->scale.x <= 1.0) {
318 entity->scale.x = 1.0f;
319 data->heartbeatTimer++;
320 }
321 break;
322 case 2:
323 case 3:
324 case 4:
325 case 5:
326 case 6:
327 case 7:
328 case 8:
329 case 9:
330 case 10:
331 case 11:
332 case 12:
333 case 13:
334 case 14:
335 case 15:
336 case 16:
337 data->heartbeatTimer++;
338 break;
339 default:
340 data->heartbeatTimer = 0;
341 break;
342 }
343
344 entity->scale.y = entity->scale.x;
345}
346
350
355
360
364
368
381
390
392 s32 useAltSparkleType = CreateEntityVarArgBuffer[0];
393 Entity* childEntity;
395
397 childEntity = get_entity_by_index(create_entity(bp, (s32)entity->pos.x, (s32)entity->pos.y, (s32)entity->pos.z, 0, MAKE_ENTITY_END));
398 data = childEntity->dataBuf.heartBlockContent;
399 data->parentEntityIndex = entity->listIndex;
400
401 if (useAltSparkleType == FALSE) {
402 data->sparkleEffectType = 3;
403 } else {
404 data->sparkleEffectType = 6;
405 }
406}
407
411
413
435
440
443 .typeDataSize = sizeof(BlockData),
444 .renderCommandList = Entity_HeartBlock_RenderScript,
445 .modelAnimationNodes = 0,
446 .fpInit = entity_base_block_init,
447 .updateEntityScript = Entity_InertBlock_Script,
448 .fpHandleCollision = entity_block_handle_collision,
449 { .dma = ENTITY_ROM(HeartBlock) },
451 .aabbSize = { 25, 25, 25 }
452};
453
456 .typeDataSize = sizeof(HeartBlockContentData),
458 .modelAnimationNodes = 0,
460 .updateEntityScript = Entity_HeartBlockContent_Script,
461 .fpHandleCollision = NULL,
462 { .dma = ENTITY_ROM(HeartBlockContent) },
464 .aabbSize = { 18, 6, 18 }
465};
466
469 .typeDataSize = sizeof(BlockData),
470 .renderCommandList = Entity_HeartBlock_RenderScript,
471 .modelAnimationNodes = 0,
472 .fpInit = entity_HeartBlock_init,
473 .updateEntityScript = Entity_HeartBlock_Script,
474 .fpHandleCollision = entity_block_handle_collision,
475 { .dma = ENTITY_ROM(HeartBlock) },
476 .entityType = ENTITY_TYPE_HEALING_BLOCK,
477 .aabbSize = { 25, 25, 25 }
478};
EntityBlueprint Entity_HeartBlockFrame
Definition HeartBlock.c:441
void entity_HeartBlockContent__reset(Entity *entity)
Definition HeartBlock.c:98
EntityModelScript Entity_HeartBlockContent_RenderScriptIdle
Definition HeartBlock.c:436
EntityModelScript Entity_HeartBlockContent_RenderScriptHit
Definition HeartBlock.c:437
EntityBlueprint Entity_HeartBlockContent
Definition HeartBlock.c:454
EntityBlueprint Entity_HeartBlock
Definition HeartBlock.c:467
void entity_HeartBlockContent_init(Entity *entity)
Definition HeartBlock.c:347
Gfx Entity_HeartBlockContent_RenderHeartHappy[]
Gfx Entity_HeartBlockContent_RenderHeartAwake[]
EntityModelScript Entity_HeartBlock_RenderScript
Definition HeartBlock.c:439
void entity_HeartBlock_show_tutorial_message(Entity *entity)
Definition HeartBlock.c:369
void entity_HeartBlock_change_render_script(Entity *entity)
Definition HeartBlock.c:365
void entity_HeartBlockContent_reset_data(Entity *entity)
Definition HeartBlock.c:176
EntityScript Entity_InertBlock_Script
Definition Block.c:503
void entity_HeartBlockContent_setupGfx(s32 entityIndex)
Definition HeartBlock.c:85
EntityModelScript Entity_HeartBlockContent_RenderScriptAfterHit
Definition HeartBlock.c:438
void entity_HeartBlock_wait_for_close_tutorial(Entity *entity)
Definition HeartBlock.c:382
void entity_HeartBlockContent__anim_heal(Entity *entity, s32 arg1)
Definition HeartBlock.c:186
s8 entity_HeartBlock_create_child_entity(Entity *entity, EntityBlueprint *bp)
Definition HeartBlock.c:391
f32 entity_HeartBlockContent_get_previous_yaw(HeartBlockContentData *data, s32 lagTime)
Definition HeartBlock.c:29
void entity_HeartBlockContent_anim_idle(Entity *entity, s32 arg1)
Definition HeartBlock.c:128
BSS u32 HeartBlockPrinterClosed
Definition HeartBlock.c:27
Gfx Entity_HeartBlockContent_RenderHeartSleeping[]
void entity_HeartBlock_idle(Entity *entity)
Definition HeartBlock.c:297
void entity_HeartBlockContent_set_initial_pos(Entity *entity)
Definition HeartBlock.c:89
void entity_HeartBlock_init(Entity *entity)
Definition HeartBlock.c:408
void entity_HeartBlockContent__setupGfx(s32 entityIndex, Gfx *arg1)
Definition HeartBlock.c:37
void entity_HeartBlockContent_idle(Entity *entity)
Definition HeartBlock.c:356
EntityScript Entity_HeartBlockContent_Script
Definition HeartBlock.c:414
void entity_HeartBlockContent_reset(Entity *entity)
Definition HeartBlock.c:351
void entity_HeartBlockContent_anim_beating(Entity *entity)
Definition HeartBlock.c:301
EntityScript Entity_HeartBlock_Script
Definition HeartBlock.c:426
Gfx Entity_HeartBlock_Render[]
Definition HeartBlock.c:50
void entity_HeartBlockContent_anim_heal(Entity *entity)
Definition HeartBlock.c:361
PartnerData partners[12]
Mtx matrixStack[0x200]
struct HeartBlockContentData * heartBlockContent
f32 Matrix4f[4][4]
#define guRotateF
#define guMtxF2L
@ FX_SPARKLES_3
Definition effects.h:237
@ FX_SPARKLES_0
Definition effects.h:234
s32 CreateEntityVarArgBuffer[]
Definition entity.c:35
s32 EntityModelScript[]
Definition entity.h:7
#define es_Call(func)
Definition entity.h:37
#define es_Restart
Definition entity.h:40
#define STANDARD_ENTITY_MODEL_SCRIPT(gfx, renderMode)
Definition entity.h:56
#define ENTITY_ADDR(entity, type, data)
Definition entity.h:64
#define es_SetCallback(func, time)
Definition entity.h:38
#define ENTITY_ROM(name)
Definition entity.h:65
s32 EntityScript[]
Definition entity.h:6
#define es_End
Definition entity.h:35
#define es_PlaySound(soundId)
Definition entity.h:45
void entity_set_render_script(Entity *entity, EntityModelScript *cmdList)
Definition entity.c:761
@ ENTITY_TYPE_HEALING_BLOCK_FRAME
Definition enums.h:2574
@ ENTITY_TYPE_HEALING_BLOCK
Definition enums.h:2570
@ ENTITY_TYPE_HEALING_BLOCK_CONTENT
Definition enums.h:2598
@ PA_FLAG_RAISED_ARMS
Sets action state to ACTION_STATE_RAISE_ARMS on idle.
Definition enums.h:3100
@ TIME_FREEZE_PARTIAL
Definition enums.h:3465
@ TIME_FREEZE_NONE
Definition enums.h:3464
@ SOUND_HEART_BLOCK
Definition enums.h:750
@ SOUND_HIT_BLOCK
Definition enums.h:768
@ RENDER_MODE_SURFACE_XLU_LAYER3
Definition enums.h:3299
@ RENDER_MODE_SURFACE_XLU_LAYER2
Definition enums.h:3287
@ RENDER_MODE_ALPHATEST
Definition enums.h:3276
@ ENTITY_FLAG_FIXED_SHADOW_SIZE
Definition enums.h:2622
@ ENTITY_FLAG_4000
Definition enums.h:2627
@ ENTITY_FLAG_DISABLE_COLLISION
Definition enums.h:2618
@ ENTITY_FLAG_ALWAYS_FACE_CAMERA
Definition enums.h:2626
@ PARTNER_GOOMBARIO
Definition enums.h:2886
@ GLOBAL_OVERRIDES_40
Definition enums.h:4325
#define MAKE_ENTITY_END
Definition evt.h:107
Entity * get_entity_by_index(s32 index)
Definition entity.c:530
s32 disable_player_input(void)
Definition 77480.c:990
s32 entity_can_collide_with_jumping_player(Entity *entity)
Definition Shadow.c:11
void entity_block_hit_animate_scale(Entity *entity)
Definition Block.c:90
s32 entity_start_script(Entity *entity)
Definition entity.c:560
f32 cos_rad(f32 x)
Definition 43F0.c:717
s32 enable_player_input(void)
Definition 77480.c:998
MessagePrintState * msg_get_printer_for_msg(s32 msgID, s32 *a1)
Definition msg.c:1424
s32 entity_base_block_idle(Entity *entity)
Definition Block.c:195
void exec_entity_commandlist(Entity *entity)
Definition entity.c:313
void entity_base_block_init(Entity *entity)
Definition Block.c:213
f32 entity_block_hit_init_scale(Entity *entity)
Definition Block.c:75
f32 sin_rad(f32 x)
Definition 43F0.c:713
void set_time_freeze_mode(s32)
Time freeze modes: 0: none 1: NPCs move, can't be interacted with 2: NPCs don't move,...
Definition main_loop.c:358
s32 create_entity(EntityBlueprint *bp,...)
Definition entity.c:1195
s32 entity_block_handle_collision(Entity *entity)
Definition Block.c:334
s32 recover_hp(s32 amt)
Recover player HP.
Definition inventory.c:2175
s32 recover_fp(s32 amt)
Recover player FP.
Definition inventory.c:2158
void sfx_play_sound(s32 soundID)
Definition sfx.c:517
@ GF_Tutorial_HeartBlock
#define BSS
Definition macros.h:7
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define PM_CC_01
Definition macros.h:276
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define PM_CC_02
Definition macros.h:277
void(* renderSetupFunc)(s32)
EntityData dataBuf
Vec3f scale
u8 Addr[]
Linker symbol address, as in ld_addrs.h.
Definition types.h:16
s32 gOverrideFlags
Definition main_loop.c:11
Gfx * gMainGfxPos
Definition cam_main.c:15
PlayerData gPlayerData
Definition 77480.c:40
u16 gMatrixListPos
Definition main_loop.c:45
PlayerStatus gPlayerStatus
Definition 77480.c:39
DisplayContext * gDisplayContext
Definition cam_main.c:16
s32 set_global_flag(s32 index)
Definition vars_access.c:65
s32 get_global_flag(s32 index)
Definition vars_access.c:89