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
24
26 Entity* entity = get_entity_by_index(entityIndex);
27 TweesterData* data = entity->dataBuf.tweester;
28 Matrix4f sp18;
29 Matrix4f sp58;
30 Gfx* gfx;
31
32 guMtxL2F(sp18, ENTITY_ADDR(entity, Mtx*, &Entity_Tweester_mtxInnerWhirl));
33 guRotateF(sp58, data->innerWhirlRotY, 0.0f, 1.0f, 0.0f);
34 guMtxCatF(sp58, sp18, sp18);
35 guMtxF2L(sp18, &data->mtxInnerWhirl);
37 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
39 gSPDisplayList(gMainGfxPos++, gfx);
40 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
41}
42
44 Entity* entity = get_entity_by_index(entityIndex);
45 TweesterData* data = entity->dataBuf.tweester;
46 Matrix4f sp18;
47 Matrix4f sp58;
48 Gfx* gfx;
49
50 guMtxL2F(sp18, ENTITY_ADDR(entity, Mtx*, &Entity_Tweester_mtxOuterWhirl));
51 guRotateF(sp58, data->outerWhirlRotY, 0.0f, 1.0f, 0.0f);
52 guMtxCatF(sp58, sp18, sp18);
53 guMtxF2L(sp18, &data->mtxOuterWhirl);
55 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
57 gSPDisplayList(gMainGfxPos++, gfx);
58 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
59}
60
61void entity_Tweester_render_face(s32 entityIndex) {
62 Entity* entity = get_entity_by_index(entityIndex);
63 TweesterData* data = entity->dataBuf.tweester;
64
65 gDPPipeSync(gMainGfxPos++);
66 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
67 gDPLoadTLUT_pal16(gMainGfxPos++, 0, D_0A0018A0_E58700);
68 gSPTexture(gMainGfxPos++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
69 gDPSetCombineMode(gMainGfxPos++, G_CC_MODULATEIA, G_CC_MODULATEIA);
70 gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
71 gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
72 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);
73 gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
74 gDPSetTextureFilter(gMainGfxPos++, G_TF_BILERP);
75 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->faceAnimTexOffset * 4, 0, (data->faceAnimTexOffset + 124) * 4, 31 * 4);
76}
77
78void entity_Tweester_setupGfx(s32 entityIndex) {
79 Entity* entity = get_entity_by_index(entityIndex);
80 TweesterData* data = entity->dataBuf.tweester;
81
82 gDPPipeSync(gMainGfxPos++);
83 gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
84 gSPTexture(gMainGfxPos++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON);
85 gDPSetCombineMode(gMainGfxPos++, PM_CC_ALT_INTERFERENCE, G_CC_MODULATEIA2);
86 gDPSetTextureDetail(gMainGfxPos++, G_TD_CLAMP);
87 gDPSetTextureLOD(gMainGfxPos++, G_TL_TILE);
88 gDPSetTextureImage(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 32, D_0A000BF0_E57A50);
89 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);
90 gDPLoadSync(gMainGfxPos++);
91 gDPLoadTile(gMainGfxPos++, G_TX_LOADTILE, 0, 0, 0x007C, 0x007C);
92 gDPPipeSync(gMainGfxPos++);
93 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);
94 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, 0, 0, 0x007C, 0x007C);
95 gDPSetTextureImage(gMainGfxPos++, G_IM_FMT_I, G_IM_SIZ_8b, 32, D_0A000FF0_E57E50);
96 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);
97 gDPLoadSync(gMainGfxPos++);
98 gDPLoadTile(gMainGfxPos++, G_TX_LOADTILE, 0, 0, 0x007C, 0x007C);
99 gDPPipeSync(gMainGfxPos++);
100 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);
101 gDPSetTileSize(gMainGfxPos++, 1, 0, 0, 0x007C, 0x007C);
102 gDPSetTexturePersp(gMainGfxPos++, G_TP_PERSP);
103 gDPSetTextureFilter(gMainGfxPos++, G_TF_BILERP);
104 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->innerWhirlTexOffsetX, data->innerWhirlTexOffsetY, data->innerWhirlTexOffsetX + 124, data->innerWhirlTexOffsetY + 124);
106 gDPPipeSync(gMainGfxPos++);
107 gDPSetTileSize(gMainGfxPos++, G_TX_RENDERTILE, data->outerWhirlTexOffsetX, data->outerWhirlTexOffsetY, data->outerWhirlTexOffsetX + 124, data->outerWhirlTexOffsetY + 124);
109 entity_Tweester_render_face(entityIndex);
110}
111
112
114 TweesterData* data = entity->dataBuf.tweester;
115 s32 i;
116
117 data->faceAnimTimer--;
118 if (data->faceAnimTimer <= 0) {
119 i = data->faceAnimState;
120 if (Entity_Tweester_FaceAnimationData[i] == 255) {
121 i = 0;
122 }
125 data->faceAnimState = i;
126 }
127}
128
130 TweesterData* data = entity->dataBuf.tweester;
131 s32 count = 0;
132 f32 deltaX = fabsf(data->targetX - entity->pos.x);
133 f32 deltaZ = fabsf(data->targetZ - entity->pos.z);
134
135 if (deltaX <= 10.0f) {
136 count++;
137 }
138 if (deltaZ <= 10.0f) {
139 count++;
140 }
141
142 return count >= 2;
143}
144
146 TweesterData* data = entity->dataBuf.tweester;
147 s32 pathOffset;
148 s32** paths;
149 s32 i, j;
150 s32* pathPtr;
151
152 pathOffset = data->pathOffset;
153 paths = data->paths;
154
155 if (pathOffset == 0) {
156 for (i = 0; *paths != PTR_LIST_END; paths++, i++) {
157 }
158 j = rand_int(i * 10 - 1) / 10;
159 paths = data->paths;
160 data->curPath = paths[j];
161 }
162 pathPtr = &data->curPath[pathOffset];
163 if (*pathPtr != TWEESTER_PATH_STOP) {
164 pathOffset += 3;
165 if (*pathPtr == TWEESTER_PATH_LOOP){
166 pathOffset = 0;
167 pathPtr = data->curPath;
168 data->targetX = *pathPtr++;
169 data->targetY = *pathPtr++;
170 data->targetZ = *pathPtr++;
171 } else {
172 data->targetX = *pathPtr++;
173 data->targetY = *pathPtr++;
174 data->targetZ = *pathPtr++;
175 }
176 }
177 data->pathOffset = pathOffset;
178}
179
181 TweesterData* data = entity->dataBuf.tweester;
182 f32 yawRad;
183
184 f32 temp_f4 = (atan2(entity->pos.x, entity->pos.z, data->targetX, data->targetZ) - data->yaw) * 0.03125f;
185 if (temp_f4 >= 0.0f && temp_f4 < 0.01) {
186 temp_f4 = 0.01f;
187 }
188 if (temp_f4 < 0.0f && temp_f4 > -0.01) {
189 temp_f4 = -0.01f;
190 }
191
192 data->yaw = clamp_angle(data->yaw + temp_f4);
193 yawRad = DEG_TO_RAD(data->yaw);
194 entity->pos.x += sin_rad(yawRad);
195 entity->pos.z -= cos_rad(yawRad);
196
199 }
200}
201
203 PlayerStatus* playerStatus = &gPlayerStatus;
204 PartnerStatus* partnerStatus = &gPartnerStatus;
205 PlayerData* playerData = &gPlayerData;
206 TweesterData* data = entity->dataBuf.tweester;
207 f32 delta;
208 f32 targetRotationSpeed;
209
212 !(playerStatus->flags & PS_FLAG_PAUSED) &&
213 (playerData->curPartner != PARTNER_GOOMBARIO ||
214 playerStatus->inputDisabledCount == 0 ||
216 )) {
217 entity_Tweester_move(entity);
218 }
219
221 data->frameCounter++;
222
223 if (data->frameCounter < 100) {
224 targetRotationSpeed = 3.5f;
225 delta = (targetRotationSpeed - data->rotSpeed) / 28.0f;
226 if (delta < 0.02) {
227 delta = 0.02f;
228 }
229 data->rotSpeed += delta;
230 if (data->rotSpeed >= targetRotationSpeed){
231 data->rotSpeed = targetRotationSpeed;
232 }
233 } else {
234 targetRotationSpeed = 1.3f;
235 delta = (targetRotationSpeed - data->rotSpeed) * 0.0625f;
236 if (delta > -0.02) {
237 delta = -0.02f;
238 }
239 data->rotSpeed += delta;
240 if (data->rotSpeed <= targetRotationSpeed){
241 data->rotSpeed = targetRotationSpeed;
242 data->frameCounter = 0;
243 }
244 }
245
246 data->innerWhirlRotY += data->rotSpeed;
247 if (data->innerWhirlRotY > 360.0f) {
248 data->innerWhirlRotY = 0.0f;
249 }
250
251 delta = data->innerWhirlRotY - data->outerWhirlRotY;
252 if (delta < 0.0f) {
253 delta += 360.0f;
254 }
255 delta *= 0.25;
256 data->outerWhirlRotY += delta;
257 if (data->outerWhirlRotY > 360.0f) {
258 data->outerWhirlRotY = 0.0f;
259 }
260
261 data->innerWhirlTexOffsetX += 4;
262 data->innerWhirlTexOffsetY -= 8;
263 data->outerWhirlTexOffsetX += 4;
264 data->outerWhirlTexOffsetY -= 16;
265
266 entity->rot.y = -gCameras[CAM_DEFAULT].curYaw;
267
268 if (partnerStatus->partnerActionState == PARTNER_ACTION_NONE || partnerStatus->actingPartner != PARTNER_BOW) {
269 if (playerStatus->actionState == ACTION_STATE_USE_TWEESTER) {
270 Npc* npc = npc_find_closest_simple(entity->pos.x, entity->pos.y, entity->pos.z, 50.0f);
271 if (npc != NULL && (npc->flags & NPC_FLAG_PARTNER)) {
273 }
274 }
275
276 if (!is_picking_up_item() &&
277 !(playerStatus->flags & PS_FLAG_PAUSED) &&
278 playerStatus->actionState != ACTION_STATE_USE_TWEESTER &&
279 playerStatus->blinkTimer == 0 &&
280 fabs(dist2D(entity->pos.x, entity->pos.z, playerStatus->pos.x, playerStatus->pos.z)) <= 50.0
281 ) {
282 TweesterTouchingPlayer = entity;
285 }
286 }
287}
288
290 entity->scale.x += 0.1;
291 if (entity->scale.x >= 1.0) {
292 entity->scale.x = 1.0f;
293 }
294 entity->scale.z = entity->scale.y = entity->scale.x;
295}
296
298 TweesterData* data = entity->dataBuf.tweester;
299
300 data->paths = (s32**)CreateEntityVarArgBuffer[0];
302 data->faceAnimTexOffset = 0;
304 entity->scale.x = 0;
305 entity->scale.y = 0;
306 entity->scale.z = 0;
307}
308
314
316
319 .typeDataSize = sizeof(TweesterData),
320 .renderCommandList = Entity_Tweester_RenderScript,
321 .modelAnimationNodes = 0,
322 .fpInit = entity_Tweester_init,
323 .updateEntityScript = Entity_Tweester_Script,
324 .fpHandleCollision = NULL,
325 { .dma = ENTITY_ROM(Tweester) },
326 .entityType = ENTITY_TYPE_TWEESTER,
327 .aabbSize = { 50, 70, 50 }
328};
329
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:717
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
s32 is_picking_up_item(void)
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
f32 sin_rad(f32 x)
Definition 43F0.c:713
s32 get_time_freeze_mode(void)
Definition main_loop.c:390
Mtx Entity_Tweester_mtxInnerWhirl
Definition Tweester.c:51
Mtx Entity_Tweester_mtxOuterWhirl
Definition Tweester.c:58
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:1995
Gfx Entity_Tweester_Render[]
Definition Tweester.c:225
void entity_Tweester_update_face_anim(Entity *entity)
Definition Tweester.c:113
void entity_Tweester_idle(Entity *entity)
Definition Tweester.c:202
unsigned char D_0A000FF0_E57E50[]
void entity_Tweester_render_inner_whirl(s32 entityIndex)
Definition Tweester.c:25
unsigned char D_0A0014A0_E58300[]
u8 Entity_Tweester_FaceAnimationData[]
Definition Tweester.c:5
void entity_Tweester_render_face(s32 entityIndex)
Definition Tweester.c:61
unsigned char D_0A0018A0_E58700[]
void entity_Tweester_render_outer_whirl(s32 entityIndex)
Definition Tweester.c:43
EntityScript Entity_Tweester_Script
Definition Tweester.c:309
Gfx Entity_Tweester_RenderOuterWhirl[]
Definition Tweester.c:122
void entity_Tweester_select_target_point(Entity *entity)
Definition Tweester.c:145
s32 entity_Tweester_has_reached_target(Entity *entity)
Definition Tweester.c:129
unsigned char D_0A000BF0_E57A50[]
Gfx Entity_Tweester_RenderInnerWhirl[]
Definition Tweester.c:177
EntityBlueprint Entity_Tweester
Definition Tweester.c:317
void entity_Tweester_setupGfx(s32 entityIndex)
Definition Tweester.c:78
void entity_Tweester_init(Entity *entity)
Definition Tweester.c:297
void entity_Tweester_move(Entity *entity)
Definition Tweester.c:180
void entity_Tweester_anim_scale(Entity *entity)
Definition Tweester.c:289
EntityModelScript Entity_Tweester_RenderScript
Definition Tweester.c:315
#define PM_CC_ALT_INTERFERENCE
Definition macros.h:376
#define DEG_TO_RAD(deg)
Definition macros.h:134
#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