Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
PiranhaPlantAI.inc.c
Go to the documentation of this file.
1// visual enemy
2#include "common.h"
3#include "npc.h"
4#include "effects.h"
5
6// hitbox enemy
8
9void N(PiranhaPlantAI_00)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
10 Enemy* enemy = script->owner1.enemy;
11 Npc* npc = get_npc_unsafe(enemy->npcID);
12
13 if (npc->duration > 0) {
14 npc->duration--;
15 } else {
16 enemy->varTable[0] = 0;
18 script->functionTemp[1] = 0;
19 script->functionTemp[0] = 1;
20 }
21}
22
23void N(PiranhaPlantAI_01)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
24 Enemy* enemy = script->owner1.enemy;
25 Npc* npc = get_npc_unsafe(enemy->npcID);
26 EffectInstance* temp;
27
28 if (basic_ai_check_player_dist(territory, enemy, aiSettings->alertRadius, aiSettings->alertOffsetDist, 0)) {
30 fx_emote(EMOTE_EXCLAMATION, npc, 0, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 10, &temp);
33 npc->duration = enemy->varTable[8];
34 script->functionTemp[0] = 10;
35 }
36}
37
38void N(PiranhaPlantAI_10)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
39 Enemy* enemy = script->owner1.enemy;
40 Npc* npc = get_npc_unsafe(enemy->npcID);
41 s32 phi_s7 = FALSE;
42 s32 phi_fp = FALSE;
43 f32 sp38;
44 f32 yaw;
45 f32 yaw2;
46 f32 moveSpeed;
47 f32 posRadius;
48 s32 cond1;
49 s32 cond2;
50 f32 terSize;
51 f32 sp20;
52 f32 sp24;
53 f32 sp28;
54 f32 sp2C;
55 f32 sp30;
56 f32 sp34;
57
58 npc->duration--;
59 if (enemy->varTable[9] >= npc->duration) {
62 }
63
64 if (npc->duration == 0) {
66 yaw2 = clamp_angle(gCameras[gCurrentCameraID].curYaw - 90.0f);
67 } else {
68 yaw2 = clamp_angle(gCameras[gCurrentCameraID].curYaw + 90.0f);
69 }
70
71 yaw = clamp_angle(yaw2 + 180.0f);
72 if (enemy->varTable[7] == 0) {
73 moveSpeed = 32.0f;
74
75 if (gPlayerStatusPtr->actionState != 0) {
76 moveSpeed = 100.0f;
77 if (gPlayerStatusPtr->actionState == 1) {
78 moveSpeed = 90.0f;
79 }
80 }
81 } else {
82 moveSpeed = 38.0f;
83
84 if (gPlayerStatusPtr->actionState != 0) {
85 moveSpeed = 90.0f;
86 if (gPlayerStatusPtr->actionState == 1) {
87 moveSpeed = 75.0f;
88 }
89 }
90 }
91
92 npc->pos.x = gPlayerStatusPtr->pos.x;
93 npc->pos.z = gPlayerStatusPtr->pos.z;
94 add_vec2D_polar(&npc->pos.x, &npc->pos.z, npc->collisionDiameter, yaw);
95 npc_move_heading(npc, moveSpeed + npc->collisionDiameter, yaw2);
96
97 if (enemy->varTable[7] == 0) {
98 if (npc->pos.x > 380.0) {
99 npc->pos.x = 380.0f;
100 }
101 if (npc->pos.x < -380.0) {
102 npc->pos.x = -380.0f;
103 }
104 if (npc->pos.z > 380.0) {
105 npc->pos.z = 380.0f;
106 }
107 if (npc->pos.z < -380.0) {
108 npc->pos.z = -380.0f;
109 }
110
111 sp38 = sqrtf(SQ(npc->pos.x) + SQ(npc->pos.z));
112 yaw2 = atan2(0.0f, 0.0f, npc->pos.x, npc->pos.z);
113
114 if (sp38 < 305.0) {
115 npc->pos.x = 0.0f;
116 npc->pos.z = 0.0f;
117 add_vec2D_polar(&npc->pos.x, &npc->pos.z, 305.0f, yaw2);
118 } else if (sp38 > 375.0) {
119 npc->pos.x = 0.0f;
120 npc->pos.z = 0.0f;
121 add_vec2D_polar(&npc->pos.x, &npc->pos.z, 375.0f, yaw2);
122 }
123 } else {
125 sp20 = gPlayerStatusPtr->pos.x;
126 sp24 = gPlayerStatusPtr->pos.y + 18.0;
127 sp28 = gPlayerStatusPtr->pos.z;
128 if (npc_test_move_simple_with_slipping(npc->collisionChannel, &sp20, &sp24, &sp28, moveSpeed, yaw2, npc->collisionHeight, npc->collisionDiameter)) {
129 sp20 = gPlayerStatusPtr->pos.x;
130 sp24 = gPlayerStatusPtr->pos.y + 45.0;
131 sp28 = gPlayerStatusPtr->pos.z;
132 cond1 = npc_test_move_simple_with_slipping(npc->collisionChannel, &sp20, &sp24, &sp28, moveSpeed, yaw2, npc->collisionHeight, npc->collisionDiameter);
133 sp2C = npc->pos.x;
134 sp30 = npc->pos.y + 100.0;
135 sp34 = npc->pos.z;
136 sp38 = 200.0f;
137 cond2 = npc_raycast_down_sides(npc->collisionChannel, &sp2C, &sp30, &sp34, &sp38);
138 if (!cond1 && cond2 && sp38 > 80.0 && sp38 < 120.0 && npc->pos.y != sp30) {
139 phi_fp = TRUE;
140 } else {
141 sp20 = gPlayerStatusPtr->pos.x;
142 sp24 = gPlayerStatusPtr->pos.y + 10.0;
143 sp28 = gPlayerStatusPtr->pos.z;
144 npc_test_move_simple_with_slipping(npc->collisionChannel, &sp20, &sp24, &sp28, moveSpeed, yaw2, npc->collisionHeight, npc->collisionDiameter);
145 posRadius = dist2D(gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z, sp20, sp28);
146 npc->pos.x = gPlayerStatusPtr->pos.x;
147 npc->pos.z = gPlayerStatusPtr->pos.z;
148 add_vec2D_polar(&npc->pos.x, &npc->pos.z, npc->collisionDiameter, yaw);
149 npc_move_heading(npc, posRadius + npc->collisionDiameter, yaw2);
150 phi_s7 = TRUE;
151 }
152 }
153 } else {
154 sp20 = gPlayerStatusPtr->pos.x;
155 sp24 = gPlayerStatusPtr->pos.y + 18.0;
156 sp28 = gPlayerStatusPtr->pos.z;
157 if (npc_test_move_simple_with_slipping(npc->collisionChannel, &sp20, &sp24, &sp28, moveSpeed, yaw2, npc->collisionHeight, npc->collisionDiameter)) {
158 posRadius = dist2D(gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z, sp20, sp28);
159 npc->pos.x = gPlayerStatusPtr->pos.x;
160 npc->pos.z = gPlayerStatusPtr->pos.z;
161 add_vec2D_polar(&npc->pos.x, &npc->pos.z, npc->collisionDiameter, yaw);
162 npc_move_heading(npc, posRadius + npc->collisionDiameter, yaw2);
163 }
164 }
165 }
166
167 if (is_point_outside_territory(territory->shape, territory->pointX, territory->pointZ, npc->pos.x, npc->pos.z, territory->sizeX, territory->sizeZ)) {
168 switch (territory->shape) {
169 case SHAPE_CYLINDER:
170 sp38 = dist2D(npc->pos.x, npc->pos.z, territory->pointX, territory->pointZ);
171
172 if (territory->sizeX < sp38) {
173 terSize = atan2(territory->pointX, territory->pointZ, npc->pos.x, npc->pos.z);
174 npc->pos.x = territory->pointX;
175 npc->pos.z = territory->pointZ;
176 add_vec2D_polar(&npc->pos.x, &npc->pos.z, territory->sizeX, terSize);
177 }
178 break;
179 case SHAPE_RECT:
180 terSize = territory->pointX + territory->sizeX;
181 if (npc->pos.x > terSize) {
182 npc->pos.x = terSize;
183 }
184
185 terSize = territory->pointX - territory->sizeX;
186 if (npc->pos.x < terSize) {
187 npc->pos.x = terSize;
188 }
189
190 terSize = territory->pointZ + territory->sizeZ;
191 if (npc->pos.z > terSize) {
192 npc->pos.z = terSize;
193 }
194
195 terSize = territory->pointZ - territory->sizeZ;
196 if (npc->pos.z < terSize) {
197 npc->pos.z = terSize;
198 }
199 break;
200 }
201 }
202
203 if (!phi_s7 && (!(npc->flags & NPC_FLAG_FLYING) || phi_fp)) {
204 sp20 = npc->pos.x;
205 sp38 = 400.0f;
206 sp28 = npc->pos.z;
207 sp24 = npc->pos.y + 150.0;
208
209 if (npc_raycast_down_sides(npc->collisionChannel, &sp20, &sp24, &sp28, &sp38) != 0) {
210 npc->pos.y = sp24;
211 }
212 }
213
214 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
217 npc->duration = enemy->varTable[10];
218 script->functionTemp[0] = 11;
219 }
220}
221
222void N(PiranhaPlantAI_11)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
223 Enemy* enemy = script->owner1.enemy;
224 Npc* npc = get_npc_unsafe(enemy->npcID);
225
226 npc->duration--;
227 if (enemy->varTable[11] >= npc->duration) {
229 }
230 if (npc->duration == 0) {
231 npc->curAnim = enemy->animList[10];
232 npc->duration = 0;
233 script->functionTemp[0] = 12;
234 }
235}
236
237void N(PiranhaPlantAI_12)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
238 Enemy* enemy = script->owner1.enemy;
239 Npc* npc = get_npc_unsafe(enemy->npcID);
240 EffectInstance* temp;
241
242 npc->duration++;
243 if (npc->duration == enemy->varTable[13]) {
244 npc->curAnim = enemy->animList[11];
245 }
246 if (npc->duration == enemy->varTable[14]) {
247 enemy->varTable[0] = 3;
248 }
249 if (npc->duration >= enemy->varTable[12]) {
250 enemy->varTable[0] = 4;
251 npc->duration = 8;
253 fx_emote(EMOTE_FRUSTRATION, npc, 0, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 10, &temp);
254 script->functionTemp[0] = 13;
255 }
256}
257
258void N(PiranhaPlantAI_13)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
259 Enemy* enemy = script->owner1.enemy;
260 Npc* npc = get_npc_unsafe(enemy->npcID);
261
262 npc->duration--;
263 if (npc->duration == 0) {
264 npc->duration = enemy->varTable[15];
265 script->functionTemp[0] = 14;
266 }
267}
268
269void N(PiranhaPlantAI_LosePlayer)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
270 Enemy* enemy = script->owner1.enemy;
271 Npc* npc = get_npc_unsafe(enemy->npcID);
272 EffectInstance* retVal;
273
274 npc->duration--;
275 if (npc->duration == 0) {
276 if (basic_ai_check_player_dist(territory, enemy, aiSettings->alertRadius, aiSettings->alertOffsetDist, 0) == 0) {
277 fx_emote(EMOTE_QUESTION, npc, 0, npc->collisionHeight, 1, 2, -20, 15, &retVal);
278 }
279 npc->duration = 0;
280 script->functionTemp[0] = 0;
281 }
282}
283
284#include "common.h"
285#include "npc.h"
286
287API_CALLABLE(N(PiranhaPlantAI_Main)) {
288 Enemy* enemy = script->owner1.enemy;
289 Npc* npc = get_npc_unsafe(enemy->npcID);
290 Bytecode* args = script->ptrReadPos;
291 EnemyDetectVolume territory;
292 EnemyDetectVolume* territoryPtr = &territory;
293 MobileAISettings* npcAISettings = (MobileAISettings*)evt_get_variable(script, *args++);
294
295 territory.skipPlayerDetectChance = 0;
296 territory.shape = enemy->territory->wander.detectShape;
297 territory.pointX = enemy->territory->wander.detectPos.x;
298 territory.pointZ = enemy->territory->wander.detectPos.z;
299 territory.sizeX = enemy->territory->wander.detectSize.x;
300 territory.sizeZ = enemy->territory->wander.detectSize.z;
301 territory.halfHeight = 200.0f;
302 territory.detectFlags = 0;
303
304 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
305 script->AI_TEMP_STATE = AI_STATE_PIRANHA_PLANT_00;
306 npc->duration = 0;
308
309 enemy->AI_VAR_ATTACK_STATE = MELEE_HITBOX_STATE_NONE;
310 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
311 script->AI_TEMP_STATE = AI_STATE_SUSPEND;
312 script->functionTemp[1] = AI_STATE_PIRANHA_PLANT_00;
313 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
314 }
315 }
316
317 switch (script->AI_TEMP_STATE) {
319 N(PiranhaPlantAI_00)(script, npcAISettings, territoryPtr);
321 N(PiranhaPlantAI_01)(script, npcAISettings, territoryPtr);
322 break;
324 N(PiranhaPlantAI_10)(script, npcAISettings, territoryPtr);
325 if (script->AI_TEMP_STATE != AI_STATE_PIRANHA_PLANT_11) {
326 break;
327 }
329 N(PiranhaPlantAI_11)(script, npcAISettings, territoryPtr);
330 if (script->AI_TEMP_STATE != AI_STATE_PIRANHA_PLANT_12) {
331 break;
332 }
334 N(PiranhaPlantAI_12)(script, npcAISettings, territoryPtr);
335 if (script->AI_TEMP_STATE != AI_STATE_PIRANHA_PLANT_13) {
336 break;
337 }
339 N(PiranhaPlantAI_13)(script, npcAISettings, territoryPtr);
340 if (script->AI_TEMP_STATE != AI_STATE_LOSE_PLAYER) {
341 break;
342 }
344 N(PiranhaPlantAI_LosePlayer)(script, npcAISettings, territoryPtr);
345 break;
346 case AI_STATE_SUSPEND:
347 basic_ai_suspend(script);
348 break;
349 }
350 return ApiStatus_BLOCK;
351}
352
void N PiranhaPlantAI_01(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_LosePlayer(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_00(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_11(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_13(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_10(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PiranhaPlantAI_12(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
Vec3s pos
Definition demo_api.c:17
#define sqrtf
#define npc_raycast_down_sides
#define clamp_angle
#define atan2
@ EMOTE_FRUSTRATION
Definition enums.h:498
@ EMOTE_EXCLAMATION
Definition enums.h:495
@ EMOTE_QUESTION
Definition enums.h:497
@ ENEMY_ANIM_INDEX_MELEE_PRE
Definition enums.h:3434
@ ENEMY_ANIM_INDEX_IDLE
Definition enums.h:3426
@ ENEMY_ANIM_INDEX_MELEE_HIT
Definition enums.h:3435
@ AI_STATE_PIRANHA_PLANT_01
Definition enums.h:4633
@ AI_STATE_PIRANHA_PLANT_10
Definition enums.h:4634
@ AI_STATE_PIRANHA_PLANT_12
Definition enums.h:4636
@ AI_STATE_PIRANHA_PLANT_13
Definition enums.h:4637
@ AI_STATE_PIRANHA_PLANT_11
Definition enums.h:4635
@ AI_STATE_PIRANHA_PLANT_00
Definition enums.h:4632
@ AI_FLAG_SUSPEND
Definition enums.h:4571
@ AI_STATE_SUSPEND
Definition enums.h:4598
@ AI_STATE_LOSE_PLAYER
Definition enums.h:4594
@ ENEMY_FLAG_IGNORE_HAMMER
Definition enums.h:4547
@ ENEMY_FLAG_IGNORE_PARTNER
Definition enums.h:4549
@ ENEMY_FLAG_SKIP_BATTLE
Definition enums.h:4541
@ ENEMY_FLAG_IGNORE_TOUCH
Definition enums.h:4545
@ ENEMY_FLAG_CANT_INTERACT
Definition enums.h:4548
@ ENEMY_FLAG_IGNORE_JUMP
Definition enums.h:4546
@ MELEE_HITBOX_STATE_NONE
Definition enums.h:4643
@ SOUND_BURROW_SURFACE
Definition enums.h:1117
@ SOUND_BURROW_DIG
Definition enums.h:1118
@ SOUND_AI_ALERT_A
Definition enums.h:1078
@ SOUND_PARAM_MORE_QUIET
Definition enums.h:1746
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3004
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
b32 is_point_outside_territory(s32 shape, f32 centerX, f32 centerZ, f32 pointX, f32 pointZ, f32 sizeX, f32 sizeZ)
Definition 23680.c:412
void ai_enemy_play_sound(Npc *npc, s32 arg1, s32 arg2)
Definition 23680.c:543
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
b32 npc_test_move_simple_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:685
void basic_ai_suspend(Evt *script)
Definition 25AF0.c:13
enum TerritoryShape shape
Definition npc.h:201
s32 flags
Definition npc.h:295
VecXZi detectSize
Definition npc.h:216
enum TerritoryShape detectShape
Definition npc.h:217
@ SHAPE_CYLINDER
Definition npc.h:197
@ SHAPE_RECT
Definition npc.h:197
s32 basic_ai_check_player_dist(EnemyDetectVolume *arg0, Enemy *arg1, f32 arg2, f32 arg3, b8 arg4)
Definition 23680.c:429
s16 npcID
Definition npc.h:300
s32 * animList
Definition npc.h:341
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
s16 detectFlags
Definition npc.h:207
u32 aiFlags
Definition npc.h:332
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
s32 skipPlayerDetectChance
Definition npc.h:200
EnemyTerritoryWander wander
Definition npc.h:232
EnemyTerritory * territory
Definition npc.h:342
Definition npc.h:294
#define SQ(x)
Definition macros.h:166
s16 collisionDiameter
s32 flags
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
Vec3f pos
s16 duration
PlayerStatus * gPlayerStatusPtr
Camera gCameras[4]
Definition cam_main.c:17
s32 gCurrentCameraID
Definition cam_math.c:4