#include "global.h" #include "code_800F958.h" #include "code_803E46C.h" #include "code_803E668.h" #include "code_8045A00.h" #include "code_805D8C8.h" #include "code_804267C.h" #include "random.h" #include "constants/ability.h" #include "constants/move_id.h" #include "constants/status.h" #include "constants/type.h" #include "constants/weather.h" #include "dungeon_engine.h" #include "dungeon_leader.h" #include "dungeon_map_access.h" #include "dungeon_movement.h" #include "dungeon_pokemon_attributes.h" #include "dungeon_random.h" #include "dungeon_message.h" #include "dungeon_util.h" #include "game_options.h" #include "move_effects_target.h" #include "moves.h" #include "pokemon.h" #include "structs/dungeon_entity.h" #include "structs/str_dungeon.h" #include "text_util.h" #include "weather.h" #include "file_system.h" #include "tile_types.h" #include "position_util.h" #include "exclusive_pokemon.h" #include "number_util.h" #include "pokemon_3.h" #include "code_8077274_1.h" #include "code_806CD90.h" #include "dungeon_capabilities.h" #include "status_checks_1.h" #include "dungeon_ai_movement.h" #include "constants/iq_skill.h" #include "structs/str_806B7F8.h" #include "structs/str_202ED28.h" #include "dungeon_config.h" extern u8 *gUnknown_80FCC7C[]; extern u8 *gUnknown_80FCCAC[]; extern u8 *gUnknown_80FDCC8[]; extern void sub_8042900(Entity *r0); extern void sub_8042968(Entity *r0); extern void EndAbilityImmuneStatus(Entity *, Entity *); void sub_8041BBC(Entity *r0); extern bool8 sub_8045888(Entity *); extern void sub_806A2BC(Entity *, u8); extern void sub_804178C(u32); extern void sub_803F508(Entity *); extern void sub_8042B20(Entity *entity); extern void sub_8042B0C(Entity *entity); extern s32 sub_803D808(UnkDungeonGlobal_unk1CD98 *strPtr, s32 id); extern void sub_8072AC8(u16 *param_1, s32 species, s32 param_3); extern s16 sub_803D970(u32); extern bool8 sub_8083660(const DungeonPos *param_1); extern Entity *gLeaderPointer; extern DungeonPos gUnknown_202EE0C; extern void sub_803F4A0(Entity *a0); extern bool8 sub_80860A8(u8 id); extern u8 gUnknown_202F32C; extern u8 sub_803D73C(s32 a0); extern void DeletePokemonDungeonSprite(s32 id); extern void sub_80429E8(Entity *r0); extern s32 sub_803DA20(s32 param_1); extern void sub_80694C0(Entity *, s32, s32, u32); extern s32 gUnknown_202EDCC; extern void sub_800F958(s32 dungeonSpriteID, DungeonPos *pos, DungeonPos *statusOffsets, u32 a3); extern void sub_8005700(DungeonPos *a0, struct axObject *a1); u32 EntityGetStatusSprites(Entity *entity); void UpdateDungeonPokemonSprite(int id, short species, int status, char visible); extern void sub_8042EC8(Entity *a0, s32 a1); extern Entity *sub_804550C(s16 a); extern Entity *sub_80453AC(s16 id); extern void sub_803F580(s32); extern void ShowWholeRevealedDungeonMap(void); extern void sub_806B678(void); extern void EntityUpdateStatusSprites(Entity *); extern Entity *sub_80696A8(Entity *a0); extern int sprintf(char *, const char *, ...); extern const u8 gUnknown_8106EA8[]; // talkp%d extern const u8 gUnknown_8106EB0[]; // talk%d extern const struct FileArchive gDungeonFileArchive; void sub_8069E0C(Entity *pokemon) { s32 index; EntityInfo *entityInfo; entityInfo = GetEntInfo(pokemon); if (AbilityIsActive(pokemon, ABILITY_FORECAST)) { entityInfo->types[0] = gCastformByWeather[GetApparentWeather(pokemon)].type; entityInfo->types[1] = TYPE_NONE; } else { for(index = 0; index < 2; index++) entityInfo->types[index] = GetPokemonType(entityInfo->id, index); } for(index = 0; index < 2; index++) entityInfo->abilities[index] = GetPokemonAbility(entityInfo->id, index); gDungeon->unkC = 1; } void TriggerWeatherAbilities(void) { Entity *entity; s32 index; if (gDungeon->unkC != 0) { gDungeon->unkC = 0; gDungeon->weather.nullifyWeather = FALSE; for(index = 0; index < DUNGEON_MAX_POKEMON; index++) { entity = gDungeon->activePokemon[index]; if (EntityIsValid(entity)) { if (AbilityIsActive(entity, ABILITY_DRIZZLE)) { gDungeon->weather.naturalWeather[WEATHER_RAIN] = 1; } else if (AbilityIsActive(entity, ABILITY_SAND_STREAM)) { gDungeon->weather.naturalWeather[WEATHER_SANDSTORM] = 1; } else if (AbilityIsActive(entity, ABILITY_DROUGHT)) { gDungeon->weather.naturalWeather[WEATHER_SUNNY] = 1; } if ((AbilityIsActive(entity, ABILITY_AIR_LOCK)) || (AbilityIsActive(entity, ABILITY_CLOUD_NINE))) { gDungeon->weather.nullifyWeather = TRUE; } } } } } s32 GetMonsterApparentID(Entity *pokemon, s32 _id) { s16 id = (s16)(_id); if (id == MONSTER_CASTFORM || IS_CASTFORM_FORM_MONSTER(id)) { if (AbilityIsActive(pokemon, ABILITY_FORECAST)) return gCastformByWeather[GetApparentWeather(pokemon)].monsterId; return MONSTER_CASTFORM; } return id; } void sub_8069F9C(Entity *pokemon, Entity *target, Move *move) { s32 abilityIndex; EntityInfo *targetInfo; EntityInfo *pokemonInfo; u8 abilities[4]; if (!EntityIsValid(pokemon)) return; if (!EntityIsValid(target)) return; if (pokemon == target) return; pokemonInfo = GetEntInfo(pokemon); targetInfo = GetEntInfo(target); abilityIndex = -1; if (targetInfo->abilities[0] == ABILITY_TRACE) { abilityIndex = 0; } if (targetInfo->abilities[1] == ABILITY_TRACE) { abilityIndex = 1; } if (abilityIndex > -1) { s32 randomIndex; s32 abilityCounter = 0; if (pokemonInfo->abilities[0] != ABILITY_UNKNOWN) { abilities[0] = pokemonInfo->abilities[0]; abilityCounter = 1; } if (pokemonInfo->abilities[1] != ABILITY_UNKNOWN) { abilities[abilityCounter] = pokemonInfo->abilities[1]; abilityCounter++; } if (abilityCounter != 0) { if (abilityCounter == 1) { randomIndex = 0; } else { randomIndex = DungeonRandInt(abilityCounter); } if (randomIndex >= 0) { targetInfo->abilities[abilityIndex] = abilities[randomIndex]; gDungeon->unkC = 1; SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], target, 0); TryDisplayDungeonLoggableMessage3(pokemon, target, *gUnknown_80FCC7C); sub_8042900(target); EndAbilityImmuneStatus(pokemon, target); } } } if (targetInfo->unk15A != 0) { targetInfo->unk15A = 0; if (AbilityIsActive(target, ABILITY_COLOR_CHANGE)) { u8 type = GetMoveTypeForMonster(pokemon,move); if (move->id == MOVE_WEATHER_BALL) { u32 weather = GetApparentWeather(pokemon); type = gWeatherBallTypes[weather]; } if (type != TYPE_NONE && !MonsterIsType(target,type)) { const u8 *str; targetInfo->types[0] = type; targetInfo->types[1] = TYPE_NONE; targetInfo->isColorChanged = TRUE; SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], target, 0); str = GetUnformattedTypeString(targetInfo->types[0]); strcpy(gFormatBuffer_Items[0], str); TryDisplayDungeonLoggableMessage3(pokemon,target,*gUnknown_80FCCAC); sub_8042968(target); } } } } void sub_806A120(Entity * pokemon, Entity * target, Move* move) { u32 uVar2_u32; u8 moveType; const char *typeString; EntityInfo *entityInfo; if ((((EntityIsValid(pokemon)) && (EntityIsValid(target))) && (pokemon != target)) && (entityInfo = GetEntInfo(target), entityInfo->reflectClassStatus.status == STATUS_CONVERSION2)) { moveType = GetMoveTypeForMonster(pokemon, move); uVar2_u32 = sub_8092364(moveType); if (uVar2_u32 != TYPE_NONE) { entityInfo->types[0] = uVar2_u32; entityInfo->types[1] = 0; sub_8041BBC(target); SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0],target,0); typeString = GetUnformattedTypeString(uVar2_u32); strcpy(gFormatBuffer_Items[0],typeString); TryDisplayDungeonLoggableMessage3(pokemon,target,*gUnknown_80FDCC8); } } } void sub_806A1B0(Entity *pokemon) { if ((EntityIsValid(pokemon)) && (AbilityIsActive(pokemon, ABILITY_TRUANT))) { PausedStatusTarget(pokemon,pokemon,0,1,0); } } void sub_806A1E8(Entity *pokemon) { bool8 bVar3; EntityInfo *entityInfo; bVar3 = FALSE; if (EntityIsValid(pokemon)) { if (GetEntityType(pokemon) == ENTITY_MONSTER) { entityInfo = GetEntInfo(pokemon); bVar3 = (!entityInfo->isNotTeamMember); } if (gGameOptionsRef->FarOffPals == '\0') { bVar3 = FALSE; } if (bVar3 && (!sub_8045888(pokemon))) { sub_806A2BC(pokemon,1); } } } void sub_806A240(Entity *pokemon, Entity *target) { bool8 isNotTeamMember; EntityInfo *entityInfo; isNotTeamMember = FALSE; if (EntityIsValid(pokemon)){ if (GetEntityType(pokemon) == ENTITY_MONSTER) { entityInfo = GetEntInfo(pokemon); isNotTeamMember = (!entityInfo->isNotTeamMember); } if (isNotTeamMember && (!sub_8045888(pokemon))) { sub_806A2BC(pokemon,1); return; } else if (GetEntityType(target) == ENTITY_MONSTER) { entityInfo = GetEntInfo(target); isNotTeamMember = (!entityInfo->isNotTeamMember); } if (isNotTeamMember && (!sub_8045888(target))) { sub_806A2BC(target,1); } } } void sub_806A2BC(Entity *pokemon, u8 param_2) { if ((EntityIsValid(pokemon)) && (GetEntityType(pokemon) == ENTITY_MONSTER) && (gDungeon->unk181e8.cameraTarget != pokemon)) { if (param_2 != '\0') { sub_804178C(1); while (gDungeon->unk12 < 0x3c) { sub_803E46C(0x34); } } sub_803E708(4,0x44); sub_803F508(pokemon); sub_804AC20(&pokemon->pos); gDungeon->unk12 = 0; } } void nullsub_95(void) {} void sub_806A338(void) { s32 i; for (i = 0; i < DUNGEON_MAX_POKEMON; i++) { Entity *entity = gDungeon->activePokemon[i]; if (EntityIsValid(entity) && (GetEntInfo(entity)->curseClassStatus.status == STATUS_SNATCH)) { gDungeon->snatchPokemon = entity; gDungeon->unk17B3C = GetEntInfo(entity)->unk98; return; } } } void sub_806A390(Entity *pokemon) { s32 i; EntityInfo *info = GetEntInfo(pokemon); for (i = 0; i < MAX_MON_MOVES; i++) { Move *move = &info->moves.moves[i]; if (MoveFlagExists(move)) { move->moveFlags2 &= 0xF7; move->moveFlags2 &= 0xEF; move->moveFlags2 |= MOVE_FLAG2_UNK4; move->PP = GetMoveBasePP(move); } } } struct UnkTalkFileStruct { const u8 *strings[4]; }; void sub_806A3D4(u8 *dst, s32 _a1, s32 id, bool32 _a3) { u8 fileName[12]; OpenedFile *file; s32 a1 = (s16) (_a1); bool8 a3 = _a3; s32 mod; struct UnkTalkFileStruct *strPtr; if (a3) { sprintf(fileName, gUnknown_8106EA8, (s16) (a1 / 10)); } else { sprintf(fileName, gUnknown_8106EB0, (s16) (a1 / 10)); } file = OpenFileAndGetFileDataPtr(fileName, &gDungeonFileArchive); mod = (s16)(a1 % 10); strPtr = ((struct UnkTalkFileStruct *)(file->data)); strcpy(dst, strPtr[mod].strings[id]); CloseFile(file); } bool8 sub_806A458(Entity *pokemon) { s32 x, y; s32 count = 0; EntityInfo *info = GetEntInfo(pokemon); bool8 isNotTeamMember = info->isNotTeamMember; if (!sub_80696A8(pokemon)) return FALSE; for (y = -1; y < 2; y++) { for (x = -1; x < 2; x++) { Tile *tile = GetTileMut(pokemon->pos.x + x, pokemon->pos.y + y); if (tile->monster && GetEntityType(tile->monster) == ENTITY_MONSTER) { if (GetEntInfo(tile->monster)->isNotTeamMember != isNotTeamMember) count++; } } } return (count > 1); } s32 sub_806A4DC(EntityInfo *info) { PokemonStruct1 pokemon; DungeonLocation loc; loc.id = 0; loc.floor = 1; sub_808CFD0(&pokemon, info->id, NULL, 0, &loc, 0); pokemon.speciesNum = info->id; pokemon.level = info->level; pokemon.IQ = info->IQ; pokemon.offense.att[0] = info->atk[0]; pokemon.offense.def[0] = info->def[0]; return sub_808F700(&pokemon); } bool8 sub_806A538(s16 r0) { s32 r0_1 = Self_s16(r0); if (r0 == 0x55AA) return TRUE; if (r0 == 0x5AA5) return TRUE; if (r0_1 >= 0) return FALSE; return TRUE; } bool8 sub_806A564(s16 r0) { if (r0 == 0x55AA) return TRUE; if (r0 == 0x5AA5) return TRUE; return FALSE; } bool8 sub_806A58C(s16 r0) { if (r0 >= 0 && r0 <= 0x19C) return TRUE; else return FALSE; } bool8 sub_806A5A4(s16 r0) { if (r0 < 0) return TRUE; else return FALSE; } extern const u8 *const gUnknown_80FD594; extern const u8 *const gUnknown_80FD5B8; extern const u8 *const gUnknown_80FEAC4; extern const u8 *const gPtrLinkMoveTwoUsesWarningMessage; extern const u8 *const gPtrLinkMoveOneUseWarningMessage; extern const u8 *const gPtrLinkedMovesComeApartMessage; void sub_806A5B8(Entity *entity) { s32 terrainType; if (!EntityIsValid(entity)) return; terrainType = GetTerrainType(GetTileAtEntitySafe(entity)); if (terrainType == TERRAIN_TYPE_SECONDARY) { EntityInfo *info = GetEntInfo(entity); // If lava - defrost and burn if (gDungeonWaterType[gDungeon->tileset] == DUNGEON_WATER_TYPE_LAVA) { if (info->frozenClassStatus.status == STATUS_FROZEN) { EndFrozenClassStatus(entity, entity); } if (GetMovementType(info->id) != 4 && info->id != MONSTER_HO_OH && info->id != MONSTER_MOLTRES && info->burnClassStatus.status != STATUS_BURN) { BurnedStatusTarget(entity, entity, 1, FALSE); } } // It's water - heal burn else { if (info->burnClassStatus.status == STATUS_BURN) { EndBurnClassStatus(entity, entity); } } } // If wall - decrement belly by 5 else if (terrainType == TERRAIN_TYPE_WALL) { const u8 *str; EntityInfo *info = GetEntInfo(entity); if (info->isTeamLeader) { FixedPoint bellyBefore = info->belly; info->belly = FixedPoint_Subtract(bellyBefore, IntToFixedPointMacro(5)); str = NULL; if (FixedPointToInt(bellyBefore) > 19 && FixedPointToInt(info->belly) <= 19) { str = gUnknown_80FD594; // Getting hungry... } if (FixedPointToInt(bellyBefore) > 9 && FixedPointToInt(info->belly) <= 9) { str = gUnknown_80FD5B8; // Getting dizzy from hunger... } if (str != NULL) { LogMessageByIdWithPopupCheckUser(entity, str); } } } } void sub_806A6E8(Entity *entity) { EntityInfo *info = GetEntInfo(entity); if (info->unk64 != info->heldItem.id) { if (!info->isTeamLeader) { if (info->heldItem.id == ITEM_HEAL_RIBBON || info->heldItem.id == ITEM_MUNCH_BELT) { info->belly = FixedPoint_Subtract(info->belly, IntToFixedPoint(10)); } else if (info->heldItem.id == ITEM_DIET_RIBBON) { info->belly = IntToFixedPoint(0); } if (gDungeon->unk644.itemHoldersIdentified) { EntityUpdateStatusSprites(entity); } } else { if (info->heldItem.id == ITEM_X_RAY_SPECS || info->unk64 == ITEM_X_RAY_SPECS) { sub_803F580(1); ShowWholeRevealedDungeonMap(); } } sub_807AA30(); } if (ItemExists(&info->heldItem)) { info->unk64 = info->heldItem.id; } else { info->unk64 = ITEM_NOTHING; } } void DisplayMsgIfNewIqSkillLearned(EntityInfo *info, s32 pokeIq); UNUSED static void DisplayMsgIfTeamMonsLearnedNewIqSkill(void) { s32 i; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { Entity *entity = gDungeon->teamPokemon[i]; if (EntityIsValid(entity)) { EntityInfo *info = GetEntInfo(entity); if (info->IQ > 1) { DisplayMsgIfNewIqSkillLearned(info, info->IQ - 1); } } } } void DisplayMsgIfNewIqSkillLearned(EntityInfo *info, s32 iqBefore) { s32 i, j; u8 iqSkillsArrayBefore[NUM_IQ_SKILLS]; u8 iqSkillsArrayNow[NUM_IQ_SKILLS]; s32 numIqSkillsBefore = GetNumAvailableIQSkills(iqSkillsArrayBefore, iqBefore); s32 numIqSkillsNow = GetNumAvailableIQSkills(iqSkillsArrayNow, info->IQ); SetMessageArgument_2(gFormatBuffer_Monsters[0], info, 0); for (i = 1; i < NUM_IQ_SKILLS; i++) { bool8 hadIqSkillBefore = FALSE; bool8 hasIqSkillNow = FALSE; for (j = 0; j < numIqSkillsBefore; j++) { if (iqSkillsArrayBefore[j] == i) { hadIqSkillBefore = TRUE; break; } } for (j = 0; j < numIqSkillsNow; j++) { if (iqSkillsArrayNow[j] == i) { hasIqSkillNow = TRUE; break; } } if (hadIqSkillBefore != hasIqSkillNow) { strcpy(gFormatBuffer_Items[0], GetIQSkillName(i)); DisplayDungeonLoggableMessageTrue(NULL, gUnknown_80FEAC4); // IQ rose! \n It learned the IQ skill 'i0' } } } void sub_806A898(Entity *entity, bool8 r7, bool8 showRunAwayEffect) { EntityInfo *info = GetEntInfo(entity); if (info->isTeamLeader) { info->targetPos.x = entity->pos.x; info->targetPos.y = entity->pos.y + 1; } else { AIMovement(entity, showRunAwayEffect); } if (info->targetPos.x != 0 || info->targetPos.y != 0) { if (!CheckVariousStatuses2(entity, TRUE) || !CheckVariousStatuses(entity)) { s32 newDirection = GetDirectionTowardsPosition(&entity->pos, &info->targetPos); info->action.direction = newDirection & DIRECTION_MASK; if (r7) { sub_806CE68(entity, newDirection); } } } } void sub_806A914(bool8 a0, bool8 a1, bool8 showRunAwayEffect) { s32 i; for (i = 0; i < DUNGEON_MAX_POKEMON; i++) { Entity *entity = gDungeon->activePokemon[i]; if (EntityIsValid(entity)) { EntityInfo *info = GetEntInfo(entity); if (!a1 || info->monsterBehavior == 1) { sub_806A898(entity, a0, showRunAwayEffect); } } } } void sub_806A974(void) { s32 i; for (i = 0; i < DUNGEON_MAX_POKEMON; i++) { Entity *entity = gDungeon->activePokemon[i]; if (EntityIsValid(entity)) { EntityInfo *info = GetEntInfo(entity); sub_806CE68(entity, info->action.direction); } } } void sub_806A9B4(Entity *entity, s32 moveIndex) { if (EntityIsValid(entity)) { EntityInfo *info = GetEntInfo(entity); s32 ret = sub_80935B8(info->moves.moves, moveIndex); if (ret == 0) { LogMessageByIdWithPopupCheckUser(entity, gPtrLinkedMovesComeApartMessage); } else if (ret == 1) { LogMessageByIdWithPopupCheckUser(entity, gPtrLinkMoveOneUseWarningMessage); } else if (ret == 2) { LogMessageByIdWithPopupCheckUser(entity, gPtrLinkMoveTwoUsesWarningMessage); } } } // s16 again... bool8 sub_806AA0C(s16 _species, bool32 _a1) { s32 species = _species; bool8 a1 = _a1; if (!IsExclusivePokemonUnlocked(_species)) return FALSE; if (gDungeon->unk37FD && GetBaseSpecies(species) == MONSTER_DEOXYS_NORMAL) return FALSE; if (species == MONSTER_MEW) { if (gDungeon->unk37FF || !a1) return FALSE; } return TRUE; } void sub_806AA70(void) { s32 i; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { Entity *entity = gDungeon->teamPokemon[i]; if (EntityIsValid(entity)) { EntityInfo *info = GetEntInfo(entity); s32 teamIndex = info->teamIndex; if (info->isTeamLeader) { if (gDungeon->unk11 == 1) { sub_8042B20(entity); } else { sub_8042B0C(entity); } entity->isVisible = FALSE; } else { if (teamIndex >= 0) { bool8 unkBool = FALSE; PokemonStruct2 *monStruct2Ptr = &gRecruitedPokemonRef->pokemon2[teamIndex]; if (gDungeon->unk11) unkBool = TRUE; else if (sub_806A564(monStruct2Ptr->unkA)) unkBool = TRUE; else if (sub_806A58C(monStruct2Ptr->unkA)) unkBool = TRUE; if (unkBool) { sub_8042B0C(entity); entity->isVisible = FALSE; } } } } } } void sub_806AB2C(void) { s32 i, j; for (i = 0; i < DUNGEON_MAX_POKEMON; i++) { Entity *entity1 = gDungeon->activePokemon[i]; if (EntityIsValid(entity1)) { EntityInfo *info1 = GetEntInfo(entity1); for (j = 0; j < DUNGEON_MAX_POKEMON; j++) { Entity *entity2 = gDungeon->activePokemon[j]; if (EntityIsValid(entity2) && entity1 != entity2 && info1->aiTarget.aiTargetSpawnGenID == entity2->spawnGenID) { info1->aiTarget.aiTarget = entity2; } } } } } void EndAbilityImmuneStatus(Entity *attacker, Entity *target) { EntityInfo *targetInfo = GetEntInfo(target); if (AbilityIsActive(target, ABILITY_LIMBER) && targetInfo->burnClassStatus.status == STATUS_PARALYSIS) { EndBurnClassStatus(attacker, target); } if (AbilityIsActive(target, ABILITY_OWN_TEMPO) && targetInfo->cringeClassStatus.status == STATUS_CONFUSED) { EndCringeClassStatus(attacker, target); } if (AbilityIsActive(target, ABILITY_WATER_VEIL) && targetInfo->burnClassStatus.status == STATUS_BURN) { EndBurnClassStatus(attacker, target); } if (AbilityIsActive(target, ABILITY_OBLIVIOUS) && targetInfo->cringeClassStatus.status == STATUS_INFATUATED) { EndCringeClassStatus(attacker, target); } if ((AbilityIsActive(target, ABILITY_INSOMNIA) || AbilityIsActive(target, ABILITY_VITAL_SPIRIT)) && (IsSleeping(target) || targetInfo->sleepClassStatus.status == STATUS_YAWNING)) { EndSleepClassStatus(attacker, target, FALSE, TRUE); } if (AbilityIsActive(target, ABILITY_MAGMA_ARMOR) && targetInfo->frozenClassStatus.status == STATUS_FROZEN) { EndFrozenClassStatus(attacker, target); } if (AbilityIsActive(target, ABILITY_IMMUNITY) && ENTITY_POISONED(targetInfo)) { EndBurnClassStatus(attacker, target); } if (AbilityIsActive(target, ABILITY_FORECAST)) { targetInfo->isColorChanged = FALSE; if (targetInfo->reflectClassStatus.status == STATUS_CONVERSION2) { EndReflectClassStatus(attacker, target); } } } void MarkLastUsedMonMove(Entity *entity, Move *move) { s32 i; EntityInfo *entInfo = GetEntInfo(entity); for (i = 0; i < MAX_MON_MOVES; i++) { entInfo->moves.moves[i].moveFlags &= ~(MOVE_FLAG_LAST_USED); } entInfo->moves.struggleMoveFlags &= ~(MOVE_FLAG_LAST_USED); if (move->id == MOVE_STRUGGLE) { entInfo->moves.struggleMoveFlags |= MOVE_FLAG_LAST_USED; } else { move->moveFlags |= MOVE_FLAG_LAST_USED; } } s32 sub_806C444(s32 species, s32 level); s32 sub_806C488(s32 species, s32 level, s32 categoryIndex); s32 sub_806C4D4(s32 species, s32 level, s32 categoryIndex); bool8 sub_806B8CC(s16 _species, s32 x, s32 y, PokemonStruct2 *monPtr, Entity **a4, bool32 _a5, u32 _a6); void sub_806BC68(bool8 a0, Entity *entity, struct unkStruct_806B7F8 *structPtr, DungeonPos *pos); void ResetMonEntityData(EntityInfo *, bool8 a1); void sub_806C264(s32 teamIndex, EntityInfo *entInfo); void sub_806AD3C(void) { s32 r10; s32 i, j; UnkDungeonGlobal_unk1CD98 sp[64]; unkDungeon2F3C *structPtr = gDungeon->unk2F3C; s32 var_24 = sub_803D808(sp, 0); for (i = 0; i < var_24; structPtr++, i++) { structPtr->species = ExtractSpeciesIndex(&sp[i]); structPtr->level = ExtractLevel(&sp[i]); sub_8072AC8(structPtr->moves, structPtr->species, structPtr->level); if (structPtr->moves[0] == MOVE_NOTHING) { structPtr->moves[0] = MOVE_BLOWBACK; } structPtr->unkC = sub_806C444(structPtr->species, structPtr->level); for (j = 0; j < 2; j++) { structPtr->unkE[j] = sub_806C488(structPtr->species, structPtr->level, j); structPtr->unk10[j] = sub_806C4D4(structPtr->species, structPtr->level, j); } } for (; i < 64; structPtr++, i++) { structPtr->species = 0; } for (i = 0; i < MONSTER_MAX; i++) { gDungeon->expYieldRankings[i] = 0; } r10 = 1; for (i = 0; i < var_24; i++) { s32 j; s32 expSpecies = -1; s32 expGain = -1; for (j = 0; j < var_24; j++) { s32 species = ExtractSpeciesIndex(&sp[j]); if (gDungeon->expYieldRankings[species] == 0) { s32 level = ExtractLevel(&sp[j]); s32 exp = CalculateEXPGain(species, level); if (expGain < exp) { expGain = exp; expSpecies = species; } } } if (expSpecies < 0) break; gDungeon->expYieldRankings[expSpecies] = r10; r10 += 2; } for (i = 0; i < MONSTER_MAX; i++) { if (gDungeon->expYieldRankings[i] == 0) { gDungeon->expYieldRankings[i] = 1; } } } void sub_806AED8(Moves *moves, s16 *maxHPStat, u8 *atk, u8 *def, s16 _species, s32 level) { s32 i; s32 moveCategory; s32 species = _species; unkDungeon2F3C *structPtr = gDungeon->unk2F3C; for (i = 0; i < 64; i++) { s16 loopSpecies; structPtr = &gDungeon->unk2F3C[i]; loopSpecies = SpeciesId(structPtr->species); if (structPtr->species == 0) break; if (loopSpecies == species && structPtr->level == level) { s32 moveIndex; for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { InitPokemonMoveOrNullObject(&moves->moves[moveIndex], structPtr->moves[moveIndex]); } *maxHPStat = structPtr->unkC; for (moveCategory = 0; moveCategory < 2; moveCategory++) { atk[moveCategory] = structPtr->unkE[moveCategory]; def[moveCategory] = structPtr->unk10[moveCategory]; } moves->struggleMoveFlags = 0; return; } } if (i == 64) { s32 moveIndex; u16 spMoves[MAX_MON_MOVES]; sub_8072AC8(spMoves, species, level); for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { InitPokemonMoveOrNullObject(&moves->moves[moveIndex], spMoves[moveIndex]); } *maxHPStat = sub_806C444(species, level); for (moveCategory = 0; moveCategory < 2; moveCategory++) { atk[moveCategory] = sub_806C488(species, level, moveCategory); def[moveCategory] = sub_806C4D4(species, level, moveCategory); } } else { s32 moveIndex; structPtr->species = species; structPtr->level = level; sub_8072AC8(structPtr->moves, species, level); structPtr->unkC = sub_806C444(structPtr->species, structPtr->level); for (moveCategory = 0; moveCategory < 2; moveCategory++) { structPtr->unkE[moveCategory] = sub_806C488(structPtr->species, structPtr->level, moveCategory); structPtr->unk10[moveCategory] = sub_806C4D4(structPtr->species, structPtr->level, moveCategory); } for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++) { InitPokemonMoveOrNullObject(&moves->moves[moveIndex], structPtr->moves[moveIndex]); } *maxHPStat = structPtr->unkC; for (moveCategory = 0; moveCategory < 2; moveCategory++) { atk[moveCategory] = structPtr->unkE[moveCategory]; def[moveCategory] = structPtr->unk10[moveCategory]; } } moves->struggleMoveFlags = 0; } UNUSED static s32 sub_806B09C(UnkDungeonGlobal_unk1CD98 *unkPtr, bool8 a1) { s32 i, j; s32 count = 0; s16 *unk2Field; UnkDungeonGlobal_unk1CD98 *loopPtr; for (i = 0, unk2Field = unkPtr->unk2, loopPtr = unkPtr; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *monStructPtr = &gRecruitedPokemonRef->pokemon2[i]; if (PokemonFlag1Struct2(monStructPtr) && PokemonFlag2Struct2(monStructPtr)) { for (j = 0; j < count; j++) { if (ExtractSpeciesIndex(&unkPtr[j]) == monStructPtr->speciesNum) break; } if (j == count) { SetSpeciesLevelToExtract(loopPtr, 0, monStructPtr->speciesNum); unk2Field[0] = 0; unk2Field[1] = 0; unk2Field += sizeof(*unkPtr) / sizeof(unkPtr->unk2[0]); // Hacky solution, because loopPtr->unk2[0/1] = 0; doesn't match loopPtr++; count++; } } } count = sub_803D808(unkPtr, count); if (a1) { SetSpeciesLevelToExtract(&unkPtr[count], 1, MONSTER_DECOY); unkPtr[count].unk2[0] = 0; unkPtr[count].unk2[1] = 0; count++; } return count; } extern const DungeonPos gUnknown_80F4598[]; void sub_806B168(void) { s32 count; PokemonStruct2 *monPtrs[MAX_TEAM_MEMBERS]; PokemonStruct2 *monPtrs2[MAX_TEAM_MEMBERS]; // Leader and partner? u8 playerSpawnRoomId = GetTile(gDungeon->playerSpawn.x, gDungeon->playerSpawn.y)->room; s32 i; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = &gRecruitedPokemonRef->pokemon2[i]; currMonPtr->unkC = i; } // Populate monPtrs count = 0; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = &gRecruitedPokemonRef->pokemon2[i]; if (PokemonFlag1Struct2(currMonPtr) && PokemonFlag2Struct2(currMonPtr)) { monPtrs[count++] = currMonPtr; } } for (; count < MAX_TEAM_MEMBERS; count++) { monPtrs[count] = NULL; } // Populate monPtrs2 count = 0; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = monPtrs[i]; if (currMonPtr != NULL && currMonPtr->isTeamLeader) { monPtrs[i] = NULL; monPtrs2[count++] = currMonPtr; } } if (gDungeon->unk644.unk18 == 0) { for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = monPtrs[i]; if (currMonPtr != NULL && currMonPtr->dungeonLocation.id == DUNGEON_JOIN_LOCATION_PARTNER) { monPtrs[i] = NULL; monPtrs2[count++] = currMonPtr; } } } for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = monPtrs[i]; if (monPtrs[i] != NULL) { monPtrs[i] = NULL; monPtrs2[count++] = currMonPtr; } } for (; count < MAX_TEAM_MEMBERS; count++) { monPtrs2[count] = NULL; } // Do something else for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = monPtrs2[i]; if (currMonPtr != NULL) { DungeonPos unkPosition; s32 j; const Tile *tile; bool8 skipSecondLoop; if (currMonPtr->speciesNum == MONSTER_CASTFORM_SNOWY || currMonPtr->speciesNum == MONSTER_CASTFORM_RAINY || currMonPtr->speciesNum == MONSTER_CASTFORM_SUNNY) { currMonPtr->speciesNum = MONSTER_CASTFORM; } skipSecondLoop = FALSE; j = 0; while (1) { unkPosition = gUnknown_80F4598[j]; if (unkPosition.x == 99) break; tile = GetTile(unkPosition.x + gDungeon->playerSpawn.x, unkPosition.y + gDungeon->playerSpawn.y); if (tile->room == playerSpawnRoomId && !sub_807034C(currMonPtr->speciesNum, tile)) { sub_806B8CC(currMonPtr->speciesNum, unkPosition.x + gDungeon->playerSpawn.x, unkPosition.y + gDungeon->playerSpawn.y, currMonPtr, NULL, TRUE, 0); skipSecondLoop = TRUE; break; } j++; } if (skipSecondLoop) continue; j = 0; while (1) { unkPosition = gUnknown_80F4598[j]; if (unkPosition.x == 99) break; tile = GetTile(unkPosition.x + gDungeon->playerSpawn.x, unkPosition.y + gDungeon->playerSpawn.y); if (!sub_807034C(currMonPtr->speciesNum, tile)) { sub_806B8CC(currMonPtr->speciesNum, unkPosition.x + gDungeon->playerSpawn.x, unkPosition.y + gDungeon->playerSpawn.y, currMonPtr, NULL, TRUE, 0); break; } j++; } } } sub_806B678(); } void sub_806B404(void) { Entity *leader; s32 i; PokemonStruct2 *monPtrs[MAX_TEAM_MEMBERS]; u8 roomId; DungeonPos pos; s32 count = 0; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { PokemonStruct2 *currMonPtr = &gRecruitedPokemonRef->pokemon2[i]; if (PokemonFlag1Struct2(currMonPtr) && PokemonFlag2Struct2(currMonPtr) && currMonPtr->unkA == 0x55AA) { monPtrs[count++] = currMonPtr; break; } } for (; count < MAX_TEAM_MEMBERS; count++) { monPtrs[count] = NULL; } gLeaderPointer = NULL; leader = GetLeader(); if (EntityIsValid(leader)) { pos.x = leader->pos.x; pos.y = leader->pos.y; } else { pos.x = gDungeon->playerSpawn.x; pos.y = gDungeon->playerSpawn.y; } roomId = GetTile(pos.x, pos.y)->room; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { DungeonPos unkPosition; bool8 skipNextLoop; const Tile *tile; s32 j; PokemonStruct2 *currMonPtr = monPtrs[i]; if (currMonPtr != NULL && PokemonFlag1Struct2(currMonPtr) && PokemonFlag2Struct2(currMonPtr) && currMonPtr->unkA == 0x55AA) { currMonPtr->unkA = 0x5AA5; skipNextLoop = FALSE; j = 0; while (1) { unkPosition = gUnknown_80F4598[j]; if (unkPosition.x == 99) break; tile = GetTile(unkPosition.x + pos.x, unkPosition.y + pos.y); if (tile->room == roomId && !sub_807034C(currMonPtr->speciesNum, tile)) { sub_806B8CC(currMonPtr->speciesNum, unkPosition.x + pos.x, unkPosition.y + pos.y, currMonPtr, NULL, TRUE, 0); skipNextLoop = TRUE; break; } j++; } if (skipNextLoop) continue; skipNextLoop = FALSE; j = 0; while (1) { unkPosition = gUnknown_80F4598[j]; if (unkPosition.x == 99) break; tile = GetTile(unkPosition.x + pos.x, unkPosition.y + pos.y); if (!sub_807034C(currMonPtr->speciesNum, tile)) { sub_806B8CC(currMonPtr->speciesNum, unkPosition.x + pos.x, unkPosition.y + pos.y, currMonPtr, NULL, TRUE, 0); skipNextLoop = TRUE; break; } j++; } if (skipNextLoop) continue; for (j = 0; j <= 99; j++) { if (sub_8083660(&unkPosition)) { const Tile *tile = GetTile(unkPosition.x, unkPosition.y); if (!sub_807034C(currMonPtr->speciesNum, tile)) { sub_806B8CC(currMonPtr->speciesNum, unkPosition.x, unkPosition.y, currMonPtr, NULL, TRUE, 0); break; } } } } } } void sub_806B678(void) { s32 i; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { Entity *mon = gDungeon->teamPokemon[i]; if (EntityIsValid(mon)) { EntityInfo *monInfo = GetEntInfo(mon); if (monInfo->isTeamLeader) { sub_803F4A0(mon); gUnknown_202EE0C = mon->pos; break; } } } } /* s16 species; u8 unk2; u32 unk4; u16 level; DungeonPos pos; u8 unk10;*/ void sub_806B6C4(void) { struct unkStruct_806B7F8 spStruct; s32 i, j; s32 x, y; bool8 r8 = (gDungeon->unk644.unk44 != 0); if (sub_80860A8(ITEM_MUSIC_BOX) && !HasRecruitedMon(MONSTER_MEW)) { gDungeon->unk37FF = FALSE; } else { gDungeon->unk37FF = TRUE; } x = DungeonRandInt(DUNGEON_MAX_SIZE_X); y = DungeonRandInt(DUNGEON_MAX_SIZE_Y); for (j = 0; j < DUNGEON_MAX_SIZE_Y; j++) { y++; if (y == DUNGEON_MAX_SIZE_Y) {y = 0;} for (i = 0; i < DUNGEON_MAX_SIZE_X; i++) { x++; if (x == DUNGEON_MAX_SIZE_X) {x = 0;} if (GetTile(x, y)->spawnOrVisibilityFlags & 8) { bool8 r6 = FALSE; if (r8) { spStruct.species = gDungeon->unk644.unk44; spStruct.level = 1; spStruct.unk2 = 1; r6 = TRUE; } else { spStruct.species = sub_803D970(0); spStruct.level = 0; spStruct.unk2 = 0; } spStruct.unk4 = 0; spStruct.unk10 = 0; spStruct.pos.x = x; spStruct.pos.y = y; if (r6 || sub_806AA0C(spStruct.species, TRUE)) { if (sub_806B7F8(&spStruct, FALSE)) { r8 = FALSE; } } } } } if (r8) { gDungeon->unkA = 1; } } Entity* sub_806B7F8(struct unkStruct_806B7F8 *structPtr, bool8 a1) { Entity *entity; EntityInfo *entityInfo; const Tile *tile = GetTile(structPtr->pos.x, structPtr->pos.y); if (sub_807034C(structPtr->species, tile)) return FALSE; entity = sub_804550C(structPtr->species); if (entity == NULL) return FALSE; sub_806BC68(FALSE, entity, structPtr, &gUnknown_202EE0C); entityInfo = GetEntInfo(entity); entityInfo->isNotTeamMember = TRUE; sub_806AED8(&entityInfo->moves, &entityInfo->maxHPStat, entityInfo->atk, entityInfo->def, entityInfo->id, entityInfo->level); entityInfo->HP = entityInfo->maxHPStat; entityInfo->moveRandomly = structPtr->unk4; if (!structPtr->unk2 && !a1 && !structPtr->unk10) { s32 rand = DungeonRandInt(100); if (GetChanceAsleep(structPtr->species) > rand) { sub_8075BF4(entity, 0x7F); sub_806CE68(entity, NUM_DIRECTIONS); } } return entity; } bool8 sub_806B8CC(s16 _species, s32 x, s32 y, PokemonStruct2 *monPtr, Entity **a4, bool32 _a5, u32 _a6) { s32 i; DungeonPos unkPosition; struct unkStruct_806B7F8 spStruct; // s16 memes s32 species = SpeciesId(_species); bool8 a5 = _a5; u8 a6 = _a6; Entity *entity; EntityInfo *entityInfo; bool8 isTeamLeader = (monPtr->isTeamLeader != FALSE); if (a4 != NULL) { *a4 = NULL; } if (GetBaseSpecies(species) == MONSTER_DEOXYS_NORMAL) { if (a5) { species = gDungeon->deoxysForm; } else { species = MONSTER_DEOXYS_NORMAL; } } if (sub_807034C(species, GetTile(x, y))) return FALSE; entity = sub_80453AC(species); if (entity == NULL) return FALSE; spStruct.pos.x = x; spStruct.pos.y = y; spStruct.species = species; spStruct.level = monPtr->level; spStruct.unk2 = 0; spStruct.unk4 = 0; spStruct.unk10 = 0; unkPosition.x = gAdjacentTileOffsets[gUnknown_202F32C].x + x; unkPosition.y = gAdjacentTileOffsets[gUnknown_202F32C].y + y; sub_806BC68(TRUE, entity, &spStruct, (isTeamLeader ? &unkPosition : &gUnknown_202EE0C)); entityInfo = GetEntInfo(entity); entityInfo->isNotTeamMember = FALSE; entityInfo->shopkeeper = 0; entityInfo->isTeamLeader = isTeamLeader; entityInfo->unkF9 = a6; gLeaderPointer = NULL; if (isTeamLeader) { gUnknown_202EE0C.x = x; gUnknown_202EE0C.y = y; } entityInfo->HP = monPtr->unk10; entityInfo->maxHPStat = monPtr->unk12; entityInfo->exp = monPtr->currExp; for (i = 0; i < 2; i++) { entityInfo->atk[i] = monPtr->offense.att[i]; entityInfo->def[i] = monPtr->offense.def[i]; } entityInfo->moves = monPtr->moves; for (i = 0; i < MAX_MON_MOVES; i++) { Move *move = &entityInfo->moves.moves[i]; if (MoveFlagExists(move)) { move->moveFlags &= ~(MOVE_FLAG_LAST_USED); move->moveFlags &= ~(MOVE_FLAG_REPLACE); } } entityInfo->moves.struggleMoveFlags &= ~(MOVE_FLAG_LAST_USED); entityInfo->moves.struggleMoveFlags &= ~(MOVE_FLAG_REPLACE); entityInfo->level = monPtr->level; entityInfo->IQ = monPtr->IQ; entityInfo->tactic = monPtr->tacticIndex; entityInfo->IQSkillMenuFlags = monPtr->IQSkills; entityInfo->hiddenPower = monPtr->hiddenPower; entityInfo->joinedAt = monPtr->dungeonLocation; entityInfo->belly = monPtr->belly; entityInfo->maxBelly = monPtr->maxBelly; entityInfo->teamIndex = monPtr->unkC; entityInfo->heldItem = monPtr->itemSlot; entityInfo->unkF3 = 0; entityInfo->unk64 = 0; // Pickup Check if (gDungeon->unk644.dungeonLocation.id != DUNGEON_TINY_WOODS && !IsBossFight() && (entityInfo->abilities[0] == ABILITY_PICKUP || entityInfo->abilities[1] == ABILITY_PICKUP) && !ItemExists(&entityInfo->heldItem)) { u32 pickUpItem = sub_803D73C(0); if (pickUpItem != ITEM_POKE) { xxx_init_itemslot_8090A8C(&entityInfo->heldItem, pickUpItem, 0); entityInfo->unkF3 = TRUE; } } sub_806A6E8(entity); LoadIQSkills(entity); if (a4) { *a4 = entity; } return TRUE; } void sub_806BB6C(Entity *entity, s32 _species) { s32 species = (s16) _species; s16 speciesMatch; struct unkStruct_806B7F8 spStruct; EntityInfo *entInfo = GetEntInfo(entity); DeletePokemonDungeonSprite(entInfo->unk98); // s16 memes... spStruct.species = 0; speciesMatch = species; ASM_MATCH_TRICK(species); spStruct.species = speciesMatch; spStruct.level = 0; spStruct.unk2 = 0; spStruct.pos = entity->pos; spStruct.unk4 = 0; { s16 apparentSpeciesMatch; s32 apparentSpecies = (s16) (GetMonsterApparentID(NULL, species)); EntityInfo *entInfo; entity->unk22 = 0; entInfo = GetEntInfo(entity); apparentSpeciesMatch = apparentSpecies; GetEntInfo(entity)->apparentID = (s16) (apparentSpeciesMatch); GetEntInfo(entity)->id = speciesMatch; entity->axObj.spriteFile = GetSpriteData(apparentSpecies); } entity->axObj.unk42_animId1 = 7; entity->axObj.unk44_direction1 = 0; entity->axObj.unk43_animId2 = 0xFF; entity->axObj.unk45_orientation = 1; entity->axObj.unk47 = 1; entity->unk1C = IntToF248_2(0); if (entInfo->frozenClassStatus.status == STATUS_WRAP || entInfo->frozenClassStatus.status == STATUS_WRAPPED) { sub_8076CB4(entInfo->unk9C); } sub_806BC68((entInfo->isNotTeamMember == FALSE), entity, &spStruct, NULL); sub_806AED8(&entInfo->moves, &entInfo->maxHPStat, entInfo->atk, entInfo->def, entInfo->id, entInfo->level); entInfo->HP = entInfo->maxHPStat; entInfo->shopkeeper = 0; sub_80429E8(entity); EntityUpdateStatusSprites(entity); } void sub_806BC68(bool8 a0, Entity *entity, struct unkStruct_806B7F8 *structPtr, DungeonPos *pos) { DungeonPos entityPos; EntityInfo *entInfo; gDungeon->unkC = 1; entInfo = GetEntInfo(entity); ResetMonEntityData(entInfo, TRUE); entInfo->monsterBehavior = structPtr->unk2; entity->isVisible = TRUE; entity->unk22 = 0; entity->prevPos.x = -1; entity->prevPos.y = -1; entity->pos.x = -2; entity->pos.y = -2; sub_80694C0(entity, structPtr->pos.x, structPtr->pos.y, 1); sub_804535C(entity, NULL); if (!a0) { if (structPtr->species == MONSTER_KECLEON && !gDungeon->unk644.unk2A && gDungeon->unk3A0A && !structPtr->unk2) { entInfo->shopkeeper = 1; } else { entInfo->shopkeeper = 0; } if (GetBaseSpecies(entInfo->id) == MONSTER_DEOXYS_NORMAL) { gDungeon->unk37FD = TRUE; } if (GetBaseSpecies(entInfo->id) == MONSTER_MEW) { gDungeon->unk37FF = TRUE; } } entInfo->unk98 = gDungeon->unk37F0; gDungeon->unk37F0++; entInfo->unk9C = 0; if (structPtr->level == 0) { entInfo->level = sub_803DA20(structPtr->species); } else { entInfo->level = structPtr->level; } entInfo->moveRandomly = structPtr->unk4; entInfo->IQ = 1; SetDefaultIQSkills(&entInfo->IQSkillMenuFlags, FALSE); GenerateHiddenPower(&entInfo->hiddenPower); entInfo->maxHPStat = 1; entInfo->HP = 1; entInfo->belly = IntToFixedPoint(100); entInfo->maxBelly = IntToFixedPoint(100); if (pos != NULL) { entInfo->targetPos = *pos; } else { entInfo->targetPos.x = 0; entInfo->targetPos.y = 0; } entInfo->flags = 0; entInfo->aiAllySkip = FALSE; entInfo->recalculateFollow = FALSE; entInfo->numMoveTiles = 0; entInfo->notMoving = 0; entInfo->aiTarget.aiObjective = 0; entInfo->aiTarget.aiTargetPos = entity->pos; entInfo->aiTarget.aiTarget = NULL; entInfo->aiTarget.unkC = 0; entInfo->aiTarget.aiTargetSpawnGenID = 0; entInfo->unkFF = 0; entInfo->unk174.raw = 0; entInfo->decoyAITracker = 0; ResetMonEntityData(entInfo, TRUE); ZeroOutItem(&entInfo->heldItem); entInfo->unk64 = 0; entInfo->statusIcons = 0; entInfo->unk164 = 0xFF; entInfo->unk165 = 0xFF; entInfo->expGainedInTurn = 0; entInfo->waiting = 0; entInfo->unk146 = 0; entInfo->unk166 = 0; entInfo->unk1F8 = 0; entInfo->mobileTurnTimer = 0; entInfo->attacking = FALSE; entInfo->unk149 = FALSE; entInfo->abilityEffectFlags = FALSE; entInfo->terrifiedTurns = 0; entInfo->useHeldItem = 0; entInfo->unk14B = 0; entInfo->unk14C = 1; entInfo->visualFlags = 0; entInfo->previousVisualFlags = 0; entInfo->unk152 = 0; entInfo->unk153 = 0; entInfo->unk154 = 0; entInfo->unk155 = 0; entInfo->turnsSinceWarpScarfActivation = 0; entInfo->perishSongTurns = 0; entInfo->unkFE = 99; entInfo->unk158 = 0; entInfo->unk159 = 0; entInfo->unk15A = 0; CalcSpeedStage(entity); entInfo->unk156 = 1; entInfo->unk15C = 0; entInfo->unk15E = 0; entInfo->unk15D = 0; entInfo->unk15F = 0; entInfo->unk160 = 0; if (entInfo->apparentID == MONSTER_DIGLETT || entInfo->apparentID == MONSTER_DUGTRIO) { entInfo->unk156 = 0; } entityPos.x = entity->pos.x; entityPos.y = entity->pos.y; AddPokemonDungeonSprite(entInfo->unk98, entInfo->apparentID, &entityPos, gDungeon->unk181e8.priority); LoadIQSkills(entity); sub_806A898(entity, FALSE, FALSE); } void ResetMonEntityData(EntityInfo *entInfo, bool8 setStatsToOne) { s32 i; bool8 hasForecast; entInfo->sleepClassStatus.status = 0; entInfo->sleepClassStatus.turns = 0; entInfo->burnClassStatus.status = 0; entInfo->burnClassStatus.turns = 0; entInfo->burnClassStatus.damageCountdown = 0; entInfo->burnClassStatus.unk4 = 0; entInfo->frozenClassStatus.status = 0; entInfo->frozenClassStatus.turns = 0; entInfo->frozenClassStatus.damageCountdown = 0; entInfo->frozenClassStatus.unk4 = 34; entInfo->cringeClassStatus.status = 0; entInfo->cringeClassStatus.turns = 0; entInfo->bideClassStatus.status = 0; entInfo->reflectClassStatus.status = 0; entInfo->reflectClassStatus.turns = 0; entInfo->curseClassStatus.status = 0; entInfo->curseClassStatus.turns = 0; entInfo->curseClassStatus.damageCountdown = 0; entInfo->leechSeedClassStatus.status = 0; entInfo->leechSeedClassStatus.turns = 0; entInfo->leechSeedClassStatus.damageCountdown = 0; entInfo->sureShotClassStatus.status = 0; entInfo->sureShotClassStatus.turns = 0; entInfo->longTossClassStatus.status = 0; entInfo->invisibleClassStatus.status = 0; entInfo->invisibleClassStatus.turns = 0; entInfo->blinkerClassStatus.status = 0; entInfo->blinkerClassStatus.turns = 0; entInfo->muzzled.muzzled = FALSE; entInfo->muzzled.turns = 0; entInfo->powerEars = FALSE; entInfo->scanning = FALSE; entInfo->stairSpotter = FALSE; entInfo->stairSpotter = FALSE; entInfo->unk164 = 0xFF; entInfo->unk165 = 0xFF; for (i = 0; i < NUM_SPEED_COUNTERS; i++) { entInfo->speedUpCounters[i] = 0; entInfo->speedDownCounters[i] = 0; } hasForecast = FALSE; for (i = 0; i < 2; i++) { entInfo->abilities[i] = GetPokemonAbility(entInfo->id, i); if (entInfo->abilities[i] == ABILITY_FORECAST) { hasForecast = TRUE; } if (setStatsToOne) { entInfo->atk[i] = 1; entInfo->def[i] = 1; } entInfo->offensiveStages[i] = 10; entInfo->defensiveStages[i] = 10; entInfo->hitChanceStages[i] = 10; entInfo->offensiveMultipliers[i].raw = IntToF248_2(1).raw; entInfo->defensiveMultipliers[i].raw = IntToF248_2(1).raw; } if (hasForecast) { entInfo->types[0] = gCastformByWeather[GetApparentWeather(NULL)].type; entInfo->types[1] = TYPE_NONE; } else { for (i = 0; i < 2; i++) { entInfo->types[i] = GetPokemonType(entInfo->id, i); } } gDungeon->unkC = 1; entInfo->flashFireBoost = 0; entInfo->stockpileStage = 0; entInfo->perishSongTurns = 0; entInfo->speedBoostFrames = 0; entInfo->grudge = 0; entInfo->expMultiplier = EXP_HALVED; entInfo->exposed = FALSE; entInfo->isColorChanged = 0; entInfo->bossFlag = 0; entInfo->unkFF = 0; } void sub_806C1D8(void) { s32 i, j; for (i = 0; i < MAX_TEAM_MEMBERS; i++) { Entity *entity = gDungeon->teamPokemon[i]; if (EntityIsValid(entity)) { EntityInfo *entInfo = GetEntInfo(entity); s32 teamIndex = entInfo->teamIndex; if (teamIndex >= 0) { for (j = 0; j < MAX_MON_MOVES; j++) { if (MoveFlagExists(&entInfo->moves.moves[j])) { entInfo->moves.moves[j].moveFlags2 &= ~(1); } } sub_806C264(teamIndex, entInfo); } } } } void sub_806C264(s32 teamIndex, EntityInfo *entInfo) { s32 i; PokemonStruct2 *monPtr = &gRecruitedPokemonRef->pokemon2[teamIndex]; monPtr->unk10 = entInfo->HP; monPtr->unk12 = entInfo->maxHPStat; monPtr->currExp = entInfo->exp; for (i = 0; i < 2; i++) { monPtr->offense.att[i] = entInfo->atk[i]; monPtr->offense.def[i] = entInfo->def[i]; } if (IS_CASTFORM_FORM_MONSTER(entInfo->apparentID)) { monPtr->speciesNum = MONSTER_CASTFORM; } monPtr->moves = entInfo->moves; monPtr->level = entInfo->level; monPtr->IQ = entInfo->IQ; monPtr->IQSkills = entInfo->IQSkillMenuFlags; monPtr->tacticIndex = entInfo->tactic; monPtr->hiddenPower = entInfo->hiddenPower; monPtr->belly = entInfo->belly; monPtr->maxBelly = entInfo->maxBelly; monPtr->itemSlot = entInfo->heldItem; if (monPtr->unkA == 0x55AA) { monPtr->unkA = 0x5AA5; } } // s16 species memes again void sub_806C330(s32 _x, s32 _y, s16 _species, u32 _a3) { s32 i; s32 x = _x; s32 y = _y; s32 species = (_species); u8 a3 = _a3; unkDungeon57C *strPtr = &gDungeon->unk57C; for (i = 0; i < strPtr->unk40; i++) { if (strPtr->unkArray[i].unk3 && strPtr->unkArray[i].unk4 == x && strPtr->unkArray[i].unk5 == y) { s16 speciesMatchMe = SpeciesId(_species); strPtr->unkArray[i].unk0 = speciesMatchMe; strPtr->unkArray[i].unk2 = a3; return; } } if (strPtr->unk40 < UNK_DUNGEON57C_ARRAY_COUNT) { strPtr->unkArray[strPtr->unk40].unk3 = TRUE; strPtr->unkArray[strPtr->unk40].unk4 = x; strPtr->unkArray[strPtr->unk40].unk5 = y; strPtr->unkArray[strPtr->unk40].unk0 = species; strPtr->unkArray[strPtr->unk40].unk2 = a3; strPtr->unk40++; } } void sub_806C3C0(void) { s32 i; struct unkStruct_806B7F8 spStruct; unkDungeon57C *strPtr = &gDungeon->unk57C; for (i = 0; i < strPtr->unk40; i++) { if (strPtr->unkArray[i].unk3) { spStruct.species = strPtr->unkArray[i].unk0; spStruct.level = 0; spStruct.pos.x = strPtr->unkArray[i].unk4; spStruct.pos.y = strPtr->unkArray[i].unk5; spStruct.unk2 = strPtr->unkArray[i].unk2; spStruct.unk4 = 0; spStruct.unk10 = 0; sub_806B7F8(&spStruct, TRUE); } } } void sub_806C42C(void) { unkDungeon57C *strPtr = &gDungeon->unk57C; strPtr->unk40 = 0; } s32 sub_806C444(s32 _species, s32 level) { LevelData levelData; s32 i; s32 species = SpeciesId(_species); s32 hpCount = GetBaseHP(species); for (i = 2; i <= level; i++) { GetPokemonLevelData(&levelData, species, i); hpCount += levelData.gainHP; } return hpCount; } s32 sub_806C488(s32 _species, s32 level, s32 categoryIndex) { LevelData levelData; s32 i; s32 species = SpeciesId(_species); s32 offensiveCount = GetBaseOffensiveStat(species, categoryIndex); for (i = 2; i <= level; i++) { GetPokemonLevelData(&levelData, species, i); offensiveCount += levelData.gainAtt[categoryIndex]; } return offensiveCount; } s32 sub_806C4D4(s32 _species, s32 level, s32 categoryIndex) { LevelData levelData; s32 i; s32 species = SpeciesId(_species); s32 defensiveCount = GetBaseDefensiveStat(species, categoryIndex); for (i = 2; i <= level; i++) { GetPokemonLevelData(&levelData, species, i); defensiveCount += levelData.gainDef[categoryIndex]; } return defensiveCount; } extern const u8 gUnknown_8106EC8[][13]; static inline u16 GetUnkFlag(Entity *entity) { if ((entity->axObj.axdata.flags & 0x2000)) return 0; else return entity->axObj.axdata.flags >> 15; } void sub_806C51C(Entity *entity) { s32 x, y, y2; bool8 var_3C; bool8 decoySprite; s32 var_34; DungeonPos pos1; DungeonPos posArray[4]; u32 statusSprites; bool8 r4; u8 r7; unkStruct_2039DB0 spriteMasks; s32 xSprite, ySprite; EntityInfo *entInfo = GetEntInfo(entity); if (gDungeon->unk181e8.cameraTarget == entity) { decoySprite = FALSE; } else { decoySprite = gDungeon->unk181e8.hallucinating; } if (entInfo->curseClassStatus.status == STATUS_DECOY) { decoySprite = TRUE; } if (entity->axObj.unk43_animId2 == entity->axObj.unk42_animId1 && entity->axObj.unk45_orientation == entity->axObj.unk44_direction1 && entity->axObj.unk47 == 0) { bool8 r2 = FALSE; if (!GetUnkFlag(entity)) r2 = TRUE; if (r2) { s32 r0; s32 r3 = sub_806CEBC(entity); entity->unk21 = 1; if (entInfo->unkFE == 99) { if (entity->axObj.unk43_animId2 <= 12) { s32 r2; if (entInfo->bideClassStatus.status == STATUS_BIDE) { r2 = 2; } else if (entity->unk23 < 3) { r2 = 0; } else { r2 = 1; } r0 = gUnknown_8106EC8[r2][entity->axObj.unk43_animId2]; if (r0 == 7) { r0 = r3; } } else { r0 = 99; } } else { r0 = entInfo->unkFE; } if (r0 != 99) { entity->axObj.unk42_animId1 = r0; entity->axObj.unk44_direction1 = entity->axObj.unk45_orientation & DIRECTION_MASK; entity->axObj.unk47 = 1; if (entity->axObj.unk42_animId1 == 6 && ++entity->axObj.unk46 == 16) { entity->axObj.unk42_animId1 = r3; } } } } if (entity->axObj.unk43_animId2 != entity->axObj.unk42_animId1 || entity->axObj.unk45_orientation != entity->axObj.unk44_direction1 || entity->axObj.unk47 != 0) { s32 r7; entity->axObj.unk43_animId2 = entity->axObj.unk42_animId1; entity->axObj.unk45_orientation = entity->axObj.unk44_direction1; entity->axObj.unk47 = 0; r7 = entity->axObj.unk40_maybeAnimTimer; if (sub_808DA44(entInfo->apparentID, entity->axObj.unk42_animId1)) { r7 = 0; } if (!decoySprite) { s32 rnd = Rand32Bit() & 3; AxResInitFile(&entity->axObj.axdata, entity->axObj.spriteFile, entity->axObj.unk42_animId1, entity->axObj.unk44_direction1, r7, rnd, FALSE); } else { OpenedFile *spriteData = GetSpriteData(MONSTER_DECOY); s32 rnd = Rand32Bit() & 3; AxResInitFile(&entity->axObj.axdata, spriteData, entity->axObj.unk42_animId1, entity->axObj.unk44_direction1, r7, rnd, FALSE); } if (entity->axObj.unk42_animId1 != 6) { entity->axObj.unk46 = 0; } } if (gDungeon->unk1356C) { if (entity->axObj.unk43_animId2 != 7 || GetMovementType(entInfo->apparentID) == 2) { if (entInfo->unk15C != 0) { if (entInfo->unk160 == 0) { if (entInfo->unk15F != 0) { RunAxAnimationFrame(&entity->axObj.axdata); RunAxAnimationFrame(&entity->axObj.axdata); RunAxAnimationFrame(&entity->axObj.axdata); } else { RunAxAnimationFrame(&entity->axObj.axdata); } } } else { RunAxAnimationFrame(&entity->axObj.axdata); } } } else { if (entInfo->frozenClassStatus.status != STATUS_FROZEN && entInfo->frozenClassStatus.status != STATUS_PETRIFIED) { if (gDungeon->unk644.unk28 != 0 && gDungeon->unk1BDD4.unk1C05F == 0) { RunAxAnimationFrame(&entity->axObj.axdata); RunAxAnimationFrame(&entity->axObj.axdata); } else if ((entity->axObj.unk43_animId2 == 0 || entity->axObj.unk43_animId2 == 7) && GetEntInfo(entity)->speedStage > 1) { RunAxAnimationFrame(&entity->axObj.axdata); } RunAxAnimationFrame(&entity->axObj.axdata); } } if (entity->pixelPos.x == entity->prevPixelPos.x && entity->pixelPos.y == entity->prevPixelPos.y) { if (entity->unk23 < 10) { entity->unk23++; } } else { entity->unk23 = 0; } entity->prevPixelPos.x = entity->pixelPos.x; entity->prevPixelPos.y = entity->pixelPos.y; x = (entity->pixelPos.x / 256) - gDungeon->unk181e8.cameraPixelPos.x; y = (((entity->pixelPos.y - entity->unk1C.raw) - entInfo->unk174.raw) / 256) - gDungeon->unk181e8.cameraPixelPos.y; y2 = (entity->pixelPos.y / 256) - gDungeon->unk181e8.cameraPixelPos.y; y2 /= 2; if (entInfo->unk156 == 0) { y2--; } if (entInfo->unk15C == 0) { var_3C = sub_8042768(entity); } else { if (entInfo->unk15D != 0) { if (gUnknown_202EDCC & 4) { x++; } else { x--; } } var_3C = (entInfo->unk15E == 0); } pos1.x = entity->pixelPos.x / 256; pos1.y = ((entity->pixelPos.y - entity->unk1C.raw) - entInfo->unk174.raw) / 256; sub_8005700(posArray, &entity->axObj); sub_800F958(entInfo->unk98, &pos1, posArray, gDungeon->unk181e8.priority); statusSprites = EntityGetStatusSprites(entity); UpdateDungeonPokemonSprite(entInfo->unk98, entInfo->apparentID, statusSprites, (var_3C && entInfo->unk14C)); sub_8042EC8(entity, y2); if (entInfo->unk15C == 0) { if (entInfo->unkFF == 1) { if (entInfo->unk174.raw <= IntToF248_2(199.999).raw) { entInfo->unk174.raw += IntToF248_2(8).raw; if (entInfo->unk174.raw > IntToF248_2(200).raw) { entInfo->unk174.raw = IntToF248_2(200).raw; } } } else { entInfo->unk174.raw -= IntToF248_2(12).raw; if (entInfo->unk174.raw < IntToF248_2(0).raw) { entInfo->unk174.raw = IntToF248_2(0).raw; } } } if (!var_3C) return; r4 = FALSE; r7 = sub_806CF54(entity); spriteMasks.unk0 = 0xF3FF; spriteMasks.unk2 = 0xFFFF; spriteMasks.unk4 = 0xF3FF; spriteMasks.unk6 = 0; spriteMasks.unk8 = 0; spriteMasks.unkA = gDungeon->unk181e8.priority << 10; if (entInfo->isNotTeamMember && (entInfo->apparentID == MONSTER_DEOXYS_ATTACK || entInfo->apparentID == MONSTER_DEOXYS_DEFENSE || entInfo->apparentID == MONSTER_DEOXYS_SPEED)) { r4 = TRUE; } if (entInfo->invisibleClassStatus.status == STATUS_INVISIBLE && !gDungeon->unk181e8.showInvisibleTrapsMonsters) { r4 = TRUE; } if (r4) { spriteMasks.unk6 |= 0x400; } var_34 = 0; if (!entInfo->isNotTeamMember || entInfo->curseClassStatus.status == STATUS_DECOY) { var_34 = 1; } if (IsExperienceLocked(entInfo->joinedAt.id) || entInfo->monsterBehavior == 1) { var_34 = 1; } if (entInfo->unkFF != 2) { s32 overworldPal; if (entInfo->frozenClassStatus.status == STATUS_PETRIFIED || entInfo->burnClassStatus.status == STATUS_PARALYSIS || entInfo->frozenClassStatus.status == STATUS_SHADOW_HOLD) { x += gUnknown_202EDCC & 2; } if (decoySprite) { overworldPal = GetPokemonOverworldPalette(MONSTER_DECOY, FALSE); } else { overworldPal = GetPokemonOverworldPalette(entInfo->apparentID, FALSE); } if (entity->unk22 == 0) { DoAxFrame_800558C(&entity->axObj.axdata, x, y, y2, overworldPal, &spriteMasks); } else if (entity->unk22 == 1 && (gUnknown_202EDCC & 1)) { DoAxFrame_800558C(&entity->axObj.axdata, x, y, y2, overworldPal, &spriteMasks); } } entInfo->pixelPos.x = (entity->pixelPos.x / 256) + entity->axObj.axdata.sub1.shadow.x; entInfo->pixelPos.y = (entity->pixelPos.y / 256) + entity->axObj.axdata.sub1.shadow.y; xSprite = entInfo->pixelPos.x - gDungeon->unk181e8.cameraPixelPos.x; ySprite = entInfo->pixelPos.y - gDungeon->unk181e8.cameraPixelPos.y; if (xSprite >= -32 && ySprite >= -32 && xSprite <= 271 && ySprite <= 191 && r7 != 6 && entity->unk22 == 0) { struct unkStruct_202ED28 *spriteStructPtr = &gUnknown_202ED28[var_34][r7]; if (entInfo->unk156 != 0) { SpriteSetX(&spriteStructPtr->sprite, xSprite + spriteStructPtr->x); SpriteSetY(&spriteStructPtr->sprite, ySprite + spriteStructPtr->y); AddSprite(&spriteStructPtr->sprite, 0, NULL, NULL); } } }