Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
npc_api.c
Go to the documentation of this file.
1#include "common.h"
2#include "npc.h"
3#include "world/partners.h"
4
5extern s32 wExtraPartnerID;
6extern s32 wExtraPartnerNpcID;
7
8Npc* resolve_npc(Evt* script, s32 npcIdOrPtr) {
9 if (npcIdOrPtr == NPC_SELF) {
10 return get_npc_safe(script->owner2.npcID);
11 } else if (npcIdOrPtr >= EVT_LIMIT) {
12 return get_npc_safe(npcIdOrPtr);
13 } else {
14 return (Npc*) npcIdOrPtr;
15 }
16}
17
18void set_npc_animation(Npc* npc, u32 animID) {
19 PlayerData* playerData = &gPlayerData;
20
21 if (PARTNER_ANIM_STILL <= animID && animID <= PARTNER_ANIM_HURT) {
22 npc->curAnim = gPartnerAnimations[playerData->curPartner].anims[animID - PARTNER_ANIM_STILL];
23 } else if (ENEMY_ANIM_IDLE <= animID && animID <= ENEMY_ANIM_F) {
24 npc->curAnim = get_enemy(npc->npcID)->animList[animID - ENEMY_ANIM_IDLE];
25 } else {
26 npc->curAnim = animID;
27 }
28}
29
30API_CALLABLE(CreateNpc) {
31 Bytecode* args = script->ptrReadPos;
32 s32 npcID = evt_get_variable(script, *args++);
33 s32 initialAnim = evt_get_variable(script, *args++);
34 NpcBlueprint blueprint;
35 Npc *npc;
36
37 blueprint.flags = 0;
38 blueprint.initialAnim = initialAnim;
39 blueprint.onUpdate = NULL;
40 blueprint.onRender = NULL;
41
42 npc = get_npc_by_index(create_basic_npc(&blueprint));
43 npc->npcID = npcID;
45 return ApiStatus_DONE2;
46}
47
48API_CALLABLE(DeleteNpc) {
49 Bytecode* args = script->ptrReadPos;
50 Npc* npc = get_npc_unsafe(evt_get_variable(script, *args++));
51
52 if (npc == NULL) {
53 return ApiStatus_DONE2;
54 }
55
56 free_npc(npc);
57 return ApiStatus_DONE2;
58}
59
60API_CALLABLE(GetNpcPointer) {
61 Bytecode* args = script->ptrReadPos;
62 s32 npcID = evt_get_variable(script, *args++);
63 Bytecode varNPC = *args++;
64
65 evt_set_variable(script, varNPC, (s32)get_npc_safe(npcID));
66 return ApiStatus_DONE2;
67}
68
69API_CALLABLE(SetNpcPos) {
70 Bytecode* args = script->ptrReadPos;
71 s32 npcID = evt_get_variable(script, *args++);
72 f32 x = evt_get_variable(script, *args++);
73 f32 y = evt_get_variable(script, *args++);
74 f32 z = evt_get_variable(script, *args++);
75 Npc* npc = resolve_npc(script, npcID);
76
77 if (npc == NULL) {
78 return ApiStatus_DONE2;
79 }
80
81 npc->pos.x = x;
82 npc->pos.y = y;
83 npc->pos.z = z;
84 npc->colliderPos.x = npc->pos.x;
85 npc->colliderPos.y = npc->pos.y;
86 npc->colliderPos.z = npc->pos.z;
88
89 return ApiStatus_DONE2;
90}
91
92API_CALLABLE(SetNpcRotation) {
93 Bytecode* args = script->ptrReadPos;
94 s32 npcID = evt_get_variable(script, *args++);
95 f32 rotX = evt_get_float_variable(script, *args++);
96 f32 rotY = evt_get_float_variable(script, *args++);
97 f32 rotZ = evt_get_float_variable(script, *args++);
98 Npc* npc = resolve_npc(script, npcID);
99
100 if (npc == NULL) {
101 return ApiStatus_DONE2;
102 }
103
104 npc->rot.x = rotX;
105 npc->rot.y = rotY;
106 npc->rot.z = rotZ;
107 return ApiStatus_DONE2;
108}
109
110API_CALLABLE(SetNpcRotationPivot) {
111 Bytecode* args = script->ptrReadPos;
112 s32 npcId = evt_get_variable(script, *args++);
113 f32 value = evt_get_float_variable(script, *args++);
114 Npc* npc;
115
116 npc = resolve_npc(script, npcId);
117 if (npc == NULL) {
118 return ApiStatus_DONE2;
119 }
120
121 npc->rotPivotOffsetY = value;
122 return ApiStatus_DONE2;
123}
124
125API_CALLABLE(SetNpcScale) {
126 Bytecode* ptrReadPos = script->ptrReadPos;
127 s32 npcID = evt_get_variable(script, *ptrReadPos++);
128 f32 scaleX = evt_get_float_variable(script, *ptrReadPos++);
129 f32 scaleY = evt_get_float_variable(script, *ptrReadPos++);
130 f32 scaleZ = evt_get_float_variable(script, *ptrReadPos++);
131 Npc* npc = resolve_npc(script, npcID);
132
133 if (npc == NULL) {
134 return ApiStatus_DONE2;
135 }
136
137 npc->scale.x = scaleX;
138 npc->scale.y = scaleY;
139 npc->scale.z = scaleZ;
140 return ApiStatus_DONE2;
141}
142
143API_CALLABLE(SetNpcCollisionSize) {
144 Bytecode* ptrReadPos = script->ptrReadPos;
145 s32 npcID = evt_get_variable(script, *ptrReadPos++);
146 s32 height = evt_get_variable(script, *ptrReadPos++);
147 s32 radius = evt_get_variable(script, *ptrReadPos++);
148 Npc* npc = resolve_npc(script, npcID);
149
150 if (npc == NULL) {
151 return ApiStatus_DONE2;
152 }
153
154 npc->collisionHeight = height;
155 npc->collisionDiameter = radius;
156 return ApiStatus_DONE2;
157}
158
159API_CALLABLE(SetNpcSpeed) {
160 Bytecode* ptrReadPos = script->ptrReadPos;
161 s32 npcID = evt_get_variable(script, *ptrReadPos++);
162 f32 speed = evt_get_float_variable(script, *ptrReadPos);
163 Npc* npc = resolve_npc(script, npcID);
164
165 if (npc == NULL) {
166 return ApiStatus_DONE2;
167 }
168
169 npc->moveSpeed = speed;
170 return ApiStatus_DONE2;
171}
172
173API_CALLABLE(SetNpcJumpscale) {
174 Bytecode* ptrReadPos = script->ptrReadPos;
175 s32 npcID = evt_get_variable(script, *ptrReadPos++);
176 f32 jumpScale = evt_get_float_variable(script, *ptrReadPos);
177 Npc* npc = resolve_npc(script, npcID);
178
179 if (npc == NULL) {
180 return ApiStatus_DONE2;
181 }
182
183 npc->jumpScale = jumpScale;
184 return ApiStatus_DONE2;
185}
186
187API_CALLABLE(SetNpcAnimation) {
188 Bytecode* ptrReadPos = script->ptrReadPos;
189 s32 npcID = evt_get_variable(script, *ptrReadPos++);
190 s32 animation = evt_get_variable(script, *ptrReadPos);
191 Npc* npc = resolve_npc(script, npcID);
192
193 if (npc == NULL) {
194 return ApiStatus_DONE2;
195 }
196
197 set_npc_animation(npc, animation);
198 return ApiStatus_DONE2;
199}
200
201API_CALLABLE(GetNpcAnimation) {
202 Bytecode* ptrReadPos = script->ptrReadPos;
203 s32 npcID = evt_get_variable(script, *ptrReadPos++);
204 Bytecode outVar = *ptrReadPos++;
205 Npc* npc = resolve_npc(script, npcID);
206
207 if (npc == NULL) {
208 return ApiStatus_DONE2;
209 }
210
211 evt_set_variable(script, outVar, npc->curAnim);
212 return ApiStatus_DONE2;
213}
214
215API_CALLABLE(SetNpcAnimationSpeed) {
216 Bytecode* ptrReadPos = script->ptrReadPos;
217 s32 npcID = evt_get_variable(script, *ptrReadPos++);
218 f32 animationSpeed = evt_get_float_variable(script, *ptrReadPos++);
219 Npc* npc = resolve_npc(script, npcID);
220
221 if (npc == NULL) {
222 return ApiStatus_DONE2;
223 }
224
225 npc->animationSpeed = animationSpeed;
226 return ApiStatus_DONE2;
227}
228
229API_CALLABLE(NpcMoveTo) {
230 Bytecode* args = script->ptrReadPos;
231 Npc* npc;
232 f32 dist;
233 f32 moveSpeed;
234
235 if (isInitialCall) {
236 script->functionTemp[0] = 0;
237 }
238
239 if (script->functionTemp[0] == 0) {
240 s32 npcID = evt_get_variable(script, *args++);
241 f32 goalX = evt_get_variable(script, *args++);
242 f32 goalZ = evt_get_variable(script, *args++);
243 s32 duration = evt_get_variable(script, *args++);
244
245 npc = resolve_npc(script, npcID);
246 if (npc == NULL) {
247 return ApiStatus_DONE2;
248 }
249
250 script->functionTempPtr[1] = npc;
251 npc->moveToPos.x = goalX;
252 npc->moveToPos.z = goalZ;
253 npc->duration = duration;
254 dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
255
256 if (npc->duration == 0) {
257 npc->duration = dist / npc->moveSpeed;
258 } else {
259 npc->moveSpeed = dist / npc->duration;
260 }
261 if (npc->duration == 0) {
262 npc->duration = 1;
263 }
264 script->functionTemp[0] = 1;
265 }
266
267 npc = script->functionTempPtr[1];
268 npc->yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
269 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
270
271 if (npc->moveSpeed < 4.0) {
273 } else {
275 }
276
277 dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
278
279 moveSpeed = npc->moveSpeed;
280 if (moveSpeed < 1.0) {
281 moveSpeed = 1.0f;
282 }
283
284 if (dist <= moveSpeed) {
285 return ApiStatus_DONE1;
286 }
287 return ApiStatus_BLOCK;
288}
289
290ApiStatus _npc_jump_to(Evt* script, s32 isInitialCall, s32 snapYaw) {
291 Bytecode* args = script->ptrReadPos;
292 f32* yaw = &script->functionTempF[2];
293 Npc* npc;
294
295 if (isInitialCall) {
296 script->functionTemp[0] = 0;
297 }
298
299 if (script->functionTemp[0] == 0) {
300 s32 npcID = evt_get_variable(script, *args++);
301 f32 goalX = evt_get_variable(script, *args++);
302 f32 goalY = evt_get_variable(script, *args++);
303 f32 goalZ = evt_get_variable(script, *args++);
304 s32 duration = evt_get_variable(script, *args++);
305 f32 dist;
306
307 npc = resolve_npc(script, npcID);
308
309 if (npc == NULL) {
310 return ApiStatus_DONE2;
311 }
312
313 script->functionTempPtr[1] = npc;
314 npc->moveToPos.x = goalX;
315 npc->moveToPos.y = goalY;
316 npc->moveToPos.z = goalZ;
317
318 npc->duration = duration;
319 dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
320 *yaw = 0.0f;
321 if (dist > 2.0) {
322 *yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
323 if (snapYaw == 0) {
324 npc->yaw = *yaw;
325 }
326 }
327
328 goalY = npc->moveToPos.y - npc->pos.y;
329
330 if (npc->duration == 0) {
331 npc->duration = dist / npc->moveSpeed;
332 } else {
333 npc->moveSpeed = dist / npc->duration;
334 }
335
336 npc->flags |= NPC_FLAG_JUMPING;
337 npc->jumpVel = (npc->jumpScale * npc->duration * 0.5f) + (goalY / npc->duration);
338 script->functionTemp[0] =1;
339 }
340
341 npc = script->functionTempPtr[1];
342 npc_move_heading(npc, npc->moveSpeed, *yaw);
343
344 npc->pos.y += npc->jumpVel;
345 npc->jumpVel -= npc->jumpScale;
346
347 npc->duration--;
348 if (npc->duration < 0) {
349 npc->jumpVel = 0.0f;
350 npc->pos.x = npc->moveToPos.x;
351 npc->pos.y = npc->moveToPos.y;
352 npc->pos.z = npc->moveToPos.z;
353 npc->flags &= ~NPC_FLAG_JUMPING;
355 return ApiStatus_DONE1;
356 }
357 return ApiStatus_BLOCK;
358}
359
360API_CALLABLE(NpcJump0) {
361 return _npc_jump_to(script, isInitialCall, 0);
362}
363
364API_CALLABLE(NpcJump1) {
365 return _npc_jump_to(script, isInitialCall, 1);
366}
367
368API_CALLABLE(NpcFlyTo) {
369 Bytecode* args = script->ptrReadPos;
370 f32* outX = (f32*)&script->varTable[3];
371 f32* outY = (f32*)&script->varTable[4];
372 f32* outZ = (f32*)&script->varTable[5];
373 Npc* npc;
374 f32 dist;
375 f32 yDelta;
376
377 if (isInitialCall) {
378 npc = resolve_npc(script, evt_get_variable(script, *args++));
379 if (npc == NULL) {
380 return ApiStatus_DONE2;
381 }
382
383 script->functionTempPtr[1] = npc;
384 npc->moveToPos.x = evt_get_float_variable(script, *args++);
385 npc->moveToPos.y = evt_get_float_variable(script, *args++);
386 npc->moveToPos.z = evt_get_float_variable(script, *args++);
387 script->varTable[6] = evt_get_variable(script, *args++);
388 script->functionTemp[2] = evt_get_variable(script, *args++);
389 script->functionTemp[3] = evt_get_variable(script, *args++);
390 npc->duration = 0;
391 *outX = npc->pos.x;
392 *outY = npc->pos.y;
393 *outZ = npc->pos.z;
394 npc->yaw = atan2(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
395 dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
396 npc->planarFlyDist = dist;
397
398 if (script->varTable[6] == 0) {
399 script->varTable[6] = (dist / npc->moveSpeed);
400 } else {
401 npc->moveSpeed = dist / script->varTable[6];
402 }
403 }
404
405 npc = script->functionTempPtr[1];
406 npc->pos.x = update_lerp(script->functionTemp[3], *outX, npc->moveToPos.x, npc->duration, script->varTable[6]);
407 npc->pos.y = update_lerp(script->functionTemp[3], *outY, npc->moveToPos.y, npc->duration, script->varTable[6]);
408 npc->pos.z = update_lerp(script->functionTemp[3], *outZ, npc->moveToPos.z, npc->duration, script->varTable[6]);
409
410 npc->duration++;
411 if (npc->duration >= script->varTable[6]) {
412 npc->pos.x = npc->moveToPos.x;
413 npc->pos.y = npc->moveToPos.y;
414 npc->pos.z = npc->moveToPos.z;
415 return ApiStatus_DONE2;
416 }
417
418 dist = dist2D(npc->pos.x, npc->pos.z, npc->moveToPos.x, npc->moveToPos.z);
419 if (dist == 0.0f) {
420 dist = 1.0f;
421 }
422 if (npc->planarFlyDist == 0.0f) {
423 npc->planarFlyDist = 1.0f;
424 }
425
426 yDelta = sin_deg((1.0 - (dist / npc->planarFlyDist)) * 180.0);
427 if (script->functionTemp[2] == 0) {
428 yDelta = 0.0f;
429 }
430 if (script->functionTemp[2] < 0) {
431 yDelta = -yDelta * -script->functionTemp[2];
432 }
433 if (script->functionTemp[2] > 0) {
434 yDelta *= script->functionTemp[2];
435 }
436 npc->pos.y += yDelta;
437 return ApiStatus_BLOCK;
438}
439
440API_CALLABLE(GetNpcYaw) {
441 Bytecode* ptrReadPos = script->ptrReadPos;
442 s32 npcID = evt_get_variable(script, *ptrReadPos++);
443 Bytecode outVar = *ptrReadPos++;
444 Npc* npc = resolve_npc(script, npcID);
445
446 if (npc == NULL) {
447 return ApiStatus_DONE2;
448 }
449
450 evt_set_variable(script, outVar, clamp_angle(npc->yaw));
451 return ApiStatus_DONE2;
452}
453
454API_CALLABLE(SetNpcYaw) {
455 Bytecode* ptrReadPos = script->ptrReadPos;
456 s32 npcID = evt_get_variable(script, *ptrReadPos++);
457 Npc* npc = resolve_npc(script, npcID);
458
459 if (npc == NULL) {
460 return ApiStatus_DONE2;
461 }
462
463 set_npc_yaw(npc, evt_get_variable(script, *ptrReadPos++));
464 return ApiStatus_DONE2;
465}
466
467API_CALLABLE(InterpNpcYaw) {
468 PlayerStatus* playerStatus = &gPlayerStatus;
469 Bytecode* args = script->ptrReadPos;
470 f32* initialYaw = &script->functionTempF[1];
471 f32* deltaYaw = &script->functionTempF[2];
472 s32* turnTime = &script->functionTemp[3];
473 Npc* npc;
474
475 if (isInitialCall) {
476 s32 npcID = evt_get_variable(script, *args++);
477
478 npc = resolve_npc(script, npcID);
479 if (npc == NULL) {
480 return ApiStatus_DONE2;
481 }
482
483 *initialYaw = npc->yaw;
484 *deltaYaw = evt_get_variable(script, *args++) - *initialYaw;
485 script->functionTempPtr[0] = npc;
486 *turnTime = evt_get_variable(script, *args++);
487
488 if (*turnTime == 0) {
489 npc->yaw += *deltaYaw;
490 return ApiStatus_DONE2;
491 }
492
493 npc->duration = 0;
494
495 if (*deltaYaw < -180.0f) {
496 *deltaYaw += 360.0f;
497 }
498 if (*deltaYaw > 180.0f) {
499 *deltaYaw -= 360.0f;
500 }
501 }
502
503 npc = script->functionTempPtr[0];
504 if (*turnTime > 0) {
505 npc->duration++;
506 npc->yaw = *initialYaw + ((*deltaYaw * npc->duration) / *turnTime);
507 npc->yaw = clamp_angle(npc->yaw);
508 return !(npc->duration < *turnTime) * ApiStatus_DONE1;
509 }
510
511 npc->yaw += *deltaYaw;
512 return ApiStatus_DONE2;
513}
514
515API_CALLABLE(NpcFacePlayer) {
516 PlayerStatus* playerStatus = &gPlayerStatus;
517 Bytecode* args = script->ptrReadPos;
518 f32* initialYaw = &script->functionTempF[1];
519 f32* deltaYaw = &script->functionTempF[2];
520 s32* turnTime = &script->functionTemp[3];
521 Npc* npc;
522
523 if (isInitialCall) {
524 s32 npcID = evt_get_variable(script, *args++);
525
526 npc = resolve_npc(script, npcID);
527 if (npc == NULL) {
528 return ApiStatus_DONE2;
529 }
530
531 *initialYaw = npc->yaw;
532 *deltaYaw = atan2(npc->pos.x, npc->pos.z, playerStatus->pos.x, playerStatus->pos.z) - *initialYaw;
533 script->functionTempPtr[0] = npc;
534 *turnTime = evt_get_variable(script, *args++);
535 npc->duration = 0;
536
537 if (*deltaYaw < -180.0f) {
538 *deltaYaw += 360.0f;
539 }
540 if (*deltaYaw > 180.0f) {
541 *deltaYaw -= 360.0f;
542 }
543 }
544
545 npc = script->functionTempPtr[0];
546 if (*turnTime > 0) {
547 npc->duration++;
548 npc->yaw = *initialYaw + ((*deltaYaw * npc->duration) / *turnTime);
549 npc->yaw = clamp_angle(npc->yaw);
550 return !(npc->duration < *turnTime) * ApiStatus_DONE1;
551 }
552
553 npc->yaw += *deltaYaw;
554 return ApiStatus_DONE2;
555}
556
557API_CALLABLE(NpcFaceNpc) {
558 Bytecode* args = script->ptrReadPos;
559 f32* initialYaw = &script->functionTempF[1];
560 f32* deltaYaw = &script->functionTempF[2];
561 s32* turnTime = &script->functionTemp[3];
562 Npc* targetNpc;
563 Npc* turningNpc;
564
565 if (isInitialCall) {
566 s32 turningNpcID = evt_get_variable(script, *args++);
567 s32 targetNpcID = evt_get_variable(script, *args++);
568
569 targetNpc = resolve_npc(script, targetNpcID);
570 if (targetNpc == NULL) {
571 return ApiStatus_DONE2;
572 }
573
574 turningNpc = resolve_npc(script, turningNpcID);
575 if (turningNpc == NULL) {
576 return ApiStatus_DONE2;
577 }
578
579 *initialYaw = turningNpc->yaw;
580 *deltaYaw = atan2(turningNpc->pos.x, turningNpc->pos.z, targetNpc->pos.x, targetNpc->pos.z) - *initialYaw;
581 script->functionTempPtr[0] = turningNpc;
582 *turnTime = evt_get_variable(script, *args++);
583 turningNpc->duration = 0;
584
585 if (*deltaYaw < -180.0f) {
586 *deltaYaw += 360.0f;
587 }
588 if (*deltaYaw > 180.0f) {
589 *deltaYaw -= 360.0f;
590 }
591 }
592
593 turningNpc = script->functionTempPtr[0];
594 if (*turnTime > 0) {
595 turningNpc->duration++;
596 turningNpc->yaw = *initialYaw + ((*deltaYaw * turningNpc->duration) / *turnTime);
597 turningNpc->yaw = clamp_angle(turningNpc->yaw);
598 return !(turningNpc->duration < *turnTime) * ApiStatus_DONE1;
599 }
600
601 turningNpc->yaw += *deltaYaw;
602 return ApiStatus_DONE2;
603}
604
605API_CALLABLE(SetNpcFlagBits) {
606 Bytecode* args = script->ptrReadPos;
607 s32 npcID = evt_get_variable(script, *args++);
608 s32 bits = *args++;
609 s32 mode = evt_get_variable(script, *args++);
610 Npc* npc = resolve_npc(script, npcID);
611
612 if (npc == NULL) {
613 return ApiStatus_DONE2;
614 }
615
616 if (mode) {
617 npc->flags |= bits;
618 } else {
619 npc->flags &= ~bits;
620 }
621
622 return ApiStatus_DONE2;
623}
624
625API_CALLABLE(GetNpcPos) {
626 Bytecode* args = script->ptrReadPos;
627 s32 npcID = evt_get_variable(script, *args++);
628 s32 outX = *args++;
629 s32 outY = *args++;
630 s32 outZ = *args++;
631 Npc* npc = resolve_npc(script, npcID);
632
633 if (npc == NULL) {
634 return ApiStatus_DONE2;
635 }
636
637 evt_set_variable(script, outX, npc->pos.x);
638 evt_set_variable(script, outY, npc->pos.y);
639 evt_set_variable(script, outZ, npc->pos.z);
640 return ApiStatus_DONE2;
641}
642
643API_CALLABLE(SetNpcCollisionChannel) {
644 Bytecode* args = script->ptrReadPos;
645 s32 npcID = evt_get_variable(script, *args++);
646 Bytecode channel = *args;
647 Npc* npc = resolve_npc(script, npcID);
648
649 if (npc == NULL) {
650 return ApiStatus_DONE2;
651 }
652
653 npc->collisionChannel = channel;
654 return ApiStatus_DONE2;
655}
656
657API_CALLABLE(SetNpcSprite) {
658 Bytecode* args = script->ptrReadPos;
659 s32 npcID = evt_get_variable(script, *args++);
660 Bytecode animID = *args;
661 Npc* npc = resolve_npc(script, npcID);
662
663 if (npc == NULL) {
664 return ApiStatus_DONE2;
665 }
666
667 set_npc_sprite(npc, animID, NULL);
668 return ApiStatus_DONE2;
669}
670
671API_CALLABLE(EnableNpcShadow) {
672 Bytecode* ptrReadPos = script->ptrReadPos;
673 s32 npcID = evt_get_variable(script, *ptrReadPos++);
674 s32 enableShadow = evt_get_variable(script, *ptrReadPos++);
675 Npc* npc = resolve_npc(script, npcID);
676
677 if (npc == NULL) {
678 return ApiStatus_DONE2;
679 }
680
681 if (enableShadow) {
683 } else {
685 }
686 return ApiStatus_DONE2;
687}
688
689API_CALLABLE(EnableNpcBlur) {
690 Bytecode* ptrReadPos = script->ptrReadPos;
691 s32 npcID = evt_get_variable(script, *ptrReadPos++);
692 s32 enableBlur = evt_get_variable(script, *ptrReadPos++);
693 Npc* npc = resolve_npc(script, npcID);
694
695 if (npc == NULL) {
696 return ApiStatus_DONE2;
697 }
698
699 if (enableBlur) {
700 enable_npc_blur(npc);
701 } else {
702 disable_npc_blur(npc);
703 }
704 return ApiStatus_DONE2;
705}
706
707API_CALLABLE(ClearPartnerMoveHistory) {
708 Bytecode* ptrReadPos = script->ptrReadPos;
709 s32 npcID = evt_get_variable(script, *ptrReadPos++);
710 Npc* npc = resolve_npc(script, npcID);
711
712 if (npc == NULL) {
713 return ApiStatus_DONE2;
714 }
715
717 return ApiStatus_DONE2;
718}
719
720API_CALLABLE(NpcSetHomePosToCurrent) {
721 Npc* npc = resolve_npc(script, evt_get_variable(script, *script->ptrReadPos));
722
723 if (npc == NULL) {
724 return ApiStatus_DONE2;
725 }
726
727 npc->homePos.x = npc->pos.x;
728 npc->homePos.y = npc->pos.y;
729 npc->homePos.z = npc->pos.z;
730 return ApiStatus_DONE2;
731}
732
733API_CALLABLE(GetPartnerPos) {
734 Bytecode* ptrReadPos = script->ptrReadPos;
735 Bytecode posX = *ptrReadPos++;
736 Bytecode posY = *ptrReadPos++;
737 Bytecode posZ = *ptrReadPos++;
739
740 if (npc == NULL) {
741 return ApiStatus_DONE2;
742 }
743
744 evt_set_variable(script, posX, npc->pos.x);
745 evt_set_variable(script, posY, npc->pos.y);
746 evt_set_variable(script, posZ, npc->pos.z);
747 return ApiStatus_DONE2;
748}
749
750API_CALLABLE(DisablePartnerAI) {
751 Bytecode* ptrReadPos = script->ptrReadPos;
752
753 if (evt_get_variable(script, *ptrReadPos++) == 0) {
755 } else {
757 }
758 return ApiStatus_DONE2;
759}
760
761API_CALLABLE(EnablePartnerAI) {
763 return ApiStatus_DONE2;
764}
765
766API_CALLABLE(func_802CF54C) {
768 return ApiStatus_DONE2;
769}
770
771API_CALLABLE(func_802CF56C) {
772 Bytecode* ptrReadPos = script->ptrReadPos;
773 s32 value = evt_get_variable(script, *ptrReadPos++);
774
775 if (value == 2) {
777 } else {
778 func_800EF3D4(value);
779 }
780 return ApiStatus_DONE2;
781}
782
783API_CALLABLE(BringPartnerOut) {
784 Bytecode* args = script->ptrReadPos;
785 NpcBlueprint bp;
786 NpcBlueprint* bpPointer = &bp;
787 PlayerData* playerData = &gPlayerData;
788 PlayerStatus* playerStatus = &gPlayerStatus;
789 Npc* partner;
790 Npc* npc;
791 f32 duration;
792 f32 playerZ;
793 f32 targetZ;
794 f32 playerX;
795 f32 targetX;
796 f32 targetY;
797 f32 playerY;
798
799 if (isInitialCall) {
800 wExtraPartnerID = evt_get_variable(script, *args++);
801 if (playerData->curPartner == wExtraPartnerID) {
802 wExtraPartnerID = 0;
803 return ApiStatus_DONE2;
804 }
805
806 partner = get_npc_unsafe(NPC_PARTNER);
807 partner->npcID = -5;
808
811 bpPointer->onUpdate = NULL;
812 bpPointer->onRender = NULL;
813
816 npc->collisionDiameter = 10;
817 npc->collisionHeight = 10;
818 npc->npcID = NPC_PARTNER;
819 npc->scale.x = 0.0f;
820 npc->scale.y = 0.0f;
821 npc->scale.z = 0.0f;
822
823 npc->moveToPos.x = targetX = partner->pos.x;
824 playerY = playerStatus->pos.y;
825 npc->moveToPos.y = playerStatus->pos.y;
826 npc->moveToPos.z = targetZ = partner->pos.z + 30.0f;
827 npc->pos.x = playerX = playerStatus->pos.x;
828 npc->pos.y = targetY = playerStatus->pos.y + (playerStatus->colliderHeight / 2);
829 playerZ = playerStatus->pos.z;
830 npc->moveSpeed = 4.0f;
831 npc->jumpScale = 1.6f;
832 npc->pos.z = playerZ;
833
834 npc->planarFlyDist = dist2D(playerX, npc->pos.z, targetX, targetZ);
835 npc->yaw = atan2(playerX, playerZ, targetX, targetZ);
836 npc->duration = npc->planarFlyDist / npc->moveSpeed;
837
838 if (npc->duration < 10) {
839 npc->duration = 10;
840 npc->moveSpeed = npc->planarFlyDist / npc->duration;
841 }
842
843 npc->jumpVel = ((playerY - targetY) + (npc->jumpScale * npc->duration * npc->duration * 0.5f)) / npc->duration;
845 return ApiStatus_BLOCK;
846 }
847
849 npc->jumpVel -= npc->jumpScale;
850 npc->pos.y += npc->jumpVel;
851 if (npc->jumpVel <= 0.0f) {
853 }
854 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
855 duration = npc->duration;
856 if (duration > 10.0f) {
857 duration = 10.0f;
858 }
859 npc->scale.x = (10.0f - duration) / 10.0f;
860 npc->scale.y = npc->scale.x;
861 npc->scale.z = npc->scale.x;
862
863 npc->duration--;
864 if (npc->duration < 0) {
866 npc->jumpVel = 0.0f;
867 npc->pos.y = npc->moveToPos.y;
868 npc->scale.x = 1.0f;
869 npc->scale.y = 1.0f;
870 npc->scale.z = 1.0f;
871 npc->yaw = clamp_angle(npc->yaw + 180.0f);
872 return ApiStatus_DONE2;
873 }
874 return ApiStatus_BLOCK;
875}
876
877API_CALLABLE(PutPartnerAway) {
878 Npc* partner = get_npc_unsafe(NPC_PARTNER);
879 PlayerStatus* playerStatus = &gPlayerStatus;
880 f32 scale;
881 f32 targetX;
882 f32 targetY;
883 f32 targetZ;
884 f32 partnerX;
885 f32 partnerY;
886 f32 partnerZ;
887
888 if (isInitialCall) {
889 if (wExtraPartnerID != 0) {
890 partner->flags &= ~NPC_FLAG_GRAVITY;
891 partner->flags &= ~NPC_FLAG_FLYING;
892 targetX = playerStatus->pos.x;
893 partner->moveToPos.x = targetX;
894 partnerX = partner->pos.x;
895 targetY = playerStatus->pos.y + (playerStatus->colliderHeight / 2);
896 partner->moveToPos.y = targetY;
897 partnerY = partner->pos.y;
898 targetZ = playerStatus->pos.z;
899 partner->moveToPos.z = targetZ;
900 partnerZ = partner->pos.z;
901 partner->moveSpeed = 4.0f;
902 partner->jumpScale = 2.6f;
903 partner->planarFlyDist = dist2D(partnerX, partnerZ, targetX, targetZ);
904 partner->yaw = atan2(partnerX, partnerZ, targetX, targetZ);
905 partner->duration = partner->planarFlyDist / partner->moveSpeed;
906
907 if (partner->duration < 10) {
908 partner->duration = 10;
909 partner->moveSpeed = partner->planarFlyDist / partner->duration;
910 }
911
912 partnerY = targetY - partnerY;
913 partner->jumpVel = (partnerY + (partner->jumpScale * partner->duration * partner->duration * 0.5f)) / partner->duration;
915 return ApiStatus_BLOCK;
916 } else {
917 return ApiStatus_DONE2;
918 }
919 }
920
921 partner->jumpVel -= partner->jumpScale;
922 partner->pos.y += partner->jumpVel;
923 if (partner->jumpVel <= 0.0f) {
925 }
926 npc_move_heading(partner, partner->moveSpeed, partner->yaw);
927
928 scale = partner->duration;
929 if (scale > 10.0f) {
930 scale = 10.0f;
931 }
932
933 partner->scale.x = scale / 10.0f;
934 partner->scale.y = partner->scale.x;
935 partner->scale.z = partner->scale.x;
936
937 partner->duration--;
938 if (partner->duration < 0) {
940 partner->jumpVel = 0.0f;
941 partner->pos.y = partner->moveToPos.y;
944 return ApiStatus_DONE2;
945 }
946 return ApiStatus_BLOCK;
947}
948
949API_CALLABLE(GetCurrentPartnerID) {
950 evt_set_variable(script, *script->ptrReadPos, gPlayerData.curPartner);
951 return ApiStatus_DONE2;
952}
953
954API_CALLABLE(PartnerCanUseAbility) {
955 Bytecode outVar = *script->ptrReadPos;
956
957 evt_set_variable(script, outVar, partner_can_use_ability());
958 return ApiStatus_DONE2;
959}
960
961API_CALLABLE(PartnerIsFlying) {
962 Bytecode outVar = *script->ptrReadPos;
963
964 evt_set_variable(script, outVar, partner_is_flying());
965 return ApiStatus_DONE2;
966}
967
968API_CALLABLE(SetNpcImgFXParams) {
969 Bytecode* args = script->ptrReadPos;
970 s32 npcId = evt_get_variable(script, *args++);
971 Bytecode imgfxType = evt_get_variable(script, *args++);
972 Bytecode var2 = evt_get_variable(script, *args++);
973 Bytecode var3 = evt_get_variable(script, *args++);
974 Bytecode var4 = evt_get_variable(script, *args++);
975 Bytecode var5 = evt_get_variable(script, *args++);
976 Npc* npc = resolve_npc(script, npcId);
977
978 if (npc == NULL) {
979 return ApiStatus_DONE2;
980 }
981
982 npc_set_imgfx_params(npc, imgfxType, var2, var3, var4, var5, npc->imgfxFlags);
983 return ApiStatus_DONE2;
984}
985
986API_CALLABLE(SetNpcImgFXFlags) {
987 Bytecode* args = script->ptrReadPos;
988 s32 npcId = evt_get_variable(script, *args++);
989 Bytecode flags = *args;
990 Npc* npc = resolve_npc(script, npcId);
991
992 if (npc == NULL) {
993 return ApiStatus_DONE2;
994 }
995
996 npc->imgfxFlags = flags;
997 return ApiStatus_DONE2;
998}
999
1000API_CALLABLE(SetNpcPaletteSwapMode) {
1001 Bytecode* args = script->ptrReadPos;
1002 s32 npcId = evt_get_variable(script, *args++);
1003 Bytecode palAdjustMode = evt_get_variable(script, *args++);
1004 Npc* npc = resolve_npc(script, npcId);
1005
1006 if (npc == NULL) {
1007 return ApiStatus_DONE2;
1008 }
1009
1010 npc_set_palswap_mode_A(npc, palAdjustMode);
1011 return ApiStatus_DONE2;
1012}
1013
1014API_CALLABLE(SetNpcPaletteSwapLower) {
1015 Bytecode* args = script->ptrReadPos;
1016 s32 npcId = evt_get_variable(script, *args++);
1017 Bytecode var1 = evt_get_variable(script, *args++);
1018 Bytecode var2 = evt_get_variable(script, *args++);
1019 Bytecode var3 = evt_get_variable(script, *args++);
1020 Bytecode var4 = evt_get_variable(script, *args++);
1021 Npc* npc = resolve_npc(script, npcId);
1022
1023 if (npc == NULL) {
1024 return ApiStatus_DONE2;
1025 }
1026
1027 npc_set_palswap_1(npc, var1, var2, var3, var4);
1028 return ApiStatus_DONE2;
1029}
1030
1031API_CALLABLE(SetNpcPaletteSwapping) {
1032 Bytecode* args = script->ptrReadPos;
1033 s32 npcId = evt_get_variable(script, *args++);
1034 Bytecode var1 = evt_get_variable(script, *args++);
1035 Bytecode var2 = evt_get_variable(script, *args++);
1036 Bytecode var3 = evt_get_variable(script, *args++);
1037 Bytecode var4 = evt_get_variable(script, *args++);
1038 Bytecode var5 = evt_get_variable(script, *args++);
1039 Bytecode var6 = evt_get_variable(script, *args++);
1040 Bytecode var7 = evt_get_variable(script, *args++);
1041 Bytecode var8 = evt_get_variable(script, *args++);
1042 Npc* npc = resolve_npc(script, npcId);
1043
1044 if (npc == NULL) {
1045 return ApiStatus_DONE2;
1046 }
1047
1048 npc_set_palswap_1(npc, var1, var2, var3, var4);
1049 npc_set_palswap_2(npc, var5, var6, var7, var8);
1050 return ApiStatus_DONE2;
1051}
1052
1053API_CALLABLE(SetNpcDecoration) {
1054 Bytecode* ptrReadPos = script->ptrReadPos;
1055 s32 npcID = evt_get_variable(script, *ptrReadPos++);
1056 s32 value1 = evt_get_variable(script, *ptrReadPos++);
1057 s32 value2 = evt_get_variable(script, *ptrReadPos++);
1058 Npc* npc = resolve_npc(script, npcID);
1059
1060 if (npc == NULL) {
1061 return ApiStatus_DONE2;
1062 }
1063
1064 npc_set_decoration(npc, value1, value2);
1065 return ApiStatus_DONE2;
1066}
1067
1068API_CALLABLE(PlaySoundAtNpc) {
1069 Bytecode* ptrReadPos = script->ptrReadPos;
1070 s32 npcID = evt_get_variable(script, *ptrReadPos++);
1071 s32 soundID = evt_get_variable(script, *ptrReadPos++);
1072 s32 flags = evt_get_variable(script, *ptrReadPos++);
1073 Npc* npc = resolve_npc(script, npcID);
1074
1075 if (npc == NULL) {
1076 return ApiStatus_DONE2;
1077 }
1078
1079 sfx_play_sound_at_position(soundID, flags, npc->pos.x, npc->pos.y, npc->pos.z);
1080 return ApiStatus_DONE2;
1081}
1082
1083API_CALLABLE(SetNpcRenderMode) {
1084 Bytecode* ptrReadPos = script->ptrReadPos;
1085 s32 npcID = evt_get_variable(script, *ptrReadPos++);
1086 u8 renderMode = evt_get_variable(script, *ptrReadPos++);
1087 Npc* npc = resolve_npc(script, npcID);
1088
1089 npc->renderMode = renderMode;
1090 return ApiStatus_DONE2;
1091}
Bytecode * ptrReadPos
union Evt::@9 owner2
Initially -1.
s8 flags
Definition demo_api.c:15
#define sfx_play_sound_at_position
#define sin_deg
#define clamp_angle
#define atan2
@ PARTNER_ANIM_STILL
Definition enums.h:3414
@ PARTNER_ANIM_HURT
Definition enums.h:3422
@ ENEMY_ANIM_F
Definition enums.h:3454
@ ENEMY_ANIM_IDLE
Definition enums.h:3439
@ NPC_SELF
Definition enums.h:2526
@ NPC_PARTNER
Definition enums.h:2528
@ SURFACE_INTERACT_RUN
Definition enums.h:4685
@ SURFACE_INTERACT_WALK
Definition enums.h:4684
@ SURFACE_INTERACT_LAND
Definition enums.h:4686
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_DIRTY_SHADOW
Definition enums.h:3014
s32 ApiStatus
Definition evt.h:115
#define ApiStatus_DONE2
Definition evt.h:118
s32 Bytecode
Definition evt.h:7
#define ApiStatus_DONE1
Definition evt.h:117
#define ApiStatus_BLOCK
Definition evt.h:116
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1690
f32 update_lerp(s32 easing, f32 start, f32 end, s32 elapsed, s32 duration)
Definition 43F0.c:735
void disable_npc_blur(Npc *npc)
Definition npc.c:1088
void func_800EF3D4(s32)
Definition partners.c:2414
void partner_clear_player_tracking(Npc *partner)
Definition partners.c:2436
void enable_npc_blur(Npc *npc)
Definition npc.c:1067
s32 evt_set_variable(Evt *script, Bytecode var, s32 value)
Definition evt.c:1847
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
s32 partner_is_flying(void)
Definition partners.c:572
void func_800EF314(void)
Definition partners.c:2386
void enable_partner_ai(void)
Definition partners.c:2390
void func_800EF3E4(void)
Definition partners.c:2418
void func_800EF43C(void)
Definition partners.c:2430
f32 evt_get_float_variable(Evt *script, Bytecode var)
Definition evt.c:1930
void func_800EF300(void)
Definition partners.c:2382
void free_npc(Npc *npc)
Definition npc.c:237
s32 create_basic_npc(NpcBlueprint *blueprint)
Definition npc.c:190
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
Definition surfaces.c:394
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2540
void npc_set_palswap_1(Npc *npc, s32 palIndexA, s32 palIndexB, s32 timeHoldA, s32 timeAB)
Definition npc.c:1287
void enable_npc_shadow(Npc *npc)
Definition npc.c:1027
s32 * animList
Definition npc.h:341
void disable_npc_shadow(Npc *npc)
Definition npc.c:1037
void free_npc_by_index(s32 listIndex)
Definition npc.c:202
void npc_set_imgfx_params(Npc *npc, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Definition npc.c:2162
void npc_set_decoration(Npc *npc, s32 idx, s32 decorationType)
Definition npc.c:1734
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
void npc_set_palswap_2(Npc *npc, s32 timeHoldB, s32 timeBA, s32 palIndexC, s32 palIndexD)
Definition npc.c:1294
void npc_set_palswap_mode_A(Npc *npc, s32 arg1)
Definition npc.c:1258
Npc * get_npc_by_index(s32 listIndex)
Definition npc.c:271
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
void set_npc_yaw(Npc *npc, f32 yaw)
Definition npc.c:1246
void set_npc_sprite(Npc *npc, s32 anim, AnimID *extraAnimList)
Definition npc.c:1048
Npc * get_npc_safe(s32 npcID)
Definition npc.c:1010
void set_npc_animation(Npc *npc, u32 animID)
Definition npc_api.c:18
s32 wExtraPartnerID
Definition script_list.c:32
ApiStatus _npc_jump_to(Evt *script, s32 isInitialCall, s32 snapYaw)
Definition npc_api.c:290
Npc * resolve_npc(Evt *script, s32 npcIdOrPtr)
Definition npc_api.c:8
s32 wExtraPartnerNpcID
Definition script_list.c:33
s32 partner_can_use_ability(void)
Definition partners.c:993
ApiStatus SetNpcPaletteSwapping(Evt *script, b32 isInitialCall)
ApiStatus PlaySoundAtNpc(Evt *script, b32 isInitialCall)
ApiStatus SetNpcRotationPivot(Evt *script, b32 isInitialCall)
ApiStatus DeleteNpc(Evt *script, b32 isInitialCall)
ApiStatus PartnerIsFlying(Evt *script, b32 isInitialCall)
ApiStatus DisablePartnerAI(Evt *script, b32 isInitialCall)
ApiStatus ClearPartnerMoveHistory(Evt *script, b32 isInitialCall)
ApiStatus SetNpcPaletteSwapMode(Evt *script, b32 isInitialCall)
ApiStatus GetNpcAnimation(Evt *script, b32 isInitialCall)
ApiStatus SetNpcImgFXFlags(Evt *script, b32 isInitialCall)
ApiStatus PartnerCanUseAbility(Evt *script, b32 isInitialCall)
ApiStatus EnableNpcShadow(Evt *script, b32 isInitialCall)
ApiStatus GetNpcPos(Evt *script, b32 isInitialCall)
ApiStatus SetNpcDecoration(Evt *script, b32 isInitialCall)
ApiStatus SetNpcImgFXParams(Evt *script, b32 isInitialCall)
ApiStatus SetNpcSpeed(Evt *script, b32 isInitialCall)
ApiStatus NpcSetHomePosToCurrent(Evt *script, b32 isInitialCall)
ApiStatus GetCurrentPartnerID(Evt *script, b32 isInitialCall)
ApiStatus SetNpcAnimation(Evt *script, b32 isInitialCall)
ApiStatus SetNpcPaletteSwapLower(Evt *script, b32 isInitialCall)
ApiStatus SetNpcScale(Evt *script, b32 isInitialCall)
ApiStatus SetNpcRenderMode(Evt *script, b32 isInitialCall)
ApiStatus EnablePartnerAI(Evt *script, b32 isInitialCall)
ApiStatus NpcFaceNpc(Evt *script, b32 isInitialCall)
ApiStatus GetNpcYaw(Evt *script, b32 isInitialCall)
ApiStatus SetNpcRotation(Evt *script, b32 isInitialCall)
ApiStatus BringPartnerOut(Evt *script, b32 isInitialCall)
ApiStatus CreateNpc(Evt *script, b32 isInitialCall)
ApiStatus InterpNpcYaw(Evt *script, b32 isInitialCall)
ApiStatus NpcJump1(Evt *script, b32 isInitialCall)
ApiStatus SetNpcPos(Evt *script, b32 isInitialCall)
ApiStatus NpcJump0(Evt *script, b32 isInitialCall)
ApiStatus NpcFacePlayer(Evt *script, b32 isInitialCall)
ApiStatus SetNpcJumpscale(Evt *script, b32 isInitialCall)
ApiStatus PutPartnerAway(Evt *script, b32 isInitialCall)
ApiStatus SetNpcAnimationSpeed(Evt *script, b32 isInitialCall)
ApiStatus SetNpcCollisionChannel(Evt *script, b32 isInitialCall)
ApiStatus SetNpcSprite(Evt *script, b32 isInitialCall)
ApiStatus SetNpcYaw(Evt *script, b32 isInitialCall)
ApiStatus GetPartnerPos(Evt *script, b32 isInitialCall)
ApiStatus GetNpcPointer(Evt *script, b32 isInitialCall)
ApiStatus NpcMoveTo(Evt *script, b32 isInitialCall)
ApiStatus SetNpcFlagBits(Evt *script, b32 isInitialCall)
ApiStatus func_802CF56C(Evt *script, b32 isInitialCall)
ApiStatus EnableNpcBlur(Evt *script, b32 isInitialCall)
ApiStatus SetNpcCollisionSize(Evt *script, b32 isInitialCall)
ApiStatus NpcFlyTo(Evt *script, b32 isInitialCall)
ApiStatus func_802CF54C(Evt *script, b32 isInitialCall)
#define EVT_LIMIT
Definition macros.h:47
void(* onRender)(struct Npc *)
Definition npc.h:89
void(* onUpdate)(struct Npc *)
Definition npc.h:88
s32 initialAnim
Definition npc.h:87
s32 flags
Definition npc.h:86
s16 collisionDiameter
f32 jumpScale
Vec3f scale
f32 jumpVel
f32 animationSpeed
s8 renderMode
s32 flags
AnimID curAnim
Vec3f moveToPos
f32 planarFlyDist
s32 collisionChannel
Vec3f colliderPos
s16 collisionHeight
Vec3f rot
u16 imgfxFlags
Vec3f pos
f32 rotPivotOffsetY
f32 moveSpeed
Vec3s homePos
s16 duration
PlayerData gPlayerData
Definition 77480.c:40
PartnerAnimations gPartnerAnimations[12]
Definition partners.c:343
PlayerStatus gPlayerStatus
Definition 77480.c:39