diff options
| author | Aetias <aetias@outlook.com> | 2024-10-19 13:34:42 +0200 |
|---|---|---|
| committer | Aetias <aetias@outlook.com> | 2024-10-19 13:34:42 +0200 |
| commit | 4826a6e764b92d623b8517883cd8e901a4348f86 (patch) | |
| tree | bc8df7ba0805e37d1e44a18e755679f2ae1cc145 /src/00_Core/Actor/Actor.cpp | |
| parent | 0d62c02f14bd122690306976d8a58c5449dd3040 (diff) | |
| parent | ffdfd609fb9bc8f968ddc6f187da1d50731cbf69 (diff) | |
Merge branch 'main' into match_actor_rupee
Diffstat (limited to 'src/00_Core/Actor/Actor.cpp')
| -rw-r--r-- | src/00_Core/Actor/Actor.cpp | 1065 |
1 files changed, 958 insertions, 107 deletions
diff --git a/src/00_Core/Actor/Actor.cpp b/src/00_Core/Actor/Actor.cpp index 719cad35..4150b42f 100644 --- a/src/00_Core/Actor/Actor.cpp +++ b/src/00_Core/Actor/Actor.cpp @@ -1,110 +1,961 @@ +extern "C" { +#include <stdlib.h> +} + #include "Actor/Actor.hpp" +#include "Actor/ActorManager.hpp" +#include "Actor/ActorPlayerDummy.hpp" +#include "Item/ItemManager.hpp" +#include "Map/MapManager.hpp" +#include "Player/EquipSword.hpp" +#include "Player/PlayerControl.hpp" +#include "Player/PlayerLinkBase.hpp" +#include "Player/TouchControl.hpp" +#include "Save/AdventureFlags.hpp" -#ifdef STUBS - -Actor::Actor() {} -Actor::~Actor() {} -bool Actor::vfunc_08() {} -void Actor::vfunc_0c() {} -void Actor::vfunc_10(u32 param1) {} -void Actor::vfunc_24() {} -void Actor::vfunc_28() {} -void Actor::GetOffsetPos(Vec3p *pos) {} -unk32 Actor::vfunc_38() {} -void Actor::func_ov00_020c1788() {} -s32 Actor::vfunc_2c() {} -unk32 Actor::vfunc_30() {} -void Actor::vfunc_14(u32 param1) {} -void Actor::vfunc_18(u32 param1) {} -void Actor::vfunc_1c(u16 param1) {} -void Actor::vfunc_20(s32 param1) {} -void Actor::SetUnk_129(bool value) {} -void Actor::SetUnk_11b() {} -bool Actor::SetVelocity(Vec3p *vel) {} -bool Actor::vfunc_60() {} -void Actor::vfunc_64() {} -void Actor::SetUnk_11c(unk8 value) {} -void Actor::vfunc_68() {} -bool Actor::vfunc_6c() {} -bool Actor::vfunc_70() {} -void Actor::vfunc_74() {} -void Actor::vfunc_7c() {} -bool Actor::vfunc_78() {} -void Actor::vfunc_80() {} -void Actor::vfunc_84() {} -void Actor::vfunc_88() {} -void Actor::vfunc_8c() {} -bool Actor::vfunc_90() {} -void Actor::vfunc_94() {} -bool Actor::vfunc_98() {} -bool Actor::vfunc_9c() {} -bool Actor::func_ov00_020c195c() {} -bool Actor::func_ov00_020c198c() {} -bool KillPickupItemActors::Filter(Actor *actor) {} -void Actor::KillPickupItemActors() {} -bool Actor::TrySetTransform(Transform *transform) {} -void Actor::SetTransform(Transform *transform) {} -void Actor::vfunc_a8() {} -void Actor::func_Ov00_020c1bfc(s32 param1) {} -void Actor::func_ov00_020c1c20(s32 param1, unk32 param2, unk32 param3) {} -bool Actor::vfunc_48(unk32 param1) {} -bool Actor::vfunc_4c(unk32 *param1) {} -bool Actor::IsNearLink() {} -void Actor::func_ov00_020c1cf8() {} -bool Actor::func_ov00_020c1d58() {} -bool Actor::func_ov00_020c1da0(s32 param1, Vec3p *param2) {} -bool Actor::func_ov00_020c1e2c(s32 param1, Vec3p *param2) {} -bool Actor::func_ov00_020c1ef8(Cylinder *param1, Vec3p *param2, s32 param3, s32 param4) {} -bool Actor::func_ov00_020c1f5c(Vec3p *param1, Vec3p *param2, s32 param3, Vec3p *param4, s32 param5, s32 param6) {} -bool Actor::func_ov00_020c1fc8(PlayerCollide flags) {} -bool Actor::CollidesWithShield(Cylinder *param1) {} -bool Actor::CollidesWithPlayer(PlayerCollide flags) {} -void Actor::func_ov00_020c23c4(ActorRef *ref, Actor *actor) {} -void Actor::func_ov00_020c23d4(ActorRef *ref, Actor *actor, Cylinder *cylinder) {} -bool Actor::func_ov00_020c243c(unk32 param1, s32 *param2) {} -bool Actor::CollidesWith(const Actor *other) {} -bool Actor::func_ov00_020c27a8(unk32 param1) {} -bool Actor::CollidesWithLink() {} -bool Actor::IsFollowedByLink() {} -void Actor::StopLinkFollow() {} -bool Actor::IsGrabbed() {} -s32 Actor::XzDistanceTo(Vec3p *vec) {} -s32 Actor::DistanceToLink() {} -s32 Actor::XzDistanceToLink() {} -s32 Actor::GetAngleTo(Vec3p *vec) {} -s32 Actor::GetAngleToLink() {} -void Actor::func_ov00_020c2988(Vec3p *param1, s32 param2, Vec3p *param3) {} -void Actor::ResetWallTouch() {} -bool Actor::func_ov00_020c29ec(s32 param1) {} -void Actor::GetHitbox(Cylinder *param1) {} -void Actor::GetUnk_08c(Cylinder *param1) {} -void Actor::IncreaseActiveFrames() {} -bool Actor::func_ov00_020c2c0c() {} -bool Actor::func_ov00_020c2c70() {} -EquipBoomerang* Actor::GetEquipBoomerang() {} -bool Actor::func_ov00_020c2d54() {} -bool Actor::func_ov00_020c2de4() {} -bool Actor::func_ov00_020c2e7c() {} -bool Actor::func_ov00_020c2ebc() {} -bool Actor::func_ov00_020c2ed4() {} -bool Actor::IsHitboxTouched(bool param1) {} -void Actor::ApplyGravity() {} -bool Actor::func_ov00_020c3094() {} -Vec3p* Actor::GetPos() {} -void Actor::vfunc_54() {} -bool Actor::func_ov00_020c3118(unk16 param1) {} -bool Actor::func_ov00_020c313c(u32 param1) {} -void Actor::func_ov00_020c3158() {} -void Actor::Kill() {} -void Actor::KillInBounds() {} -void Actor::func_ov00_020c31c0(unk32 param1) {} -void Actor::vfunc_ac_Thunk() {} -void Actor::vfunc_ac() {} -void Actor::func_ov00_020c3200(s32 param1) {} -void Actor::vfunc_b0() {} -void Actor::GetLinkPos(Vec3p *result) {} -void Actor::GetLinkDummyPos(Vec3p *result) {} -Actor_UnkStruct_09c::Actor_UnkStruct_09c() {} -Actor_UnkStruct_012::Actor_UnkStruct_012() {} +static char *sShipTypes[] = {"brg", "anc", "bow", "hul", "can", "dco", "pdl", "fnl"}; + +struct UnkStruct3 { + /* 0 */ s16 mUnk_0; + /* 2 */ u8 mUnk_2; + /* 3 */ +}; +const UnkStruct3 sUnkTable[] = { + {0xff, 2}, {0xff, 2}, {0xff, 2}, {0xff, 2}, {0xff, 2}, {6, 2}, {4, 2}, {4, 2}, {4, 2}, {1, 2}, + {12, 2}, {4, 2}, {4, 2}, {8, 2}, {12, 2}, {2, 2}, {2, 2}, {20, 2}, {20, 2}, {1, 2}, + {4, 2}, {4, 2}, {4, 2}, {8, 2}, {4, 2}, {0xff, 2}, {20, 2}, {6, 2}, {6, 2}, {2, 2}, +}; + +Actor_UnkStruct_020::Actor_UnkStruct_020() : + mUnk_0c(-1), + mUnk_0d(0), + mUnk_0e(1), + mUnk_10(-1) { + for (s32 i = 0; i < 4; ++i) { + mUnk_00[i] = 0; + } + for (s32 i = 0; i < 2; ++i) { + mUnk_08[i] = 0; + mUnk_0a[i] = 0; + } +} + +ARM Actor::Actor() : + mType(ActorTypeId_Null), + mRef(-1, -1), + mUnk_010(0), + mUnk_011(0), + mUnk_012(0), + mUnk_034(-1), + mUnk_038(-1), + mUnk_03c(-1), + mUnk_040(-1, -1), + mGravity(FLOAT_TO_Q20(0.0498)), + mMaxFall(FLOAT_TO_Q20(0.5)), + mUnk_074(2), + mAngle(0), + mUnk_07a(-1), + mHitbox(FLOAT_TO_Q20(0.5)), + mUnk_08c(mHitbox), + mUnk_0a4(0, FLOAT_TO_Q20(1.0), 0, FLOAT_TO_Q20(1.0)), + mUnk_0dc(0xffff), + mUnk_0de(0xffff), + mUnk_0e0(0xffff), + mUnk_0e2(0xffff), + mUnk_0e4(0), + mUnk_106(0), + mUnk_107(0), + mUnk_108(0), + mUnk_109(0), + mUnk_110(0), + mUnk_111(0), + mUnk_112(0), + mUnk_113(0), + mUnk_114(0), + mUnk_115(0), + mAlive(true), + mUnk_119(1), + mVisible(true), + mUnk_11b(false), + mUnk_11c(0), + mUnk_11d(false), + mYOffset(0), + mUnk_120(4), + mUnk_122(0xff), + mUnk_124(1), + mUnk_125(4), + mUnk_126(3), + mUnk_128(false), + mUnk_129(false), + mUnk_12a(0), + mUnk_12c(0), + mUnk_130(-1), + mUnk_134(-1), + mActiveFrames(0), + mUnk_13c(0), + mUnk_140(0), + mUnk_144(0) { + mUnk_014.x = 0; + mUnk_014.y = 0; + mUnk_014.z = 0; + mPos.x = 0; + mPos.y = 0; + mPos.z = 0; + mPrevPos.x = 0; + mPrevPos.y = 0; + mPrevPos.z = 0; + mVel.x = 0; + mVel.y = 0; + mVel.z = 0; +} + +ARM Actor::~Actor() {} + +ARM bool Actor::vfunc_08() { + return true; +} + +ARM void Actor::vfunc_0c() {} +ARM void Actor::vfunc_10(u32 param1) {} +ARM void Actor::vfunc_24() {} +ARM void Actor::vfunc_28() {} + +ARM void Actor::GetOffsetPos(Vec3p *pos) { + *pos = mPos; + pos->y += mYOffset; +} + +extern "C" unk32 func_ov00_02087ef0(); +ARM unk32 Actor::vfunc_38() { + return func_ov00_02087ef0(); +} + +ARM unk8 Actor::func_ov00_020c1788() { + return gMapManager->func_ov00_02083570(mUnk_010, mUnk_011); +} + +ARM s32 Actor::vfunc_2c() { + return -1; +} + +ARM unk32 Actor::vfunc_30() { + return 0; +} + +ARM void Actor::vfunc_14(u32 param1) {} + +extern "C" void func_ov00_0207a1c8(Actor_UnkStruct_0a4 *param1, u32 param2, Vec3p *param3); +ARM void Actor::vfunc_18(u32 param1) { + func_ov00_0207a1c8(&mUnk_0a4, param1, &mPos); +} + +struct UnkStruct1 { + /* 00 */ unk32 mUnk_00; + /* 04 */ unk32 mUnk_04; + /* 08 */ unk8 mUnk_08; + /* 09 */ unk8 mUnk_09; + /* 0a */ unk8 mUnk_0a; + /* 0b */ unk8 mUnk_0b; + /* 0c */ unk32 mUnk_0c; + /* 10 */ unk32 mUnk_10; + /* 14 */ unk8 mUnk_14; + /* 15 */ unk8 mUnk_15; + /* 16 */ unk16 mUnk_16; + /* 18 */ unk32 mUnk_18; + /* 1c */ unk32 mUnk_1c; + /* 20 */ +}; +extern void *data_027e0d3c; +extern unk32 data_02063e4c; +extern "C" bool func_ov00_02079470(void *param1, Vec3p *param2, unk32 param3, unk32 param4, unk32 *param5, unk32 *param6, + unk32 param7, unk32 param8); +extern "C" void func_01ffbe34(UnkStruct1 *param1); +extern "C" void func_020313c8(unk32 *param1, unk32 param2, unk32 param3, u32 param4, UnkStruct1 *param5); +ARM void Actor::vfunc_1c(u16 *param1) { + u16 unk1 = mUnk_07a; + if (mUnk_129) unk1 = mUnk_126; + if (unk1 != 0xffff) { + if ((*param1 & 4) == 0 && (*param1 & 8) == 0) return; + unk32 unk2; + unk32 unk3; + if (func_ov00_02079470(data_027e0d3c, &mPos, 0, 0, &unk2, &unk3, 0, 0)) { + UnkStruct1 unk4; + func_01ffbe34(&unk4); + unk4.mUnk_04 = 1; + func_020313c8(&data_02063e4c, unk2, unk3, unk1, &unk4); + } + } +} + +ARM void Actor::vfunc_20(s32 param1) {} + +ARM void Actor::SetUnk_129(bool value) { + if (mUnk_128) mUnk_129 = value; +} + +ARM bool Actor::SetUnk_11b() { + if (mUnk_11b) return false; + mUnk_11b = true; + return true; +} + +ARM bool Actor::SetVelocity(Vec3p *vel) { + if (!mUnk_11b) return false; + mVel = *vel; + mUnk_11b = false; + return true; +} + +ARM bool Actor::vfunc_60() { + return false; +} + +ARM void Actor::vfunc_64() {} + +ARM void Actor::SetUnk_11c(unk8 value) { + mUnk_11c = value; +} + +ARM void Actor::vfunc_68() {} + +ARM bool Actor::vfunc_6c() { + return true; +} + +ARM bool Actor::vfunc_70() { + return true; +} + +ARM void Actor::vfunc_74() {} +ARM void Actor::vfunc_7c() {} + +ARM bool Actor::vfunc_78() { + return true; +} + +ARM void Actor::vfunc_80() {} +ARM void Actor::vfunc_84() {} +ARM void Actor::vfunc_88() {} + +ARM bool Actor::vfunc_8c() { + return true; +} + +ARM bool Actor::vfunc_90() { + return true; +} + +ARM void Actor::vfunc_94() {} +ARM bool Actor::vfunc_98() {} +ARM bool Actor::vfunc_9c() {} + +ARM bool Actor::func_ov00_020c195c() { + if (!mUnk_11b) return false; + gPlayerLink->func_ov00_020bc854(&mPos); + return true; +} + +struct UnkStruct2 { + /* 0 */ u32 mUnk_0; + /* 4 */ u32 mUnk_4; + /* 8 */ +}; +extern UnkStruct2 data_027e077c; +extern u8 data_02056be4[]; +extern "C" bool func_ov05_02103f4c(s32 param1); +extern s32 data_027e103c; +ARM bool Actor::func_ov00_020c198c() { + u32 unk1 = data_027e077c.mUnk_0; + u32 unk2 = data_027e077c.mUnk_4; + if (data_027e077c.mUnk_0 != data_027e077c.mUnk_4 || (data_02056be4[unk1] & 1) != 0 || (data_02056be4[unk2] & 4) != 0 || + func_ov05_02103f4c(data_027e103c) || gPlayer->mHealth <= 0) + { + return false; + } + if (gPlayerLink && !gPlayerLink->func_ov00_020bd304()) return false; + return true; +} + +ARM bool KillPickupsFilter::Filter(Actor *actor) { + switch (actor->mType) { + case ActorTypeId_Rupee: + case ActorTypeId_Heart: + case ActorTypeId_Bomb: + case ActorTypeId_Arrow: + case ActorTypeId_BMRN: + case ActorTypeId_BMTY: + case ActorTypeId_FLAL: + case ActorTypeId_FLBM: + case ActorTypeId_FLBT: + case ActorTypeId_FLTM: { + actor->Kill(); + return true; + } + + default: return false; + } +} + +ARM void Actor::KillPickupItemActors() { + KillPickupsFilter killPickups; + gActorManager->FilterActors(&killPickups, NULL); +} + +ARM bool Actor::TrySetTransform(Transform *transform) { + mPrevPos = mPos; + mPos = transform->pos; + mAngle = transform->angle; + mVisible = transform->visible; + return true; +} + +ARM void Actor::SetTransform(Transform *transform) { + mPrevPos = mPos; + mPos = transform->pos; + mAngle = transform->angle; + mVisible = transform->visible; +} + +ARM void Actor::vfunc_a8() {} + +ARM void Actor::func_Ov00_020c1bfc(s32 param1) { + gMapManager->func_ov00_02084be0(mUnk_020.mUnk_0a[param1], mUnk_020.mUnk_08[param1]); +} + +ARM void Actor::func_ov00_020c1c20(s32 param1, unk32 param2) { + gMapManager->func_ov00_02084b38(mUnk_020.mUnk_0a[param1], mUnk_020.mUnk_08[param1], param2); +} + +ARM bool Actor::vfunc_48(Knockback *param1) { + return true; +} + +extern "C" void func_ov00_020c8398(ActorTypeId type, Vec3p *pos, unk32 param2); +ARM bool Actor::vfunc_4c(unk32 *param1) { + if ((*param1 & 0x1f) == 0x8) { + func_ov00_020c8398(mType, &mPos, 1); + this->Kill(); + return true; + } + this->Kill(); + return true; +} + +ARM bool Actor::IsNearLink() { + Vec3p playerPos = gPlayerPos; + + q20 z = playerPos.z; + q20 dx = abs(playerPos.x - mPos.x); + if (dx > FLOAT_TO_Q20(10.0)) return false; + q20 dz = abs(playerPos.z - mPos.z); + return dz <= FLOAT_TO_Q20(10.0); +} + +ARM void Actor::func_ov00_020c1cf8() { + if (mUnk_0a4.mUnk_00 || mUnk_0a4.mUnk_01 || mUnk_129 == true || mUnk_11d == true || mUnk_11b == true) { + mInactive = 0; + } else { + if (this->IsNearLink()) { + mInactive = 1; + } else { + mInactive = 2; + } + } +} + +ARM bool Actor::func_ov00_020c1d58() { + if (gAdventureFlags->func_ov00_02097738()) return false; + return gPlayer->vfunc_04() != false; +} + +ARM bool Actor::func_ov00_020c1da0(s32 param1, Vec3p *param2) { + if (!this->func_ov00_020c1d58()) return false; + + Vec3p vec; + if (param2) { + vec = *param2; + } else { + Vec3p_Sub(&gPlayerPos, &mPrevPos, &vec); + } + + return gPlayer->vfunc_30(mUnk_124, &vec, param1); +} + +ARM bool Actor::func_ov00_020c1e2c(s32 param1, Vec3p *param2) { + if (!this->func_ov00_020c1d58()) return false; + if (mHitbox.size < 0) return false; + + Vec3p vec; + if (param2) { + vec = *param2; + } else { + Vec3p_Sub(&gPlayerPos, &mPrevPos, &vec); + } + + Cylinder hitbox; + this->GetHitbox(&hitbox); + if (gPlayer->CollidesWith(&hitbox)) { + return gPlayer->vfunc_30(mUnk_124, &vec, param1); + } + return false; +} + +ARM bool Actor::func_ov00_020c1ef8(Cylinder *param1, Vec3p *param2, s32 param3, s32 param4) { + if (!this->func_ov00_020c1d58()) return false; + if (gPlayer->CollidesWith(param1)) { + return gPlayer->vfunc_30(param3, param2, param4); + } + return false; +} + +ARM bool Actor::func_ov00_020c1f5c(Vec3p *param1, Vec3p *param2, s32 param3, Vec3p *param4, u8 param5, s32 param6) { + if (!this->func_ov00_020c1d58()) return false; + if (gPlayer->func_ov00_020a7c60(param1, param2, param3)) { + return gPlayer->vfunc_30(param5, param4, param6); + } + return false; +} + +ARM bool Actor::func_ov00_020c1fc8(PlayerCollide flags) { + if (gAdventureFlags->func_ov00_02097738()) return false; + bool result = false; + if (mHitbox.size >= 0) { + Vec3p vecFromPlayer; + Vec3p_Sub(&mPos, &gPlayerPos, &vecFromPlayer); + if (this->CollidesWithPlayer(flags & PlayerCollide_Sword)) { + Knockback knockback; + knockback.mUnk_00 = gPlayer->EquipItem_vfunc_2c(); + knockback.vec = vecFromPlayer; + knockback.mUnk_10 = 0; + knockback.actor = NULL; + + result = this->vfunc_48(&knockback); + } else if (this->CollidesWithPlayer(flags & PlayerCollide_Shield)) { + Knockback knockback; + knockback.mUnk_00 = 0; + knockback.vec = vecFromPlayer; + if ((s32) gItemManager->GetActiveFairyLevel(FairyId_Wisdom) >= 1) { + knockback.mUnk_10 = 3; + } else { + knockback.mUnk_10 = 2; + } + knockback.actor = NULL; + + result = this->vfunc_48(&knockback); + } else if (this->CollidesWithPlayer(flags & PlayerCollide_Hammer)) { + Knockback knockback; + knockback.mUnk_00 = gPlayer->EquipItem_vfunc_2c(); + knockback.vec = vecFromPlayer; + knockback.mUnk_10 = 4; + knockback.actor = NULL; + + result = this->vfunc_48(&knockback); + } else if (this->CollidesWithPlayer(flags & PlayerCollide_Gongoron)) { + Knockback knockback; + knockback.mUnk_00 = gPlayerLink->vfunc_78(); + knockback.vec = vecFromPlayer; + if (knockback.mUnk_00 != 0) { + knockback.mUnk_10 = 9; + } else { + knockback.mUnk_10 = 2; + } + knockback.actor = NULL; + + result = this->vfunc_48(&knockback); + } + } + return result; +} + +ARM bool Actor::CollidesWithShield(Cylinder *param1) { + Vec3p vecFromPlayer; + Vec3p_Sub(&mPos, &gPlayerPos, &vecFromPlayer); + s32 currAngle = gPlayerAngle; + s32 angle = Atan2(vecFromPlayer.x, vecFromPlayer.z); + s32 angleDiff = (s16) angle - currAngle; + if (angleDiff < 0) angleDiff = -angleDiff; + if (angleDiff <= DEG_TO_ANG(90) && gPlayer->EquipCollidesWith(param1, ItemFlag_WoodenShield)) { + return true; + } + return false; +} + +ARM bool Actor::CollidesWithPlayer(PlayerCollide flags) { + if (flags != 0 && mHitbox.size >= 0) { + Cylinder hitbox; + this->GetHitbox(&hitbox); + if (flags & PlayerCollide_Player) { + if (gPlayer->CollidesWith(&hitbox)) return true; + } + if (flags & PlayerCollide_Sword) { + if (gPlayer->EquipCollidesWith(&hitbox, ItemFlag_OshusSword)) return true; + } + if (flags & PlayerCollide_Shield) { + if (this->CollidesWithShield(&hitbox)) return true; + } + if (flags & PlayerCollide_Gongoron) { + if (gPlayerLink && gPlayerLink->GongoronCollidesWith(&hitbox)) return true; + } + if (flags & PlayerCollide_Hammer) { + if (gPlayer->EquipCollidesWith(&hitbox, ItemFlag_Hammer)) return true; + } + } + return false; +} + +ARM void Actor::func_ov00_020c23c4(ActorRef *ref, Actor *actor) { + Actor::func_ov00_020c23d4(ref, actor, &actor->mHitbox); +} + +ARM void Actor::func_ov00_020c23d4(ActorRef *ref, Actor *actor, Cylinder *cylinder) { + *ref = actor->mUnk_040; + if (!gActorManager->func_ov00_020c398c(actor->mRef.index)) { + ref->Reset(); + } + actor->mUnk_040.Reset(); + gActorManager->func_ov00_020c399c(actor->mRef.index, cylinder); +} + +ARM bool Actor::func_ov00_020c243c(ActorTypeId *actorTypes, Actor **out) { + if (out) *out = NULL; + if (gAdventureFlags->func_ov00_02097738()) return false; -#endif + bool result = false; + if (mHitbox.size >= 0) { + Actor *actor = gActorManager->func_ov00_020c39ac(mRef.index, actorTypes, false); + if (actor) { + Knockback knockback; + if (actor->mType == ActorTypeId_Arrow || actor->mType == ActorTypeId_SBEM) { + q20 cos = COS(actor->mAngle); + q20 sin = SIN(actor->mAngle); + + knockback.vec.x = sin; + knockback.vec.y = 0; + knockback.vec.z = cos; + } else { + Vec3p_Sub(&mPos, &actor->mPrevPos, &knockback.vec); + } + knockback.mUnk_00 = actor->mUnk_125; + knockback.actor = actor; + + switch (actor->mType) { + case ActorTypeId_SBEM: { + knockback.mUnk_10 = 1; + } break; + + case ActorTypeId_Arrow: { + knockback.mUnk_10 = 7; + } break; + + case ActorTypeId_BMRN: { + knockback.mUnk_10 = 5; + } break; + + case ActorTypeId_ROPE: { + knockback.mUnk_10 = 8; + } break; + + case ActorTypeId_Bomb: + case ActorTypeId_BLST: + case ActorTypeId_BMTY: + case ActorTypeId_CBLS: { + knockback.mUnk_10 = 6; + } break; + + case ActorTypeId_TSBH: + case ActorTypeId_BIGR: + case ActorTypeId_BTRF: + case ActorTypeId_STNE: + case ActorTypeId_TARU: + case ActorTypeId_BKEY: + case ActorTypeId_FORC: + case ActorTypeId_FLTB: + case ActorTypeId_TSUB: { + knockback.mUnk_10 = 10; + } break; + + case ActorTypeId_VLR0: { + knockback.mUnk_10 = 4; + } break; + + default: { + knockback.mUnk_10 = 11; + } break; + } + + result = this->vfunc_48(&knockback); + if (result) { + actor->mUnk_040 = this->mRef; + if (out) *out = actor; + } + } + } + return result; +} + +ARM bool Actor::CollidesWith(Actor *other) { + bool collides = false; + if (other->mAlive) { + if (other->mHitbox.size >= 0 && mHitbox.size >= 0) { + Cylinder a, b; + this->GetHitbox(&a); + other->GetHitbox(&b); + if (a.Overlaps(&b)) collides = true; + } + } + return collides; +} + +ARM bool Actor::func_ov00_020c27a8(unk32 param1) { + if (mUnk_11b) return false; + if (param1 == 0) return mUnk_12c != 0; + return mUnk_12c == param1; +} + +ARM bool Actor::CollidesWithLink() { + Cylinder hitbox; + this->GetHitbox(&hitbox); + // Link's hitbox has a radius of 1, hence why they add 1.0 here + return this->DistanceToLink() < hitbox.size + FLOAT_TO_Q20(1.0); +} + +ARM bool Actor::IsFollowedByLink() { + return mRef.id == gPlayerControl->mFollowRef.id; +} + +ARM void Actor::StopLinkFollow() { + if (!this->IsFollowedByLink()) return; + gPlayerControl->StopFollowing(); +} + +ARM bool Actor::IsGrabbed() { + s32 id = mRef.id; + return id == gPlayerLink->GetGrabActorId(); +} + +ARM q20 Actor::XzDistanceTo(Vec3p *vec) { + Vec3p src, dest; + Vec3p_CopyXZ(&mPos, &src); + Vec3p_CopyXZ(vec, &dest); + return Vec3p_Distance(&src, &dest); +} + +ARM q20 Actor::DistanceToLink() { + return Vec3p_Distance(&mPos, &gPlayerPos); +} + +ARM q20 Actor::XzDistanceToLink() { + Vec3p src; + Vec3p_CopyXZ(&mPos, &src); + Vec3p dest = gPlayerPos; + + dest.y = 0; + return Vec3p_Distance(&src, &dest); +} + +ARM s16 Actor::GetAngleTo(Vec3p *vec) { + s16 angle = mAngle; + + q20 dz = vec->z - mPos.z; + q20 dx = vec->x - mPos.x; + if (dx != 0 || dz != 0) { + angle = Atan2(dx, dz); + } + return angle; +} + +ARM s32 Actor::GetAngleToLink() { + return this->GetAngleTo(&gPlayerPos); +} + +extern "C" void func_0202d95c(Vec3p *param1, q20 param2); +ARM void Actor::func_ov00_020c2988(Vec3p *param1, q20 param2, Vec3p *param3) { + q20 z1 = param1->z; + q20 z0 = mPos.z; + + param3->x = param1->x - mPos.x; + param3->y = 0; + param3->z = z1 - z0; + q20 dist = this->XzDistanceTo(param1); + if (dist < param2) param2 = dist; + func_0202d95c(param3, param2); +} + +ARM void Actor::ResetWallTouch() { + mWallTouch.x = 0; + mWallTouch.y = 0; + mWallTouch.z = 0; +} + +ARM bool Actor::func_ov00_020c29ec(q20 param1) { + return Vec3p_Length(&mWallTouch) > param1; +} + +ARM void Actor::GetHitbox(Cylinder *hitbox) { + hitbox->size = mHitbox.size; + u32 angle = 2 * (mAngle >> 4); + hitbox->pos.x = mPos.x; + hitbox->pos.y = mPos.y; + hitbox->pos.z = mPos.z; + hitbox->pos.y += mHitbox.pos.y; + + q20 sin = gSinCosTable[angle]; + q20 cos = gSinCosTable[angle + 1]; + Vec3p_Rotate(&mHitbox.pos, sin, cos, &hitbox->pos); +} + +ARM void Actor::GetUnk_08c(Cylinder *param1) { + param1->size = mUnk_08c.size; + u32 angle = 2 * (mAngle >> 4); + param1->pos.x = mPos.x; + param1->pos.y = mPos.y; + param1->pos.z = mPos.z; + param1->pos.y += mUnk_08c.pos.y; + + q20 sin = gSinCosTable[angle]; + q20 cos = gSinCosTable[angle + 1]; + Vec3p_Rotate(&mUnk_08c.pos, sin, cos, ¶m1->pos); +} + +ARM void Actor::IncreaseActiveFrames() { + mActiveFrames += 1; + if (mActiveFrames < 0) mActiveFrames = 0; +} + +ARM bool Actor::func_ov00_020c2c0c() { + const ActorTypeId types[] = { + ActorTypeId_BMRN, + ActorTypeId_Null, + }; + return mHitbox.size >= 0 && gActorManager->func_ov00_020c39ac(mRef.index, types, false); +} + +ARM bool Actor::func_ov00_020c2c70() { + Vec3p vel; + Actor *boomerang = this->GetEquipBoomerang()->GetActor(); + if (boomerang) { + Vec3p_Sub(&boomerang->mPos, &mPos, &vel); + if (Vec3p_Length(&vel) > FLOAT_TO_Q20(1.0)) { + func_0202d95c(&vel, FLOAT_TO_Q20(1.0)); + } + } else { + PlayerCharacter character = gPlayerLink->GetCurrentCharacter(); + if (character == PlayerCharacter_Gongoron) { + Vec3p pos; + this->GetLinkPos(&pos); + Vec3p_Sub(&pos, &mPos, &vel); + } else { + Vec3p_Sub(&gPlayerPos, &mPos, &vel); + } + } + Vec3p_Add(&mPos, &vel, &mPos); + mVel = vel; + return boomerang != NULL; +} + +ARM EquipBoomerang *Actor::GetEquipBoomerang() { + return (EquipBoomerang *) ItemManager::GetEquipItemUnchecked(ItemFlag_Boomerang); +} + +ARM bool Actor::func_ov00_020c2d54() { + const ActorTypeId types[] = { + ActorTypeId_ROPE, + ActorTypeId_Null, + }; + if (mHitbox.size >= 0) { + Actor *actor = gActorManager->func_ov00_020c39ac(mRef.index, types, false); + if (actor) { + EquipRope *rope = EquipSword::GetEquipRope(); + if (rope->func_ov14_0213d480(mRef.id) < 0) { + actor->mUnk_040 = mRef; + return true; + } + } + } + return false; +} + +ARM bool Actor::func_ov00_020c2de4() { + Vec3p vel; + + EquipRope *rope = EquipSword::GetEquipRope(); + + Actor *actor = rope->func_ov14_0213d420(); + if (actor) { + Vec3p_Sub(&actor->mPos, &mPos, &vel); + if (Vec3p_Length(&vel) > FLOAT_TO_Q20(1.0)) { + func_0202d95c(&vel, FLOAT_TO_Q20(1.0)); + } + } else { + Vec3p_Sub(&gPlayerPos, &mPos, &vel); + } + Vec3p_Add(&mPos, &vel, &mPos); + mVel = vel; + return actor != NULL; +} + +ARM bool Actor::func_ov00_020c2e7c() { + bool result = false; + + EquipRope *rope = EquipSword::GetEquipRope(); + if (!mUnk_11d) { + s32 unk1 = rope->func_ov14_0213ddd4(this); + s32 unk2 = unk1; + if (unk1 >= 0) { + unk1 = rope->mUnk_70; + if (unk1 >= unk2) result = true; + } + } + return result; +} + +ARM bool Actor::func_ov00_020c2ebc() { + EquipRope *rope = EquipSword::GetEquipRope(); + return rope->func_ov14_0213defc(this); +} + +ARM bool Actor::func_ov00_020c2ed4() { + EquipRope *rope = EquipSword::GetEquipRope(); + + s32 index = rope->func_ov14_0213d440(mRef.id); + if (index >= 0) { + bool unk1 = rope->func_ov14_0213d420(); + if (unk1) { + Vec3p vel; + if (rope->func_ov14_0213d81c(index, &vel)) { + mVel = vel; + Vec3p_Add(&mPos, &mVel, &mPos); + if (!this->func_01fffd04(1)) { + Cylinder hitbox; + this->GetHitbox(&hitbox); + return rope->func_ov14_0213dadc(index, &hitbox); + } + rope->func_ov14_0213d91c(index); + return false; + } else { + return true; + } + } + } else { + index = rope->func_ov14_0213d480(mRef.id); + if (index >= 0) return true; + } + if (rope->mUnk_6a) mVel = gVec3p_ZERO; + return false; +} + +ARM bool Actor::IsHitboxTouched(bool param1) { + q20 size = mHitbox.size; + + bool result = false; + if (size >= 0) { + Vec3p pos = mPos; + pos.y += size; + if (param1) { + result = TouchControl::func_0202b864(&pos, size, 8); + } else { + result = TouchControl::func_0202b894(&pos, size, 8); + } + } + return result; +} + +ARM void Actor::ApplyGravity() { + mVel.y -= mGravity; + if (mVel.y < -mMaxFall) mVel.y = -mMaxFall; +} + +ARM bool Actor::func_ov00_020c3094() { + bool result = false; + Vec3p pos, prevPos; + Vec3p_Copy(&mPos, &pos); + Vec3p_Copy(&mPrevPos, &prevPos); + s32 unk1 = gMapManager->func_ov00_02083ef8(&pos, &prevPos, 0); + if (mPos.y <= unk1) { + result = true; + mPos.y = unk1; + } + return result; +} + +ARM Vec3p *Actor::GetPos() { + return &mPos; +} + +ARM void Actor::vfunc_54() {} + +extern "C" bool func_ov00_020c5924(Vec3p *param1, unk16 param2, ActorRef *param3, unk32 param4, ActorRef *param5); +ARM bool Actor::func_ov00_020c3118(unk16 param1) { + return func_ov00_020c5924(&mPos, param1, &mRef, 2, NULL); +} + +extern u8 data_027e0c54; +ARM bool Actor::func_ov00_020c313c(u32 param1) { + return param1 == data_027e0c54; +} + +ARM void Actor::func_ov00_020c3158() { + if (mUnk_03c < 0) return; + gMapManager->func_ov00_02084c5c(mUnk_03c, 1); +} + +ARM void Actor::Kill() { + mAlive = false; + if (mUnk_119 == 0) return; + this->func_ov00_020c3158(); +} + +ARM void Actor::KillInBounds() { + if (mPos.y >= -FLOAT_TO_Q20(10.0)) return; + this->Kill(); +} + +extern unk32 data_ov00_020e9c88; +extern "C" void func_ov00_0207b89c(unk32 *param1, s32 param2, Vec3p *param3, void *param4, Actor *param5); +void vfunc_ac_Thunk(Actor *actor); +ARM void Actor::func_ov00_020c31c0(unk32 param1) { + func_ov00_0207b89c(&data_ov00_020e9c88, param1, &mPos, &vfunc_ac_Thunk, this); +} + +ARM void vfunc_ac_Thunk(Actor *actor) { + actor->vfunc_ac(); +} + +ARM void Actor::vfunc_ac() {} + +ARM void Actor::func_ov00_020c3200(s32 param1) { + const UnkStruct3 *entry = &sUnkTable[param1]; + + mUnk_122 = sUnkTable[param1].mUnk_0; + mUnk_120 = sUnkTable[param1].mUnk_0; + mUnk_124 = entry->mUnk_2; +} + +ARM void Actor::vfunc_b0() {} + +ARM void Actor::GetLinkPos(Vec3p *result) { + if (gPlayerLink != NULL && gPlayerLink->GetCurrentCharacter() != PlayerCharacter_Link) { + return this->GetLinkDummyPos(result); + } + *result = gPlayerPos; +} + +ARM void Actor::GetLinkDummyPos(Vec3p *result) { + ActorRef dummyRef; + ActorManager::FindActorByType(&dummyRef, gActorManager, ActorTypeId_PlayerDummy); + ActorPlayerDummy *dummy = (ActorPlayerDummy *) gActorManager->GetActor(&dummyRef); + if (dummy != NULL && dummy->mUnk_16e == 0) { + *result = dummy->mPos; + return; + } + *result = gPlayerPos; +} + +Actor_UnkStruct_09c::Actor_UnkStruct_09c() { + mUnk_0 = 0xff; + mUnk_2 = 1; + mUnk_3 = 0; + mUnk_4 = 0; +} + +Actor_UnkStruct_012::Actor_UnkStruct_012() {} |
