7#ifndef AI_SENTINEL_FIRST_NPC
8#error AI_SENTINEL_FIRST_NPC must be defined for SentinelAI.inc.c
9#define AI_SENTINEL_FIRST_NPC 0
11#ifndef AI_SENTINEL_LAST_NPC
12#error AI_SENTINEL_LAST_NPC must be defined for SentinelAI.inc.c
13#define AI_SENTINEL_LAST_NPC 0
37#define SENTINEL_AI_FLAG_CHASING 0x100
38#define SENTINEL_AI_FLAG_PLAYING_SOUND 0x1000
40#define SENTINEL_AI_DESCEND_RATE 1.8
43 Enemy* enemy = script->owner1.enemy;
50 npc->
flags &= ~NPC_FLAG_FLIP_INSTANTLY;
51 npc->
duration = aiSettings->chaseUpdateInterval / 2 +
rand_int(aiSettings->chaseUpdateInterval / 2 + 1);
56 if (aiSettings->chaseTurnRate <
fabsf(deltaAngle)) {
58 if (deltaAngle < 0.0f) {
59 angle += -aiSettings->chaseTurnRate;
61 angle += aiSettings->chaseTurnRate;
70 Enemy* enemy = script->owner1.enemy;
92 Enemy* enemy = script->owner1.enemy;
114 Enemy* enemy = script->owner1.enemy;
116 f32 posX, posY, posZ, hitDepth;
122 enemy->varTable[0] &= ~SENTINEL_AI_FLAG_CHASING;
124 npc->
flags &= ~NPC_FLAG_FLIP_INSTANTLY;
130 if (npc->
rot.
y > 360.0) {
133 color = 255.0f - (
cosine((s32)npc->
rot.
y % 180) * 56.0f);
145 npc->
flags &= ~NPC_FLAG_FLIP_INSTANTLY;
159 Enemy* enemy = script->owner1.enemy;
162 enemy->varTable[0] &= ~SENTINEL_AI_FLAG_CHASING;
166 enemy->varTable[0] &= ~SENTINEL_AI_FLAG_PLAYING_SOUND;
174 Enemy* enemy = script->owner1.enemy;
176 f32 posX, posY, posZ, posW;
177 f32 idleHeight = (f32)enemy->varTable[3] / 100.0;
186 if (!(npc->
pos.
y < posY + idleHeight)) {
188 npc->
pos.
y = posY + idleHeight;
196 Enemy* enemy = script->owner1.enemy;
206 Enemy* enemy = script->owner1.enemy;
223 Enemy* enemy = script->owner1.enemy;
226 enemy->varTable[0] &= ~SENTINEL_AI_FLAG_CHASING;
227 npc->
flags &= ~NPC_FLAG_FLIP_INSTANTLY;
228 npc->
moveSpeed = 2.0 * aiSettings->moveSpeed;
229 enemy->varTable[2] = 0;
230 enemy->varTable[4] = npc->
pos.
y * 100.0;
231 script->functionTemp[1] = 30;
235 Enemy* enemy = script->owner1.enemy;
237 f32 posX = npc->
pos.
x;
238 f32 posY = npc->
pos.
y;
239 f32 posZ = npc->
pos.
z;
240 f32 hitDepth = 1000.0f;
241 f32 idleHeight = (f32)enemy->varTable[3] / 100.0;
242 f32 temp_f24 = idleHeight + (f32)((f32)enemy->varTable[7] / 100.0);
243 f32 undulateAmplitude = (f32)enemy->varTable[1] / 100.0;
244 f32 undulateAmount =
sin_deg(enemy->varTable[2]);
248 npc->
pos.
y = posY + idleHeight + (undulateAmount * undulateAmplitude);
250 npc->
pos.
y = temp_f24 + (undulateAmount * undulateAmplitude);
253 enemy->varTable[2] =
clamp_angle(enemy->varTable[2] + 12);
254 if (script->functionTemp[1] <= 0) {
255 script->functionTemp[1] = aiSettings->playerSearchInterval;
265 script->functionTemp[1]--;
270 if (hitDepth <= (2.0f * npc->
moveSpeed)) {
271 script->functionTemp[1] = (
rand_int(1000) % 3) + 2;
277API_CALLABLE(N(SentinelAI_Main)) {
278 Enemy* enemy = script->owner1.enemy;
280 Bytecode* args = script->ptrReadPos;
299 switch (script->AI_TEMP_STATE) {
void N FlyingAI_LoiterInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Loiter(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N FlyingAI_Wander(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 SentinelAI_GrabPlayer(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_Descend(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_PostLosePlayer(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define SENTINEL_AI_FLAG_CHASING
#define SENTINEL_AI_DESCEND_RATE
#define AI_SENTINEL_FIRST_NPC
#define SENTINEL_AI_FLAG_PLAYING_SOUND
void N SentinelAI_ReturnHome(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_LosePlayerInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_ChaseInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_Chase(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N SentinelAI_LosePlayer(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define AI_SENTINEL_LAST_NPC
void N SentinelAI_ReturnHomeInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
@ AI_STATE_SENTINEL_LOITER
@ AI_STATE_SENTINEL_DESCEND
@ AI_STATE_SENTINEL_LOSE_PLAYER_INIT
@ AI_STATE_SENTINEL_CHASE_INIT
@ AI_STATE_SENTINEL_CHASE
@ AI_STATE_SENTINEL_WANDER
@ AI_STATE_SENTINEL_GRAB_PLAYER
@ AI_STATE_SENTINEL_LOITER_INIT
@ AI_STATE_SENTINEL_DESCEND_INIT
@ AI_STATE_SENTINEL_POST_LOSE_PLAYER
@ AI_STATE_SENTINEL_RETURN_HOME_INIT
@ AI_STATE_SENTINEL_RETURN_HOME
@ AI_STATE_SENTINEL_LOSE_PLAYER
@ AI_STATE_SENTINEL_CAUGHT_PLAYER
@ AI_STATE_SENTINEL_WANDER_INIT
void N SentinelAI_DescendInit(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define sfx_play_sound_at_position
#define npc_raycast_down_sides
@ ENEMY_ANIM_INDEX_MELEE_PRE
@ ENEMY_ANIM_INDEX_MELEE_HIT
@ SOUND_LOOP_SENTINEL_ALARM
@ NPC_FLAG_FLIP_INSTANTLY
s32 evt_get_variable(Evt *script, Bytecode var)
void partner_disable_input(void)
void ai_enemy_play_sound(Npc *npc, s32 arg1, s32 arg2)
s32 disable_player_input(void)
s32 enable_player_input(void)
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
f32 get_clamped_angle_diff(f32, f32)
enum TerritoryShape shape
enum TerritoryShape detectShape
s32 basic_ai_check_player_dist(EnemyDetectVolume *arg0, Enemy *arg1, f32 arg2, f32 arg3, b8 arg4)
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Npc * get_npc_unsafe(s32 npcID)
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
s32 skipPlayerDetectChance
EnemyTerritoryWander wander
EnemyTerritory * territory
void partner_enable_input(void)
void sfx_stop_sound(s32 soundID)
s32 sfx_adjust_env_sound_pos(s32 soundID, s32 sourceFlags, f32 x, f32 y, f32 z)
void set_npc_imgfx_all(s32 spriteIdx, ImgFXType imgfxType, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 imgfxArg5)
s16 turnAroundYawAdjustment
PlayerStatus * gPlayerStatusPtr
PartnerStatus gPartnerStatus