OdysseyDecomp/lib/al/Library/LiveActor/ActorAreaFunction.cpp

276 lines
9.9 KiB
C++

#include "Library/LiveActor/ActorAreaFunction.h"
#include "Library/Area/AreaInitInfo.h"
#include "Library/Area/AreaObj.h"
#include "Library/Area/AreaObjDirector.h"
#include "Library/Area/AreaObjGroup.h"
#include "Library/Area/AreaObjMtxConnecter.h"
#include "Library/Area/AreaObjUtil.h"
#include "Library/Area/IUseAreaObj.h"
#include "Library/Area/SwitchKeepOnAreaGroup.h"
#include "Library/Area/SwitchOnAreaGroup.h"
#include "Library/Area/ValidatorBase.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorInitInfo.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/LiveActor/ActorSceneInfo.h"
#include "Library/LiveActor/LiveActor.h"
#include "Library/Math/MathUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Player/PlayerUtil.h"
namespace al {
AreaObj* tryFindAreaObjPlayerOne(const PlayerHolder* holder, const char* name) {
s32 playerNum = getPlayerNumMax(holder);
AreaObj* selectedAreaObj = nullptr;
for (s32 i = 0; i < playerNum; i++) {
if (isPlayerDead(holder, i))
continue;
if (!isAreaTarget(getPlayerActor(holder, i)))
continue;
const sead::Vector3f& playerPos = getPlayerPos(holder, i);
AreaObj* areaObj = tryFindAreaObj(getPlayerActor(holder, i), name, playerPos);
if (areaObj &&
(!selectedAreaObj || selectedAreaObj->getPriority() < areaObj->getPriority())) {
selectedAreaObj = areaObj;
}
}
return selectedAreaObj;
}
AreaObj* tryFindAreaObjPlayerAll(const PlayerHolder* holder, const char* name) {
s32 playerNum = getPlayerNumMax(holder);
if (playerNum == 0)
return nullptr;
AreaObjGroup* areaGroup = tryFindAreaObjGroup(getPlayerActor(holder, 0), name);
if (!areaGroup)
return nullptr;
s32 groupSize = areaGroup->getSize();
AreaObj* selectedAreaObj = nullptr;
for (s32 i = 0; i < groupSize; i++) {
AreaObj* areaObj = areaGroup->getAreaObj(i);
AreaObj* currentAreaObject = nullptr;
for (s32 j = 0; j < playerNum; j++) {
if (isPlayerDead(holder, j))
continue;
const sead::Vector3f& playerPos = getPlayerPos(holder, j);
currentAreaObject = areaObj;
if (!areaObj->isInVolume(playerPos)) {
currentAreaObject = nullptr;
break;
}
}
if (currentAreaObject && (!selectedAreaObj || selectedAreaObj->getPriority() <
currentAreaObject->getPriority())) {
selectedAreaObj = currentAreaObject;
}
}
return selectedAreaObj;
}
AreaObj* createAreaObj(const ActorInitInfo& actorInitInfo, const char* name) {
AreaInitInfo areaInitInfo;
initAreaInitInfo(&areaInitInfo, actorInitInfo);
AreaObj* areaObj = new AreaObj(name);
areaObj->init(areaInitInfo);
return areaObj;
}
void initAreaInitInfo(AreaInitInfo* areaInitInfo, const ActorInitInfo& actorInitInfo) {
initAreaInitInfo(areaInitInfo, *actorInitInfo.placementInfo, actorInitInfo);
}
AreaObj* createLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) {
const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo;
PlacementInfo placementInfo;
getLinksInfoByIndex(&placementInfo, actorPlacementInfo, name, 0);
AreaInitInfo areaInfo;
initAreaInitInfo(&areaInfo, placementInfo, initInfo);
AreaObj* areaObj = new AreaObj(areaName);
areaObj->init(areaInfo);
return areaObj;
}
void initAreaInitInfo(AreaInitInfo* areaInitInfo, const PlacementInfo& placementInfo,
const ActorInitInfo& actorInitInfo) {
areaInitInfo->set(placementInfo, actorInitInfo.stageSwitchDirector,
actorInitInfo.actorSceneInfo.sceneObjHolder);
}
AreaObj* tryCreateLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) {
s32 linkChildNum = calcLinkChildNum(initInfo, name);
if (linkChildNum < 1)
return nullptr;
return createLinkArea(initInfo, name, areaName);
}
__attribute__((always_inline)) AreaObjGroup* createLinkAreaGroup(const ActorInitInfo& initInfo,
const char* name,
const char* groupName,
const char* areaName) {
s32 linkChildNum = calcLinkChildNum(initInfo, name);
if (linkChildNum < 1)
return nullptr;
AreaObjGroup* areaGroup = new AreaObjGroup(groupName, 0);
areaGroup->createBuffer(linkChildNum);
const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo;
for (s32 i = 0; i < linkChildNum; i++) {
PlacementInfo placementInfo;
getLinksInfoByIndex(&placementInfo, actorPlacementInfo, name, i);
AreaInitInfo areaInfo;
initAreaInitInfo(&areaInfo, placementInfo, initInfo);
AreaObj* areaObj = new AreaObj(areaName);
areaObj->init(areaInfo);
areaGroup->registerAreaObj(areaObj);
}
return areaGroup;
}
AreaObjGroup* createLinkAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo, const char* name,
const char* groupName, const char* areaName) {
return createLinkAreaGroup(initInfo, name, groupName, areaName);
}
AreaObj* tryFindAreaObj(const LiveActor* actor, const char* name) {
if (!isAreaTarget(actor))
return nullptr;
return tryFindAreaObj(actor, name, getTrans(actor));
}
bool isInAreaObj(const LiveActor* actor, const char* name) {
if (!isAreaTarget(actor))
return false;
return isInAreaObj(actor, name, getTrans(actor));
}
bool isInDeathArea(const LiveActor* actor) {
if (!isAreaTarget(actor))
return false;
return isInDeathArea(actor, getTrans(actor));
}
bool isInWaterArea(const LiveActor* actor) {
if (!isAreaTarget(actor))
return false;
return isInWaterArea(actor, getTrans(actor));
}
bool isInPlayerControlOffArea(const LiveActor* actor) {
if (!isAreaTarget(actor))
return false;
return isInPlayerControlOffArea(actor, getTrans(actor));
}
f32 calcWaterSinkDepth(const LiveActor* actor) {
return calcWaterSinkDepth(actor, getTrans(actor));
}
void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
const ActorInitInfo& initInfo) {
areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx(
mtx, *initInfo.placementInfo, nullptr);
}
void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
const ActorInitInfo& initInfo, const ValidatorBase& validator) {
areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx(
mtx, *initInfo.placementInfo, validator.fnc_8());
}
void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) {
registerAreaHostMtx(actor, actor->getBaseMtx(), initInfo);
}
void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo,
const ValidatorBase& validator) {
registerAreaHostMtx(actor, actor->getBaseMtx(), initInfo, validator);
}
void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
const ActorInitInfo& initInfo) {
areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx(
mtx, *initInfo.placementInfo, nullptr);
}
void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
const ActorInitInfo& initInfo, const ValidatorBase& validator) {
areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx(
mtx, *initInfo.placementInfo, validator.fnc_8());
}
void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) {
registerAreaSyncHostMtx(actor, actor->getBaseMtx(), initInfo);
}
void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo,
const ValidatorBase& validator) {
registerAreaSyncHostMtx(actor, actor->getBaseMtx(), initInfo, validator);
}
bool tryReviseVelocityInsideAreaObj(sead::Vector3f* nearestEdgePos, LiveActor* actor,
AreaObjGroup* areaGroup, const AreaObj* areaObj) {
if (!areaGroup || !areaObj)
return false;
if (!isInAreaObj(areaGroup, getTrans(actor))) {
calcNearestAreaObjEdgePos(nearestEdgePos, areaObj, getTrans(actor));
setTrans(actor, *nearestEdgePos);
setVelocityZero(actor);
return true;
}
f32 velMagnitude = getVelocity(actor).length();
sead::Vector3f nextPosition = getTrans(actor) + getVelocity(actor);
if (isInAreaObj(areaGroup, nextPosition))
return false;
calcNearestAreaObjEdgePos(nearestEdgePos, areaObj, nextPosition);
sead::Vector3f newVelocity = *nearestEdgePos - getTrans(actor);
if (newVelocity.length() > velMagnitude)
setLength(&newVelocity, velMagnitude);
setVelocity(actor, newVelocity);
return true;
}
SwitchKeepOnAreaGroup* tryCreateSwitchKeepOnAreaGroup(LiveActor* actor,
const ActorInitInfo& initInfo) {
AreaObjGroup* areaGroup =
createLinkAreaGroup(actor, initInfo, "AreaSwitchKeepOn", "子供スイッチキープエリアグループ",
"子供スイッチキープエリア");
if (!areaGroup)
return nullptr;
return new SwitchKeepOnAreaGroup(areaGroup);
}
SwitchOnAreaGroup* tryCreateSwitchOnAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo) {
AreaObjGroup* areaGroup = createLinkAreaGroup(
actor, initInfo, "AreaSwitchOn", "子供スイッチOnエリアグループ", "子供スイッチOnエリア");
if (!areaGroup)
return nullptr;
return new SwitchOnAreaGroup(areaGroup);
}
} // namespace al