sync item config, add oras dowse

This commit is contained in:
cawtds 2026-04-03 15:35:55 +02:00
parent a07dc137b2
commit 0e5008ce4b
18 changed files with 702 additions and 22 deletions

View File

@ -179,6 +179,7 @@ EventScript_TryPickUpHiddenItem::
return
EventScript_PickedUpHiddenItem::
callnative Script_ClearDowsingColor
call_if_eq VAR_0x8006, 1, EventScript_FoundSingleItem
call_if_ne VAR_0x8006, 1, EventScript_FoundMultipleItems
copyvar VAR_0x8006, VAR_0x8005
@ -189,6 +190,7 @@ EventScript_PickedUpHiddenItem::
msgbox Text_PutItemAway
hideitemdescription
special SetHiddenItemFlag
callnative Script_UpdateDowseState
releaseall
end

View File

@ -0,0 +1,19 @@
JASC-PAL
0100
16
115 197 164
0 0 0
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 255 255
255 0 255

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

View File

@ -87,6 +87,7 @@ enum FieldEffect
FLDEFF_CAVE_DUST,
FLDEFF_USE_ROCK_CLIMB,
FLDEFF_ROCK_CLIMB_DUST,
FLDEFF_ORAS_DOWSE,
FLDEFF_COUNT,
};
@ -103,6 +104,7 @@ enum FieldEffect
#define FLDEFF_PAL_TAG_HOF_MONITOR 0x1010
#define FLDEFF_PAL_TAG_CAVE_DUST 0x1012
#define FLDEFF_PAL_TAG_DUST_CLOUD 0x1013
#define FLDEFF_PAL_TAG_ORAS_DOWSE 0x1014
// tile tags, for field effects that may have many copies on screen at once
#define FLDEFF_TILE_TAG_SHADOW_SMALL 0x1400

View File

@ -166,5 +166,6 @@ u32 FldEff_SnowTracksSpot(void);
u32 FldEff_CaveDust(void);
u32 FldEff_UseRockClimb(void);
u32 FldEff_RockClimbDust(void);
u32 FldEff_ORASDowsing(void);
#endif //GUARD_FIELD_EFFECTS_H

View File

@ -1,6 +1,8 @@
#ifndef GUARD_ITEMFINDER_H
#define GUARD_ITEMFINDER_H
bool8 HiddenItemIsWithinRangeOfPlayer(const struct MapEvents *events, u8 taskId);
u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY);
void ItemUseOnFieldCB_Itemfinder(u8 taskId);
#endif //GUARD_ITEMFINDER_H

39
include/oras_dowse.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef GUARD_ORAS_DOWSE_H
#define GUARD_ORAS_DOWSE_H
// States for ORAS Dowsing
enum
{
ORASD_WIGGLE_NONE,
ORASD_WIGGLE_SLOW,
ORASD_WIGGLE_NORMAL,
ORASD_WIGGLE_FAST,
ORASD_WIGGLE_FASTER
};
#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_SLOW (ANIM_STD_FACE_EAST + 1)
#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_SLOW (ANIM_STD_FACE_EAST + 2)
#define ANIM_ORAS_DOWSE_WIGGLE_WEST_SLOW (ANIM_STD_FACE_EAST + 3)
#define ANIM_ORAS_DOWSE_WIGGLE_EAST_SLOW (ANIM_STD_FACE_EAST + 4)
#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH (ANIM_STD_FACE_EAST + 5)
#define ANIM_ORAS_DOWSE_WIGGLE_NORTH (ANIM_STD_FACE_EAST + 6)
#define ANIM_ORAS_DOWSE_WIGGLE_WEST (ANIM_STD_FACE_EAST + 7)
#define ANIM_ORAS_DOWSE_WIGGLE_EAST (ANIM_STD_FACE_EAST + 8)
#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FAST (ANIM_STD_FACE_EAST + 9)
#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_FAST (ANIM_STD_FACE_EAST + 10)
#define ANIM_ORAS_DOWSE_WIGGLE_WEST_FAST (ANIM_STD_FACE_EAST + 11)
#define ANIM_ORAS_DOWSE_WIGGLE_EAST_FAST (ANIM_STD_FACE_EAST + 12)
#define ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FASTER (ANIM_STD_FACE_EAST + 13)
#define ANIM_ORAS_DOWSE_WIGGLE_NORTH_FASTER (ANIM_STD_FACE_EAST + 14)
#define ANIM_ORAS_DOWSE_WIGGLE_WEST_FASTER (ANIM_STD_FACE_EAST + 15)
#define ANIM_ORAS_DOWSE_WIGGLE_EAST_FASTER (ANIM_STD_FACE_EAST + 16)
extern const u16 gFieldEffectPal_ORASDowsing[];
void Task_UseORASDowsingMachine(u8 taskId);
void ResumeORASDowseFieldEffect(void);
void UpdateDowseState(struct Sprite *sprite);
void UpdateDowsingAnimDirection(struct Sprite *sprite, struct ObjectEvent *playerObj);
void EndORASDowsing(void);
#endif // GUARD_ORAS_DOWSE_H

View File

@ -15,6 +15,12 @@ $(OBJEVENTGFXDIR)/misc/surf_blob.4bpp: %.4bpp: %.png
$(FLDEFFGFXDIR)/rock_climb_blob.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 4 -mheight 4
$(FLDEFFGFXDIR)/oras_dowsing_red.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 2 -mheight 4
$(FLDEFFGFXDIR)/oras_dowsing_green.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 2 -mheight 4
$(OBJEVENTGFXDIR)/misc/ss_anne.4bpp: %.4bpp: %.png
$(GFX) $< $@ -mwidth 8 -mheight 4

View File

@ -5,6 +5,7 @@
#include "event_object_movement.h"
#include "fieldmap.h"
#include "field_camera.h"
#include "oras_dowse.h"
#include "overworld.h"
#include "constants/map_types.h"
#include "constants/songs.h"
@ -332,6 +333,7 @@ void GetOnOffBike(u8 flags)
}
else
{
EndORASDowsing();
SetPlayerAvatarTransitionFlags(flags);
if (Overworld_MusicCanOverrideMapMusic(MUS_CYCLING))
{

View File

@ -19,6 +19,7 @@
#include "malloc.h"
#include "menu.h"
#include "metatile_behavior.h"
#include "oras_dowse.h"
#include "overworld.h"
#include "palette.h"
#include "party_menu.h"
@ -376,6 +377,7 @@ static const u32 (*const sFieldEffectFuncs[FLDEFF_COUNT]) (void) =
[FLDEFF_CAVE_DUST] = FldEff_CaveDust,
[FLDEFF_USE_ROCK_CLIMB] = FldEff_UseRockClimb,
[FLDEFF_ROCK_CLIMB_DUST] = FldEff_RockClimbDust,
[FLDEFF_ORAS_DOWSE] = FldEff_ORASDowsing,
};
static const struct OamData sOamData_8x8 =
@ -1564,6 +1566,8 @@ void StartEscalatorWarp(u8 metatileBehavior, u8 priority)
gTasks[taskId].tGoingUp = FALSE;
if (metatileBehavior == MB_UP_ESCALATOR)
gTasks[taskId].tGoingUp = TRUE;
EndORASDowsing();
}
static void Task_EscalatorWarpOut(u8 taskId)
@ -2046,6 +2050,7 @@ static bool32 (*const sLavaridgeGymB1FWarpEffectFuncs[])(struct Task *task, stru
void StartLavaridgeGymB1FWarp(u8 priority)
{
EndORASDowsing();
CreateTask(Task_LavaridgeGymB1FWarp, priority);
}
@ -2304,6 +2309,7 @@ void SpriteCB_AshLaunch(struct Sprite *sprite)
void StartLavaridgeGym1FWarp(u8 priority)
{
EndORASDowsing();
CreateTask(Task_LavaridgeGym1FWarp, priority);
}
@ -2442,6 +2448,7 @@ void StartEscapeRopeFieldEffect(void)
LockPlayerFieldControls();
FreezeObjectEvents();
HideFollowerForFieldEffect(); // hide follower before warping
EndORASDowsing();
CreateTask(Task_EscapeRopeWarpOut, 80);
}
@ -2770,6 +2777,7 @@ static void TeleportWarpOutFieldEffect_Init(struct Task *task)
LockPlayerFieldControls();
FreezeObjectEvents();
CameraObjectFreeze();
EndORASDowsing();
task->tStartDir = GetPlayerFacingDirection();
task->tState = TELEPORT_WARP_OUT_SPIN_GROUND;
}

View File

@ -15,6 +15,7 @@
#include "link.h"
#include "map_preview_screen.h"
#include "metatile_behavior.h"
#include "oras_dowse.h"
#include "overworld.h"
#include "palette.h"
#include "quest_log.h"
@ -690,6 +691,7 @@ static void Task_Teleport2Warp(u8 taskId)
case 0:
FreezeObjectEvents();
LockPlayerFieldControls();
EndORASDowsing();
task->data[0]++;
break;
case 1:
@ -775,6 +777,7 @@ static void Task_DoorWarp(u8 taskId)
ObjectEventSetHeldMovement(followerObject, MOVEMENT_ACTION_ENTER_POKEBALL);
}
task->tDoorTask = FieldAnimateDoorOpen(*xp, *yp - 1);
EndORASDowsing();
task->tState = DOORWARP_START_WALK_UP;
break;
case DOORWARP_START_WALK_UP:

View File

@ -12,6 +12,7 @@
#include "help_system.h"
#include "menu.h"
#include "metatile_behavior.h"
#include "oras_dowse.h"
#include "overworld.h"
#include "party_menu.h"
#include "quest_log_player.h"
@ -1306,6 +1307,7 @@ void SetPlayerInvisibility(bool8 invisible)
void StartPlayerAvatarSummonMonForFieldMoveAnim(void)
{
EndORASDowsing();
ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_FIELD_MOVE));
StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], ANIM_FIELD_MOVE);
}
@ -1325,12 +1327,14 @@ u8 GetPlayerAvatarVsSeekerGfxId(void)
void StartPlayerAvatarVsSeekerAnim(void)
{
EndORASDowsing();
ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarVsSeekerGfxId());
StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], ANIM_VS_SEEKER);
}
void SetPlayerAvatarFishing(u8 direction)
{
EndORASDowsing();
QuestLogCallUpdatePlayerSprite(QL_PLAYER_GFX_FISH);
}
@ -1342,6 +1346,7 @@ void PlayerUseAcroBikeOnBumpySlope(u8 direction)
void SetPlayerAvatarWatering(u8 direction)
{
EndORASDowsing();
ObjectEventSetGraphicsId(&gObjectEvents[gPlayerAvatar.objectEventId], GetPlayerAvatarGraphicsIdByStateId(PLAYER_AVATAR_STATE_WATERING));
StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], GetFaceDirectionAnimNum(direction));
}

View File

@ -5,7 +5,9 @@
#include "field_player_avatar.h"
#include "field_specials.h"
#include "fieldmap.h"
#include "itemfinder.h"
#include "menu.h"
#include "oras_dowse.h"
#include "script.h"
#include "sound.h"
#include "strings.h"
@ -15,12 +17,10 @@
static void Task_NoResponse_CleanUp(u8 taskId);
static void Task_ItemfinderResponseSoundsAndAnims(u8 taskId);
static void Task_ItemfinderUnderfootSoundsAndAnims(u8 taskId);
static bool8 HiddenItemIsWithinRangeOfPlayer(const struct MapEvents * events, u8 taskId);
static void SetUnderfootHiddenItem(u8 taskId, u32 hiddenItem);
static void SetNormalHiddenItem(u8 taskId);
static void FindHiddenItemsInConnectedMaps(u8 taskId);
static void RegisterHiddenItemRelativeCoordsIfCloser(u8 taskId, s16 dx, s16 dy);
static u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY);
static void Task_ItemfinderResponsePrintMessage(u8 taskId);
static void Task_ItemfinderResponseCleanUp(u8 taskId);
static void Task_ItemfinderUnderfootPrintMessage(u8 taskId);
@ -130,20 +130,33 @@ static const struct SpriteSheet sArrowAndStarSpriteSheet = {
void ItemUseOnFieldCB_Itemfinder(u8 taskId)
{
u8 i;
for (i = 0; i < 16; i++)
gTasks[taskId].data[i] = 0;
if (HiddenItemIsWithinRangeOfPlayer(gMapHeader.events, taskId) == TRUE)
if (I_ORAS_DOWSING_FLAG != 0)
{
LoadArrowAndStarTiles();
if (gTasks[taskId].tUnderfoot == TRUE)
gTasks[taskId].func = Task_ItemfinderUnderfootSoundsAndAnims;
if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING) && !TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_UNDERWATER))
gTasks[taskId].func = Task_UseORASDowsingMachine;
else
gTasks[taskId].func = Task_ItemfinderResponseSoundsAndAnims;
DisplayItemMessageOnField(taskId, FONT_NORMAL, gText_OakForbidsUseOfItemHere, Task_NoResponse_CleanUp);
}
else
{
DisplayItemMessageOnField(taskId, FONT_NORMAL, gText_NopeTheresNoResponse, Task_NoResponse_CleanUp);
u8 i;
for (i = 0; i < NUM_TASK_DATA; i++)
gTasks[taskId].data[i] = 0;
if (HiddenItemIsWithinRangeOfPlayer(gMapHeader.events, taskId) == TRUE)
{
LoadArrowAndStarTiles();
if (gTasks[taskId].tUnderfoot == TRUE)
gTasks[taskId].func = Task_ItemfinderUnderfootSoundsAndAnims;
else
gTasks[taskId].func = Task_ItemfinderResponseSoundsAndAnims;
}
else
{
DisplayItemMessageOnField(taskId, FONT_NORMAL, gText_NopeTheresNoResponse, Task_NoResponse_CleanUp);
}
}
}
@ -199,11 +212,16 @@ static void Task_ItemfinderUnderfootSoundsAndAnims(u8 taskId)
tDingTimer++;
}
static bool8 HiddenItemIsWithinRangeOfPlayer(const struct MapEvents * events, u8 taskId)
bool8 HiddenItemIsWithinRangeOfPlayer(const struct MapEvents *events, u8 taskId)
{
s16 x, y, i, dx, dy;
PlayerGetDestCoords(&x, &y);
gTasks[taskId].tHiddenItemFound = FALSE;
if (I_ORAS_DOWSING_FLAG != 0)
gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId].tHiddenItemFound = FALSE;
else
gTasks[taskId].tHiddenItemFound = FALSE;
for (i = 0; i < events->bgEventCount; i++)
{
if (events->bgEvents[i].kind == 7 && !FlagGet(GetHiddenItemAttr(events->bgEvents[i].bgUnion.hiddenItem, HIDDEN_ITEM_FLAG)))
@ -230,7 +248,7 @@ static bool8 HiddenItemIsWithinRangeOfPlayer(const struct MapEvents * events, u8
}
}
FindHiddenItemsInConnectedMaps(taskId);
if (gTasks[taskId].tHiddenItemFound == TRUE)
if (gTasks[taskId].tHiddenItemFound == TRUE || gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId].tHiddenItemFound)
{
SetNormalHiddenItem(taskId);
return TRUE;
@ -431,7 +449,7 @@ static void RegisterHiddenItemRelativeCoordsIfCloser(u8 taskId, s16 dx, s16 dy)
}
}
static u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY)
u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY)
{
s16 abX, abY;

View File

@ -496,6 +496,18 @@ static void PrintMessageWithPlaceholders(const u8 *str)
MoveRelearnerPrintMessage(gStringVar4, GetPlayerTextSpeedDelay());
}
// If reusable TMs is off, remove the TM from the bag
static void RemoveRelearnerTMFromBag(enum Move move)
{
enum Item item = GetTMHMItemIdFromMoveId(move);
if (!I_REUSABLE_TMS && !P_ENABLE_ALL_TM_MOVES
&& gMoveRelearnerState == MOVE_RELEARNER_TM_MOVES && GetItemTMHMIndex(item) <= NUM_TECHNICAL_MACHINES)
{
RemoveBagItem(item, 1);
}
}
static void DoMoveRelearnerMain(void)
{
switch (sMoveRelearnerStruct->state)
@ -717,6 +729,7 @@ static void DoMoveRelearnerMain(void)
break;
case MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE:
PrintMessageWithPlaceholders(gText_MonForgotOldMoveAndMonLearnedNewMove);
RemoveRelearnerTMFromBag(GetCurrentSelectedMove());
sMoveRelearnerStruct->state = MENU_STATE_PRINT_TEXT_THEN_FANFARE;
PlayFanfare(MUS_LEVEL_UP);
break;

562
src/oras_dowse.c Normal file
View File

@ -0,0 +1,562 @@
#include "global.h"
#include "bike.h"
#include "event_data.h"
#include "event_object_lock.h"
#include "event_object_movement.h"
#include "field_effect_helpers.h"
#include "field_effect.h"
#include "field_player_avatar.h"
#include "fldeff.h"
#include "item_use.h"
#include "itemfinder.h"
#include "oras_dowse.h"
#include "overworld.h"
#include "palette.h"
#include "script.h"
#include "sound.h"
#include "task.h"
#include "constants/field_effects.h"
#include "constants/songs.h"
#include "constants/rgb.h"
static void StartORASDowseFieldEffect(void);
static void UpdateORASDowsingFieldEffect(struct Sprite *sprite);
static void ChangeDowsingColor(enum Direction direction, struct Sprite *sprite);
static void ClearDowsingColor(struct Sprite *sprite);
static void PlayDowseSound(u32 dowseState);
const u32 gFieldEffectObjectPic_ORASDowsingRed[] = INCBIN_U32("graphics/field_effects/pics/oras_dowsing_red.4bpp");
const u32 gFieldEffectObjectPic_ORASDowsingGreen[] = INCBIN_U32("graphics/field_effects/pics/oras_dowsing_green.4bpp");
const u16 gFieldEffectPal_ORASDowsing[] = INCBIN_U16("graphics/field_effects/palettes/oras_dowsing.gbapal");
static const struct SpriteFrameImage sPicTable_ORASDowsingRed[] = {
overworld_ascending_frames(gFieldEffectObjectPic_ORASDowsingRed, 2, 4),
};
static const struct SpriteFrameImage sPicTable_ORASDowsingGreen[] = {
overworld_ascending_frames(gFieldEffectObjectPic_ORASDowsingGreen, 2, 4),
};
static const union AnimCmd sAnim_FaceSouth[] =
{
ANIMCMD_FRAME(0, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_FaceNorth[] =
{
ANIMCMD_FRAME(1, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_FaceWest[] =
{
ANIMCMD_FRAME(2, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_FaceEast[] =
{
ANIMCMD_FRAME(2, 16, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleSouthSlow[] =
{
ANIMCMD_FRAME(0, 32),
ANIMCMD_FRAME(0, 32),
ANIMCMD_FRAME(4, 32),
ANIMCMD_FRAME(4, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleNorthSlow[] =
{
ANIMCMD_FRAME(1, 32),
ANIMCMD_FRAME(1, 32),
ANIMCMD_FRAME(6, 32),
ANIMCMD_FRAME(6, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleWestSlow[] =
{
ANIMCMD_FRAME(2, 32),
ANIMCMD_FRAME(2, 32),
ANIMCMD_FRAME(8, 32),
ANIMCMD_FRAME(8, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleEastSlow[] =
{
ANIMCMD_FRAME(2, 32, .hFlip = TRUE),
ANIMCMD_FRAME(2, 32, .hFlip = TRUE),
ANIMCMD_FRAME(8, 32, .hFlip = TRUE),
ANIMCMD_FRAME(8, 32, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleSouth[] =
{
ANIMCMD_FRAME(0, 32),
ANIMCMD_FRAME(3, 32),
ANIMCMD_FRAME(0, 32),
ANIMCMD_FRAME(4, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleNorth[] =
{
ANIMCMD_FRAME(1, 32),
ANIMCMD_FRAME(5, 32),
ANIMCMD_FRAME(1, 32),
ANIMCMD_FRAME(6, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleWest[] =
{
ANIMCMD_FRAME(2, 32),
ANIMCMD_FRAME(7, 32),
ANIMCMD_FRAME(2, 32),
ANIMCMD_FRAME(8, 32),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleEast[] =
{
ANIMCMD_FRAME(2, 32, .hFlip = TRUE),
ANIMCMD_FRAME(7, 32, .hFlip = TRUE),
ANIMCMD_FRAME(2, 32, .hFlip = TRUE),
ANIMCMD_FRAME(8, 32, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleSouthFast[] =
{
ANIMCMD_FRAME(0, 16),
ANIMCMD_FRAME(3, 16),
ANIMCMD_FRAME(0, 16),
ANIMCMD_FRAME(4, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleNorthFast[] =
{
ANIMCMD_FRAME(1, 16),
ANIMCMD_FRAME(5, 16),
ANIMCMD_FRAME(1, 16),
ANIMCMD_FRAME(6, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleWestFast[] =
{
ANIMCMD_FRAME(2, 16),
ANIMCMD_FRAME(7, 16),
ANIMCMD_FRAME(2, 16),
ANIMCMD_FRAME(8, 16),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleEastFast[] =
{
ANIMCMD_FRAME(2, 16, .hFlip = TRUE),
ANIMCMD_FRAME(7, 16, .hFlip = TRUE),
ANIMCMD_FRAME(2, 16, .hFlip = TRUE),
ANIMCMD_FRAME(8, 16, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleSouthFaster[] =
{
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(3, 8),
ANIMCMD_FRAME(0, 8),
ANIMCMD_FRAME(4, 8),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleNorthFaster[] =
{
ANIMCMD_FRAME(1, 8),
ANIMCMD_FRAME(5, 8),
ANIMCMD_FRAME(1, 8),
ANIMCMD_FRAME(6, 8),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleWestFaster[] =
{
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(7, 8),
ANIMCMD_FRAME(2, 8),
ANIMCMD_FRAME(8, 8),
ANIMCMD_JUMP(0),
};
static const union AnimCmd sAnim_ORASDowseWiggleEastFaster[] =
{
ANIMCMD_FRAME(2, 8, .hFlip = TRUE),
ANIMCMD_FRAME(7, 8, .hFlip = TRUE),
ANIMCMD_FRAME(2, 8, .hFlip = TRUE),
ANIMCMD_FRAME(8, 8, .hFlip = TRUE),
ANIMCMD_JUMP(0),
};
static const union AnimCmd *const sAnimTable_ORASDowsing[] =
{
[ANIM_STD_FACE_SOUTH] = sAnim_FaceSouth,
[ANIM_STD_FACE_NORTH] = sAnim_FaceNorth,
[ANIM_STD_FACE_WEST] = sAnim_FaceWest,
[ANIM_STD_FACE_EAST] = sAnim_FaceEast,
[ANIM_ORAS_DOWSE_WIGGLE_SOUTH_SLOW] = sAnim_ORASDowseWiggleSouthSlow,
[ANIM_ORAS_DOWSE_WIGGLE_NORTH_SLOW] = sAnim_ORASDowseWiggleNorthSlow,
[ANIM_ORAS_DOWSE_WIGGLE_WEST_SLOW] = sAnim_ORASDowseWiggleWestSlow,
[ANIM_ORAS_DOWSE_WIGGLE_EAST_SLOW] = sAnim_ORASDowseWiggleEastSlow,
[ANIM_ORAS_DOWSE_WIGGLE_SOUTH] = sAnim_ORASDowseWiggleSouth,
[ANIM_ORAS_DOWSE_WIGGLE_NORTH] = sAnim_ORASDowseWiggleNorth,
[ANIM_ORAS_DOWSE_WIGGLE_WEST] = sAnim_ORASDowseWiggleWest,
[ANIM_ORAS_DOWSE_WIGGLE_EAST] = sAnim_ORASDowseWiggleEast,
[ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FAST] = sAnim_ORASDowseWiggleSouthFast,
[ANIM_ORAS_DOWSE_WIGGLE_NORTH_FAST] = sAnim_ORASDowseWiggleNorthFast,
[ANIM_ORAS_DOWSE_WIGGLE_WEST_FAST] = sAnim_ORASDowseWiggleWestFast,
[ANIM_ORAS_DOWSE_WIGGLE_EAST_FAST] = sAnim_ORASDowseWiggleEastFast,
[ANIM_ORAS_DOWSE_WIGGLE_SOUTH_FASTER] = sAnim_ORASDowseWiggleSouthFaster,
[ANIM_ORAS_DOWSE_WIGGLE_NORTH_FASTER] = sAnim_ORASDowseWiggleNorthFaster,
[ANIM_ORAS_DOWSE_WIGGLE_WEST_FASTER] = sAnim_ORASDowseWiggleWestFaster,
[ANIM_ORAS_DOWSE_WIGGLE_EAST_FASTER] = sAnim_ORASDowseWiggleEastFaster,
};
static const struct OamData gObjectEventOam_ORASDowse = {
.shape = SPRITE_SHAPE(16x32),
.size = SPRITE_SIZE(16x32),
.priority = 2
};
const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingRed = {
.tileTag = TAG_NONE,
.paletteTag = FLDEFF_PAL_TAG_ORAS_DOWSE,
.oam = &gObjectEventOam_ORASDowse,
.anims = sAnimTable_ORASDowsing,
.images = sPicTable_ORASDowsingRed,
.callback = UpdateORASDowsingFieldEffect,
};
const struct SpriteTemplate gFieldEffectObjectTemplate_ORASDowsingGreen = {
.tileTag = TAG_NONE,
.paletteTag = FLDEFF_PAL_TAG_ORAS_DOWSE,
.oam = &gObjectEventOam_ORASDowse,
.anims = sAnimTable_ORASDowsing,
.images = sPicTable_ORASDowsingGreen,
.callback = UpdateORASDowsingFieldEffect,
};
void Task_UseORASDowsingMachine(u8 taskId)
{
if (FlagGet(I_ORAS_DOWSING_FLAG))
{
EndORASDowsing();
}
else
{
if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_BIKE))
GetOnOffBike(0);
StartORASDowseFieldEffect();
}
ScriptUnfreezeObjectEvents();
UnlockPlayerFieldControls();
DestroyTask(taskId);
}
static void StartORASDowseFieldEffect(void)
{
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
gFieldEffectArguments[0] = playerObj->currentCoords.x;
gFieldEffectArguments[1] = playerObj->currentCoords.y;
FieldEffectStart(FLDEFF_ORAS_DOWSE);
}
void ResumeORASDowseFieldEffect(void)
{
if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG))
StartORASDowseFieldEffect();
}
static const struct SpritePalette gSpritePalette_ORASDowsing = {gFieldEffectPal_ORASDowsing, FLDEFF_PAL_TAG_ORAS_DOWSE};
// Sprite data for ORAS Dowsing Machine
#define tItemDistanceX data[0]
#define tItemDistanceY data[1]
#define sItemFound data[2]
#define sCounter data[3]
#define sSoundTimer data[4]
#define sDowseState data[5]
#define sPrevDowseState data[6]
#define sMoveActive data[7]
#define fPlayerX gFieldEffectArguments[0]
#define fPlayerY gFieldEffectArguments[1]
// Create the ORAS Dowsing Machine sprite.
u32 FldEff_ORASDowsing(void)
{
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
u32 spriteId;
u32 palNum;
FlagSet(I_ORAS_DOWSING_FLAG);
SetSpritePosToOffsetMapCoords((s16 *)&fPlayerX, (s16 *)&fPlayerY, 8, 0);
if (gPlayerAvatar.gender == MALE)
spriteId = CreateSpriteAtEnd(&gFieldEffectObjectTemplate_ORASDowsingRed, fPlayerX, fPlayerY, 1);
else
spriteId = CreateSpriteAtEnd(&gFieldEffectObjectTemplate_ORASDowsingGreen, fPlayerX, fPlayerY, 1);
if (spriteId != MAX_SPRITES)
{
struct Sprite *sprite = &gSprites[spriteId];
sprite->coordOffsetEnabled = TRUE;
palNum = LoadSpritePalette(&gSpritePalette_ORASDowsing);
if (palNum != 0xFF)
sprite->oam.paletteNum = palNum;
else
sprite->oam.paletteNum = LoadPlayerObjectEventPalette(gSaveBlock2Ptr->playerGender);
playerObj->fieldEffectSpriteId = spriteId;
sprite->sDowseState = ORASD_WIGGLE_NONE;
UpdateDowseState(sprite);
}
FieldEffectActiveListRemove(FLDEFF_ORAS_DOWSE);
return spriteId;
}
// Callback for ORAS Dowsing Machine sprite.
static void UpdateORASDowsingFieldEffect(struct Sprite *sprite)
{
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
struct Sprite *playerSprite = &gSprites[playerObj->spriteId];
if (!FlagGet(I_ORAS_DOWSING_FLAG))
{
DestroySpriteAndFreeResources(sprite);
return;
}
sprite->x = playerSprite->x;
sprite->y = playerSprite->y;
sprite->x2 = playerSprite->x2;
sprite->y2 = playerSprite->y2;
if (playerSprite->anims[playerSprite->animNum][playerSprite->animCmdIndex].frame.imageValue > 2)
sprite->y2++;
if (playerObj->previousMovementDirection != playerObj->movementDirection)
UpdateDowsingAnimDirection(sprite, playerObj);
if (playerObj->movementActionId != MOVEMENT_ACTION_NONE)
{
if (playerObj->heldMovementFinished == FALSE)
{
if (sprite->sCounter == 0)
{
sprite->sMoveActive = TRUE;
sprite->sCounter++;
}
}
else if (playerObj->heldMovementFinished == TRUE && sprite->sMoveActive)
{
sprite->sMoveActive = FALSE;
sprite->sCounter = 0;
UpdateDowseState(sprite);
}
}
if (I_ORAS_DOWSING_SOUNDS && sprite->sDowseState == ORASD_WIGGLE_FASTER && playerObj->heldMovementFinished != FALSE)
{
if (++sprite->sSoundTimer == 70)
{
PlaySE(SE_ITEMFINDER);
sprite->sSoundTimer = 0;
}
}
sprite->oam.priority = playerSprite->oam.priority;
}
static const u8 sClockwiseDirections[] = {DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST};
void UpdateDowseState(struct Sprite *sprite)
{
struct ObjectEvent *playerObj = &gObjectEvents[gPlayerAvatar.objectEventId];
sprite->tItemDistanceX = 0;
sprite->tItemDistanceY = 0;
sprite->sPrevDowseState = sprite->sDowseState;
if (HiddenItemIsWithinRangeOfPlayer(gMapHeader.events, TASK_NONE) == TRUE)
{
s8 distX = sprite->tItemDistanceX;
s8 distY = sprite->tItemDistanceY;
enum Direction directionToItem = CARDINAL_DIRECTION_COUNT;
enum Direction playerDirToItem = GetPlayerDirectionTowardsHiddenItem(distX, distY);
if (playerDirToItem != DIR_NONE)
directionToItem = sClockwiseDirections[GetPlayerDirectionTowardsHiddenItem(distX, distY) - 1];
if (distX < 0)
distX *= -1;
if (distY < 0)
distY *= -1;
// If the player is facing the item's direction.
if (directionToItem == playerObj->movementDirection)
{
ChangeDowsingColor(directionToItem, sprite);
}
// If x and y distances are equal, make sure item can bee seen from both facing directions.
else if (distX == distY && distX != 0)
{
if ((directionToItem == DIR_NORTH || directionToItem == DIR_SOUTH) && sprite->tItemDistanceX > 0 && playerObj->movementDirection == DIR_EAST)
ChangeDowsingColor(DIR_EAST, sprite);
else if ((directionToItem == DIR_NORTH || directionToItem == DIR_SOUTH) && sprite->tItemDistanceX < 0 && playerObj->movementDirection == DIR_WEST)
ChangeDowsingColor(DIR_WEST, sprite);
else
ClearDowsingColor(sprite);
}
else
{
ClearDowsingColor(sprite);
}
}
else
{
ClearDowsingColor(sprite);
}
UpdateDowsingAnimDirection(sprite, playerObj);
}
static void ChangeDowsingColor(enum Direction direction, struct Sprite *sprite)
{
s16 distance;
u16 color = I_ORAS_DOWSING_COLOR_NONE;
if (direction == DIR_NORTH || direction == DIR_SOUTH)
distance = sprite->tItemDistanceY;
else
distance = sprite->tItemDistanceX;
// Absolute value.
if (distance < 0)
distance *= -1;
switch (distance)
{
case 1:
if (sprite->tItemDistanceX == 0 || sprite->tItemDistanceY == 0)
{
color = I_ORAS_DOWSING_COLOR_FASTER;
sprite->sDowseState = ORASD_WIGGLE_FASTER;
break;
}
case 2:
color = I_ORAS_DOWSING_COLOR_FAST;
sprite->sDowseState = ORASD_WIGGLE_FAST;
break;
case 3:
case 4:
color = I_ORAS_DOWSING_COLOR_NORMAL;
sprite->sDowseState = ORASD_WIGGLE_NORMAL;
break;
case 5:
case 6:
case 7:
color = I_ORAS_DOWSING_COLOR_SLOW;
sprite->sDowseState = ORASD_WIGGLE_SLOW;
break;
}
if (I_ORAS_DOWSING_SOUNDS && sprite->sDowseState != sprite->sPrevDowseState)
{
sprite->sSoundTimer = 0;
PlayDowseSound(sprite->sDowseState);
}
FillPalette(color, (OBJ_PLTT_ID(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)) + I_ORAS_DOWSING_COLOR_PAL), PLTT_SIZEOF(1));
UpdateSpritePaletteWithTime(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE));
}
static void ClearDowsingColor(struct Sprite *sprite)
{
sprite->sDowseState = ORASD_WIGGLE_NONE;
FillPalette(I_ORAS_DOWSING_COLOR_NONE, (OBJ_PLTT_ID(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE)) + I_ORAS_DOWSING_COLOR_PAL), PLTT_SIZEOF(1));
UpdateSpritePaletteWithTime(IndexOfSpritePaletteTag(FLDEFF_PAL_TAG_ORAS_DOWSE));
}
static void PlayDowseSound(u32 dowseState)
{
switch (dowseState)
{
case ORASD_WIGGLE_SLOW:
PlaySE(SE_CONTEST_ICON_CLEAR);
return;
case ORASD_WIGGLE_NORMAL:
PlaySE(SE_PIN);
return;
case ORASD_WIGGLE_FAST:
PlaySE(SE_SUCCESS);
return;
case ORASD_WIGGLE_FASTER:
PlaySE(SE_ITEMFINDER);
return;
}
}
void UpdateDowsingAnimDirection(struct Sprite *sprite, struct ObjectEvent *playerObj)
{
u32 anim = (playerObj->facingDirection - 1);
switch (sprite->sDowseState)
{
case ORASD_WIGGLE_SLOW:
anim += 4;
break;
case ORASD_WIGGLE_NORMAL:
anim += 8;
break;
case ORASD_WIGGLE_FAST:
anim += 12;
break;
case ORASD_WIGGLE_FASTER:
anim += 16;
break;
}
// Don't completely restart anim if wiggling didn't stop.
if (sprite->sPrevDowseState != ORASD_WIGGLE_NONE && sprite->sDowseState != ORASD_WIGGLE_NONE)
SetAndStartSpriteAnim(sprite, anim, sprite->animCmdIndex);
else
StartSpriteAnimIfDifferent(sprite, anim);
}
void EndORASDowsing(void)
{
if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG))
FlagClear(I_ORAS_DOWSING_FLAG);
}
void Script_ClearDowsingColor(void)
{
if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG))
{
struct Sprite *sprite = &gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId];
ClearDowsingColor(sprite);
UpdateDowsingAnimDirection(sprite, &gObjectEvents[gPlayerAvatar.objectEventId]);
}
}
void Script_UpdateDowseState(void)
{
if (I_ORAS_DOWSING_FLAG != 0 && FlagGet(I_ORAS_DOWSING_FLAG))
UpdateDowseState(&gSprites[gObjectEvents[gPlayerAvatar.objectEventId].fieldEffectSpriteId]);
}

View File

@ -43,6 +43,7 @@
#include "money.h"
#include "new_game.h"
#include "overworld.h"
#include "oras_dowse.h"
#include "palette.h"
#include "play_time.h"
#include "quest_log_objects.h"
@ -2178,6 +2179,7 @@ static bool32 ReturnToFieldLocal(u8 *state)
case 2:
InitViewGraphics();
FollowerNPC_BindToSurfBlobOnReloadScreen();
ResumeORASDowseFieldEffect();
SetHelpContextForMap();
(*state)++;
break;

View File

@ -939,14 +939,10 @@ static bool8 IsWildLevelAllowedByRepel(u8 wildLevel)
for (i = 0; i < PARTY_SIZE; i++)
{
if (GetMonData(&gPlayerParty[i], MON_DATA_HP) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
if (I_REPEL_INCLUDE_FAINTED == GEN_1 || I_REPEL_INCLUDE_FAINTED >= GEN_6 || GetMonData(&gPlayerParty[i], MON_DATA_HP))
{
u8 ourLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
if (wildLevel < ourLevel)
return FALSE;
else
return TRUE;
if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
return wildLevel >= GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
}
}