mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-18 12:37:38 +01:00
646 lines
22 KiB
C
646 lines
22 KiB
C
#include "global.h"
|
|
#include "event_obj_lock.h"
|
|
#include "event_object_movement.h"
|
|
#include "faraway_island.h"
|
|
#include "field_camera.h"
|
|
#include "field_effect.h"
|
|
#include "field_player_avatar.h"
|
|
#include "fieldmap.h"
|
|
#include "fldeff.h"
|
|
#include "malloc.h"
|
|
#include "metatile_behavior.h"
|
|
#include "overworld.h"
|
|
#include "party_menu.h"
|
|
#include "script.h"
|
|
#include "sound.h"
|
|
#include "sprite.h"
|
|
#include "task.h"
|
|
#include "trig.h"
|
|
#include "constants/abilities.h"
|
|
#include "constants/event_objects.h"
|
|
#include "constants/field_effects.h"
|
|
#include "constants/songs.h"
|
|
#include "constants/metatile_labels.h"
|
|
|
|
extern struct MapPosition gPlayerFacingPosition;
|
|
|
|
extern const u8 EventScript_FldEffCut[];
|
|
extern const u8 FarawayIsland_Interior_EventScript_HideMewWhenGrassCut[];
|
|
|
|
extern const u8 gFieldEffectPic_CutGrass[];
|
|
extern const u16 gFieldEffectObjectPalette6[];
|
|
|
|
// cut 'square' defines
|
|
#define CUT_NORMAL_SIDE 3
|
|
#define CUT_NORMAL_AREA CUT_NORMAL_SIDE * CUT_NORMAL_SIDE
|
|
|
|
#define CUT_HYPER_SIDE 5
|
|
#define CUT_HYPER_AREA CUT_HYPER_SIDE * CUT_HYPER_SIDE
|
|
|
|
#define CUT_SPRITE_ARRAY_COUNT 8
|
|
|
|
struct HyperCutterUnk
|
|
{
|
|
s8 x;
|
|
s8 y;
|
|
u8 unk2[2];
|
|
};
|
|
|
|
// this file's functions
|
|
static void FieldCallback_CutTree(void);
|
|
static void FieldCallback_CutGrass(void);
|
|
static void StartCutTreeFieldEffect(void);
|
|
static void StartCutGrassFieldEffect(void);
|
|
static void SetCutGrassMetatile(s16, s16);
|
|
static void SetCutGrassMetatiles(s16, s16);
|
|
static void CutGrassSpriteCallback1(struct Sprite *);
|
|
static void CutGrassSpriteCallback2(struct Sprite *);
|
|
static void CutGrassSpriteCallbackEnd(struct Sprite *);
|
|
static void HandleLongGrassOnHyper(u8, s16, s16);
|
|
|
|
// IWRAM variables
|
|
static u8 sCutSquareSide;
|
|
static u8 sTileCountFromPlayer_X;
|
|
static u8 sTileCountFromPlayer_Y;
|
|
static u32 sUnused;
|
|
static bool8 sHyperCutTiles[CUT_HYPER_AREA];
|
|
|
|
// EWRAM variables
|
|
static EWRAM_DATA u8 *sCutGrassSpriteArrayPtr = NULL;
|
|
|
|
// const rom data
|
|
static const struct HyperCutterUnk sHyperCutStruct[] =
|
|
{
|
|
{-2, -2, {1}},
|
|
{-1, -2, {1}},
|
|
{0, -2, {2}},
|
|
{1, -2, {3}},
|
|
{2, -2, {3}},
|
|
{-2, -1, {1}},
|
|
{2, -1, {3}},
|
|
{-2, 0, {4}},
|
|
{2, 0, {6}},
|
|
{-2, 1, {7}},
|
|
{2, 1, {9}},
|
|
{-2, 2, {7}},
|
|
{-1, 2, {7}},
|
|
{0, 2, {8}},
|
|
{1, 2, {9}},
|
|
{2, 2, {9}},
|
|
};
|
|
|
|
static const struct OamData sOamData_CutGrass =
|
|
{
|
|
.y = 0,
|
|
.affineMode = ST_OAM_AFFINE_OFF,
|
|
.objMode = ST_OAM_OBJ_NORMAL,
|
|
.mosaic = 0,
|
|
.bpp = ST_OAM_4BPP,
|
|
.shape = SPRITE_SHAPE(8x8),
|
|
.x = 0,
|
|
.matrixNum = 0,
|
|
.size = SPRITE_SIZE(8x8),
|
|
.tileNum = 1,
|
|
.priority = 1,
|
|
.paletteNum = 1,
|
|
.affineParam = 0,
|
|
};
|
|
|
|
static const union AnimCmd sSpriteAnim_CutGrass[] =
|
|
{
|
|
ANIMCMD_FRAME(0, 30),
|
|
ANIMCMD_JUMP(0),
|
|
};
|
|
|
|
static const union AnimCmd *const sSpriteAnimTable_CutGrass[] =
|
|
{
|
|
sSpriteAnim_CutGrass,
|
|
};
|
|
|
|
static const struct SpriteFrameImage sSpriteImageTable_CutGrass[] =
|
|
{
|
|
{gFieldEffectPic_CutGrass, 0x20},
|
|
};
|
|
|
|
const struct SpritePalette gFieldEffectObjectPaletteInfo6 = {gFieldEffectObjectPalette6, 0x1000};
|
|
|
|
static const struct SpriteTemplate sSpriteTemplate_CutGrass =
|
|
{
|
|
.tileTag = 0xFFFF,
|
|
.paletteTag = 0x1000,
|
|
.oam = &sOamData_CutGrass,
|
|
.anims = sSpriteAnimTable_CutGrass,
|
|
.images = sSpriteImageTable_CutGrass,
|
|
.affineAnims = gDummySpriteAffineAnimTable,
|
|
.callback = CutGrassSpriteCallback1,
|
|
};
|
|
|
|
// code
|
|
bool8 SetUpFieldMove_Cut(void)
|
|
{
|
|
s16 x, y;
|
|
u8 i, j;
|
|
u8 tileBehavior;
|
|
u8 userAbility;
|
|
bool8 cutTiles[CUT_NORMAL_AREA];
|
|
bool8 ret;
|
|
|
|
if (CheckObjectGraphicsInFrontOfPlayer(EVENT_OBJ_GFX_CUTTABLE_TREE) == TRUE)
|
|
{
|
|
// Standing in front of cuttable tree.
|
|
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
|
|
gPostMenuFieldCallback = FieldCallback_CutTree;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
PlayerGetDestCoords(&gPlayerFacingPosition.x, &gPlayerFacingPosition.y);
|
|
userAbility = GetMonAbility(&gPlayerParty[GetCursorSelectionMonId()]);
|
|
if (userAbility == ABILITY_HYPER_CUTTER)
|
|
{
|
|
sCutSquareSide = CUT_HYPER_SIDE;
|
|
sTileCountFromPlayer_X = 2;
|
|
sTileCountFromPlayer_Y = 2;
|
|
}
|
|
else
|
|
{
|
|
sCutSquareSide = CUT_NORMAL_SIDE;
|
|
sTileCountFromPlayer_X = 1;
|
|
sTileCountFromPlayer_Y = 1;
|
|
}
|
|
|
|
for (i = 0; i < CUT_NORMAL_AREA; i++)
|
|
cutTiles[i] = FALSE;
|
|
for (i = 0; i < CUT_HYPER_AREA; i++)
|
|
sHyperCutTiles[i] = FALSE;
|
|
|
|
ret = FALSE;
|
|
|
|
for (i = 0; i < CUT_NORMAL_SIDE; i++)
|
|
{
|
|
y = i - 1 + gPlayerFacingPosition.y;
|
|
for (j = 0; j < CUT_NORMAL_SIDE; j++)
|
|
{
|
|
x = j - 1 + gPlayerFacingPosition.x;
|
|
if (MapGridGetZCoordAt(x, y) == gPlayerFacingPosition.height)
|
|
{
|
|
tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
|
|
if (MetatileBehavior_IsPokeGrass(tileBehavior) == TRUE
|
|
|| MetatileBehavior_IsAshGrass(tileBehavior) == TRUE)
|
|
{
|
|
// Standing in front of grass.
|
|
sHyperCutTiles[6 + (i * 5) + j] = TRUE;
|
|
ret = TRUE;
|
|
}
|
|
if (MapGridIsImpassableAt(x, y) == TRUE)
|
|
{
|
|
cutTiles[i * 3 + j] = FALSE;
|
|
}
|
|
else
|
|
{
|
|
cutTiles[i * 3 + j] = TRUE;
|
|
if (MetatileBehavior_IsCuttableGrass(tileBehavior) == TRUE)
|
|
sHyperCutTiles[6 + (i * 5) + j] = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cutTiles[i * 3 + j] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (userAbility != ABILITY_HYPER_CUTTER)
|
|
{
|
|
if (ret == TRUE)
|
|
{
|
|
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
|
|
gPostMenuFieldCallback = FieldCallback_CutGrass;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bool8 tileCuttable;
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
x = gPlayerFacingPosition.x + sHyperCutStruct[i].x;
|
|
y = gPlayerFacingPosition.y + sHyperCutStruct[i].y;
|
|
tileCuttable = TRUE;
|
|
|
|
j = 0;
|
|
do
|
|
{
|
|
if (sHyperCutStruct[i].unk2[j] == 0)
|
|
break;
|
|
if (cutTiles[(u8)(sHyperCutStruct[i].unk2[j] - 1)] == FALSE)
|
|
{
|
|
tileCuttable = FALSE;
|
|
break;
|
|
}
|
|
} while (++j <= 1);
|
|
|
|
if (tileCuttable == TRUE)
|
|
{
|
|
if (MapGridGetZCoordAt(x, y) == gPlayerFacingPosition.height)
|
|
{
|
|
u8 tileArrayId = ((sHyperCutStruct[i].y * 5) + 12) + (sHyperCutStruct[i].x);
|
|
tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
|
|
if (MetatileBehavior_IsPokeGrass(tileBehavior) == TRUE
|
|
|| MetatileBehavior_IsAshGrass(tileBehavior) == TRUE)
|
|
{
|
|
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
|
|
gPostMenuFieldCallback = FieldCallback_CutGrass;
|
|
sHyperCutTiles[tileArrayId] = TRUE;
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (MetatileBehavior_IsCuttableGrass(tileBehavior) == TRUE)
|
|
sHyperCutTiles[tileArrayId] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ret == TRUE)
|
|
{
|
|
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
|
|
gPostMenuFieldCallback = FieldCallback_CutGrass;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
static void FieldCallback_CutGrass(void)
|
|
{
|
|
FieldEffectStart(FLDEFF_USE_CUT_ON_GRASS);
|
|
gFieldEffectArguments[0] = GetCursorSelectionMonId();
|
|
}
|
|
|
|
bool8 FldEff_UseCutOnGrass(void)
|
|
{
|
|
u8 taskId = oei_task_add();
|
|
|
|
gTasks[taskId].data[8] = (u32)StartCutGrassFieldEffect >> 16;
|
|
gTasks[taskId].data[9] = (u32)StartCutGrassFieldEffect;
|
|
IncrementGameStat(GAME_STAT_USED_CUT);
|
|
return FALSE;
|
|
}
|
|
|
|
static void FieldCallback_CutTree(void)
|
|
{
|
|
gFieldEffectArguments[0] = GetCursorSelectionMonId();
|
|
ScriptContext1_SetupScript(EventScript_FldEffCut);
|
|
}
|
|
|
|
bool8 FldEff_UseCutOnTree(void)
|
|
{
|
|
u8 taskId = oei_task_add();
|
|
|
|
gTasks[taskId].data[8] = (u32)StartCutTreeFieldEffect >> 16;
|
|
gTasks[taskId].data[9] = (u32)StartCutTreeFieldEffect;
|
|
IncrementGameStat(GAME_STAT_USED_CUT);
|
|
return FALSE;
|
|
}
|
|
|
|
static void StartCutGrassFieldEffect(void)
|
|
{
|
|
FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_GRASS);
|
|
FieldEffectStart(FLDEFF_CUT_GRASS);
|
|
}
|
|
|
|
bool8 FldEff_CutGrass(void)
|
|
{
|
|
s16 x, y;
|
|
u8 i = 0;
|
|
|
|
PlaySE(SE_W015);
|
|
PlayerGetDestCoords(&gPlayerFacingPosition.x, &gPlayerFacingPosition.y);
|
|
for (i = 0; i < CUT_HYPER_AREA; i++)
|
|
{
|
|
if (sHyperCutTiles[i] == TRUE)
|
|
{
|
|
s8 xAdd = (i % 5) - 2;
|
|
s8 yAdd = (i / 5) - 2;
|
|
|
|
x = xAdd + gPlayerFacingPosition.x;
|
|
y = yAdd + gPlayerFacingPosition.y;
|
|
|
|
SetCutGrassMetatile(x, y);
|
|
sub_808E75C(x, y);
|
|
}
|
|
}
|
|
|
|
SetCutGrassMetatiles(gPlayerFacingPosition.x - sTileCountFromPlayer_X, gPlayerFacingPosition.y - (1 + sTileCountFromPlayer_Y));
|
|
DrawWholeMapView();
|
|
sCutGrassSpriteArrayPtr = AllocZeroed(CUT_SPRITE_ARRAY_COUNT);
|
|
|
|
// populate sprite ID array
|
|
for (i = 0; i < CUT_SPRITE_ARRAY_COUNT; i++)
|
|
{
|
|
sCutGrassSpriteArrayPtr[i] = CreateSprite(&sSpriteTemplate_CutGrass,
|
|
gSprites[gPlayerAvatar.spriteId].oam.x + 8, gSprites[gPlayerAvatar.spriteId].oam.y + 20, 0);
|
|
gSprites[sCutGrassSpriteArrayPtr[i]].data[2] = 32 * i;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// set map grid metatile depending on x, y
|
|
static void SetCutGrassMetatile(s16 x, s16 y)
|
|
{
|
|
s32 metatileId = MapGridGetMetatileIdAt(x, y);
|
|
|
|
switch (metatileId)
|
|
{
|
|
case METATILE_ID(Fortree, LongGrass_Root):
|
|
case METATILE_ID(General, LongGrass):
|
|
case METATILE_ID(General, TallGrass):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(General, Grass));
|
|
break;
|
|
case METATILE_ID(General, TallGrass_TreeLeft):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(General, Grass_TreeLeft));
|
|
break;
|
|
case METATILE_ID(General, TallGrass_TreeRight):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(General, Grass_TreeRight));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(Fortree, SecretBase_LongGrass_TopMid));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(Fortree, SecretBase_LongGrass_TopRight));
|
|
break;
|
|
case METATILE_ID(Lavaridge, NormalGrass):
|
|
case METATILE_ID(Lavaridge, AshGrass):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(Lavaridge, LavaField));
|
|
break;
|
|
case METATILE_ID(Fallarbor, NormalGrass):
|
|
case METATILE_ID(Fallarbor, AshGrass):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(Fallarbor, AshField));
|
|
break;
|
|
case METATILE_ID(General, TallGrass_TreeUp):
|
|
MapGridSetMetatileIdAt(x, y, METATILE_ID(General, Grass_TreeUp));
|
|
break;
|
|
}
|
|
}
|
|
|
|
enum
|
|
{
|
|
LONG_GRASS_NONE,
|
|
LONG_GRASS_FIELD,
|
|
LONG_GRASS_BASE_LEFT,
|
|
LONG_GRASS_BASE_CENTER,
|
|
LONG_GRASS_BASE_RIGHT
|
|
};
|
|
|
|
static u8 GetLongGrassCaseAt(s16 x, s16 y)
|
|
{
|
|
u16 metatileId = MapGridGetMetatileIdAt(x, y);
|
|
|
|
if (metatileId == METATILE_ID(General, Grass))
|
|
return LONG_GRASS_FIELD;
|
|
else if (metatileId == METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft))
|
|
return LONG_GRASS_BASE_LEFT;
|
|
else if (metatileId == METATILE_ID(Fortree, SecretBase_LongGrass_TopMid))
|
|
return LONG_GRASS_BASE_CENTER;
|
|
else if (metatileId == METATILE_ID(Fortree, SecretBase_LongGrass_TopRight))
|
|
return LONG_GRASS_BASE_RIGHT;
|
|
else
|
|
return LONG_GRASS_NONE;
|
|
}
|
|
|
|
static void SetCutGrassMetatiles(s16 x, s16 y)
|
|
{
|
|
s16 i;
|
|
s16 lowerY = y + sCutSquareSide;
|
|
|
|
for (i = 0; i < sCutSquareSide; i++)
|
|
{
|
|
s16 currentX = x + i;
|
|
if (MapGridGetMetatileIdAt(currentX, y) == METATILE_ID(General, LongGrass))
|
|
{
|
|
switch (GetLongGrassCaseAt(currentX, y + 1))
|
|
{
|
|
case LONG_GRASS_FIELD:
|
|
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_ID(Fortree, LongGrass_Root));
|
|
break;
|
|
case LONG_GRASS_BASE_LEFT:
|
|
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft));
|
|
break;
|
|
case LONG_GRASS_BASE_CENTER:
|
|
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid));
|
|
break;
|
|
case LONG_GRASS_BASE_RIGHT:
|
|
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight));
|
|
break;
|
|
}
|
|
}
|
|
if (MapGridGetMetatileIdAt(currentX, lowerY) == METATILE_ID(General, Grass))
|
|
{
|
|
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_ID(Fortree, LongGrass_Root))
|
|
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_ID(General, Grass));
|
|
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft))
|
|
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft));
|
|
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid))
|
|
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopMid));
|
|
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight))
|
|
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopRight));
|
|
}
|
|
}
|
|
|
|
if (sCutSquareSide == CUT_HYPER_SIDE)
|
|
{
|
|
HandleLongGrassOnHyper(0, x, y);
|
|
HandleLongGrassOnHyper(1, x, y);
|
|
}
|
|
}
|
|
|
|
static void HandleLongGrassOnHyper(u8 caseId, s16 x, s16 y)
|
|
{
|
|
s16 newX;
|
|
bool8 arr[3];
|
|
|
|
if (caseId == 0)
|
|
{
|
|
arr[0] = sHyperCutTiles[5];
|
|
arr[1] = sHyperCutTiles[10];
|
|
arr[2] = sHyperCutTiles[15];
|
|
newX = x;
|
|
}
|
|
else if (caseId == 1)
|
|
{
|
|
arr[0] = sHyperCutTiles[9];
|
|
arr[1] = sHyperCutTiles[14];
|
|
arr[2] = sHyperCutTiles[19];
|
|
newX = x + 4;
|
|
}
|
|
else // invalid case
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (arr[0] == TRUE)
|
|
{
|
|
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_ID(Fortree, LongGrass_Root))
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(General, Grass));
|
|
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft))
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft));
|
|
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid))
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_TopMid));
|
|
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight))
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_TopRight));
|
|
}
|
|
if (arr[1] == TRUE)
|
|
{
|
|
if (MapGridGetMetatileIdAt(newX, y + 2) == METATILE_ID(General, LongGrass))
|
|
{
|
|
switch (GetLongGrassCaseAt(newX, y + 3))
|
|
{
|
|
case LONG_GRASS_FIELD:
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, LongGrass_Root));
|
|
break;
|
|
case LONG_GRASS_BASE_LEFT:
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft));
|
|
break;
|
|
case LONG_GRASS_BASE_CENTER:
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid));
|
|
break;
|
|
case LONG_GRASS_BASE_RIGHT:
|
|
MapGridSetMetatileIdAt(newX, y + 3, METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_ID(Fortree, LongGrass_Root))
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(General, Grass));
|
|
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft))
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft));
|
|
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid))
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_TopMid));
|
|
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight))
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_TopRight));
|
|
}
|
|
if (arr[2] == TRUE)
|
|
{
|
|
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_ID(General, LongGrass))
|
|
{
|
|
switch (GetLongGrassCaseAt(newX, y + 4))
|
|
{
|
|
case LONG_GRASS_FIELD:
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, LongGrass_Root));
|
|
break;
|
|
case LONG_GRASS_BASE_LEFT:
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft));
|
|
break;
|
|
case LONG_GRASS_BASE_CENTER:
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid));
|
|
break;
|
|
case LONG_GRASS_BASE_RIGHT:
|
|
MapGridSetMetatileIdAt(newX, y + 4, METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void CutGrassSpriteCallback1(struct Sprite *sprite)
|
|
{
|
|
sprite->data[0] = 8;
|
|
sprite->data[1] = 0;
|
|
sprite->data[3] = 0;
|
|
sprite->callback = CutGrassSpriteCallback2;
|
|
}
|
|
|
|
static void CutGrassSpriteCallback2(struct Sprite *sprite)
|
|
{
|
|
sprite->pos2.x = Sin(sprite->data[2], sprite->data[0]);
|
|
sprite->pos2.y = Cos(sprite->data[2], sprite->data[0]);
|
|
|
|
sprite->data[2] = (sprite->data[2] + 8) & 0xFF;
|
|
sprite->data[0] += 1 + (sprite->data[3] >> 2); // right shift by 2 is dividing by 4
|
|
sprite->data[3]++;
|
|
|
|
if (sprite->data[1] != 28)
|
|
sprite->data[1]++;
|
|
else
|
|
sprite->callback = CutGrassSpriteCallbackEnd; // done rotating the grass, execute clean up function
|
|
}
|
|
|
|
static void CutGrassSpriteCallbackEnd(struct Sprite *sprite)
|
|
{
|
|
u8 i;
|
|
|
|
for (i = 1; i < CUT_SPRITE_ARRAY_COUNT; i++)
|
|
DestroySprite(&gSprites[sCutGrassSpriteArrayPtr[i]]);
|
|
|
|
FieldEffectStop(&gSprites[sCutGrassSpriteArrayPtr[0]], FLDEFF_CUT_GRASS);
|
|
FREE_AND_SET_NULL(sCutGrassSpriteArrayPtr);
|
|
ScriptUnfreezeEventObjects();
|
|
ScriptContext2_Disable();
|
|
|
|
if (IsMewPlayingHideAndSeek() == TRUE)
|
|
ScriptContext1_SetupScript(FarawayIsland_Interior_EventScript_HideMewWhenGrassCut);
|
|
}
|
|
|
|
void FixLongGrassMetatilesWindowTop(s16 x, s16 y)
|
|
{
|
|
u8 metatileBehavior = MapGridGetMetatileBehaviorAt(x, y);
|
|
if (MetatileBehavior_IsLongGrass_Duplicate(metatileBehavior))
|
|
{
|
|
switch (GetLongGrassCaseAt(x, y + 1))
|
|
{
|
|
case LONG_GRASS_FIELD:
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, LongGrass_Root));
|
|
break;
|
|
case LONG_GRASS_BASE_LEFT:
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft));
|
|
break;
|
|
case LONG_GRASS_BASE_CENTER:
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid));
|
|
break;
|
|
case LONG_GRASS_BASE_RIGHT:
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FixLongGrassMetatilesWindowBottom(s16 x, s16 y)
|
|
{
|
|
if (MapGridGetMetatileIdAt(x, y) == METATILE_ID(General, Grass))
|
|
{
|
|
u8 metatileBehavior = MapGridGetMetatileBehaviorAt(x, y + 1);
|
|
if (MetatileBehavior_IsLongGrassSouthEdge(metatileBehavior))
|
|
{
|
|
s32 metatileId = MapGridGetMetatileIdAt(x, y + 1);
|
|
switch (metatileId)
|
|
{
|
|
case METATILE_ID(Fortree, LongGrass_Root):
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(General, Grass));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomLeft):
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopLeft));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomMid):
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopMid));
|
|
break;
|
|
case METATILE_ID(Fortree, SecretBase_LongGrass_BottomRight):
|
|
MapGridSetMetatileIdAt(x, y + 1, METATILE_ID(Fortree, SecretBase_LongGrass_TopRight));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void StartCutTreeFieldEffect(void)
|
|
{
|
|
PlaySE(SE_W015);
|
|
FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_TREE);
|
|
EnableBothScriptContexts();
|
|
}
|