Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
SpinyAI.inc.c
Go to the documentation of this file.
1// spiny AI
2
3#include "common.h"
4#include "npc.h"
5#include "effects.h"
6#include "sprite/npc/Spiny.h"
7
8// prerequisites
10
11API_CALLABLE(N(SpinyAI_Main)) {
12 Enemy* enemy = script->owner1.enemy;
13 Npc* npc = get_npc_unsafe(enemy->npcID);
14 Bytecode* args = script->ptrReadPos;
15 EnemyDetectVolume territory;
16 EnemyDetectVolume* territoryPtr = &territory;
17 MobileAISettings* aiSettings = (MobileAISettings*)evt_get_variable(script, *args);
18 u32 x, y, z;
19 f32 x2, y2, z2, w2;
20 Npc* npc2;
21
22 territory.skipPlayerDetectChance = 0;
23 territory.shape = enemy->territory->wander.detectShape;
24 territory.pointX = enemy->territory->wander.detectPos.x;
25 territory.pointZ = enemy->territory->wander.detectPos.z;
26 territory.sizeX = enemy->territory->wander.detectSize.x;
27 territory.sizeZ = enemy->territory->wander.detectSize.z;
28 territory.halfHeight = 65.0f;
29 territory.detectFlags = 0;
30
31 if (isInitialCall) {
32 enemy->varTable[6] = npc->collisionHeight;
34 }
35
36 if (isInitialCall || (enemy->varTable[10] == 100)) {
37 script->AI_TEMP_STATE = 100;
38 npc->duration = 0;
40 npc->flags &= ~NPC_FLAG_JUMPING;
42 npc->flags &= ~NPC_FLAG_GRAVITY;
43 npc->flags |= NPC_FLAG_FLYING;
44 enemy->varTable[10] = 0;
45 enemy->varTable[11] = -1;
46 npc->pos.x = NPC_DISPOSE_POS_X;
47 npc->pos.y = NPC_DISPOSE_POS_Y;
48 npc->pos.z = NPC_DISPOSE_POS_Z;
49 }
50
51 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
52 npc->duration = 0;
53 npc->collisionHeight = enemy->varTable[6];
54 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
55 if (npc->flags & NPC_FLAG_JUMPING) {
56 npc->curAnim = ANIM_Spiny_Anim18;
57 npc->moveSpeed = 0.0f;
58 npc->jumpVel = 0.0f;
59 npc->jumpScale = 1.0f;
60 script->AI_TEMP_STATE = 102;
61 } else {
62 EffectInstance* emoteTemp;
63 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 0x28, &emoteTemp);
65 script->functionTemp[1] = 0;
66 script->AI_TEMP_STATE = 200;
67 }
68 }
69 get_screen_coords(CAM_DEFAULT, npc->pos.x, npc->pos.y, npc->pos.z, &x, &y, &z);
70 if (script->AI_TEMP_STATE < 100 && x + 50 >= 421) {
71 script->AI_TEMP_STATE = 110;
72 }
73
74 switch (script->AI_TEMP_STATE) {
75 case 0:
76 basic_ai_wander_init(script, aiSettings, territoryPtr);
77 npc->collisionHeight = enemy->varTable[6];
78 if (enemy->varTable[13] != 0) {
79 if (npc->pos.y <= 0.0) {
80 npc->flags &= ~NPC_FLAG_GRAVITY;
81 npc->flags |= NPC_FLAG_FLYING;
82 } else {
83 npc->flags |= NPC_FLAG_GRAVITY;
84 npc->flags &= ~NPC_FLAG_FLYING;
85 }
86 }
87 basic_ai_wander(script, aiSettings, territoryPtr);
88 break;
89 case 1:
90 basic_ai_wander(script, aiSettings, territoryPtr);
91 break;
92 case 2:
93 basic_ai_loiter_init(script, aiSettings, territoryPtr);
94 case 3:
95 basic_ai_loiter(script, aiSettings, territoryPtr);
96 break;
97 case 12:
98 N(set_script_owner_npc_anim)(script, aiSettings, territoryPtr);
99 case 13:
100 N(UnkDistFunc)(script, aiSettings, territoryPtr);
101 npc->collisionHeight = enemy->varTable[6];
102 break;
103 case 14:
104 N(UnkNpcAIFunc12)(script, aiSettings, territoryPtr);
105 break;
106 case 15:
107 N(set_script_owner_npc_col_height)(script, aiSettings, territoryPtr);
108 break;
109 case 100:
110 if (enemy->varTable[10] != 2) {
111 break;
112 }
113 npc2 = get_npc_unsafe(get_enemy(enemy->varTable[11])->npcID);
114 if (npc2->yaw < 180.0) {
115 npc->pos.x = npc2->pos.x + 12.0;
116 } else {
117 npc->pos.x = npc2->pos.x - 12.0;
118 }
119 npc->pos.y = npc2->pos.y + 25.0;
120 npc->pos.z = npc2->pos.z + 1.0;
121 npc->rot.y = 0.0f;
122 npc->flags |= NPC_FLAG_FLYING;
123 npc->flags &= ~NPC_FLAG_INVISIBLE;
124 npc->flags &= ~NPC_FLAG_GRAVITY;
125 npc->renderYaw = 0.0f;
126 npc->curAnim = ANIM_Spiny_Anim18;
127 script->AI_TEMP_STATE = 101;
128 case 101:
129 if (enemy->varTable[10] != 3) {
130 break;
131 }
132 enemy->varTable[10] = 4;
133 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
134 npc->moveSpeed = 2.5f;
135 npc->jumpVel = 8.0f;
136 npc->jumpScale = 0.8f;
137 npc->flags |= NPC_FLAG_JUMPING;
138 script->AI_TEMP_STATE = 102;
139 case 102:
140 if (npc->moveSpeed > 0.0) {
141 x2 = npc->pos.x;
142 y2 = npc->pos.y;
143 z2 = npc->pos.z;
144 if (npc_test_move_simple_with_slipping(npc->collisionChannel, &x2, &y2, &z2, npc->moveSpeed, npc->yaw, npc->collisionHeight,
145 npc->collisionDiameter) == 0) {
146 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
147 } else {
148 npc->moveSpeed = 0.0f;
149 }
150 }
151 if (npc->jumpVel < 0.0) {
152 x2 = npc->pos.x;
153 y2 = npc->pos.y + 13.0;
154 z2 = npc->pos.z;
155 w2 = fabsf(npc->jumpVel) + 16.0;
156 if ((npc_raycast_down_sides(npc->collisionChannel, &x2, &y2, &z2, &w2) != 0) && (w2 <= (fabsf(npc->jumpVel) + 13.0))) {
157 npc->pos.y = y2;
158 enemy->territory->wander.centerPos.x = npc->pos.x;
159 enemy->territory->wander.centerPos.y = npc->pos.y;
160 enemy->territory->wander.centerPos.z = npc->pos.z;
161 enemy->territory->wander.detectPos.x = npc->pos.x;
162 enemy->territory->wander.detectPos.y = npc->pos.y;
163 enemy->territory->wander.detectPos.z = npc->pos.z;
164 enemy->varTable[10] = 5;
165 if (enemy->varTable[13] != 0) {
166 if (npc->pos.y <= 0.0) {
167 npc->flags &= ~NPC_FLAG_GRAVITY;
168 npc->flags |= NPC_FLAG_FLYING;
169 } else {
170 npc->flags |= NPC_FLAG_GRAVITY;
171 npc->flags &= ~NPC_FLAG_FLYING;
172 }
173 } else if (!enemy->territory->wander.isFlying) {
174 npc->flags |= NPC_FLAG_GRAVITY;
175 npc->flags &= ~NPC_FLAG_FLYING;
176 } else {
177 npc->flags &= ~NPC_FLAG_GRAVITY;
178 npc->flags |= NPC_FLAG_FLYING;
179 }
181 npc->flags &= ~NPC_FLAG_JUMPING;
182 npc->jumpVel = 0.0f;
183 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
184 npc->curAnim = ANIM_Spiny_Anim1A;
185 npc->duration = 3;
186 script->AI_TEMP_STATE = 103;
187 break;
188 }
189 }
190 npc->pos.y += npc->jumpVel;
191 npc->jumpVel -= npc->jumpScale;
192 break;
193 case 103:
194 npc->duration--;
195 if (npc->duration <= 0) {
196 npc->flags &= ~NPC_FLAG_IGNORE_CAMERA_FOR_YAW;
197 npc->curAnim = ANIM_Spiny_Anim01;
198 script->AI_TEMP_STATE = 0;
199 }
200 break;
201 case 110:
202 npc->duration = 30;
203 npc->pos.x = NPC_DISPOSE_POS_X;
204 npc->pos.y = NPC_DISPOSE_POS_Y;
205 npc->pos.z = NPC_DISPOSE_POS_Z;
207 npc->flags &= ~NPC_FLAG_GRAVITY;
208 script->AI_TEMP_STATE = 111;
209 case 111:
210 npc->duration--;
211 if (npc->duration <= 0) {
212 enemy->varTable[10] = 0;
213 script->AI_TEMP_STATE = 100;
214 }
215 break;
216 case 200:
217 basic_ai_suspend(script);
218 break;
219 }
220 return ApiStatus_BLOCK;
221}
222
void N UnkNpcAIFunc12(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
ApiStatus N UnkDistFunc(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N set_script_owner_npc_col_height(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N set_script_owner_npc_anim(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define npc_raycast_down_sides
#define atan2
@ EMOTE_QUESTION
Definition enums.h:497
@ ENEMY_ANIM_INDEX_IDLE
Definition enums.h:3426
@ AI_FLAG_SUSPEND
Definition enums.h:4571
@ AI_FLAG_SKIP_EMOTE_AFTER_FLEE
Definition enums.h:4572
@ ENEMY_FLAG_ACTIVE_WHILE_OFFSCREEN
Definition enums.h:4542
@ CAM_DEFAULT
Definition enums.h:1800
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
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 get_screen_coords(s32 camID, f32 x, f32 y, f32 z, s32 *screenX, s32 *screenY, s32 *screenZ)
Definition cam_main.c:410
void basic_ai_wander(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:588
b32 npc_test_move_simple_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void basic_ai_wander_init(Evt *script, MobileAISettings *npcAISettings, EnemyDetectVolume *territory)
Definition 23680.c:567
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
s32 flags
Definition npc.h:295
VecXZi detectSize
Definition npc.h:216
enum TerritoryShape detectShape
Definition npc.h:217
s16 npcID
Definition npc.h:300
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2540
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
#define NPC_DISPOSE_POS_Z
Definition macros.h:161
#define NPC_DISPOSE_POS_X
Definition macros.h:159
#define NPC_DISPOSE_POS_Y
Definition macros.h:160
s16 collisionDiameter
f32 jumpScale
f32 jumpVel
s32 flags
f32 renderYaw
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
Vec3f rot
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr