Dynamic AI Functions (#4908)
* dynamic ai func * add AI_TagBattlePreferFoe as an example * Update src/battle_ai_main.c * Update src/battle_ai_main.c --------- Co-authored-by: ghoulslash <pokevoyager0@gmail.com> Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
parent
49e93799d1
commit
e1d8ef8190
@ -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.
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
@ -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);
|
||||
@ -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) =
|
||||
@ -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
|
||||
[29] = AI_Roaming, // AI_FLAG_ROAMING
|
||||
[30] = AI_Safari, // AI_FLAG_SAFARI
|
||||
[31] = AI_FirstBattle, // AI_FLAG_FIRST_BATTLE
|
||||
@ -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;
|
||||
}
|
||||
@ -5335,3 +5341,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;
|
||||
}
|
||||
|
||||
@ -1766,6 +1766,7 @@ static void FreeRestoreBattleData(void)
|
||||
FreeMonSpritesGfx();
|
||||
FreeBattleSpritesData();
|
||||
FreeBattleResources();
|
||||
ResetDynamicAiFunc();
|
||||
}
|
||||
|
||||
void CB2_QuitRecordedBattle(void)
|
||||
@ -5530,6 +5531,7 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void)
|
||||
if (gBattleStruct != NULL && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
|
||||
{
|
||||
ZeroEnemyPartyMons();
|
||||
ResetDynamicAiFunc();
|
||||
FreeMonSpritesGfx();
|
||||
FreeBattleResources();
|
||||
FreeBattleSpritesData();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user