Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
ParatroopaAI.inc.c
Go to the documentation of this file.
1#include "common.h"
2
3// prerequisites
5
6// ai-specific states
13
14void N(ParatroopaAI_Windup)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
15 Bytecode* args = script->ptrReadPos;
16 Enemy* enemy = script->owner1.enemy;
17 Npc* npc = get_npc_unsafe(enemy->npcID);
18 f32 yawTemp;
19
20 npc->curAnim = enemy->animList[9];
21 npc->jumpVel = -5.0f;
22 npc->jumpScale = 0.15f;
23 npc->collisionHeight = enemy->varTable[8] / 2;
24
26 npc->moveSpeed = 7.0f;
27 enemy->unk_10.x = npc->pos.x;
28 enemy->unk_10.y = npc->pos.y;
29 enemy->unk_10.z = npc->pos.z;
30 enemy->hitboxIsActive = TRUE;
31
33 yawTemp = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
34 npc->duration = 12;
35 npc->yaw = yawTemp;
36 script->AI_TEMP_STATE = AI_STATE_PARATROOPA_DIVE;
37}
38
39void N(ParatroopaAI_Dive)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
40 Enemy* enemy = script->owner1.enemy;
41 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
42
43 npc->jumpVel += npc->jumpScale;
44 npc->pos.y += npc->jumpVel;
45 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
46 npc->duration--;
47
48 if (npc->duration <= 0) {
49 enemy->hitboxIsActive = FALSE;
50 npc->jumpScale = 0.3f;
51 npc->jumpVel = 0.0f;
52 npc->moveSpeed = 3.0f;
53 npc->curAnim = enemy->animList[10];
54 script->AI_TEMP_STATE = AI_STATE_PARATROOPA_OVERSHOOT;
55 }
56}
57
59{
60 Enemy* enemy = script->owner1.enemy;
61 Npc* npc = get_npc_unsafe(enemy->npcID);
62 f32 overshootAmtRaw = enemy->varTable[3];
63 f32 posX, posY, posZ, hitDepth;
64 f32 endOvershootHeight;
65 f32 overshootAmt;
66
67 npc->jumpVel += npc->jumpScale;
68 npc->pos.y += npc->jumpVel;
69 overshootAmt = overshootAmtRaw / 100.0;
70 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
71
72 posX = npc->pos.x;
73 posY = npc->pos.y;
74 posZ = npc->pos.z;
75 hitDepth = 1000.0f;
76 if (npc_raycast_down_sides(npc->collisionChannel, &posX, &posY, &posZ, &hitDepth)) {
77 endOvershootHeight = posY + overshootAmt;
78 } else {
79 endOvershootHeight = overshootAmt;
80 }
81
82 if (!(npc->pos.y < endOvershootHeight)) {
83 npc->duration = 10;
84 npc->curAnim = enemy->animList[11];
85 npc->collisionHeight = enemy->varTable[8];
86 script->AI_TEMP_STATE = AI_STATE_PARATROOPA_RESET;
87 }
88}
89
90void N(ParatroopaAI_Reset)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
91 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
92
93 npc->duration--;
94 if (npc->duration <= 0) {
95 script->AI_TEMP_STATE = AI_STATE_WANDER_INIT;
96 }
97}
98
99API_CALLABLE(N(ParatroopaAI_Main)) {
100 Bytecode* args = script->ptrReadPos;
101 Enemy* enemy = script->owner1.enemy;
102 Npc* npc = get_npc_unsafe(enemy->npcID);
103 EnemyDetectVolume territory;
104 EnemyDetectVolume* territoryPtr = &territory;
105 MobileAISettings* aiSettings = (MobileAISettings*)evt_get_variable(script, *args++);
106
107 territory.skipPlayerDetectChance = 0;
108 territory.shape = enemy->territory->wander.detectShape;
109 territory.pointX = enemy->territory->wander.detectPos.x;
110 territory.pointZ = enemy->territory->wander.detectPos.z;
111 territory.sizeX = enemy->territory->wander.detectSize.x;
112 territory.sizeZ = enemy->territory->wander.detectSize.z;
113 territory.halfHeight = 120.0f;
114 territory.detectFlags = 0;
115
116 if (isInitialCall) {
117 N(FlyingAI_Init)(npc, enemy, script, aiSettings);
118 enemy->varTable[8] = npc->collisionHeight;
119 script->AI_TEMP_STATE = 0;
120 }
121
122 npc->verticalRenderOffset = -3;
123
124 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
125 if (enemy->aiSuspendTime != 0) {
126 return ApiStatus_BLOCK;
127 }
128 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
129 }
130
131 switch (script->AI_TEMP_STATE) {
133 N(FlyingAI_WanderInit)(script, aiSettings, territoryPtr);
134 // fallthrough
135 case AI_STATE_WANDER:
136 N(FlyingAI_Wander)(script, aiSettings, territoryPtr);
137 if (script->AI_TEMP_STATE != 2) {
138 break;
139 }
140 // fallthrough
142 N(FlyingAI_LoiterInit)(script, aiSettings, territoryPtr);
143 // fallthrough
144 case AI_STATE_LOITER:
145 N(FlyingAI_Loiter)(script, aiSettings, territoryPtr);
146 if (script->AI_TEMP_STATE != AI_STATE_ALERT_INIT) {
147 break;
148 }
149 // fallthrough
151 N(FlyingAI_JumpInit)(script, aiSettings, territoryPtr);
152 if (script->AI_TEMP_STATE != AI_STATE_ALERT) {
153 break;
154 }
155 // fallthrough
156 case AI_STATE_ALERT:
157 N(FlyingAI_Jump)(script, aiSettings, territoryPtr);
158 if (script->AI_TEMP_STATE != AI_STATE_PARATROOPA_WINDUP) {
159 break;
160 }
161 // fallthrough
163 N(ParatroopaAI_Windup)(script, aiSettings, territoryPtr);
164 if (script->AI_TEMP_STATE != AI_STATE_PARATROOPA_DIVE) {
165 break;
166 }
167 // fallthrough
169 N(ParatroopaAI_Dive)(script, aiSettings, territoryPtr);
170 if (script->AI_TEMP_STATE != AI_STATE_PARATROOPA_OVERSHOOT) {
171 break;
172 }
173 // fallthrough
175 N(ParatroopaAI_Overshoot)(script, aiSettings, territoryPtr);
176 if (script->AI_TEMP_STATE != AI_STATE_PARATROOPA_RESET) {
177 break;
178 }
179 // fallthrough
181 N(ParatroopaAI_Reset)(script, aiSettings, territoryPtr);
182 break;
183 }
184 return ApiStatus_BLOCK;
185}
void N FlyingAI_LoiterInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Loiter(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Jump(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Wander(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_JumpInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Init(Npc *npc, Enemy *enemy, Evt *script, MobileAISettings *aiSettings)
void N FlyingAI_WanderInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N ParatroopaAI_Overshoot(Evt *script, MobileAISettings *arg1, EnemyDetectVolume *arg2)
void N ParatroopaAI_Dive(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N ParatroopaAI_Windup(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N ParatroopaAI_Reset(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
AiStateParatroopa
@ AI_STATE_PARATROOPA_DIVE
@ AI_STATE_PARATROOPA_WINDUP
@ AI_STATE_PARATROOPA_RESET
@ AI_STATE_PARATROOPA_OVERSHOOT
#define npc_raycast_down_sides
#define atan2
@ AI_FLAG_SUSPEND
Definition enums.h:4571
@ AI_STATE_WANDER
Definition enums.h:4582
@ 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_ALERT_INIT
Definition enums.h:4590
@ SOUND_PARAGOOMBA_DIVE
Definition enums.h:1029
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
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
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
s32 * animList
Definition npc.h:341
s8 aiSuspendTime
Definition npc.h:333
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
Vec3s unk_10
Definition npc.h:302
s8 hitboxIsActive
Definition npc.h:299
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
f32 jumpScale
f32 jumpVel
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
s8 verticalRenderOffset
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr