Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
GuardAI.inc.c
Go to the documentation of this file.
1#ifndef _AI_GUARD_H_
2#define _AI_GUARD_H_
3
4// Used in:
5// - kmr_02 Toad
6// - kmr_07 GoombaBros
7// - kmr_11 GoombaBros/King
8// - sbk_30 (unused)
9// - trd_01 Bobomb <-- only real use case!
10// - nok_01 (unused)
11// - omo_02 (unused)
12
13// custom states for this AI
20
21#include "common.h"
22#include "npc.h"
23#include "effects.h"
24
25void N(GuardAI_IdleInit)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
26 Enemy* enemy = script->owner1.enemy;
27 Npc* npc = get_npc_unsafe(enemy->npcID);
28
30 script->AI_TEMP_STATE = AI_STATE_GUARD_IDLE;
31
32 if (enemy->flags & ENEMY_FLAG_SKIP_BATTLE) {
33 npc->yaw = enemy->varTable[0];
34 }
35
36 if (enemy->territory->wander.moveSpeedOverride <= 0) {
37 npc->moveSpeed = aiSettings->chaseSpeed;
38 } else {
39 npc->moveSpeed = enemy->territory->wander.moveSpeedOverride / 32767.0;
40 }
41}
42
43void N(GuardAI_Idle)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
44 Enemy* enemy = script->owner1.enemy;
45 Npc* npc = get_npc_unsafe(enemy->npcID);
46 EffectInstance* emoteTemp;
47
48 if (aiSettings->playerSearchInterval >= 0 && basic_ai_check_player_dist(territory, enemy, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, 0)) {
49 fx_emote(EMOTE_EXCLAMATION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
51 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
52
54 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
55 } else {
56 script->AI_TEMP_STATE = AI_STATE_ALERT_INIT;
57 }
58 }
59}
60
61void N(GuardAI_AlertInit)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
62 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
63
64 npc->jumpVel = 10.0f;
65 npc->jumpScale = 2.0f;
66 npc->moveToPos.y = npc->pos.y;
67 npc->flags |= NPC_FLAG_JUMPING;
68 script->AI_TEMP_STATE = AI_STATE_ALERT;
69}
70
71void N(GuardAI_Alert)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
72 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
73
74 npc->pos.y += npc->jumpVel;
75 npc->jumpVel -= npc->jumpScale;
76
77 if (!(npc->pos.y > npc->moveToPos.y)) {
78 npc->pos.y = npc->moveToPos.y;
79 npc->jumpVel = 0.0f;
80 npc->flags &= ~NPC_FLAG_JUMPING;
81 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
82 }
83}
84
85void N(GuardAI_ChaseInit)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
86 Enemy* enemy = script->owner1.enemy;
87 Npc* npc = get_npc_unsafe(enemy->npcID);
88 f32 tempAngle;
89 f32 angleDiff;
90
91 npc->duration = (aiSettings->chaseUpdateInterval / 2) + rand_int(aiSettings->chaseUpdateInterval / 2 + 1);
93 npc->moveSpeed = aiSettings->chaseSpeed;
94
95 tempAngle = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
96 angleDiff = get_clamped_angle_diff(npc->yaw, tempAngle);
97
98 if (aiSettings->chaseTurnRate < fabsf(angleDiff)) {
99 tempAngle = npc->yaw;
100
101 if (angleDiff < 0.0f) {
102 tempAngle += -aiSettings->chaseTurnRate;
103 } else {
104 tempAngle += aiSettings->chaseTurnRate;
105 }
106 }
107
108 npc->yaw = clamp_angle(tempAngle);
109 script->AI_TEMP_STATE = AI_STATE_CHASE;
110}
111
112void N(GuardAI_Chase)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* arg2) {
113 Enemy* enemy = script->owner1.enemy;
114 Npc* npc = get_npc_unsafe(enemy->npcID);
115 EffectInstance* emoteTemp;
116
117 if (!basic_ai_check_player_dist(arg2, enemy, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, 1)) {
118 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
120 npc->duration = 25;
121 script->AI_TEMP_STATE = AI_STATE_LOSE_PLAYER;
122 } else {
123 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
125 npc->duration--;
126 if (npc->duration == 0) {
127 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
128 }
129 }
130}
131
132void N(GuardAI_LosePlayer)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
133 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
134
135 npc->duration--;
136 if (npc->duration == 0) {
137 script->AI_TEMP_STATE = AI_STATE_GUARD_RETURN_HOME_INIT;
138 }
139}
140
141void N(GuardAI_ReturnHomeInit)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
142 Enemy* enemy = script->owner1.enemy;
143 Npc* npc = get_npc_unsafe(enemy->npcID);
144
146 if (enemy->territory->wander.moveSpeedOverride < 0) {
147 npc->moveSpeed = aiSettings->chaseSpeed * 0.3;
148 } else {
149 npc->moveSpeed = enemy->territory->wander.moveSpeedOverride / 32767.0;
150 }
151 script->functionTemp[1] = 0;
152 script->AI_TEMP_STATE = AI_STATE_GUARD_RETURN_HOME;
153}
154
155void N(GuardAI_ReturnHome)(Evt* script, GuardAISettings* aiSettings, EnemyDetectVolume* territory) {
156 Enemy* enemy = script->owner1.enemy;
157 Npc* npc = get_npc_unsafe(enemy->npcID);
158 EffectInstance* emoteTemp;
159
160 if (aiSettings->playerSearchInterval >= 0) {
161 if (script->functionTemp[1] <= 0) {
162 script->functionTemp[1] = aiSettings->playerSearchInterval;
163 if (basic_ai_check_player_dist(territory, enemy, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, 0)) {
164 fx_emote(EMOTE_EXCLAMATION, npc, 0.0f, (f32) npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
166 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
168 script->AI_TEMP_STATE = AI_STATE_ALERT_INIT;
169 } else {
170 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
171 }
172 return;
173 }
174 }
175 script->functionTemp[1]--;
176 }
177
178 if (dist2D(npc->pos.x, npc->pos.z, enemy->territory->wander.centerPos.x, enemy->territory->wander.centerPos.z) < npc->moveSpeed) {
179 npc->pos.x = enemy->territory->wander.centerPos.x;
180 npc->pos.z = enemy->territory->wander.centerPos.z;
181 npc->yaw = enemy->territory->wander.wanderSize.x;
182 script->AI_TEMP_STATE = AI_STATE_GUARD_IDLE_INIT;
183 }
184
185 if (npc->turnAroundYawAdjustment == 0) {
186 npc->yaw = atan2(npc->pos.x, npc->pos.z, enemy->territory->wander.centerPos.x, enemy->territory->wander.centerPos.z);
187 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
188 }
189}
190
191API_CALLABLE(N(GuardAI_Main)) {
192 Bytecode* args = script->ptrReadPos;
193 Enemy* enemy = script->owner1.enemy;
194 Npc* npc = get_npc_unsafe(enemy->npcID);
195 EnemyDetectVolume territory;
196 EnemyDetectVolume* territoryPtr = &territory;
197 GuardAISettings* aiSettings = (GuardAISettings*)evt_get_variable(script, *args++);
198
199 territory.skipPlayerDetectChance = 0;
200 territory.shape = enemy->territory->wander.detectShape;
201 territory.pointX = enemy->territory->wander.detectPos.x;
202 territory.pointZ = enemy->territory->wander.detectPos.z;
203 territory.sizeX = enemy->territory->wander.detectSize.x;
204 territory.sizeZ = enemy->territory->wander.detectSize.z;
205 territory.halfHeight = 65.0f;
206 territory.detectFlags = 0;
207
208 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
209 script->AI_TEMP_STATE = AI_STATE_GUARD_IDLE_INIT;
210 npc->duration = 0;
211 enemy->varTable[0] = npc->yaw;
213 npc->flags &= ~NPC_FLAG_JUMPING;
214
215 if (!(enemy->territory->wander.isFlying)) {
216 npc->flags |= NPC_FLAG_GRAVITY;
217 npc->flags &= ~NPC_FLAG_FLYING;
218 } else {
219 npc->flags &= ~NPC_FLAG_GRAVITY;
220 npc->flags |= NPC_FLAG_FLYING;
221 }
222
223 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
224 script->AI_TEMP_STATE = AI_STATE_SUSPEND;
225 script->functionTemp[1] = 15;
226 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
227 } else if (enemy->flags & ENEMY_FLAG_BEGIN_WITH_CHASING) {
228 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
229 enemy->flags &= ~ENEMY_FLAG_BEGIN_WITH_CHASING;
230 }
231 }
232
233 switch (script->AI_TEMP_STATE) {
235 N(GuardAI_IdleInit)(script, aiSettings, territoryPtr);
237 N(GuardAI_Idle)(script, aiSettings, territoryPtr);
238 break;
239
241 N(GuardAI_AlertInit)(script, aiSettings, territoryPtr);
242 case AI_STATE_ALERT:
243 N(GuardAI_Alert)(script, aiSettings, territoryPtr);
244 break;
245
247 N(GuardAI_ChaseInit)(script, aiSettings, territoryPtr);
248 case AI_STATE_CHASE:
249 N(GuardAI_Chase)(script, aiSettings, territoryPtr);
250 break;
251
253 N(GuardAI_LosePlayer)(script, aiSettings, territoryPtr);
254 break;
255
257 N(GuardAI_ReturnHomeInit)(script, aiSettings, territoryPtr);
259 N(GuardAI_ReturnHome)(script, aiSettings, territoryPtr);
260 break;
261
262 case AI_STATE_SUSPEND:
263 basic_ai_suspend(script);
264 break;
265 }
266 return ApiStatus_BLOCK;
267}
268
269#endif
void N GuardAI_Alert(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
Definition GuardAI.inc.c:71
void N GuardAI_LosePlayer(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
void N GuardAI_Chase(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *arg2)
AiStateGuard
Definition GuardAI.inc.c:14
@ AI_STATE_GUARD_RETURN_HOME
Definition GuardAI.inc.c:18
@ AI_STATE_GUARD_RETURN_HOME_INIT
Definition GuardAI.inc.c:17
@ AI_STATE_GUARD_IDLE
Definition GuardAI.inc.c:16
@ AI_STATE_GUARD_IDLE_INIT
Definition GuardAI.inc.c:15
void N GuardAI_AlertInit(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
Definition GuardAI.inc.c:61
void N GuardAI_ReturnHomeInit(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
void N GuardAI_ChaseInit(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
Definition GuardAI.inc.c:85
void N GuardAI_IdleInit(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
Definition GuardAI.inc.c:25
void N GuardAI_ReturnHome(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
void N GuardAI_Idle(Evt *script, GuardAISettings *aiSettings, EnemyDetectVolume *territory)
Definition GuardAI.inc.c:43
#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_CHASE
Definition enums.h:3429
@ AI_FLAG_SUSPEND
Definition enums.h:4571
@ AI_STATE_SUSPEND
Definition enums.h:4598
@ AI_STATE_ALERT
Definition enums.h:4591
@ AI_STATE_CHASE_INIT
Definition enums.h:4592
@ AI_STATE_CHASE
Definition enums.h:4593
@ AI_STATE_LOSE_PLAYER
Definition enums.h:4594
@ AI_STATE_ALERT_INIT
Definition enums.h:4590
@ ENEMY_FLAG_SKIP_BATTLE
Definition enums.h:4541
@ ENEMY_FLAG_BEGIN_WITH_CHASING
Definition enums.h:4551
@ SOUND_AI_ALERT_A
Definition enums.h:1078
@ SURFACE_INTERACT_RUN
Definition enums.h:4685
@ AI_ACTION_JUMP_WHEN_SEE_PLAYER
Definition enums.h:4612
@ SOUND_PARAM_MORE_QUIET
Definition enums.h:1746
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
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)
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
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
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
VecXZi wanderSize
Definition npc.h:212
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
s16 actionFlags
Definition npc.h:156
s16 detectFlags
Definition npc.h:207
s32 moveSpeedOverride
Definition npc.h:213
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 skipPlayerDetectChance
Definition npc.h:200
EnemyTerritoryWander wander
Definition npc.h:232
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