OdysseyDecomp/lib/al/Library/Player/PlayerUtil.cpp
MonsterDruide1 e8e607cc7e wip
2025-10-24 00:34:30 +02:00

332 lines
11 KiB
C++

#include "Library/Player/PlayerUtil.h"
#include "Library/Controller/PadRumbleDirector.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorModelFunction.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/LiveActor/ActorSceneInfo.h"
#include "Library/LiveActor/LiveActor.h"
#include "Library/Player/PlayerHolder.h"
namespace al {
s32 getPlayerNumMax(const LiveActor* actor) {
return getPlayerNumMax(actor->getSceneInfo()->playerHolder);
}
s32 getPlayerNumMax(const PlayerHolder* holder) {
return holder->getPlayerNum();
}
s32 getAlivePlayerNum(const LiveActor* actor) {
return getAlivePlayerNum(actor->getSceneInfo()->playerHolder);
}
s32 getAlivePlayerNum(const PlayerHolder* holder) {
s32 player_num = getPlayerNumMax(holder);
s32 alive_players = 0;
for (s32 i = 0; i < player_num; i++) {
LiveActor* player = getPlayerActor(holder, i);
if (isAlive(player))
alive_players++;
}
return alive_players;
}
LiveActor* getPlayerActor(const LiveActor* actor, s32 index) {
return getPlayerActor(actor->getSceneInfo()->playerHolder, index);
}
LiveActor* getPlayerActor(const PlayerHolder* holder, s32 index) {
return tryGetPlayerActor(holder, index);
}
const sead::Vector3f& getPlayerPos(const LiveActor* actor, s32 index) {
return getPlayerPos(actor->getSceneInfo()->playerHolder, index);
}
const sead::Vector3f& getPlayerPos(const PlayerHolder* holder, s32 index) {
return getTrans(getPlayerActor(holder, index));
}
LiveActor* tryGetPlayerActor(const LiveActor* actor, s32 index) {
return tryGetPlayerActor(actor->getSceneInfo()->playerHolder, index);
}
LiveActor* tryGetPlayerActor(const PlayerHolder* holder, s32 index) {
return holder->tryGetPlayer(index);
}
bool isPlayerDead(const LiveActor* actor, s32 index) {
return isPlayerDead(actor->getSceneInfo()->playerHolder, index);
}
bool isPlayerDead(const PlayerHolder* holder, s32 index) {
return isDead(getPlayerActor(holder, index));
}
bool isPlayerAreaTarget(const LiveActor* actor, s32 index) {
return isPlayerAreaTarget(actor->getSceneInfo()->playerHolder, index);
}
bool isPlayerAreaTarget(const PlayerHolder* holder, s32 index) {
return isAreaTarget(getPlayerActor(holder, index));
}
LiveActor* tryFindAlivePlayerActorFirst(const LiveActor* actor) {
return tryFindAlivePlayerActorFirst(actor->getSceneInfo()->playerHolder);
}
LiveActor* tryFindAlivePlayerActorFirst(const PlayerHolder* holder) {
u32 player_num = getPlayerNumMax(holder);
for (u32 i = 0; i < player_num; i++) {
LiveActor* player = holder->tryGetPlayer(i);
if (!isDead(player))
return player;
}
return nullptr;
}
LiveActor* findAlivePlayerActorFirst(const LiveActor* actor) {
return findAlivePlayerActorFirst(actor->getSceneInfo()->playerHolder);
}
LiveActor* findAlivePlayerActorFirst(const PlayerHolder* holder) {
return tryFindAlivePlayerActorFirst(holder);
}
static inline PadRumbleKeeper* getPlayerPadRumbleKeeper(const PlayerHolder* holder, s32 index) {
return holder->getPadRumbleKeeper(index);
}
PadRumbleKeeper* getPlayerPadRumbleKeeper(const LiveActor* actor, s32 index) {
return getPlayerPadRumbleKeeper(actor->getSceneInfo()->playerHolder, index);
}
s32 getPlayerPort(const PlayerHolder* holder, s32 index) {
return getPlayerPadRumbleKeeper(holder, index)->port;
}
s32 getPlayerPort(const LiveActor* actor, s32 index) {
return getPlayerPort(actor->getSceneInfo()->playerHolder, index);
}
LiveActor* findAlivePlayerActorFromPort(const PlayerHolder* holder, s32 port) {
return tryFindAlivePlayerActorFromPort(holder, port);
}
LiveActor* tryFindAlivePlayerActorFromPort(const PlayerHolder* holder, s32 port) {
s32 player_num = getPlayerNumMax(holder);
for (s32 i = 0; i < player_num; i++) {
LiveActor* player = tryGetPlayerActor(holder, i);
if (getPlayerPort(player, i) == port && !isPlayerDead(player, i))
return player;
}
return nullptr;
}
LiveActor* findAlivePlayerActorFromPort(const LiveActor* actor, s32 port) {
return tryFindAlivePlayerActorFromPort(actor, port);
}
LiveActor* tryFindAlivePlayerActorFromPort(const LiveActor* actor, s32 port) {
return tryFindAlivePlayerActorFromPort(actor->getSceneInfo()->playerHolder, port);
}
s32 findNearestPlayerIdCondition(const LiveActor* actor, const sead::Vector3f& pos,
bool (*condition)(const al::LiveActor*), f32 threshold) {
PlayerHolder* holder = actor->getSceneInfo()->playerHolder;
s32 player_num = getPlayerNumMax(holder);
f32 min_distance = sead::Mathf::maxNumber();
s32 nearest_player_id = -1;
for (s32 i = 0; i < player_num; i++) {
LiveActor* player = holder->getPlayer(i);
if (player && !condition(player)) {
const sead::Vector3f& player_pos = getTrans(player);
f32 distance = (player_pos - pos).squaredLength();
if (distance < min_distance) {
min_distance = distance;
nearest_player_id = i;
}
}
}
if (threshold * threshold < min_distance && threshold > 0.0f)
return -1;
return nearest_player_id;
}
s32 findNearestPlayerId(const LiveActor* actor, f32 threshold) {
return findNearestPlayerIdCondition(actor, getTrans(actor), &isDead, threshold);
}
LiveActor* findNearestPlayerActor(const LiveActor* actor) {
return getPlayerActor(actor, findNearestPlayerId(actor, -1.0f));
}
LiveActor* tryFindNearestPlayerActor(const LiveActor* actor) {
s32 nearest_player_id = findNearestPlayerId(actor, -1.0f);
if (nearest_player_id < 0)
return nullptr;
return getPlayerActor(actor, nearest_player_id);
}
const sead::Vector3f& findNearestPlayerPos(const LiveActor* actor) {
return getPlayerPos(actor, findNearestPlayerId(actor, -1.0f));
}
bool tryFindNearestPlayerPos(sead::Vector3f* pos, const LiveActor* actor) {
s32 nearest_player_id = findNearestPlayerId(actor, -1.0f);
if (nearest_player_id < 0)
return false;
al::LiveActor* player = getPlayerActor(actor, nearest_player_id);
if (!player)
return false;
*pos = getTrans(player);
return true;
}
// NON_MATCHING: regalloc (https://decomp.me/scratch/XLeWX)
bool tryFindNearestPlayerDisatanceFromTarget(f32* distance, const LiveActor* actor,
const sead::Vector3f& target) {
s32 nearest_player_id = findNearestPlayerIdCondition(actor, target, &isDead, -1.0f);
if (nearest_player_id < 0)
return false;
LiveActor* player = getPlayerActor(actor, nearest_player_id);
if (!player)
return false;
*distance = (getTrans(player) - target).length();
return true;
}
bool isNearPlayer(const LiveActor* actor, f32 threshold) {
return findNearestPlayerId(actor, threshold) >= 0;
}
// BUG: This only checks the nearest player (overall), not all players
bool isNearPlayerH(const LiveActor* actor, f32 threshold) {
s32 nearest_player_id = findNearestPlayerId(actor, -1.0f);
if (nearest_player_id < 0)
return false;
sead::Vector3f player_pos = getPlayerPos(actor, nearest_player_id);
sead::Vector3f diff = player_pos - getTrans(actor);
f32 hDiff = diff.dot(getGravity(actor));
return (diff - getGravity(actor) * hDiff).length() <= threshold;
}
// BUG: This only checks the nearest player (overall), not all players
bool isNearPlayerHCondition(const LiveActor* actor, f32 threshold,
bool (*condition)(const LiveActor*)) {
s32 nearest_player_id = findNearestPlayerIdCondition(actor, getTrans(actor), condition, -1.0f);
if (nearest_player_id < 0)
return false;
return calcDistanceH(getPlayerActor(actor, nearest_player_id), actor) <= threshold;
}
const sead::Vector3f& getFarPlayerPosMaxX(const LiveActor* actor) {
PlayerHolder* holder = actor->getSceneInfo()->playerHolder;
getTrans(actor);
const LiveActor* far_player = nullptr;
f32 max_x = -1.0f;
for (s32 i = 0; i < getPlayerNumMax(holder); i++) {
LiveActor* player = holder->getPlayer(i);
if (!far_player || max_x < getTrans(player).x) {
max_x = getTrans(player).x;
far_player = player;
}
}
return getTrans(far_player);
}
const sead::Vector3f& getFarPlayerPosMinX(const LiveActor* actor) {
PlayerHolder* holder = actor->getSceneInfo()->playerHolder;
getTrans(actor);
const LiveActor* far_player = nullptr;
f32 max_x = -1.0f;
for (s32 i = 0; i < getPlayerNumMax(holder); i++) {
LiveActor* player = holder->getPlayer(i);
if (!far_player || getTrans(player).x < max_x) {
max_x = getTrans(player).x;
far_player = player;
}
}
return getTrans(far_player);
}
// NON_MATCHING: regalloc and final return being size instead of result_num
// (https://decomp.me/scratch/xg110)
u32 calcPlayerListOrderByDistance(const LiveActor* actor, const LiveActor** actor_list, u32 size) {
u32 player_num = getPlayerNumMax(actor);
const sead::Vector3f& pos = getTrans(actor);
f32 distances[64];
for (u32 i = 0; i != player_num; i++) {
LiveActor* player = getPlayerActor(actor, i);
f32 distance = sead::Mathf::maxNumber();
if (!isDead(player)) {
sead::Vector3f player_pos = getTrans(player);
distance = (player_pos - pos).squaredLength();
}
distances[i] = distance;
}
u32 result_num = 0;
for (result_num = 0; result_num < size; result_num++) {
f32 min_distance = sead::Mathf::maxNumber();
s32 min_index = -1;
for (u32 i = 0; i < player_num; i++) {
if (distances[i] <= min_distance) {
min_distance = distances[i];
min_index = i;
}
}
if (min_index == -1)
break;
actor_list[result_num] = getPlayerActor(actor, min_index);
distances[min_index] = sead::Mathf::maxNumber();
}
return result_num;
}
static void useless(int x) {}
u32 calcAlivePlayerActor(const LiveActor* x, const LiveActor**, u32) {useless(3);return 0;}
LiveActor* tryFindNearestPlayerActorCondition(const LiveActor*, bool (*)(const LiveActor*));
bool tryFindNearestPlayerPosCondition(sead::Vector3f*, const LiveActor*,
bool (*)(const LiveActor*));
bool isResetablePlayerPos(const LiveActor*, const sead::Vector3f&, f32, f32);
bool isResetablePlayerPos(const LiveActor*, f32);
void faceToPlayer(LiveActor*);
} // namespace al
namespace alPlayerFunction {
void registerPlayer(al::LiveActor*, al::PadRumbleKeeper*);
bool isFullPlayerHolder(al::LiveActor*);
s32 findPlayerHolderIndex(const al::LiveActor*);
s32 findPlayerHolderIndex(const al::HitSensor*);
bool isPlayerActor(const al::LiveActor*);
bool isPlayerActor(const al::HitSensor*);
} // namespace alPlayerFunction