first changes to item_use in preparation for new items

This commit is contained in:
cawtds
2024-04-16 21:40:57 +02:00
parent 356ffd1627
commit d869d3355d
38 changed files with 1830 additions and 10546 deletions

View File

@@ -553,6 +553,20 @@
.4byte \ptr
.endm
.macro if_status4 battler:req, status:req, ptr:req
.byte 0x5e
.byte \battler
.4byte \status
.4byte \ptr
.endm
.macro if_not_status4 battler:req, status:req, ptr:req
.byte 0x5f
.byte \battler
.4byte \status
.4byte \ptr
.endm
@ useful script macros
.macro get_curr_move_type
get_type AI_TYPE_MOVE

View File

@@ -1378,3 +1378,31 @@
.macro jumpifnotbattletype flags:req, jumpptr:req
jumpifword CMP_NO_COMMON_BITS, gBattleTypeFlags, \flags, \jumpptr
.endm
.macro callnative func:req
.byte 0xff
.4byte \func
.endm
@ callnative macros
.macro itemrestorehp
callnative BS_ItemRestoreHP
.endm
.macro itemcurestatus
callnative BS_ItemCureStatus
.endm
.macro itemincreasestat
callnative BS_ItemIncreaseStat
.endm
.macro itemrestorepp
callnative BS_ItemRestorePP
.endm
@ returns B_SIDE_x to gBattleCommunication[0]
.macro getbattlerside battler:req
callnative BS_GetBattlerSide
.byte \battler
.endm

View File

@@ -569,7 +569,7 @@ AI_CBM_Refresh::
end
AI_CBM_MudSport::
if_status3 AI_USER, STATUS3_MUDSPORT, Score_Minus10
if_status4 AI_USER, STATUS4_MUD_SPORT, Score_Minus10
end
AI_CBM_Tickle::
@@ -588,7 +588,7 @@ AI_CBM_BulkUp::
end
AI_CBM_WaterSport::
if_status3 AI_USER, STATUS3_WATERSPORT, Score_Minus10
if_status4 AI_USER, STATUS4_WATER_SPORT, Score_Minus10
end
AI_CBM_CalmMind::

View File

@@ -24,7 +24,7 @@ gBattlescriptsForBallThrow::
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowSafariBall
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowBall
.4byte BattleScript_ThrowBall
@@ -35,6 +35,19 @@ gBattlescriptsForBallThrow::
gBattlescriptsForUsingItem::
.4byte BattleScript_PlayerUseItem
.4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_RESTORE_HP
.4byte BattleScript_ItemCureStatus @ EFFECT_ITEM_CURE_STATUS
.4byte BattleScript_ItemHealAndCureStatus @ EFFECT_ITEM_HEAL_AND_CURE_STATUS
.4byte BattleScript_ItemIncreaseStat @ EFFECT_ITEM_INCREASE_STAT
.4byte BattleScript_ItemSetMist @ EFFECT_ITEM_SET_MIST
.4byte BattleScript_ItemSetFocusEnergy @ EFFECT_ITEM_SET_FOCUS_ENERGY
.4byte BattleScript_RunByUsingItem @ EFFECT_ITEM_ESCAPE
.4byte BattleScript_BallThrow @ EFFECT_ITEM_THROW_BALL
.4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_REVIVE
.4byte BattleScript_ItemRestorePP @ EFFECT_ITEM_RESTORE_PP
.4byte BattleScript_ItemIncreaseAllStats @ EFFECT_ITEM_INCREASE_ALL_STATS
gBattleScriptsForAIUsingItems::
.4byte BattleScript_AIUseFullRestoreOrHpHeal
.4byte BattleScript_AIUseFullRestoreOrHpHeal
.4byte BattleScript_AIUseStatRestore
@@ -45,6 +58,115 @@ gBattlescriptsForRunningByItem::
.4byte BattleScript_UseFluffyTail
.4byte BattleScript_UsePokeFlute
BattleScript_ItemEnd:
end
BattleScript_UseItemMessage:
@ printstring STRINGID_EMPTYSTRING3
@ pause B_WAIT_TIME_MED
@ playse SE_USE_ITEM
@ getbattlerside BS_ATTACKER
@ copybyte cMULTISTRING_CHOOSER, gBattleCommunication
@ printfromtable gTrainerUsedItemStringIds
@ waitmessage B_WAIT_TIME_LONG
moveendcase 15
return
BattleScript_ItemRestoreHP::
@ call BattleScript_UseItemMessage
@ itemrestorehp
@ bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
@ orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
@ healthbarupdate BS_SCRIPTING
@ datahpupdate BS_SCRIPTING
@ printstring STRINGID_ITEMRESTOREDSPECIESHEALTH
@ waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemCureStatus::
@call BattleScript_UseItemMessage
@itemcurestatus
@updatestatusicon BS_SCRIPTING
@printstring STRINGID_ITEMCUREDSPECIESSTATUS
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemHealAndCureStatus::
@call BattleScript_UseItemMessage
@itemrestorehp
@itemcurestatus
@printstring STRINGID_ITEMRESTOREDSPECIESHEALTH
@waitmessage B_WAIT_TIME_LONG
@bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
@orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
@healthbarupdate BS_SCRIPTING
@datahpupdate BS_SCRIPTING
@updatestatusicon BS_SCRIPTING
@printstring STRINGID_ITEMRESTOREDSPECIESHEALTH
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemIncreaseStat::
@call BattleScript_UseItemMessage
@itemincreasestat
@statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd
@setgraphicalstatchangevalues
@playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
@printfromtable gStatUpStringIds
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemSetMist::
@call BattleScript_UseItemMessage
@setmist
@playmoveanimation BS_ATTACKER, MOVE_MIST
@waitanimation
@printfromtable gMistUsedStringIds
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemSetFocusEnergy::
@call BattleScript_UseItemMessage
@jumpifstatus2 BS_ATTACKER, STATUS2_FOCUS_ENERGY, BattleScript_ButItFailed
@setfocusenergy
@playmoveanimation BS_ATTACKER, MOVE_FOCUS_ENERGY
@waitanimation
@copybyte sBATTLER, gBattlerAttacker
@printstring STRINGID_PKMNUSEDXTOGETPUMPED
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_RunByUsingItem::
playse SE_FLEE
setbyte gBattleOutcome, B_OUTCOME_RAN
finishturn
BattleScript_BallThrow::
jumpifbattletype BATTLE_TYPE_OLD_MAN_TUTORIAL, BattleScript_OldManThrowBall
jumpifbattletype BATTLE_TYPE_POKEDUDE, BattleScript_PokedudeThrowBall
printstring STRINGID_PLAYERUSEDITEM
handleballthrow
BattleScript_ItemRestorePP::
@call BattleScript_UseItemMessage
@itemrestorepp
@printstring STRINGID_ITEMRESTOREDSPECIESPP
@waitmessage B_WAIT_TIME_LONG
moveendcase 15
end
BattleScript_ItemIncreaseAllStats::
@call BattleScript_UseItemMessage
@call BattleScript_AllStatsUp
moveendcase 15
end
gBattlescriptsForSafariActions::
.4byte BattleScript_WatchesCarefully
.4byte BattleScript_ThrowRock
@@ -65,7 +187,7 @@ BattleScript_PokedudeThrowBall::
printstring STRINGID_POKEDUDEUSED
handleballthrow
BattleScript_ThrowSafariBall::
BattleScript_SafariBallThrow::
printstring STRINGID_PLAYERUSEDITEM
updatestatusicon BS_ATTACKER
handleballthrow

View File

@@ -71,6 +71,9 @@ ViridianCity_Mart_Items::
.2byte ITEM_PARALYZE_HEAL
.2byte ITEM_RARE_CANDY
.2byte ITEM_MASTER_BALL
.2byte ITEM_CHERI_BERRY
.2byte ITEM_TM02
.2byte ITEM_X_ATTACK
.2byte ITEM_NONE
release
end

View File

@@ -168,7 +168,8 @@ struct DisableStruct
/*0x18*/ u8 unk18_a_2 : 2;
/*0x18*/ u8 mimickedMoves : 4;
/*0x19*/ u8 rechargeTimer;
/*0x1A*/ u8 unk1A[2];
/*0x1A*/ u8 unk1A[1];
u8 wrapTurns;
};
extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT];
@@ -685,6 +686,7 @@ extern u8 gMultiHitCounter;
extern struct BattleScripting gBattleScripting;
extern u8 gBattlerFainted;
extern u32 gStatuses3[MAX_BATTLERS_COUNT];
extern u32 gStatuses4[MAX_BATTLERS_COUNT];
extern u8 gSentPokesToOpponent[2];
extern const u8 *gBattlescriptCurrInstr;
extern const u8 *gSelectionBattleScripts[MAX_BATTLERS_COUNT];
@@ -723,4 +725,25 @@ extern u8 gBattleTerrain;
extern struct MultiBattlePokemonTx gMultiPartnerParty[3];
extern u16 gRandomTurnNumber;
static inline u32 GetBattlerPosition(u32 battler)
{
return gBattlerPositions[battler];
}
static inline u32 GetBattlerSide(u32 battler)
{
return GetBattlerPosition(battler) & BIT_SIDE;
}
static inline struct Pokemon *GetSideParty(u32 side)
{
return (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
}
static inline struct Pokemon *GetBattlerParty(u32 battler)
{
return GetSideParty(GetBattlerSide(battler));
}
#endif // GUARD_BATTLE_H

View File

@@ -244,8 +244,8 @@ bool8 TranslateAnimVerticalArc(struct Sprite *sprite);
void SetSpritePrimaryCoordsFromSecondaryCoords(struct Sprite *sprite);
void InitSpritePosToAnimTarget(struct Sprite *sprite, bool8 respectMonPicOffsets);
void InitSpritePosToAnimAttacker(struct Sprite *sprite, bool8 respectMonPicOffsets);
u8 GetBattlerSide(u8 battlerId);
u8 GetBattlerPosition(u8 battlerId);
// u8 GetBattlerSide(u8 battlerId);
// u8 GetBattlerPosition(u8 battlerId);
u8 GetBattlerAtPosition(u8 position);
bool8 IsBattlerSpritePresent(u8 battlerId);
bool8 IsDoubleBattle(void);

View File

@@ -18,6 +18,7 @@ void BattleCreateYesNoCursorAt(void);
void BufferMoveToLearnIntoBattleTextBuff2(void);
void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 battlerId);
u8 GetCatchingBattler(void);
extern void (* const gBattleScriptingCommandsTable[])(void);

View File

@@ -234,6 +234,7 @@ extern const u8 *const gBattleScriptsForMoveEffects[];
extern const u8 *const gBattlescriptsForBallThrow[];
extern const u8 *const gBattlescriptsForRunningByItem[];
extern const u8 *const gBattlescriptsForUsingItem[];
extern const u8 *const gBattleScriptsForAIUsingItems[];
extern const u8 *const gBattlescriptsForSafariActions[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@@ -93,5 +93,7 @@ void ClearFuryCutterDestinyBondGrudge(u8 battlerId);
void HandleAction_RunBattleScript(void);
u8 GetMoveTarget(u16 move, u8 setTarget);
u8 IsMonDisobedient(void);
u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating);
bool32 IsBattlerAlive(u32 battler);
#endif // GUARD_BATTLE_UTIL_H

View File

@@ -25,14 +25,14 @@
// Use this switch to choose a handler for pretty printing.
// NOTE: mini_printf supports a custom pretty printing formatter to display preproc encoded strings. (%S)
// some libc distributions (especially dkp arm-libc) will fail to link pretty printing.
#define PRETTY_PRINT_HANDLER (PRETTY_PRINT_OFF)
#define PRETTY_PRINT_HANDLER (PRETTY_PRINT_MINI_PRINTF)
// Use this switch to choose a handler for printf output.
// NOTE: These will only work on the respective emulators and should not be used in a productive environment.
// Some emulators or real hardware might (and is allowed to) crash if they are used.
// AGB_PRINT is supported on respective debug units.
#define LOG_HANDLER (LOG_HANDLER_AGB_PRINT)
#define LOG_HANDLER (LOG_HANDLER_MGBA_PRINT)
#endif // NDEBUG
// Define the game version for use elsewhere

View File

@@ -114,7 +114,7 @@
#define B_SKETCH_BANS GEN_LATEST // In Gen9+, Sketch is unable to copy more moves than in previous generations.
// Ability settings
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.
#define B_EXPANDED_ABILITY_NAMES FALSE // If TRUE, ability names are increased from 12 characters to 16 characters.
#define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability.
#define B_GALE_WINGS GEN_LATEST // In Gen7+ requires full HP to trigger.
#define B_STANCE_CHANGE_FAIL GEN_LATEST // In Gen7+, Stance Change fails if the Pokémon is unable to use a move because of confusion, paralysis, etc. In Gen6, it doesn't.

View File

@@ -97,8 +97,9 @@
#define STATUS1_TOXIC_POISON (1 << 7)
#define STATUS1_TOXIC_COUNTER (1 << 8 | 1 << 9 | 1 << 10 | 1 << 11)
#define STATUS1_TOXIC_TURN(num) ((num) << 8)
#define STATUS1_FROSTBITE (1 << 12)
#define STATUS1_PSN_ANY (STATUS1_POISON | STATUS1_TOXIC_POISON)
#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON)
#define STATUS1_ANY (STATUS1_SLEEP | STATUS1_POISON | STATUS1_BURN | STATUS1_FREEZE | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON | STATUS1_FROSTBITE)
// Volatile status ailments
// These are removed after exiting the battle or switching out
@@ -113,8 +114,8 @@
#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash
#define STATUS2_LOCK_CONFUSE_TURN(num)((num) << 10)
#define STATUS2_MULTIPLETURNS (1 << 12)
#define STATUS2_WRAPPED (1 << 13 | 1 << 14 | 1 << 15)
#define STATUS2_WRAPPED_TURN(num) ((num) << 13)
#define STATUS2_WRAPPED (1 << 13)
#define STATUS2_POWDER (1 << 14)
#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler
#define STATUS2_INFATUATED_WITH(battler) (gBitTable[battler] << 16)
#define STATUS2_FOCUS_ENERGY (1 << 20)
@@ -146,12 +147,31 @@
#define STATUS3_IMPRISONED_OTHERS (1 << 13)
#define STATUS3_GRUDGE (1 << 14)
#define STATUS3_CANT_SCORE_A_CRIT (1 << 15)
#define STATUS3_MUDSPORT (1 << 16)
#define STATUS3_WATERSPORT (1 << 17)
#define STATUS3_GASTRO_ACID (1 << 16)
#define STATUS3_EMBARGO (1 << 17)
#define STATUS3_UNDERWATER (1 << 18)
#define STATUS3_INTIMIDATE_POKES (1 << 19)
#define STATUS3_TRACE (1 << 20)
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
#define STATUS3_SMACKED_DOWN (1 << 21)
#define STATUS3_ME_FIRST (1 << 22)
#define STATUS3_TELEKINESIS (1 << 23)
#define STATUS3_PHANTOM_FORCE (1 << 24)
#define STATUS3_MIRACLE_EYED (1 << 25)
#define STATUS3_MAGNET_RISE (1 << 26)
#define STATUS3_HEAL_BLOCK (1 << 27)
#define STATUS3_AQUA_RING (1 << 28)
#define STATUS3_LASER_FOCUS (1 << 29)
#define STATUS3_POWER_TRICK (1 << 30)
#define STATUS3_SKY_DROPPED (1 << 31) // Target of Sky Drop
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE)
#define STATUS4_ELECTRIFIED (1 << 0)
#define STATUS4_MUD_SPORT (1 << 1) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_WATER_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
#define STATUS4_INFINITE_CONFUSION (1 << 3) // Used for Berserk Gene
#define STATUS4_SALT_CURE (1 << 4)
#define STATUS4_SYRUP_BOMB (1 << 5)
#define STATUS4_GLAIVE_RUSH (1 << 6)
// Not really sure what a "hitmarker" is.
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.

View File

@@ -1,6 +1,7 @@
#ifndef GUARD_CONSTANTS_GLOBAL_H
#define GUARD_CONSTANTS_GLOBAL_H
#include "config/battle.h"
#include "config/pokemon.h"
// Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen.
// In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen.

View File

@@ -69,7 +69,97 @@
#define HOLD_EFFECT_THICK_CLUB 65
#define HOLD_EFFECT_STICK 66
// Gen4 hold effects.
#define HOLD_EFFECT_CHOICE_SCARF 67
#define HOLD_EFFECT_CHOICE_SPECS 68
#define HOLD_EFFECT_DAMP_ROCK 69
#define HOLD_EFFECT_GRIP_CLAW 70
#define HOLD_EFFECT_HEAT_ROCK 71
#define HOLD_EFFECT_ICY_ROCK 72
#define HOLD_EFFECT_LIGHT_CLAY 73
#define HOLD_EFFECT_SMOOTH_ROCK 74
#define HOLD_EFFECT_POWER_HERB 75
#define HOLD_EFFECT_BIG_ROOT 76
#define HOLD_EFFECT_EXPERT_BELT 77
#define HOLD_EFFECT_LIFE_ORB 78
#define HOLD_EFFECT_METRONOME 79
#define HOLD_EFFECT_MUSCLE_BAND 80
#define HOLD_EFFECT_WIDE_LENS 81
#define HOLD_EFFECT_WISE_GLASSES 82
#define HOLD_EFFECT_ZOOM_LENS 83
#define HOLD_EFFECT_LAGGING_TAIL 84
#define HOLD_EFFECT_FOCUS_SASH 85
#define HOLD_EFFECT_FLAME_ORB 86
#define HOLD_EFFECT_TOXIC_ORB 87
#define HOLD_EFFECT_STICKY_BARB 88
#define HOLD_EFFECT_IRON_BALL 89
#define HOLD_EFFECT_BLACK_SLUDGE 90
#define HOLD_EFFECT_DESTINY_KNOT 91
#define HOLD_EFFECT_SHED_SHELL 92
#define HOLD_EFFECT_QUICK_POWDER 93
#define HOLD_EFFECT_ADAMANT_ORB 94
#define HOLD_EFFECT_LUSTROUS_ORB 95
#define HOLD_EFFECT_GRISEOUS_ORB 96
#define HOLD_EFFECT_ENIGMA_BERRY 97
#define HOLD_EFFECT_RESIST_BERRY 98
#define HOLD_EFFECT_POWER_ITEM 99
#define HOLD_EFFECT_RESTORE_PCT_HP 100
#define HOLD_EFFECT_MICLE_BERRY 101
#define HOLD_EFFECT_CUSTAP_BERRY 102
#define HOLD_EFFECT_JABOCA_BERRY 103
#define HOLD_EFFECT_ROWAP_BERRY 104
#define HOLD_EFFECT_KEE_BERRY 105
#define HOLD_EFFECT_MARANGA_BERRY 106
#define HOLD_EFFECT_PLATE 107
// Gen5 hold effects
#define HOLD_EFFECT_FLOAT_STONE 117
#define HOLD_EFFECT_EVIOLITE 118
#define HOLD_EFFECT_ASSAULT_VEST 119
#define HOLD_EFFECT_DRIVE 120
#define HOLD_EFFECT_GEMS 121
#define HOLD_EFFECT_ROCKY_HELMET 122
#define HOLD_EFFECT_AIR_BALLOON 123
#define HOLD_EFFECT_RED_CARD 124
#define HOLD_EFFECT_RING_TARGET 125
#define HOLD_EFFECT_BINDING_BAND 126
#define HOLD_EFFECT_EJECT_BUTTON 127
#define HOLD_EFFECT_ABSORB_BULB 128
#define HOLD_EFFECT_CELL_BATTERY 129
// Gen6 hold effects
#define HOLD_EFFECT_FAIRY_POWER 139
#define HOLD_EFFECT_MEGA_STONE 140
#define HOLD_EFFECT_SAFETY_GOGGLES 141
#define HOLD_EFFECT_LUMINOUS_MOSS 142
#define HOLD_EFFECT_SNOWBALL 143
#define HOLD_EFFECT_WEAKNESS_POLICY 144
#define HOLD_EFFECT_PRIMAL_ORB 145
// Gen7 hold effects
#define HOLD_EFFECT_PROTECTIVE_PADS 154
#define HOLD_EFFECT_TERRAIN_EXTENDER 155
#define HOLD_EFFECT_SEEDS 156
#define HOLD_EFFECT_ADRENALINE_ORB 157
#define HOLD_EFFECT_MEMORY 158
#define HOLD_EFFECT_Z_CRYSTAL 159
// Gen8 hold effects
#define HOLD_EFFECT_UTILITY_UMBRELLA 169
#define HOLD_EFFECT_EJECT_PACK 170
#define HOLD_EFFECT_ROOM_SERVICE 171
#define HOLD_EFFECT_BLUNDER_POLICY 172
#define HOLD_EFFECT_HEAVY_DUTY_BOOTS 173
#define HOLD_EFFECT_THROAT_SPRAY 174
// Gen9 hold effects
#define HOLD_EFFECT_ABILITY_SHIELD 175
#define HOLD_EFFECT_CLEAR_AMULET 176
#define HOLD_EFFECT_MIRROR_HERB 177 // Not implemented.
#define HOLD_EFFECT_PUNCHING_GLOVE 178
#define HOLD_EFFECT_COVERT_CLOAK 179
#define HOLD_EFFECT_LOADED_DICE 180
#define HOLD_EFFECT_BOOSTER_ENERGY 181 // Not implemented.
#define HOLD_EFFECT_MASK 183
#endif // GUARD_HOLD_EFFECTS_H

View File

@@ -49,13 +49,16 @@
#define ITEM5_FRIENDSHIP_ALL (ITEM5_FRIENDSHIP_LOW | ITEM5_FRIENDSHIP_MID | ITEM5_FRIENDSHIP_HIGH)
#define ITEM10_IS_VITAMIN 0x1
// fields 6 and onwards are item-specific arguments
#define ITEM_EFFECT_ARG_START 6
// Special HP recovery amounts for ITEM4_HEAL_HP
#define ITEM6_HEAL_HP_FULL ((u8) -1)
#define ITEM6_HEAL_HP_HALF ((u8) -2)
#define ITEM6_HEAL_HP_LVL_UP ((u8) -3)
#define ITEM6_HEAL_HP_FULL ((u8) -1)
#define ITEM6_HEAL_HP_HALF ((u8) -2)
#define ITEM6_HEAL_HP_LVL_UP ((u8) -3)
#define ITEM6_HEAL_HP_QUARTER ((u8) -4)
// Special PP recovery amounts for ITEM4_HEAL_PP
#define ITEM6_HEAL_PP_FULL 0x7F

View File

@@ -458,7 +458,25 @@
#define GOOD_ROD 1
#define SUPER_ROD 2
// Check if the item is one that can be used on a Pokemon.
#define IS_POKEMON_ITEM(item) ((item) >= ITEM_POTION && (item) <= MAX_BERRY_INDEX)
// Item parameters for EXP Candies
#define EXP_100 1
#define EXP_800 2
#define EXP_3000 3
#define EXP_10000 4
#define EXP_30000 5
// Item battle script IDs (need to be non-zero)
#define EFFECT_ITEM_RESTORE_HP 1
#define EFFECT_ITEM_CURE_STATUS 2
#define EFFECT_ITEM_HEAL_AND_CURE_STATUS 3
#define EFFECT_ITEM_INCREASE_STAT 4
#define EFFECT_ITEM_SET_MIST 5
#define EFFECT_ITEM_SET_FOCUS_ENERGY 6
#define EFFECT_ITEM_ESCAPE 7
#define EFFECT_ITEM_THROW_BALL 8
#define EFFECT_ITEM_REVIVE 9
#define EFFECT_ITEM_RESTORE_PP 10
#define EFFECT_ITEM_INCREASE_ALL_STATS 11
#define EFFECT_ITEM_POKEFLUTE 12
#endif // GUARD_CONSTANTS_ITEMS_H

View File

@@ -131,6 +131,19 @@ extern u8 gStringVar4[];
#define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT)
#define NUM_ADDITIONAL_PHRASE_BYTES ROUND_BITS_TO_BYTES(NUM_ADDITIONAL_PHRASES)
// Calls m0/m1/.../m8 depending on how many arguments are passed.
#define VARARG_8(m, ...) CAT(m, NARG_8(__VA_ARGS__))(__VA_ARGS__)
// This returns the number of arguments passed to it (up to 8).
#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a ## b
#define STR(a) STR_(a)
#define STR_(a) #a
// Converts a string to a compound literal, essentially making it a pointer to const u8
#define COMPOUND_STRING(str) (const u8[]) _(str)

View File

@@ -3,24 +3,26 @@
#include "global.h"
typedef void (*ItemUseFunc)(u8);
struct Item
{
u16 itemId;
u8 name[ITEM_NAME_LENGTH];
u16 price;
u8 secondaryId; // only used for fishing rods
ItemUseFunc fieldUseFunc;
const u8 *description;
u8 name[ITEM_NAME_LENGTH];
u8 holdEffect;
u8 holdEffectParam;
const u8 *description;
u8 importance;
u8 registrability;
u8 pocket;
u8 type; // unused for balls
ItemUseFunc fieldUseFunc;
u8 battleUsage;
ItemUseFunc battleUseFunc;
u8 secondaryId; // only used for fishing rods
// u8 registrability;
// u16 itemId;
};
struct BagPocket
@@ -55,7 +57,6 @@ bool8 CheckPCHasItem(u16 itemId, u16 count);
bool8 AddPCItem(u16 itemId, u16 count);
void SwapRegisteredBike(void);
const u8 *ItemId_GetName(u16 itemId);
u16 ItemId_GetId(u16 itemId);
u16 ItemId_GetPrice(u16 itemId);
u8 ItemId_GetHoldEffect(u16 itemId);
u8 ItemId_GetHoldEffectParam(u16 itemId);

View File

@@ -42,4 +42,12 @@ void Task_UseDigEscapeRopeOnField(u8 taskId);
u8 CanUseEscapeRopeOnCurrMap(void);
u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId);
enum {
BALL_THROW_UNABLE_TWO_MONS,
BALL_THROW_UNABLE_NO_ROOM,
BALL_THROW_UNABLE_SEMI_INVULNERABLE,
BALL_THROW_ABLE,
BALL_THROW_UNABLE_DISABLED_FLAG,
};
#endif //GUARD_ITEM_USE_H

View File

@@ -51,6 +51,7 @@ bool8 FieldCallback_PrepareFadeInFromMenu(void);
void CB2_ReturnToPartyMenuFromFlyMap(void);
void SetUsedFlyQuestLogEvent(const u8 *healLocCtrlData);
void CB2_ShowPartyMenuForItemUse(void);
void ItemUseCB_BattleScript(u8 taskId, TaskFunc task);
void ItemUseCB_Medicine(u8 taskId, TaskFunc func);
void ItemUseCB_MedicineStep(u8 taskId, TaskFunc func);
void ItemUseCB_TryRestorePP(u8 taskId, TaskFunc func);
@@ -84,4 +85,6 @@ void ShowPartyMenuToShowcaseMultiBattleParty(void);
void ChooseMonForDaycare(void);
void ChoosePartyMonByMenuType(u8 menuType);
const u8* GetItemEffect(u16 item);
#endif // GUARD_PARTY_MENU_H

View File

@@ -4,6 +4,7 @@
#include "global.h"
#include "sprite.h"
#include "constants/pokemon.h"
#include "constants/items.h"
#define FORM_SPECIES_END (0xffff)
@@ -370,7 +371,7 @@ extern struct Pokemon gPlayerParty[PARTY_SIZE];
extern u8 gEnemyPartyCount;
extern struct Pokemon gEnemyParty[PARTY_SIZE];
extern const struct SpeciesInfo gSpeciesInfo[];
extern const u8 *const gItemEffectTable[];
extern const u8 *const gItemEffectTable[ITEMS_COUNT];
extern const u8 gStatStageRatios[][2];
extern struct SpriteTemplate gMultiuseSpriteTemplate;
extern struct PokemonStorage* gPokemonStoragePtr;
@@ -453,7 +454,7 @@ bool8 PokemonItemUseNoEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mo
u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit);
const u8 *Battle_PrintStatBoosterEffectMessage(u16 itemId);
u8 GetNature(struct Pokemon *mon);
u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem);
u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem, struct Pokemon *tradePartner);
u16 NationalPokedexNumToSpecies(u16 nationalNum);
u16 SpeciesToNationalPokedexNum(u16 species);
u16 HoennToNationalOrder(u16 hoennNum);

View File

@@ -136,6 +136,8 @@ static void Cmd_end(void);
static void Cmd_if_level_compare(void);
static void Cmd_if_target_taunted(void);
static void Cmd_if_target_not_taunted(void);
static void Cmd_if_status4(void);
static void Cmd_if_not_status4(void);
static void RecordLastUsedMoveByTarget(void);
static void BattleAI_DoAIProcessing(void);
@@ -240,6 +242,8 @@ static const BattleAICmdFunc sBattleAICmdTable[] =
Cmd_if_level_compare, // 0x5B
Cmd_if_target_taunted, // 0x5C
Cmd_if_target_not_taunted, // 0x5D
Cmd_if_status4, // 0x5E
Cmd_if_not_status4, // 0x5F
};
static const u16 sDiscouragedPowerfulMoveEffects[] =
@@ -1946,6 +1950,42 @@ static void Cmd_if_target_not_taunted(void)
sAIScriptPtr += 5;
}
static void Cmd_if_status4(void)
{
u16 battlerId;
u32 status;
if (sAIScriptPtr[1] == AI_USER)
battlerId = gBattlerAttacker;
else
battlerId = gBattlerTarget;
status = T1_READ_32(sAIScriptPtr + 2);
if (gStatuses4[battlerId] & status)
sAIScriptPtr = T1_READ_PTR(sAIScriptPtr + 6);
else
sAIScriptPtr += 10;
}
static void Cmd_if_not_status4(void)
{
u16 battlerId;
u32 status;
if (sAIScriptPtr[1] == AI_USER)
battlerId = gBattlerAttacker;
else
battlerId = gBattlerTarget;
status = T1_READ_32(sAIScriptPtr + 2);
if (!(gStatuses4[battlerId] & status))
sAIScriptPtr = T1_READ_PTR(sAIScriptPtr + 6);
else
sAIScriptPtr += 10;
}
static void AIStackPushVar(const u8 *var)
{
gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = var;

View File

@@ -580,12 +580,12 @@ static bool8 ShouldUseItem(void)
if (i && validMons > (gBattleResources->battleHistory->itemsNo - i) + 1)
continue;
item = gBattleResources->battleHistory->trainerItems[i];
if (item == ITEM_NONE || gItemEffectTable[item - ITEM_POTION] == NULL)
if (item == ITEM_NONE || gItemEffectTable[item] == NULL)
continue;
if (item == ITEM_ENIGMA_BERRY)
itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffects = gItemEffectTable[item - ITEM_POTION];
itemEffects = gItemEffectTable[item];
*(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects);
switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2))
{

View File

@@ -818,15 +818,15 @@ void InitSpritePosToAnimAttacker(struct Sprite *sprite, bool8 respectMonPicOffse
sprite->y += gBattleAnimArgs[1];
}
u8 GetBattlerSide(u8 battlerId)
{
return GET_BATTLER_SIDE2(battlerId);
}
// u8 GetBattlerSide(u8 battlerId)
// {
// return GET_BATTLER_SIDE2(battlerId);
// }
u8 GetBattlerPosition(u8 battlerId)
{
return GET_BATTLER_POSITION(battlerId);
}
// u8 GetBattlerPosition(u8 battlerId)
// {
// return GET_BATTLER_POSITION(battlerId);
// }
u8 GetBattlerAtPosition(u8 position)
{

View File

@@ -188,6 +188,7 @@ EWRAM_DATA u8 gUnusedFirstBattleVar2 = 0;
EWRAM_DATA u16 gSideStatuses[2] = {0};
EWRAM_DATA struct SideTimer gSideTimers[2] = {0};
EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u32 gStatuses4[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA u16 gPauseCounterBattle = 0;
EWRAM_DATA u16 gPaydayMoney = 0;
@@ -2229,6 +2230,7 @@ static void BattleStartClearSetData(void)
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
gStatuses3[i] = 0;
gStatuses4[i] = 0;
dataPtr = (u8 *)&gDisableStructs[i];
for (j = 0; j < sizeof(struct DisableStruct); j++)
@@ -2359,7 +2361,8 @@ void SwitchInClearSetData(void)
if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
{
gBattleMons[gActiveBattler].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED);
gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_MUDSPORT | STATUS3_WATERSPORT);
gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED);
gStatuses4[gActiveBattler] &= (STATUS4_MUD_SPORT | STATUS4_WATER_SPORT);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(gActiveBattler) != GetBattlerSide(i)
@@ -2375,6 +2378,7 @@ void SwitchInClearSetData(void)
{
gBattleMons[gActiveBattler].status2 = 0;
gStatuses3[gActiveBattler] = 0;
gStatuses4[gActiveBattler] = 0;
}
for (i = 0; i < gBattlersCount; i++)
@@ -2449,6 +2453,7 @@ void FaintClearSetData(void)
gBattleMons[gActiveBattler].status2 = 0;
gStatuses3[gActiveBattler] = 0;
gStatuses4[gActiveBattler] = 0;
for (i = 0; i < gBattlersCount; i++)
{
@@ -3198,7 +3203,7 @@ static void HandleTurnActionSelectionState(void)
}
else
{
BtlController_EmitChooseItem(0, gBattleStruct->battlerPartyOrders[gActiveBattler]);
BtlController_EmitChooseItem(BUFFER_A, gBattleStruct->battlerPartyOrders[gActiveBattler]);
MarkBattlerForControllerExec(gActiveBattler);
}
break;
@@ -3902,7 +3907,7 @@ static void TryEvolvePokemon(void)
levelUpBits &= ~(gBitTable[i]);
gLeveledUpInBattle = levelUpBits;
species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_NORMAL, levelUpBits);
species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_NORMAL, levelUpBits, NULL);
if (species != SPECIES_NONE)
{
gBattleMainFunc = WaitForEvoSceneToFinish;
@@ -4163,22 +4168,26 @@ static void HandleAction_UseItem(void)
gBattle_BG0_Y = 0;
ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
gLastUsedItem = gBattleBufferB[gBattlerAttacker][1] | (gBattleBufferB[gBattlerAttacker][2] << 8);
if (gLastUsedItem <= ITEM_PREMIER_BALL) // is ball
{
gBattlescriptCurrInstr = gBattlescriptsForBallThrow[gLastUsedItem];
}
else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
{
gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0];
}
else if (gLastUsedItem == ITEM_POKE_FLUTE)
{
gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[1];
}
else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
{
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[0];
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) {
// change to index minus 1
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[ItemId_GetBattleUsage(gLastUsedItem)];
}
// if (gLastUsedItem <= ITEM_PREMIER_BALL) // is ball
// {
// gBattlescriptCurrInstr = gBattlescriptsForBallThrow[gLastUsedItem];
// }
// else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
// {
// gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0];
// }
// else if (gLastUsedItem == ITEM_POKE_FLUTE)
// {
// gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[1];
// }
// else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
// {
// gBattlescriptCurrInstr = gBattlescriptsForUsingItem[0];
// }
else
{
gBattleScripting.battler = gBattlerAttacker;
@@ -4230,7 +4239,7 @@ static void HandleAction_UseItem(void)
break;
}
gBattlescriptCurrInstr = gBattlescriptsForUsingItem[*(gBattleStruct->AI_itemType + gBattlerAttacker / 2)];
gBattlescriptCurrInstr = gBattleScriptsForAIUsingItems[*(gBattleStruct->AI_itemType + gBattlerAttacker / 2) - 1];
}
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
}
@@ -4384,7 +4393,7 @@ static void HandleAction_SafariZoneBallThrow(void)
gBattle_BG0_Y = 0;
--gNumSafariBalls;
gLastUsedItem = ITEM_SAFARI_BALL;
gBattlescriptCurrInstr = gBattlescriptsForBallThrow[ITEM_SAFARI_BALL];
gBattlescriptCurrInstr = BattleScript_SafariBallThrow;
gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
}

View File

@@ -37,6 +37,38 @@
#include "constants/pokemon.h"
#include "constants/maps.h"
// Helper for accessing command arguments and advancing gBattlescriptCurrInstr.
//
// For example accuracycheck is defined as:
//
// .macro accuracycheck failInstr:req, move:req
// .byte 0x1
// .4byte \failInstr
// .2byte \move
// .endm
//
// Which corresponds to:
//
// CMD_ARGS(const u8 *failInstr, u16 move);
//
// The arguments can be accessed as cmd->failInstr and cmd->move.
// gBattlescriptCurrInstr = cmd->nextInstr; advances to the next instruction.
#define CMD_ARGS(...) const struct __attribute__((packed)) { u8 opcode; MEMBERS(__VA_ARGS__) const u8 nextInstr[0]; } *const cmd UNUSED = (const void *)gBattlescriptCurrInstr
#define VARIOUS_ARGS(...) CMD_ARGS(u8 battler, u8 id, ##__VA_ARGS__)
#define NATIVE_ARGS(...) CMD_ARGS(void (*func)(void), ##__VA_ARGS__)
#define MEMBERS(...) VARARG_8(MEMBERS_, __VA_ARGS__)
#define MEMBERS_0()
#define MEMBERS_1(a) a;
#define MEMBERS_2(a, b) a; b;
#define MEMBERS_3(a, b, c) a; b; c;
#define MEMBERS_4(a, b, c, d) a; b; c; d;
#define MEMBERS_5(a, b, c, d, e) a; b; c; d; e;
#define MEMBERS_6(a, b, c, d, e, f) a; b; c; d; e; f;
#define MEMBERS_7(a, b, c, d, e, f, g) a; b; c; d; e; f; g;
#define MEMBERS_8(a, b, c, d, e, f, g, h) a; b; c; d; e; f; g; h;
extern const u8 *const gBattleScriptsForMoveEffects[];
#define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
@@ -2487,7 +2519,11 @@ void SetMoveEffect(bool8 primary, u8 certain)
}
else
{
gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED_TURN((Random() & 3) + 3); // 3-6 turns
gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED;
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_GRIP_CLAW)
gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? 7 : 5;
else
gDisableStructs[gEffectBattler].wrapTurns = B_BINDING_TURNS >= GEN_5 ? (Random() % 2) + 4 : (Random() % 4) + 2;
*(gBattleStruct->wrappedMove + gEffectBattler * 2 + 0) = gCurrentMove;
*(gBattleStruct->wrappedMove + gEffectBattler * 2 + 1) = gCurrentMove >> 8;
@@ -9319,18 +9355,18 @@ static void Cmd_settypebasedhalvers(void)
if (gBattleMoves[gCurrentMove].effect == EFFECT_MUD_SPORT)
{
if (!(gStatuses3[gBattlerAttacker] & STATUS3_MUDSPORT))
if (!(gStatuses4[gBattlerAttacker] & STATUS4_MUD_SPORT))
{
gStatuses3[gBattlerAttacker] |= STATUS3_MUDSPORT;
gStatuses4[gBattlerAttacker] |= STATUS4_MUD_SPORT;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_ELECTRIC;
worked = TRUE;
}
}
else // Water Sport
{
if (!(gStatuses3[gBattlerAttacker] & STATUS3_WATERSPORT))
if (!(gStatuses4[gBattlerAttacker] & STATUS4_WATER_SPORT))
{
gStatuses3[gBattlerAttacker] |= STATUS3_WATERSPORT;
gStatuses4[gBattlerAttacker] |= STATUS4_WATER_SPORT;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEAKEN_FIRE;
worked = TRUE;
}
@@ -9460,6 +9496,14 @@ static void Cmd_removelightscreenreflect(void)
gBattlescriptCurrInstr++;
}
u8 GetCatchingBattler(void)
{
if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)))
return GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
else
return GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
static void Cmd_handleballthrow(void)
{
u8 ballMultiplier = 0;
@@ -9884,3 +9928,177 @@ static void Cmd_finishturn(void)
gCurrentActionFuncId = B_ACTION_FINISHED;
gCurrentTurnActionNumber = gBattlersCount;
}
void BS_GetBattlerSide(void)
{
// NATIVE_ARGS(u8 battler);
// gBattleCommunication[0] = GetBattlerSide(GetBattlerForBattleScript(cmd->battler));
// gBattlescriptCurrInstr = cmd->nextInstr;
gBattlescriptCurrInstr++;
}
void BS_ItemRestoreHP(void)
{
gBattlescriptCurrInstr++;
// NATIVE_ARGS();
// u16 healAmount;
// u32 battler = MAX_BATTLERS_COUNT;
// u32 healParam = GetItemEffect(gLastUsedItem)[6];
// u32 side = GetBattlerSide(gBattlerAttacker);
// struct Pokemon *party = GetSideParty(side);
// u16 hp = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP);
// u16 maxHP = GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_MAX_HP);
// gBattleCommunication[MULTIUSE_STATE] = 0;
// // Track the number of Revives used in a battle.
// if (hp == 0 && side == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255)
// gBattleResults.numRevivesUsed++;
// // Check if the recipient is an active battler.
// if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
// battler = gBattlerAttacker;
// else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
// && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
// battler = BATTLE_PARTNER(gBattlerAttacker);
// // Get amount to heal.
// switch (healParam)
// {
// case ITEM6_HEAL_HP_FULL:
// healAmount = maxHP;
// break;
// case ITEM6_HEAL_HP_HALF:
// healAmount = maxHP / 2;
// break;
// case ITEM6_HEAL_HP_QUARTER:
// healAmount = maxHP / 4;
// break;
// default:
// healAmount = healParam;
// break;
// }
// if (hp + healAmount > maxHP)
// healAmount = maxHP - hp;
// gBattleScripting.battler = battler;
// PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
// // Heal is applied as move damage if battler is active.
// if (battler != MAX_BATTLERS_COUNT && hp != 0)
// {
// gBattleMoveDamage = -healAmount;
// gBattlescriptCurrInstr = cmd->nextInstr;
// }
// else
// {
// hp += healAmount;
// SetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_HP, &hp);
// // Revived battlers on the field need to be brought back.
// if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && battler != MAX_BATTLERS_COUNT)
// {
// gAbsentBattlerFlags &= ~gBitTable[battler];
// gBattleCommunication[MULTIUSE_STATE] = TRUE;
// }
// gBattlescriptCurrInstr = BattleScript_ItemRestoreHP_Party;
// }
}
void BS_ItemCureStatus(void)
{
gBattlescriptCurrInstr++;
// NATIVE_ARGS();
// u32 battler = gBattlerAttacker;
// u32 side = GetBattlerSide(gBattlerAttacker);
// struct Pokemon *party = GetSideParty(side);
// // Heal Status2 conditions if battler is active.
// if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
// {
// gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem);
// }
// else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
// && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
// {
// gBattleMons[gBattlerAttacker].status2 &= ~GetItemStatus2Mask(gLastUsedItem);
// battler = BATTLE_PARTNER(gBattlerAttacker);
// }
// // Heal Status1 conditions.
// HealStatusConditions(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], GetItemStatus1Mask(gLastUsedItem), battler);
// if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP)
// gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
// if (GetItemStatus2Mask(gLastUsedItem) & STATUS2_CONFUSION)
// gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION;
// gBattleScripting.battler = battler;
// PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(&party[gBattleStruct->itemPartyIndex[gBattlerAttacker]], MON_DATA_SPECIES));
// gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ItemIncreaseStat(void)
{
gBattlescriptCurrInstr++;
// NATIVE_ARGS();
// u16 statId = GetItemEffect(gLastUsedItem)[1];
// u16 stages = ItemId_GetHoldEffectParam(gLastUsedItem);
// SET_STATCHANGER(statId, stages, FALSE);
// gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ItemRestorePP(void)
{
gBattlescriptCurrInstr++;
// NATIVE_ARGS();
// const u8 *effect = GetItemEffect(gLastUsedItem);
// u32 i, pp, maxPP, moveId, loopEnd;
// u32 battler = MAX_BATTLERS_COUNT;
// struct Pokemon *mon = (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) ? &gPlayerParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]] : &gEnemyParty[gBattleStruct->itemPartyIndex[gBattlerAttacker]];
// // Check whether to apply to all moves.
// if (effect[4] & ITEM4_HEAL_PP_ONE)
// {
// i = gBattleStruct->itemMoveIndex[gBattlerAttacker];
// loopEnd = i + 1;
// }
// else
// {
// i = 0;
// loopEnd = MAX_MON_MOVES;
// }
// // Check if the recipient is an active battler.
// if (gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[gBattlerAttacker])
// battler = gBattlerAttacker;
// else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
// && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)])
// battler = BATTLE_PARTNER(gBattlerAttacker);
// // Heal PP!
// for (; i < loopEnd; i++)
// {
// pp = GetMonData(mon, MON_DATA_PP1 + i, NULL);
// moveId = GetMonData(mon, MON_DATA_MOVE1 + i, NULL);
// maxPP = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), i);
// if (pp != maxPP)
// {
// pp += effect[6];
// if (pp > maxPP)
// pp = maxPP;
// SetMonData(mon, MON_DATA_PP1 + i, &pp);
// // Update battler PP if needed.
// if (battler != MAX_BATTLERS_COUNT
// && gBattleStruct->itemPartyIndex[gBattlerAttacker] == gBattlerPartyIndexes[battler]
// && MOVE_IS_PERMANENT(battler, i))
// {
// gBattleMons[battler].pp[i] = pp;
// }
// }
// }
// gBattleScripting.battler = battler;
// PREPARE_SPECIES_BUFFER(gBattleTextBuff1, GetMonData(mon, MON_DATA_SPECIES));
// gBattlescriptCurrInstr = cmd->nextInstr;
}

View File

@@ -872,8 +872,7 @@ u8 DoBattlerEndTurnEffects(void)
case ENDTURN_WRAP: // wrap
if ((gBattleMons[gActiveBattler].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBattler].hp != 0)
{
gBattleMons[gActiveBattler].status2 -= STATUS2_WRAPPED_TURN(1);
if (gBattleMons[gActiveBattler].status2 & STATUS2_WRAPPED) // damaged by wrap
if (--gDisableStructs[gActiveBattler].wrapTurns != 0) // damaged by wrap
{
gBattleScripting.animArg1 = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 0);
gBattleScripting.animArg2 = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 1);
@@ -889,6 +888,7 @@ u8 DoBattlerEndTurnEffects(void)
}
else // broke free
{
gBattleMons[gActiveBattler].status2 &= ~STATUS2_WRAPPED;
gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
gBattleTextBuff1[1] = B_BUFF_MOVE;
gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBattler * 2 + 0);
@@ -2328,14 +2328,14 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
case ABILITYEFFECT_MUD_SPORT:
for (i = 0; i < gBattlersCount; i++)
{
if (gStatuses3[i] & STATUS3_MUDSPORT)
if (gStatuses4[i] & STATUS4_MUD_SPORT)
effect = i + 1;
}
break;
case ABILITYEFFECT_WATER_SPORT:
for (i = 0; i < gBattlersCount; i++)
{
if (gStatuses3[i] & STATUS3_WATERSPORT)
if (gStatuses4[i] & STATUS4_WATER_SPORT)
effect = i + 1;
}
break;
@@ -3250,3 +3250,59 @@ u8 IsMonDisobedient(void)
}
}
}
u32 GetBattlerAbility(u32 battler)
{
// if (gStatuses3[battler] & STATUS3_GASTRO_ACID)
// return ABILITY_NONE;
// if (IsNeutralizingGasOnField() && !IsNeutralizingGasBannedAbility(gBattleMons[battler].ability))
// return ABILITY_NONE;
// if (IsMyceliumMightOnField())
// return ABILITY_NONE;
// if (((IsMoldBreakerTypeAbility(gBattleMons[gBattlerAttacker].ability)
// && !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
// || gBattleMoves[gCurrentMove].ignoresTargetAbility)
// && sAbilitiesAffectedByMoldBreaker[gBattleMons[battler].ability]
// && gBattlerByTurnOrder[gCurrentTurnActionNumber] == gBattlerAttacker
// && gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE
// && gCurrentTurnActionNumber < gBattlersCount)
// return ABILITY_NONE;
return gBattleMons[battler].ability;
}
u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating)
{
if (checkNegating)
{
// if (gStatuses3[battler] & STATUS3_EMBARGO)
// return HOLD_EFFECT_NONE;
// if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)
// return HOLD_EFFECT_NONE;
if (GetBattlerAbility(battler) == ABILITY_KLUTZ)
return HOLD_EFFECT_NONE;
}
gPotentialItemEffectBattler = battler;
if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY)
return gEnigmaBerries[battler].holdEffect;
else
return ItemId_GetHoldEffect(gBattleMons[battler].item);
}
bool32 IsBattlerAlive(u32 battler)
{
if (gBattleMons[battler].hp == 0)
return FALSE;
else if (battler >= gBattlersCount)
return FALSE;
else if (gAbsentBattlerFlags & gBitTable[battler])
return FALSE;
else
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -335,70 +335,70 @@ static const u8 sItemEffect_SitrusBerry[7] = {
[6] = 30, // Amount of HP to recover
};
const u8 *const gItemEffectTable[] =
const u8 *const gItemEffectTable[ITEMS_COUNT] =
{
[ITEM_POTION - ITEM_POTION] = sItemEffect_Potion,
[ITEM_ANTIDOTE - ITEM_POTION] = sItemEffect_Antidote,
[ITEM_BURN_HEAL - ITEM_POTION] = sItemEffect_BurnHeal,
[ITEM_ICE_HEAL - ITEM_POTION] = sItemEffect_IceHeal,
[ITEM_AWAKENING - ITEM_POTION] = sItemEffect_Awakening,
[ITEM_PARALYZE_HEAL - ITEM_POTION] = sItemEffect_ParalyzeHeal,
[ITEM_FULL_RESTORE - ITEM_POTION] = sItemEffect_FullRestore,
[ITEM_MAX_POTION - ITEM_POTION] = sItemEffect_MaxPotion,
[ITEM_HYPER_POTION - ITEM_POTION] = sItemEffect_HyperPotion,
[ITEM_SUPER_POTION - ITEM_POTION] = sItemEffect_SuperPotion,
[ITEM_FULL_HEAL - ITEM_POTION] = sItemEffect_FullHeal,
[ITEM_REVIVE - ITEM_POTION] = sItemEffect_Revive,
[ITEM_MAX_REVIVE - ITEM_POTION] = sItemEffect_MaxRevive,
[ITEM_FRESH_WATER - ITEM_POTION] = sItemEffect_FreshWater,
[ITEM_SODA_POP - ITEM_POTION] = sItemEffect_SodaPop,
[ITEM_LEMONADE - ITEM_POTION] = sItemEffect_Lemonade,
[ITEM_MOOMOO_MILK - ITEM_POTION] = sItemEffect_MoomooMilk,
[ITEM_ENERGY_POWDER - ITEM_POTION] = sItemEffect_EnergyPowder,
[ITEM_ENERGY_ROOT - ITEM_POTION] = sItemEffect_EnergyRoot,
[ITEM_HEAL_POWDER - ITEM_POTION] = sItemEffect_HealPowder,
[ITEM_REVIVAL_HERB - ITEM_POTION] = sItemEffect_RevivalHerb,
[ITEM_ETHER - ITEM_POTION] = sItemEffect_Ether,
[ITEM_MAX_ETHER - ITEM_POTION] = sItemEffect_MaxEther,
[ITEM_ELIXIR - ITEM_POTION] = sItemEffect_Elixir,
[ITEM_MAX_ELIXIR - ITEM_POTION] = sItemEffect_MaxElixir,
[ITEM_LAVA_COOKIE - ITEM_POTION] = sItemEffect_LavaCookie,
[ITEM_BLUE_FLUTE - ITEM_POTION] = sItemEffect_BlueFlute,
[ITEM_YELLOW_FLUTE - ITEM_POTION] = sItemEffect_YellowFlute,
[ITEM_RED_FLUTE - ITEM_POTION] = sItemEffect_RedFlute,
[ITEM_BERRY_JUICE - ITEM_POTION] = sItemEffect_BerryJuice,
[ITEM_SACRED_ASH - ITEM_POTION] = sItemEffect_SacredAsh,
[ITEM_HP_UP - ITEM_POTION] = sItemEffect_HPUp,
[ITEM_PROTEIN - ITEM_POTION] = sItemEffect_Protein,
[ITEM_IRON - ITEM_POTION] = sItemEffect_Iron,
[ITEM_CARBOS - ITEM_POTION] = sItemEffect_Carbos,
[ITEM_CALCIUM - ITEM_POTION] = sItemEffect_Calcium,
[ITEM_RARE_CANDY - ITEM_POTION] = sItemEffect_RareCandy,
[ITEM_PP_UP - ITEM_POTION] = sItemEffect_PPUp,
[ITEM_ZINC - ITEM_POTION] = sItemEffect_Zinc,
[ITEM_PP_MAX - ITEM_POTION] = sItemEffect_PPMax,
[ITEM_GUARD_SPEC - ITEM_POTION] = sItemEffect_GuardSpec,
[ITEM_DIRE_HIT - ITEM_POTION] = sItemEffect_DireHit,
[ITEM_X_ATTACK - ITEM_POTION] = sItemEffect_XAttack,
[ITEM_X_DEFEND - ITEM_POTION] = sItemEffect_XDefend,
[ITEM_X_SPEED - ITEM_POTION] = sItemEffect_XSpeed,
[ITEM_X_ACCURACY - ITEM_POTION] = sItemEffect_XAccuracy,
[ITEM_X_SPECIAL - ITEM_POTION] = sItemEffect_XSpecial,
[ITEM_SUN_STONE - ITEM_POTION] = sItemEffect_SunStone,
[ITEM_MOON_STONE - ITEM_POTION] = sItemEffect_MoonStone,
[ITEM_FIRE_STONE - ITEM_POTION] = sItemEffect_FireStone,
[ITEM_THUNDER_STONE - ITEM_POTION] = sItemEffect_ThunderStone,
[ITEM_WATER_STONE - ITEM_POTION] = sItemEffect_WaterStone,
[ITEM_LEAF_STONE - ITEM_POTION] = sItemEffect_LeafStone,
[ITEM_CHERI_BERRY - ITEM_POTION] = sItemEffect_CheriBerry,
[ITEM_CHESTO_BERRY - ITEM_POTION] = sItemEffect_ChestoBerry,
[ITEM_PECHA_BERRY - ITEM_POTION] = sItemEffect_PechaBerry,
[ITEM_RAWST_BERRY - ITEM_POTION] = sItemEffect_RawstBerry,
[ITEM_ASPEAR_BERRY - ITEM_POTION] = sItemEffect_AspearBerry,
[ITEM_LEPPA_BERRY - ITEM_POTION] = sItemEffect_LeppaBerry,
[ITEM_ORAN_BERRY - ITEM_POTION] = sItemEffect_OranBerry,
[ITEM_PERSIM_BERRY - ITEM_POTION] = sItemEffect_PersimBerry,
[ITEM_LUM_BERRY - ITEM_POTION] = sItemEffect_LumBerry,
[ITEM_SITRUS_BERRY - ITEM_POTION] = sItemEffect_SitrusBerry,
[LAST_BERRY_INDEX - ITEM_POTION] = NULL,
[ITEM_POTION] = sItemEffect_Potion,
[ITEM_ANTIDOTE] = sItemEffect_Antidote,
[ITEM_BURN_HEAL] = sItemEffect_BurnHeal,
[ITEM_ICE_HEAL] = sItemEffect_IceHeal,
[ITEM_AWAKENING] = sItemEffect_Awakening,
[ITEM_PARALYZE_HEAL] = sItemEffect_ParalyzeHeal,
[ITEM_FULL_RESTORE] = sItemEffect_FullRestore,
[ITEM_MAX_POTION] = sItemEffect_MaxPotion,
[ITEM_HYPER_POTION] = sItemEffect_HyperPotion,
[ITEM_SUPER_POTION] = sItemEffect_SuperPotion,
[ITEM_FULL_HEAL] = sItemEffect_FullHeal,
[ITEM_REVIVE] = sItemEffect_Revive,
[ITEM_MAX_REVIVE] = sItemEffect_MaxRevive,
[ITEM_FRESH_WATER] = sItemEffect_FreshWater,
[ITEM_SODA_POP] = sItemEffect_SodaPop,
[ITEM_LEMONADE] = sItemEffect_Lemonade,
[ITEM_MOOMOO_MILK] = sItemEffect_MoomooMilk,
[ITEM_ENERGY_POWDER] = sItemEffect_EnergyPowder,
[ITEM_ENERGY_ROOT] = sItemEffect_EnergyRoot,
[ITEM_HEAL_POWDER] = sItemEffect_HealPowder,
[ITEM_REVIVAL_HERB] = sItemEffect_RevivalHerb,
[ITEM_ETHER] = sItemEffect_Ether,
[ITEM_MAX_ETHER] = sItemEffect_MaxEther,
[ITEM_ELIXIR] = sItemEffect_Elixir,
[ITEM_MAX_ELIXIR] = sItemEffect_MaxElixir,
[ITEM_LAVA_COOKIE] = sItemEffect_LavaCookie,
[ITEM_BLUE_FLUTE] = sItemEffect_BlueFlute,
[ITEM_YELLOW_FLUTE] = sItemEffect_YellowFlute,
[ITEM_RED_FLUTE] = sItemEffect_RedFlute,
[ITEM_BERRY_JUICE] = sItemEffect_BerryJuice,
[ITEM_SACRED_ASH] = sItemEffect_SacredAsh,
[ITEM_HP_UP] = sItemEffect_HPUp,
[ITEM_PROTEIN] = sItemEffect_Protein,
[ITEM_IRON] = sItemEffect_Iron,
[ITEM_CARBOS] = sItemEffect_Carbos,
[ITEM_CALCIUM] = sItemEffect_Calcium,
[ITEM_RARE_CANDY] = sItemEffect_RareCandy,
[ITEM_PP_UP] = sItemEffect_PPUp,
[ITEM_ZINC] = sItemEffect_Zinc,
[ITEM_PP_MAX] = sItemEffect_PPMax,
[ITEM_GUARD_SPEC] = sItemEffect_GuardSpec,
[ITEM_DIRE_HIT] = sItemEffect_DireHit,
[ITEM_X_ATTACK] = sItemEffect_XAttack,
[ITEM_X_DEFEND] = sItemEffect_XDefend,
[ITEM_X_SPEED] = sItemEffect_XSpeed,
[ITEM_X_ACCURACY] = sItemEffect_XAccuracy,
[ITEM_X_SPECIAL] = sItemEffect_XSpecial,
[ITEM_SUN_STONE] = sItemEffect_SunStone,
[ITEM_MOON_STONE] = sItemEffect_MoonStone,
[ITEM_FIRE_STONE] = sItemEffect_FireStone,
[ITEM_THUNDER_STONE] = sItemEffect_ThunderStone,
[ITEM_WATER_STONE] = sItemEffect_WaterStone,
[ITEM_LEAF_STONE] = sItemEffect_LeafStone,
[ITEM_CHERI_BERRY] = sItemEffect_CheriBerry,
[ITEM_CHESTO_BERRY] = sItemEffect_ChestoBerry,
[ITEM_PECHA_BERRY] = sItemEffect_PechaBerry,
[ITEM_RAWST_BERRY] = sItemEffect_RawstBerry,
[ITEM_ASPEAR_BERRY] = sItemEffect_AspearBerry,
[ITEM_LEPPA_BERRY] = sItemEffect_LeppaBerry,
[ITEM_ORAN_BERRY] = sItemEffect_OranBerry,
[ITEM_PERSIM_BERRY] = sItemEffect_PersimBerry,
[ITEM_LUM_BERRY] = sItemEffect_LumBerry,
[ITEM_SITRUS_BERRY] = sItemEffect_SitrusBerry,
[LAST_BERRY_INDEX] = NULL,
};

File diff suppressed because it is too large Load Diff

View File

@@ -614,12 +614,6 @@ const u8 * ItemId_GetName(u16 itemId)
return gItems[SanitizeItemId(itemId)].name;
}
// Unused
u16 ItemId_GetId(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].itemId;
}
u16 ItemId_GetPrice(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].price;
@@ -645,12 +639,6 @@ u8 ItemId_GetImportance(u16 itemId)
return gItems[SanitizeItemId(itemId)].importance;
}
// Unused
u8 ItemId_GetRegistrability(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].registrability;
}
u8 ItemId_GetPocket(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].pocket;

View File

@@ -1683,17 +1683,44 @@ static void Task_ItemMenuAction_Cancel(u8 taskId)
Task_RedrawArrowsAndReturnToBagMenuSelect(taskId);
}
void ItemUseInBattle_BagMenu(u8 taskId)
{
}
static void Task_ItemMenuAction_BattleUse(u8 taskId)
{
if (ItemId_GetBattleFunc(gSpecialVar_ItemId) != NULL)
{
HideBagWindow(10);
HideBagWindow(6);
PutWindowTilemap(0);
PutWindowTilemap(1);
CopyWindowToVram(0, COPYWIN_MAP);
ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId);
// Safety check
u16 type = ItemId_GetType(gSpecialVar_ItemId);
if (!ItemId_GetBattleUsage(gSpecialVar_ItemId))
return;
HideBagWindow(10);
HideBagWindow(6);
PutWindowTilemap(0);
PutWindowTilemap(1);
CopyWindowToVram(0, COPYWIN_MAP);
if (gSpecialVar_ItemId == ITEM_BERRY_POUCH) {
BattleUseFunc_BerryPouch(taskId);
return;
}
if (gSpecialVar_ItemId == ITEM_ENIGMA_BERRY) {
ItemUseInBattle_EnigmaBerry(taskId);
return;
}
DebugPrintfLevel(MGBA_LOG_WARN, "Task_ItemMenuAction_BattleUse");
// if (type == ITEM_TYPE_BAG_MENU)
// ItemUseInBattle_BagMenu(taskId);
// else if (type == ITEM_TYPE_PARTY_MENU)
// ItemUseInBattle_PartyMenu(taskId);
// else if (type == ITEM_USE_PARTY_MENU_MOVES)
// ItemUseInBattle_PartyMenuChooseMove(taskId);
ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId);
}
static void Task_ItemContext_FieldGive(u8 taskId)
@@ -2177,11 +2204,11 @@ void InitPokedudeBag(u8 a0)
cb2 = CB2_ReturnToTeachyTV;
location = a0;
break;
case 7:
case ITEMMENULOCATION_TTVSCR_STATUS:
cb2 = SetCB2ToReshowScreenAfterMenu2;
location = ITEMMENULOCATION_TTVSCR_STATUS;
break;
case 8:
case ITEMMENULOCATION_TTVSCR_CATCHING:
cb2 = SetCB2ToReshowScreenAfterMenu2;
location = ITEMMENULOCATION_TTVSCR_CATCHING;
break;

View File

@@ -1,6 +1,7 @@
#include "global.h"
#include "gflib.h"
#include "battle.h"
#include "battle_anim.h"
#include "berry_pouch.h"
#include "berry_powder.h"
#include "bike.h"
@@ -69,6 +70,7 @@ static void UseFameCheckerFromBag(void);
static void Task_UseFameCheckerFromField(u8 taskId);
static void Task_BattleUse_StatBooster_DelayAndPrint(u8 taskId);
static void Task_BattleUse_StatBooster_WaitButton_ReturnToBattle(u8 taskId);
static bool32 CannotUseBagBattleItem(u16 itemId);
// unknown unused data.
// It's curiously about the size of an array of values indexed by species (including padding),
@@ -799,19 +801,25 @@ static void ItemUse_SwitchToPartyMenuInBattle(u8 taskId)
}
}
// void ItemUseInBattle_PartyMenu(u8 taskId)
// {
// gItemUseCB = ItemUseCB_BattleScript;
// ItemUse_SwitchToPartyMenuInBattle(taskId);
// }
// void ItemUseInBattle_PartyMenuChooseMove(u8 taskId)
// {
// gItemUseCB = ItemUseCB_BattleChooseMove;
// ItemUse_SwitchToPartyMenuInBattle(taskId);
// }
void BattleUseFunc_Medicine(u8 taskId)
{
DebugPrintfLevel(MGBA_LOG_WARN, "BattleUseFunc_Medicine");
gItemUseCB = ItemUseCB_MedicineStep;
ItemUse_SwitchToPartyMenuInBattle(taskId);
}
// Unused. Sacred Ash cannot be used in battle
static void BattleUseFunc_SacredAsh(u8 taskId)
{
gItemUseCB = ItemUseCB_SacredAsh;
ItemUse_SwitchToPartyMenuInBattle(taskId);
}
void BattleUseFunc_Ether(u8 taskId)
{
gItemUseCB = ItemUseCB_TryRestorePP;
@@ -830,6 +838,140 @@ void BattleUseFunc_PokeDoll(u8 taskId)
PrintNotTheTimeToUseThat(taskId, 0);
}
static u32 GetBallThrowableState(void)
{
if (IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT))
&& IsBattlerAlive(GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)))
return BALL_THROW_UNABLE_TWO_MONS;
else if (IsPlayerPartyAndPokemonStorageFull() == TRUE)
return BALL_THROW_UNABLE_NO_ROOM;
else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE))
return BALL_THROW_UNABLE_SEMI_INVULNERABLE;
else if (FlagGet(B_FLAG_NO_CATCHING))
return BALL_THROW_UNABLE_DISABLED_FLAG;
return BALL_THROW_ABLE;
}
bool32 CanThrowBall(void)
{
return (GetBallThrowableState() == BALL_THROW_ABLE);
}
static const u8 sText_CantThrowPokeBall_TwoMons[] = _("Cannot throw a ball!\nThere are two Pokémon out there!\p");
static const u8 sText_CantThrowPokeBall_SemiInvulnerable[] = _("Cannot throw a ball!\nThere's no Pokémon in sight!\p");
static const u8 sText_CantThrowPokeBall_Disabled[] = _("POKé BALLS cannot be used\nright now!\p");
void ItemUseInBattle_PokeBall(u8 taskId)
{
switch (GetBallThrowableState())
{
case BALL_THROW_ABLE:
default:
RemoveBagItem(gSpecialVar_ItemId, 1);
// Task_FadeAndCloseBagMenu(taskId);
ItemMenu_StartFadeToExitCallback(taskId);
break;
case BALL_THROW_UNABLE_TWO_MONS:
PrintNotTheTimeToUseThat(taskId, 0);
// DisplayItemMessage(taskId, FONT_NORMAL, sText_CantThrowPokeBall_TwoMons, CloseItemMessage);
break;
case BALL_THROW_UNABLE_NO_ROOM:
PrintNotTheTimeToUseThat(taskId, 0);
// DisplayItemMessage(taskId, FONT_NORMAL, gText_BoxFull, CloseItemMessage);
break;
case BALL_THROW_UNABLE_SEMI_INVULNERABLE:
PrintNotTheTimeToUseThat(taskId, 0);
// DisplayItemMessage(taskId, FONT_NORMAL, sText_CantThrowPokeBall_SemiInvulnerable, CloseItemMessage);
break;
case BALL_THROW_UNABLE_DISABLED_FLAG:
PrintNotTheTimeToUseThat(taskId, 0);
// DisplayItemMessage(taskId, FONT_NORMAL, sText_CantThrowPokeBall_Disabled, CloseItemMessage);
break;
}
}
// Returns whether an item can be used in battle and sets the fail text.
static bool32 CannotUseBagBattleItem(u16 itemId)
{
u8 cannotUse = FALSE;
u16 battleUsage = ItemId_GetBattleUsage(itemId);
const u8* failStr = NULL;
// Embargo Check
if ((gPartyMenu.slotId == 0 && gStatuses3[B_POSITION_PLAYER_LEFT] & STATUS3_EMBARGO)
|| (gPartyMenu.slotId == 1 && gStatuses3[B_POSITION_PLAYER_RIGHT] & STATUS3_EMBARGO))
{
return TRUE;
}
// X-Items
if (battleUsage == EFFECT_ITEM_INCREASE_STAT
&& gBattleMons[gBattlerInMenuId].statStages[gItemEffectTable[itemId][1]] == MAX_STAT_STAGE)
{
cannotUse++;
}
// Dire Hit
if (battleUsage == EFFECT_ITEM_SET_FOCUS_ENERGY
&& (gBattleMons[gBattlerInMenuId].status2 & STATUS2_FOCUS_ENERGY))
{
cannotUse++;
}
// Guard Spec
if (battleUsage == EFFECT_ITEM_SET_MIST
&& gSideStatuses[GetBattlerSide(gBattlerInMenuId)] & SIDE_STATUS_MIST)
{
cannotUse++;
}
// Escape Items
if (battleUsage == EFFECT_ITEM_ESCAPE
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
cannotUse++;
}
// Poke Balls
if (battleUsage == EFFECT_ITEM_THROW_BALL)
{
switch (GetBallThrowableState())
{
case BALL_THROW_UNABLE_TWO_MONS:
failStr = sText_CantThrowPokeBall_TwoMons;
cannotUse++;
break;
case BALL_THROW_UNABLE_NO_ROOM:
failStr = gText_BoxFull;
cannotUse++;
break;
case BALL_THROW_UNABLE_SEMI_INVULNERABLE:
failStr = sText_CantThrowPokeBall_SemiInvulnerable;
cannotUse++;
break;
case BALL_THROW_UNABLE_DISABLED_FLAG:
failStr = sText_CantThrowPokeBall_Disabled;
cannotUse++;
break;
}
}
// Max Mushrooms
// if (battleUsage == EFFECT_ITEM_INCREASE_ALL_STATS)
// {
// u32 i;
// for (i = 1; i < NUM_STATS; i++)
// {
// if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL))
// {
// cannotUse++;
// break;
// }
// }
// }
if (failStr != NULL)
StringExpandPlaceholders(gStringVar4, failStr);
else
StringExpandPlaceholders(gStringVar4, gText_WontHaveEffect);
return cannotUse;
}
void ItemUseOutOfBattle_EnigmaBerry(u8 taskId)
{
switch (GetItemEffectType(gSpecialVar_ItemId))

View File

@@ -1885,7 +1885,7 @@ static void CreateNidoranFSprite(u8 taskId)
u8 spriteId;
LoadSpecialPokePic(MonSpritesGfxManager_GetSpritePtr(0), INTRO_SPECIES, 0, TRUE);
LoadCompressedSpritePaletteUsingHeapWithTag(GetMonSpritePalStructFromOtIdPersonality(INTRO_SPECIES, 0, 0), INTRO_SPECIES);
LoadCompressedSpritePaletteUsingHeapWithTag(GetMonSpritePalStructFromOtIdPersonality(INTRO_SPECIES, 0, SHINY_ODDS), INTRO_SPECIES);
SetMultiuseSpriteTemplateToPokemon(INTRO_SPECIES, 0);
spriteId = CreateSprite(&gMultiuseSpriteTemplate, 96, 96, 1);
gSprites[spriteId].callback = SpriteCallbackDummy;

View File

@@ -869,7 +869,7 @@ static bool8 DisplayPartyPokemonDataForMoveTutorOrEvolutionItem(u8 slot)
DisplayPartyPokemonDataToTeachMove(slot, item, 0);
break;
case 2: // Evolution stone
if (!GetMonData(currentPokemon, MON_DATA_IS_EGG) && GetEvolutionTargetSpecies(currentPokemon, EVO_MODE_ITEM_CHECK, item) != SPECIES_NONE)
if (!GetMonData(currentPokemon, MON_DATA_IS_EGG) && GetEvolutionTargetSpecies(currentPokemon, EVO_MODE_ITEM_CHECK, item, NULL) != SPECIES_NONE)
return FALSE;
DisplayPartyPokemonDescriptionData(slot, PARTYBOX_DESC_NO_USE);
break;
@@ -4330,7 +4330,7 @@ static bool8 IsHPRecoveryItem(u16 item)
if (item == ITEM_ENIGMA_BERRY)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item - ITEM_POTION];
effect = gItemEffectTable[item];
if (effect[4] & ITEM4_HEAL_HP)
return TRUE;
else
@@ -4416,6 +4416,39 @@ static bool8 IsItemFlute(u16 item)
return FALSE;
}
// Battle scripts called in HandleAction_UseItem
// void ItemUseCB_BattleScript(u8 taskId, TaskFunc task)
// {
// struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
// if (CannotUsePartyBattleItem(gSpecialVar_ItemId, mon))
// {
// gPartyMenuUseExitCallback = FALSE;
// PlaySE(SE_SELECT);
// DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
// ScheduleBgCopyTilemapToVram(2);
// gTasks[taskId].func = task;
// }
// else
// {
// gBattleStruct->itemPartyIndex[gBattlerInMenuId] = GetPartyIdFromBattleSlot(gPartyMenu.slotId);
// gPartyMenuUseExitCallback = TRUE;
// PlaySE(SE_SELECT);
// RemoveBagItem(gSpecialVar_ItemId, 1);
// ScheduleBgCopyTilemapToVram(2);
// gTasks[taskId].func = task;
// }
// }
// void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task)
// {
// PlaySE(SE_SELECT);
// DisplayPartyMenuStdMessage(PARTY_MSG_RESTORE_WHICH_MOVE);
// ShowMoveSelectWindow(gPartyMenu.slotId);
// gTasks[taskId].func = Task_HandleRestoreWhichMoveInput;
// }
static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMoveIndex)
{
if (gMain.inBattle)
@@ -4426,39 +4459,7 @@ static bool8 ExecuteTableBasedItemEffect_(u8 partyMonIndex, u16 item, u8 monMove
void ItemUseCB_Medicine(u8 taskId, TaskFunc func)
{
u16 hp;
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
u16 item = gSpecialVar_ItemId;
bool8 canHeal;
if (!NotUsingHPEVItemOnShedinja(mon, item))
{
canHeal = TRUE;
}
else
{
if (IsHPRecoveryItem(item) == TRUE)
{
hp = GetMonData(mon, MON_DATA_HP);
if (hp == GetMonData(mon, MON_DATA_MAX_HP))
canHeal = FALSE;
}
canHeal = PokemonItemUseNoEffect(mon, item, gPartyMenu.slotId, 0);
}
PlaySE(SE_SELECT);
if (canHeal)
{
gPartyMenuUseExitCallback = FALSE;
DisplayPartyMenuMessage(gText_WontHaveEffect, TRUE);
ScheduleBgCopyTilemapToVram(2);
gTasks[taskId].func = func;
}
else
{
ItemUse_SetQuestLogEvent(QL_EVENT_USED_ITEM, mon, item, 0xFFFF);
Task_DoUseItemAnim(taskId);
gItemUseCB = ItemUseCB_MedicineStep;
}
ItemUseCB_MedicineStep(taskId, func);
}
void ItemUseCB_MedicineStep(u8 taskId, TaskFunc func)
@@ -4466,13 +4467,16 @@ void ItemUseCB_MedicineStep(u8 taskId, TaskFunc func)
u16 hp = 0;
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
u16 item = gSpecialVar_ItemId;
bool8 canHeal;
bool8 cannotHeal;
bool8 canHeal, cannotUse;
if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE)
cannotHeal = TRUE;
DebugPrintfLevel(MGBA_LOG_WARN, "ItemUseCB_MedicineStep");
if (NotUsingHPEVItemOnShedinja(mon, item) == FALSE) {
DebugPrintfLevel(MGBA_LOG_WARN, "Shedinja");
cannotUse = TRUE;
}
else
{
DebugPrintfLevel(MGBA_LOG_WARN, "notShedinja");
canHeal = IsHPRecoveryItem(item);
if (canHeal == TRUE)
{
@@ -4481,10 +4485,11 @@ void ItemUseCB_MedicineStep(u8 taskId, TaskFunc func)
canHeal = FALSE;
}
cannotHeal = ExecuteTableBasedItemEffect_(gPartyMenu.slotId, item, 0);
DebugPrintfLevel(MGBA_LOG_WARN, "next: ExecuteTableBasedItemEffect");
cannotUse = ExecuteTableBasedItemEffect(mon, item, gPartyMenu.slotId, 0);
}
if (cannotHeal != FALSE)
if (cannotUse != FALSE)
{
gPartyMenuUseExitCallback = FALSE;
PlaySE(SE_SELECT);
@@ -4596,7 +4601,7 @@ void ItemUseCB_TryRestorePP(u8 taskId, TaskFunc func)
if (item == ITEM_ENIGMA_BERRY)
effect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
effect = gItemEffectTable[item - ITEM_POTION];
effect = gItemEffectTable[item];
if (!(effect[4] & ITEM4_HEAL_PP_ONE))
{
@@ -5166,7 +5171,7 @@ static void Task_TryLearningNextMove(u8 taskId)
static void PartyMenuTryEvolution(u8 taskId)
{
struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId];
u16 targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE);
u16 targetSpecies = GetEvolutionTargetSpecies(mon, EVO_MODE_NORMAL, ITEM_NONE, NULL);
if (targetSpecies != SPECIES_NONE)
{
@@ -5318,24 +5323,29 @@ static void CB2_UseEvolutionStone(void)
static bool8 MonCanEvolve(void)
{
if (!IsNationalPokedexEnabled()
&& GetEvolutionTargetSpecies(&gPlayerParty[gPartyMenu.slotId], EVO_MODE_ITEM_USE, gSpecialVar_ItemId) > KANTO_DEX_COUNT)
&& GetEvolutionTargetSpecies(&gPlayerParty[gPartyMenu.slotId], EVO_MODE_ITEM_USE, gSpecialVar_ItemId, NULL) > KANTO_DEX_COUNT)
return FALSE;
else
return TRUE;
}
const u8* GetItemEffect(u16 item)
{
if (item == ITEM_ENIGMA_BERRY)
return gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
return gItemEffectTable[item];
}
u8 GetItemEffectType(u16 item)
{
const u8 *itemEffect;
u32 statusCure;
const u8 *itemEffect = GetItemEffect(item);
if (!IS_POKEMON_ITEM(item))
return ITEM_EFFECT_NONE;
// Read the item's effect properties.
if (item == ITEM_ENIGMA_BERRY)
itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffect = gItemEffectTable[item - ITEM_POTION];
if (itemEffect == NULL)
return ITEM_EFFECT_NONE;
if ((itemEffect[0] & (ITEM0_DIRE_HIT | ITEM0_X_ATTACK)) || itemEffect[1] || itemEffect[2] || (itemEffect[3] & ITEM3_GUARD_SPEC))
return ITEM_EFFECT_X_ITEM;
else if (itemEffect[0] & ITEM0_SACRED_ASH)

File diff suppressed because it is too large Load Diff

View File

@@ -1774,7 +1774,7 @@ static bool8 DoTradeAnim_Cable(void)
case STATE_TRY_EVOLUTION: // Only if in-game trade, link trades use CB2_TryLinkTradeEvolution
TradeMons(gSpecialVar_0x8005, 0);
gCB2_AfterEvolution = CB2_InGameTrade;
evoTarget = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, ITEM_NONE);
evoTarget = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, ITEM_NONE, &gPlayerParty[gSelectedTradeMonPositions[TRADE_PARTNER]]);
if (evoTarget != SPECIES_NONE)
TradeEvolutionScene(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], evoTarget, sTradeAnim->monSpriteIds[1], gSelectedTradeMonPositions[TRADE_PLAYER]);
sTradeAnim->state++;
@@ -2274,7 +2274,7 @@ static bool8 DoTradeAnim_Wireless(void)
case STATE_TRY_EVOLUTION: // Only if in-game trade, link trades use CB2_TryLinkTradeEvolution
TradeMons(gSpecialVar_0x8005, 0);
gCB2_AfterEvolution = CB2_InGameTrade;
evoTarget = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, ITEM_NONE);
evoTarget = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, ITEM_NONE, &gPlayerParty[gSelectedTradeMonPositions[TRADE_PARTNER]]);
if (evoTarget != SPECIES_NONE)
TradeEvolutionScene(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], evoTarget, sTradeAnim->monSpriteIds[TRADE_PARTNER], gSelectedTradeMonPositions[TRADE_PLAYER]);
sTradeAnim->state++;
@@ -2318,7 +2318,7 @@ static void CB2_TryLinkTradeEvolution(void)
break;
case 4:
gCB2_AfterEvolution = CB2_SaveAndEndTrade;
evoSpecies = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, 0);
evoSpecies = GetEvolutionTargetSpecies(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], EVO_MODE_TRADE, ITEM_NONE, &gPlayerParty[gSelectedTradeMonPositions[TRADE_PARTNER]]);
if (evoSpecies != SPECIES_NONE)
TradeEvolutionScene(&gPlayerParty[gSelectedTradeMonPositions[TRADE_PLAYER]], evoSpecies, sTradeAnim->monSpriteIds[TRADE_PARTNER], gSelectedTradeMonPositions[TRADE_PLAYER]);
else