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 f32 distToPlayer;
15 s32 detectedPlayer;
16
17 f32 posXFwd;
18 f32 posYFwd;
19 f32 posZFwd;
20 f32 posXCW;
21 f32 posYCW;
22 f32 posZCW;
23 f32 posXCCW;
24 f32 posYCCW;
25 f32 posZCCW;
26
27 npc->duration = npcAISettings->chaseUpdateInterval / 2 + rand_int(npcAISettings->chaseUpdateInterval / 2 + 1);
29 npc->moveSpeed = npcAISettings->chaseSpeed;
30 detectedPlayer = FALSE;
31
32 yawFwd = clamp_angle(atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x,
33 gPlayerStatusPtr->pos.z) + 180.0f);
34 deltaYaw = get_clamped_angle_diff(npc->yaw, yawFwd);
35 if (npcAISettings->chaseTurnRate < fabsf(deltaYaw)) {
36 yawFwd = npc->yaw;
37 if (deltaYaw < 0.0f) {
38 yawFwd += -npcAISettings->chaseTurnRate;
39 } else {
40 yawFwd += npcAISettings->chaseTurnRate;
41 }
42 }
43
44 npc->yaw = clamp_angle(yawFwd);
45
46 posXFwd = npc->pos.x;
47 posYFwd = npc->pos.y;
48 posZFwd = npc->pos.z;
49
50 yawFwd = clamp_angle(atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z) + 180.0f);
51 distFwd = 0.0f;
52 distCW = 0.0f;
53 distCCW = 0.0f;
54
56 &posXFwd, &posYFwd, &posZFwd, npc->moveSpeed * 4.5,
57 yawFwd, npc->collisionHeight, npc->collisionDiameter)) {
58 distFwd = dist2D(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
59
60 // check 'whisker' 35 degrees CW
61 posXCW = npc->pos.x;
62 posYCW = npc->pos.y;
63 posZCW = npc->pos.z;
65 &posXCW, &posYCW, &posZCW, npc->moveSpeed * 4.5,
66 clamp_angle(yawFwd + 35.0f), npc->collisionHeight, npc->collisionDiameter)) {
67 distCW = dist2D(npc->pos.x, npc->pos.z, posXCW, posZCW);
68 }
69
70 // check 'whisker' 35 degrees CCW
71 posXCCW = npc->pos.x;
72 posYCCW = npc->pos.y;
73 posZCCW = npc->pos.z;
75 &posXCCW, &posYCCW, &posZCCW, npc->moveSpeed * 4.5,
76 clamp_angle(yawFwd - 35.0f), npc->collisionHeight, npc->collisionDiameter)) {
77 distCCW = dist2D(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
78 }
79
80 // unused
81 distToPlayer = dist2D(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
82
83 if ((distFwd < npc->moveSpeed * 1.5) && (distCW < npc->moveSpeed * 1.5) && (distCCW < npc->moveSpeed * 1.5) &&
84 (basic_ai_check_player_dist(territory, enemy, npcAISettings->alertRadius, npcAISettings->alertOffsetDist, 0))) {
85 detectedPlayer = TRUE;
86 }
87
88 if (!detectedPlayer) {
89 if ((distCW < distFwd) && (distCCW < distCW)) {
90 yawFwd = atan2(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
91 } else if ((distCW < distFwd) && (distCW < distCCW)) {
92 yawFwd = atan2(npc->pos.x, npc->pos.z, posXFwd, posZFwd);
93 } else if ((distFwd < distCW) && (distCCW < distFwd)) {
94 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCW, posZCW);
95 } else if ((distCCW < distCW) && (distFwd < distCCW)) {
96 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCW, posZCW);
97 } else if ((distFwd < distCCW) && (distCW < distFwd)) {
98 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
99 } else if ((distCW < distCCW) && (distFwd < distCW)) {
100 yawFwd = atan2(npc->pos.x, npc->pos.z, posXCCW, posZCCW);
101 }
102
103 deltaYaw = get_clamped_angle_diff(npc->yaw, yawFwd);
104 if (npcAISettings->chaseTurnRate < fabsf(deltaYaw)) {
105 yawFwd = npc->yaw;
106 if (deltaYaw < 0.0f) {
107 yawFwd += -npcAISettings->chaseTurnRate;
108 } else {
109 yawFwd += npcAISettings->chaseTurnRate;
110 }
111 }
112 npc->yaw = clamp_angle(yawFwd);
113 }
114 }
115 if (detectedPlayer) {
116 npc->duration = 10;
118 }
119 script->AI_TEMP_STATE = AI_STATE_CHASE;
120}
121
122void N(AvoidPlayerAI_Chase)(Evt* script, MobileAISettings* npcAISettings, EnemyDetectVolume* territory) {
123 Enemy* enemy = script->owner1.enemy;
124 Npc* npc = get_npc_unsafe(enemy->npcID);
125 EffectInstance* emoteTemp;
126
127 if (!basic_ai_check_player_dist(territory, enemy, npcAISettings->chaseRadius, npcAISettings->chaseOffsetDist, 1)) {
128 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
130 npc->duration = 25;
131 script->AI_TEMP_STATE = AI_STATE_LOSE_PLAYER;
132 } else {
133 if (npc->curAnim != enemy->animList[ENEMY_ANIM_INDEX_MELEE_PRE]) {
134 if (npc->moveSpeed < 4.0) {
136 } else {
138 }
139 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
140 }
141 if (npc->duration > 0) {
142 npc->duration--;
143 return;
144 }
145 script->AI_TEMP_STATE = AI_STATE_CHASE_INIT;
146 }
147}
148
149void N(AvoidPlayerAI_LosePlayer)(Evt* script, MobileAISettings* npcAISettings, EnemyDetectVolume* territory) {
150 Enemy* enemy = script->owner1.enemy;
151 Npc* npc = get_npc_unsafe(enemy->npcID);
152
153 npc->duration--;
154 if (npc->duration == 0) {
155 script->AI_TEMP_STATE = AI_STATE_WANDER_INIT;
156 }
157}
158
159API_CALLABLE(N(AvoidPlayerAI_Main)) {
160 Enemy* enemy = script->owner1.enemy;
161 Npc* npc = get_npc_unsafe(enemy->npcID);
162 Bytecode* args = script->ptrReadPos;
163 EnemyDetectVolume territory;
164 EnemyDetectVolume* territoryPtr = &territory;
165 MobileAISettings* npcAISettings = (MobileAISettings*)evt_get_variable(script, *args++);
166
167 territory.skipPlayerDetectChance = 0;
168 territory.shape = enemy->territory->wander.detectShape;
169 territory.pointX = enemy->territory->wander.detectPos.x;
170 territory.pointZ = enemy->territory->wander.detectPos.z;
171 territory.sizeX = enemy->territory->wander.detectSize.x;
172 territory.sizeZ = enemy->territory->wander.detectSize.z;
173 territory.halfHeight = 100.0f;
174 territory.detectFlags = 0;
175
176 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
177 script->functionTemp[0] = AI_STATE_WANDER_INIT;
178 npc->duration = 0;
180 npc->flags &= ~NPC_FLAG_JUMPING;
181 if (!enemy->territory->wander.isFlying) {
182 npc->flags |= NPC_FLAG_GRAVITY;
183 npc->flags &= ~NPC_FLAG_FLYING;
184 } else {
185 npc->flags &= ~NPC_FLAG_GRAVITY;
186 npc->flags |= NPC_FLAG_FLYING;
187 }
188 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
189 script->functionTemp[0] = AI_STATE_SUSPEND;
190 script->functionTemp[1] = AI_STATE_WANDER_INIT;
191 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
192 }
193 }
194
195 switch (script->functionTemp[0]) {
197 basic_ai_wander_init(script, npcAISettings, territoryPtr);
198 case AI_STATE_WANDER:
199 basic_ai_wander(script, npcAISettings, territoryPtr);
200 break;
202 basic_ai_loiter_init(script, npcAISettings, territoryPtr);
203 case AI_STATE_LOITER:
204 basic_ai_loiter(script, npcAISettings, territoryPtr);
205 break;
207 basic_ai_found_player_jump_init(script, npcAISettings, territoryPtr);
208 case AI_STATE_ALERT:
209 basic_ai_found_player_jump(script, npcAISettings, territoryPtr);
210 break;
212 N(AvoidPlayerAI_ChaseInit)(script, npcAISettings, territoryPtr);
213 case AI_STATE_CHASE:
214 N(AvoidPlayerAI_Chase)(script, npcAISettings, territoryPtr);
215 break;
217 N(AvoidPlayerAI_LosePlayer)(script, npcAISettings, territoryPtr);
218 break;
219 case AI_STATE_SUSPEND:
220 basic_ai_suspend(script);
221 break;
222 }
223
224 return ApiStatus_BLOCK;
225}
226
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:4571
@ AI_STATE_WANDER
Definition enums.h:4582
@ AI_STATE_LOITER
Definition enums.h:4588
@ AI_STATE_SUSPEND
Definition enums.h:4598
@ 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_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
@ SURFACE_INTERACT_RUN
Definition enums.h:4685
@ SURFACE_INTERACT_WALK
Definition enums.h:4684
@ 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:1690
f32 fabsf(f32 f)
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
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:606
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
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
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
s16 collisionDiameter
s32 flags
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr