pokeemerald/src/fldeff_cut.c

648 lines
21 KiB
C
Raw Normal View History

#include "global.h"
#include "event_object_lock.h"
2018-10-15 00:43:40 +02:00
#include "event_object_movement.h"
2020-07-02 10:59:52 +02:00
#include "event_scripts.h"
#include "faraway_island.h"
2018-06-16 00:45:48 +02:00
#include "field_camera.h"
#include "field_effect.h"
#include "field_player_avatar.h"
#include "fieldmap.h"
2018-12-24 21:59:05 +01:00
#include "fldeff.h"
#include "malloc.h"
2018-06-16 00:45:48 +02:00
#include "metatile_behavior.h"
#include "overworld.h"
2018-10-15 00:43:40 +02:00
#include "party_menu.h"
2018-06-16 00:45:48 +02:00
#include "script.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "trig.h"
2018-10-15 00:43:40 +02:00
#include "constants/abilities.h"
2018-06-16 00:45:48 +02:00
#include "constants/event_objects.h"
2018-11-13 15:19:04 +01:00
#include "constants/field_effects.h"
2018-06-16 00:45:48 +02:00
#include "constants/songs.h"
2019-06-12 04:22:50 +02:00
#include "constants/metatile_labels.h"
2018-06-16 00:45:48 +02:00
extern struct MapPosition gPlayerFacingPosition;
2019-10-31 22:00:37 +01:00
extern const u8 FarawayIsland_Interior_EventScript_HideMewWhenGrassCut[];
extern const u8 gFieldEffectPic_CutGrass[];
2020-07-02 10:59:52 +02:00
extern const u16 gFieldEffectPal_CutGrass[];
// cut 'square' defines
2018-06-16 00:45:48 +02:00
#define CUT_NORMAL_SIDE 3
#define CUT_NORMAL_AREA CUT_NORMAL_SIDE * CUT_NORMAL_SIDE
2018-06-16 00:45:48 +02:00
#define CUT_HYPER_SIDE 5
#define CUT_HYPER_AREA CUT_HYPER_SIDE * CUT_HYPER_SIDE
#define CUT_SPRITE_ARRAY_COUNT 8
2018-06-16 00:45:48 +02:00
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 bool8 sHyperCutTiles[CUT_HYPER_AREA];
// EWRAM variables
static EWRAM_DATA u8 *sCutGrassSpriteArrayPtr = NULL;
// const rom data
static const struct HyperCutterUnk sHyperCutStruct[] =
2018-06-16 00:45:48 +02:00
{
{-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 =
2018-06-16 00:45:48 +02:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2022-07-30 03:27:39 +02:00
.mosaic = FALSE,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(8x8),
2018-06-16 00:45:48 +02:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(8x8),
2018-06-16 00:45:48 +02:00
.tileNum = 1,
.priority = 1,
.paletteNum = 1,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_CutGrass[] =
2018-06-16 00:45:48 +02:00
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_JUMP(0),
};
static const union AnimCmd *const sSpriteAnimTable_CutGrass[] =
2018-06-16 00:45:48 +02:00
{
sSpriteAnim_CutGrass,
2018-06-16 00:45:48 +02:00
};
static const struct SpriteFrameImage sSpriteImageTable_CutGrass[] =
2018-06-16 00:45:48 +02:00
{
{gFieldEffectPic_CutGrass, 0x20},
};
2020-07-02 10:59:52 +02:00
const struct SpritePalette gSpritePalette_CutGrass = {gFieldEffectPal_CutGrass, FLDEFF_PAL_TAG_CUT_GRASS};
2018-06-16 00:45:48 +02:00
static const struct SpriteTemplate sSpriteTemplate_CutGrass =
2018-06-16 00:45:48 +02:00
{
2021-09-14 19:14:14 +02:00
.tileTag = TAG_NONE,
2020-07-02 10:59:52 +02:00
.paletteTag = FLDEFF_PAL_TAG_CUT_GRASS,
.oam = &sOamData_CutGrass,
.anims = sSpriteAnimTable_CutGrass,
.images = sSpriteImageTable_CutGrass,
2018-06-16 00:45:48 +02:00
.affineAnims = gDummySpriteAffineAnimTable,
.callback = CutGrassSpriteCallback1,
};
// code
2018-06-16 00:45:48 +02:00
bool8 SetUpFieldMove_Cut(void)
{
s16 x, y;
u8 i, j;
u8 tileBehavior;
u16 userAbility;
bool8 cutTiles[CUT_NORMAL_AREA];
2018-06-16 00:45:48 +02:00
bool8 ret;
if (CheckObjectGraphicsInFrontOfPlayer(OBJ_EVENT_GFX_CUTTABLE_TREE) == TRUE)
2018-06-16 00:45:48 +02:00
{
// 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;
2018-06-16 00:45:48 +02:00
}
else
{
sCutSquareSide = CUT_NORMAL_SIDE;
sTileCountFromPlayer_X = 1;
sTileCountFromPlayer_Y = 1;
2018-06-16 00:45:48 +02:00
}
for (i = 0; i < CUT_NORMAL_AREA; i++)
cutTiles[i] = FALSE;
2018-06-16 00:45:48 +02:00
for (i = 0; i < CUT_HYPER_AREA; i++)
sHyperCutTiles[i] = FALSE;
2018-06-16 00:45:48 +02:00
ret = FALSE;
for (i = 0; i < CUT_NORMAL_SIDE; i++)
2018-06-16 00:45:48 +02:00
{
y = i - 1 + gPlayerFacingPosition.y;
for (j = 0; j < CUT_NORMAL_SIDE; j++)
2018-06-16 00:45:48 +02:00
{
x = j - 1 + gPlayerFacingPosition.x;
if (MapGridGetElevationAt(x, y) == gPlayerFacingPosition.elevation)
2018-06-16 00:45:48 +02:00
{
tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
if (MetatileBehavior_IsPokeGrass(tileBehavior) == TRUE
|| MetatileBehavior_IsAshGrass(tileBehavior) == TRUE)
{
// Standing in front of grass.
sHyperCutTiles[6 + (i * 5) + j] = TRUE;
2018-06-16 00:45:48 +02:00
ret = TRUE;
}
#ifdef BUGFIX
// Collision has a range 0-3, any value != 0 is impassable
if (MapGridGetCollisionAt(x, y))
#else
if (MapGridGetCollisionAt(x, y) == 1)
#endif
2018-06-16 00:45:48 +02:00
{
cutTiles[i * 3 + j] = FALSE;
2018-06-16 00:45:48 +02:00
}
else
{
cutTiles[i * 3 + j] = TRUE;
2018-06-16 00:45:48 +02:00
if (MetatileBehavior_IsCuttableGrass(tileBehavior) == TRUE)
sHyperCutTiles[6 + (i * 5) + j] = TRUE;
2018-06-16 00:45:48 +02:00
}
}
else
{
cutTiles[i * 3 + j] = FALSE;
2018-06-16 00:45:48 +02:00
}
}
}
if (userAbility != ABILITY_HYPER_CUTTER)
{
if (ret == TRUE)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
gPostMenuFieldCallback = FieldCallback_CutGrass;
}
}
else
{
bool8 tileCuttable;
2018-06-16 00:45:48 +02:00
for (i = 0; i < 16; i++)
{
x = gPlayerFacingPosition.x + sHyperCutStruct[i].x;
y = gPlayerFacingPosition.y + sHyperCutStruct[i].y;
tileCuttable = TRUE;
2018-06-16 00:45:48 +02:00
for (j = 0; j < 2; ++j)
2018-06-16 00:45:48 +02:00
{
if (sHyperCutStruct[i].unk2[j] == 0) break; // one line required to match -g
if (cutTiles[(u8)(sHyperCutStruct[i].unk2[j] - 1)] == FALSE)
2018-06-16 00:45:48 +02:00
{
tileCuttable = FALSE;
2018-06-16 00:45:48 +02:00
break;
}
}
2018-06-16 00:45:48 +02:00
if (tileCuttable == TRUE)
2018-06-16 00:45:48 +02:00
{
if (MapGridGetElevationAt(x, y) == gPlayerFacingPosition.elevation)
2018-06-16 00:45:48 +02:00
{
u8 tileArrayId = ((sHyperCutStruct[i].y * 5) + 12) + (sHyperCutStruct[i].x);
2018-06-16 00:45:48 +02:00
tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
if (MetatileBehavior_IsPokeGrass(tileBehavior) == TRUE
|| MetatileBehavior_IsAshGrass(tileBehavior) == TRUE)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
gPostMenuFieldCallback = FieldCallback_CutGrass;
sHyperCutTiles[tileArrayId] = TRUE;
2018-06-16 00:45:48 +02:00
ret = TRUE;
}
else
{
if (MetatileBehavior_IsCuttableGrass(tileBehavior) == TRUE)
sHyperCutTiles[tileArrayId] = TRUE;
2018-06-16 00:45:48 +02:00
}
}
}
}
if (ret == TRUE)
{
gFieldCallback2 = FieldCallback_PrepareFadeInFromMenu;
gPostMenuFieldCallback = FieldCallback_CutGrass;
}
}
return ret;
}
}
static void FieldCallback_CutGrass(void)
2018-06-16 00:45:48 +02:00
{
FieldEffectStart(FLDEFF_USE_CUT_ON_GRASS);
gFieldEffectArguments[0] = GetCursorSelectionMonId();
}
bool8 FldEff_UseCutOnGrass(void)
{
u8 taskId = CreateFieldMoveTask();
2018-06-16 00:45:48 +02:00
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)
2018-06-16 00:45:48 +02:00
{
gFieldEffectArguments[0] = GetCursorSelectionMonId();
ScriptContext_SetupScript(EventScript_UseCut);
2018-06-16 00:45:48 +02:00
}
bool8 FldEff_UseCutOnTree(void)
{
u8 taskId = CreateFieldMoveTask();
2018-06-16 00:45:48 +02:00
gTasks[taskId].data[8] = (u32)StartCutTreeFieldEffect >> 16;
gTasks[taskId].data[9] = (u32)StartCutTreeFieldEffect;
IncrementGameStat(GAME_STAT_USED_CUT);
return FALSE;
}
static void StartCutGrassFieldEffect(void)
2018-06-16 00:45:48 +02:00
{
FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_GRASS);
FieldEffectStart(FLDEFF_CUT_GRASS);
}
bool8 FldEff_CutGrass(void)
{
s16 x, y;
2018-06-30 14:26:33 +02:00
u8 i = 0;
2018-06-16 00:45:48 +02:00
2020-08-21 00:02:00 +02:00
PlaySE(SE_M_CUT);
2018-06-30 14:26:33 +02:00
PlayerGetDestCoords(&gPlayerFacingPosition.x, &gPlayerFacingPosition.y);
for (i = 0; i < CUT_HYPER_AREA; i++)
2018-06-16 00:45:48 +02:00
{
if (sHyperCutTiles[i] == TRUE)
2018-06-16 00:45:48 +02:00
{
s8 xAdd = (i % 5) - 2;
s8 yAdd = (i / 5) - 2;
x = xAdd + gPlayerFacingPosition.x;
y = yAdd + gPlayerFacingPosition.y;
SetCutGrassMetatile(x, y);
2021-04-06 11:05:33 +02:00
AllowObjectAtPosTriggerGroundEffects(x, y);
2018-06-16 00:45:48 +02:00
}
}
SetCutGrassMetatiles(gPlayerFacingPosition.x - sTileCountFromPlayer_X, gPlayerFacingPosition.y - (1 + sTileCountFromPlayer_Y));
2018-06-16 00:45:48 +02:00
DrawWholeMapView();
sCutGrassSpriteArrayPtr = AllocZeroed(CUT_SPRITE_ARRAY_COUNT);
2018-06-16 00:45:48 +02:00
// populate sprite ID array
for (i = 0; i < CUT_SPRITE_ARRAY_COUNT; i++)
2018-06-16 00:45:48 +02:00
{
sCutGrassSpriteArrayPtr[i] = CreateSprite(&sSpriteTemplate_CutGrass,
2018-06-16 00:45:48 +02:00
gSprites[gPlayerAvatar.spriteId].oam.x + 8, gSprites[gPlayerAvatar.spriteId].oam.y + 20, 0);
gSprites[sCutGrassSpriteArrayPtr[i]].data[2] = 32 * i;
2018-06-16 00:45:48 +02:00
}
return FALSE;
}
// set map grid metatile depending on x, y
static void SetCutGrassMetatile(s16 x, s16 y)
2018-06-16 00:45:48 +02:00
{
s32 metatileId = MapGridGetMetatileIdAt(x, y);
switch (metatileId)
{
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_LongGrass_Root:
case METATILE_General_LongGrass:
case METATILE_General_TallGrass:
MapGridSetMetatileIdAt(x, y, METATILE_General_Grass);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_General_TallGrass_TreeLeft:
MapGridSetMetatileIdAt(x, y, METATILE_General_Grass_TreeLeft);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_General_TallGrass_TreeRight:
MapGridSetMetatileIdAt(x, y, METATILE_General_Grass_TreeRight);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomLeft:
MapGridSetMetatileIdAt(x, y, METATILE_Fortree_SecretBase_LongGrass_TopLeft);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomMid:
MapGridSetMetatileIdAt(x, y, METATILE_Fortree_SecretBase_LongGrass_TopMid);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomRight:
MapGridSetMetatileIdAt(x, y, METATILE_Fortree_SecretBase_LongGrass_TopRight);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_Lavaridge_NormalGrass:
case METATILE_Lavaridge_AshGrass:
MapGridSetMetatileIdAt(x, y, METATILE_Lavaridge_LavaField);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fallarbor_NormalGrass:
case METATILE_Fallarbor_AshGrass:
MapGridSetMetatileIdAt(x, y, METATILE_Fallarbor_AshField);
2018-06-16 00:45:48 +02:00
break;
2020-06-29 17:41:09 +02:00
case METATILE_General_TallGrass_TreeUp:
MapGridSetMetatileIdAt(x, y, METATILE_General_Grass_TreeUp);
2018-06-16 00:45:48 +02:00
break;
}
}
enum
{
LONG_GRASS_NONE,
LONG_GRASS_FIELD,
LONG_GRASS_BASE_LEFT,
LONG_GRASS_BASE_CENTER,
LONG_GRASS_BASE_RIGHT
2018-06-16 00:45:48 +02:00
};
static u8 GetLongGrassCaseAt(s16 x, s16 y)
2018-06-16 00:45:48 +02:00
{
u16 metatileId = MapGridGetMetatileIdAt(x, y);
2020-06-29 17:41:09 +02:00
if (metatileId == METATILE_General_Grass)
return LONG_GRASS_FIELD;
2020-06-29 17:41:09 +02:00
else if (metatileId == METATILE_Fortree_SecretBase_LongGrass_TopLeft)
return LONG_GRASS_BASE_LEFT;
2020-06-29 17:41:09 +02:00
else if (metatileId == METATILE_Fortree_SecretBase_LongGrass_TopMid)
return LONG_GRASS_BASE_CENTER;
2020-06-29 17:41:09 +02:00
else if (metatileId == METATILE_Fortree_SecretBase_LongGrass_TopRight)
return LONG_GRASS_BASE_RIGHT;
2018-06-16 00:45:48 +02:00
else
return LONG_GRASS_NONE;
2018-06-16 00:45:48 +02:00
}
static void SetCutGrassMetatiles(s16 x, s16 y)
2018-06-16 00:45:48 +02:00
{
s16 i;
s16 lowerY = y + sCutSquareSide;
2018-06-16 00:45:48 +02:00
for (i = 0; i < sCutSquareSide; i++)
2018-06-16 00:45:48 +02:00
{
s16 currentX = x + i;
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(currentX, y) == METATILE_General_LongGrass)
2018-06-16 00:45:48 +02:00
{
switch (GetLongGrassCaseAt(currentX, y + 1))
2018-06-16 00:45:48 +02:00
{
case LONG_GRASS_FIELD:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_Fortree_LongGrass_Root);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_LEFT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomLeft);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_CENTER:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomMid);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_RIGHT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(currentX, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomRight);
2018-06-16 00:45:48 +02:00
break;
}
}
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(currentX, lowerY) == METATILE_General_Grass)
2018-06-16 00:45:48 +02:00
{
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_Fortree_LongGrass_Root)
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_General_Grass);
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_Fortree_SecretBase_LongGrass_BottomLeft)
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_Fortree_SecretBase_LongGrass_TopLeft);
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_Fortree_SecretBase_LongGrass_BottomMid)
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_Fortree_SecretBase_LongGrass_TopMid);
if (MapGridGetMetatileIdAt(currentX, lowerY + 1) == METATILE_Fortree_SecretBase_LongGrass_BottomRight)
MapGridSetMetatileIdAt(currentX, lowerY + 1, METATILE_Fortree_SecretBase_LongGrass_TopRight);
2018-06-16 00:45:48 +02:00
}
}
if (sCutSquareSide == CUT_HYPER_SIDE)
2018-06-16 00:45:48 +02:00
{
HandleLongGrassOnHyper(0, x, y);
HandleLongGrassOnHyper(1, x, y);
2018-06-16 00:45:48 +02:00
}
}
static void HandleLongGrassOnHyper(u8 caseId, s16 x, s16 y)
2018-06-16 00:45:48 +02:00
{
s16 newX;
bool8 arr[3];
if (caseId == 0)
{
arr[0] = sHyperCutTiles[5];
arr[1] = sHyperCutTiles[10];
arr[2] = sHyperCutTiles[15];
2018-06-16 00:45:48 +02:00
newX = x;
}
else if (caseId == 1)
{
arr[0] = sHyperCutTiles[9];
arr[1] = sHyperCutTiles[14];
arr[2] = sHyperCutTiles[19];
2018-06-16 00:45:48 +02:00
newX = x + 4;
}
else // invalid case
{
return;
}
if (arr[0] == TRUE)
{
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_Fortree_LongGrass_Root)
MapGridSetMetatileIdAt(newX, y + 3, METATILE_General_Grass);
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_Fortree_SecretBase_LongGrass_BottomLeft)
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_TopLeft);
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_Fortree_SecretBase_LongGrass_BottomMid)
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_TopMid);
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_Fortree_SecretBase_LongGrass_BottomRight)
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_TopRight);
2018-06-16 00:45:48 +02:00
}
if (arr[1] == TRUE)
{
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(newX, y + 2) == METATILE_General_LongGrass)
2018-06-16 00:45:48 +02:00
{
switch (GetLongGrassCaseAt(newX, y + 3))
2018-06-16 00:45:48 +02:00
{
case LONG_GRASS_FIELD:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_LongGrass_Root);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_LEFT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_BottomLeft);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_CENTER:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_BottomMid);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_RIGHT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 3, METATILE_Fortree_SecretBase_LongGrass_BottomRight);
2018-06-16 00:45:48 +02:00
break;
}
}
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_Fortree_LongGrass_Root)
MapGridSetMetatileIdAt(newX, y + 4, METATILE_General_Grass);
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_Fortree_SecretBase_LongGrass_BottomLeft)
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_TopLeft);
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_Fortree_SecretBase_LongGrass_BottomMid)
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_TopMid);
if (MapGridGetMetatileIdAt(newX, y + 4) == METATILE_Fortree_SecretBase_LongGrass_BottomRight)
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_TopRight);
2018-06-16 00:45:48 +02:00
}
if (arr[2] == TRUE)
{
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(newX, y + 3) == METATILE_General_LongGrass)
2018-06-16 00:45:48 +02:00
{
switch (GetLongGrassCaseAt(newX, y + 4))
2018-06-16 00:45:48 +02:00
{
case LONG_GRASS_FIELD:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_LongGrass_Root);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_LEFT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_BottomLeft);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_CENTER:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_BottomMid);
2018-06-16 00:45:48 +02:00
break;
case LONG_GRASS_BASE_RIGHT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(newX, y + 4, METATILE_Fortree_SecretBase_LongGrass_BottomRight);
2018-06-16 00:45:48 +02:00
break;
}
}
}
}
static void CutGrassSpriteCallback1(struct Sprite *sprite)
2018-06-16 00:45:48 +02:00
{
sprite->data[0] = 8;
sprite->data[1] = 0;
sprite->data[3] = 0;
sprite->callback = CutGrassSpriteCallback2;
}
static void CutGrassSpriteCallback2(struct Sprite *sprite)
2018-06-16 00:45:48 +02:00
{
2021-07-07 15:11:52 +02:00
sprite->x2 = Sin(sprite->data[2], sprite->data[0]);
sprite->y2 = Cos(sprite->data[2], sprite->data[0]);
2018-06-16 00:45:48 +02:00
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]++;
2018-06-16 00:45:48 +02:00
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);
ScriptUnfreezeObjectEvents();
UnlockPlayerFieldControls();
if (IsMewPlayingHideAndSeek() == TRUE)
ScriptContext_SetupScript(FarawayIsland_Interior_EventScript_HideMewWhenGrassCut);
}
2018-12-28 18:18:23 +01:00
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:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_LongGrass_Root);
break;
case LONG_GRASS_BASE_LEFT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomLeft);
break;
case LONG_GRASS_BASE_CENTER:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomMid);
break;
case LONG_GRASS_BASE_RIGHT:
2020-06-29 17:41:09 +02:00
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_BottomRight);
break;
}
}
}
2018-12-28 18:18:23 +01:00
void FixLongGrassMetatilesWindowBottom(s16 x, s16 y)
{
2020-06-29 17:41:09 +02:00
if (MapGridGetMetatileIdAt(x, y) == METATILE_General_Grass)
{
u8 metatileBehavior = MapGridGetMetatileBehaviorAt(x, y + 1);
if (MetatileBehavior_IsLongGrassSouthEdge(metatileBehavior))
{
s32 metatileId = MapGridGetMetatileIdAt(x, y + 1);
switch (metatileId)
{
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_LongGrass_Root:
MapGridSetMetatileIdAt(x, y + 1, METATILE_General_Grass);
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomLeft:
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_TopLeft);
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomMid:
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_TopMid);
break;
2020-06-29 17:41:09 +02:00
case METATILE_Fortree_SecretBase_LongGrass_BottomRight:
MapGridSetMetatileIdAt(x, y + 1, METATILE_Fortree_SecretBase_LongGrass_TopRight);
break;
}
}
}
}
static void StartCutTreeFieldEffect(void)
{
2020-08-21 00:02:00 +02:00
PlaySE(SE_M_CUT);
FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_TREE);
ScriptContext_Enable();
}