papermario/src/encounter.c
Unnunu 8fd2613bd8
encounters and static npc flags (#843)
* matched update_encounters_neutral

* matched encounter funcs

* replaced NPC flags with ENEMY flags

* cleaning up

* warnings
2022-11-01 12:27:10 +00:00

2744 lines
110 KiB
C

#include "common.h"
#include "battle/battle.h"
#include "script_api/battle.h"
#include "npc.h"
#include "effects.h"
#include "hud_element.h"
#include "world/partners.h"
#include "sprite.h"
#include "sprite/npc/BattleMerlee.h"
ApiStatus ShowMerleeCoinMessage(Evt* script, s32 isInitialCall);
ApiStatus ShowMerleeRanOutMessage(Evt* script, s32 isInitialCall);
ApiStatus FadeInMerlee(Evt* script, s32 isInitialCall);
ApiStatus FadeOutMerlee(Evt* script, s32 isInitialCall);
ApiStatus MerleeUpdateFX(Evt* script, s32 isInitialCall);
ApiStatus MerleeStopFX(Evt* script, s32 isInitialCall);
ApiStatus PlayMerleeGatherFX(Evt* script, s32 isInitialCall);
ApiStatus PlayMerleeOrbFX(Evt* script, s32 isInitialCall);
s32 D_80077C40 = 0;
EvtScript D_80077C44 = {
EVT_WAIT(10)
EVT_CALL(FadeBackgroundToBlack)
EVT_WAIT(10)
EVT_CALL(CreateNpc, NPC_BTL_MERLEE, ANIM_BattleMerlee_Gather)
EVT_CALL(SetNpcFlagBits, NPC_BTL_MERLEE, NPC_FLAG_100, TRUE)
EVT_CALL(SetNpcYaw, NPC_BTL_MERLEE, 0)
EVT_CALL(GetCamLookAtObjVector)
EVT_CALL(SetNpcPos, NPC_BTL_MERLEE, LVar0, LVar1, LVar2)
EVT_THREAD
EVT_CALL(MerleeUpdateFX)
EVT_END_THREAD
EVT_CALL(FadeInMerlee)
EVT_WAIT(30)
EVT_CALL(SetNpcAnimation, NPC_BTL_MERLEE, ANIM_BattleMerlee_Release)
EVT_CALL(MerleeStopFX)
EVT_CALL(UnfadeBackgroundFromBlack)
EVT_WAIT(20)
EVT_THREAD
EVT_CALL(FadeOutMerlee)
EVT_CALL(DeleteNpc, NPC_BTL_MERLEE)
EVT_END_THREAD
EVT_CALL(PlaySound, SOUND_2075)
EVT_CALL(GetPlayerPos, LVar0, LVar1, LVar2)
EVT_CALL(PlayMerleeGatherFX, LVar0, LVar1, LVar2)
EVT_CALL(PlayMerleeOrbFX, LVar0, LVar1, LVar2)
EVT_WAIT(15)
EVT_CALL(ShowMerleeCoinMessage)
EVT_WAIT(15)
EVT_CALL(HasMerleeCasts)
EVT_IF_EQ(LVar0, 1)
EVT_RETURN
EVT_END_IF
EVT_CALL(ShowMerleeRanOutMessage)
EVT_WAIT(15)
EVT_RETURN
EVT_END
};
EvtScript SCRIPT_NpcDefeat = {
EVT_CALL(GetBattleOutcome, LVar0)
EVT_SWITCH(LVar0)
EVT_CASE_EQ(OUTCOME_PLAYER_WON)
EVT_CALL(OnDefeatEnemy)
EVT_CASE_EQ(OUTCOME_PLAYER_LOST)
EVT_CASE_EQ(OUTCOME_PLAYER_FLED)
EVT_END_SWITCH
EVT_RETURN
EVT_END
};
EvtScript D_80077E9C = {
EVT_CALL(OnFleeBattleDrops)
EVT_RETURN
EVT_END
};
EnemyDrops D_80077EB8 = {
.dropFlags = NPC_DROP_FLAGS_80,
.itemDropChance = 10,
.itemDrops = {
{
.item = ITEM_MUSHROOM,
.weight = 50,
.unk_04 = -1,
},
},
.heartDrops = {
{
.cutoff = F16(75),
.generalChance = F16(100),
.attempts = 0,
.chancePerAttempt = 1,
},
{
.cutoff = F16(50),
.generalChance = F16(75),
.attempts = 0,
.chancePerAttempt = 2,
},
{
.cutoff = F16(25),
.generalChance = F16(50),
.attempts = 0,
.chancePerAttempt = 3,
},
{
.cutoff = F16(0),
.generalChance = F16(25),
.attempts = 0,
.chancePerAttempt = 4,
},
},
.flowerDrops = {
{
.cutoff = 1,
.generalChance = 3,
.attempts = 0,
.chancePerAttempt = 0,
},
},
.minCoinBonus = 0,
.maxCoinBonus = 0,
};
EvtScript EnemyNpcHit = {
EVT_CALL(GetOwnerEncounterTrigger, LVar0)
EVT_SWITCH(LVar0)
EVT_CASE_EQ(ENCOUNTER_TRIGGER_NONE)
EVT_CASE_OR_EQ(ENCOUNTER_TRIGGER_JUMP)
EVT_CASE_OR_EQ(ENCOUNTER_TRIGGER_HAMMER)
EVT_CASE_OR_EQ(ENCOUNTER_TRIGGER_PARTNER)
EVT_CALL(GetSelfAnimationFromTable, ENEMY_ANIM_INDEX_HIT, LVar0)
EVT_EXEC_WAIT(EVS_NpcHitRecoil)
EVT_CASE_EQ(ENCOUNTER_TRIGGER_SPIN)
EVT_THREAD
EVT_CALL(func_800458CC, LVar0)
EVT_IF_EQ(LVar0, 0)
EVT_SET(LVarA, 0)
EVT_LOOP(30)
EVT_ADD(LVarA, 40)
EVT_CALL(SetNpcRotation, NPC_SELF, 0, LVarA, 0)
EVT_WAIT(1)
EVT_END_LOOP
EVT_END_IF
EVT_END_THREAD
EVT_END_CASE_GROUP
EVT_END_SWITCH
EVT_RETURN
EVT_END
};
EvtScript EnemyNpcDefeat = {
EVT_CALL(SetNpcRotation, NPC_SELF, 0, 0, 0)
EVT_CALL(GetBattleOutcome, LVar0)
EVT_SWITCH(LVar0)
EVT_CASE_EQ(OUTCOME_PLAYER_WON)
EVT_CALL(DoNpcDefeat)
EVT_CASE_EQ(OUTCOME_PLAYER_FLED)
EVT_CALL(OnPlayerFled, 0)
EVT_CASE_EQ(OUTCOME_ENEMY_FLED)
EVT_CALL(SetEnemyFlagBits, -1, ENEMY_FLAGS_FLED, 1)
EVT_CALL(RemoveNpc, NPC_SELF)
EVT_END_SWITCH
EVT_RETURN
EVT_END
};
extern s8 D_8009A63C;
extern s8 D_8009A654;
extern s16 gFirstStrikeMessagePos;
extern s8 D_8009A670;
extern s32 D_800A0BA0;
extern f32 D_800A0BA4;
extern Evt* D_800A0BB0;
extern s32 D_800A0BB4;
extern EffectInstance* WorldMerleeOrbEffect;
extern EffectInstance* WorldMerleeWaveEffect;
void set_battle_formation(Battle*);
void func_800E97E4(void);
void partner_handle_after_battle(void);
s32 get_coin_drop_amount(Enemy* enemy);
s32 get_defeated(s32 mapID, s32 encounterID) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
s32 encounterIdx = encounterID / 32;
s32 encounterShift = encounterID % 32;
return currentEncounter->defeatFlags[mapID][encounterIdx] & (1 << encounterShift);
}
void set_defeated(s32 mapID, s32 encounterID) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
s32 encounterIdx = encounterID / 32;
s32 encounterShift;
s32 flag;
flag = encounterID % 32;
encounterShift = flag;
flag = currentEncounter->defeatFlags[mapID][encounterIdx];
currentEncounter->defeatFlags[mapID][encounterIdx] = flag | (1 << encounterShift);
// TODO: The below should work but has regalloc issues:
/*EncounterStatus *currentEncounter = &gCurrentEncounter;
s32 encounterIdx = encounterID / 32;
s32 encounterShift = encounterID % 32;
currentEncounter->defeatFlags[mapID][encounterIdx] |= (1 << encounterShift);*/
}
ApiStatus ShowMerleeCoinMessage(Evt* script, s32 isInitialCall) {
if (isInitialCall) {
show_merlee_message(0, 60);
}
if (is_merlee_message_done()) {
return ApiStatus_BLOCK;
} else {
return ApiStatus_DONE2;
}
}
ApiStatus ShowMerleeRanOutMessage(Evt* script, s32 isInitialCall) {
if (isInitialCall) {
show_merlee_message(1, 60);
}
if (is_merlee_message_done()) {
return ApiStatus_BLOCK;
} else {
return ApiStatus_DONE2;
}
}
ApiStatus FadeBackgroundToBlack(Evt* script, s32 isInitialCall) {
if (isInitialCall) {
mdl_set_all_fog_mode(1);
*gBgRenderTypePtr = BACKGROUND_RENDER_TYPE_1;
set_background_color_blend(0, 0, 0, 0);
script->functionTemp[0] = 25;
}
set_background_color_blend(0, 0, 0, ((25 - script->functionTemp[0]) * 10) & 254);
script->functionTemp[0]--;
if (script->functionTemp[0] == 0) {
return ApiStatus_DONE2;
} else {
return ApiStatus_BLOCK;
}
}
ApiStatus UnfadeBackgroundFromBlack(Evt* script, s32 isInitialCall) {
if (isInitialCall) {
script->functionTemp[0] = 25;
}
set_background_color_blend(0, 0, 0, (script->functionTemp[0] * 10) & 0xFE);
script->functionTemp[0] -= 5;
if (script->functionTemp[0] == 0) {
set_background_color_blend(0, 0, 0, 0);
return ApiStatus_DONE2;
} else {
return ApiStatus_BLOCK;
}
}
ApiStatus FadeInMerlee(Evt* script, s32 isInitialCall) {
Npc* npc = get_npc_unsafe(NPC_BTL_MERLEE);
if (isInitialCall) {
sfx_play_sound(SOUND_24B);
npc->alpha = 0;
}
npc->alpha += 17;
if ((u32)(npc->alpha & 0xFF) >= 0xFF) {
npc->alpha = 0xFF;
return ApiStatus_DONE1;
} else {
return ApiStatus_BLOCK;
}
}
ApiStatus FadeOutMerlee(Evt* script, s32 isInitialCall) {
Npc* npc = get_npc_unsafe(NPC_BTL_MERLEE);
npc->alpha -= 17;
if (npc->alpha == 0) {
npc->alpha = 0;
return ApiStatus_DONE1;
} else {
return ApiStatus_BLOCK;
}
}
// same as BattleMerleeUpdateFX aside from syms
ApiStatus MerleeUpdateFX(Evt* script, s32 isInitialCall) {
Npc* merlee = get_npc_unsafe(NPC_BTL_MERLEE);
EnergyOrbWaveFXData* effectData;
if (isInitialCall) {
script->functionTemp[1] = 0;
D_800A0BA4 = merlee->pos.y;
WorldMerleeOrbEffect = fx_energy_orb_wave(0, merlee->pos.x, merlee->pos.y, merlee->pos.z, 0.4f, 0);
WorldMerleeWaveEffect = fx_energy_orb_wave(3, merlee->pos.x, merlee->pos.y, merlee->pos.z, 0.00001f, 0);
D_800A0BB8 = 0;
D_800A0BA0 = 12;
sfx_play_sound(SOUND_2074);
}
merlee->pos.y = D_800A0BA4 + sin_rad(DEG_TO_RAD(script->functionTemp[1])) * 3.0f;
script->functionTemp[1] += 10;
script->functionTemp[1] = clamp_angle(script->functionTemp[1]);
effectData = WorldMerleeOrbEffect->data.energyOrbWave;
effectData->pos.x = merlee->pos.x;
effectData->pos.y = merlee->pos.y + 16.0f;
effectData->pos.z = merlee->pos.z;
effectData = WorldMerleeWaveEffect->data.energyOrbWave;
effectData->pos.x = merlee->pos.x;
effectData->pos.y = merlee->pos.y + 16.0f;
effectData->pos.z = merlee->pos.z + 5.0f;
if (D_800A0BB8 == 2) {
WorldMerleeOrbEffect->data.energyOrbWave->scale = 0.00001f;
WorldMerleeWaveEffect->data.energyOrbWave->scale = 0.00001f;
WorldMerleeOrbEffect->flags |= EFFECT_INSTANCE_FLAGS_10;
WorldMerleeWaveEffect->flags |= EFFECT_INSTANCE_FLAGS_10;
return ApiStatus_DONE1;
}
if (D_800A0BB8 == 1) {
effectData = WorldMerleeOrbEffect->data.energyOrbWave;
effectData->scale += 0.35;
if (effectData->scale > 3.5) {
effectData->scale = 3.5f;
}
if (D_800A0BA0 != 0) {
D_800A0BA0--;
} else {
effectData = WorldMerleeWaveEffect->data.energyOrbWave;
effectData->scale += 0.5;
if (effectData->scale > 5.0) {
D_800A0BB8 = 2;
}
}
}
return ApiStatus_BLOCK;
}
ApiStatus MerleeStopFX(Evt* script, s32 isInitialCall) {
D_800A0BB8 = 1;
return ApiStatus_DONE2;
}
ApiStatus GetCamLookAtObjVector(Evt* script, s32 isInitialCall) {
script->varTable[0] = gCameras[gCurrentCameraID].lookAt_obj.x;
script->varTable[1] = gCameras[gCurrentCameraID].lookAt_obj.y;
script->varTable[2] = gCameras[gCurrentCameraID].lookAt_obj.z;
return ApiStatus_DONE2;
}
ApiStatus HasMerleeCasts(Evt* script, s32 isInitialCall) {
script->varTable[0] = FALSE;
if (gPlayerData.merleeCastsLeft > 0) {
script->varTable[0] = TRUE;
}
return ApiStatus_DONE2;
}
ApiStatus PlayMerleeGatherFX(Evt* script, s32 isInitialCall) {
Bytecode* args = script->ptrReadPos;
s32 var0 = evt_get_variable(script, *args++);
s32 var1 = evt_get_variable(script, *args++);
s32 var2 = evt_get_variable(script, *args++);
fx_energy_in_out(6, var0, var1, var2, 1.2f, 30);
return ApiStatus_DONE2;
}
ApiStatus PlayMerleeOrbFX(Evt* script, s32 isInitialCall) {
Bytecode* args = script->ptrReadPos;
s32 var0 = evt_get_variable(script, *args++);
s32 var1 = evt_get_variable(script, *args++);
s32 var2 = evt_get_variable(script, *args++);
fx_energy_orb_wave(9, var0, var1, var2, 5.0f, 15);
return ApiStatus_DONE2;
}
ApiStatus OnDefeatEnemy(Evt* script, s32 isInitialCall) {
Enemy* enemy = script->owner1.enemy;
Npc* npc = get_npc_unsafe(enemy->npcID);
s32 temp1;
if (isInitialCall) {
script->functionTemp[0] = 0;
script->functionTemp[1] = 20;
}
if (script->functionTemp[1] & 1) {
npc->flags &= ~NPC_FLAG_2;
} else {
npc->flags |= NPC_FLAG_2;
}
if (script->functionTemp[1] == 15) {
sfx_play_sound(SOUND_DEATH);
fx_damage_stars(1, npc->pos.x, npc->pos.y + (npc->collisionHeight / 2), npc->pos.z, 0, -1.0f, 0, 10);
}
temp1 = script->functionTemp[1];
if (script->functionTemp[1] == 10) {
fx_big_smoke_puff(npc->pos.x, npc->pos.y + 10.0f, npc->pos.z + 10.0f);
if (script->functionTemp[1] == temp1) { // what? (never can be false, seemingly)
spawn_drops(enemy);
}
}
script->functionTemp[1]--;
if (script->functionTemp[1] == 0) {
npc->flags |= NPC_FLAG_2;
return ApiStatus_DONE1;
}
return ApiStatus_BLOCK;
}
ApiStatus OnFleeBattleDrops(Evt* script, s32 isInitialCall) {
PlayerStatus* playerStatus = &gPlayerStatus;
PlayerData* playerData = &gPlayerData;
if (isInitialCall) {
script->functionTemp[0] = 0;
script->functionTemp[1] = 40;
script->functionTemp[2] = 0;
}
script->functionTemp[2]++;
if (script->functionTemp[2] >= 5) {
if (rand_int(100) < 50) {
if (playerData->coins != 0) {
playerData->coins--;
make_item_entity_delayed(ITEM_COIN, playerStatus->position.x, playerStatus->position.y + playerStatus->colliderHeight,
playerStatus->position.z, 3, 0, 0);
}
}
script->functionTemp[2] = 0;
}
return --script->functionTemp[1] == 0;
}
void update_encounters_neutral(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
PlayerStatus* playerStatus = &gPlayerStatus;
Camera* camera = &gCameras[gCurrentCameraID];
s32 screenX, screenY, screenZ;
f32 npcX, npcY, npcZ;
f32 npcYaw;
f32 testX, testY, testZ;
f32 x, y, z;
s32 e;
f32 playerX, playerY, playerZ;
f32 playerYaw;
Encounter* encounter;
Evt* script;
Npc* npc;
f32 distance;
f32 colHeight;
f32 colRadius;
f32 hammerDir;
s32 cond;
s32 cond2;
s32 firstStrikeType;
s32 aiPaused;
Enemy* enemy;
Enemy* currentEnemy;
s32 i;
f32 playerJumpColHeight = 37.0f;
f32 playerColRadius = 14.0f;
f32 playerColHeight = 18.0f;
f32 dx, dz;
f32 angle1, angle2;
do {
if (currentEncounter->hitType == ENCOUNTER_TRIGGER_CONVERSATION) {
goto START_BATTLE;
}
} while (0);
currentEncounter->songID = -1;
currentEncounter->unk_18 = -1;
currentEncounter->hitType = 0;
currentEncounter->allowFleeing = FALSE;
currentEncounter->dropWhackaBump = FALSE;
currentEncounter->flags &= ~ENCOUNTER_STATUS_FLAGS_1;
currentEncounter->flags &= ~ENCOUNTER_STATUS_FLAGS_2;
currentEncounter->flags &= ~ENCOUNTER_STATUS_FLAGS_4;
playerX = playerStatus->position.x;
playerY = playerStatus->position.y;
playerZ = playerStatus->position.z;
playerYaw = playerStatus->spriteFacingAngle;
if (playerYaw < 180.0f) {
playerYaw = clamp_angle(camera->currentYaw - 90.0f);
} else {
playerYaw = clamp_angle(camera->currentYaw + 90.0f);
}
if (currentEncounter->battleTriggerCooldown != 0) {
if (!(gOverrideFlags & GLOBAL_OVERRIDES_40)) {
currentEncounter->battleTriggerCooldown--;
}
if (playerStatus->blinkTimer != 0) {
if (!(playerStatus->flags & PS_FLAGS_INPUT_DISABLED)) {
playerStatus->blinkTimer = currentEncounter->battleTriggerCooldown;
} else {
playerStatus->blinkTimer = 1;
}
}
}
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
npc = get_npc_unsafe(enemy->npcID);
if (enemy->aiPaused != 0) {
if (!(gOverrideFlags & GLOBAL_OVERRIDES_40)) {
enemy->aiPaused--;
aiPaused = enemy->aiPaused;
} else {
aiPaused = 0;
}
if (aiPaused & 1) {
npc->flags |= NPC_FLAG_80000000;
enemy->flags |= ENEMY_FLAGS_80000000;
} else {
npc->flags &= ~NPC_FLAG_80000000;
enemy->flags &= ~ENEMY_FLAGS_80000000;
}
script = get_script_by_id(enemy->auxScriptID);
if (script != NULL) {
set_script_flags(script, EVT_FLAG_SUSPENDED);
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
set_script_flags(script, EVT_FLAG_SUSPENDED);
}
if (enemy->flags & ENEMY_FLAGS_80000) {
script = get_script_by_id(enemy->auxScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
}
} else if (!(enemy->flags & ENEMY_FLAGS_200000)) {
get_screen_coords(gCurrentCameraID, npc->pos.x, npc->pos.y, npc->pos.z, &screenX, &screenY, &screenZ);
if ((screenX < -160 || screenX > 480 || screenY < -120 || screenY > 360 || screenZ < 0) && !(enemy->flags & ENEMY_FLAGS_1)) {
npc->flags |= NPC_FLAG_80000000;
enemy->flags |= ENEMY_FLAGS_80000000;
script = get_script_by_id(enemy->auxScriptID);
if (script != NULL) {
set_script_flags(script, EVT_FLAG_SUSPENDED);
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
set_script_flags(script, EVT_FLAG_SUSPENDED);
}
} else {
npc->flags &= ~NPC_FLAG_80000000;
enemy->flags &= ~ENEMY_FLAGS_80000000;
script = get_script_by_id(enemy->auxScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
}
} else {
npc->flags &= ~NPC_FLAG_80000000;
enemy->flags &= ~ENEMY_FLAGS_80000000;
script = get_script_by_id(enemy->auxScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
}
if (enemy->flags & ENEMY_FLAGS_80000000) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_1) {
if (!(enemy->flags & ENEMY_FLAGS_400000)) {
if (npc == playerStatus->encounteredNPC) {
enemy->unk_E0 = npc->yaw;
npc->yaw = atan2(npc->pos.x, npc->pos.z, playerStatus->position.x, playerStatus->position.z);
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
set_script_flags(script, EVT_FLAG_SUSPENDED);
}
} else {
if (enemy->unk_E0 != 12345) {
npc->yaw = enemy->unk_E0;
enemy->unk_E0 = 12345;
}
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
}
} else {
script = get_script_by_id(enemy->aiScriptID);
if (script != NULL) {
clear_script_flags(script, EVT_FLAG_SUSPENDED);
}
}
}
if (currentEncounter->battleTriggerCooldown != 0 ||
gGameStatusPtr->debugEnemyContact == 1 ||
(playerStatus->flags & PS_FLAGS_80000) ||
(gOverrideFlags & GLOBAL_OVERRIDES_40) ||
gPartnerActionStatus.actingPartner == PARTNER_BOW ||
(enemy->flags & ENEMY_FLAGS_1) ||
(gOverrideFlags & (GLOBAL_OVERRIDES_DISABLE_BATTLES | GLOBAL_OVERRIDES_200 | GLOBAL_OVERRIDES_400 | GLOBAL_OVERRIDES_800)) ||
is_picking_up_item()) {
continue;
}
do {
if (!(enemy->flags & ENEMY_FLAGS_10000000) && partner_test_enemy_collision(npc) != 0) {
currentEncounter->hitType = ENCOUNTER_TRIGGER_PARTNER;
enemy->encountered = ENCOUNTER_TRIGGER_PARTNER;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
goto START_BATTLE;
}
} while (0);
npcX = npc->pos.x;
npcY = npc->pos.y;
npcZ = npc->pos.z;
npcYaw = npc->yaw;
colHeight = npc->collisionHeight;
colRadius = npc->collisionRadius / 2;
if (enemy->unk_DC != 0) {
npcYaw = npc->yawCamOffset;
if (npcYaw < 180.0f) {
npcYaw = clamp_angle(camera->currentYaw - 90.0f);
} else {
npcYaw = clamp_angle(camera->currentYaw + 90.0f);
}
add_vec2D_polar(&npcX, &npcZ, enemy->unk_DC, npcYaw);
}
dx = npcX - playerX;
dz = npcZ - playerZ;
distance = sqrtf(SQ(dx) + SQ(dz));
switch (playerStatus->actionState) {
case ACTION_STATE_HAMMER:
x = playerX;
y = playerY;
z = playerZ;
if (clamp_angle(playerStatus->spriteFacingAngle) < 180.0f) {
hammerDir = clamp_angle(camera->currentYaw - 90.0f);
if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
hammerDir = clamp_angle(hammerDir + 30.0f);
}
} else {
hammerDir = clamp_angle(camera->currentYaw + 90.0f);
if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
hammerDir = clamp_angle(hammerDir - 30.0f);
}
}
add_vec2D_polar(&x, &z, 24.0f, hammerDir);
dx = npcX - x;
dz = npcZ - z;
distance = sqrtf(SQ(dx) + SQ(dz));
if (enemy->flags & ENEMY_FLAGS_IGNORE_HAMMER) {
break;
}
if (!(playerStatus->flags & PS_FLAGS_1000000)) {
break;
}
if (distance >= playerColRadius + colRadius || y > npcY + colHeight || npcY > y + playerColHeight) {
break;
}
testX = npcX;
testY = npcY;
testZ = npcZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(npcX, npcZ, playerX, playerZ), colHeight, colRadius * 2.0f) != 0) {
testX = playerX;
testY = playerY;
testZ = playerZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(playerX, playerZ, npcX, npcZ), colHeight, colRadius * 2.0f) != 0) {
break;
}
}
if (enemy->unk_07 != 0) {
npcX = enemy->unk_10.x;
npcY = enemy->unk_10.y;
npcZ = enemy->unk_10.z;
}
angle1 = fabsf(get_clamped_angle_diff(atan2(playerX, playerZ, npcX, npcZ), playerYaw));
angle2 = fabsf(get_clamped_angle_diff(atan2(npcX, npcZ, playerX, playerZ), npcYaw));
cond = FALSE;
if (angle1 >= 90.0f && angle2 >= 90.0f) {
cond = FALSE;
}
if (angle1 < 90.0f && angle2 >= 90.0f) {
cond = TRUE;
}
if (angle1 >= 90.0f && angle2 < 90.0f) {
cond = FALSE;
}
if (angle1 < 90.0f && angle2 < 90.0f) {
cond = TRUE;
}
if (cond) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_NORMAL, 0, playerStatus->position.x, playerStatus->position.y, playerStatus->position.z);
currentEncounter->hitType = ENCOUNTER_TRIGGER_HAMMER;
currentEncounter->hitTier = gPlayerData.hammerLevel;
enemy->encountered = ENCOUNTER_TRIGGER_HAMMER;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
goto START_BATTLE;
}
break;
case ACTION_STATE_JUMP:
case ACTION_STATE_BOUNCE:
case ACTION_STATE_FALLING:
case ACTION_STATE_STEP_DOWN:
case ACTION_STATE_LAND:
case ACTION_STATE_STEP_DOWN_LAND:
case ACTION_STATE_SPIN_JUMP:
case ACTION_STATE_SPIN_POUND:
case ACTION_STATE_TORNADO_JUMP:
case ACTION_STATE_TORNADO_POUND:
x = playerX;
z = playerZ;
if (!(enemy->flags & ENEMY_FLAGS_IGNORE_JUMP)) {
if (distance >= playerColRadius + colRadius) {
continue;
}
if (playerY > npcY + colHeight || npcY > playerY + playerJumpColHeight) {
continue;
}
testX = npcX;
testY = npcY;
testZ = npcZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(npcX, npcZ, playerX, playerZ), colHeight, colRadius * 2.0f) != 0) {
testX = playerX;
testY = playerY;
testZ = playerZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(playerX, playerZ, npcX, npcZ), colHeight, colRadius * 2.0f) != 0) {
break;
}
}
cond = FALSE;
if (npcY + colHeight < playerY + playerJumpColHeight * 0.5f) {
if (playerStatus->actionState == ACTION_STATE_FALLING ||
playerStatus->actionState == ACTION_STATE_STEP_DOWN ||
playerStatus->actionState == ACTION_STATE_LAND ||
playerStatus->actionState == ACTION_STATE_STEP_DOWN_LAND ||
playerStatus->actionState == ACTION_STATE_SPIN_JUMP ||
playerStatus->actionState == ACTION_STATE_SPIN_POUND ||
playerStatus->actionState == ACTION_STATE_TORNADO_JUMP ||
playerStatus->actionState == ACTION_STATE_TORNADO_POUND) {
cond = TRUE;
}
}
if (playerY + playerJumpColHeight < npcY + colHeight * 0.5f) {
cond = FALSE;
}
if (cond) {
if (gPlayerData.bootsLevel < 0) {
currentEncounter->hitType = ENCOUNTER_TRIGGER_NONE;
enemy->encountered = ENCOUNTER_TRIGGER_NONE;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
currentEncounter->hitTier = 0;
goto START_BATTLE;
}
currentEncounter->hitType = ENCOUNTER_TRIGGER_JUMP;
switch (playerStatus->actionState) {
case ACTION_STATE_JUMP:
case ACTION_STATE_BOUNCE:
case ACTION_STATE_FALLING:
case ACTION_STATE_STEP_DOWN:
case ACTION_STATE_LAND:
case ACTION_STATE_STEP_DOWN_LAND:
currentEncounter->hitTier = 0;
break;
case ACTION_STATE_SPIN_JUMP:
case ACTION_STATE_SPIN_POUND:
currentEncounter->hitTier = 1;
break;
case ACTION_STATE_TORNADO_JUMP:
case ACTION_STATE_TORNADO_POUND:
currentEncounter->hitTier = 2;
break;
}
sfx_play_sound_at_position(SOUND_HIT_PLAYER_NORMAL, 0, playerStatus->position.x, playerStatus->position.y, playerStatus->position.z);
enemy->encountered = 2;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
goto START_BATTLE;
}
}
break;
}
if (enemy->flags & ENEMY_FLAGS_IGNORE_TOUCH) {
continue;
}
dx = npcX - playerX;
dz = npcZ - playerZ;
distance = sqrtf(SQ(dx) + SQ(dz));
if (distance >= (playerColRadius + colRadius) * 0.8) {
continue;
}
if (npcY + colHeight < playerY) {
continue;
}
if (playerY + playerJumpColHeight < npcY) {
continue;
}
testX = npcX;
testY = npcY;
testZ = npcZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(npcX, npcZ, playerX, playerZ), colHeight, colRadius * 2.0f) != 0) {
testX = playerX;
testY = playerY;
testZ = playerZ;
if (npc_test_move_taller_with_slipping(COLLISION_CHANNEL_10000, &testX, &testY, &testZ, distance, atan2(playerX, playerZ, npcX, npcZ), colHeight, colRadius * 2.0f) != 0) {
continue;
}
}
cond = FALSE;
if (is_ability_active(ABILITY_SPIN_ATTACK) && gPlayerData.level >= enemy->npcSettings->level) {
cond = !currentEncounter->scriptedBattle;
}
if (is_ability_active(ABILITY_DIZZY_ATTACK)) {
cond = TRUE;
}
if ((playerStatus->animFlags & PA_FLAGS_SPINNING) && !(enemy->flags & ENEMY_FLAGS_20000000) && cond) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_NORMAL, 0, playerStatus->position.x, playerStatus->position.y, playerStatus->position.z);
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
currentEncounter->hitType = ENCOUNTER_TRIGGER_SPIN;
playerStatus->animFlags |= PA_FLAGS_20000;
enemy->encountered = ENCOUNTER_TRIGGER_SPIN;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
} else {
currentEncounter->hitType = ENCOUNTER_TRIGGER_NONE;
playerStatus->animFlags &= ~PA_FLAGS_20000;
enemy->encountered = ENCOUNTER_TRIGGER_NONE;
currentEncounter->currentEncounter = encounter;
currentEncounter->currentEnemy = enemy;
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
firstStrikeType = FIRST_STRIKE_NONE;
if (enemy->unk_07 != 0) {
if (is_ability_active(ABILITY_CHILL_OUT)) {
firstStrikeType = FIRST_STRIKE_NONE;
} else {
firstStrikeType = FIRST_STRIKE_ENEMY;
}
}
if (!is_ability_active(ABILITY_BUMP_ATTACK) || gPlayerData.level < enemy->npcSettings->level || (enemy->flags & ENEMY_FLAGS_40)) {
currentEncounter->firstStrikeType = firstStrikeType;
} else {
if (!currentEncounter->scriptedBattle) {
firstStrikeType = FIRST_STRIKE_NONE;
}
currentEncounter->firstStrikeType = firstStrikeType;
}
}
goto START_BATTLE;
}
}
START_BATTLE:
switch (currentEncounter->hitType) {
case 0:
break;
case ENCOUNTER_TRIGGER_NONE:
currentEnemy = enemy = currentEncounter->currentEnemy;
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if ((currentEnemy->flags & ENEMY_FLAGS_40) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->hitBytecode != NULL) {
enemy->encountered = ENCOUNTER_TRIGGER_NONE;
script = start_script(enemy->hitBytecode, EVT_PRIORITY_A, 0);
enemy->hitScript = script;
enemy->hitScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
disable_player_input();
partner_disable_input();
if (playerStatus->actionState != ACTION_STATE_TORNADO_JUMP &&
playerStatus->actionState != ACTION_STATE_TORNADO_POUND &&
playerStatus->actionState != ACTION_STATE_SPIN_JUMP &&
playerStatus->actionState != ACTION_STATE_SPIN_POUND) {
playerStatus->flags |= PS_FLAGS_40000;
}
if (!is_ability_active(ABILITY_CHILL_OUT) && currentEncounter->firstStrikeType == FIRST_STRIKE_ENEMY) {
set_action_state(ACTION_STATE_ENEMY_FIRST_STRIKE);
npc = get_npc_unsafe(enemy->npcID);
sfx_play_sound_at_position(SOUND_HIT_PLAYER_NORMAL, 0, npc->pos.x, npc->pos.y, npc->pos.z);
}
currentEncounter->scriptedBattle = FALSE;
gEncounterState = ENCOUNTER_STATE_PRE_BATTLE;
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT;
break;
case ENCOUNTER_TRIGGER_SPIN:
currentEnemy = enemy = currentEncounter->currentEnemy;
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if ((currentEnemy->flags & ENEMY_FLAGS_40) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->hitBytecode != NULL) {
enemy->encountered = ENCOUNTER_TRIGGER_SPIN;
script = start_script(enemy->hitBytecode, EVT_PRIORITY_A, 0);
enemy->hitScript = script;
enemy->hitScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
disable_player_input();
partner_disable_input();
currentEncounter->scriptedBattle = FALSE;
gEncounterState = ENCOUNTER_STATE_PRE_BATTLE;
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT;
playerStatus->flags |= PS_FLAGS_40000;
break;
case ENCOUNTER_TRIGGER_JUMP:
currentEnemy = enemy = currentEncounter->currentEnemy;
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
encounter = currentEncounter->currentEncounter;
cond2 = FALSE;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if ((currentEnemy->flags & ENEMY_FLAGS_40) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->hitBytecode != NULL) {
enemy->encountered = ENCOUNTER_TRIGGER_JUMP;
script = start_script(enemy->hitBytecode, EVT_PRIORITY_A, 0);
enemy->hitScript = script;
enemy->hitScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
npc = get_npc_unsafe(enemy->npcID);
cond2 = TRUE;
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
} else if (!(enemy->flags & ENEMY_FLAGS_1)) {
npc = get_npc_unsafe(enemy->npcID);
cond2 = TRUE;
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
}
}
disable_player_input();
partner_disable_input();
playerStatus->flags |= PS_FLAGS_40000;
if (cond2) {
start_bounce_a();
}
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
currentEncounter->scriptedBattle = FALSE;
sfx_play_sound(0);
gEncounterState = ENCOUNTER_STATE_PRE_BATTLE;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT;
break;
case ENCOUNTER_TRIGGER_HAMMER:
currentEnemy = enemy = currentEncounter->currentEnemy;
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if ((currentEnemy->flags & ENEMY_FLAGS_40) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->hitBytecode != NULL) {
enemy->encountered = ENCOUNTER_TRIGGER_HAMMER;
script = start_script(enemy->hitBytecode, EVT_PRIORITY_A, 0);
enemy->hitScript = script;
enemy->hitScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
npc = get_npc_unsafe(enemy->npcID);
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
} else if (!(enemy->flags & ENEMY_FLAGS_1)) {
npc = get_npc_unsafe(enemy->npcID);
testX = playerStatus->position.x + ((npc->pos.x - playerStatus->position.x) * 0.5f);
testY = playerStatus->position.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->position.y + playerStatus->colliderHeight)) * 0.5f);
testZ = playerStatus->position.z + ((npc->pos.z - playerStatus->position.z) * 0.5f);
fx_damage_stars(3, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 0.0f, -1.0f, 0.0f, 3);
}
}
disable_player_input();
partner_disable_input();
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
currentEncounter->scriptedBattle = FALSE;
playerStatus->flags |= PS_FLAGS_40000;
sfx_play_sound(0);
gEncounterState = ENCOUNTER_STATE_PRE_BATTLE;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT;
break;
case ENCOUNTER_TRIGGER_CONVERSATION:
suspend_all_group(EVT_GROUP_01);
enemy = currentEncounter->currentEnemy;
if (enemy != NULL && enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
enemy = currentEncounter->currentEnemy;
if (enemy->interactBytecode != NULL) {
enemy->encountered = 5;
script = start_script(enemy->interactBytecode, EVT_PRIORITY_A, 0);
enemy->interactScript = script;
enemy->interactScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
disable_player_input();
partner_disable_input();
set_action_state(ACTION_STATE_TALK);
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
func_800EF3D4(1);
gEncounterState = ENCOUNTER_STATE_CONVERSATION;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_CONVERSATION_INIT;
break;
case ENCOUNTER_TRIGGER_PARTNER:
currentEnemy = enemy = currentEncounter->currentEnemy;
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if ((currentEnemy->flags & ENEMY_FLAGS_40) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->hitBytecode != NULL) {
enemy->encountered = ENCOUNTER_TRIGGER_PARTNER;
script = start_script(enemy->hitBytecode, EVT_PRIORITY_A, 0);
enemy->hitScript = script;
enemy->hitScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
npc = get_npc_unsafe(enemy->npcID);
testX = npc->pos.x;
testY = npc->pos.y + npc->collisionHeight;
testZ = npc->pos.z;
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
} else if (!(enemy->flags & ENEMY_FLAGS_1)) {
npc = get_npc_unsafe(enemy->npcID);
testX = npc->pos.x;
testY = npc->pos.y + npc->collisionHeight;
testZ = npc->pos.z;
fx_damage_stars(3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
}
}
disable_player_input();
partner_disable_input();
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 0;
currentEncounter->scriptedBattle = FALSE;
playerStatus->flags |= PS_FLAGS_40000;
sfx_play_sound(0);
gEncounterState = ENCOUNTER_STATE_PRE_BATTLE;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT;
break;
}
}
void draw_encounters_neutral(void) {
}
void update_encounters_pre_battle(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
PlayerData* playerData = &gPlayerData;
Encounter* encounter;
Enemy* enemy;
s32 i;
s32 j;
switch (gEncounterSubState) {
case ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT:
currentEncounter->fadeOutAmount = 0;
currentEncounter->unk_94 = 1;
currentEncounter->fadeOutAccel = 1;
currentEncounter->unk_08 = -1;
D_8009A654 = FALSE;
D_80077C40 = 0;
suspend_all_group(EVT_GROUP_10);
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter != NULL) {
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy != NULL && !(enemy->flags & ENEMY_FLAGS_20)) {
if (enemy->aiScript != NULL) {
suspend_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
suspend_all_script(enemy->auxScriptID);
}
}
}
}
}
enemy = currentEncounter->currentEnemy;
if ((enemy->flags & ENEMY_FLAGS_100000) && !currentEncounter->scriptedBattle) {
currentEncounter->unk_94 = 0;
currentEncounter->battleStartCountdown = 0;
partner_handle_before_battle();
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_3;
return;
}
if (gGameStatusPtr->debugEnemyContact == 2) {
currentEncounter->unk_94 = 0;
currentEncounter->battleStartCountdown = 10;
partner_handle_before_battle();
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_AUTO_WIN;
return;
}
enemy = currentEncounter->currentEnemy;
if (currentEncounter->hitType != ENCOUNTER_TRIGGER_NONE &&
currentEncounter->hitType != ENCOUNTER_TRIGGER_SPIN &&
is_ability_active(ABILITY_FIRST_ATTACK) &&
(playerData->level >= enemy->npcSettings->level) &&
!(enemy->flags & ENEMY_FLAGS_40) &&
!currentEncounter->scriptedBattle)
{
currentEncounter->unk_94 = 0;
currentEncounter->battleStartCountdown = 0xA;
D_80077C40 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_AUTO_WIN;
return;
}
enemy = currentEncounter->currentEnemy;
if ((
(is_ability_active(ABILITY_BUMP_ATTACK)) &&
(playerData->level >= enemy->npcSettings->level) &&
(!(enemy->flags & ENEMY_FLAGS_40) &&
!(currentEncounter->scriptedBattle))
) || (
(enemy = currentEncounter->currentEnemy,
(currentEncounter->hitType == ENCOUNTER_TRIGGER_SPIN)) &&
(is_ability_active(ABILITY_SPIN_ATTACK)) &&
playerData->level >= enemy->npcSettings->level &&
!(enemy->flags & ENEMY_FLAGS_40) &&
!currentEncounter->scriptedBattle
))
{
currentEncounter->battleStartCountdown = 10;
D_80077C40 = 1;
currentEncounter->unk_94 = 0;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_AUTO_WIN;
return;
}
if (currentEncounter->songID < 0) {
switch (currentEncounter->firstStrikeType) {
case 0:
bgm_set_battle_song(SONG_NORMAL_BATTLE, FIRST_STRIKE_NONE);
break;
case 1:
bgm_set_battle_song(SONG_NORMAL_BATTLE, FIRST_STRIKE_PLAYER);
break;
case 2:
bgm_set_battle_song(SONG_NORMAL_BATTLE, FIRST_STRIKE_ENEMY);
break;
}
} else {
bgm_set_battle_song(currentEncounter->songID, FIRST_STRIKE_NONE);
}
bgm_push_battle_song();
D_8009A654 = TRUE;
currentEncounter->battleStartCountdown = 10;
gEncounterSubState = ENCOUNTER_SUBSTATE_PRE_BATTLE_LOAD_BATTLE;
case ENCOUNTER_SUBSTATE_PRE_BATTLE_LOAD_BATTLE:
if (currentEncounter->fadeOutAmount == 255) {
if (currentEncounter->battleStartCountdown != 0) {
currentEncounter->battleStartCountdown--;
break;
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy != NULL &&
((!(enemy->flags & ENEMY_FLAGS_8) || enemy == currentEncounter->currentEnemy)) &&
!(enemy->flags & ENEMY_FLAGS_20) &&
enemy->hitScript != NULL)
{
kill_script_by_ID(enemy->hitScriptID);
enemy->hitScript = NULL;
}
}
partner_handle_before_battle();
currentEncounter->dizzyAttackStatus = 0;
currentEncounter->dizzyAttackDuration = 0;
enemy = currentEncounter->currentEnemy;
currentEncounter->unk_10 = enemy->unk_B5;
if (is_ability_active(ABILITY_DIZZY_ATTACK) && currentEncounter->hitType == ENCOUNTER_TRIGGER_SPIN) {
currentEncounter->dizzyAttackStatus = 4;
currentEncounter->dizzyAttackDuration = 3;
}
sfx_stop_sound(SOUND_2111);
sfx_stop_sound(SOUND_2112);
sfx_stop_sound(SOUND_2113);
sfx_stop_sound(SOUND_2114);
set_battle_formation(NULL);
set_battle_stage(encounter->stage);
load_battle(encounter->battle);
currentEncounter->unk_07 = 1;
currentEncounter->unk_08 = 0;
currentEncounter->merleeCoinBonus = 0;
currentEncounter->damageTaken = 0;
currentEncounter->coinsEarned = 0;
currentEncounter->fadeOutAccel = 0;
currentEncounter->fadeOutAmount = 255;
set_screen_overlay_params_front(0, 255.0f);
gEncounterState = ENCOUNTER_STATE_POST_BATTLE;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_INIT;
}
break;
case ENCOUNTER_SUBSTATE_PRE_BATTLE_AUTO_WIN:
if (currentEncounter->battleStartCountdown != 0) {
currentEncounter->battleStartCountdown--;
break;
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy != NULL &&
(!(enemy->flags & ENEMY_FLAGS_8) || enemy == currentEncounter->currentEnemy) &&
!(enemy->flags & ENEMY_FLAGS_20) &&
(enemy->hitScript != 0))
{
kill_script_by_ID(enemy->hitScriptID);
enemy->hitScript = NULL;
}
}
currentEncounter->unk_08 = 1;
currentEncounter->unk_07 = 1;
currentEncounter->battleOutcome = OUTCOME_PLAYER_WON;
currentEncounter->merleeCoinBonus = 0;
currentEncounter->damageTaken = 0;
gEncounterState = ENCOUNTER_STATE_POST_BATTLE;
currentEncounter->coinsEarned = 0;
currentEncounter->fadeOutAccel = 0;
currentEncounter->fadeOutAmount = 0;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_INIT;
break;
case ENCOUNTER_SUBSTATE_PRE_BATTLE_3:
currentEncounter->battleOutcome = OUTCOME_4;
currentEncounter->unk_08 = 1;
currentEncounter->fadeOutAmount = 0;
currentEncounter->fadeOutAccel = 0;
gEncounterState = ENCOUNTER_STATE_POST_BATTLE;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_INIT;
break;
}
}
void draw_encounters_pre_battle(void) {
EncounterStatus* encounter = &gCurrentEncounter;
Npc* npc = get_npc_unsafe(encounter->currentEnemy->npcID);
PlayerStatus* playerStatus = &gPlayerStatus;
if (encounter->unk_94 != 0) {
f32 playerX, playerY, playerZ;
f32 otherX, otherY, otherZ;
s32 pScreenX, pScreenY, pScreenZ;
s32 oScreenX, oScreenY, oScreenZ;
if (encounter->fadeOutAmount != 255) {
encounter->fadeOutAccel++;
if (encounter->fadeOutAccel > 10) {
encounter->fadeOutAccel = 10;
}
encounter->fadeOutAmount += encounter->fadeOutAccel;
if (encounter->fadeOutAmount > 255) {
encounter->fadeOutAmount = 255;
}
playerX = playerStatus->position.x;
playerY = playerStatus->position.y;
playerZ = playerStatus->position.z;
otherX = npc->pos.x;
otherY = npc->pos.y;
otherZ = npc->pos.z;
if (otherY < -990.0f) {
otherX = playerX;
otherY = playerY;
otherZ = playerZ;
}
if (gGameStatusPtr->demoState == 2) {
set_screen_overlay_params_back(10, encounter->fadeOutAmount);
set_screen_overlay_alpha(1, 255.0f);
set_screen_overlay_color(1, 0, 0, 0);
get_screen_coords(gCurrentCameraID, playerX, playerY + 20.0f, playerZ, &pScreenX, &pScreenY, &pScreenZ);
get_screen_coords(gCurrentCameraID, otherX, otherY + 15.0f, otherZ, &oScreenX, &oScreenY, &oScreenZ);
set_screen_overlay_center(1, 0, (pScreenX - oScreenX) / 2 + oScreenX,
(pScreenY - oScreenY) / 2 + oScreenY);
} else {
set_screen_overlay_params_front(10, encounter->fadeOutAmount);
set_screen_overlay_alpha(0, 255.0f);
set_screen_overlay_color(0, 0, 0, 0);
get_screen_coords(gCurrentCameraID, playerX, playerY + 20.0f, playerZ, &pScreenX, &pScreenY, &pScreenZ);
get_screen_coords(gCurrentCameraID, otherX, otherY + 15.0f, otherZ, &oScreenX, &oScreenY, &oScreenZ);
set_screen_overlay_center(0, 0, (pScreenX - oScreenX) / 2 + oScreenX,
(pScreenY - oScreenY) / 2 + oScreenY);
}
}
}
}
void show_first_strike_message(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
s32 posX;
s32 width;
s32 xOffset;
s32 screenWidthHalf;
if (currentEncounter->unk_94 == 0) {
gFirstStrikeMessagePos = -200;
return;
}
gFirstStrikeMessagePos += 40;
xOffset = gFirstStrikeMessagePos;
if (xOffset > 0) {
if (xOffset < 1600) {
xOffset = 0;
} else {
xOffset -= 1600;
}
}
screenWidthHalf = SCREEN_WIDTH / 2;
switch (currentEncounter->firstStrikeType) {
case FIRST_STRIKE_PLAYER:
switch (currentEncounter->hitType) {
case 2:
case 4:
width = get_msg_width(MSG_Menus_PlayerFirstStrike, 0) + 24;
posX = (xOffset + screenWidthHalf) - (width / 2);
draw_box(0, 0x14, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
SCREEN_WIDTH, SCREEN_HEIGHT, NULL);
draw_msg(MSG_Menus_PlayerFirstStrike, posX + 11, 75, 0xFF, 0xA, 0);
break;
case 6:
width = get_msg_width(MSG_Menus_PartnerFirstStrike, 0) + 24;
posX = (xOffset + screenWidthHalf) - (width / 2);
draw_box(0, 0x14, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
SCREEN_WIDTH, SCREEN_HEIGHT, NULL);
draw_msg(MSG_Menus_PartnerFirstStrike, posX + 11, 75, 0xFF, 0xA, 0);
break;
}
break;
case FIRST_STRIKE_ENEMY:
if (!is_ability_active(ABILITY_CHILL_OUT)) {
width = get_msg_width(MSG_Menus_EnemyFirstStrike, 0) + 24;
posX = (xOffset + screenWidthHalf) - (width / 2);
draw_box(0, 4, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
SCREEN_WIDTH, SCREEN_HEIGHT, NULL);
draw_msg(MSG_Menus_EnemyFirstStrike, posX + 11, 75, 0xFF, 0xA, 0);
}
break;
}
}
void update_encounters_post_battle(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
PlayerStatus* playerStatus = &gPlayerStatus;
PlayerData* playerData = &gPlayerData;
PartnerActionStatus* partnerActionStatus = &gPartnerActionStatus;
Encounter* encounter;
Evt* script;
Enemy* enemy;
s32 i, j;
s32 cond;
Npc* npc;
switch (gEncounterSubState) {
case ENCOUNTER_SUBSTATE_POST_BATTLE_INIT:
if (currentEncounter->unk_08 == 0) {
return;
}
currentEncounter->unk_08 = 0;
gPlayerStatus.blinkTimer = 0;
currentEncounter->scriptedBattle = FALSE;
func_800E97E4();
currentEncounter->dizzyAttackStatus = 0;
currentEncounter->unk_A4 = 0;
currentEncounter->unk_A8 = 0;
currentEncounter->unk_AC = 0;
currentEncounter->dizzyAttackDuration = 0;
currentEncounter->unk_A6 = 0;
currentEncounter->unk_AA = 0;
currentEncounter->unk_AE = 0;
if (D_8009A654 == TRUE) {
bgm_pop_battle_song();
}
currentEncounter->fadeOutAccel = 1;
currentEncounter->battleStartCountdown = 0;
D_8009A670 = FALSE;
gPlayerStatus.flags &= ~PS_FLAGS_40000;
if (currentEncounter->hitType == ENCOUNTER_TRIGGER_SPIN) {
D_8009A670 = TRUE;
}
currentEncounter->hitType = 0;
if (D_80077C40 == 0) {
partner_handle_after_battle();
}
D_8009A63C = FALSE;
if (partnerActionStatus->partnerAction_unk_1) {
D_8009A63C = TRUE;
} else if (D_8009A670 == 0 &&
!(gPlayerStatus.flags & (PS_FLAGS_JUMPING | PS_FLAGS_FALLING)) &&
gPlayerStatus.actionState != ACTION_STATE_RIDE &&
gPlayerStatus.actionState != ACTION_STATE_USE_SPINNING_FLOWER) {
set_action_state(ACTION_STATE_IDLE);
}
switch (currentEncounter->battleOutcome) {
case OUTCOME_PLAYER_WON:
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_WON_CHECK_MERLEE_BONUS;
break;
case OUTCOME_PLAYER_LOST:
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_INIT;
break;
case OUTCOME_PLAYER_FLED:
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_INIT;
break;
case OUTCOME_4:
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_300;
break;
case OUTCOME_ENEMY_FLED:
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_INIT;
break;
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_WON_CHECK_MERLEE_BONUS:
if (currentEncounter->merleeCoinBonus != 0) {
if (get_coin_drop_amount(currentEncounter->currentEnemy) != 0) {
D_800A0BB0 = start_script(&D_80077C44, EVT_PRIORITY_A, 0);
D_800A0BB0->groupFlags = 0;
D_800A0BB4 = D_800A0BB0->id;
} else {
playerData->merleeTurnCount = 0;
playerData->merleeCastsLeft++;
}
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_PLAY_NPC_DEFEAT;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_PLAY_NPC_DEFEAT:
if ((currentEncounter->merleeCoinBonus != 0) && (get_coin_drop_amount(currentEncounter->currentEnemy) != 0)) {
currentEncounter->fadeOutAccel += 4;
currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
if (currentEncounter->fadeOutAmount < 0) {
currentEncounter->fadeOutAmount = 0;
}
if (does_script_exist(D_800A0BB4)) {
break;
}
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->defeatBytecode != NULL) {
script = start_script_in_group(enemy->defeatBytecode, EVT_PRIORITY_A, 0, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = 0;
currentEncounter->battleStartCountdown = 1;
} else {
script = start_script_in_group(&SCRIPT_NpcDefeat, EVT_PRIORITY_A, 0, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = 0;
}
}
if (!(currentEncounter->flags & ENCOUNTER_STATUS_FLAGS_1) && !D_8009A63C && currentEncounter->battleStartCountdown == 0 && D_8009A670 == 0) {
suggest_player_anim_clearUnkFlag(0x10032);
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_WON_WAIT;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_WON_WAIT:
if (currentEncounter->fadeOutAmount == 0) {
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_WON_KILL;
} else {
currentEncounter->fadeOutAccel += 4;
currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
if (currentEncounter->fadeOutAmount < 0) {
currentEncounter->fadeOutAmount = 0;
}
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_WON_KILL:
cond = FALSE;
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (does_script_exist(enemy->defeatScriptID)) {
cond = TRUE;
} else {
enemy->defeatScript = NULL;
}
}
if (!cond) {
if (!(currentEncounter->flags & ENCOUNTER_STATUS_FLAGS_1) && !D_8009A63C && currentEncounter->battleStartCountdown == 1) {
suggest_player_anim_clearUnkFlag(ANIM_Mario_ThumbsUp);
}
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_4) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_1)) {
if (!(enemy->flags & ENEMY_FLAGS_FLED)) {
set_defeated(currentEncounter->mapID, encounter->encounterID + i);
}
}
kill_enemy(enemy);
}
currentEncounter->unk_94 = 0;
if (!(currentEncounter->flags & ENCOUNTER_STATUS_FLAGS_1) && !D_8009A63C && currentEncounter->battleStartCountdown == 1) {
currentEncounter->unk_94 = 30;
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_WON_TO_NEUTRAL;
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_WON_TO_NEUTRAL:
if (!(currentEncounter->flags & ENCOUNTER_STATUS_FLAGS_2) && (gGameStatusPtr->stickX[0] != 0 || gGameStatusPtr->stickY[0] != 0)) {
currentEncounter->unk_94 = 0;
}
if (currentEncounter->unk_94 != 0) {
currentEncounter->unk_94--;
break;
}
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
if (enemy->aiScript != NULL) {
resume_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
resume_all_script(enemy->auxScriptID);
}
}
}
currentEncounter->battleTriggerCooldown = 15;
enable_player_input();
partner_enable_input();
if (!D_8009A63C) {
suggest_player_anim_clearUnkFlag(ANIM_Mario_10002);
}
set_screen_overlay_params_front(255, -1.0f);
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_INIT:
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->defeatBytecode != NULL) {
script = start_script(enemy->defeatBytecode, EVT_PRIORITY_A, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
enemy->aiFlags |= 1;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_WAIT;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_WAIT:
if (currentEncounter->fadeOutAmount == 0) {
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_102;
} else {
currentEncounter->fadeOutAccel += 4;
currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
if (currentEncounter->fadeOutAmount < 0) {
currentEncounter->fadeOutAmount = 0;
}
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_102:
encounter = currentEncounter->currentEncounter;
cond = FALSE;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_20)) {
if (does_script_exist(enemy->defeatScriptID)) {
cond = TRUE;
} else {
enemy->defeatScript = NULL;
}
}
}
if (!cond) {
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
if (enemy->aiScript != NULL) {
resume_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
resume_all_script(enemy->auxScriptID);
}
}
}
enemy = currentEncounter->currentEnemy;
encounter = currentEncounter->currentEncounter;;
if (!(enemy->flags & ENEMY_FLAGS_40000)) {
enemy->aiPaused = 45;
playerStatus->blinkTimer = 45;
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_8) {
continue;
}
enemy->aiPaused = 45;
playerStatus->blinkTimer = 45;
}
}
enemy = currentEncounter->currentEnemy;
if (!(currentEncounter->flags & ENCOUNTER_STATUS_FLAGS_4)) {
script = start_script(&D_80077E9C, EVT_PRIORITY_A, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
currentEncounter->battleTriggerCooldown = 45;
playerStatus->blinkTimer = 45;
enable_player_input();
partner_enable_input();
set_screen_overlay_params_front(255, -1.0f);
if (!D_8009A63C) {
currentEncounter->unk_94 = 15;
} else {
currentEncounter->unk_94 = 0;
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_103;
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_103:
if (currentEncounter->unk_94 != 0) {
currentEncounter->unk_94--;
if (gGameStatusPtr->currentButtons[0] == 0 && gGameStatusPtr->stickX[0] == 0 && gGameStatusPtr->stickY[0] == 0) {
break;
}
}
if (!D_8009A63C && playerStatus->anim == ANIM_Mario_50000) {
suggest_player_anim_clearUnkFlag(ANIM_Mario_10002);
}
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_INIT:
suggest_player_anim_clearUnkFlag(ANIM_Mario_80009);
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->defeatBytecode != NULL) {
script = start_script(enemy->defeatBytecode, 0xA, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_WAIT;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_WAIT:
if (currentEncounter->fadeOutAmount == 0) {
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_202;
} else {
currentEncounter->fadeOutAccel += 4;
currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
if (currentEncounter->fadeOutAmount < 0) {
currentEncounter->fadeOutAmount = 0;
}
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_202:
cond = FALSE;
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_20)) {
if (does_script_exist(enemy->defeatScriptID)) {
cond = TRUE;
} else {
enemy->defeatScript = NULL;
}
}
}
if (!cond) {
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
if (enemy->aiScript != NULL) {
resume_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
resume_all_script(enemy->auxScriptID);
}
}
}
enable_player_input();
partner_enable_input();
set_screen_overlay_params_front(255, -1.0f);
currentEncounter->unk_94 = 15;
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_TO_NEUTRAL;
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_TO_NEUTRAL:
if (currentEncounter->unk_94 != 0) {
currentEncounter->unk_94--;
if (gGameStatusPtr->currentButtons[0] == 0 && gGameStatusPtr->stickX[0] == 0 && gGameStatusPtr->stickY[0] == 0) {
break;
}
}
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_300:
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
if (enemy->aiScript != NULL) {
resume_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
resume_all_script(enemy->auxScriptID);
}
}
}
enable_player_input();
partner_enable_input();
set_screen_overlay_params_front(255, -1.0f);
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_INIT:
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if ((enemy->flags & ENEMY_FLAGS_8) && enemy != currentEncounter->currentEnemy) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->defeatBytecode != NULL) {
script = start_script(enemy->defeatBytecode, 0xA, 0);
enemy->defeatScript = script;
enemy->defeatScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_WAIT;
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_WAIT:
if (currentEncounter->fadeOutAmount == 0) {
gEncounterSubState = ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_TO_NEUTRAL;
} else {
currentEncounter->fadeOutAccel += 4;
currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
if (currentEncounter->fadeOutAmount < 0) {
currentEncounter->fadeOutAmount = 0;
}
}
break;
case ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_TO_NEUTRAL:
cond = FALSE;
encounter = currentEncounter->currentEncounter;
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_20)) {
if (does_script_exist(enemy->defeatScriptID)) {
cond = TRUE;
} else {
enemy->defeatScript = NULL;
}
}
}
if (!cond) {
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
if (enemy->aiScript != NULL) {
resume_all_script(enemy->aiScriptID);
}
if (enemy->auxScript != NULL) {
resume_all_script(enemy->auxScriptID);
}
}
}
enemy = currentEncounter->currentEnemy;
if (!(enemy->flags & ENEMY_FLAGS_4)) {
encounter = currentEncounter->currentEncounter;
enemy->aiPaused = 45;
playerStatus->blinkTimer = 45;
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_20) {
continue;
}
if (enemy->flags & ENEMY_FLAGS_8) {
continue;
}
enemy->aiPaused = 45;
playerStatus->blinkTimer = 45;
}
}
currentEncounter->battleTriggerCooldown = 45;
enable_player_input();
partner_enable_input();
set_screen_overlay_params_front(255, -1.0f);
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
}
break;
}
for (i = 0; i < currentEncounter->numEncounters; i++) {
encounter = currentEncounter->encounterList[i];
if (encounter == NULL) {
continue;
}
for (j = 0; j < encounter->count; j++) {
enemy = encounter->enemy[j];
if (enemy == NULL || (enemy->flags & ENEMY_FLAGS_20)) {
continue;
}
npc = get_npc_unsafe(enemy->npcID);
if (enemy->aiPaused != 0) {
if (enemy->aiPaused & 1) {
npc->flags |= NPC_FLAG_80000000;
enemy->flags |= ENEMY_FLAGS_80000000;
} else {
npc->flags &= ~NPC_FLAG_80000000;
enemy->flags &= ~ENEMY_FLAGS_80000000;
}
}
}
}
}
void draw_encounters_post_battle(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
s32 ret = currentEncounter->fadeOutAccel;
if (ret != 0) {
set_screen_overlay_params_front(0, currentEncounter->fadeOutAmount);
set_screen_overlay_color(0, 0, 0, 0);
}
}
void update_encounters_conversation(void) {
EncounterStatus* encounter = &gCurrentEncounter;
PlayerStatus* playerStatus = &gPlayerStatus;
Enemy* currentEnemy;
s32 flag;
switch (gEncounterSubState) {
case ENCOUNTER_SUBSTATE_CONVERSATION_INIT:
currentEnemy = encounter->currentEnemy;
flag = FALSE;
if (currentEnemy->interactScript != NULL) {
if (does_script_exist(currentEnemy->interactScriptID)) {
flag = TRUE;
} else {
currentEnemy->interactScript = NULL;
}
}
if (currentEnemy->hitScript != NULL) {
if (does_script_exist(currentEnemy->hitScriptID)) {
flag = TRUE;
} else {
currentEnemy->hitScript = NULL;
}
}
if (!flag) {
gEncounterSubState = ENCOUNTER_SUBSTATE_CONVERSATION_END;
}
break;
case ENCOUNTER_SUBSTATE_CONVERSATION_END:
resume_all_group(EVT_GROUP_01);
currentEnemy = encounter->currentEnemy;
if (currentEnemy != NULL && currentEnemy->aiScript != NULL) {
resume_all_script(currentEnemy->aiScriptID);
}
enable_player_input();
partner_enable_input();
if (playerStatus->actionState == ACTION_STATE_TALK) {
set_action_state(ACTION_STATE_IDLE);
}
func_800EF3D4(0);
encounter->hitType = 0;
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
}
}
void draw_encounters_conversation(void) {
}
s32 check_conversation_trigger(void) {
PlayerStatus* playerStatus = &gPlayerStatus;
Camera* camera = &gCameras[gCurrentCameraID];
EncounterStatus* encounterStatus = &gCurrentEncounter;
f32 npcX, npcY, npcZ;
f32 angle;
f32 deltaX, deltaZ;
Encounter* encounter;
f32 playerX, playerY, playerZ;
f32 playerColliderHeight;
f32 playerColliderRadius;
f32 length;
f32 npcCollisionHeight;
f32 npcCollisionRadius;
Encounter* encounterTemp;
Npc* npc;
Npc* encounterNpc;
Enemy* enemy;
Enemy* encounterEnemy;
f32 minLength;
f32 xTemp, yTemp, zTemp;
s32 i, j;
playerStatus->encounteredNPC = NULL;
playerStatus->flags &= ~PS_FLAGS_HAS_CONVERSATION_NPC;
playerColliderHeight = playerStatus->colliderHeight;
playerColliderRadius = playerStatus->colliderDiameter / 2;
playerX = playerStatus->position.x;
playerY = playerStatus->position.y;
playerZ = playerStatus->position.z;
if (gPartnerActionStatus.partnerActionState != PARTNER_ACTION_NONE) {
return FALSE;
}
encounter = NULL;
npc = NULL;
enemy = NULL;
minLength = 65535.0f;
for (i = 0; i < encounterStatus->numEncounters; i++) {
encounterTemp = encounterStatus->encounterList[i];
if (encounterTemp == NULL) {
continue;
}
for (j = 0; j < encounterTemp->count; j++) {
encounterEnemy = encounterTemp->enemy[j];
if (encounterEnemy == NULL) {
continue;
}
if (encounterEnemy->flags & (ENEMY_FLAGS_80000000 | ENEMY_FLAGS_20)) {
continue;
}
if (!(encounterEnemy->flags & ENEMY_FLAGS_1)) {
continue;
}
if ((encounterEnemy->flags & ENEMY_FLAGS_8000000) || encounterEnemy->interactBytecode == NULL) {
continue;
}
encounterNpc = get_npc_unsafe(encounterEnemy->npcID);
npcX = encounterNpc->pos.x;
npcY = encounterNpc->pos.y;
npcZ = encounterNpc->pos.z;
deltaX = npcX - playerX;
deltaZ = npcZ - playerZ;
npcCollisionHeight = encounterNpc->collisionHeight;
npcCollisionRadius = encounterNpc->collisionRadius;
length = sqrtf(SQ(deltaX) + SQ(deltaZ));
if ((playerColliderRadius + npcCollisionRadius <= length) ||
(npcY + npcCollisionHeight < playerY) ||
(playerY + playerColliderHeight < npcY)) {
continue;
}
if (clamp_angle(playerStatus->spriteFacingAngle) < 180.0f) {
angle = clamp_angle(camera->currentYaw - 120.0f);
if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
angle = clamp_angle(angle + 60.0f);
}
} else {
angle = clamp_angle(camera->currentYaw + 120.0f);
if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
angle = clamp_angle(angle - 60.0f);
}
}
if (fabsf(get_clamped_angle_diff(angle, atan2(playerX, playerZ, npcX, npcZ))) > 90.0f) {
continue;
}
if (!(encounterEnemy->flags & ENEMY_FLAGS_10000) && encounterNpc->flags & NPC_FLAG_20000000) {
xTemp = npcX;
yTemp = npcY;
zTemp = npcZ;
if (npc_test_move_taller_with_slipping(0, &xTemp, &yTemp, &zTemp, length,
atan2(npcX, npcZ, playerX, playerZ),
npcCollisionHeight,
2.0f * npcCollisionRadius) != 0) {
continue;
}
}
if (length < minLength) {
minLength = length;
encounter = encounterTemp;
npc = encounterNpc;
enemy = encounterEnemy;
}
}
}
if (!(playerStatus->animFlags & PA_FLAGS_8BIT_MARIO) && npc != NULL && !is_picking_up_item()) {
playerStatus->encounteredNPC = npc;
playerStatus->flags |= PS_FLAGS_HAS_CONVERSATION_NPC;
if (playerStatus->pressedButtons & BUTTON_A) {
close_status_menu();
gCurrentEncounter.hitType = ENCOUNTER_TRIGGER_CONVERSATION;
enemy->encountered = ENCOUNTER_TRIGGER_CONVERSATION;
encounterStatus->currentEncounter = encounter;
encounterStatus->currentEnemy = enemy;
encounterStatus->firstStrikeType = FIRST_STRIKE_PLAYER;
return TRUE;
}
}
return FALSE;
}
void create_encounters(void) {
EncounterStatus* currentEncounter = &gCurrentEncounter;
NpcBlueprint sp10;
NpcBlueprint* bp = &sp10;
NpcGroup* groupList = (NpcGroup*)(currentEncounter->npcGroupList);
s32 groupNpcCount;
s32 mapID = currentEncounter->mapID;
Npc* newNpc;
s32 newNpcIndex;
s32 npcCount;
NpcSettings* npcSettings;
StaticNpc* npcData;
Enemy* enemy;
Encounter* encounter;
Evt* script;
s32 totalNpcCount;
s32 cond1;
s32 cond2;
s32 i;
s32 k;
s32 e;
switch (gEncounterSubState) {
case ENCOUNTER_SUBSTATE_CREATE_INIT:
if (currentEncounter->resetMapEncounterFlags != 1) {
// check for current map among most recently visited
for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
if (currentEncounter->recentMaps[i] == mapID) {
break;
}
}
// current map not found in recent: reset all defeat flags
if (i >= ARRAY_COUNT(currentEncounter->recentMaps)) {
for (k = 0; k < ARRAY_COUNT(currentEncounter->defeatFlags[mapID]); k++) {
currentEncounter->defeatFlags[mapID][k] = FALSE;
}
}
// add current map to recent maps, pushing out the least recent
for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps) - 1; i++) {
currentEncounter->recentMaps[i] = currentEncounter->recentMaps[i + 1];
}
currentEncounter->recentMaps[i] = mapID;
}
e = 0;
totalNpcCount = 0;
while(TRUE) {
if (groupList->npcCount == 0) {
break;
}
npcData = groupList->npcs;
groupNpcCount = groupList->npcCount;
encounter = heap_malloc(sizeof(*encounter));
currentEncounter->encounterList[e] = encounter;
ASSERT(encounter != NULL);
encounter->count = groupNpcCount;
encounter->battle = groupList->battle;
encounter->stage = groupList->stage - 1;
encounter->encounterID = totalNpcCount;
for (i = 0; i < groupNpcCount; i++) {
if (get_defeated(mapID, encounter->encounterID + i)) {
npcData++;
encounter->enemy[i] = NULL;
continue;
}
enemy = encounter->enemy[i] = heap_malloc(sizeof(*enemy));
ASSERT (enemy != NULL);
for (k = 0; k < ARRAY_COUNT(enemy->varTable); k++) {
enemy->varTable[k] = 0;
}
enemy->encounterIndex = e;
enemy->npcID = npcData->id;
npcSettings = enemy->npcSettings = npcData->settings;
enemy->drops = &npcData->drops;
if ((*(s16*)(&npcData->drops) & 0xFF00) != 0x8000) { //TODO s16?
enemy->drops = &D_80077EB8;
}
enemy->encountered = 0;
if ((s32) npcData->init < EVT_LIMIT) {
enemy->initBytecode = npcData->init;
} else {
enemy->initBytecode = NULL;
}
enemy->interactBytecode = npcSettings->onInteract;
enemy->aiBytecode = npcSettings->ai;
enemy->hitBytecode = npcSettings->onHit;
enemy->auxBytecode = npcSettings->aux;
enemy->defeatBytecode = npcSettings->onDefeat;
enemy->initScript = NULL;
enemy->interactScript = NULL;
enemy->aiScript = NULL;
enemy->hitScript = NULL;
enemy->auxScript = NULL;
enemy->defeatScript = NULL;
enemy->interactScriptID = 0;
enemy->aiScriptID = 0;
enemy->hitScriptID = 0;
enemy->auxScriptID = 0;
enemy->defeatScriptID = 0;
enemy->unk_07 = 0;
enemy->unk_B5 = 0;
enemy->aiDetectFlags = npcData->aiDetectFlags;
enemy->aiFlags = npcData->aiFlags;
enemy->unk_DC = 0;
enemy->aiPaused = 0;
enemy->unk_B8 = (EvtScript*)npcSettings->unk_24; // ??
enemy->unk_BC = NULL;
enemy->unk_C0 = 0;
enemy->unk_C4 = 0;
enemy->animList = (s32*)&npcData->animations;
enemy->territory = &npcData->territory;
enemy->flags = npcSettings->flags;
enemy->flags |= npcData->flags;
enemy->unk_64 = NULL;
enemy->tattleMsg = npcData->tattle;
if (npcData->initVarCount != 0) {
if (npcData->initVarCount == 1) {
enemy->varTable[0] = npcData->initVar.value;
} else {
s32* initialVars = npcData->initVar.array;
for (k = 0; k < npcData->initVarCount; k++) {
enemy->varTable[k] = *initialVars++;
}
}
}
// create the new NPC
bp->flags = 0;
if (npcSettings->defaultAnim == 0) {
bp->initialAnim = enemy->animList[0];
} else {
bp->initialAnim = npcSettings->defaultAnim;
}
bp->onUpdate = NULL;
bp->onRender = NULL;
if (!(enemy->flags & ENEMY_FLAGS_20000)) {
newNpcIndex = _create_npc_standard(bp, (AnimID*) npcData->extraAnimations);
} else {
newNpcIndex = _create_npc_partner(bp);
}
newNpc = get_npc_by_index(newNpcIndex);
newNpc->npcID = npcData->id;
newNpc->collisionRadius = npcSettings->radius;
newNpc->collisionHeight = npcSettings->height;
enemy->spawnPos[0] = newNpc->pos.x = npcData->pos.x;
enemy->spawnPos[1] = newNpc->pos.y = npcData->pos.y;
enemy->spawnPos[2] = newNpc->pos.z = npcData->pos.z;
newNpc->unk_96 = 0;
newNpc->planarFlyDist = 0.0f;
newNpc->homePos.x = newNpc->pos.x;
newNpc->homePos.y = newNpc->pos.y;
newNpc->homePos.z = newNpc->pos.z;
set_npc_yaw(newNpc, npcData->yaw);
enemy->unk_E0 = 12345;
if (newNpc->collisionRadius >= 24.0) {
newNpc->shadowScale = newNpc->collisionRadius / 24.0;
} else {
newNpc->shadowScale = 1.0f;
}
if (enemy->flags & ENEMY_FLAGS_100) {
newNpc->flags |= NPC_FLAG_40;
}
if (enemy->flags & ENEMY_FLAGS_200) {
newNpc->flags |= NPC_FLAG_100;
}
if (enemy->flags & ENEMY_FLAGS_400) {
newNpc->flags |= NPC_FLAG_8000;
}
if (enemy->flags & ENEMY_FLAGS_800) {
newNpc->flags |= NPC_FLAG_ENABLE_HIT_SCRIPT;
}
if (enemy->flags & ENEMY_FLAGS_GRAVITY) {
newNpc->flags |= NPC_FLAG_GRAVITY;
}
if (!(enemy->flags & ENEMY_FLAGS_1)) {
newNpc->flags |= NPC_FLAG_100;
}
if (enemy->flags & ENEMY_FLAGS_4000) {
newNpc->flags |= NPC_FLAG_1000000;
}
if (enemy->flags & ENEMY_FLAGS_2000) {
newNpc->flags |= NPC_FLAG_NO_AI;
}
if (enemy->flags & ENEMY_FLAGS_8000) {
newNpc->flags |= NPC_FLAG_10000000;
}
if (enemy->flags & ENEMY_FLAGS_10000) {
newNpc->flags |= NPC_FLAG_20000000;
}
if (enemy->flags & ENEMY_FLAGS_80) {
newNpc->flags |= NPC_FLAG_LOCK_ANIMS;
}
enemy->scriptGroup = EVT_GROUP_08 | EVT_GROUP_02 | EVT_GROUP_01;
if (enemy->flags & ENEMY_FLAGS_1) {
enemy->scriptGroup = EVT_GROUP_08 | EVT_GROUP_02;
}
if (npcSettings->otherAI != NULL) {
script = start_script(npcSettings->otherAI, EVT_PRIORITY_A, 0);
enemy->aiScript = script;
enemy->aiScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
npcData++;
}
groupList++;
e++;
totalNpcCount += groupNpcCount;
}
currentEncounter->numEncounters = e;
gEncounterSubState = ENCOUNTER_SUBSTATE_CREATE_RUN_INIT_SCRIPT;
break;
case ENCOUNTER_SUBSTATE_CREATE_RUN_INIT_SCRIPT:
cond2 = FALSE;
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (enemy->aiScript != NULL) {
if (does_script_exist(enemy->aiScriptID)) {
cond2 = TRUE;
}
}
}
}
if (!cond2) {
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (enemy->initBytecode != NULL) {
script = start_script(enemy->initBytecode, EVT_PRIORITY_A, 0);
enemy->initScript = script;
enemy->initScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
}
gEncounterSubState = ENCOUNTER_SUBSTATE_CREATE_RUN_AI;
}
break;
case ENCOUNTER_SUBSTATE_CREATE_RUN_AI:
cond1 = FALSE;
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (enemy->initScript != NULL) {
if (does_script_exist(enemy->initScriptID)) {
cond1 = TRUE;
} else {
enemy->initScript = NULL;
}
}
}
}
if (cond1) {
break;
}
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_20)) {
if (enemy->aiBytecode != NULL) {
script = start_script(enemy->aiBytecode, EVT_PRIORITY_A, 0);
enemy->aiScript = script;
enemy->aiScriptID = script->id;
enemy->unk_C8 = 100;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
}
}
for (e = 0; e < currentEncounter->numEncounters; e++) {
encounter = currentEncounter->encounterList[e];
if (encounter == NULL) {
continue;
}
for (i = 0; i < encounter->count; i++) {
enemy = encounter->enemy[i];
if (enemy == NULL) {
continue;
}
if (!(enemy->flags & ENEMY_FLAGS_20)) {
if (enemy->auxBytecode != NULL) {
script = start_script(enemy->auxBytecode, EVT_PRIORITY_A, 0);
enemy->auxScript = script;
enemy->auxScriptID = script->id;
script->owner1.enemy = enemy;
script->owner2.npcID = enemy->npcID;
script->groupFlags = enemy->scriptGroup;
}
}
}
}
resume_all_group(EVT_GROUP_10);
gEncounterState = ENCOUNTER_STATE_NEUTRAL;
D_8009A678 = 1;
gEncounterSubState = ENCOUNTER_SUBSTATE_NEUTRAL;
break;
}
}
void init_encounters_ui(void) {
}
s32 is_starting_conversation(void) {
s32 ret = gEncounterState == ENCOUNTER_STATE_PRE_BATTLE;
if (gCurrentEncounter.hitType == ENCOUNTER_TRIGGER_CONVERSATION) {
ret = TRUE;
}
return ret;
}