Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
Tweester.c
Go to the documentation of this file.
1#include "common.h"
2#include "entity.h"
3#include "ld_addrs.h"
4
6 0, 2,
7 32, 2,
8 0, 3,
9 32, 2,
10 0, 80,
11 255, 0
12};
13
14extern unsigned char D_0A000BF0_E57A50[];
15extern unsigned char D_0A000FF0_E57E50[];
16extern unsigned char D_0A0018A0_E58700[];
17extern unsigned char D_0A0014A0_E58300[];
22extern Gfx Entity_Tweester_Render[];
23
25 Entity* entity = get_entity_by_index(entityIndex);
26 TweesterData* data = entity->dataBuf.tweester;
27 Matrix4f sp18;
28 Matrix4f sp58;
29 Gfx* gfx;
30
31 guMtxL2F(sp18, ENTITY_ADDR(entity, Mtx*, &Entity_Tweester_mtxInnerWhirl));
32 guRotateF(sp58, data->innerWhirlRotY, 0.0f, 1.0f, 0.0f);
33 guMtxCatF(sp58, sp18, sp18);
34 guMtxF2L(sp18, &data->mtxInnerWhirl);
36 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
38 gSPDisplayList(gMainGfxPos++, gfx);
39 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
40}
41
43 Entity* entity = get_entity_by_index(entityIndex);
44 TweesterData* data = entity->dataBuf.tweester;
45 Matrix4f sp18;
46 Matrix4f sp58;
47 Gfx* gfx;
48
49 guMtxL2F(sp18, ENTITY_ADDR(entity, Mtx*, &Entity_Tweester_mtxOuterWhirl));
50 guRotateF(sp58, data->outerWhirlRotY, 0.0f, 1.0f, 0.0f);
51 guMtxCatF(sp58, sp18, sp18);
52 guMtxF2L(sp18, &data->mtxOuterWhirl);
54 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
56 gSPDisplayList(gMainGfxPos++, gfx);
57 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
58}
59
60void entity_Tweester_render_face(s32 entityIndex) {
61 Entity* entity = get_entity_by_index(entityIndex);
62 TweesterData* data = entity->dataBuf.tweester;
63
64 gDPPipeSync(gMainGfxPos++);
65 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
66 gDPLoadTLUT_pal16(gMainGfxPos++, 0, D_0A0018A0_E58700);
67 gSPTexture(gMainGfxPos++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
68 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIA, G_CC_MODULATEIA);
69 gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
70 gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
71 gDPLoadTextureBlock_4b(gMainGfxPos++, D_0A0014A0_E58300, G_IM_FMT_CI, 64, 32, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_CLAMP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
72 gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
73 gDPSetTextureFilter(gMainGfxPos++, G_TF_BILERP);
74 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->faceAnimTexOffset * 4, 0, (data->faceAnimTexOffset + 124) * 4, 31 * 4);
75}
76
77void entity_Tweester_setupGfx(s32 entityIndex) {
78 Entity* entity = get_entity_by_index(entityIndex);
79 TweesterData* data = entity->dataBuf.tweester;
80
81 gDPPipeSync(gMainGfxPos++);
82 gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
83 gSPTexture(gMainGfxPos++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
84 gDPSetCombineMode(gMainGfxPos++, PM_CC_ALT_INTERFERENCE, G_CC_MODULATEIA2);
85 gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
86 gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
87 gDPSetTextureImage(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 32, D_0A000BF0_E57A50);
88 gDPSetTile(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 4, 0x0000, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD);
89 gDPLoadSync(gMainGfxPos++);
90 gDPLoadTile(gMainGfxPos++, G_TX_LOADTILE, 0, 0, 0x007C, 0x007C);
91 gDPPipeSync(gMainGfxPos++);
92 gDPSetTile(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 4, 0x0000, G_TX_RENDERTILE, 0, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD);
93 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, 0, 0, 0x007C, 0x007C);
94 gDPSetTextureImage(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 32, D_0A000FF0_E57E50);
95 gDPSetTile(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 4, 0x0080, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD);
96 gDPLoadSync(gMainGfxPos++);
97 gDPLoadTile(gMainGfxPos++, G_TX_LOADTILE, 0, 0, 0x007C, 0x007C);
98 gDPPipeSync(gMainGfxPos++);
99 gDPSetTile(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 4, 0x0080, 1, 0, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, 5, G_TX_NOLOD);
100 gDPSetTileSize(gMainGfxPos++, 1, 0, 0, 0x007C, 0x007C);
101 gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
102 gDPSetTextureFilter(gMainGfxPos++, G_TF_BILERP);
103 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->innerWhirlTexOffsetX, data->innerWhirlTexOffsetY, data->innerWhirlTexOffsetX + 124, data->innerWhirlTexOffsetY + 124);
105 gDPPipeSync(gMainGfxPos++);
106 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->outerWhirlTexOffsetX, data->outerWhirlTexOffsetY, data->outerWhirlTexOffsetX + 124, data->outerWhirlTexOffsetY + 124);
108 entity_Tweester_render_face(entityIndex);
109}
110
112 TweesterData* data = entity->dataBuf.tweester;
113 s32 i;
114
115 data->faceAnimTimer--;
116 if (data->faceAnimTimer <= 0) {
117 i = data->faceAnimState;
118 if (Entity_Tweester_FaceAnimationData[i] == 255) {
119 i = 0;
120 }
123 data->faceAnimState = i;
124 }
125}
126
128 TweesterData* data = entity->dataBuf.tweester;
129 s32 count = 0;
130 f32 deltaX = fabsf(data->targetX - entity->pos.x);
131 f32 deltaZ = fabsf(data->targetZ - entity->pos.z);
132
133 if (deltaX <= 10.0f) {
134 count++;
135 }
136 if (deltaZ <= 10.0f) {
137 count++;
138 }
139
140 return count >= 2;
141}
142
144 TweesterData* data = entity->dataBuf.tweester;
145 s32 pathOffset;
146 s32** paths;
147 s32 i, j;
148 s32* pathPtr;
149
150 pathOffset = data->pathOffset;
151 paths = data->paths;
152
153 if (pathOffset == 0) {
154 for (i = 0; *paths != PTR_LIST_END; paths++, i++) {
155 }
156 j = rand_int(i * 10 - 1) / 10;
157 paths = data->paths;
158 data->curPath = paths[j];
159 }
160 pathPtr = &data->curPath[pathOffset];
161 if (*pathPtr != TWEESTER_PATH_STOP) {
162 pathOffset += 3;
163 if (*pathPtr == TWEESTER_PATH_LOOP){
164 pathOffset = 0;
165 pathPtr = data->curPath;
166 data->targetX = *pathPtr++;
167 data->targetY = *pathPtr++;
168 data->targetZ = *pathPtr++;
169 } else {
170 data->targetX = *pathPtr++;
171 data->targetY = *pathPtr++;
172 data->targetZ = *pathPtr++;
173 }
174 }
175 data->pathOffset = pathOffset;
176}
177
179 TweesterData* data = entity->dataBuf.tweester;
180 f32 yawRad;
181
182 f32 temp_f4 = (atan2(entity->pos.x, entity->pos.z, data->targetX, data->targetZ) - data->yaw) * 0.03125f;
183 if (temp_f4 >= 0.0f && temp_f4 < 0.01) {
184 temp_f4 = 0.01f;
185 }
186 if (temp_f4 < 0.0f && temp_f4 > -0.01) {
187 temp_f4 = -0.01f;
188 }
189
190 data->yaw = clamp_angle(data->yaw + temp_f4);
191 yawRad = DEG_TO_RAD(data->yaw);
192 entity->pos.x += sin_rad(yawRad);
193 entity->pos.z -= cos_rad(yawRad);
194
197 }
198}
199
201 PlayerStatus* playerStatus = &gPlayerStatus;
202 PartnerStatus* partnerStatus = &gPartnerStatus;
203 PlayerData* playerData = &gPlayerData;
204 TweesterData* data = entity->dataBuf.tweester;
205 f32 delta;
206 f32 targetRotationSpeed;
207
210 !(playerStatus->flags & PS_FLAG_PAUSED) &&
211 (playerData->curPartner != PARTNER_GOOMBARIO ||
212 playerStatus->inputDisabledCount == 0 ||
214 )) {
215 entity_Tweester_move(entity);
216 }
217
219 data->frameCounter++;
220
221 if (data->frameCounter < 100) {
222 targetRotationSpeed = 3.5f;
223 delta = (targetRotationSpeed - data->rotSpeed) / 28.0f;
224 if (delta < 0.02) {
225 delta = 0.02f;
226 }
227 data->rotSpeed += delta;
228 if (data->rotSpeed >= targetRotationSpeed){
229 data->rotSpeed = targetRotationSpeed;
230 }
231 } else {
232 targetRotationSpeed = 1.3f;
233 delta = (targetRotationSpeed - data->rotSpeed) * 0.0625f;
234 if (delta > -0.02) {
235 delta = -0.02f;
236 }
237 data->rotSpeed += delta;
238 if (data->rotSpeed <= targetRotationSpeed){
239 data->rotSpeed = targetRotationSpeed;
240 data->frameCounter = 0;
241 }
242 }
243
244 data->innerWhirlRotY += data->rotSpeed;
245 if (data->innerWhirlRotY > 360.0f) {
246 data->innerWhirlRotY = 0.0f;
247 }
248
249 delta = data->innerWhirlRotY - data->outerWhirlRotY;
250 if (delta < 0.0f) {
251 delta += 360.0f;
252 }
253 delta *= 0.25;
254 data->outerWhirlRotY += delta;
255 if (data->outerWhirlRotY > 360.0f) {
256 data->outerWhirlRotY = 0.0f;
257 }
258
259 data->innerWhirlTexOffsetX += 4;
260 data->innerWhirlTexOffsetY -= 8;
261 data->outerWhirlTexOffsetX += 4;
262 data->outerWhirlTexOffsetY -= 16;
263
264 entity->rot.y = -gCameras[CAM_DEFAULT].curYaw;
265
266 if (partnerStatus->partnerActionState == PARTNER_ACTION_NONE || partnerStatus->actingPartner != PARTNER_BOW) {
267 if (playerStatus->actionState == ACTION_STATE_USE_TWEESTER) {
268 Npc* npc = npc_find_closest_simple(entity->pos.x, entity->pos.y, entity->pos.z, 50.0f);
269 if (npc != NULL && (npc->flags & NPC_FLAG_PARTNER)) {
271 }
272 }
273
274 if (!is_picking_up_item() &&
275 !(playerStatus->flags & PS_FLAG_PAUSED) &&
276 playerStatus->actionState != ACTION_STATE_USE_TWEESTER &&
277 playerStatus->blinkTimer == 0 &&
278 fabs(dist2D(entity->pos.x, entity->pos.z, playerStatus->pos.x, playerStatus->pos.z)) <= 50.0
279 ) {
280 TweesterTouchingPlayer = entity;
283 }
284 }
285}
286
288 entity->scale.x += 0.1;
289 if (entity->scale.x >= 1.0) {
290 entity->scale.x = 1.0f;
291 }
292 entity->scale.z = entity->scale.y = entity->scale.x;
293}
294
296 TweesterData* data = entity->dataBuf.tweester;
297
298 data->paths = (s32**)CreateEntityVarArgBuffer[0];
300 data->faceAnimTexOffset = 0;
302 entity->scale.x = 0;
303 entity->scale.y = 0;
304 entity->scale.z = 0;
305}
306
312
314
317 .typeDataSize = sizeof(TweesterData),
318 .renderCommandList = Entity_Tweester_RenderScript,
319 .modelAnimationNodes = 0,
320 .fpInit = entity_Tweester_init,
321 .updateEntityScript = Entity_Tweester_Script,
322 .fpHandleCollision = NULL,
323 { .dma = ENTITY_ROM(Tweester) },
324 .entityType = ENTITY_TYPE_TWEESTER,
325 .aabbSize = { 50, 70, 50 }
326};
327
Mtx matrixStack[0x200]
f32 Matrix4f[4][4]
struct TweesterData * tweester
#define guRotateF
#define guMtxF2L
#define guMtxCatF
#define rand_int
#define clamp_angle
#define atan2
s32 CreateEntityVarArgBuffer[]
Definition entity.c:35
s32 ** paths
Definition entity.h:316
s32 EntityModelScript[]
Definition entity.h:7
s16 outerWhirlTexOffsetY
Definition entity.h:313
#define STANDARD_ENTITY_MODEL_SCRIPT(gfx, renderMode)
Definition entity.h:56
s8 faceAnimTexOffset
Definition entity.h:304
f32 rotSpeed
Definition entity.h:305
#define TWEESTER_PATH_LOOP
Definition entity.h:70
#define ENTITY_ADDR(entity, type, data)
Definition entity.h:64
#define es_SetCallback(func, time)
Definition entity.h:38
s16 targetX
Definition entity.h:317
s16 targetY
Definition entity.h:318
f32 outerWhirlRotY
Definition entity.h:307
s16 innerWhirlTexOffsetY
Definition entity.h:311
#define ENTITY_ROM(name)
Definition entity.h:65
s16 targetZ
Definition entity.h:319
s8 faceAnimTimer
Definition entity.h:303
Mtx mtxOuterWhirl
Definition entity.h:309
s32 EntityScript[]
Definition entity.h:6
#define TWEESTER_PATH_STOP
Definition entity.h:69
f32 innerWhirlRotY
Definition entity.h:306
#define es_End
Definition entity.h:35
s16 pathOffset
Definition entity.h:320
s8 faceAnimState
Definition entity.h:302
s16 innerWhirlTexOffsetX
Definition entity.h:310
s16 outerWhirlTexOffsetX
Definition entity.h:312
Mtx mtxInnerWhirl
Definition entity.h:308
s16 frameCounter
Definition entity.h:314
s32 * curPath
Definition entity.h:315
@ PS_FLAG_PAUSED
Definition enums.h:3040
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ ENTITY_TYPE_TWEESTER
Definition enums.h:2597
@ PA_FLAG_INTERRUPT_USE_PARTNER
forces actions with bow, parakarry, watt, and lakilester to end (sushie not tested)
Definition enums.h:3093
@ TIME_FREEZE_NONE
Definition enums.h:3464
@ RENDER_MODE_SURFACE_XLU_LAYER1
Definition enums.h:3282
@ ENTITY_FLAG_DISABLE_COLLISION
Definition enums.h:2618
@ PARTNER_BOW
Definition enums.h:2894
@ PARTNER_GOOMBARIO
Definition enums.h:2886
@ ACTION_STATE_USE_TWEESTER
Definition enums.h:2459
@ CAM_DEFAULT
Definition enums.h:1800
@ NPC_FLAG_PARTNER
Definition enums.h:3024
Entity * get_entity_by_index(s32 index)
Definition entity.c:530
f32 fabsf(f32 f)
f64 fabs(f64 f)
f32 cos_rad(f32 x)
Definition 43F0.c:716
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:669
s32 is_picking_up_item(void)
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
f32 sin_rad(f32 x)
Definition 43F0.c:712
s32 get_time_freeze_mode(void)
Definition main_loop.c:390
Npc * npc_find_closest_simple(f32 x, f32 y, f32 z, f32 radius)
Finds the closest simple-hitbox NPC to a given point within a radius.
Definition npc.c:1994
Gfx Entity_Tweester_Render[]
Definition Tweester.c:225
void entity_Tweester_update_face_anim(Entity *entity)
Definition Tweester.c:111
void entity_Tweester_idle(Entity *entity)
Definition Tweester.c:200
Mtx Entity_Tweester_mtxInnerWhirl
Definition Tweester.c:51
unsigned char D_0A000FF0_E57E50[]
void entity_Tweester_render_inner_whirl(s32 entityIndex)
Definition Tweester.c:24
unsigned char D_0A0014A0_E58300[]
u8 Entity_Tweester_FaceAnimationData[]
Definition Tweester.c:5
void entity_Tweester_render_face(s32 entityIndex)
Definition Tweester.c:60
unsigned char D_0A0018A0_E58700[]
void entity_Tweester_render_outer_whirl(s32 entityIndex)
Definition Tweester.c:42
Mtx Entity_Tweester_mtxOuterWhirl
Definition Tweester.c:58
EntityScript Entity_Tweester_Script
Definition Tweester.c:307
Gfx Entity_Tweester_RenderOuterWhirl[]
Definition Tweester.c:122
void entity_Tweester_select_target_point(Entity *entity)
Definition Tweester.c:143
s32 entity_Tweester_has_reached_target(Entity *entity)
Definition Tweester.c:127
unsigned char D_0A000BF0_E57A50[]
Gfx Entity_Tweester_RenderInnerWhirl[]
Definition Tweester.c:177
EntityBlueprint Entity_Tweester
Definition Tweester.c:315
void entity_Tweester_setupGfx(s32 entityIndex)
Definition Tweester.c:77
void entity_Tweester_init(Entity *entity)
Definition Tweester.c:295
void entity_Tweester_move(Entity *entity)
Definition Tweester.c:178
void entity_Tweester_anim_scale(Entity *entity)
Definition Tweester.c:287
EntityModelScript Entity_Tweester_RenderScript
Definition Tweester.c:313
#define PM_CC_ALT_INTERFERENCE
Definition macros.h:380
#define DEG_TO_RAD(deg)
Definition macros.h:138
#define PTR_LIST_END
Definition macros.h:42
void(* renderSetupFunc)(s32)
EntityData dataBuf
Vec3f scale
s32 flags
Entity * TweesterTouchingPartner
Definition 7B440.c:5
PartnerStatus gPartnerStatus
Definition partners.c:42
Camera gCameras[4]
Definition cam_main.c:17
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
Entity * TweesterTouchingPlayer
Definition 7B440.c:6
DisplayContext * gDisplayContext
Definition cam_main.c:16