Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
States_PatrolAI.inc.c
Go to the documentation of this file.
1#ifndef _AI_PATROL_INC_
2#define _AI_PATROL_INC_ 0
3
4#include "common.h"
5#include "npc.h"
6#include "effects.h"
7
8// selects the next patrol point
9void N(PatrolAI_MoveInit)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
10 Enemy* enemy = script->owner1.enemy;
11 Npc* npc = get_npc_unsafe(enemy->npcID);
12 f32 ret;
13 f32 max;
14 f32 posX;
15 f32 posZ;
16 s32 i;
17 s32 j;
18 s32 x, z;
19
20 script->functionTemp[1] = 0;
21 max = 32767.0f;
22 posX = npc->pos.x;
23 posZ = npc->pos.z;
24 script->AI_PATROL_GOAL_INDEX = 0;
25
26 for (i = 0, j = 0; i < enemy->territory->patrol.numPoints; i++, j++) {
27 //TODO strange match -- index and array are backwards!
28 x = i[enemy->territory->patrol.points].x;
29 z = i[enemy->territory->patrol.points].z;
30 ret = dist2D(posX, posZ, x, z);
31 if (ret < max) {
32 max = ret;
33 script->AI_PATROL_GOAL_INDEX = j;
34 }
35 }
36
38 if (enemy->territory->patrol.moveSpeedOverride < 0) {
39 npc->moveSpeed = aiSettings->moveSpeed;
40 } else {
41 npc->moveSpeed = enemy->territory->patrol.moveSpeedOverride / 32767.0;
42 }
43
44 script->AI_TEMP_STATE = AI_STATE_PATROL;
45}
46
47void N(PatrolAI_Move)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
48 Enemy* enemy = script->owner1.enemy;
49 Npc* npc = get_npc_unsafe(enemy->npcID);
50 f32 x, z;
51 EffectInstance* emoteTemp;
52
53 if (aiSettings->playerSearchInterval >= 0) {
54 if (script->functionTemp[1] <= 0) {
55 script->functionTemp[1] = aiSettings->playerSearchInterval;
56 if (basic_ai_check_player_dist(territory, enemy, aiSettings->alertRadius, aiSettings->alertOffsetDist, 0)) {
57 fx_emote(EMOTE_EXCLAMATION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 0xF, &emoteTemp);
60 script->AI_TEMP_STATE = AI_STATE_ALERT_INIT;
61 } else {
62 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
63 }
64 return;
65 }
66 }
67 script->functionTemp[1]--;
68 }
69
70 if (npc->turnAroundYawAdjustment == 0) {
71 if (npc->moveSpeed < 4.0) {
73 } else {
75 }
76 //TODO strange match -- index and array are backwards!
77 x = script->AI_PATROL_GOAL_INDEX[enemy->territory->patrol.points].x;
78 z = script->AI_PATROL_GOAL_INDEX[enemy->territory->patrol.points].z;
79 npc->yaw = atan2(npc->pos.x, npc->pos.z, x, z);
80 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
81 if (dist2D(npc->pos.x, npc->pos.z, x, z) <= npc->moveSpeed) {
82 script->AI_TEMP_STATE = AI_STATE_LOITER_INIT;
83 script->functionTemp[1] = (rand_int(1000) % 3) + 2;
84 if ((aiSettings->unk_AI_2C <= 0) || (aiSettings->moveTime <= 0) ||
85 (aiSettings->waitTime <= 0) || (script->functionTemp[1] == 0)) {
86 script->AI_TEMP_STATE = AI_STATE_LOITER_POST;
87 }
88 if (rand_int(10000) % 100 < aiSettings->moveTime) {
89 script->AI_TEMP_STATE = AI_STATE_LOITER_POST;
90 }
91 }
92 }
93}
94
95// identical to basic_ai_loiter_init
96void N(PatrolAI_LoiterInit)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
97 Enemy* enemy = script->owner1.enemy;
98 Npc* npc = get_npc_unsafe(enemy->npcID);
99
100 npc->duration = (aiSettings->waitTime / 2) + rand_int((aiSettings->waitTime / 2) + 1);
101 npc->yaw = clamp_angle(npc->yaw + rand_int(180) - 90.0f);
103 script->AI_TEMP_STATE = AI_STATE_LOITER;
104}
105
106
107void N(PatrolAI_Loiter)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
108 Enemy* enemy = script->owner1.enemy;
109 Npc* npc = get_npc_unsafe(enemy->npcID);
110 EffectInstance* emoteTemp;
111
112 if ((aiSettings->playerSearchInterval >= 0) && basic_ai_check_player_dist(territory, enemy, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, 0)) {
113 fx_emote(EMOTE_EXCLAMATION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 0xF, &emoteTemp);
114 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
117 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
118 } else {
119 script->AI_TEMP_STATE = AI_STATE_ALERT_INIT;
120 }
121 return;
122 }
123
124 // look around randomly
125 if (npc->turnAroundYawAdjustment == 0) {
126 npc->duration--;
127 if (npc->duration == 0) {
128 script->functionTemp[1]--;
129 if (script->functionTemp[1] != 0) {
131 npc->yaw = clamp_angle(npc->yaw + 180.0f);
132 }
133 npc->duration = aiSettings->waitTime / 2 + rand_int(aiSettings->waitTime / 2 + 1);
134 } else {
135 script->AI_TEMP_STATE = AI_STATE_LOITER_POST;
136 }
137 }
138 }
139}
140
141void N(PatrolAI_PostLoiter)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
142 Enemy* enemy = script->owner1.enemy;
143 Npc* npc = get_npc_unsafe(enemy->npcID);
144
145 script->functionTemp[2]++;
146 if (script->functionTemp[2] >= enemy->territory->patrol.numPoints) {
147 script->functionTemp[2] = 0;
148 }
150 if (enemy->territory->patrol.moveSpeedOverride < 0) {
151 npc->moveSpeed = aiSettings->moveSpeed;
152 } else {
153 npc->moveSpeed = enemy->territory->patrol.moveSpeedOverride / 32767.0;
154 }
155 script->AI_TEMP_STATE = AI_STATE_PATROL;
156}
157
158void N(PatrolAI_JumpInit)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
159 Enemy* enemy = script->owner1.enemy;
160 Npc* npc = get_npc_unsafe(enemy->npcID);
161
163 npc->jumpVel = 10.0f;
164 npc->jumpScale = 2.0f;
165 npc->moveToPos.y = npc->pos.y;
166 npc->flags |= NPC_FLAG_JUMPING;
167 script->functionTemp[0] = AI_STATE_ALERT;
168}
169
170void N(PatrolAI_Jump)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
171 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
172
173 npc->pos.y += npc->jumpVel;
174 npc->jumpVel -= npc->jumpScale;
175
176 if (!(npc->pos.y > npc->moveToPos.y)) {
177 npc->pos.y = npc->moveToPos.y;
178 npc->jumpVel = 0.0f;
179 npc->flags &= ~NPC_FLAG_JUMPING;
180 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
181 }
182}
183
184void N(PatrolAI_ChaseInit)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
185 Enemy* enemy = script->owner1.enemy;
186 Npc* npc = get_npc_unsafe(enemy->npcID);
187 f32 angle;
188 f32 angleDiff;
189
190 npc->duration = (aiSettings->chaseUpdateInterval / 2) + rand_int(aiSettings->chaseUpdateInterval / 2 + 1);
192 npc->moveSpeed = aiSettings->chaseSpeed;
193
194 angle = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
195 angleDiff = get_clamped_angle_diff(npc->yaw, angle);
196
197 if (aiSettings->chaseTurnRate < fabsf(angleDiff)) {
198 angle = npc->yaw;
199
200 if (angleDiff < 0.0f) {
201 angle += -aiSettings->chaseTurnRate;
202 } else {
203 angle += aiSettings->chaseTurnRate;
204 }
205 }
206
207 npc->yaw = clamp_angle(angle);
208 script->functionTemp[0] = 13;
209}
210
211void N(PatrolAI_Chase)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
212 Enemy* enemy = script->owner1.enemy;
213 Npc* npc = get_npc_unsafe(enemy->npcID);
214 EffectInstance* emoteTemp;
215
216 if (!basic_ai_check_player_dist(territory, enemy, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, 1)) {
217 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
219 npc->duration = 25;
220 script->AI_TEMP_STATE = AI_STATE_LOSE_PLAYER;
221 } else {
223 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
224 if (npc->duration > 0) {
225 npc->duration--;
226 } else {
227 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
228 }
229 }
230}
231
232void N(PatrolAI_LosePlayer)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
233 Enemy* enemy = script->owner1.enemy;
234 Npc* npc = get_npc_unsafe(enemy->npcID);
235
236 npc->duration--;
237 if (npc->duration == 0) {
238 if (enemy->aiFlags & AI_FLAG_80) {
239 script->AI_TEMP_STATE = AI_STATE_PATROL_15;
240 } else {
241 script->AI_TEMP_STATE = AI_STATE_WANDER_INIT;
242 }
243 }
244}
245
246void N(PatrolNoAttackAI_15)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
247 Enemy* enemy = script->owner1.enemy;
248 Npc* npc = get_npc_unsafe(enemy->npcID);
249 s32 i;
250
251 // get next patrol point
252 for (i = script->AI_PATROL_GOAL_INDEX; i < enemy->territory->patrol.numPoints; i++) {
253 if (i[enemy->territory->patrol.points].y <= npc->pos.y) {
254 script->AI_PATROL_GOAL_INDEX = i;
255 break;
256 }
257 }
258
259 npc->moveSpeed = aiSettings->moveSpeed;
261 script->functionTemp[1] = 0;
262 script->AI_TEMP_STATE = AI_STATE_PATROL;
263}
264
265#endif
void N PatrolAI_MoveInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_PostLoiter(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_Loiter(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolNoAttackAI_15(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_Jump(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_JumpInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_ChaseInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_Chase(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_Move(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_LoiterInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N PatrolAI_LosePlayer(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define rand_int
#define clamp_angle
#define atan2
@ EMOTE_EXCLAMATION
Definition enums.h:495
@ EMOTE_QUESTION
Definition enums.h:497
@ ENEMY_ANIM_INDEX_IDLE
Definition enums.h:3426
@ ENEMY_ANIM_INDEX_WALK
Definition enums.h:3427
@ ENEMY_ANIM_INDEX_JUMP
Definition enums.h:3430
@ ENEMY_ANIM_INDEX_CHASE
Definition enums.h:3429
@ AI_FLAG_80
Definition enums.h:4576
@ AI_STATE_LOITER
Definition enums.h:4588
@ AI_STATE_WANDER_INIT
Definition enums.h:4581
@ AI_STATE_LOITER_INIT
Definition enums.h:4587
@ AI_STATE_ALERT
Definition enums.h:4591
@ AI_STATE_PATROL_15
Definition enums.h:4595
@ AI_STATE_CHASE_INIT
Definition enums.h:4592
@ AI_STATE_LOITER_POST
Definition enums.h:4589
@ AI_STATE_PATROL
Definition enums.h:4584
@ AI_STATE_LOSE_PLAYER
Definition enums.h:4594
@ AI_STATE_ALERT_INIT
Definition enums.h:4590
@ SOUND_AI_ALERT_A
Definition enums.h:1078
@ SURFACE_INTERACT_RUN
Definition enums.h:4685
@ SURFACE_INTERACT_WALK
Definition enums.h:4684
@ AI_ACTION_LOOK_AROUND_DURING_LOITER
Definition enums.h:4616
@ AI_ACTION_JUMP_WHEN_SEE_PLAYER
Definition enums.h:4612
@ SOUND_PARAM_MORE_QUIET
Definition enums.h:1746
@ NPC_FLAG_JUMPING
Definition enums.h:3009
f32 fabsf(f32 f)
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
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:606
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
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
Definition surfaces.c:394
s32 * animList
Definition npc.h:341
Vec3i points[10]
Definition npc.h:223
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
s16 actionFlags
Definition npc.h:156
EnemyTerritoryPatrol patrol
Definition npc.h:233
NpcSettings * npcSettings
Definition npc.h:304
u32 aiFlags
Definition npc.h:332
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
s32 moveSpeedOverride
Definition npc.h:224
EnemyTerritory * territory
Definition npc.h:342
Definition npc.h:294
f32 jumpScale
f32 jumpVel
s32 flags
AnimID curAnim
Vec3f moveToPos
s16 collisionHeight
s16 turnAroundYawAdjustment
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr