mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-23 09:04:21 +00:00
1781 lines
63 KiB
C++
1781 lines
63 KiB
C++
#include "Library/LiveActor/ActorMovementFunction.h"
|
|
|
|
#include "Library/Area/AreaObjUtil.h"
|
|
#include "Library/Audio/System/AudioKeeper.h"
|
|
#include "Library/Collision/Collider.h"
|
|
#include "Library/Collision/CollisionPartsKeeperUtil.h"
|
|
#include "Library/Collision/CollisionPartsTriangle.h"
|
|
#include "Library/HitSensor/SensorFunction.h"
|
|
#include "Library/LiveActor/ActorCollisionFunction.h"
|
|
#include "Library/LiveActor/ActorParamHolder.h"
|
|
#include "Library/LiveActor/ActorPoseKeeper.h"
|
|
#include "Library/LiveActor/ActorPoseUtil.h"
|
|
#include "Library/LiveActor/ActorSensorUtil.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Library/Matrix/MatrixUtil.h"
|
|
#include "Library/Player/PlayerUtil.h"
|
|
#include "Library/Screen/ScreenPointerUtil.h"
|
|
#include "Library/Se/SeKeeper.h"
|
|
|
|
namespace al {
|
|
|
|
inline f32 modDegree(f32 deg) {
|
|
return modf(deg + 360.0f, 360.0f) + 0.0f;
|
|
}
|
|
|
|
void resetPosition(LiveActor* actor) {
|
|
if (actor->getPoseKeeper())
|
|
actor->calcAnim();
|
|
if (actor->getHitSensorKeeper()) {
|
|
alSensorFunction::clearHitSensors(actor);
|
|
alSensorFunction::updateHitSensorsAll(actor);
|
|
}
|
|
if (actor->getScreenPointKeeper())
|
|
alScreenPointFunction::updateScreenPointAll(actor);
|
|
if (actor->getCollider())
|
|
actor->getCollider()->onInvalidate();
|
|
if (actor->getCollisionParts())
|
|
resetAllCollisionMtx(actor);
|
|
if (actor->getAudioKeeper() && actor->getAudioKeeper()->getSeKeeper())
|
|
actor->getAudioKeeper()->getSeKeeper()->resetPosition();
|
|
}
|
|
|
|
void resetPosition(LiveActor* actor, const sead::Vector3f& trans) {
|
|
updatePoseTrans(actor, trans);
|
|
resetPosition(actor);
|
|
}
|
|
|
|
void resetRotatePosition(LiveActor* actor, const sead::Vector3f& rot, const sead::Vector3f& trans) {
|
|
updatePoseRotate(actor, rot);
|
|
resetPosition(actor, trans);
|
|
}
|
|
|
|
void resetQuatPosition(LiveActor* actor, const sead::Quatf& quat, const sead::Vector3f& trans) {
|
|
updatePoseQuat(actor, quat);
|
|
resetPosition(actor, trans);
|
|
}
|
|
|
|
void resetMtxPosition(LiveActor* actor, const sead::Matrix34f& mtx) {
|
|
updatePoseMtx(actor, &mtx);
|
|
resetPosition(actor);
|
|
}
|
|
|
|
void resetActorPosition(LiveActor* actor, const LiveActor* target) {
|
|
resetMtxPosition(actor, *target->getBaseMtx());
|
|
}
|
|
|
|
bool trySetPosOnGround(LiveActor* actor) {
|
|
sead::Vector3f pos = getTrans(actor);
|
|
sead::Vector3f dir = {0.0f, -500.0f, 0.0f};
|
|
pos.y += 200.0f;
|
|
return alCollisionUtil::getFirstPolyOnArrow(actor, getTransPtr(actor), nullptr, pos, dir,
|
|
nullptr, nullptr);
|
|
}
|
|
|
|
const sead::Vector3f& getVelocity(const LiveActor* actor) {
|
|
return actor->getPoseKeeper()->getVelocity();
|
|
}
|
|
|
|
sead::Vector3f* getVelocityPtr(LiveActor* actor) {
|
|
return actor->getPoseKeeper()->getVelocityPtr();
|
|
}
|
|
|
|
void separateVelocityHV(sead::Vector3f* horizontal, sead::Vector3f* vertical,
|
|
const LiveActor* actor) {
|
|
separateVelocityDirHV(horizontal, vertical, actor, getGravity(actor));
|
|
}
|
|
|
|
void separateVelocityDirHV(sead::Vector3f* horizontal, sead::Vector3f* vertical,
|
|
const LiveActor* actor, const sead::Vector3f& dir) {
|
|
separateVectorHV(horizontal, vertical, dir, getVelocity(actor));
|
|
}
|
|
|
|
void separateVelocityParallelVertical(sead::Vector3f* parallel, sead::Vector3f* vertical,
|
|
const LiveActor* actor, const sead::Vector3f& dir) {
|
|
separateVectorParallelVertical(parallel, vertical, dir, getVelocity(actor));
|
|
}
|
|
|
|
void setVelocity(LiveActor* actor, const sead::Vector3f& vel) {
|
|
getVelocityPtr(actor)->set(vel);
|
|
}
|
|
|
|
void setVelocity(LiveActor* actor, f32 x, f32 y, f32 z) {
|
|
getVelocityPtr(actor)->set(x, y, z);
|
|
}
|
|
|
|
void setVelocityX(LiveActor* actor, f32 x) {
|
|
getVelocityPtr(actor)->x = x;
|
|
}
|
|
|
|
void setVelocityY(LiveActor* actor, f32 y) {
|
|
getVelocityPtr(actor)->y = y;
|
|
}
|
|
|
|
void setVelocityZ(LiveActor* actor, f32 z) {
|
|
getVelocityPtr(actor)->z = z;
|
|
}
|
|
|
|
void setVelocityZero(LiveActor* actor) {
|
|
setVelocity(actor, 0.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
void setVelocityZeroX(LiveActor* actor) {
|
|
setVelocityX(actor, 0.0f);
|
|
}
|
|
|
|
void setVelocityZeroY(LiveActor* actor) {
|
|
setVelocityY(actor, 0.0f);
|
|
}
|
|
|
|
void setVelocityZeroZ(LiveActor* actor) {
|
|
setVelocityZ(actor, 0.0f);
|
|
}
|
|
|
|
void setVelocityZeroH(LiveActor* actor) {
|
|
setVelocityZeroH(actor, getGravity(actor));
|
|
}
|
|
|
|
void setVelocityZeroH(LiveActor* actor, const sead::Vector3f& gravity) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
parallelizeVec(velocity, gravity, *velocity);
|
|
}
|
|
|
|
void setVelocityZeroV(LiveActor* actor) {
|
|
setVelocityZeroV(actor, getGravity(actor));
|
|
}
|
|
|
|
void setVelocityZeroV(LiveActor* actor, const sead::Vector3f& gravity) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
verticalizeVec(velocity, gravity, *velocity);
|
|
}
|
|
|
|
void setVelocityJump(LiveActor* actor, f32 speed) {
|
|
getVelocityPtr(actor)->setScale(getGravity(actor), -speed);
|
|
}
|
|
|
|
void setVelocityToFront(LiveActor* actor, f32 speed) {
|
|
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
|
|
calcFrontDir(&front, actor);
|
|
getVelocityPtr(actor)->setScale(front, speed);
|
|
}
|
|
|
|
void setVelocityToUp(LiveActor* actor, f32 speed) {
|
|
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
|
|
calcUpDir(&up, actor);
|
|
getVelocityPtr(actor)->setScale(up, speed);
|
|
}
|
|
|
|
void setVelocityToSide(LiveActor* actor, f32 speed) {
|
|
sead::Vector3f side = {0.0f, 0.0f, 0.0f};
|
|
calcSideDir(&side, actor);
|
|
getVelocityPtr(actor)->setScale(side, speed);
|
|
}
|
|
|
|
void setVelocityToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 speed) {
|
|
sead::Vector3f normDir;
|
|
tryNormalizeOrZero(&normDir, dir);
|
|
getVelocityPtr(actor)->setScale(normDir, speed);
|
|
}
|
|
|
|
void setVelocityToGravity(LiveActor* actor, f32 speed) {
|
|
getVelocityPtr(actor)->setScale(getGravity(actor), speed);
|
|
}
|
|
|
|
void setVelocitySeparateHV(LiveActor* actor, const sead::Vector3f& h, const sead::Vector3f& v,
|
|
f32 speedH, f32 speedV) {
|
|
calcVectorSeparateHV(getVelocityPtr(actor), h, v, speedH, speedV);
|
|
}
|
|
|
|
void setVelocitySeparateHV(LiveActor* actor, const sead::Vector3f& h, f32 speedH, f32 speedV) {
|
|
calcVelocitySeparateHV(getVelocityPtr(actor), actor, h, speedH, speedV);
|
|
}
|
|
|
|
void calcVelocitySeparateHV(sead::Vector3f* velocity, const LiveActor* actor,
|
|
const sead::Vector3f& h, f32 speedH, f32 speedV) {
|
|
calcVectorSeparateHV(velocity, h, -getGravity(actor), speedH, speedV);
|
|
}
|
|
|
|
void setVelocitySeparateUp(LiveActor* actor, const sead::Vector3f& h, f32 speedH, f32 speedV) {
|
|
sead::Vector3f up;
|
|
calcUpDir(&up, actor);
|
|
setVelocitySeparateHV(actor, h, up, speedH, speedV);
|
|
}
|
|
|
|
void setVelocityOnlyDir(LiveActor* actor, const sead::Vector3f& dir, f32 speed) {
|
|
sead::Vector3f normDir;
|
|
tryNormalizeOrZero(&normDir, dir);
|
|
getVelocityPtr(actor)->add(normDir * (speed - normDir.dot(getVelocity(actor))));
|
|
}
|
|
|
|
void setVelocityOnlyV(LiveActor* actor, f32 speed) {
|
|
setVelocityOnlyDir(actor, getGravity(actor), -speed);
|
|
}
|
|
|
|
void setVelocityOnlyGravity(LiveActor* actor, f32 speed) {
|
|
setVelocityOnlyDir(actor, getGravity(actor), speed);
|
|
}
|
|
|
|
void addVelocity(LiveActor* actor, const sead::Vector3f& vel) {
|
|
getVelocityPtr(actor)->add(vel);
|
|
}
|
|
|
|
void addVelocity(LiveActor* actor, f32 x, f32 y, f32 z) {
|
|
addVelocity(actor, {x, y, z});
|
|
}
|
|
|
|
void addVelocityX(LiveActor* actor, f32 x) {
|
|
getVelocityPtr(actor)->x += x;
|
|
}
|
|
|
|
void addVelocityY(LiveActor* actor, f32 y) {
|
|
getVelocityPtr(actor)->y += y;
|
|
}
|
|
|
|
void addVelocityZ(LiveActor* actor, f32 z) {
|
|
getVelocityPtr(actor)->z += z;
|
|
}
|
|
|
|
void addVelocityDump(LiveActor* actor, const sead::Vector3f& dir, f32 force) {
|
|
getVelocity(actor); // unused
|
|
sead::Vector3f accel = dir - getVelocity(actor);
|
|
sead::Vector3f add;
|
|
lerpVec(&add, dir, accel, force);
|
|
addVelocity(actor, add);
|
|
}
|
|
|
|
void addVelocityJump(LiveActor* actor, f32 force) {
|
|
addVelocity(actor, getGravity(actor) * -force);
|
|
}
|
|
|
|
inline void addVelocityInline(LiveActor* actor, const sead::Vector3f& vel, f32 force) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
velocity->setScaleAdd(force, vel, *velocity);
|
|
}
|
|
|
|
void addVelocityToFront(LiveActor* actor, f32 force) {
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
addVelocityInline(actor, front, force);
|
|
}
|
|
|
|
void addVelocityToUp(LiveActor* actor, f32 force) {
|
|
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
|
|
calcUpDir(&up, actor);
|
|
addVelocityInline(actor, up, force);
|
|
}
|
|
|
|
void addVelocityToSide(LiveActor* actor, f32 force) {
|
|
sead::Vector3f side = {0.0f, 0.0f, 0.0f};
|
|
calcSideDir(&side, actor);
|
|
addVelocityInline(actor, side, force);
|
|
}
|
|
|
|
void addVelocityToDown(LiveActor* actor, f32 force) {
|
|
sead::Vector3f down = {0.0f, 0.0f, 0.0f};
|
|
calcDownDir(&down, actor);
|
|
addVelocityInline(actor, down, force);
|
|
}
|
|
|
|
void addVelocityToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 force) {
|
|
sead::Vector3f normDir;
|
|
tryNormalizeOrZero(&normDir, dir);
|
|
addVelocityInline(actor, normDir, force);
|
|
}
|
|
|
|
void addVelocityToGravity(LiveActor* actor, f32 force) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
velocity->setScaleAdd(force, getGravity(actor), *velocity);
|
|
}
|
|
|
|
void addVelocityToGravityLimit(LiveActor* actor, f32 force, f32 limit) {
|
|
addVectorLimit(getVelocityPtr(actor), getGravity(actor) * force, limit);
|
|
}
|
|
|
|
void addVelocityToGravityFittedGround(LiveActor* actor, f32 force, u32 maxAirTime) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
const sead::Vector3f& normal = getOnGroundNormal(actor, maxAirTime);
|
|
// TODO maybe this should be a Vector3::subScale() method?
|
|
velocity->x -= normal.x * force;
|
|
velocity->y -= normal.y * force;
|
|
velocity->z -= normal.z * force;
|
|
}
|
|
|
|
void addVelocityToGravityNaturalOrFittedGround(LiveActor* actor, f32 force) {
|
|
sead::Vector3f gravity = sead::Vector3f::zero;
|
|
calcGravityDir(&gravity, actor);
|
|
addVelocityInline(actor, gravity, force);
|
|
}
|
|
|
|
void calcGravityDir(sead::Vector3f* gravity, const LiveActor* actor) {
|
|
if (isCollidedGround(actor))
|
|
*gravity = -getOnGroundNormal(actor, 0);
|
|
else
|
|
gravity->set(getGravity(actor));
|
|
tryNormalizeOrZero(gravity);
|
|
}
|
|
|
|
void addVelocityToTarget(LiveActor* actor, const sead::Vector3f& target, f32 force) {
|
|
sead::Vector3f diff = target;
|
|
diff -= getTrans(actor);
|
|
tryNormalizeOrZero(&diff);
|
|
addVelocityInline(actor, diff, force);
|
|
}
|
|
|
|
void addVelocityToTarget(LiveActor* actor, const sead::Vector3f& target, f32 minForce, f32 maxForce,
|
|
f32 minDistance, f32 maxDistance) {
|
|
sead::Vector3f diff = target;
|
|
diff -= getTrans(actor);
|
|
f32 distance;
|
|
separateScalarAndDirection(&distance, &diff, diff);
|
|
f32 normDistance = normalize(distance, minDistance, maxDistance);
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
f32 force = lerpValue(minForce, maxForce, normDistance);
|
|
velocity->setScaleAdd(force, diff, *velocity);
|
|
}
|
|
|
|
void addVelocityToTargetH(LiveActor* actor, const sead::Vector3f& target, f32 force) {
|
|
sead::Vector3f diff = target;
|
|
diff -= getTrans(actor);
|
|
verticalizeVec(&diff, getGravity(actor), diff);
|
|
tryNormalizeOrZero(&diff);
|
|
addVelocityInline(actor, diff, force);
|
|
}
|
|
|
|
void addVelocityToTargetHV(LiveActor* actor, const sead::Vector3f& target, f32 forceH, f32 forceV) {
|
|
sead::Vector3f diff = target;
|
|
diff -= getTrans(actor);
|
|
f32 diffDown = diff.dot(getGravity(actor));
|
|
sead::Vector3f diffV = diffDown * getGravity(actor);
|
|
sead::Vector3f diffH = diff - diffV;
|
|
tryNormalizeOrZero(&diffH);
|
|
tryNormalizeOrZero(&diffV);
|
|
addVelocityInline(actor, diffH, forceH);
|
|
addVelocityInline(actor, diffV, forceV);
|
|
}
|
|
|
|
void addVelocityDampToTarget(LiveActor* actor, const sead::Vector3f& target, f32 forceDamp) {
|
|
addVelocityDampToTarget(actor, target, forceDamp, forceDamp);
|
|
}
|
|
|
|
void addVelocityDampToTarget(LiveActor* actor, const sead::Vector3f& target, f32 force, f32 damp) {
|
|
sead::Vector3f diff = (target - getTrans(actor)) * force;
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
lerpVec(velocity, *velocity, diff, damp);
|
|
}
|
|
|
|
bool addVelocityToPlayer(LiveActor* actor, f32 force, const sead::Vector3f& offset) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
|
|
addVelocityToTarget(actor, playerPos + offset, force);
|
|
return true;
|
|
}
|
|
|
|
bool addVelocityToPlayerHV(LiveActor* actor, f32 forceH, f32 forceV, const sead::Vector3f& offset) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
|
|
addVelocityToTargetHV(actor, playerPos + offset, forceH, forceV);
|
|
return true;
|
|
}
|
|
|
|
void addVelocityFromTarget(LiveActor* actor, const sead::Vector3f& target, f32 force) {
|
|
sead::Vector3f diff = getTrans(actor);
|
|
diff -= target;
|
|
tryNormalizeOrZero(&diff);
|
|
addVelocityInline(actor, diff, force);
|
|
}
|
|
|
|
void addVelocityFromTargetHV(LiveActor* actor, const sead::Vector3f& target, f32 forceH,
|
|
f32 forceV) {
|
|
sead::Vector3f diff = getTrans(actor);
|
|
diff -= target;
|
|
f32 diffDown = diff.dot(getGravity(actor));
|
|
sead::Vector3f diffV = diffDown * getGravity(actor);
|
|
sead::Vector3f diffH = diff - diffV;
|
|
tryNormalizeOrZero(&diffH);
|
|
tryNormalizeOrZero(&diffV);
|
|
addVelocityInline(actor, diffH, forceH);
|
|
addVelocityInline(actor, diffV, forceV);
|
|
}
|
|
|
|
bool addVelocityFromPlayer(LiveActor* actor, f32 force, const sead::Vector3f& offset) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
|
|
addVelocityFromTarget(actor, playerPos + offset, force);
|
|
return true;
|
|
}
|
|
|
|
bool addVelocityFromPlayerHV(LiveActor* actor, f32 forceH, f32 forceV,
|
|
const sead::Vector3f& offset) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
|
|
addVelocityFromTargetHV(actor, playerPos + offset, forceH, forceV);
|
|
return true;
|
|
}
|
|
|
|
void addVelocityClockwiseToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 force) {
|
|
sead::Vector3f dirVelocity;
|
|
if (!calcVelocityClockwiseToDirection(actor, &dirVelocity, dir))
|
|
return;
|
|
sead::Vector3f normDir;
|
|
tryNormalizeOrZero(&normDir, dirVelocity);
|
|
addVelocityInline(actor, normDir, force);
|
|
}
|
|
|
|
bool calcVelocityClockwiseToDirection(LiveActor* actor, sead::Vector3f* dirVelocity,
|
|
const sead::Vector3f& dir) {
|
|
sead::Vector3f normDir;
|
|
if (!dirVelocity || !tryNormalizeOrZero(&normDir, dir))
|
|
return false;
|
|
|
|
dirVelocity->setCross(getGravity(actor), normDir);
|
|
return true;
|
|
}
|
|
|
|
void addVelocityClockwiseToTarget(LiveActor* actor, const sead::Vector3f& target, f32 force) {
|
|
addVelocityClockwiseToDirection(actor, target - getTrans(actor), force);
|
|
}
|
|
|
|
void addVelocityJumpGroundInertia(LiveActor* actor, const sead::Vector3f& velocity, f32 force) {
|
|
sead::Vector3f inertia = {0.0f, 0.0f, 0.0f};
|
|
calcJumpInertia(&inertia, actor, velocity, force);
|
|
addVelocity(actor, inertia);
|
|
}
|
|
|
|
void tryAddVelocityLimit(LiveActor* actor, const sead::Vector3f& velocity, f32 limit) {
|
|
sead::Vector3f newVelocity = getVelocity(actor);
|
|
addVectorLimit(&newVelocity, velocity, limit);
|
|
setVelocity(actor, newVelocity);
|
|
}
|
|
|
|
void subVelocityExceptDirectionLimit(LiveActor* actor, const sead::Vector3f& direction, f32 subVel,
|
|
f32 limit) {
|
|
sead::Vector3f horizontal = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityDirHV(&horizontal, &vertical, actor, direction);
|
|
|
|
f32 length = horizontal.length();
|
|
f32 newLen = sead::Mathf::clampMin(length - subVel, limit);
|
|
// TODO sead function to scale a vector to a certain length?
|
|
f32 lenAgain = horizontal.length();
|
|
if (lenAgain > 0.0f)
|
|
horizontal *= newLen / lenAgain;
|
|
|
|
setVelocity(actor, horizontal + vertical);
|
|
}
|
|
|
|
void scaleVelocity(LiveActor* actor, f32 factor) {
|
|
*getVelocityPtr(actor) *= factor;
|
|
}
|
|
|
|
void scaleVelocityLimit(LiveActor* actor, f32 factor, f32 limit) {
|
|
sead::Vector3f direction = {0.0f, 0.0f, 0.0f};
|
|
f32 scalar = 0.0f;
|
|
if (separateScalarAndDirection(&scalar, &direction, getVelocity(actor)))
|
|
return;
|
|
|
|
// enforces a *lower* limit = minimum speed!
|
|
if (scalar < limit)
|
|
return;
|
|
scalar = sead::Mathf::clampMin(scalar * factor, limit);
|
|
setVelocity(actor, scalar * direction);
|
|
}
|
|
|
|
void scaleVelocityX(LiveActor* actor, f32 factorX) {
|
|
getVelocityPtr(actor)->x *= factorX;
|
|
}
|
|
|
|
void scaleVelocityY(LiveActor* actor, f32 factorY) {
|
|
getVelocityPtr(actor)->y *= factorY;
|
|
}
|
|
|
|
void scaleVelocityZ(LiveActor* actor, f32 factorZ) {
|
|
getVelocityPtr(actor)->z *= factorZ;
|
|
}
|
|
|
|
void scaleVelocityHV(LiveActor* actor, f32 factorH, f32 factorV) {
|
|
scaleVelocityParallelVertical(actor, getGravity(actor), factorV, factorH);
|
|
}
|
|
|
|
void scaleVelocityDirection(LiveActor* actor, const sead::Vector3f& direction, f32 factor) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
scaleVectorDirection(velocity, direction, *velocity, factor);
|
|
}
|
|
|
|
void scaleVelocityExceptDirection(LiveActor* actor, const sead::Vector3f& direction, f32 factor) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
scaleVectorExceptDirection(velocity, direction, *velocity, factor);
|
|
}
|
|
|
|
void scaleVelocityParallelVertical(LiveActor* actor, const sead::Vector3f& direction, f32 parallel,
|
|
f32 vertical) {
|
|
const sead::Vector3f& velocity = getVelocity(actor);
|
|
|
|
f32 speedV = direction.dot(velocity);
|
|
sead::Vector3f parallelVec = direction * (speedV * parallel);
|
|
sead::Vector3f verticalVec = velocity;
|
|
// TODO sead subScale ?
|
|
verticalVec.x -= direction.x * speedV;
|
|
verticalVec.y -= direction.y * speedV;
|
|
verticalVec.z -= direction.z * speedV;
|
|
|
|
sead::Vector3f* newVelocity = getVelocityPtr(actor);
|
|
*newVelocity = parallelVec;
|
|
newVelocity->setScaleAdd(vertical, verticalVec, parallelVec);
|
|
}
|
|
|
|
void limitVelocity(LiveActor* actor, f32 limit) {
|
|
if (calcSpeed(actor) > limit) {
|
|
tryNormalizeOrZero(getVelocityPtr(actor));
|
|
scaleVelocity(actor, limit);
|
|
}
|
|
}
|
|
|
|
f32 calcSpeed(const LiveActor* actor) {
|
|
return getVelocity(actor).length();
|
|
}
|
|
|
|
void limitVelocityX(LiveActor* actor, f32 limitX) {
|
|
if (getVelocity(actor).x > limitX)
|
|
getVelocityPtr(actor)->x = limitX;
|
|
else if (getVelocity(actor).x < -limitX)
|
|
getVelocityPtr(actor)->x = -limitX;
|
|
}
|
|
|
|
void limitVelocityY(LiveActor* actor, f32 limitY) {
|
|
if (getVelocity(actor).y > limitY)
|
|
getVelocityPtr(actor)->y = limitY;
|
|
else if (getVelocity(actor).y < -limitY)
|
|
getVelocityPtr(actor)->y = -limitY;
|
|
}
|
|
|
|
void limitVelocityZ(LiveActor* actor, f32 limitZ) {
|
|
if (getVelocity(actor).z > limitZ)
|
|
getVelocityPtr(actor)->z = limitZ;
|
|
else if (getVelocity(actor).z < -limitZ)
|
|
getVelocityPtr(actor)->z = -limitZ;
|
|
}
|
|
|
|
void limitVelocityH(LiveActor* actor, f32 limitH) {
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f horizontal = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(&vertical, &horizontal, actor, getGravity(actor));
|
|
if (horizontal.squaredLength() > sead::Mathf::square(limitH)) {
|
|
f32 length = horizontal.length();
|
|
if (length > 0.0f)
|
|
horizontal *= limitH / length;
|
|
}
|
|
setVelocity(actor, vertical + horizontal);
|
|
}
|
|
|
|
void limitVelocityHV(LiveActor* actor, f32 limitH, f32 limitV) {
|
|
sead::Vector3f horizontal, vertical;
|
|
separateVelocityHV(&horizontal, &vertical, actor);
|
|
if (horizontal.squaredLength() > sead::Mathf::square(limitH)) {
|
|
f32 length = horizontal.length();
|
|
if (length > 0.0f)
|
|
horizontal *= limitH / length;
|
|
}
|
|
if (vertical.squaredLength() > sead::Mathf::square(limitV)) {
|
|
f32 length = vertical.length();
|
|
if (length > 0.0f)
|
|
vertical *= limitV / length;
|
|
}
|
|
setVelocity(actor, horizontal + vertical);
|
|
}
|
|
|
|
void limitVelocityUpGravityH(LiveActor* actor, f32 limitDown, f32 limitUp, f32 limitH) {
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f horizontal = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(&vertical, &horizontal, actor, getGravity(actor));
|
|
if (horizontal.squaredLength() > sead::Mathf::square(limitH)) {
|
|
f32 length = horizontal.length();
|
|
if (length > 0.0f)
|
|
horizontal *= limitH / length;
|
|
}
|
|
|
|
f32 speedV = vertical.dot(getGravity(actor));
|
|
if (speedV > limitUp)
|
|
vertical = getGravity(actor) * limitUp;
|
|
f32 negLimitDown = -limitDown;
|
|
if (speedV < negLimitDown)
|
|
vertical = getGravity(actor) * negLimitDown;
|
|
setVelocity(actor, vertical + horizontal);
|
|
}
|
|
|
|
void limitVelocityDir(LiveActor* actor, const sead::Vector3f& dir, f32 limit) {
|
|
sead::Vector3f parallel = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(¶llel, &vertical, actor, dir);
|
|
if (parallel.squaredLength() > sead::Mathf::square(limit)) {
|
|
f32 length = parallel.length();
|
|
if (length > 0.0f)
|
|
parallel *= limit / length;
|
|
}
|
|
setVelocity(actor, parallel + vertical);
|
|
}
|
|
|
|
void limitVelocityDirSign(LiveActor* actor, const sead::Vector3f& dir, f32 limit) {
|
|
sead::Vector3f parallel = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(¶llel, &vertical, actor, dir);
|
|
if (dir.dot(parallel) < 0.0f)
|
|
return;
|
|
|
|
if (parallel.squaredLength() > sead::Mathf::square(limit)) {
|
|
f32 length = parallel.length();
|
|
if (length > 0.0f)
|
|
parallel *= limit / length;
|
|
}
|
|
setVelocity(actor, parallel + vertical);
|
|
}
|
|
|
|
void limitVelocityDirV(LiveActor* actor, const sead::Vector3f& dir, f32 limit) {
|
|
sead::Vector3f parallel = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(¶llel, &vertical, actor, dir);
|
|
if (vertical.squaredLength() > sead::Mathf::square(limit)) {
|
|
f32 length = vertical.length();
|
|
if (length > 0.0f)
|
|
vertical *= limit / length;
|
|
}
|
|
setVelocity(actor, parallel + vertical);
|
|
}
|
|
|
|
void limitVelocityDirVRate(LiveActor* actor, const sead::Vector3f& dir, f32 limit, f32 rate) {
|
|
sead::Vector3f parallel = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f vertical = {0.0f, 0.0f, 0.0f};
|
|
separateVelocityParallelVertical(¶llel, &vertical, actor, dir);
|
|
if (vertical.squaredLength() > sead::Mathf::square(limit)) {
|
|
f32 length1 = vertical.length();
|
|
f32 length = vertical.length();
|
|
if (length > 0.0f)
|
|
vertical *= ((length1 - limit) * rate + limit) / length;
|
|
}
|
|
setVelocity(actor, parallel + vertical);
|
|
}
|
|
|
|
void limitVelocityParallelVertical(LiveActor* actor, const sead::Vector3f& dir, f32 parallel,
|
|
f32 vertical) {
|
|
limitVectorParallelVertical(getVelocityPtr(actor), dir, parallel, vertical);
|
|
}
|
|
|
|
void limitVelocitySeparateHV(LiveActor* actor, const sead::Vector3f& dir, f32 horizontal,
|
|
f32 vertical) {
|
|
limitVectorSeparateHV(getVelocityPtr(actor), dir, horizontal, vertical);
|
|
}
|
|
|
|
u32 reboundVelocityPart(LiveActor* actor, f32 rebound, f32 threshold) {
|
|
return reboundVelocityPart(actor, rebound, rebound, rebound, threshold);
|
|
}
|
|
|
|
u32 reboundVelocityPart(LiveActor* actor, f32 ground, f32 wall, f32 ceiling, f32 threshold) {
|
|
u32 result = 0;
|
|
if (isCollidedGround(actor)) {
|
|
sead::Vector3f normal = getCollidedGroundNormal(actor);
|
|
f32 dot = normal.dot(getVelocity(actor));
|
|
if (ground < 0.0f || dot < -threshold) {
|
|
addVelocity(actor, -(normal * ((ground + 1.0f) * dot)));
|
|
if (ground >= 0.0f)
|
|
result |= 1;
|
|
} else if (dot < 0.0f) {
|
|
addVelocity(actor, -(normal * dot));
|
|
}
|
|
}
|
|
|
|
if (isCollidedWall(actor)) {
|
|
sead::Vector3f normal = getCollidedWallNormal(actor);
|
|
f32 dot = normal.dot(getVelocity(actor));
|
|
if (wall < 0.0f || dot < -threshold) {
|
|
addVelocity(actor, -(normal * ((wall + 1.0f) * dot)));
|
|
if (wall >= 0.0f)
|
|
result |= 2;
|
|
} else if (dot < 0.0f) {
|
|
addVelocity(actor, -(normal * dot));
|
|
}
|
|
}
|
|
|
|
if (isCollidedCeiling(actor)) {
|
|
sead::Vector3f normal = getCollidedCeilingNormal(actor);
|
|
f32 dot = normal.dot(getVelocity(actor));
|
|
if (ceiling < 0.0f || dot < -threshold) {
|
|
addVelocity(actor, -(normal * ((ceiling + 1.0f) * dot)));
|
|
if (ceiling >= 0.0f)
|
|
result |= 4;
|
|
} else if (dot < 0.0f) {
|
|
addVelocity(actor, -(normal * dot));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool reboundVelocityFromEachCollision(LiveActor* actor, f32 ground, f32 wall, f32 ceiling,
|
|
f32 threshold) {
|
|
if (!isCollided(actor))
|
|
return false;
|
|
|
|
sead::Vector3f normalSum;
|
|
calcCollidedNormalSum(actor, &normalSum);
|
|
if (isNearZero(normalSum, 0.001f))
|
|
return false;
|
|
|
|
normalize(&normalSum);
|
|
const sead::Vector3f& gravity = getGravity(actor);
|
|
f32 rebound;
|
|
if (isFloorPolygon(normalSum, gravity))
|
|
rebound = ground;
|
|
else if (isWallPolygon(normalSum, gravity))
|
|
rebound = wall;
|
|
else if (isCeilingPolygon(normalSum, gravity))
|
|
rebound = ceiling;
|
|
else
|
|
rebound = 0.0f;
|
|
|
|
f32 dot = normalSum.dot(getVelocity(actor));
|
|
if (dot < -threshold) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
f32 mul = (rebound + 1.0f) * dot;
|
|
velocity->setScaleAdd(-mul, normalSum, *velocity);
|
|
return true;
|
|
} else if (dot < 0.0f) {
|
|
sead::Vector3f* velocity = getVelocityPtr(actor);
|
|
velocity->setScaleAdd(-dot, normalSum, *velocity);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool reboundVelocityFromCollision(LiveActor* actor, f32 reboundStrength, f32 reboundMin,
|
|
f32 friction) {
|
|
if (!isCollided(actor))
|
|
return false;
|
|
|
|
sead::Vector3f normalSum;
|
|
calcCollidedNormalSum(actor, &normalSum);
|
|
if (isNearZero(normalSum, 0.001f))
|
|
return false;
|
|
|
|
normalize(&normalSum);
|
|
f32 dot = normalSum.dot(getVelocity(actor));
|
|
if (dot < -reboundMin) {
|
|
*getVelocityPtr(actor) -= normalSum * dot;
|
|
scaleVelocity(actor, friction);
|
|
*getVelocityPtr(actor) -= normalSum * dot * reboundStrength;
|
|
return true;
|
|
} else if (dot < 0.0f) {
|
|
*getVelocityPtr(actor) -= normalSum * dot;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool reboundVelocityFromTriangles(LiveActor* actor, f32 reboundStrength, f32 reboundMin) {
|
|
Collider* collider = getActorCollider(actor);
|
|
s32 planeCount = collider->getPlaneCount();
|
|
if (collider->get_48() == 0)
|
|
return false;
|
|
|
|
bool isRebound = false;
|
|
for (s32 i = 0; i != planeCount; i++) {
|
|
sead::Vector3f normal = collider->getPlane(i)->getNormal(0);
|
|
f32 dot = normal.dot(getVelocity(actor));
|
|
if (reboundStrength < 0.0) {
|
|
addVelocity(actor, -((reboundStrength + 1.0f) * dot * normal));
|
|
isRebound = true;
|
|
} else if (dot < -reboundMin) {
|
|
addVelocity(actor, -((reboundStrength + 1.0f) * dot * normal));
|
|
isRebound = true;
|
|
} else if (dot < 0.0)
|
|
addVelocity(actor, -(dot * normal));
|
|
}
|
|
|
|
return isRebound;
|
|
}
|
|
|
|
bool reboundVelocityFromActor(LiveActor* actor, const LiveActor* target, f32 reboundStrength) {
|
|
return reboundVelocityFromActor(actor, target, getVelocity(target), reboundStrength);
|
|
}
|
|
|
|
ALWAYS_INLINE bool reboundVelocityFromActorInline(LiveActor* actor, const LiveActor* target,
|
|
const sead::Vector3f& targetVelocity,
|
|
f32 reboundStrength) {
|
|
sead::Vector3f direction;
|
|
calcDirToActor(&direction, actor, target);
|
|
f32 dot = (getVelocity(actor) - targetVelocity).dot(direction);
|
|
if (dot <= 0.0f) // moving away from each other
|
|
return false;
|
|
|
|
addVelocity(actor, direction * dot * -(reboundStrength + 1.0f));
|
|
return true;
|
|
}
|
|
|
|
bool reboundVelocityFromActor(LiveActor* actor, const LiveActor* target,
|
|
const sead::Vector3f& targetVelocity, f32 reboundStrength) {
|
|
return reboundVelocityFromActorInline(actor, target, targetVelocity, reboundStrength);
|
|
}
|
|
|
|
bool reboundVelocityFromSensor(LiveActor* actor, const HitSensor* sensor, f32 reboundStrength) {
|
|
return reboundVelocityFromSensor(actor, sensor, getActorVelocity(sensor), reboundStrength);
|
|
}
|
|
|
|
bool reboundVelocityFromSensor(LiveActor* actor, const HitSensor* sensor,
|
|
const sead::Vector3f& targetVelocity, f32 reboundStrength) {
|
|
return reboundVelocityFromActorInline(actor, getSensorHost(sensor), targetVelocity,
|
|
reboundStrength);
|
|
}
|
|
|
|
bool calcDirToActor(sead::Vector3f* dir, const LiveActor* actor, const LiveActor* target) {
|
|
dir->setSub(getTrans(target), getTrans(actor));
|
|
return !tryNormalizeOrZero(dir);
|
|
}
|
|
|
|
bool reboundVelocityBetweenActor(LiveActor* actor, LiveActor* target,
|
|
const sead::Vector3f& direction, f32 reboundStrength);
|
|
|
|
bool reboundVelocityBetweenActor(LiveActor* actor, LiveActor* target, f32 reboundStrength) {
|
|
sead::Vector3f direction;
|
|
calcDirToActor(&direction, actor, target);
|
|
return reboundVelocityBetweenActor(actor, target, direction, reboundStrength);
|
|
}
|
|
|
|
bool reboundVelocityBetweenActor(LiveActor* actor, LiveActor* target,
|
|
const sead::Vector3f& direction, f32 reboundStrength) {
|
|
f32 dot = (getVelocity(actor) - getVelocity(target)).dot(direction);
|
|
if (dot <= 0.0f) // moving away from each other
|
|
return false;
|
|
sead::Vector3f vel = direction * dot * ((reboundStrength + 1.0f) * 0.5f);
|
|
addVelocity(target, vel);
|
|
addVelocity(actor, -vel);
|
|
return true;
|
|
}
|
|
|
|
bool reboundVelocityBetweenSensor(HitSensor* sensorA, HitSensor* sensorB, f32 reboundStrength) {
|
|
sead::Vector3f direction;
|
|
calcDirBetweenSensors(&direction, sensorA, sensorB);
|
|
return reboundVelocityBetweenActor(getSensorHost(sensorA), getSensorHost(sensorB), direction,
|
|
reboundStrength);
|
|
}
|
|
|
|
void calcVelocityKeepLengthBetweenActor(sead::Vector3f* vel, const LiveActor* actor,
|
|
const LiveActor* target, f32 targetLength, f32 force) {
|
|
sead::Vector3f dir;
|
|
dir.setSub(getTrans(target), getTrans(actor));
|
|
f32 len = dir.length();
|
|
tryNormalizeOrDirZ(&dir);
|
|
*vel = (targetLength - len) * dir * force * 0.5f;
|
|
}
|
|
|
|
void addVelocityKeepLengthBetweenActor(LiveActor* actor, LiveActor* target, f32 targetLength,
|
|
f32 force) {
|
|
sead::Vector3f vel;
|
|
calcVelocityKeepLengthBetweenActor(&vel, actor, target, targetLength, force);
|
|
addVelocity(actor, -vel);
|
|
addVelocity(target, vel);
|
|
}
|
|
|
|
void addVelocityDumpKeepLengthBetweenActor(LiveActor* actor, LiveActor* target, f32 targetLength,
|
|
f32 lenForce, f32 dumpForce) {
|
|
sead::Vector3f vel;
|
|
calcVelocityKeepLengthBetweenActor(&vel, actor, target, targetLength, lenForce);
|
|
addVelocityDump(actor, -vel, dumpForce);
|
|
addVelocityDump(target, vel, dumpForce);
|
|
}
|
|
|
|
void calcVelocityBlowAttack(sead::Vector3f* velocity, const LiveActor* actor,
|
|
const sead::Vector3f& trans, f32 speedH, f32 speedV) {
|
|
calcVelocitySeparateHV(velocity, actor, getTrans(actor) - trans, speedH, speedV);
|
|
}
|
|
|
|
void addVelocityBlowAttack(LiveActor* actor, const sead::Vector3f& trans, f32 speedH, f32 speedV) {
|
|
sead::Vector3f velocity;
|
|
calcVelocityBlowAttack(&velocity, actor, trans, speedH, speedV);
|
|
addVelocity(actor, velocity);
|
|
}
|
|
|
|
void addVelocityBlowAttack(LiveActor* actor, const HitSensor* sensor, f32 speedH, f32 speedV) {
|
|
addVelocityBlowAttack(actor, getSensorPos(sensor), speedH, speedV);
|
|
}
|
|
|
|
void setVelocityBlowAttack(LiveActor* actor, const sead::Vector3f& trans, f32 speedH, f32 speedV) {
|
|
setVelocitySeparateHV(actor, getTrans(actor) - trans, speedH, speedV);
|
|
}
|
|
|
|
void setVelocityBlowAttack(LiveActor* actor, const HitSensor* sensor, f32 speedH, f32 speedV) {
|
|
setVelocitySeparateHV(actor, getTrans(actor) - getSensorPos(sensor), speedH, speedV);
|
|
}
|
|
|
|
void setVelocityBlowAttackAndTurnToTarget(LiveActor* actor, const sead::Vector3f& target,
|
|
f32 speedH, f32 speedV) {
|
|
sead::Vector3f dir = getTrans(actor) - target;
|
|
bool isValidDir = tryNormalizeOrZero(&dir);
|
|
setVelocitySeparateHV(actor, dir, speedH, speedV);
|
|
if (!isValidDir)
|
|
return;
|
|
sead::Quatf quat;
|
|
makeQuatUpFront(&quat, -getGravity(actor), -dir);
|
|
updatePoseQuat(actor, quat);
|
|
}
|
|
|
|
bool isVelocityFast(const LiveActor* actor, f32 threshold) {
|
|
return getVelocity(actor).squaredLength() > sead::Mathf::square(threshold);
|
|
}
|
|
|
|
bool isVelocityFastH(const LiveActor* actor, f32 threshold) {
|
|
sead::Vector3f velocity = getVelocity(actor);
|
|
verticalizeVec(&velocity, getGravity(actor), velocity);
|
|
return sead::Mathf::square(threshold) < velocity.squaredLength();
|
|
}
|
|
|
|
bool isVelocitySlow(const LiveActor* actor, f32 threshold) {
|
|
return getVelocity(actor).squaredLength() < sead::Mathf::square(threshold);
|
|
}
|
|
|
|
bool isVelocitySlowH(const LiveActor* actor, f32 threshold) {
|
|
sead::Vector3f velocity = getVelocity(actor);
|
|
verticalizeVec(&velocity, getGravity(actor), velocity);
|
|
return velocity.squaredLength() < sead::Mathf::square(threshold);
|
|
}
|
|
|
|
f32 calcSpeedH(const LiveActor* actor) {
|
|
sead::Vector3f velocityH;
|
|
verticalizeVec(&velocityH, getGravity(actor), getVelocity(actor));
|
|
return velocityH.length();
|
|
}
|
|
|
|
f32 calcSpeedV(const LiveActor* actor) {
|
|
return -getVelocity(actor).dot(getGravity(actor));
|
|
}
|
|
|
|
f32 calcSpeedDirection(const LiveActor* actor, const sead::Vector3f& dir) {
|
|
return sead::Mathf::abs(getVelocity(actor).dot(dir));
|
|
}
|
|
|
|
f32 calcSpeedExceptDir(const LiveActor* actor, const sead::Vector3f& dir) {
|
|
sead::Vector3f velocityExceptDir = {0.0f, 0.0f, 0.0f};
|
|
verticalizeVec(&velocityExceptDir, dir, getVelocity(actor));
|
|
return velocityExceptDir.length();
|
|
}
|
|
|
|
bool isNear(const LiveActor* actor, const LiveActor* target, f32 threshold) {
|
|
return isNear(actor, getTrans(target), threshold);
|
|
}
|
|
|
|
bool isNear(const LiveActor* actor, const sead::Vector3f& trans, f32 threshold) {
|
|
return (getTrans(actor) - trans).squaredLength() < sead::Mathf::square(threshold);
|
|
}
|
|
|
|
bool isNearXZ(const LiveActor* actor, const sead::Vector3f& trans, f32 threshold) {
|
|
const sead::Vector3f& actorTrans = getTrans(actor);
|
|
return sead::Mathf::square(actorTrans.x - trans.x) +
|
|
sead::Mathf::square(actorTrans.z - trans.z) <
|
|
sead::Mathf::square(threshold);
|
|
}
|
|
|
|
bool isNearH(const LiveActor* actor, const sead::Vector3f& trans, f32 threshold) {
|
|
return calcDistanceH(actor, trans) < threshold;
|
|
}
|
|
|
|
f32 calcDistanceH(const LiveActor* actor, const sead::Vector3f& trans) {
|
|
sead::Vector3f dist;
|
|
verticalizeVec(&dist, getGravity(actor), trans - getTrans(actor));
|
|
return dist.length();
|
|
}
|
|
|
|
bool isNearV(const LiveActor* actor, const sead::Vector3f& trans, f32 threshold) {
|
|
return calcDistanceV(actor, trans) < threshold;
|
|
}
|
|
|
|
f32 calcDistanceV(const LiveActor* actor, const sead::Vector3f& trans) {
|
|
const sead::Vector3f& gravity = getGravity(actor);
|
|
return sead::Mathf::abs((trans - getTrans(actor)).dot(gravity));
|
|
}
|
|
|
|
bool isNearHV(const LiveActor* actor, const sead::Vector3f& trans, f32 threshH, f32 threshV) {
|
|
if (calcDistanceV(actor, trans) > threshV)
|
|
return false;
|
|
return isNearH(actor, trans, threshH);
|
|
}
|
|
|
|
bool isNearHV(const LiveActor* actor, const sead::Vector3f& trans, f32 threshH, f32 minV,
|
|
f32 maxV) {
|
|
f32 height = calcHeight(actor, trans);
|
|
if (height < minV || height > maxV)
|
|
return false;
|
|
return isNearH(actor, trans, threshH);
|
|
}
|
|
|
|
f32 calcHeight(const LiveActor* actor, const sead::Vector3f& trans) {
|
|
const sead::Vector3f& gravity = getGravity(actor);
|
|
return -(trans - getTrans(actor)).dot(gravity);
|
|
}
|
|
|
|
bool isFar(const LiveActor* actor, const LiveActor* target, f32 threshold) {
|
|
return isFar(actor, getTrans(target), threshold);
|
|
}
|
|
|
|
bool isFar(const LiveActor* actor, const sead::Vector3f& trans, f32 threshold) {
|
|
return (getTrans(actor) - trans).squaredLength() > sead::Mathf::square(threshold);
|
|
}
|
|
|
|
f32 calcDistance(const LiveActor* actor, const LiveActor* target) {
|
|
return calcDistance(actor, getTrans(target));
|
|
}
|
|
|
|
f32 calcDistance(const LiveActor* actor, const sead::Vector3f& trans) {
|
|
return (getTrans(actor) - trans).length();
|
|
}
|
|
|
|
f32 calcDistanceV(const LiveActor* actor, const LiveActor* target) {
|
|
return calcDistanceV(actor, getTrans(target));
|
|
}
|
|
|
|
f32 calcDistanceH(const LiveActor* actor, const LiveActor* target) {
|
|
return calcDistanceH(actor, getTrans(target));
|
|
}
|
|
|
|
f32 calcDistanceH(const LiveActor* actor, const sead::Vector3f& trans1,
|
|
const sead::Vector3f& trans2) {
|
|
sead::Vector3f dist;
|
|
verticalizeVec(&dist, getGravity(actor), trans2 - trans1);
|
|
return dist.length();
|
|
}
|
|
|
|
f32 calcHeight(const LiveActor* actor, const LiveActor* target) {
|
|
return calcHeight(actor, getTrans(target));
|
|
}
|
|
|
|
f32 calcDistanceFront(const LiveActor* actor, const sead::Vector3f& trans) {
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
return (trans - getTrans(actor)).dot(front);
|
|
}
|
|
|
|
f32 calcDistanceFront(const LiveActor* actor, const LiveActor* target) {
|
|
return calcDistanceFront(actor, getTrans(target));
|
|
}
|
|
|
|
void addRotateAndRepeatX(LiveActor* actor, f32 deg) {
|
|
setRotateX(actor, modDegree(getRotate(actor).x + deg));
|
|
}
|
|
|
|
void addRotateAndRepeatY(LiveActor* actor, f32 deg) {
|
|
setRotateY(actor, modDegree(getRotate(actor).y + deg));
|
|
}
|
|
|
|
void addRotateAndRepeatZ(LiveActor* actor, f32 deg) {
|
|
setRotateZ(actor, modDegree(getRotate(actor).z + deg));
|
|
}
|
|
|
|
void addRandomRotateY(LiveActor* actor) {
|
|
addRotateAndRepeatY(actor, getRandomDegree());
|
|
}
|
|
|
|
void calcQuatSide(sead::Vector3f* side, const LiveActor* actor) {
|
|
calcQuatSide(side, getQuat(actor));
|
|
}
|
|
|
|
void calcQuatUp(sead::Vector3f* up, const LiveActor* actor) {
|
|
calcQuatUp(up, getQuat(actor));
|
|
}
|
|
|
|
void calcQuatFront(sead::Vector3f* front, const LiveActor* actor) {
|
|
calcQuatFront(front, getQuat(actor));
|
|
}
|
|
|
|
void calcQuatLocalAxis(sead::Vector3f* local, const LiveActor* actor, s32 axis) {
|
|
calcQuatLocalAxis(local, getQuat(actor), axis);
|
|
}
|
|
|
|
void calcTransOffsetFront(sead::Vector3f* offset, const LiveActor* actor, f32 len) {
|
|
multVecPose(offset, actor, {0.0f, 0.0f, len});
|
|
}
|
|
|
|
void calcTransOffsetUp(sead::Vector3f* offset, const LiveActor* actor, f32 len) {
|
|
multVecPose(offset, actor, {0.0f, len, 0.0f});
|
|
}
|
|
|
|
void calcTransOffsetSide(sead::Vector3f* offset, const LiveActor* actor, f32 len) {
|
|
multVecPose(offset, actor, {len, 0.0f, 0.0f});
|
|
}
|
|
|
|
void setTransOffsetLocalDir(LiveActor* actor, const sead::Quatf& quat,
|
|
const sead::Vector3f& globalOffset, f32 localOffset, s32 axis) {
|
|
sead::Vector3f offset;
|
|
calcQuatLocalAxis(&offset, quat, axis);
|
|
getTransPtr(actor)->setScaleAdd(localOffset, offset, globalOffset);
|
|
}
|
|
|
|
void addTransOffsetLocal(LiveActor* actor, const sead::Vector3f& localOffset) {
|
|
sead::Quatf quat = sead::Quatf::unit;
|
|
calcQuat(&quat, actor);
|
|
sead::Vector3f offset;
|
|
offset.setRotated(quat, localOffset);
|
|
*getTransPtr(actor) += offset;
|
|
}
|
|
|
|
void addTransOffsetLocalDir(LiveActor* actor, f32 localOffset, s32 axis) {
|
|
setTransOffsetLocalDir(actor, getQuat(actor), getTrans(actor), localOffset, axis);
|
|
}
|
|
|
|
void rotateQuatXDirDegree(LiveActor* actor, f32 deg) {
|
|
sead::Quatf* quat = getQuatPtr(actor);
|
|
rotateQuatXDirDegree(quat, *quat, deg);
|
|
}
|
|
|
|
void rotateQuatXDirDegree(LiveActor* actor, const sead::Quatf& quat, f32 deg) {
|
|
rotateQuatXDirDegree(getQuatPtr(actor), quat, deg);
|
|
}
|
|
|
|
void rotateQuatYDirDegree(LiveActor* actor, f32 deg) {
|
|
sead::Quatf* quat = getQuatPtr(actor);
|
|
rotateQuatYDirDegree(quat, *quat, deg);
|
|
}
|
|
|
|
void rotateQuatYDirDegree(LiveActor* actor, const sead::Quatf& quat, f32 deg) {
|
|
rotateQuatYDirDegree(getQuatPtr(actor), quat, deg);
|
|
}
|
|
|
|
void rotateQuatZDirDegree(LiveActor* actor, f32 deg) {
|
|
sead::Quatf* quat = getQuatPtr(actor);
|
|
rotateQuatZDirDegree(quat, *quat, deg);
|
|
}
|
|
|
|
void rotateQuatZDirDegree(LiveActor* actor, const sead::Quatf& quat, f32 deg) {
|
|
rotateQuatZDirDegree(getQuatPtr(actor), quat, deg);
|
|
}
|
|
|
|
void rotateQuatLocalDirDegree(LiveActor* actor, s32 axis, f32 deg) {
|
|
sead::Quatf* quat = getQuatPtr(actor);
|
|
rotateQuatLocalDirDegree(quat, *quat, axis, deg);
|
|
}
|
|
|
|
void rotateQuatLocalDirDegree(LiveActor* actor, const sead::Quatf& quat, s32 axis, f32 deg) {
|
|
rotateQuatLocalDirDegree(getQuatPtr(actor), quat, axis, deg);
|
|
}
|
|
|
|
void rotateQuatYDirRandomDegree(LiveActor* actor) {
|
|
sead::Quatf* quat = getQuatPtr(actor);
|
|
rotateQuatYDirDegree(quat, *quat, getRandomDegree());
|
|
}
|
|
|
|
void rotateQuatYDirRandomDegree(LiveActor* actor, const sead::Quatf& quat) {
|
|
rotateQuatYDirDegree(getQuatPtr(actor), quat, getRandomDegree());
|
|
}
|
|
|
|
bool turnQuatFrontToDirDegreeH(LiveActor* actor, const sead::Vector3f& dir, f32 deg) {
|
|
return turnQuatFrontToDirDegreeH(getQuatPtr(actor), dir, deg);
|
|
}
|
|
|
|
bool turnQuatFrontToPosDegreeH(LiveActor* actor, const sead::Vector3f& pos, f32 deg) {
|
|
sead::Vector3f dir;
|
|
dir.setSub(pos, getTrans(actor));
|
|
return turnQuatFrontToDirDegreeH(actor, dir, deg);
|
|
}
|
|
|
|
bool turnQuatFrontFromPosDegreeH(LiveActor* actor, const sead::Vector3f& pos, f32 deg) {
|
|
sead::Vector3f dir;
|
|
dir.setSub(getTrans(actor), pos);
|
|
return turnQuatFrontToDirDegreeH(actor, dir, deg);
|
|
}
|
|
|
|
void turnFront(LiveActor* actor, f32 deg) {
|
|
sead::Vector3f up = sead::Vector3f::ey;
|
|
calcUpDir(&up, actor);
|
|
turnFront(actor, up, deg);
|
|
}
|
|
|
|
void turnFront(LiveActor* actor, const sead::Vector3f& up, f32 deg) {
|
|
sead::Vector3f* front = getFrontPtr(actor);
|
|
rotateVectorDegree(front, *front, up, deg);
|
|
normalize(getFrontPtr(actor));
|
|
}
|
|
|
|
void turnFrontToPos(LiveActor* actor, const sead::Vector3f& pos, f32 deg) {
|
|
turnFrontToDir(actor, pos - getTrans(actor), deg);
|
|
}
|
|
|
|
void turnFrontToDir(LiveActor* actor, const sead::Vector3f& dir, f32 deg) {
|
|
turnFrontToDirGetIsFinished(actor, dir, deg);
|
|
}
|
|
|
|
bool turnFrontToDirGetIsFinished(LiveActor* actor, const sead::Vector3f& dir, f32 deg) {
|
|
sead::Vector3f up;
|
|
calcFrontDir(&up, actor);
|
|
bool finished = turnDirectionDegree(actor, &up, dir, deg);
|
|
turnVecToVecDegree(getFrontPtr(actor), getFront(actor), up, deg);
|
|
normalize(getFrontPtr(actor));
|
|
return finished;
|
|
}
|
|
|
|
bool turnDirectionDegree(const LiveActor* actor, sead::Vector3f* vec, const sead::Vector3f& dir,
|
|
f32 deg) {
|
|
f32 cos = sead::Mathf::cos(sead::Mathf::deg2rad(deg));
|
|
return turnDirection(actor, vec, dir, cos);
|
|
}
|
|
|
|
void turnFrontToTarget(LiveActor* actor, const LiveActor* target, f32 deg) {
|
|
turnFrontToDir(actor, getTrans(target) - getTrans(actor), deg);
|
|
}
|
|
|
|
void turnFrontFromTarget(LiveActor* actor, const LiveActor* target, f32 deg) {
|
|
turnFrontToDir(actor, getTrans(actor) - getTrans(target), deg);
|
|
}
|
|
|
|
bool turnFrontToPlayer(LiveActor* actor, f32 deg) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
turnFrontToDir(actor, playerPos - getTrans(actor), deg);
|
|
return true;
|
|
}
|
|
|
|
bool turnFrontFromPlayer(LiveActor* actor, f32 deg) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
turnFrontToDir(actor, getTrans(actor) - playerPos, deg);
|
|
return true;
|
|
}
|
|
|
|
bool turnDirection(const LiveActor* actor, sead::Vector3f* vec, const sead::Vector3f& dir,
|
|
f32 cos) {
|
|
return turnVecToVecCosOnPlane(vec, dir, getGravity(actor), cos);
|
|
}
|
|
|
|
bool turnDirectionToTarget(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& target, f32 cos) {
|
|
return turnDirection(actor, vec, target - getTrans(actor), cos);
|
|
}
|
|
|
|
bool turnDirectionToTargetDegree(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& target, f32 deg) {
|
|
return turnDirectionDegree(actor, vec, target - getTrans(actor), deg);
|
|
}
|
|
|
|
bool turnDirectionFromTargetDegree(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& target, f32 deg) {
|
|
return turnDirectionDegree(actor, vec, getTrans(actor) - target, deg);
|
|
}
|
|
|
|
void turnDirectionAlongGround(const LiveActor* actor, sead::Vector3f* dir) {
|
|
sead::Vector3f down;
|
|
if (isCollidedGround(actor))
|
|
down = -getOnGroundNormal(actor, 0);
|
|
else
|
|
down.set(getGravity(actor));
|
|
|
|
verticalizeVec(dir, down, *dir);
|
|
normalize(dir);
|
|
}
|
|
|
|
void turnDirectionAlongGround(LiveActor* actor) {
|
|
if (tryGetQuatPtr(actor)) {
|
|
sead::Vector3f ground;
|
|
calcFrontDir(&ground, actor);
|
|
|
|
sead::Vector3f down;
|
|
if (isCollidedGround(actor))
|
|
down = -getOnGroundNormal(actor, 0);
|
|
else
|
|
down.set(getGravity(actor));
|
|
|
|
verticalizeVec(&ground, down, ground);
|
|
if (!tryNormalizeOrZero(&ground))
|
|
return;
|
|
|
|
turnToDirectionAxis(actor, ground, -down, 180.0f);
|
|
} else if (getFrontPtr(actor)) {
|
|
turnDirectionAlongGround(actor, getFrontPtr(actor));
|
|
}
|
|
}
|
|
|
|
bool turnToDirectionAxis(LiveActor* actor, const sead::Vector3f& horizontal,
|
|
const sead::Vector3f& vertical, f32 deg) {
|
|
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
|
|
calcFrontDir(&front, actor);
|
|
bool result = turnVecToVecCosOnPlane(&front, horizontal, vertical,
|
|
sead::Mathf::cos(sead::Mathf::deg2rad(deg)));
|
|
|
|
sead::Quatf quat = sead::Quatf::unit;
|
|
makeQuatUpFront(&quat, vertical, front);
|
|
updatePoseQuat(actor, quat);
|
|
return result;
|
|
}
|
|
|
|
bool turnFrontSpherical(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& targetFront, f32 cos) {
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
sead::Vector3f axis;
|
|
axis.setCross(front, targetFront);
|
|
if (isNearZero(axis, 0.001f))
|
|
calcUpDir(&axis, actor);
|
|
normalize(&axis);
|
|
normalize(&front);
|
|
return turnVecToVecCosOnPlane(vec, front, targetFront, axis, cos);
|
|
}
|
|
|
|
bool turnFrontSphericalToTarget(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& target, f32 cos) {
|
|
sead::Vector3f targetFront = target - getTrans(actor);
|
|
if (!tryNormalizeOrZero(&targetFront)) {
|
|
calcFrontDir(vec, actor);
|
|
return true;
|
|
}
|
|
return turnFrontSpherical(actor, vec, targetFront, cos);
|
|
}
|
|
|
|
bool turnFrontSphericalToTargetDegree(const LiveActor* actor, sead::Vector3f* vec,
|
|
const sead::Vector3f& target, f32 deg) {
|
|
return turnFrontSphericalToTarget(actor, vec, target,
|
|
sead::Mathf::cos(sead::Mathf::deg2rad(deg)));
|
|
}
|
|
|
|
bool turnToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 deg) {
|
|
sead::Vector3f vec;
|
|
calcFrontDir(&vec, actor);
|
|
bool result = turnDirectionDegree(actor, &vec, dir, deg);
|
|
|
|
sead::Quatf quat;
|
|
makeQuatUpFront(&quat, -getGravity(actor), vec);
|
|
updatePoseQuat(actor, quat);
|
|
return result;
|
|
}
|
|
|
|
void turnLocalDirToDirection(LiveActor* actor, const sead::Vector3f& localDir,
|
|
const sead::Vector3f& targetDir, f32 deg) {
|
|
sead::Quatf quat;
|
|
calcQuat(&quat, actor);
|
|
sead::Vector3f globalDir = localDir;
|
|
rotateVectorQuat(&globalDir, quat);
|
|
|
|
sead::Quatf quat2;
|
|
makeQuatRotationLimit(&quat2, globalDir, targetDir, sead::Mathf::deg2rad(deg));
|
|
|
|
quat2 *= quat;
|
|
updatePoseQuat(actor, quat2);
|
|
}
|
|
|
|
bool turnToTarget(LiveActor* actor, const sead::Vector3f& target, f32 deg) {
|
|
sead::Vector3f dir = target - getTrans(actor);
|
|
if (!tryNormalizeOrZero(&dir))
|
|
return false;
|
|
return turnToDirection(actor, dir, deg);
|
|
}
|
|
|
|
bool turnToTarget(LiveActor* actor, const LiveActor* target, f32 deg) {
|
|
return turnToTarget(actor, getTrans(target), deg);
|
|
}
|
|
|
|
void faceToDirection(LiveActor* actor, const sead::Vector3f& dir) {
|
|
if (isParallelDirection(dir, getGravity(actor), 0.01f))
|
|
return;
|
|
|
|
sead::Quatf quat;
|
|
makeQuatUpFront(&quat, -getGravity(actor), dir);
|
|
updatePoseQuat(actor, quat);
|
|
}
|
|
|
|
void faceToDirectionSupportUp(LiveActor* actor, const sead::Vector3f& dir) {
|
|
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
|
|
calcUpDir(&up, actor);
|
|
if (isParallelDirection(dir, up, 0.01f))
|
|
return;
|
|
|
|
sead::Quatf quat;
|
|
makeQuatFrontUp(&quat, dir, up);
|
|
updatePoseQuat(actor, quat);
|
|
}
|
|
|
|
void faceToTarget(LiveActor* actor, const sead::Vector3f& target) {
|
|
sead::Vector3f direction = target - getTrans(actor);
|
|
if (!tryNormalizeOrZero(&direction))
|
|
return;
|
|
faceToDirection(actor, direction);
|
|
}
|
|
|
|
void faceToTarget(LiveActor* actor, const LiveActor* target) {
|
|
faceToTarget(actor, getTrans(target));
|
|
}
|
|
|
|
void faceToSensor(LiveActor* actor, const HitSensor* sensor) {
|
|
faceToTarget(actor, getSensorPos(sensor));
|
|
}
|
|
|
|
void faceToVelocity(LiveActor* actor) {
|
|
sead::Vector3f direction = getVelocity(actor);
|
|
if (!tryNormalizeOrZero(&direction))
|
|
return;
|
|
faceToDirection(actor, direction);
|
|
}
|
|
|
|
void calcDirClockwiseToDir(sead::Vector3f* out, const LiveActor* actor, const sead::Vector3f& dir) {
|
|
sead::Vector3f result;
|
|
result.setCross(getGravity(actor), dir);
|
|
tryNormalizeOrZero(out, result);
|
|
}
|
|
|
|
void calcDirClockwiseToPos(sead::Vector3f* out, const LiveActor* actor,
|
|
const sead::Vector3f& target) {
|
|
calcDirClockwiseToDir(out, actor, target - getTrans(actor));
|
|
}
|
|
|
|
void calcDirToActorH(sead::Vector3f* out, const LiveActor* actor, const LiveActor* target) {
|
|
calcDirToActorH(out, actor, getTrans(target));
|
|
}
|
|
|
|
void calcDirToActorH(sead::Vector3f* out, const LiveActor* actor, const sead::Vector3f& target) {
|
|
out->setSub(target, getTrans(actor));
|
|
verticalizeVec(out, getGravity(actor), *out);
|
|
tryNormalizeOrZero(out);
|
|
}
|
|
|
|
f32 calcAngleToTargetH(const LiveActor* actor, const sead::Vector3f& target) {
|
|
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f up = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f dir = {0.0f, 0.0f, 0.0f};
|
|
calcFrontDir(&front, actor);
|
|
calcUpDir(&up, actor);
|
|
dir.setSub(target, getTrans(actor));
|
|
if (!tryNormalizeOrZero(&dir))
|
|
return 0.0f;
|
|
return calcAngleOnPlaneDegree(front, dir, up);
|
|
}
|
|
|
|
f32 calcAngleToTargetV(const LiveActor* actor, const sead::Vector3f& target) {
|
|
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f side = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f dir = {0.0f, 0.0f, 0.0f};
|
|
calcFrontDir(&front, actor);
|
|
calcSideDir(&side, actor);
|
|
dir.setSub(target, getTrans(actor));
|
|
if (!tryNormalizeOrZero(&dir))
|
|
return 0.0f;
|
|
return calcAngleOnPlaneDegree(front, dir, side);
|
|
}
|
|
|
|
bool isFaceToTargetDegree(const LiveActor* actor, const sead::Vector3f& target,
|
|
const sead::Vector3f& face, f32 threshDeg) {
|
|
return isNearAngleDegree(target - getTrans(actor), face, threshDeg);
|
|
}
|
|
|
|
bool isFaceToTargetDegree(const LiveActor* actor, const sead::Vector3f& target, f32 threshDeg) {
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
return isNearAngleDegree(target - getTrans(actor), front, threshDeg);
|
|
}
|
|
|
|
bool isFaceToTargetDegreeHV(const LiveActor* actor, const sead::Vector3f& target,
|
|
const sead::Vector3f& face, f32 degH, f32 degV) {
|
|
return isNearAngleDegreeHV(target - getTrans(actor), face, getGravity(actor), degH, degV);
|
|
}
|
|
|
|
bool isFaceToTargetDegreeH(const LiveActor* actor, const sead::Vector3f& target,
|
|
const sead::Vector3f& face, f32 degH) {
|
|
sead::Vector3f diff = target;
|
|
diff -= getTrans(actor);
|
|
verticalizeVec(&diff, getGravity(actor), diff);
|
|
sead::Vector3f alignedFace;
|
|
verticalizeVec(&alignedFace, getGravity(actor), face);
|
|
return isNearAngleDegree(diff, alignedFace, degH);
|
|
}
|
|
|
|
bool isInSightCone(const LiveActor* actor, const sead::Vector3f& target, const sead::Vector3f& face,
|
|
f32 maxDist, f32 threshDeg) {
|
|
return (getTrans(actor) - target).squaredLength() < sead::Mathf::square(maxDist) &&
|
|
isFaceToTargetDegree(actor, target, face, threshDeg);
|
|
}
|
|
|
|
bool isInSightConeTarget(const LiveActor* actor, const LiveActor* target, f32 maxDist,
|
|
f32 threshDeg) {
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
return isInSightCone(actor, getTrans(target), front, maxDist, threshDeg);
|
|
}
|
|
|
|
bool isInSightConePlayer(const LiveActor* actor, f32 maxDist, f32 threshDeg) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
return isInSightCone(actor, playerPos, front, maxDist, threshDeg);
|
|
}
|
|
|
|
bool isInSightFan(const LiveActor* actor, const sead::Vector3f& target, const sead::Vector3f& face,
|
|
f32 maxDist, f32 angleH, f32 angleV) {
|
|
return (getTrans(actor) - target).squaredLength() < sead::Mathf::square(maxDist) &&
|
|
isFaceToTargetDegreeHV(actor, target, face, angleH, angleV);
|
|
}
|
|
|
|
bool isInSightFanTarget(const LiveActor* actor, const LiveActor* target, f32 maxDist, f32 angleH,
|
|
f32 angleV) {
|
|
sead::Vector3f front = sead::Vector3f::ez;
|
|
calcFrontDir(&front, actor);
|
|
return isInSightFan(actor, getTrans(target), front, maxDist, angleH, angleV);
|
|
}
|
|
|
|
bool isInSightBox(const LiveActor* actor, const sead::Vector3f& pos, const sead::BoundBox3f& box) {
|
|
sead::Vector3f localPos;
|
|
multVecInvPose(&localPos, actor, pos);
|
|
return box.isInside(localPos);
|
|
}
|
|
|
|
void walkAndTurnToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 forceFront,
|
|
f32 forceGravity, f32 decay, f32 deg, bool turnAlongGround) {
|
|
walkAndTurnToDirection(actor, getFrontPtr(actor), dir, forceFront, forceGravity, decay, deg,
|
|
turnAlongGround);
|
|
}
|
|
|
|
void walkAndTurnToDirection(LiveActor* actor, sead::Vector3f* front, const sead::Vector3f& dir,
|
|
f32 forceFront, f32 forceGravity, f32 decay, f32 deg,
|
|
bool turnAlongGround) {
|
|
turnDirection(actor, front, dir, sead::Mathf::cos(sead::Mathf::deg2rad(deg)));
|
|
if (turnAlongGround)
|
|
turnDirectionAlongGround(actor);
|
|
|
|
sead::Vector3f velFront;
|
|
tryNormalizeOrZero(&velFront, *front);
|
|
addVelocityInline(actor, velFront, forceFront);
|
|
|
|
if (!isOnGround(actor, 3))
|
|
addVelocityToGravity(actor, forceGravity);
|
|
|
|
scaleVelocity(actor, decay);
|
|
}
|
|
|
|
void walkAndTurnPoseToDirection(LiveActor* actor, const sead::Vector3f& dir,
|
|
const ActorParamMove& param, bool turnAlongGround) {
|
|
sead::Vector3f* frontPtr;
|
|
sead::Vector3f frontForQuat;
|
|
if (getQuatPtr(actor)) {
|
|
frontPtr = &frontForQuat;
|
|
calcFrontDir(&frontForQuat, actor);
|
|
turnToDirection(actor, dir, param.turnSpeedDegree);
|
|
} else if (getFrontPtr(actor)) {
|
|
frontPtr = getFrontPtr(actor);
|
|
turnDirectionDegree(actor, frontPtr, dir, param.turnSpeedDegree);
|
|
} else
|
|
return;
|
|
|
|
if (turnAlongGround)
|
|
turnDirectionAlongGround(actor);
|
|
|
|
f32 moveAccel = param.moveAccel;
|
|
sead::Vector3f velFront;
|
|
tryNormalizeOrZero(&velFront, *frontPtr);
|
|
addVelocityInline(actor, velFront, moveAccel);
|
|
|
|
if (!isOnGround(actor, 3))
|
|
addVelocityToGravity(actor, param.gravity);
|
|
|
|
// BUG: should have been param.decay (_8)
|
|
scaleVelocity(actor, param.moveAccel);
|
|
}
|
|
|
|
void walkAndTurnToTarget(LiveActor* actor, const sead::Vector3f& target, f32 forceFront,
|
|
f32 forceGravity, f32 decay, f32 deg, bool turnAlongGround) {
|
|
sead::Vector3f dir = target - getTrans(actor);
|
|
walkAndTurnToDirection(actor, dir, forceFront, forceGravity, decay, deg, turnAlongGround);
|
|
}
|
|
|
|
void flyAndTurnToDirection(LiveActor* actor, sead::Vector3f* front, const sead::Vector3f& dir,
|
|
f32 forceFront, f32 forceGravity, f32 decay, f32 deg) {
|
|
sead::Vector3f normFrontH, actorFront, frontH;
|
|
|
|
calcFrontDir(&actorFront, actor);
|
|
turnDirectionDegree(actor, &actorFront, dir, deg);
|
|
turnVecToVecDegree(front, *front, actorFront, deg);
|
|
|
|
calcFrontDir(&frontH, actor);
|
|
verticalizeVec(&frontH, getGravity(actor), frontH);
|
|
normalize(&frontH);
|
|
|
|
tryNormalizeOrZero(&normFrontH, frontH);
|
|
addVelocityInline(actor, normFrontH, forceFront);
|
|
addVelocityToGravity(actor, forceGravity);
|
|
scaleVelocity(actor, decay);
|
|
}
|
|
|
|
void flyAndTurnToDirection(LiveActor* actor, const sead::Vector3f& dir, f32 forceFront,
|
|
f32 forceGravity, f32 decay, f32 deg) {
|
|
flyAndTurnToDirection(actor, getFrontPtr(actor), dir, forceFront, forceGravity, decay, deg);
|
|
}
|
|
|
|
void flyAndTurnToTarget(LiveActor* actor, const sead::Vector3f& target, f32 forceFront,
|
|
f32 forceGravity, f32 decay, f32 deg) {
|
|
flyAndTurnToDirection(actor, target - getTrans(actor), forceFront, forceGravity, decay, deg);
|
|
}
|
|
|
|
bool walkAndTurnToDirectionFittedGroundGravity(LiveActor* actor, sead::Vector3f* front,
|
|
const sead::Vector3f& dir, f32 forceFront,
|
|
f32 forceGravity, f32 decay, f32 deg,
|
|
bool turnAlongGround) {
|
|
turnDirection(actor, front, dir, sead::Mathf::cos(sead::Mathf::deg2rad(deg)));
|
|
if (turnAlongGround)
|
|
turnDirectionAlongGround(actor, front);
|
|
|
|
sead::Vector3f velFront;
|
|
tryNormalizeOrZero(&velFront, *front);
|
|
addVelocityInline(actor, velFront, forceFront);
|
|
|
|
bool isOnGround = isOnGroundNoVelocity(actor, 3);
|
|
if (isOnGround)
|
|
addVelocityToGravityFittedGround(actor, forceGravity, 3);
|
|
else
|
|
addVelocityToGravity(actor, forceGravity);
|
|
|
|
scaleVelocity(actor, decay);
|
|
return isOnGround;
|
|
}
|
|
|
|
bool walkAndTurnToDirectionFittedGroundGravity(LiveActor* actor, const sead::Vector3f& dir,
|
|
f32 forceFront, f32 forceGravity, f32 decay, f32 deg,
|
|
bool turnAlongGround) {
|
|
return walkAndTurnToDirectionFittedGroundGravity(actor, getFrontPtr(actor), dir, forceFront,
|
|
forceGravity, decay, deg, turnAlongGround);
|
|
}
|
|
|
|
bool walkAndTurnToTargetFittedGroundGravity(LiveActor* actor, const sead::Vector3f& target,
|
|
f32 forceFront, f32 forceGravity, f32 decay, f32 deg,
|
|
bool turnAlongGround) {
|
|
return walkAndTurnToDirectionFittedGroundGravity(actor, target - getTrans(actor), forceFront,
|
|
forceGravity, decay, deg, turnAlongGround);
|
|
}
|
|
|
|
bool tryKillByDeathArea(LiveActor* actor) {
|
|
if (!isInDeathArea(actor, getTrans(actor)))
|
|
return false;
|
|
actor->kill();
|
|
return true;
|
|
}
|
|
|
|
void rotateAndKeepColliderPosRate(LiveActor* actor, const sead::Vector3f& up,
|
|
const sead::Vector3f& front, f32 rate) {
|
|
sead::Vector3f colliderPos = {0.0f, 0.0f, 0.0f};
|
|
calcColliderPos(&colliderPos, actor);
|
|
|
|
sead::Vector3f localColliderPos;
|
|
sead::Matrix34f mtx;
|
|
makeMtxRT(&mtx, actor);
|
|
calcMtxLocalTrans(&localColliderPos, mtx, colliderPos);
|
|
|
|
sead::Quatf quat;
|
|
makeQuatUpFront(&quat, up, front);
|
|
slerpQuat(getQuatPtr(actor), getQuat(actor), quat, rate);
|
|
|
|
sead::Matrix34f mtx2;
|
|
makeMtxRT(&mtx2, actor);
|
|
|
|
sead::Vector3f newColliderPos = {0.0f, 0.0f, 0.0f};
|
|
calcTransLocalOffsetByMtx(&newColliderPos, mtx2, localColliderPos);
|
|
sead::Vector3f colliderOffset = colliderPos - newColliderPos;
|
|
|
|
*getTransPtr(actor) += colliderOffset;
|
|
resetPosition(actor);
|
|
}
|
|
|
|
void calcSpringMovement(LiveActor* actor, const sead::Vector3f& pos, f32 springPos, f32 sinStrength,
|
|
const sead::Vector3f& offset, f32 constStrength, f32 sinAmpl) {
|
|
f32 sinPart = sead::Mathf::sin(sead::Mathf::clamp(springPos, 0.0f, 1.0f) * 2 *
|
|
sead::Mathf::pi() * sinAmpl) *
|
|
(1.0f - springPos) * sinStrength;
|
|
f32 constPart = (1.0f - springPos) * constStrength;
|
|
getTransPtr(actor)->setScaleAdd(sinPart + constPart, offset, pos);
|
|
}
|
|
|
|
bool addVelocityClockwiseToPlayer(LiveActor* actor, f32 force) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
addVelocityClockwiseToDirection(actor, playerPos - getTrans(actor), force);
|
|
return true;
|
|
}
|
|
|
|
bool calcDirClockwiseToPlayer(sead::Vector3f* dir, const LiveActor* actor) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
// BUG: should have been calcDirClockwiseToPos
|
|
calcDirClockwiseToDir(dir, actor, playerPos);
|
|
return true;
|
|
}
|
|
|
|
bool flyAndTurnToPlayer(LiveActor* actor, const ActorParamMove& param) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
flyAndTurnToTarget(actor, playerPos, param.moveAccel, param.gravity, param.moveFriction,
|
|
param.turnSpeedDegree);
|
|
return true;
|
|
}
|
|
|
|
bool escapeFromPlayer(LiveActor* actor, f32 forceFront, f32 forceGravity, f32 decay, f32 deg) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
walkAndTurnToDirection(actor, getTrans(actor) - playerPos, forceFront, forceGravity, decay, deg,
|
|
true);
|
|
return true;
|
|
}
|
|
|
|
bool escapeFromPlayer(LiveActor* actor, sead::Vector3f* front, f32 forceFront, f32 forceGravity,
|
|
f32 decay, f32 deg) {
|
|
sead::Vector3f playerPos = {0.0f, 0.0f, 0.0f};
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
walkAndTurnToDirection(actor, front, getTrans(actor) - playerPos, forceFront, forceGravity,
|
|
decay, deg, true);
|
|
return true;
|
|
}
|
|
|
|
bool walkAndTurnToPlayer(LiveActor* actor, f32 forceFront, f32 forceGravity, f32 decay, f32 deg,
|
|
bool turnAlongGround) {
|
|
sead::Vector3f playerPos;
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
return walkAndTurnToTargetFittedGroundGravity(actor, playerPos, forceFront, forceGravity, decay,
|
|
deg, turnAlongGround);
|
|
}
|
|
|
|
bool isPlayerInSightFan(const LiveActor* actor, f32 maxDist, f32 angleH, f32 angleV) {
|
|
sead::Vector3f playerPos;
|
|
if (!tryFindNearestPlayerPos(&playerPos, actor))
|
|
return false;
|
|
sead::Vector3f front;
|
|
calcFrontDir(&front, actor);
|
|
return isInSightFan(actor, playerPos, front, maxDist, angleH, angleV);
|
|
}
|
|
|
|
inline bool nextMove(Triangle* triangle, const LiveActor* actor, const sead::Vector3f& velocity,
|
|
f32 gravity, f32 searchDist) {
|
|
sead::Vector3f hitPos = {0.0f, 0.0f, 0.0f};
|
|
sead::Vector3f pos = getTrans(actor) + velocity;
|
|
pos.y += gravity;
|
|
|
|
return alCollisionUtil::getFirstPolyOnArrow(actor, &hitPos, triangle, pos,
|
|
-sead::Vector3f::ey * searchDist, nullptr, nullptr);
|
|
}
|
|
|
|
bool isFallOrDamageCodeNextMove(const LiveActor* actor, const sead::Vector3f& velocity, f32 gravity,
|
|
f32 searchDist) {
|
|
Triangle triangle;
|
|
if (!nextMove(&triangle, actor, velocity, gravity, searchDist))
|
|
return true;
|
|
return isFloorCode(triangle, "DamageFire") || isFloorCode(triangle, "Poison");
|
|
}
|
|
|
|
bool isFallNextMove(const LiveActor* actor, const sead::Vector3f& velocity, f32 gravity,
|
|
f32 searchDist) {
|
|
Triangle triangle;
|
|
return !nextMove(&triangle, actor, velocity, gravity, searchDist);
|
|
}
|
|
|
|
} // namespace al
|