pokeplatinum/src/map_object_move.c

1064 lines
34 KiB
C

#include "map_object_move.h"
#include <nitro.h>
#include <string.h>
#include "generated/movement_types.h"
#include "struct_decls/map_object.h"
#include "struct_decls/map_object_manager.h"
#include "field/field_system.h"
#include "overlay005/ov5_021ECC20.h"
#include "overlay005/ov5_021F134C.h"
#include "overlay005/ov5_021F17B8.h"
#include "overlay005/ov5_021F1CC8.h"
#include "overlay005/ov5_021F2A7C.h"
#include "overlay005/ov5_021F2BD0.h"
#include "overlay005/ov5_021F2D20.h"
#include "overlay005/ov5_021F3284.h"
#include "overlay005/ov5_021F348C.h"
#include "overlay005/ov5_021F37A8.h"
#include "overlay005/ov5_021F3A50.h"
#include "overlay005/struct_ov5_021ECD10.h"
#include "map_object.h"
#include "map_tile_behavior.h"
#include "terrain_collision_manager.h"
#include "unk_020655F4.h"
#include "unk_020673B8.h"
#define sinkInDeepSnowDistance -12
#define sinkInDeeperSnowDistance -14
#define sinkInDeepestSnowDistance -16
#define sinkInMudDistance -12
#define sinkInDeepMudDistance -14
static int sub_02063478(const MapObject *mapObj);
static void sub_020634DC(MapObject *mapObj);
static void sub_020634F4(MapObject *mapObj);
static void MapObject_StartMove(MapObject *mapObj);
static void sub_0206353C(MapObject *mapObj);
static void MapObject_EndMove(MapObject *mapObj);
static void sub_020635AC(MapObject *mapObj);
static void sub_0206363C(MapObject *mapObj);
static void sub_020636F0(MapObject *mapObj);
static void sub_0206375C(MapObject *mapObj);
static void sub_020637D4(MapObject *mapObj);
static void MapObject_SinkIntoTerrain(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063964(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_0206397C(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063994(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063A30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063A64(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063A70(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063A78(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063B20(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063BB4(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C00(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C18(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C48(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C60(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063C94(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063CC8(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063CFC(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063D30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void sub_02063DA8(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static void MapObject_DetermineElevatedBridgeStatus(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *unused);
static void MapObject_EmptyFunction(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3);
static BOOL (*const Unk_020EE76C[4])(u8);
static BOOL (*const Unk_020EE77C[4])(u8);
void MapObject_InitMove(MapObject *mapObj)
{
sub_02062B00(mapObj);
sub_020673B8(mapObj);
}
void MapObject_Move(MapObject *mapObj)
{
if (MapObject_CheckManagerStatus(mapObj, (1 << 1))) {
return;
}
sub_020634DC(mapObj);
sub_020634F4(mapObj);
MapObject_StartMove(mapObj);
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_4)) {
MapObject_DoMovementAction(mapObj);
} else if (MapObject_IsMovementPaused(mapObj) == FALSE && sub_02063478(mapObj) == TRUE && sub_020673C0(mapObj) == FALSE) {
sub_02062B14(mapObj);
}
sub_0206353C(mapObj);
MapObject_EndMove(mapObj);
}
static BOOL sub_02063478(const MapObject *mapObj)
{
if (MapObject_IsMoving(mapObj) == TRUE) {
return TRUE;
}
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_12 | MAP_OBJ_STATUS_11) == FALSE) {
return TRUE;
} else if (MapObject_GetMovementType(mapObj) == 0x32) {
return TRUE;
}
u32 status = MapObject_GetStatus(mapObj);
if (status & (1 << 12) && (status & (1 << 23)) == FALSE) {
return FALSE;
}
if (status & (1 << 11) && sub_02062FDC(mapObj) == FALSE) {
return FALSE;
}
return TRUE;
}
static void sub_020634DC(MapObject *mapObj)
{
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_12)) {
MapObject_RecalculateObjectHeight(mapObj);
}
}
static void sub_020634F4(MapObject *mapObj)
{
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_11) && MapObject_SetTileBehaviors(mapObj) == TRUE) {
MapObject_SetStartMovement(mapObj);
}
}
static void MapObject_StartMove(MapObject *mapObj)
{
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_START_MOVEMENT)) {
sub_020635AC(mapObj);
}
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_START_MOVEMENT | MAP_OBJ_STATUS_START_JUMP);
}
static void sub_0206353C(MapObject *mapObj)
{
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_START_JUMP)) {
sub_020636F0(mapObj);
} else if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_START_MOVEMENT)) {
sub_0206363C(mapObj);
}
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_START_MOVEMENT | MAP_OBJ_STATUS_START_JUMP);
}
static void MapObject_EndMove(MapObject *mapObj)
{
if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_END_JUMP)) {
sub_020637D4(mapObj);
} else if (MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_END_MOVEMENT)) {
sub_0206375C(mapObj);
}
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_END_MOVEMENT | MAP_OBJ_STATUS_END_JUMP);
}
static void sub_020635AC(MapObject *mapObj)
{
MapObject_SetTileBehaviors(mapObj);
if (sub_02062DFC(mapObj) == TRUE) {
u8 currTileBehavior = MapObject_GetCurrTileBehavior(mapObj);
u8 prevTileBehavior = MapObject_GetPrevTileBehavior(mapObj);
const UnkStruct_ov5_021ECD10 *v2 = ov5_021ECD04(mapObj);
MapObject_DetermineElevatedBridgeStatus(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063964(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A70(mapObj, currTileBehavior, prevTileBehavior, v2);
MapObject_SinkIntoTerrain(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C00(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063D30(mapObj, currTileBehavior, prevTileBehavior, v2);
}
}
static void sub_0206363C(MapObject *mapObj)
{
MapObject_SetTileBehaviors(mapObj);
if (sub_02062DFC(mapObj) == TRUE) {
u8 currTileBehavior = MapObject_GetCurrTileBehavior(mapObj);
u8 prevTileBehavior = MapObject_GetPrevTileBehavior(mapObj);
const UnkStruct_ov5_021ECD10 *v2 = ov5_021ECD04(mapObj);
MapObject_DetermineElevatedBridgeStatus(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_0206397C(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063994(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A78(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C18(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C48(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C60(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063CC8(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063D30(mapObj, currTileBehavior, prevTileBehavior, v2);
MapObject_EmptyFunction(mapObj, currTileBehavior, prevTileBehavior, v2);
}
}
static void sub_020636F0(MapObject *mapObj)
{
MapObject_SetTileBehaviors(mapObj);
if (sub_02062DFC(mapObj) == TRUE) {
u8 currTileBehavior = MapObject_GetCurrTileBehavior(mapObj);
u8 prevTileBehavior = MapObject_GetPrevTileBehavior(mapObj);
const UnkStruct_ov5_021ECD10 *v2 = ov5_021ECD04(mapObj);
MapObject_DetermineElevatedBridgeStatus(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A78(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063D30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A64(mapObj, currTileBehavior, prevTileBehavior, v2);
MapObject_EmptyFunction(mapObj, currTileBehavior, prevTileBehavior, v2);
}
}
static void sub_0206375C(MapObject *mapObj)
{
MapObject_SetTileBehaviors(mapObj);
if (sub_02062DFC(mapObj) == TRUE) {
u8 currTileBehavior = MapObject_GetCurrTileBehavior(mapObj);
u8 prevTileBehavior = MapObject_GetPrevTileBehavior(mapObj);
const UnkStruct_ov5_021ECD10 *v2 = ov5_021ECD04(mapObj);
MapObject_SinkIntoTerrain(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C94(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063CFC(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063DA8(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063B20(mapObj, currTileBehavior, prevTileBehavior, v2);
}
}
static void sub_020637D4(MapObject *mapObj)
{
MapObject_SetTileBehaviors(mapObj);
if (sub_02062DFC(mapObj) == TRUE) {
u8 currTileBehavior = MapObject_GetCurrTileBehavior(mapObj);
u8 prevTileBehavior = MapObject_GetPrevTileBehavior(mapObj);
const UnkStruct_ov5_021ECD10 *v2 = ov5_021ECD04(mapObj);
MapObject_SinkIntoTerrain(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063C94(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063CFC(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063A30(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063DA8(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063B20(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_0206397C(mapObj, currTileBehavior, prevTileBehavior, v2);
sub_02063BB4(mapObj, currTileBehavior, prevTileBehavior, v2);
}
}
static void MapObject_SinkIntoTerrain(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (MapObject_CheckFlagDoNotSinkIntoTerrain(mapObj) == FALSE) {
if (TileBehavior_IsDeepMud(currTileBehavior) == TRUE || TileBehavior_IsDeepMudWithGrass(currTileBehavior) == TRUE) {
VecFx32 spriteOffset = { 0, FX32_ONE * sinkInDeepMudDistance, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
return;
}
if (TileBehavior_IsMud(currTileBehavior) == TRUE || TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE) {
VecFx32 spriteOffset = { 0, FX32_ONE * sinkInMudDistance, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
return;
}
if (TileBehavior_IsDeepestSnow(currTileBehavior) == TRUE) {
VecFx32 spriteOffset = { 0, FX32_ONE * sinkInDeepestSnowDistance, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
return;
}
if (TileBehavior_IsDeeperSnow(currTileBehavior) == TRUE) {
VecFx32 spriteOffset = { 0, FX32_ONE * sinkInDeeperSnowDistance, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
return;
}
if (TileBehavior_IsDeepSnow(currTileBehavior) == TRUE) {
VecFx32 spriteOffset = { 0, FX32_ONE * sinkInDeepSnowDistance, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
return;
}
}
VecFx32 spriteOffset = { 0, 0, 0 };
MapObject_SetSpriteTerrainOffset(mapObj, &spriteOffset);
}
static void sub_02063964(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsTallGrass(currTileBehavior) == TRUE) {
ov5_021F2EA4(mapObj, 0);
}
}
static void sub_0206397C(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsTallGrass(currTileBehavior) == TRUE) {
ov5_021F2EA4(mapObj, 1);
}
}
static void sub_02063994(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (param3->unk_04_6 == 0) {
return;
}
if (TileBehavior_IsSnowWithShadows(prevTileBehavior) == TRUE) {
if (param3->unk_04_6 == 1) {
ov5_021F1EBC(mapObj);
} else if (param3->unk_04_6 == 2) {
ov5_021F1EC8(mapObj);
}
}
if (MapObject_IsOnSand(mapObj, prevTileBehavior) == TRUE) {
if (param3->unk_04_6 == 1) {
ov5_021F1E8C(mapObj);
} else if (param3->unk_04_6 == 2) {
ov5_021F1E98(mapObj);
}
return;
}
if (TileBehavior_IsDeeperSnow(prevTileBehavior) == TRUE
|| TileBehavior_IsDeepestSnow(prevTileBehavior) == TRUE
|| TileBehavior_IsDeepSnow(prevTileBehavior)) {
ov5_021F1EB0(mapObj);
return;
}
if (MapObject_IsOnShallowSnow(mapObj, prevTileBehavior) == TRUE) {
ov5_021F1EA4(mapObj);
return;
}
}
static void sub_02063A30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsShallowWater(currTileBehavior) == TRUE) {
if (sub_02062EC8(mapObj) == FALSE) {
ov5_021F331C(mapObj, 1);
sub_02062EAC(mapObj, 1);
}
} else {
sub_02062EAC(mapObj, 0);
}
}
static void sub_02063A64(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
sub_02062EAC(mapObj, 0);
}
static void sub_02063A70(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
sub_02063A78(mapObj, currTileBehavior, prevTileBehavior, param3);
}
static void sub_02063A78(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
const MapObjectManager *mapObjMan = MapObject_MapObjectManager(mapObj);
if (sub_02062CE4(mapObjMan) == FALSE) {
return;
}
if (param3->unk_04_4 == 0) {
return;
}
if (TileBehavior_IsTallGrass(currTileBehavior) == TRUE
|| TileBehavior_IsVeryTallGrass(currTileBehavior) == TRUE
|| MapObject_IsOnWater(mapObj, currTileBehavior) == TRUE
|| TileBehavior_IsPuddle(currTileBehavior) == TRUE
|| TileBehavior_IsShallowWater(currTileBehavior) == TRUE
|| MapObject_IsOnSnow(mapObj, currTileBehavior) == TRUE
|| TileBehavior_IsMud(currTileBehavior) == TRUE
|| TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE
|| TileBehavior_IsReflective(currTileBehavior)) {
MapObject_SetStatusFlagOn(mapObj, MAP_OBJ_STATUS_HIDE_SHADOW);
} else {
if (!MapObject_CheckStatus(mapObj, MAP_OBJ_STATUS_SHOW_SHADOW)) {
ov5_021F1570(mapObj);
MapObject_SetStatusFlagOn(mapObj, MAP_OBJ_STATUS_SHOW_SHADOW);
}
}
}
static void sub_02063B20(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
const MapObjectManager *mapObjMan = MapObject_MapObjectManager(mapObj);
if (sub_02062CE4(mapObjMan) == FALSE) {
return;
}
if (param3->unk_04_4 == 0) {
return;
}
if (TileBehavior_IsTallGrass(currTileBehavior) == TRUE
|| TileBehavior_IsVeryTallGrass(currTileBehavior) == TRUE
|| MapObject_IsOnWater(mapObj, currTileBehavior) == TRUE
|| TileBehavior_IsPuddle(currTileBehavior) == TRUE
|| TileBehavior_IsShallowWater(currTileBehavior) == TRUE
|| MapObject_IsOnSnow(mapObj, currTileBehavior) == TRUE
|| TileBehavior_IsMud(currTileBehavior) == TRUE
|| TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE
|| TileBehavior_IsReflective(currTileBehavior)) {
MapObject_SetStatusFlagOn(mapObj, MAP_OBJ_STATUS_HIDE_SHADOW);
} else {
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_HIDE_SHADOW);
}
}
static void sub_02063BB4(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (MapObject_IsOnWater(mapObj, currTileBehavior) == TRUE
|| TileBehavior_IsShallowWater(currTileBehavior) == TRUE
|| TileBehavior_IsIce(currTileBehavior) == TRUE
|| TileBehavior_IsMud(currTileBehavior) == TRUE
|| TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE
|| MapObject_IsOnSnow(mapObj, currTileBehavior) == TRUE) {
return;
}
ov5_021F3638(mapObj);
}
static void sub_02063C00(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsVeryTallGrass(currTileBehavior) == TRUE) {
ov5_021F3844(mapObj, 0);
}
}
static void sub_02063C18(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsVeryTallGrass(currTileBehavior) == TRUE) {
ov5_021F3844(mapObj, 1);
}
}
static void sub_02063C30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE) {
ov5_021F3AEC(mapObj, 0);
}
}
static void sub_02063C48(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsMudWithGrass(currTileBehavior) == TRUE) {
ov5_021F3AEC(mapObj, 1);
}
}
static void sub_02063C60(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsPuddle(prevTileBehavior) == TRUE) {
ov5_021F2AE4(mapObj, MapObject_GetXPrev(mapObj), MapObject_GetYPrev(mapObj), MapObject_GetZPrev(mapObj));
}
}
static void sub_02063C94(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsPuddle(currTileBehavior) == TRUE) {
ov5_021F2AE4(mapObj, MapObject_GetX(mapObj), MapObject_GetY(mapObj), MapObject_GetZ(mapObj));
}
}
static void sub_02063CC8(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsMud(prevTileBehavior) == TRUE) {
ov5_021F2C38(mapObj, MapObject_GetXPrev(mapObj), MapObject_GetYPrev(mapObj), MapObject_GetZPrev(mapObj));
}
}
static void sub_02063CFC(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (TileBehavior_IsMud(currTileBehavior) == TRUE) {
ov5_021F2C38(mapObj, MapObject_GetX(mapObj), MapObject_GetY(mapObj), MapObject_GetZ(mapObj));
}
}
static void sub_02063D30(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (param3->unk_04_10 == 0) {
return;
}
if (sub_02062F64(mapObj) == FALSE) {
u8 tileBehavior = GetNullTileBehaviorID();
if (TileBehavior_HasReflectiveSurface(currTileBehavior) == TRUE) {
tileBehavior = currTileBehavior;
} else {
u8 southTileBehavior = MapObject_GetTileBehaviorFromDir(mapObj, DIR_SOUTH);
if (TileBehavior_HasReflectiveSurface(southTileBehavior) == TRUE) {
tileBehavior = southTileBehavior;
}
}
if (tileBehavior != GetNullTileBehaviorID()) {
int v2;
sub_02062F48(mapObj, 1);
if (TileBehavior_IsReflective(tileBehavior) == TRUE) {
v2 = 2;
} else if (TileBehavior_IsPuddle(tileBehavior) == TRUE) {
v2 = 0;
} else {
v2 = 1;
}
ov5_021F1800(mapObj, v2);
}
}
}
static void sub_02063DA8(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
if (param3->unk_04_10 == 0 || sub_02062F64(mapObj) == FALSE) {
return;
}
u8 southTileBehavior = MapObject_GetTileBehaviorFromDir(mapObj, DIR_SOUTH);
if (TileBehavior_HasReflectiveSurface(southTileBehavior) == FALSE) {
sub_02062F48(mapObj, 0);
}
}
static void MapObject_DetermineElevatedBridgeStatus(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *unused)
{
if (TileBehavior_IsBridgeStart(currTileBehavior) == TRUE) {
MapObject_SetElevatedBridgeStatus(mapObj, TRUE);
} else if (MapObject_IsStatusOnElevatedBridge(mapObj) == TRUE && TileBehavior_IsBridge(currTileBehavior) == FALSE) {
MapObject_SetElevatedBridgeStatus(mapObj, FALSE);
}
}
static void MapObject_EmptyFunction(MapObject *mapObj, u8 currTileBehavior, u8 prevTileBehavior, const UnkStruct_ov5_021ECD10 *param3)
{
return;
}
u32 sub_02063E18(const MapObject *mapObj, const VecFx32 *pos, int x, int y, int z, int dir)
{
u32 v0 = 0;
if (MapObject_IsOutOfRange(mapObj, x, y, z) == TRUE) {
v0 |= (1 << 0);
}
s8 v1;
FieldSystem *fieldSystem = MapObject_FieldSystem(mapObj);
if (TerrainCollisionManager_WillMapObjectCollide(fieldSystem, pos, x, z, &v1) == TRUE) {
v0 |= (1 << 1);
if (v1 != 0) {
v0 |= (1 << 3);
}
}
if (sub_02064004(mapObj, x, z, dir) == TRUE) {
v0 |= (1 << 1);
}
if (sub_02063F00(mapObj, x, y, z) == TRUE) {
v0 |= (1 << 2);
}
return v0;
}
u32 sub_02063E94(const MapObject *mapObj, int x, int y, int z, int dir)
{
VecFx32 pos;
MapObject_GetPosPtr(mapObj, &pos);
return sub_02063E18(mapObj, &pos, x, y, z, dir);
}
u32 sub_02063EBC(const MapObject *mapObj, int dir)
{
int x = MapObject_GetX(mapObj) + MapObject_GetDxFromDir(dir);
int y = MapObject_GetY(mapObj);
int z = MapObject_GetZ(mapObj) + MapObject_GetDzFromDir(dir);
return sub_02063E94(mapObj, x, y, z, dir);
}
int sub_02063F00(const MapObject *mapObj, int x, int y, int z)
{
int maxObjects, objX, objZ;
const MapObjectManager *mapObjMan = MapObject_MapObjectManager(mapObj);
const MapObject *v4 = MapObjectMan_GetMapObjectConst(mapObjMan);
maxObjects = MapObjectMan_GetMaxObjects(mapObjMan);
do {
if (v4 != mapObj
&& MapObject_CheckStatus(v4, MAP_OBJ_STATUS_0)
&& !MapObject_CheckStatus(v4, MAP_OBJ_STATUS_18)) {
objX = MapObject_GetX(v4);
objZ = MapObject_GetZ(v4);
if (objX == x && objZ == z) {
int objY = MapObject_GetY(v4);
int v6 = objY - y;
if (v6 < 0) {
v6 = -v6;
}
if (v6 < (1 * 2)) {
return TRUE;
}
}
objX = MapObject_GetXPrev(v4);
objZ = MapObject_GetZPrev(v4);
if (objX == x && objZ == z) {
int objY = MapObject_GetY(v4);
int v8 = objY - y;
if (v8 < 0) {
v8 = -v8;
}
if (v8 < (1 * 2)) {
return TRUE;
}
}
}
sub_02062880(&v4);
maxObjects--;
} while (maxObjects);
return FALSE;
}
int MapObject_IsOutOfRange(const MapObject *mapObj, int x, int y, int z)
{
int initialPos, movementRange, minPos, maxPos;
initialPos = MapObject_GetXInitial(mapObj);
movementRange = MapObject_GetMovementRangeX(mapObj);
if (movementRange != -1) {
minPos = initialPos - movementRange;
maxPos = initialPos + movementRange;
if (minPos > x || maxPos < x) {
return TRUE;
}
}
initialPos = MapObject_GetZInitial(mapObj);
movementRange = MapObject_GetMovementRangeZ(mapObj);
if (movementRange != -1) {
minPos = initialPos - movementRange;
maxPos = initialPos + movementRange;
if (minPos > z || maxPos < z) {
return TRUE;
}
}
return FALSE;
}
int sub_02064004(const MapObject *mapObj, int x, int z, int dir)
{
if (sub_02062FDC(mapObj) == FALSE) {
FieldSystem *fieldSystem = MapObject_FieldSystem(mapObj);
u8 v1 = MapObject_GetCurrTileBehavior(mapObj);
u8 v2 = TerrainCollisionManager_GetTileBehavior(fieldSystem, x, z);
if (v2 == GetNullTileBehaviorID()) {
return TRUE;
}
if (Unk_020EE76C[dir](v1) == TRUE || Unk_020EE77C[dir](v2) == TRUE) {
return TRUE;
}
}
return FALSE;
}
static BOOL (*const Unk_020EE76C[4])(u8) = {
TileBehavior_BlocksMovementNorthward,
TileBehavior_BlocksMovementSouthward,
TileBehavior_BlocksMovementWestward,
TileBehavior_BlocksMovementEastward
};
static BOOL (*const Unk_020EE77C[4])(u8) = {
TileBehavior_BlocksMovementSouthward,
TileBehavior_BlocksMovementNorthward,
TileBehavior_BlocksMovementEastward,
TileBehavior_BlocksMovementWestward
};
int MapObject_IsOnWater(MapObject *mapObj, u32 tileBehavior)
{
if (TileBehavior_IsBridgeOverWater(tileBehavior)) {
if (!MapObject_IsStatusOnElevatedBridge(mapObj)) {
return TRUE;
}
} else if (TileBehavior_IsSurfable(tileBehavior)) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnSand(MapObject *mapObj, u32 tileBehavior)
{
if (TileBehavior_IsBridgeOverSand(tileBehavior)) {
if (!MapObject_IsStatusOnElevatedBridge(mapObj)) {
return TRUE;
}
} else if (TileBehavior_IsSand(tileBehavior)) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnSnow(MapObject *mapObj, u32 tileBehavior)
{
if (TileBehavior_IsBridgeOverSnow(tileBehavior)) {
if (!MapObject_IsStatusOnElevatedBridge(mapObj)) {
return TRUE;
}
} else if (TileBehavior_IsSnow(tileBehavior)) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnShallowSnow(MapObject *mapObj, u32 tileBehavior)
{
if (TileBehavior_IsBridgeOverSnow(tileBehavior)) {
if (!MapObject_IsStatusOnElevatedBridge(mapObj)) {
return TRUE;
}
} else if (TileBehavior_IsShallowSnow(tileBehavior)) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnElevatedBridge(MapObject *mapObj, u32 tileBehavior)
{
if (MapObject_IsStatusOnElevatedBridge(mapObj) == TRUE && TileBehavior_IsBridge(tileBehavior) == TRUE) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnBikeBridgeNorthSouth(MapObject *mapObj, u32 tileBehavior)
{
if (MapObject_IsStatusOnElevatedBridge(mapObj) == TRUE && TileBehavior_IsBikeBridgeNorthSouth(tileBehavior) == TRUE) {
return TRUE;
}
return FALSE;
}
int MapObject_IsOnBikeBridgeEastWest(MapObject *mapObj, u32 tileBehavior)
{
if (MapObject_IsStatusOnElevatedBridge(mapObj) == TRUE && TileBehavior_IsBikeBridgeEastWest(tileBehavior) == TRUE) {
return TRUE;
}
return FALSE;
}
static const int sMapObjectDxDir[] = {
[DIR_NORTH] = 0,
[DIR_SOUTH] = 0,
[DIR_WEST] = -1,
[DIR_EAST] = 1
};
static const int UNUSED_GPosY_Dir4AddTbl[] = {
0,
0,
0,
0
};
static const int sMapObjectDzDir[] = {
[DIR_NORTH] = -1,
[DIR_SOUTH] = 1,
[DIR_WEST] = 0,
[DIR_EAST] = 0
};
int MapObject_GetDxFromDir(int dir)
{
return sMapObjectDxDir[dir];
}
int MapObject_GetDzFromDir(int dir)
{
return sMapObjectDzDir[dir];
}
void MapObject_StepDir(MapObject *mapObj, int dir)
{
MapObject_SetXPrev(mapObj, MapObject_GetX(mapObj));
MapObject_SetYPrev(mapObj, MapObject_GetY(mapObj));
MapObject_SetZPrev(mapObj, MapObject_GetZ(mapObj));
MapObject_AddX(mapObj, MapObject_GetDxFromDir(dir));
MapObject_AddY(mapObj, 0);
MapObject_AddZ(mapObj, MapObject_GetDzFromDir(dir));
}
void MapObject_UpdateCoords(MapObject *mapObj)
{
MapObject_SetXPrev(mapObj, MapObject_GetX(mapObj));
MapObject_SetYPrev(mapObj, MapObject_GetY(mapObj));
MapObject_SetZPrev(mapObj, MapObject_GetZ(mapObj));
}
u32 MapObject_GetTileBehaviorFromDir(MapObject *mapObj, int dir)
{
int x = MapObject_GetX(mapObj) + MapObject_GetDxFromDir(dir);
int z = MapObject_GetZ(mapObj) + MapObject_GetDzFromDir(dir);
FieldSystem *fieldSystem = MapObject_FieldSystem(mapObj);
u8 tileBehavior = TerrainCollisionManager_GetTileBehavior(fieldSystem, x, z);
return tileBehavior;
}
void MapObject_AddVecToPos(MapObject *mapObj, const VecFx32 *vec)
{
VecFx32 pos;
MapObject_GetPosPtr(mapObj, &pos);
pos.x += vec->x;
pos.y += vec->y;
pos.z += vec->z;
MapObject_SetPos(mapObj, &pos);
}
void MapObject_MovePosInDir(MapObject *mapObj, int dir, fx32 distance)
{
VecFx32 pos;
MapObject_GetPosPtr(mapObj, &pos);
switch (dir) {
case DIR_NORTH:
pos.z -= distance;
break;
case DIR_SOUTH:
pos.z += distance;
break;
case DIR_WEST:
pos.x -= distance;
break;
case DIR_EAST:
pos.x += distance;
break;
}
MapObject_SetPos(mapObj, &pos);
}
int MapObject_RecalculateObjectHeight(MapObject *mapObj)
{
VecFx32 pos, updatedPos;
MapObject_GetPosPtr(mapObj, &pos);
updatedPos = pos;
if (MapObject_IsHeightCalculationDisabled(mapObj) == TRUE) {
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_12);
return FALSE;
}
int dynamicHeightCalculationEnabled = MapObject_IsDynamicHeightCalculationEnabled(mapObj);
FieldSystem *fieldSystem = MapObject_FieldSystem(mapObj);
int heightUpdated = MapObject_RecalculatePositionHeightEx(fieldSystem, &updatedPos, dynamicHeightCalculationEnabled);
if (heightUpdated == TRUE) {
pos.y = updatedPos.y;
MapObject_SetPos(mapObj, &pos);
MapObject_SetYPrev(mapObj, MapObject_GetY(mapObj));
MapObject_SetY(mapObj, (((pos.y) >> 3) / FX32_ONE));
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_12);
} else {
MapObject_SetStatusFlagOn(mapObj, MAP_OBJ_STATUS_12);
}
return heightUpdated;
}
int MapObject_SetTileBehaviors(MapObject *mapObj)
{
u8 prevTileBehavior = GetNullTileBehaviorID();
u8 currTileBehavior = prevTileBehavior;
if (sub_02062FDC(mapObj) == FALSE) {
int x = MapObject_GetXPrev(mapObj);
int z = MapObject_GetZPrev(mapObj);
FieldSystem *fieldSystem = MapObject_FieldSystem(mapObj);
prevTileBehavior = TerrainCollisionManager_GetTileBehavior(fieldSystem, x, z);
x = MapObject_GetX(mapObj);
z = MapObject_GetZ(mapObj);
currTileBehavior = TerrainCollisionManager_GetTileBehavior(fieldSystem, x, z);
}
MapObject_SetPrevTileBehavior(mapObj, prevTileBehavior);
MapObject_SetCurrTileBehavior(mapObj, currTileBehavior);
if (TileBehavior_IsNull(currTileBehavior) == TRUE) {
MapObject_SetStatusFlagOn(mapObj, MAP_OBJ_STATUS_11);
return FALSE;
}
MapObject_SetStatusFlagOff(mapObj, MAP_OBJ_STATUS_11);
return TRUE;
}
void VecFx32_StepDirection(int dir, VecFx32 *vec, fx32 val)
{
switch (dir) {
case DIR_NORTH:
vec->z -= val;
break;
case DIR_SOUTH:
vec->z += val;
break;
case DIR_WEST:
vec->x -= val;
break;
case DIR_EAST:
vec->x += val;
break;
}
}
void VecFx32_SetPosFromMapCoords(int x, int z, VecFx32 *outVec)
{
outVec->x = MAP_OBJECT_COORD_CENTER_TO_FX32(x);
outVec->z = MAP_OBJECT_COORD_CENTER_TO_FX32(z);
}
void sub_02064464(MapObject *mapObj)
{
int movementType = MapObject_GetMovementType(mapObj);
if (movementType == MOVEMENT_TYPE_DISGUISE_SNOW
|| movementType == MOVEMENT_TYPE_DISGUISE_SAND
|| movementType == MOVEMENT_TYPE_DISGUISE_ROCK
|| movementType == MOVEMENT_TYPE_DISGUISE_GRASS) {
sub_02062B14(mapObj);
}
}
static const int sOppositeDirections[] = {
[DIR_NORTH] = DIR_SOUTH,
[DIR_SOUTH] = DIR_NORTH,
[DIR_WEST] = DIR_EAST,
[DIR_EAST] = DIR_WEST
};
int Direction_GetOpposite(int dir)
{
return sOppositeDirections[dir];
}
int sub_02064488(int param0, int param1, int param2, int param3)
{
if (param0 > param2) {
return DIR_WEST;
}
if (param0 < param2) {
return DIR_EAST;
}
if (param1 > param3) {
return DIR_NORTH;
}
return DIR_SOUTH;
}
int MapObject_RecalculatePositionHeight(FieldSystem *fieldSystem, VecFx32 *pos)
{
u8 newObjectHeightSource;
fx32 objectHeight = TerrainCollisionManager_GetHeight(fieldSystem, pos->y, pos->x, pos->z, &newObjectHeightSource);
if (newObjectHeightSource == CALCULATED_HEIGHT_SOURCE_NONE) {
return FALSE;
}
pos->y = objectHeight;
return TRUE;
}
int MapObject_RecalculatePositionHeightEx(FieldSystem *fieldSystem, VecFx32 *pos, int dynamicHeightCalculationEnabled)
{
u8 newObjectHeightSource;
fx32 objectHeight = TerrainCollisionManager_GetHeight(fieldSystem, pos->y, pos->x, pos->z, &newObjectHeightSource);
if (newObjectHeightSource == CALCULATED_HEIGHT_SOURCE_NONE) {
return FALSE;
}
if (newObjectHeightSource == CALCULATED_HEIGHT_SOURCE_DYNAMIC && dynamicHeightCalculationEnabled == FALSE) {
return FALSE;
}
pos->y = objectHeight;
return TRUE;
}