Important battle util functions

This commit is contained in:
DizzyEggg 2018-07-14 16:41:14 +02:00
parent b24427f3bf
commit 939127bfff
9 changed files with 297 additions and 9 deletions

View File

@ -473,8 +473,10 @@
.word \jumpptr
.endm
.macro nullsub_53
.macro if_field_status flag jumpptr
.byte 0x53
.word \flag
.word \jumpptr
.endm
.macro nullsub_54

View File

@ -570,7 +570,7 @@ AI_CBM_Refresh: @ 82DC713
end
AI_CBM_MudSport: @ 82DC71E
if_status3 AI_USER, STATUS3_MUDSPORT, Score_Minus10
if_field_status STATUS_FIELD_MUDSPORT, Score_Minus10
end
AI_CBM_Tickle: @ 82DC729
@ -589,7 +589,7 @@ AI_CBM_BulkUp: @ 82DC74B
end
AI_CBM_WaterSport: @ 82DC75C
if_status3 AI_USER, STATUS3_WATERSPORT, Score_Minus10
if_field_status STATUS_FIELD_WATERSPORT, Score_Minus10
end
AI_CBM_CalmMind: @ 82DC767

View File

@ -171,7 +171,8 @@ struct DisableStruct
/*0x18*/ u8 unk18_a_2:2;
/*0x18*/ u8 unk18_b:4;
/*0x19*/ u8 rechargeCounter;
/*0x1A*/ u8 unk1A[2];
/*0x1A*/ u8 autonomizeCount;
/*0x1B*/ u8 slowStartTimer;
};
struct ProtectStruct
@ -259,6 +260,7 @@ struct FieldTimer
u8 mistyTerrainTimer;
u8 electricTerrainTimer;
u8 psychicTerrainTimer;
u8 echoVoiceCounter;
};
struct WishFutureKnock

View File

@ -72,5 +72,12 @@ void ClearFuryCutterDestinyBondGrudge(u8 battlerId);
void HandleAction_RunBattleScript(void);
u8 GetMoveTarget(u16 move, u8 setTarget);
u8 IsMonDisobedient(void);
u32 GetBattlerAbility(u8 battlerId);
u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating);
u32 GetBattlerHoldEffectParam(u8 battlerId);
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk);
bool32 IsBattlerGrounded(u8 battlerId);
u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move);
u32 GetBattlerWeight(u8 battlerId);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -143,11 +143,14 @@
#define STATUS3_IMPRISONED_OTHERS 0x2000
#define STATUS3_GRUDGE 0x4000
#define STATUS3_CANT_SCORE_A_CRIT 0x8000
// #define STATUS3_MUDSPORT 0x10000
// #define STATUS3_WATERSPORT 0x20000
#define STATUS3_GASTRO_ACID 0x10000
#define STATUS3_EMBARGO 0x20000
#define STATUS3_UNDERWATER 0x40000
#define STATUS3_INTIMIDATE_POKES 0x80000
#define STATUS3_TRACE 0x100000
#define STATUS3_SMACKED_DOWN 0x200000
#define STATUS3_ME_FIRST 0x400000
#define STATUS3_TELEKINESIS 0x800000
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
// Not really sure what a "hitmarker" is.

View File

@ -216,4 +216,29 @@
#define EFFECT_DRAGON_DANCE 212
#define EFFECT_CAMOUFLAGE 213
// New move effects
#define EFFECT_PLEDGE 214
#define EFFECT_FLING 215
#define EFFECT_NATURAL_GIFT 216
#define EFFECT_WAKE_UP_SLAP 217
#define EFFECT_WRING_OUT 218
#define EFFECT_HEX 219
#define EFFECT_ASSURANCE 220
#define EFFECT_TRUMP_CARD 221
#define EFFECT_ACROBATICS 222
#define EFFECT_HEAT_CRASH 223
#define EFFECT_PUNISHMENT 224
#define EFFECT_STORED_POWER 225
#define EFFECT_ELECTRO_BALL 226
#define EFFECT_GYRO_BALL 227
#define EFFECT_ECHOED_VOICE 228
#define EFFECT_PAYBACK 229
#define EFFECT_ROUND 230
#define EFFECT_BRINE 231
#define EFFECT_VENOSHOCK 232
#define EFFECT_RETALITATE 233
#define EFFECT_BULLDOZE 234
#define EFFECT_FOUL_PLAY 235
#define EFFECT_PSYSHOCK 236
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -97,5 +97,13 @@
#define HOLD_EFFECT_DESTINY_KNOT 91
#define HOLD_EFFECT_SHED_SHELL 92
// Gen5 hold effects
#define HOLD_EFFECT_FLOAT_STONE 115
// Gen6 hold effects
#define HOLD_EFFECT_FAIRY_POWER 130
// Gen7 hold effects
#define HOLD_EFFECT_PROTECTIVE_PADS 150
#endif // GUARD_HOLD_EFFECTS_H

View File

@ -136,7 +136,7 @@ static void BattleAICmd_get_move_power_from_result(void);
static void BattleAICmd_get_move_effect_from_result(void);
static void BattleAICmd_get_protect_count(void);
static void BattleAICmd_if_move_flag(void);
static void BattleAICmd_nullsub_53(void);
static void BattleAICmd_if_field_status(void);
static void BattleAICmd_nullsub_54(void);
static void BattleAICmd_nullsub_55(void);
static void BattleAICmd_nullsub_56(void);
@ -245,7 +245,7 @@ static const BattleAICmdFunc sBattleAICmdTable[] =
BattleAICmd_get_move_effect_from_result, // 0x50
BattleAICmd_get_protect_count, // 0x51
BattleAICmd_if_move_flag, // 0x52
BattleAICmd_nullsub_53, // 0x53
BattleAICmd_if_field_status, // 0x53
BattleAICmd_nullsub_54, // 0x54
BattleAICmd_nullsub_55, // 0x55
BattleAICmd_nullsub_56, // 0x56
@ -2133,8 +2133,14 @@ static void BattleAICmd_if_move_flag(void)
gAIScriptPtr += 7;
}
static void BattleAICmd_nullsub_53(void)
static void BattleAICmd_if_field_status(void)
{
u32 fieldFlags = T1_READ_32(gAIScriptPtr + 1);
if (gFieldStatuses & fieldFlags)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5);
else
gAIScriptPtr += 9;
}
static void BattleAICmd_nullsub_54(void)

View File

@ -22,6 +22,7 @@
#include "event_data.h"
#include "link.h"
#include "berry.h"
#include "pokedex.h"
extern u8 weather_get_current(void);
@ -3369,3 +3370,237 @@ u8 IsMonDisobedient(void)
}
}
}
static const u8 sAbilitiesAffectedByMoldBreaker[] =
{
[ABILITY_BATTLE_ARMOR] = 1,
[ABILITY_CLEAR_BODY] = 1,
[ABILITY_DAMP] = 1,
[ABILITY_DRY_SKIN] = 1,
[ABILITY_FILTER] = 1,
[ABILITY_FLASH_FIRE] = 1,
[ABILITY_FLOWER_GIFT] = 1,
[ABILITY_HEATPROOF] = 1,
[ABILITY_HYPER_CUTTER] = 1,
[ABILITY_IMMUNITY] = 1,
[ABILITY_INNER_FOCUS] = 1,
[ABILITY_INSOMNIA] = 1,
[ABILITY_KEEN_EYE] = 1,
[ABILITY_LEAF_GUARD] = 1,
[ABILITY_LEVITATE] = 1,
[ABILITY_LIGHTNING_ROD] = 1,
[ABILITY_LIMBER] = 1,
[ABILITY_MAGMA_ARMOR] = 1,
[ABILITY_MARVEL_SCALE] = 1,
[ABILITY_MOTOR_DRIVE] = 1,
[ABILITY_OBLIVIOUS] = 1,
[ABILITY_OWN_TEMPO] = 1,
[ABILITY_SAND_VEIL] = 1,
[ABILITY_SHELL_ARMOR] = 1,
[ABILITY_SHIELD_DUST] = 1,
[ABILITY_SIMPLE] = 1,
[ABILITY_SNOW_CLOAK] = 1,
[ABILITY_SOLID_ROCK] = 1,
[ABILITY_SOUNDPROOF] = 1,
[ABILITY_STICKY_HOLD] = 1,
[ABILITY_STORM_DRAIN] = 1,
[ABILITY_STURDY] = 1,
[ABILITY_SUCTION_CUPS] = 1,
[ABILITY_TANGLED_FEET] = 1,
[ABILITY_THICK_FAT] = 1,
[ABILITY_UNAWARE] = 1,
[ABILITY_VITAL_SPIRIT] = 1,
[ABILITY_VOLT_ABSORB] = 1,
[ABILITY_WATER_ABSORB] = 1,
[ABILITY_WATER_VEIL] = 1,
[ABILITY_WHITE_SMOKE] = 1,
[ABILITY_WONDER_GUARD] = 1,
[ABILITY_BIG_PECKS] = 1,
[ABILITY_CONTRARY] = 1,
[ABILITY_FRIEND_GUARD] = 1,
[ABILITY_HEAVY_METAL] = 1,
[ABILITY_LIGHT_METAL] = 1,
[ABILITY_MAGIC_BOUNCE] = 1,
[ABILITY_MULTISCALE] = 1,
[ABILITY_SAP_SIPPER] = 1,
[ABILITY_TELEPATHY] = 1,
[ABILITY_WONDER_SKIN] = 1,
[ABILITY_AROMA_VEIL] = 1,
[ABILITY_BULLETPROOF] = 1,
[ABILITY_FLOWER_VEIL] = 1,
[ABILITY_FUR_COAT] = 1,
[ABILITY_OVERCOAT] = 1,
[ABILITY_SWEET_VEIL] = 1,
[ABILITY_DAZZLING] = 1,
[ABILITY_DISGUISE] = 1,
[ABILITY_FLUFFY] = 1,
[ABILITY_QUEENLY_MAJESTY] = 1,
[ABILITY_WATER_BUBBLE] = 1,
};
u32 GetBattlerAbility(u8 battlerId)
{
if (gStatuses3[battlerId] & STATUS3_GASTRO_ACID)
return ABILITY_NONE;
else if ((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TERAVOLT
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TURBOBLAZE)
&& sAbilitiesAffectedByMoldBreaker[gBattleMons[battlerId].ability]
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == gBattlerAttacker
&& gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE
&& gCurrentTurnActionNumber < gBattlersCount
&& !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
return ABILITY_NONE;
else
return gBattleMons[battlerId].ability;
}
u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
{
if (checkNegating)
{
if (gStatuses3[battlerId] & STATUS3_EMBARGO)
return HOLD_EFFECT_NONE;
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)
return HOLD_EFFECT_NONE;
if (gBattleMons[battlerId].ability == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID))
return HOLD_EFFECT_NONE;
}
gPotentialItemEffectBattler = battlerId;
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY)
return gEnigmaBerries[battlerId].holdEffect;
else
return ItemId_GetHoldEffect(gBattleMons[battlerId].item);
}
u32 GetBattlerHoldEffectParam(u8 battlerId)
{
if (gBattleMons[battlerId].item == ITEM_ENIGMA_BERRY)
return gEnigmaBerries[battlerId].holdEffectParam;
else
return ItemId_GetHoldEffectParam(gBattleMons[battlerId].item);
}
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk)
{
if (!(gBattleMoves[move].flags & FLAG_MAKES_CONTACT))
return FALSE;
else if (GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH)
return FALSE;
else if (GetBattlerHoldEffect(battlerAtk, TRUE) == HOLD_EFFECT_PROTECTIVE_PADS)
return FALSE;
else
return TRUE;
}
bool32 IsBattlerGrounded(u8 battlerId)
{
if (GetBattlerHoldEffect(battlerId, TRUE) == HOLD_EFFECT_IRON_BALL)
return TRUE;
else if (gFieldStatuses & STATUS_FIELD_GRAVITY)
return TRUE;
else if (gStatuses3[battlerId] & STATUS3_ROOTED)
return TRUE;
else if (gStatuses3[battlerId] & STATUS3_SMACKED_DOWN)
return TRUE;
else if (gStatuses3[battlerId] & STATUS3_TELEKINESIS)
return FALSE;
else if (GetBattlerAbility(battlerId) == ABILITY_LEVITATE)
return FALSE;
else if (IS_BATTLER_OF_TYPE(battlerId, TYPE_FLYING))
return FALSE;
else
return TRUE;
}
bool32 IsBattlerAlive(u8 battlerId)
{
if (gBattleMons[battlerId].hp == 0)
return FALSE;
else if (battlerId >= gBattlersCount)
return FALSE;
else if (gAbsentBattlerFlags & gBitTable[battlerId])
return FALSE;
else
return TRUE;
}
u8 GetBattleMonMoveSlot(struct BattlePokemon *battleMon, u16 move)
{
u8 i;
for (i = 0; i < 4; i++)
{
if (battleMon->moves[i] == move)
break;
}
return i;
}
u32 GetBattlerWeight(u8 battlerId)
{
u32 weight = GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[battlerId].species), 1);
u32 ability = GetBattlerAbility(battlerId);
u32 holdEffect = GetBattlerHoldEffect(battlerId, TRUE);
if (ability == ABILITY_HEAVY_METAL)
weight *= 2;
else if (ability == ABILITY_LIGHT_METAL)
weight /= 2;
if (holdEffect == HOLD_EFFECT_FLOAT_STONE)
weight /= 2;
if (gDisableStructs[battlerId].autonomizeCount)
weight -= 1000 * gDisableStructs[battlerId].autonomizeCount;
if (weight == 0)
weight = 1;
return weight;
}
u32 CountBattlerStatIncreases(u8 battlerId, bool32 countEvasionAcc)
{
u32 i;
u32 count = 0;
for (i = 0; i < BATTLE_STATS_NO; i++)
{
if ((i == STAT_ACC || i == STAT_EVASION) && !countEvasionAcc)
continue;
if (gBattleMons[battlerId].statStages[i] > 6) // Stat is increased.
count += gBattleMons[battlerId].statStages[i] - 6;
}
return count;
}
u32 GetMoveTargetCount(u16 move, u8 battlerAtk, u8 battlerDef)
{
switch (gBattleMoves[move].target)
{
case MOVE_TARGET_BOTH:
return IsBattlerAlive(battlerDef)
+ IsBattlerAlive(BATTLE_PARTNER(battlerDef));
case MOVE_TARGET_FOES_AND_ALLY:
return IsBattlerAlive(battlerDef)
+ IsBattlerAlive(BATTLE_PARTNER(battlerDef))
+ IsBattlerAlive(BATTLE_PARTNER(battlerAtk));
case MOVE_TARGET_OPPONENTS_FIELD:
return 1;
case MOVE_TARGET_DEPENDS:
case MOVE_TARGET_SELECTED:
case MOVE_TARGET_RANDOM:
case MOVE_TARGET_USER_OR_SELECTED:
return IsBattlerAlive(battlerDef);
case MOVE_TARGET_USER:
return IsBattlerAlive(battlerAtk);
default:
return 0;
}
}