Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
FireBarAI.inc.c
Go to the documentation of this file.
1#ifndef _AI_FIRE_BAR_INC_
2#define _AI_FIRE_BAR_INC_ 0
3
4#include "common.h"
5
6// from data
7extern s32 N(FireBar_Sounds)[11];
8extern EvtScript N(EVS_FireBar_Defeated);
9
10enum {
14};
15
16API_CALLABLE(N(FireBarAI_Main)) {
17 PlayerStatus* playerStatus = &gPlayerStatus;
18 PartnerStatus* partnerStatus = &gPartnerStatus;
19 Bytecode* args = script->ptrReadPos;
20 FireBarAISettings* settings;
21 FireBarData* data;
22 Npc* partnerNpc;
23 Npc* npc;
24 f32 distToPlayer, angleToPlayer;
25 f32 distToNpc, angleToNpc;
26 f32 deltaYaw, clampedYaw;
27 f32 dX, dY, dZ;
28 f32 tempPlayerDist;
29 s32 hitDetected;
30 s32 i;
31
32 settings = (FireBarAISettings*) evt_get_variable(script, *args++);
33 npc = get_npc_unsafe(script->owner1.enemy->npcID);
34 partnerNpc = get_npc_unsafe(NPC_PARTNER);
35 hitDetected = 0;
36
37 if (isInitialCall) {
38 data = heap_malloc(sizeof(*data));
39 script->functionTempPtr[1] = data;
40 data->flags = 0;
41 data->centerPos.x = settings->centerPos.x;
42 data->centerPos.y = settings->centerPos.y;
43 data->centerPos.z = settings->centerPos.z;
44 data->rotRate = settings->rotRate;
45 data->firstNpc = settings->firstNpc;
46 data->npcCount = settings->npcCount;
47 data->callback = settings->callback;
48 data->soundIndex = 0;
49 data->lastDeltaYaw = 0;
50 data->yaw = 0;
51 data->settings = settings;
52 }
53
55 return 0;
56 }
57
58 data = script->functionTempPtr[1];
59 for (i = 0; i < data->npcCount; i++) {
60 npc = get_npc_unsafe(data->firstNpc + i);
61 if (!(data->flags & 1)) {
62 f32 radius = (i * npc->collisionDiameter) * npc->scale.x;
63 dX = radius * sin_deg(data->yaw);
64 dZ = -radius * cos_deg(data->yaw);
65 npc->pos.x = data->centerPos.x + dX;
66 npc->pos.y = data->centerPos.y;
67 npc->pos.z = data->centerPos.z + dZ;
68 npc->yaw = atan2(npc->pos.x, npc->pos.z, playerStatus->pos.x, playerStatus->pos.z);
69 }
70 if (!(data->flags & 2) && !(playerStatus->flags & PS_FLAG_HAZARD_INVINCIBILITY)) {
71 dY = playerStatus->pos.y - npc->pos.y;
72 if (partnerStatus->partnerActionState == PARTNER_ACTION_USE) {
73 if (partnerStatus->actingPartner == PARTNER_LAKILESTER) {
74 dY = partnerNpc->pos.y - npc->pos.y;
75 } else if (partnerStatus->actingPartner == PARTNER_PARAKARRY) {
76 dY = (playerStatus->pos.y - 10.0f) - npc->pos.y;
77 }
78 }
79 dX = playerStatus->pos.x - npc->pos.x;
80 dZ = playerStatus->pos.z - npc->pos.z;
81 if ((fabsf(dY) < (npc->collisionHeight * 0.8f))
82 && (sqrtf(SQ(dX) + SQ(dZ)) <= ((npc->collisionDiameter * 0.5f * npc->scale.x * 0.5f) + (playerStatus->colliderDiameter * 0.5f * 0.5f)))) {
83 hitDetected = 1;
84 }
85 }
86 }
87 if (playerStatus->flags & PS_FLAG_HAZARD_INVINCIBILITY) {
88 hitDetected = -1;
89 }
90 data->yaw += data->rotRate;
91 clampedYaw = clamp_angle(data->yaw);
92 if (clampedYaw != data->yaw) {
93 data->yaw = clampedYaw;
94 sfx_play_sound_at_position(N(FireBar_Sounds)[data->soundIndex], SOUND_SPACE_DEFAULT, data->centerPos.x, data->centerPos.y, data->centerPos.z);
95 }
96 distToPlayer = dist2D(data->centerPos.x, data->centerPos.z, playerStatus->pos.x, playerStatus->pos.z);
97 distToNpc = dist2D(data->centerPos.x, data->centerPos.z, npc->pos.x, npc->pos.z)
98 + (npc->collisionDiameter * 0.5f * npc->scale.x * 0.5f) + (playerStatus->colliderDiameter * 0.5f * 0.5f);
99 tempPlayerDist = distToPlayer; // needed to match
100 angleToPlayer = atan2(data->centerPos.x, data->centerPos.z, playerStatus->pos.x, playerStatus->pos.z);
101 angleToNpc = atan2(data->centerPos.x, data->centerPos.z, npc->pos.x, npc->pos.z);
102 deltaYaw = get_clamped_angle_diff(angleToPlayer, angleToNpc);
103 if ((hitDetected > 0) && (playerStatus->actionState != ACTION_STATE_HIT_FIRE)) {
104 playerStatus->hazardType = HAZARD_TYPE_FIRE_BAR;
106 sfx_play_sound_at_position(SOUND_TOUCH_LAVA, SOUND_SPACE_DEFAULT, playerStatus->pos.x, playerStatus->pos.y, playerStatus->pos.z);
108 playerStatus->blinkTimer = 45;
109 playerStatus->lastGoodPos.x = playerStatus->pos.x;
110 playerStatus->lastGoodPos.y = playerStatus->pos.y;
111 playerStatus->lastGoodPos.z = playerStatus->pos.z;
112 data->soundIndex = 0;
113 if (data->callback != NULL) {
114 data->callback(data, FIRE_BAR_HIT);
115 }
116 } else if ((tempPlayerDist < distToNpc) && !(data->flags & 2)
117 && (hitDetected == 0) && (playerStatus->actionState != ACTION_STATE_HIT_FIRE)) {
118 if (data->rotRate > 0.0f) {
119 if (data->lastDeltaYaw < 0.0f) {
120 if (deltaYaw > 0.0f) {
121 data->soundIndex++;
122 if (data->callback != NULL) {
123 data->callback(data, FIRE_BAR_SPEED_UP);
124 }
125 }
126 }
127 } else if (data->lastDeltaYaw > 0.0f) {
128 if (deltaYaw < 0.0f) {
129 data->soundIndex++;
130 if (data->callback != NULL) {
131 data->callback(data, FIRE_BAR_SPEED_UP);
132 }
133 }
134 }
135 }
136 data->lastDeltaYaw = deltaYaw;
137 if (data->callback != NULL) {
138 data->callback(data, FIRE_BAR_SLOW_DOWN);
139 }
140 return ApiStatus_BLOCK;
141}
142
143void N(FireBarAI_Callback)(FireBarData* data, s32 mode) {
144 switch (mode) {
146 if (data->flags & 2) {
147 data->rotRate *= 0.95f;
148 }
149 break;
151 data->rotRate *= 1.12f;
152 if (data->soundIndex == 10) {
153 Evt* script = start_script(&N(EVS_FireBar_Defeated), EVT_PRIORITY_1, 0);
154 script->varTable[0] = data->firstNpc;
155 script->varTable[1] = data->npcCount;
156 data->flags |= 2;
157 }
158 break;
159 case FIRE_BAR_HIT:
160 data->rotRate = abs(data->settings->rotRate) * signF(-data->rotRate);
161 break;
162 }
163 return;
164}
165
166#endif
@ FIRE_BAR_HIT
@ FIRE_BAR_SPEED_UP
@ FIRE_BAR_SLOW_DOWN
void N FireBarAI_Callback(FireBarData *data, s32 mode)
Bytecode EvtScript[]
#define sfx_play_sound_at_position
#define sqrtf
#define sin_deg
#define clamp_angle
#define cos_deg
#define atan2
@ PS_FLAG_HAZARD_INVINCIBILITY
Definition enums.h:3056
@ PARTNER_ACTION_USE
Definition enums.h:2933
@ NPC_PARTNER
Definition enums.h:2528
@ HAZARD_TYPE_FIRE_BAR
Definition enums.h:3502
@ TIME_FREEZE_NONE
Definition enums.h:3464
@ SOUND_TOUCH_LAVA
Definition enums.h:723
@ PARTNER_LAKILESTER
Definition enums.h:2893
@ PARTNER_PARAKARRY
Definition enums.h:2889
@ ACTION_STATE_HIT_FIRE
Causes Mario to fly up and take damage. Used for fire bars.
Definition enums.h:2449
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ EVT_PRIORITY_1
Definition evt.h:152
s32 Bytecode
Definition evt.h:7
#define ApiStatus_BLOCK
Definition evt.h:116
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1690
f32 fabsf(f32 f)
f32 signF(f32 val)
Definition 43F0.c:557
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
Evt * start_script(EvtScript *source, s32 priority, s32 initialState)
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
s32 get_time_freeze_mode(void)
Definition main_loop.c:390
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:606
void * heap_malloc(s32 size)
Definition heap.c:34
f32 lastDeltaYaw
Definition npc.h:138
s32 npcCount
Definition npc.h:135
FireBarCallback callback
Definition npc.h:127
s32 firstNpc
Definition npc.h:134
s8 battleTriggerCooldown
set to 15 after victory, 45 after fleeing
Definition npc.h:373
FireBarAISettings * settings
Definition npc.h:140
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
Vec3f centerPos
Definition npc.h:132
f32 yaw
Definition npc.h:139
f32 rotRate
Definition npc.h:133
EncounterStatus gCurrentEncounter
Definition encounter.c:176
s32 flags
Definition npc.h:131
FireBarCallback callback
Definition npc.h:136
Vec3i centerPos
Definition npc.h:123
s32 soundIndex
Definition npc.h:137
#define SQ(x)
Definition macros.h:166
s16 collisionDiameter
Vec3f scale
s16 collisionHeight
Vec3f pos
PartnerStatus gPartnerStatus
Definition partners.c:42
PlayerStatus gPlayerStatus
Definition 77480.c:39