#include "functions.h" #include "message.h" #include "npc.h" #include "hitbox.h" #include "collision.h" typedef struct { u8 unk_0; // u8 u8 unk_0b; // u8 u16 unk_1; // u16 u16 unk_2; // u16 u16 unk_3; u16 unk_4; u16 unk_5; // u16 u16 unk_6; // u16 u16 unk_7; // u16 u16 unk_8; // u16 } UnkHeap; void sub_08060E70(Entity*, u32); u32 sub_08061230(Entity*); u32 sub_08060F80(Entity*); void sub_08060EDC(Entity*); void sub_08061090(Entity*, u32, u32); bool32 sub_08060FD0(Entity*, u32, u32); void sub_08061464(Entity*, u32, u32); void sub_08061120(Entity*, u32, u32, u32); bool32 sub_08061170(Entity*); void sub_08061358(Entity*); void sub_08060E94(Entity*); void sub_08060A00(Entity*); void sub_08061AA0(Entity*); void sub_08061AA8(Entity*); void sub_08061B58(Entity*); void sub_08060AE0(Entity*); void sub_08060B5C(Entity*); void sub_08060BA0(Entity*); void sub_08060D78(Entity*); void sub_08060DD0(Entity*); void sub_08060DF4(Entity*); void sub_08060DFC(Entity*); void sub_08060E34(Entity*); void sub_08061ACC(Entity*); void sub_08061B18(Entity*); u32 PointInsideRadius(s32, s32, s32); extern u8 gUnk_0200D654[]; extern u8 gUnk_02027EB4[]; u32 sub_080611D4(Entity*); extern u32 sub_08079FD4(Entity*, u32); extern void sub_08016AD2(Entity*); bool32 sub_08061630(Entity*, s32, s32, s32); bool32 sub_08061720(Entity*, s32, s32, s32); bool32 sub_080616A8(Entity*, s32, s32, s32); bool32 sub_08061798(Entity*, s32, s32, s32); bool32 sub_08061888(Entity*, s32, s32, s32); bool32 sub_08061978(Entity*, s32, s32, s32); bool32 sub_08061810(Entity*, s32, s32, s32); bool32 sub_08061900(Entity*, s32, s32, s32); bool32 sub_08061A74(u8*, s32, s32, s32); bool32 sub_08061A1C(u8*, s32, s32, s32); bool32 sub_080619F0(u8*, s32, s32, s32); bool32 sub_08061A48(u8*, s32, s32, s32); void sub_08061AFC(Entity*); extern u16* gUnk_0810B660[8]; void CreateZeldaFollower(void) { Entity* npc; if (CheckGlobalFlag(0x1c) != 0) { npc = CreateNPC(ZELDA_FOLLOWER, 0, 0); if (npc != NULL) { CopyPosition(&gPlayerEntity, npc); npc->flags |= ENT_PERSIST; npc->animationState = GetAnimationState(npc); } } } // UNUSED zelda follower, probably because it was too resource heavy void NPC5(Entity* this) { static void (*const gUnk_0810AC1C[])(Entity*) = { sub_08060A00, sub_08061AA0, sub_08061AA8, sub_08061B58, }; gUnk_0810AC1C[this->type](this); } void sub_08060A00(Entity* this) { static void (*const Npc5_Actions[])(Entity*) = { sub_08060AE0, sub_08060B5C, sub_08060BA0, sub_08060D78, sub_08060DD0, sub_08060DF4, sub_08060DFC, sub_08060E34, }; u32 tmp; if ((gPlayerState.jump_status & 0x80) != 0) { if (this->action != 0) { if (((((UnkHeap*)this->myHeap)->unk_0) & 4) == 0) { ((UnkHeap*)this->myHeap)->unk_0 |= 4; ((UnkHeap*)this->myHeap)->unk_5 = (gPlayerEntity.x.HALF.HI & 0xfff0) + 8; ((UnkHeap*)this->myHeap)->unk_6 = (gPlayerEntity.y.HALF.HI & 0xfff0) + 8; } } } if ((this->action == 0) || (this->spriteSettings.draw != 0)) { Npc5_Actions[this->action](this); } if (this->action != 0) { ((UnkHeap*)this->myHeap)->unk_1 = gPlayerEntity.x.HALF.HI; ((UnkHeap*)this->myHeap)->unk_2 = gPlayerEntity.y.HALF.HI; } if (this->field_0x74.HWORD != gRoomControls.room) { this->field_0x74.HWORD = gRoomControls.room; CopyPosition(&gPlayerEntity, this); this->action = 1; this->spriteSettings.draw = 1; this->speed = 0x120; tmp = gRoomControls.scroll_direction; this->animationState = tmp * 2; InitAnimationForceUpdate(this, tmp << 0x19 >> 0x19); // TODO some conversion between u8 and u32? this->frameDuration = (Random() & 0x7f) + 0x80; ((UnkHeap*)this->myHeap)->unk_0 &= 0xfb; } } void sub_08060AE0(Entity* this) { UnkHeap* heapObj; Entity* otherNpc; heapObj = (UnkHeap*)zMalloc(0x14); // TODO UnkHeap struct should have size 0x14? if (heapObj != NULL) { this->myHeap = (u32*)heapObj; heapObj->unk_0b = 0x20; this->action = 1; COLLISION_ON(this); this->animationState &= 3; this->collisionFlags = 7; this->hurtType = 0x48; this->hitType = 0x49; this->flags2 = 3; this->hitbox = (Hitbox*)&gHitbox_0; this->followerFlag &= 0xfe; this->field_0x6c.HALF.LO = 0xff; sub_08060E70(this, this->animationState); otherNpc = CreateNPC(NPC_UNK_5, 2, 0); if (otherNpc != NULL) { otherNpc->parent = this; *(Entity**)&this->field_0x78 = otherNpc; } } } void sub_08060B5C(Entity* this) { if (sub_08061230(this) == 0) { if ((sub_08060F80(this) == 0) && (((GetFacingDirection(this, &gPlayerEntity) + (this->animationState * -4) + 4) & 0x1f)) < 9) { this->action = 2; this->subtimer = 0; return; } sub_08060EDC(this); } } void sub_08060BA0(Entity* this) { Entity* r5; //! @bug: r5 is uninitialized if (sub_08061230(this) != 0) { return; } if ((((UnkHeap*)this->myHeap)->unk_0 & 4) != 0) { if ((((UnkHeap*)this->myHeap)->unk_0 & 8) != 0) { this->speed = 0x1e0; sub_08061120(this, ((UnkHeap*)this->myHeap)->unk_7, ((UnkHeap*)this->myHeap)->unk_8, 0xc); sub_08061170(this); if (EntityWithinDistance(this, ((UnkHeap*)this->myHeap)->unk_7, ((UnkHeap*)this->myHeap)->unk_8, 4) != 0) { ((UnkHeap*)this->myHeap)->unk_0 &= 0xf7; } } else { if (sub_08060FD0(this, ((UnkHeap*)this->myHeap)->unk_5, ((UnkHeap*)this->myHeap)->unk_6) != 0) { if (EntityWithinDistance(this, ((UnkHeap*)this->myHeap)->unk_5, ((UnkHeap*)this->myHeap)->unk_6, 4) != 0) { ((UnkHeap*)this->myHeap)->unk_0 &= 0xfb; this->action = 5; this->direction = r5->direction; this->speed = 0x160; sub_08060E70(this, 8); } else { this->speed = 0x1e0; sub_08061120(this, r5->x.HALF.HI, r5->y.HALF.HI, 0xc); sub_08061170(this); } } else { sub_08061464(this, r5->x.HALF.HI, r5->y.HALF.HI); } } } else { if (sub_08060FD0(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI) != 0) { sub_08061090(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI); sub_08061170(this); ((UnkHeap*)this->myHeap)->unk_0 &= 0xf5; } else { ((UnkHeap*)this->myHeap) = (UnkHeap*)this->myHeap; if ((((UnkHeap*)this->myHeap)->unk_0 & 8) != 0) { this->speed = 0x1e0; sub_08061120(this, ((UnkHeap*)this->myHeap)->unk_7, ((UnkHeap*)this->myHeap)->unk_8, 0xc); sub_08061170(this); if (EntityWithinDistance(this, ((UnkHeap*)this->myHeap)->unk_7, ((UnkHeap*)this->myHeap)->unk_8, 4) != 0) { ((UnkHeap*)this->myHeap)->unk_0 &= 0xf7; } } else { if ((((UnkHeap*)this->myHeap)->unk_0 & 2) == 0) { ((UnkHeap*)this->myHeap)->unk_0 |= 2; ((UnkHeap*)this->myHeap)->unk_3 = ((UnkHeap*)this->myHeap)->unk_1; ((UnkHeap*)this->myHeap)->unk_4 = ((UnkHeap*)this->myHeap)->unk_2; } if (sub_08060FD0(this, ((UnkHeap*)this->myHeap)->unk_3, ((UnkHeap*)this->myHeap)->unk_4) != 0) { this->speed = 0x1e0; sub_08061120(this, ((UnkHeap*)this->myHeap)->unk_3, ((UnkHeap*)this->myHeap)->unk_4, 0xc); sub_08061170(this); if (EntityWithinDistance(this, ((UnkHeap*)this->myHeap)->unk_3, ((UnkHeap*)this->myHeap)->unk_4, 4) != 0) { ((UnkHeap*)this->myHeap)->unk_0 &= 0xfd; } } else { ((UnkHeap*)this->myHeap)->unk_0 &= 0xfd; sub_08061464(this, gPlayerEntity.x.HALF.HI, gPlayerEntity.y.HALF.HI); } } } } if (sub_08060F80(this) != 0) { this->action = 1; ((UnkHeap*)this->myHeap)->unk_0 &= 0xfb; sub_08060E70(this, 0); } } void sub_08060D78(Entity* this) { sub_08061358(this); if (sub_08060F80(this) != 0) { if ((u32)this->animIndex - 0x20 < 0x10) { if ((this->frame & 7) != 0) { this->frameDuration = 1; UpdateAnimationSingleFrame(this); } this->animationState = this->frame & 0x18; this->field_0x6c.HALF.LO = 0xff; } this->action = 1; sub_08060E70(this, 0); } } void sub_08060DD0(Entity* this) { UpdateAnimationSingleFrame(this); if ((this->frame & ANIM_DONE) != 0) { this->action = 1; sub_08060E70(this, 0); } } void sub_08060DF4(Entity* this) { sub_08061170(this); } void sub_08060DFC(Entity* this) { u32 uVar1; LinearMoveUpdate(this); sub_08060E94(this); uVar1 = GravityUpdate(this, Q_8_8(32.0)); if (uVar1 == 0) { this->action = 7; this->collisionLayer = 1; UpdateSpriteForCollisionLayer(this); sub_08060E70(this, 0x1c); } } void sub_08060E34(Entity* this) { UpdateAnimationSingleFrame(this); if ((this->frame & ANIM_DONE) != 0) { this->action = 2; this->animationState = DirectionToAnimationState(GetFacingDirection(this, &gPlayerEntity)) * 2; sub_08060E70(this, 8); } } void sub_08060E70(Entity* this, u32 param) { u32 tmp = param + this->animationState / 2; if (tmp != this->animIndex) { this->field_0x6c.HALF.LO = param; InitAnimationForceUpdate(this, tmp); } } void sub_08060E94(Entity* this) { if (((*(u32*)&this->animIndex & 0x80ff00) == 0x800100) && (this->animIndex < 4)) { InitAnimationForceUpdate(this, (this->animationState >> 1)); this->frameDuration = (Random() & 0x7f) + 0x80; } else { UpdateAnimationSingleFrame(this); } } void sub_08060EDC(Entity* this) { s32 tmp; if (((u32)this->animIndex - 0x20 < 0x10) && ((this->frame & ANIM_DONE) == 0)) { UpdateAnimationSingleFrame(this); } else { tmp = GetFacingDirection(this, &gPlayerEntity) + this->animationState * -4; if (((tmp + 3) & 0x1f) >= 7) { if ((tmp & 0x1f) < 0x10) { InitAnimationForceUpdate(this, this->animationState + 0x20); this->animationState = (this->animationState + 1) & 7; } else { InitAnimationForceUpdate(this, this->animationState + 0x28); this->animationState = (this->animationState - 1) & 7; } } else { if ((this->animationState & 1) == 0) { if (((this->frame & ANIM_DONE) != 0) && (0xf >= (u32)this->animIndex - 0x20)) { sub_08060E70(this, 0); } else { sub_08060E94(this); } } } } } u32 sub_08060F80(Entity* this) { if (sub_08060FD0(this, (s32)gPlayerEntity.x.HALF.HI, (s32)gPlayerEntity.y.HALF.HI) == 0) { return 0; } ((UnkHeap*)this->myHeap)->unk_0 &= 0xfb; if (PointInsideRadius(gPlayerEntity.x.HALF.HI - this->x.HALF.HI, gPlayerEntity.y.HALF.HI - this->y.HALF.HI, ((UnkHeap*)this->myHeap)->unk_0b) != 0) { return 1; } return 0; } bool32 sub_08060FD0(Entity* this, u32 a, u32 b) { s32 sVar1; s32 sVar2; int iVar3; int x; int y; u8* puVar8; x = this->x.HALF.HI; y = this->y.HALF.HI; iVar3 = sub_080045DA(a - x, b - y); x <<= 8; y <<= 8; sVar1 = gSineTable[iVar3] * 6; sVar2 = gSineTable[(iVar3 + 0x40)] * 6; if (this->collisionLayer != 2) { puVar8 = gUnk_02027EB4; } else { puVar8 = gUnk_0200D654; } while (1) { if (IsTileCollision(puVar8, x / 0x100, y / 0x100, 6)) { return 0; } if (((a - (x / 0x100)) + 6 >= 0xd) || ((b - (y / 0x100)) + 6 >= 0xd)) { x += sVar1; y -= sVar2; continue; } return 1; } } void sub_08061090(Entity* this, u32 a, u32 b) { s32 xDist; s32 yDist; s32 sqrDist; u32 tmp; xDist = gPlayerEntity.x.HALF.HI - this->x.HALF.HI; yDist = gPlayerEntity.y.HALF.HI - this->y.HALF.HI; sqrDist = (xDist * xDist) + (yDist * yDist); if (sqrDist < 0x900) { this->speed = 0x120; } else { if (sqrDist < 0x1900) { this->speed = ((sqrDist - 0x900) >> 4) + 0x120; } else { this->speed = 0x220; } } if (this->speed == 0x120) { tmp = 4; } else if (this->speed < 0x160) { tmp = 8; } else { tmp = 0xc; } sub_08061120(this, a, b, tmp); } void sub_08061120(Entity* this, u32 param_a, u32 param_b, u32 param_c) { this->direction = CalculateDirectionTo(this->x.HALF.HI, this->y.HALF.HI, param_a, param_b); if ((param_c != this->field_0x6c.HALF.LO) || (10 < ((this->direction + this->animationState * -4 + 5) & 0x1f))) { this->animationState = DirectionRoundUp(this->direction) >> 2; sub_08060E70(this, param_c); } } bool32 sub_08061170(Entity* this) { u32 direction; u32 tmp; UpdateAnimationSingleFrame(this); if (ProcessMovement6(this) == 0) { direction = sub_080611D4(this); if (direction != 0xff) { this->action = 6; tmp = (sub_08079FD4(this, 1)); tmp <<= 4; tmp -= 4; tmp = tmp << 0xc; this->zVelocity = tmp; this->speed = 0x100; this->direction = direction; this->animationState = direction >> 2; if (tmp >> 0x10 != 0) { sub_08060E70(this, 0x14); } else { sub_08060E70(this, 0x18); } } return FALSE; } else { sub_08016AD2(this); return TRUE; } } u32 sub_080611D4(Entity* this) { static const struct { s8 unk_0; s8 unk_1; } PACKED gUnk_0810AC4C[] = { { 0, -8 }, { 8, 0 }, { 0, 3 }, { -8, 0 }, }; static const u8 gUnk_0810AC54[] = { 0x2b, 0x10, 0x2a, 0x0, 0x2d, 0x8, 0x2c, 0x18, 0x0, }; u32 uVar2; u32 x; s32 a; s32 b; s8* ptr; const u8* ptr2; x = this->animationState & 6; ptr = (s8*)gUnk_0810AC4C; a = ptr[x]; b = ptr[x + 1]; uVar2 = GetRelativeCollisionTile(this, a, b); ptr2 = gUnk_0810AC54; do { if (*ptr2 != uVar2 || this->animationState != (ptr2[1] >> 2)) { continue; } ++this->subtimer; if (this->subtimer < 8) { return 0xff; } return ptr2[1]; } while (ptr2 += 2, *ptr2 != 0); this->subtimer = 0; return 0xff; } u32 sub_08061230(Entity* this) { if ((((UnkHeap*)this->myHeap)->unk_0 & 1) == 0) { if ((this->contactFlags & 0x80) != 0) { switch (this->contactFlags & 0x7f) { case 0: case 1: case 2: case 3: case 0xf: case 0x13: case 0x1b: case 0x1e: case 0x1f: break; default: ((UnkHeap*)this->myHeap)->unk_0 = ((UnkHeap*)this->myHeap)->unk_0 | 1; InitAnimationForceUpdate(this, (this->animationState >> 1) + 0x40); return 1; } } } else { UpdateAnimationSingleFrame(this); if ((this->frame & ANIM_DONE) == 0) { return 1; } ((UnkHeap*)this->myHeap)->unk_0 &= 0xfe; InitAnimationForceUpdate(this, this->field_0x6c.HALF.LO + (this->animationState >> 1)); } this->contactFlags = this->contactFlags & 0x7f; if (this->iframes != 0) { this->iframes += 1; } return 0; } void sub_08061358(Entity* this) { static const u8 gUnk_0810AC5D[] = { 0x30, 0x31, 0x38, 0x39, 0x32, 0x33, 0x3a, 0x3b, 0x34, 0x35, 0x3c, 0x3d, 0x36, 0x37, 0x3e, 0x3f, 0x0, 0x0, 0x0, }; u32 uVar2; u32 bVar4; switch (this->subAction) { case 0: UpdateAnimationSingleFrame(this); if ((this->frame & ANIM_DONE) == 0) { return; } this->subAction = 1; this->timer = 0xf; sub_08060E70(this, 0); break; case 1: this->timer -= 1; if (this->timer != 0) { return; } uVar2 = Random(); bVar4 = uVar2; if ((uVar2 & 1) == 0) { this->subAction = 3; this->timer = (bVar4 & 0x18) + 0x1e; sub_08060E70(this, 4); return; } this->subAction = 2; InitAnimationForceUpdate(this, gUnk_0810AC5D[(u32)this->animationState * 2 + ((uVar2 >> 4) & 3)]); break; case 2: UpdateAnimationSingleFrame(this); if ((this->frame & ANIM_DONE) == 0) { return; } this->animationState = ((this->frame & 0x18) >> 2); if ((Random() & 1)) { this->subAction = 3; this->timer = (bVar4 & 0x18) + 0x1e; sub_08060E70(this, 4); return; } this->subAction = 0; sub_08060E70(this, 0x10); break; case 3: if (sub_08061170(this) == 0) { this->subAction = 2; //! @bug bVar4 (r6) is uninitialized. InitAnimationForceUpdate(this, gUnk_0810AC5D[this->animationState * 2 + (bVar4 >> 4 & 3)]); return; } if (--this->timer != 0) { return; } this->subAction = 0; sub_08060E70(this, 0x10); break; } } void sub_08061464(Entity* this, u32 param_a, u32 param_b) { s32 iVar10; s32 iVar9; u32 bVar1; iVar10 = this->x.HALF.HI; iVar9 = this->y.HALF.HI; switch (((CalculateDirectionTo(this->x.HALF.HI, this->y.HALF.HI, param_a, param_b) + 2) & 0x1c) >> 2) { case 0: this->field_0x6e.HWORD = param_b; if (this->x.HALF.HI > (s32)param_a) { sub_08061630(this, iVar10, iVar9 + -8, param_a); break; } sub_080616A8(this, iVar10, iVar9 + -8, param_a); break; case 1: this->field_0x6e.HWORD = param_a; if (sub_08061720(this, iVar10 + 8, iVar9, param_b) != 0) break; this->field_0x6e.HWORD = param_b; sub_080616A8(this, iVar10, iVar9 + -8, param_a); break; case 2: this->field_0x6e.HWORD = param_a; if (this->y.HALF.HI > (s32)param_b) { sub_08061720(this, iVar10 + 8, iVar9, param_b); } else { sub_08061798(this, iVar10 + 8, iVar9, param_b); } break; case 3: this->field_0x6e.HWORD = param_a; if (sub_08061798(this, iVar10 + 8, iVar9, param_b) != 0) break; this->field_0x6e.HWORD = param_b; sub_08061888(this, iVar10, iVar9 + 8, param_a); break; case 4: this->field_0x6e.HWORD = param_b; if (this->x.HALF.HI > (s32)param_a) { sub_08061810(this, iVar10, iVar9 + 8, param_a); break; } sub_08061888(this, iVar10, iVar9 + 8, param_a); break; case 5: this->field_0x6e.HWORD = param_a; if (sub_08061978(this, iVar10 + -8, iVar9, param_b) != 0) break; this->field_0x6e.HWORD = param_b; sub_08061810(this, iVar10, iVar9 + 8, param_a); break; case 6: this->field_0x6e.HWORD = param_a; if (this->y.HALF.HI > (s32)param_b) { sub_08061900(this, iVar10 + -8, iVar9, param_b); } else { sub_08061978(this, iVar10 + -8, iVar9, param_b); } break; case 7: this->field_0x6e.HWORD = param_a; if (sub_08061900(this, iVar10 + -8, iVar9, param_b) == 0) { this->field_0x6e.HWORD = param_b; sub_08061630(this, iVar10, iVar9 + -8, param_a); } } bVar1 = ((UnkHeap*)this->myHeap)->unk_0 & 8; if (bVar1 == 0) { this->action = 3; this->subAction = bVar1; } } bool32 sub_08061630(Entity* this, s32 x, s32 y, s32 param) { u32 param_y = y; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A74(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = x; ((UnkHeap*)this->myHeap)->unk_8 = param_y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD >= y) { return TRUE; } } y -= 8; } return FALSE; } bool32 sub_080616A8(Entity* this, s32 x, s32 y, s32 param) { u32 param_y = y; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A1C(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = x; ((UnkHeap*)this->myHeap)->unk_8 = param_y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD >= y) { return TRUE; } } y -= 8; } return FALSE; } bool32 sub_08061720(Entity* this, s32 x, s32 y, s32 param) { u32 param_x = x; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_080619F0(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = param_x; ((UnkHeap*)this->myHeap)->unk_8 = y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD <= x) { return TRUE; } } x += 8; } return FALSE; } bool32 sub_08061798(Entity* this, s32 x, s32 y, s32 param) { u32 param_x = x; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A48(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = param_x; ((UnkHeap*)this->myHeap)->unk_8 = y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD <= x) { return TRUE; } } x += 8; } return FALSE; } bool32 sub_08061810(Entity* this, s32 x, s32 y, s32 param) { u32 param_y = y; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A74(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = x; ((UnkHeap*)this->myHeap)->unk_8 = param_y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD <= y) { return TRUE; } } y += 8; } return FALSE; } bool32 sub_08061888(Entity* this, s32 x, s32 y, s32 param) { u32 param_y = y; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A1C(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = x; ((UnkHeap*)this->myHeap)->unk_8 = param_y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD <= y) { return TRUE; } } y += 8; } return FALSE; } bool32 sub_08061900(Entity* this, s32 x, s32 y, s32 param) { u32 param_x = x; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_080619F0(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = param_x; ((UnkHeap*)this->myHeap)->unk_8 = y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD >= x) { return TRUE; } } x -= 8; } return FALSE; } bool32 sub_08061978(Entity* this, s32 x, s32 y, s32 param) { u32 param_x = x; u8* layer = (this->collisionLayer == 2) ? gUnk_0200D654 : gUnk_02027EB4; while (!IsTileCollision(layer, x, y, 6)) { if (sub_08061A48(layer, x, y, param)) { ((UnkHeap*)this->myHeap)->unk_7 = param_x; ((UnkHeap*)this->myHeap)->unk_8 = y; ((UnkHeap*)this->myHeap)->unk_0 |= 8; if (this->field_0x6e.HWORD >= x) { return TRUE; } } x -= 8; } return FALSE; } bool32 sub_080619F0(u8* layer, s32 x, s32 y, s32 param) { while (param <= y) { if (IsTileCollision(layer, x, y, 6) != 0) { return FALSE; } y -= 8; } return TRUE; } bool32 sub_08061A1C(u8* layer, s32 x, s32 y, s32 param) { while (param >= x) { if (IsTileCollision(layer, x, y, 6) != 0) { return FALSE; } x += 8; } return TRUE; } bool32 sub_08061A48(u8* layer, s32 x, s32 y, s32 param) { while (param >= y) { if (IsTileCollision(layer, x, y, 6) != 0) { return FALSE; } y += 8; } return TRUE; } bool32 sub_08061A74(u8* layer, s32 x, s32 y, s32 param) { while (param <= x) { if (IsTileCollision(layer, x, y, 6) != 0) { return FALSE; } x -= 8; } return TRUE; } void sub_08061AA0(Entity* this) { DeleteThisEntity(); } void sub_08061AA8(Entity* this) { static void (*const gUnk_0810AC70[])(Entity*) = { sub_08061ACC, sub_08061B18, }; gUnk_0810AC70[this->action](this); CopyPosition(this->parent, this); } void sub_08061ACC(Entity* this) { this->flags = this->flags | ENT_PERSIST; this->action = 1; this->subAction = 0xff; this->timer = 0; this->followerFlag = this->followerFlag & 0xfe; sub_08078778(this); sub_08061AFC(this); } void sub_08061AFC(Entity* this) { u32 tmp = 0; if (this->subAction != 0) { this->subAction = tmp; *((u16**)&this->field_0x68) = gUnk_0810B660[0]; this->timer = 0; } } void sub_08061B18(Entity* this) { u16* puVar2; switch (this->interactType) { case 0: break; case 1: this->interactType = 0; sub_08061AFC(this); puVar2 = *(u16**)&this->field_0x68; puVar2 += (this->timer++); if (puVar2[1] == 0) { this->timer = 0; } MessageNoOverlap(puVar2[0], this); break; } } void sub_08061B58(Entity* this) { if (this->action == 0) { this->action = 1; InitAnimationForceUpdate(this, 2); } if (gRoomTransition.entity_update_type == 2) { UpdateAnimationSingleFrame(this); } sub_0806FD3C(this); }