Final ai damage calc touches
This commit is contained in:
parent
967117093d
commit
6f484c20ce
5 changed files with 170 additions and 45 deletions
|
@ -275,6 +275,14 @@ struct WishFutureKnock
|
||||||
u8 knockedOffPokes[2];
|
u8 knockedOffPokes[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AI_SavedBattleMon
|
||||||
|
{
|
||||||
|
u8 ability;
|
||||||
|
u16 moves[4];
|
||||||
|
u16 heldItem;
|
||||||
|
u16 species;
|
||||||
|
};
|
||||||
|
|
||||||
struct AI_ThinkingStruct
|
struct AI_ThinkingStruct
|
||||||
{
|
{
|
||||||
u8 aiState;
|
u8 aiState;
|
||||||
|
@ -287,6 +295,7 @@ struct AI_ThinkingStruct
|
||||||
u8 aiLogicId;
|
u8 aiLogicId;
|
||||||
u8 filler12[6];
|
u8 filler12[6];
|
||||||
u8 simulatedRNG[4];
|
u8 simulatedRNG[4];
|
||||||
|
struct AI_SavedBattleMon saved[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UsedMoves
|
struct UsedMoves
|
||||||
|
|
|
@ -529,6 +529,7 @@ void GetSpeciesName(u8 *name, u16 species);
|
||||||
u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex);
|
u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex);
|
||||||
void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex);
|
void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex);
|
||||||
void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex);
|
void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex);
|
||||||
|
void PokemonToBattleMon(struct Pokemon *src, struct BattlePokemon *dst);
|
||||||
void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex);
|
void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex);
|
||||||
bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex);
|
bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex);
|
||||||
bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e);
|
bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "constants/battle_move_effects.h"
|
#include "constants/battle_move_effects.h"
|
||||||
#include "constants/moves.h"
|
#include "constants/moves.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "malloc.h"
|
||||||
#include "constants/battle_ai.h"
|
#include "constants/battle_ai.h"
|
||||||
|
|
||||||
#define AI_ACTION_DONE 0x0001
|
#define AI_ACTION_DONE 0x0001
|
||||||
|
@ -624,6 +625,25 @@ static void RecordLastUsedMoveByTarget(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool8 IsBattlerAIControlled(u8 battlerId)
|
||||||
|
{
|
||||||
|
switch (GetBattlerPosition(battlerId))
|
||||||
|
{
|
||||||
|
case B_POSITION_PLAYER_LEFT:
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
case B_POSITION_OPPONENT_LEFT:
|
||||||
|
return TRUE;
|
||||||
|
case B_POSITION_PLAYER_RIGHT:
|
||||||
|
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
case B_POSITION_OPPONENT_RIGHT:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClearBattlerMoveHistory(u8 battlerId)
|
void ClearBattlerMoveHistory(u8 battlerId)
|
||||||
{
|
{
|
||||||
s32 i;
|
s32 i;
|
||||||
|
@ -652,19 +672,115 @@ void ClearBattlerItemEffectHistory(u8 battlerId)
|
||||||
BATTLE_HISTORY->itemEffects[battlerId] = 0;
|
BATTLE_HISTORY->itemEffects[battlerId] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SaveBattlerData(u8 battlerId)
|
||||||
|
{
|
||||||
|
if (!IsBattlerAIControlled(battlerId))
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
AI_THINKING_STRUCT->saved[battlerId].ability = gBattleMons[battlerId].ability;
|
||||||
|
AI_THINKING_STRUCT->saved[battlerId].heldItem = gBattleMons[battlerId].item;
|
||||||
|
AI_THINKING_STRUCT->saved[battlerId].species = gBattleMons[battlerId].species;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
AI_THINKING_STRUCT->saved[battlerId].moves[i] = gBattleMons[battlerId].moves[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetBattlerData(u8 battlerId)
|
||||||
|
{
|
||||||
|
if (!IsBattlerAIControlled(battlerId))
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
// Use the known battler's ability.
|
||||||
|
if (BATTLE_HISTORY->abilities[battlerId] != ABILITY_NONE)
|
||||||
|
gBattleMons[battlerId].ability = BATTLE_HISTORY->abilities[battlerId];
|
||||||
|
// Check if mon can only have one ability.
|
||||||
|
else if (gBaseStats[gBattleMons[battlerId].species].ability2 == ABILITY_NONE)
|
||||||
|
gBattleMons[battlerId].ability = gBaseStats[gBattleMons[battlerId].species].ability1;
|
||||||
|
else
|
||||||
|
// The ability is unknown.
|
||||||
|
gBattleMons[battlerId].ability = ABILITY_NONE;
|
||||||
|
|
||||||
|
if (BATTLE_HISTORY->itemEffects[battlerId] == 0)
|
||||||
|
gBattleMons[battlerId].item = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (BATTLE_HISTORY->usedMoves[battlerId].moves[i] == 0)
|
||||||
|
gBattleMons[battlerId].moves[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RestoreBattlerData(u8 battlerId)
|
||||||
|
{
|
||||||
|
if (!IsBattlerAIControlled(battlerId))
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
gBattleMons[battlerId].ability = AI_THINKING_STRUCT->saved[battlerId].ability;
|
||||||
|
gBattleMons[battlerId].item = AI_THINKING_STRUCT->saved[battlerId].heldItem;
|
||||||
|
gBattleMons[battlerId].species = AI_THINKING_STRUCT->saved[battlerId].species;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
gBattleMons[battlerId].moves[i] = AI_THINKING_STRUCT->saved[battlerId].moves[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
|
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||||
{
|
{
|
||||||
return CalculateMoveDamage(move, battlerAtk, battlerDef, gBattleMoves[move].type, 0, FALSE, FALSE);
|
s32 dmg;
|
||||||
|
|
||||||
|
SaveBattlerData(battlerAtk);
|
||||||
|
SaveBattlerData(battlerDef);
|
||||||
|
|
||||||
|
SetBattlerData(battlerAtk);
|
||||||
|
SetBattlerData(battlerDef);
|
||||||
|
|
||||||
|
dmg = CalculateMoveDamage(move, battlerAtk, battlerDef, gBattleMoves[move].type, 0, FALSE, FALSE);
|
||||||
|
|
||||||
|
RestoreBattlerData(battlerAtk);
|
||||||
|
RestoreBattlerData(battlerDef);
|
||||||
|
|
||||||
|
return dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon *mon)
|
s32 AI_CalcPartyMonDamage(u16 move, u8 battlerAtk, u8 battlerDef, struct Pokemon *mon)
|
||||||
{
|
{
|
||||||
return 0;
|
s32 dmg;
|
||||||
|
u32 i;
|
||||||
|
struct BattlePokemon *battleMons = Alloc(sizeof(struct BattlePokemon) * MAX_BATTLERS_COUNT);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||||
|
battleMons[i] = gBattleMons[i];
|
||||||
|
|
||||||
|
PokemonToBattleMon(mon, &gBattleMons[battlerAtk]);
|
||||||
|
dmg = AI_CalcDamage(move, battlerAtk, battlerDef);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||||
|
gBattleMons[i] = battleMons[i];
|
||||||
|
|
||||||
|
Free(battleMons);
|
||||||
|
|
||||||
|
return dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
|
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||||
{
|
{
|
||||||
return CalcTypeEffectivenessMultiplier(move, gBattleMoves[move].type, battlerAtk, battlerDef, FALSE);
|
u16 typeEffectiveness;
|
||||||
|
|
||||||
|
SaveBattlerData(battlerAtk);
|
||||||
|
SaveBattlerData(battlerDef);
|
||||||
|
|
||||||
|
SetBattlerData(battlerAtk);
|
||||||
|
SetBattlerData(battlerDef);
|
||||||
|
|
||||||
|
typeEffectiveness = CalcTypeEffectivenessMultiplier(move, gBattleMoves[move].type, battlerAtk, battlerDef, FALSE);
|
||||||
|
|
||||||
|
RestoreBattlerData(battlerAtk);
|
||||||
|
RestoreBattlerData(battlerDef);
|
||||||
|
|
||||||
|
return typeEffectiveness;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BattleAICmd_if_random_less_than(void)
|
static void BattleAICmd_if_random_less_than(void)
|
||||||
|
|
|
@ -17,8 +17,6 @@ extern void sub_81B8FB0(u8, u8);
|
||||||
|
|
||||||
void AllocateBattleResources(void)
|
void AllocateBattleResources(void)
|
||||||
{
|
{
|
||||||
gBattleResources = gBattleResources; // something dumb needed to match
|
|
||||||
|
|
||||||
if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
|
if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
|
||||||
sub_81D55D0();
|
sub_81D55D0();
|
||||||
|
|
||||||
|
|
|
@ -3420,57 +3420,58 @@ void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex)
|
||||||
mon->ppBonuses &= gUnknown_08329D26[moveIndex];
|
mon->ppBonuses &= gUnknown_08329D26[moveIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex)
|
void PokemonToBattleMon(struct Pokemon *src, struct BattlePokemon *dst)
|
||||||
{
|
{
|
||||||
u16* hpSwitchout;
|
|
||||||
s32 i;
|
s32 i;
|
||||||
u8 nickname[POKEMON_NAME_LENGTH * 2];
|
u8 nickname[POKEMON_NAME_LENGTH * 2];
|
||||||
|
|
||||||
gBattleMons[battlerId].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL);
|
|
||||||
gBattleMons[battlerId].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
gBattleMons[battlerId].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL);
|
dst->moves[i] = GetMonData(src, MON_DATA_MOVE1 + i, NULL);
|
||||||
gBattleMons[battlerId].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL);
|
dst->pp[i] = GetMonData(src, MON_DATA_PP1 + i, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
gBattleMons[battlerId].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL);
|
dst->species = GetMonData(src, MON_DATA_SPECIES, NULL);
|
||||||
gBattleMons[battlerId].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL);
|
dst->item = GetMonData(src, MON_DATA_HELD_ITEM, NULL);
|
||||||
gBattleMons[battlerId].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL);
|
dst->ppBonuses = GetMonData(src, MON_DATA_PP_BONUSES, NULL);
|
||||||
gBattleMons[battlerId].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL);
|
dst->friendship = GetMonData(src, MON_DATA_FRIENDSHIP, NULL);
|
||||||
gBattleMons[battlerId].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL);
|
dst->experience = GetMonData(src, MON_DATA_EXP, NULL);
|
||||||
gBattleMons[battlerId].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL);
|
dst->hpIV = GetMonData(src, MON_DATA_HP_IV, NULL);
|
||||||
gBattleMons[battlerId].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED_IV, NULL);
|
dst->attackIV = GetMonData(src, MON_DATA_ATK_IV, NULL);
|
||||||
gBattleMons[battlerId].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL);
|
dst->defenseIV = GetMonData(src, MON_DATA_DEF_IV, NULL);
|
||||||
gBattleMons[battlerId].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL);
|
dst->speedIV = GetMonData(src, MON_DATA_SPEED_IV, NULL);
|
||||||
gBattleMons[battlerId].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL);
|
dst->spAttackIV = GetMonData(src, MON_DATA_SPATK_IV, NULL);
|
||||||
gBattleMons[battlerId].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL);
|
dst->spDefenseIV = GetMonData(src, MON_DATA_SPDEF_IV, NULL);
|
||||||
gBattleMons[battlerId].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL);
|
dst->personality = GetMonData(src, MON_DATA_PERSONALITY, NULL);
|
||||||
gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL);
|
dst->status1 = GetMonData(src, MON_DATA_STATUS, NULL);
|
||||||
gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL);
|
dst->level = GetMonData(src, MON_DATA_LEVEL, NULL);
|
||||||
gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL);
|
dst->hp = GetMonData(src, MON_DATA_HP, NULL);
|
||||||
gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL);
|
dst->maxHP = GetMonData(src, MON_DATA_MAX_HP, NULL);
|
||||||
gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED, NULL);
|
dst->attack = GetMonData(src, MON_DATA_ATK, NULL);
|
||||||
gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL);
|
dst->defense = GetMonData(src, MON_DATA_DEF, NULL);
|
||||||
gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL);
|
dst->speed = GetMonData(src, MON_DATA_SPEED, NULL);
|
||||||
gBattleMons[battlerId].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL);
|
dst->spAttack = GetMonData(src, MON_DATA_SPATK, NULL);
|
||||||
gBattleMons[battlerId].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL);
|
dst->spDefense = GetMonData(src, MON_DATA_SPDEF, NULL);
|
||||||
gBattleMons[battlerId].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL);
|
dst->isEgg = GetMonData(src, MON_DATA_IS_EGG, NULL);
|
||||||
gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1;
|
dst->altAbility = GetMonData(src, MON_DATA_ALT_ABILITY, NULL);
|
||||||
gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2;
|
dst->otId = GetMonData(src, MON_DATA_OT_ID, NULL);
|
||||||
gBattleMons[battlerId].ability = GetAbilityBySpecies(gBattleMons[battlerId].species, gBattleMons[battlerId].altAbility);
|
dst->type1 = gBaseStats[dst->species].type1;
|
||||||
GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
|
dst->type2 = gBaseStats[dst->species].type2;
|
||||||
StringCopy10(gBattleMons[battlerId].nickname, nickname);
|
dst->ability = GetAbilityBySpecies(dst->species, dst->altAbility);
|
||||||
GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[battlerId].otName);
|
GetMonData(src, MON_DATA_NICKNAME, nickname);
|
||||||
|
StringCopy10(dst->nickname, nickname);
|
||||||
|
GetMonData(src, MON_DATA_OT_NAME, dst->otName);
|
||||||
|
|
||||||
hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(battlerId)];
|
for (i = 0; i < BATTLE_STATS_NO; i++)
|
||||||
*hpSwitchout = gBattleMons[battlerId].hp;
|
dst->statStages[i] = 6;
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
dst->status2 = 0;
|
||||||
gBattleMons[battlerId].statStages[i] = 6;
|
}
|
||||||
|
|
||||||
gBattleMons[battlerId].status2 = 0;
|
void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex)
|
||||||
|
{
|
||||||
|
PokemonToBattleMon(&gPlayerParty[partyIndex], &gBattleMons[battlerId]);
|
||||||
|
gBattleStruct->hpOnSwitchout[GetBattlerSide(battlerId)] = gBattleMons[battlerId].hp;
|
||||||
sub_803FA70(battlerId);
|
sub_803FA70(battlerId);
|
||||||
ClearTemporarySpeciesSpriteData(battlerId, FALSE);
|
ClearTemporarySpeciesSpriteData(battlerId, FALSE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue