#include "global.h" #include "gflib.h" #include "battle.h" #include "event_data.h" #include "event_scripts.h" #include "random.h" struct TrainerFanClub { u8 timer:7; u8 gotInitialFans:1; u8 fanFlags; }; #define TRAINER_FAN_CLUB ((struct TrainerFanClub *)GetVarPointer(VAR_FANCLUB_FAN_COUNTER)) #define GET_TRAINER_FAN_CLUB_FLAG(flag) (fanClub->fanFlags >> (flag) & 1) #define SET_TRAINER_FAN_CLUB_FLAG(flag) (fanClub->fanFlags |= 1 << (flag)) #define FLIP_TRAINER_FAN_CLUB_FLAG(flag)(fanClub->fanFlags ^= 1 << (flag)) #define FANCLUB_MEMBER1 0 #define FANCLUB_MEMBER2 1 #define FANCLUB_MEMBER3 2 #define FANCLUB_MEMBER4 3 #define FANCLUB_MEMBER5 4 #define FANCLUB_MEMBER6 5 #define FANCLUB_MEMBER7 6 #define FANCLUB_MEMBER8 7 #define NUM_TRAINER_FAN_CLUB_MEMBERS 8 static void TryLoseFansFromPlayTimeAfterLinkBattle(struct TrainerFanClub *); static void UpdateTrainerFanClubGameClear(struct TrainerFanClub *); static u8 PlayerGainRandomTrainerFan(struct TrainerFanClub *); static u16 GetNumFansOfPlayerInTrainerFanClub(struct TrainerFanClub *); static void TryLoseFansFromPlayTime(struct TrainerFanClub *); static bool16 IsFanClubMemberFanOfPlayer(struct TrainerFanClub *); static void SetInitialFansOfPlayer(struct TrainerFanClub *); static void BufferFanClubTrainerName(struct LinkBattleRecords *, u8, u8); static void UpdateTrainerFansAfterLinkBattle(struct TrainerFanClub *); static bool8 DidPlayerGetFirstFans(struct TrainerFanClub * ); static void SetPlayerGotFirstFans(struct TrainerFanClub *); void ResetTrainerFanClub(void) { VarSet(VAR_FANCLUB_FAN_COUNTER, 0); VarSet(VAR_FANCLUB_LOSE_FAN_TIMER, 0); } void Script_TryLoseFansFromPlayTimeAfterLinkBattle(void) { TryLoseFansFromPlayTimeAfterLinkBattle(TRAINER_FAN_CLUB); } static void TryLoseFansFromPlayTimeAfterLinkBattle(struct TrainerFanClub *fanClub) { if (DidPlayerGetFirstFans(fanClub)) { TryLoseFansFromPlayTime(fanClub); VarSet(VAR_FANCLUB_LOSE_FAN_TIMER, gSaveBlock2Ptr->playTimeHours); } } void Script_UpdateTrainerFanClubGameClear(void) { UpdateTrainerFanClubGameClear(TRAINER_FAN_CLUB); } static void UpdateTrainerFanClubGameClear(struct TrainerFanClub *fanClub) { if (!fanClub->gotInitialFans) { SetPlayerGotFirstFans(fanClub); SetInitialFansOfPlayer(fanClub); VarSet(VAR_FANCLUB_LOSE_FAN_TIMER, gSaveBlock2Ptr->playTimeHours); FlagClear(FLAG_HIDE_SAFFRON_FAN_CLUB_BLACKBELT); FlagClear(FLAG_HIDE_SAFFRON_FAN_CLUB_ROCKER); FlagClear(FLAG_HIDE_SAFFRON_FAN_CLUB_WOMAN); FlagClear(FLAG_HIDE_SAFFRON_FAN_CLUB_BEAUTY); VarSet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB, 1); } } ALIGNED(4) const u8 sCounterIncrements[] = {2, 1, 2, 1}; static u8 TryGainNewFanFromCounter(struct TrainerFanClub *fanClub, u8 a1) { if (VarGet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB) == 2) { if (fanClub->timer + sCounterIncrements[a1] >= 20) { if (GetNumFansOfPlayerInTrainerFanClub(fanClub) < 3) { PlayerGainRandomTrainerFan(fanClub); fanClub->timer = 0; } else fanClub->timer = 20; } else fanClub->timer += sCounterIncrements[a1]; } return fanClub->timer; } static u8 PlayerGainRandomTrainerFan(struct TrainerFanClub *fanClub) { static const u8 sFanClubMemberIds[] = { FANCLUB_MEMBER2, FANCLUB_MEMBER4, FANCLUB_MEMBER6, FANCLUB_MEMBER1, FANCLUB_MEMBER8, FANCLUB_MEMBER7, FANCLUB_MEMBER5, FANCLUB_MEMBER3 }; u8 i; u8 idx = 0; for (i = 0; i < NUM_TRAINER_FAN_CLUB_MEMBERS; i++) { if (!(GET_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[i]))) { idx = i; if (Random() % 2) { SET_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[i]); return sFanClubMemberIds[i]; } } } SET_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[idx]); return sFanClubMemberIds[idx]; } static u8 PlayerLoseRandomTrainerFan(struct TrainerFanClub *fanClub) { static const u8 sFanClubMemberIds[] = { FANCLUB_MEMBER6, FANCLUB_MEMBER7, FANCLUB_MEMBER4, FANCLUB_MEMBER8, FANCLUB_MEMBER5, FANCLUB_MEMBER2, FANCLUB_MEMBER1, FANCLUB_MEMBER3 }; u8 i; u8 idx = 0; if (GetNumFansOfPlayerInTrainerFanClub(fanClub) == 1) return 0; for (i = 0; i < NUM_TRAINER_FAN_CLUB_MEMBERS; i++) { if (GET_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[i])) { idx = i; if (Random() % 2) { FLIP_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[i]); return sFanClubMemberIds[i]; } } } if (GET_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[idx])) FLIP_TRAINER_FAN_CLUB_FLAG(sFanClubMemberIds[idx]); return sFanClubMemberIds[idx]; } u16 Script_GetNumFansOfPlayerInTrainerFanClub(void) { return GetNumFansOfPlayerInTrainerFanClub(TRAINER_FAN_CLUB); } static u16 GetNumFansOfPlayerInTrainerFanClub(struct TrainerFanClub *fanClub) { u8 count = 0; u8 i; for (i = 0; i < NUM_TRAINER_FAN_CLUB_MEMBERS; i++) { if (GET_TRAINER_FAN_CLUB_FLAG(i)) count++; } return count; } void Script_TryLoseFansFromPlayTime(void) { TryLoseFansFromPlayTime(TRAINER_FAN_CLUB); } static void TryLoseFansFromPlayTime(struct TrainerFanClub *fanClub) { u8 i = 0; u16 timer; if (gSaveBlock2Ptr->playTimeHours < 999) { while (1) { if (GetNumFansOfPlayerInTrainerFanClub(fanClub) < 5) { VarSet(VAR_FANCLUB_LOSE_FAN_TIMER, gSaveBlock2Ptr->playTimeHours); break; } if (i == NUM_TRAINER_FAN_CLUB_MEMBERS) break; timer = VarGet(VAR_FANCLUB_LOSE_FAN_TIMER); if (gSaveBlock2Ptr->playTimeHours - timer < 12) break; PlayerLoseRandomTrainerFan(fanClub); timer = VarGet(VAR_FANCLUB_LOSE_FAN_TIMER); VarSet(VAR_FANCLUB_LOSE_FAN_TIMER, timer + 12); i++; } } } bool16 Script_IsFanClubMemberFanOfPlayer(void) { return IsFanClubMemberFanOfPlayer(TRAINER_FAN_CLUB); } static bool16 IsFanClubMemberFanOfPlayer(struct TrainerFanClub *fanClub) { return GET_TRAINER_FAN_CLUB_FLAG(gSpecialVar_0x8004); } static void SetInitialFansOfPlayer(struct TrainerFanClub *fanClub) { SET_TRAINER_FAN_CLUB_FLAG(FANCLUB_MEMBER1); SET_TRAINER_FAN_CLUB_FLAG(FANCLUB_MEMBER2); SET_TRAINER_FAN_CLUB_FLAG(FANCLUB_MEMBER3); } void Script_BufferFanClubTrainerName(void) { u8 whichLinkTrainer = 0; u8 whichNPCTrainer = 0; switch (gSpecialVar_0x8004) { case FANCLUB_MEMBER1: whichNPCTrainer = 0; whichLinkTrainer = 0; break; case FANCLUB_MEMBER2: case FANCLUB_MEMBER3: case FANCLUB_MEMBER4: case FANCLUB_MEMBER8: break; case FANCLUB_MEMBER5: whichNPCTrainer = 1; whichLinkTrainer = 0; break; case FANCLUB_MEMBER6: whichNPCTrainer = 0; whichLinkTrainer = 1; break; case FANCLUB_MEMBER7: whichNPCTrainer = 2; whichLinkTrainer = 1; break; } BufferFanClubTrainerName(&gSaveBlock2Ptr->linkBattleRecords, whichLinkTrainer, whichNPCTrainer); } static void BufferFanClubTrainerName(struct LinkBattleRecords *linkRecords, u8 whichLinkTrainer, u8 whichNPCTrainer) { u8 *str; const u8 *linkTrainerName = linkRecords->entries[whichLinkTrainer].name; if (linkTrainerName[0] == EOS) { switch (whichNPCTrainer) { case 0: StringCopy(gStringVar1, gSaveBlock1Ptr->rivalName); break; case 1: StringCopy(gStringVar1, gText_LtSurge); break; case 2: StringCopy(gStringVar1, gText_Koga); break; default: StringCopy(gStringVar1, gSaveBlock1Ptr->rivalName); break; } } else { str = gStringVar1; StringCopyN(str, linkTrainerName, PLAYER_NAME_LENGTH); str[PLAYER_NAME_LENGTH] = EOS; if ( str[0] == EXT_CTRL_CODE_BEGIN && str[1] == EXT_CTRL_CODE_JPN) { str += 2; while (*str != EOS) str++; *str++ = EXT_CTRL_CODE_BEGIN; *str++ = EXT_CTRL_CODE_ENG; *str++ = EOS; } } } void Special_UpdateTrainerFansAfterLinkBattle(void) { UpdateTrainerFansAfterLinkBattle(TRAINER_FAN_CLUB); } static void UpdateTrainerFansAfterLinkBattle(struct TrainerFanClub *fanClub) { if (VarGet(VAR_MAP_SCENE_SAFFRON_CITY_POKEMON_TRAINER_FAN_CLUB) == 2) { TryLoseFansFromPlayTimeAfterLinkBattle(fanClub); if (gBattleOutcome == B_OUTCOME_WON) PlayerGainRandomTrainerFan(fanClub); else PlayerLoseRandomTrainerFan(fanClub); } } static bool8 DidPlayerGetFirstFans(struct TrainerFanClub *fanClub) { return fanClub->gotInitialFans; } void Script_SetPlayerGotFirstFans(void) { SetPlayerGotFirstFans(TRAINER_FAN_CLUB); } static void SetPlayerGotFirstFans(struct TrainerFanClub *fanClub) { fanClub->gotInitialFans = TRUE; } u8 Script_TryGainNewFanFromCounter(void) { return TryGainNewFanFromCounter(TRAINER_FAN_CLUB, gSpecialVar_0x8004); }