diff --git a/graphics/battle_interface/text.pal b/graphics/battle_interface/text.pal index 574999b72..17feedc7f 100755 --- a/graphics/battle_interface/text.pal +++ b/graphics/battle_interface/text.pal @@ -6,8 +6,8 @@ JASC-PAL 131 0 0 255 164 98 131 82 49 -0 0 0 -0 0 0 +172 230 172 +123 205 115 0 0 0 0 0 0 0 0 0 diff --git a/src/battle_bg.c b/src/battle_bg.c index 0ed1eec2e..1d9386518 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -370,6 +370,33 @@ static const struct WindowTemplate sStandardBattleWindowTemplates[] = .paletteNum = 0, .baseBlock = 0x00b0, }, + { // super effective + .bg = 0, + .tilemapLeft = 21, + .tilemapTop = 57, + .width = 8, + .height = 2, + .paletteNum = 5, + .baseBlock = 0x02a0, + }, + { // not very effective + .bg = 0, + .tilemapLeft = 21, + .tilemapTop = 57, + .width = 8, + .height = 2, + .paletteNum = 5, + .baseBlock = 0x02a0, + }, + { // no effect + .bg = 0, + .tilemapLeft = 21, + .tilemapTop = 57, + .width = 8, + .height = 2, + .paletteNum = 5, + .baseBlock = 0x02a0, + }, DUMMY_WIN_TEMPLATE }; diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 291988361..2b9f48c01 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -36,6 +36,8 @@ #include "constants/songs.h" #include "constants/trainers.h" #include "constants/rgb.h" +#include "constants/battle_move_effects.h" +#include "event_data.h" static void PlayerHandleGetMonData(void); static void PlayerHandleSetMonData(void); @@ -100,6 +102,7 @@ static void HandleInputChooseTarget(void); static void HandleInputChooseMove(void); static void MoveSelectionDisplayPpNumber(void); static void MoveSelectionDisplayPpString(void); +static void MoveSelectionDisplayMoveTypeDoubles(u8 targetId); static void MoveSelectionDisplayMoveType(void); static void MoveSelectionDisplayMoveNames(void); static void HandleMoveSwitching(void); @@ -185,6 +188,34 @@ static void (*const sPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(void) = }; // unknown unused data +#define X UQ_4_12 + +static const u16 sTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES] = +{ + // normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy + {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // normal + {X(2.0), X(1.0), X(0.5), X(0.5), X(1.0), X(2.0), X(0.5), X(0.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(2.0), X(0.5)}, // fight + {X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // flying + {X(1.0), X(1.0), X(1.0), X(0.5), X(0.5), X(0.5), X(1.0), X(0.5), X(0.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0)}, // poison + {X(1.0), X(1.0), X(0.0), X(2.0), X(1.0), X(2.0), X(0.5), X(1.0), X(2.0), X(1.0), X(2.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // ground + {X(1.0), X(0.5), X(2.0), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0)}, // rock + {X(1.0), X(0.5), X(0.5), X(0.5), X(1.0), X(1.0), X(1.0), X(0.5), X(0.5), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(2.0), X(1.0), X(1.0), X(2.0), X(0.5)}, // bug + {X(0.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(0.5), X(1.0)}, // ghost + {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.5), X(0.5), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(1.0), X(2.0)}, // steel + {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // mystery + {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(2.0), X(1.0), X(0.5), X(0.5), X(2.0), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(1.0)}, // fire + {X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(0.5), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0)}, // water + {X(1.0), X(1.0), X(0.5), X(0.5), X(2.0), X(2.0), X(0.5), X(1.0), X(0.5), X(1.0), X(0.5), X(2.0), X(0.5), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0)}, // grass + {X(1.0), X(1.0), X(2.0), X(1.0), X(0.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(0.5), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0)}, // electric + {X(1.0), X(2.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(0.0), X(1.0)}, // psychic + {X(1.0), X(1.0), X(2.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.5), X(0.5), X(2.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0)}, // ice + {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(0.0)}, // dragon + {X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(0.5), X(0.5)}, // dark + {X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(2.0), X(1.0)}, // fairy +}; + +#undef X + static const u8 sUnused[] = {0x48, 0x48, 0x20, 0x5a, 0x50, 0x50, 0x50, 0x58}; void BattleControllerDummy(void) @@ -437,6 +468,7 @@ static void HandleInputChooseTarget(void) i++; break; } + MoveSelectionDisplayMoveTypeDoubles(GetBattlerPosition(gMultiUsePlayerCursor)); if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] || !CanTargetBattler(gActiveBattler, gMultiUsePlayerCursor, move)) @@ -487,6 +519,7 @@ static void HandleInputChooseTarget(void) i++; break; } + MoveSelectionDisplayMoveTypeDoubles(GetBattlerPosition(gMultiUsePlayerCursor)); if (gAbsentBattlerFlags & gBitTable[gMultiUsePlayerCursor] || !CanTargetBattler(gActiveBattler, gMultiUsePlayerCursor, move)) @@ -1716,6 +1749,83 @@ static void MoveSelectionDisplayPpNumber(void) BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_PP_REMAINING); } +static void MulModifier(u16 *modifier, u16 val) +{ + *modifier = UQ_4_12_TO_INT((*modifier * val) + UQ_4_12_ROUND); +} + +u8 TypeEffectiveness(struct ChooseMoveStruct *moveInfo, u8 targetId) +{ + bool8 isInverse = (B_FLAG_INVERSE_BATTLE != 0 && FlagGet(B_FLAG_INVERSE_BATTLE)) ? TRUE : FALSE; + + if (gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].power == 0) + return 10; + else + { + u16 mod = sTypeEffectivenessTable[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].type][gBattleMons[targetId].type1]; + + if (gBattleMons[targetId].type2 != gBattleMons[targetId].type1) + { + u16 mod2 = sTypeEffectivenessTable[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].type][gBattleMons[targetId].type2]; + MulModifier(&mod, mod2); + } + + if (gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].effect == EFFECT_TWO_TYPED_MOVE) + { + u16 mod3 = sTypeEffectivenessTable[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].argument][gBattleMons[targetId].type1]; + MulModifier(&mod, mod3); + + if (gBattleMons[targetId].type2 != gBattleMons[targetId].type1) + { + u16 mod4 = sTypeEffectivenessTable[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].argument][gBattleMons[targetId].type2]; + MulModifier(&mod, mod4); + } + } + + // 10 - normal effectiveness + // 24 - super effective + // 25 - not very effective + // 26 - no effect + + if (mod == UQ_4_12(0.0)) { + if(isInverse) + return 24; + else + return 26; + } + else if (mod <= UQ_4_12(0.5)) { + if(isInverse) + return 24; + else + return 25; + } + else if (mod >= UQ_4_12(2.0)) { + if(isInverse) + return 25; + else + return 24; + } + else + return 10; + } +} + +static void MoveSelectionDisplayMoveTypeDoubles(u8 targetId) +{ + u8 *txtPtr; + struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleResources->bufferA[gActiveBattler][4]); + + txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); + txtPtr[0] = EXT_CTRL_CODE_BEGIN; + txtPtr++; + txtPtr[0] = 6; + txtPtr++; + txtPtr[0] = 1; + txtPtr++; + + StringCopy(txtPtr, gTypeNames[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].type]); + BattlePutTextOnWindow(gDisplayedStringBattle, TypeEffectiveness(moveInfo, targetId)); +} static void MoveSelectionDisplayMoveType(void) { u8 *txtPtr; @@ -1727,7 +1837,7 @@ static void MoveSelectionDisplayMoveType(void) *(txtPtr)++ = FONT_NORMAL; StringCopy(txtPtr, gTypeNames[gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].type]); - BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MOVE_TYPE); + BattlePutTextOnWindow(gDisplayedStringBattle, TypeEffectiveness(moveInfo, 1)); } void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 baseTileNum) diff --git a/src/battle_message.c b/src/battle_message.c index 7c69a2462..c68f95232 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2338,6 +2338,42 @@ static const struct BattleWindowText sTextOnWindowsInfo_Normal[] = .fgColor = 1, .shadowColor = 6, }, + { // 24 "type" super-effective + .fillValue = PIXEL_FILL(0xE), + .fontId = 7, + .x = 0, + .y = 1, + .letterSpacing = 0, + .lineSpacing = 0, + .speed = 0, + .fgColor = 6, + .bgColor = 14, + .shadowColor = 5, + }, + { // 25 "type" not very effective + .fillValue = PIXEL_FILL(0xE), + .fontId = 7, + .x = 0, + .y = 1, + .letterSpacing = 0, + .lineSpacing = 0, + .speed = 0, + .fgColor = 1, + .bgColor = 14, + .shadowColor = 3, + }, + { // 26 "type" no effect + .fillValue = PIXEL_FILL(0xE), + .fontId = 7, + .x = 0, + .y = 1, + .letterSpacing = 0, + .lineSpacing = 0, + .speed = 0, + .fgColor = 11, + .bgColor = 14, + .shadowColor = 11, + }, }; static const struct BattleWindowText sTextOnWindowsInfo_Arena[] =