Final ai damage calc touches

This commit is contained in:
DizzyEggg 2018-07-15 18:07:01 +02:00
parent 967117093d
commit 6f484c20ce
5 changed files with 170 additions and 45 deletions

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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();

View file

@ -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);
} }