Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
AvoidPlayerAI.inc.c
Go to the documentation of this file.
1#include "common.h"
2#include "npc.h"
3#include "effects.h"
4
5void N(AvoidPlayerAI_ChaseInit)(Evt* script, MobileAISettings* npcAISettings, EnemyDetectVolume* territory) {
6 Enemy* enemy = script->owner1.enemy;
7 Npc* npc = get_npc_unsafe(enemy->npcID);
8
9 f32 deltaYaw;
10 f32 yawFwd;
11 f32 distFwd;
12 f32 distCW;
13 f32 distCCW;
14 s32 detectedPlayer;
15
16 f32 posXFwd;
17 f32 posYFwd;
18 f32 posZFwd;
19 f32 posXCW;
20 f32 posYCW;
21 f32 posZCW;
22 f32 posXCCW;
23 f32 posYCCW;
24 f32 posZCCW;
25
26 npc->duration = npcAISettings->chaseUpdateInterval / 2 + rand_int(npcAISettings->chaseUpdateInterval / 2 + 1);
28 npc->moveSpeed = npcAISettings->chaseSpeed;
29 detectedPlayer = FALSE;
30
31 yawFwd = clamp_angle(atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x,
32 gPlayerStatusPtr->pos.z) + 180.0f);
33 deltaYaw = get_clamped_angle_diff(npc->yaw, yawFwd);
34 if (npcAISettings->chaseTurnRate < fabsf(deltaYaw)) {
35 yawFwd = npc->yaw;
36 if (deltaYaw < 0.0f) {
37 yawFwd += -npcAISettings->chaseTurnRate;
38 } else {
39 yawFwd += npcAISettings->chaseTurnRate;
40 }
41 }
42
43 npc->yaw = clamp_angle(yawFwd);
44
45 posXFwd = npc->pos.x;
46 posYFwd = npc->pos.y;
47 posZFwd = npc->pos.z;
48
49 yawFwd = clamp_angle(atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z) + 180.0f);
50 distFwd = 0.0f;
51 distCW = 0.0f;
52 distCCW = 0.0f;
53
55 &posXFwd, &posYFwd, &posZFwd, npc->moveSpeed * 4.5,
56 yawFwd, npc->collisionHeight, npc->collisionDiameter)) {
57 distFwd = dist2D(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
58
59 // check 'whisker' 35 degrees CW
60 posXCW = npc->pos.x;
61 posYCW = npc->pos.y;
62 posZCW = npc->pos.z;
64 &posXCW, &posYCW, &posZCW, npc->moveSpeed * 4.5,
65 clamp_angle(yawFwd + 35.0f), npc->collisionHeight, npc->collisionDiameter)) {
66 distCW = dist2D(npc->pos.x, npc->pos.z, posXCW, posZCW);
67 }
68
69 // check 'whisker' 35 degrees CCW
70 posXCCW = npc->pos.x;
71 posYCCW = npc->pos.y;
72 posZCCW = npc->pos.z;
74 &posXCCW, &posYCCW, &posZCCW, npc->moveSpeed * 4.5,
75 clamp_angle(yawFwd - 35.0f), npc->collisionHeight, npc->collisionDiameter)) {
76 distCCW = dist2D(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
77 }
78
79 if ((distFwd < npc->moveSpeed * 1.5) && (distCW < npc->moveSpeed * 1.5) && (distCCW < npc->moveSpeed * 1.5) &&
80 (basic_ai_check_player_dist(territory, enemy, npcAISettings->alertRadius, npcAISettings->alertOffsetDist, 0))) {
81 detectedPlayer = TRUE;
82 }
83
84 if (!detectedPlayer) {
85 if ((distCW < distFwd) && (distCCW < distCW)) {
86 yawFwd = atan2(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
87 } else if ((distCW < distFwd) && (distCW < distCCW)) {
88 yawFwd = atan2(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
89 } else if ((distFwd < distCW) && (distCCW < distFwd)) {
90 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCW, posZCW);
91 } else if ((distCCW < distCW) && (distFwd < distCCW)) {
92 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCW, posZCW);
93 } else if ((distFwd < distCCW) && (distCW < distFwd)) {
94 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
95 } else if ((distCW < distCCW) && (distFwd < distCW)) {
96 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
97 }
98
99 deltaYaw = get_clamped_angle_diff(npc->yaw, yawFwd);
100 if (npcAISettings->chaseTurnRate < fabsf(deltaYaw)) {
101 yawFwd = npc->yaw;
102 if (deltaYaw < 0.0f) {
103 yawFwd += -npcAISettings->chaseTurnRate;
104 } else {
105 yawFwd += npcAISettings->chaseTurnRate;
106 }
107 }
108 npc->yaw = clamp_angle(yawFwd);
109 }
110 }
111 if (detectedPlayer) {
112 npc->duration = 10;
114 }
115 script->AI_TEMP_STATE = AI_STATE_CHASE;
116}
117
118void N(AvoidPlayerAI_Chase)(Evt* script, MobileAISettings* npcAISettings, EnemyDetectVolume* territory) {
119 Enemy* enemy = script->owner1.enemy;
120 Npc* npc = get_npc_unsafe(enemy->npcID);
121 EffectInstance* emoteTemp;
122
123 if (!basic_ai_check_player_dist(territory, enemy, npcAISettings->chaseRadius, npcAISettings->chaseOffsetDist, 1)) {
124 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
126 npc->duration = 25;
127 script->AI_TEMP_STATE = AI_STATE_LOSE_PLAYER;
128 } else {
129 if (npc->curAnim != enemy->animList[ENEMY_ANIM_INDEX_MELEE_PRE]) {
130 if (npc->moveSpeed < 4.0) {
132 } else {
134 }
135 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
136 }
137 if (npc->duration > 0) {
138 npc->duration--;
139 return;
140 }
141 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
142 }
143}
144
145void N(AvoidPlayerAI_LosePlayer)(Evt* script, MobileAISettings* npcAISettings, EnemyDetectVolume* territory) {
146 Enemy* enemy = script->owner1.enemy;
147 Npc* npc = get_npc_unsafe(enemy->npcID);
148
149 npc->duration--;
150 if (npc->duration == 0) {
151 script->AI_TEMP_STATE = AI_STATE_WANDER_INIT;
152 }
153}
154
155API_CALLABLE(N(AvoidPlayerAI_Main)) {
156 Enemy* enemy = script->owner1.enemy;
157 Npc* npc = get_npc_unsafe(enemy->npcID);
158 Bytecode* args = script->ptrReadPos;
159 EnemyDetectVolume territory;
160 EnemyDetectVolume* territoryPtr = &territory;
161 MobileAISettings* npcAISettings = (MobileAISettings*)evt_get_variable(script, *args++);
162
163 territory.skipPlayerDetectChance = 0;
164 territory.shape = enemy->territory->wander.detectShape;
165 territory.pointX = enemy->territory->wander.detectPos.x;
166 territory.pointZ = enemy->territory->wander.detectPos.z;
167 territory.sizeX = enemy->territory->wander.detectSize.x;
168 territory.sizeZ = enemy->territory->wander.detectSize.z;
169 territory.halfHeight = 100.0f;
170 territory.detectFlags = 0;
171
172 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
173 script->functionTemp[0] = AI_STATE_WANDER_INIT;
174 npc->duration = 0;
176 npc->flags &= ~NPC_FLAG_JUMPING;
177 if (!enemy->territory->wander.isFlying) {
178 npc->flags |= NPC_FLAG_GRAVITY;
179 npc->flags &= ~NPC_FLAG_FLYING;
180 } else {
181 npc->flags &= ~NPC_FLAG_GRAVITY;
182 npc->flags |= NPC_FLAG_FLYING;
183 }
184 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
185 script->functionTemp[0] = AI_STATE_SUSPEND;
186 script->functionTemp[1] = AI_STATE_WANDER_INIT;
187 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
188 }
189 }
190
191 switch (script->functionTemp[0]) {
193 basic_ai_wander_init(script, npcAISettings, territoryPtr);
194 case AI_STATE_WANDER:
195 basic_ai_wander(script, npcAISettings, territoryPtr);
196 break;
198 basic_ai_loiter_init(script, npcAISettings, territoryPtr);
199 case AI_STATE_LOITER:
200 basic_ai_loiter(script, npcAISettings, territoryPtr);
201 break;
203 basic_ai_found_player_jump_init(script, npcAISettings, territoryPtr);
204 case AI_STATE_ALERT:
205 basic_ai_found_player_jump(script, npcAISettings, territoryPtr);
206 break;
208 N(AvoidPlayerAI_ChaseInit)(script, npcAISettings, territoryPtr);
209 case AI_STATE_CHASE:
210 N(AvoidPlayerAI_Chase)(script, npcAISettings, territoryPtr);
211 break;
213 N(AvoidPlayerAI_LosePlayer)(script, npcAISettings, territoryPtr);
214 break;
215 case AI_STATE_SUSPEND:
216 basic_ai_suspend(script);
217 break;
218 }
219
220 return ApiStatus_BLOCK;
221}
222
void N AvoidPlayerAI_ChaseInit(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
void N AvoidPlayerAI_Chase(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
void N AvoidPlayerAI_LosePlayer(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
#define rand_int
#define clamp_angle
#define atan2
@ 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_CHASE
Definition enums.h:3429
@ AI_FLAG_SUSPEND
Definition enums.h:4570
@ AI_STATE_WANDER
Definition enums.h:4581
@ AI_STATE_LOITER
Definition enums.h:4587
@ AI_STATE_SUSPEND
Definition enums.h:4597
@ AI_STATE_WANDER_INIT
Definition enums.h:4580
@ AI_STATE_LOITER_INIT
Definition enums.h:4586
@ AI_STATE_ALERT
Definition enums.h:4590
@ AI_STATE_CHASE_INIT
Definition enums.h:4591
@ AI_STATE_CHASE
Definition enums.h:4592
@ AI_STATE_LOSE_PLAYER
Definition enums.h:4593
@ AI_STATE_ALERT_INIT
Definition enums.h:4589
@ SURFACE_INTERACT_RUN
Definition enums.h:4684
@ SURFACE_INTERACT_WALK
Definition enums.h:4683
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ 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:1689
f32 fabsf(f32 f)
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:669
void basic_ai_wander(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:588
void basic_ai_found_player_jump_init(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:735
void basic_ai_wander_init(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:567
void basic_ai_found_player_jump(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:748
b32 npc_test_move_simple_without_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:605
void basic_ai_loiter_init(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
Definition 23680.c:681
void basic_ai_suspend(Evt *script)
Definition 25AF0.c:13
void basic_ai_loiter(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:691
enum TerritoryShape shape
Definition npc.h:201
VecXZi detectSize
Definition npc.h:216
enum TerritoryShape detectShape
Definition npc.h:217
s16 npcID
Definition npc.h:300
b32 basic_ai_check_player_dist(EnemyDetectVolume *arg0, Enemy *arg1, f32 arg2, f32 arg3, s8 arg4)
Definition 23680.c:429
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
Definition surfaces.c:394
s32 * animList
Definition npc.h:341
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:994
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:985
s32 skipPlayerDetectChance
Definition npc.h:200
EnemyTerritoryWander wander
Definition npc.h:232
EnemyTerritory * territory
Definition npc.h:342
Definition npc.h:294
s16 collisionDiameter
s32 flags
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr