Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic AI Functions #4908

Merged
merged 5 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions asm/macros/event.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2094,6 +2094,11 @@
setvar VAR_0x8006, \item
special CreateEnemyEventMon
.endm

.macro setdynamicaifunc func:req
callnative ScriptSetDynamicAiFunc
.4byte \func
.endm

@ Set up a totem boost for the next battle.
@ 'battler' is the position of the mon you want to gain a boost. see B_POSITION_xx in include/constants/battle.h.
Expand Down
4 changes: 4 additions & 0 deletions include/battle_ai_main.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef GUARD_BATTLE_AI_MAIN_H
#define GUARD_BATTLE_AI_MAIN_H


typedef s32 (*AiScoreFunc)(u32, u32, u32, s32);

#define UNKNOWN_NO_OF_HITS UINT32_MAX

// return vals for BattleAI_ChooseMoveOrAction
Expand Down Expand Up @@ -101,6 +104,7 @@ void Ai_InitPartyStruct(void);
void Ai_UpdateSwitchInData(u32 battler);
void Ai_UpdateFaintData(u32 battler);
void SetAiLogicDataForTurn(struct AiLogicData *aiData);
void ResetDynamicAiFunc(void);

extern u8 sBattler_AI;

Expand Down
1 change: 1 addition & 0 deletions include/constants/battle_ai.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#define AI_FLAG_COUNT 20

// 'other' ai logic flags
#define AI_FLAG_DYNAMIC_FUNC (1 << 28) // Create custom AI functions for specific battles via "setdynamicaifunc" cmd
#define AI_FLAG_ROAMING (1 << 29)
#define AI_FLAG_SAFARI (1 << 30)
#define AI_FLAG_FIRST_BATTLE (1 << 31)
Expand Down
52 changes: 51 additions & 1 deletion src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "random.h"
#include "recorded_battle.h"
#include "util.h"
#include "script.h"
#include "constants/abilities.h"
#include "constants/battle_ai.h"
#include "constants/battle_move_effects.h"
Expand All @@ -39,6 +40,7 @@ static bool32 IsPinchBerryItemEffect(u32 holdEffect);
// ewram
EWRAM_DATA const u8 *gAIScriptPtr = NULL; // Still used in contests
EWRAM_DATA u8 sBattler_AI = 0;
EWRAM_DATA AiScoreFunc sDynamicAiFunc = NULL;

// const rom data
static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
Expand All @@ -54,6 +56,7 @@ static s32 AI_Safari(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);
static s32 AI_DynamicFunc(u32 battlerAtk, u32 battlerDef, u32 move, s32 score);


static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
Expand Down Expand Up @@ -86,7 +89,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) =
[25] = NULL, // Unused
[26] = NULL, // Unused
[27] = NULL, // Unused
[28] = NULL, // Unused
[28] = AI_DynamicFunc, // AI_FLAG_DYNAMIC_FUNC
AlexOn1ine marked this conversation as resolved.
Show resolved Hide resolved
[29] = AI_Roaming, // AI_FLAG_ROAMING
[30] = AI_Safari, // AI_FLAG_SAFARI
[31] = AI_FirstBattle, // AI_FLAG_FIRST_BATTLE
Expand Down Expand Up @@ -179,6 +182,9 @@ static u32 GetAiFlags(u16 trainerId)
// Automatically includes AI_FLAG_SMART_MON_CHOICES to improve smart switching
if (flags & AI_FLAG_SMART_SWITCHING)
flags |= AI_FLAG_SMART_MON_CHOICES;

if (sDynamicAiFunc != NULL)
flags |= AI_FLAG_DYNAMIC_FUNC;

return flags;
}
Expand Down Expand Up @@ -5331,3 +5337,47 @@ static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)

return score;
}


// Dynamic AI Functions
// For specific battle scenarios

// Example - prefer attacking opposite foe in a tag battle
s32 AI_TagBattlePreferFoe(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER))
{
/* not a partner battle */
return score;
}
else if (!IsBattlerAlive(BATTLE_OPPOSITE(battlerAtk)) || !IsBattlerAlive(BATTLE_PARTNER(BATTLE_OPPOSITE(battlerAtk))))
{
/* partner is defeated so attack normally */
return score;
}
else if (battlerDef == BATTLE_OPPOSITE(battlerAtk))
{
/* attacking along the diagonal */
ADJUST_SCORE(-20);
}

return score;
}

static s32 AI_DynamicFunc(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
{
if (sDynamicAiFunc != NULL)
score = sDynamicAiFunc(battlerAtk, battlerDef, move, score);
return score;
}

void ScriptSetDynamicAiFunc(struct ScriptContext *ctx)
{
AiScoreFunc func = (AiScoreFunc)ScriptReadWord(ctx);
sDynamicAiFunc = func;
}

void ResetDynamicAiFunc(void)
{
sDynamicAiFunc = NULL;
}
2 changes: 2 additions & 0 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,7 @@ static void FreeRestoreBattleData(void)
FreeMonSpritesGfx();
FreeBattleSpritesData();
FreeBattleResources();
ResetDynamicAiFunc();
}

void CB2_QuitRecordedBattle(void)
Expand Down Expand Up @@ -5530,6 +5531,7 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void)
if (gBattleStruct != NULL && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
{
ZeroEnemyPartyMons();
ResetDynamicAiFunc();
FreeMonSpritesGfx();
FreeBattleResources();
FreeBattleSpritesData();
Expand Down
Loading