Skip to content

Commit

Permalink
Library/Camera: Implement CameraShaker
Browse files Browse the repository at this point in the history
  • Loading branch information
MonsterDruide1 committed Jan 2, 2025
1 parent 769899d commit 617833d
Show file tree
Hide file tree
Showing 3 changed files with 236 additions and 13 deletions.
26 changes: 13 additions & 13 deletions data/odyssey_functions.csv
Original file line number Diff line number Diff line change
Expand Up @@ -51681,19 +51681,19 @@ Address,Quality,Size,Name
0x000000710083927c,U,000136,_ZNK2al20CameraResourceHolder18findCameraResourceEPKc
0x0000007100839304,U,000136,_ZNK2al20CameraResourceHolder21tryFindCameraResourceEPKc
0x000000710083938c,U,000252,_ZNK2al20CameraResourceHolder21tryFindCameraResourceEPKNS_11PlacementIdE
0x0000007100839488,U,000104,_ZN2al12CameraShakerC2Ev
0x00000071008394f0,U,000152,_ZN2al12CameraShaker6updateEPKc
0x0000007100839588,U,000008,_ZN2al12CameraShaker18startShakeByActionEPKcS2_S2_i
0x0000007100839590,U,000360,_ZN2al12CameraShaker16startShakeByNameEPKci
0x00000071008396f8,U,000008,_ZN2al12CameraShaker23startShakeByHitReactionEPKcS2_S2_i
0x0000007100839700,U,000044,_ZN2al12CameraShaker7exeWaitEv
0x000000710083972c,U,000244,_ZN2al12CameraShaker8exeShakeEv
0x0000007100839820,U,000124,_ZN2al12CameraShaker12exeShakeLoopEv
0x000000710083989c,U,000276,_ZN2al12CameraShaker17startShakeByIndexEii
0x00000071008399b0,U,000036,_ZN2al12CameraShakerD0Ev
0x00000071008399d4,U,000048,
0x0000007100839a04,U,000128,
0x0000007100839a84,U,000008,
0x0000007100839488,O,000104,_ZN2al12CameraShakerC2Ev
0x00000071008394f0,O,000152,_ZN2al12CameraShaker6updateEPKc
0x0000007100839588,O,000008,_ZN2al12CameraShaker18startShakeByActionEPKcS2_S2_i
0x0000007100839590,O,000360,_ZN2al12CameraShaker16startShakeByNameEPKci
0x00000071008396f8,O,000008,_ZN2al12CameraShaker23startShakeByHitReactionEPKcS2_S2_i
0x0000007100839700,O,000044,_ZN2al12CameraShaker7exeWaitEv
0x000000710083972c,O,000244,_ZN2al12CameraShaker8exeShakeEv
0x0000007100839820,O,000124,_ZN2al12CameraShaker12exeShakeLoopEv
0x000000710083989c,O,000276,_ZN2al12CameraShaker17startShakeByIndexEii
0x00000071008399b0,O,000036,_ZN2al12CameraShakerD0Ev
0x00000071008399d4,O,000048,_ZNK12_GLOBAL__N_119CameraShakerNrvWait7executeEPN2al11NerveKeeperE
0x0000007100839a04,O,000128,_ZNK12_GLOBAL__N_124CameraShakerNrvShakeLoop7executeEPN2al11NerveKeeperE
0x0000007100839a84,O,000008,_ZNK12_GLOBAL__N_120CameraShakerNrvShake7executeEPN2al11NerveKeeperE
0x0000007100839a8c,U,000028,_ZN2al20CameraStartParamCtrlC2Ev
0x0000007100839aa8,U,000012,_ZN2al20CameraStartParamCtrl4initEPNS_15AreaObjDirectorEPKNS_14CameraFlagCtrlE
0x0000007100839ab4,U,000064,_ZN2al20CameraStartParamCtrl18initAfterPlacementEv
Expand Down
151 changes: 151 additions & 0 deletions lib/al/Library/Camera/CameraShaker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include "Library/Camera/CameraShaker.h"

#include "Library/Base/StringUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"

namespace {
using namespace al;

NERVE_IMPL(CameraShaker, Shake); // 38
NERVE_IMPL(CameraShaker, Wait); // 58
NERVE_IMPL(CameraShaker, ShakeLoop); // 60

NERVES_MAKE_NOSTRUCT(CameraShaker, Shake);
NERVES_MAKE_STRUCT(CameraShaker, Wait, ShakeLoop);
} // namespace

namespace al {

const CameraShaker::ShakeInfo WeakShakeLoop = {"", -1, 7.5f, 0.0007f,
CameraShaker::ShakeDirection::Both};

const CameraShaker::ShakeInfo ShakeInfos[11] = {
{"微弱", 15, 2.5f, 0.0015f, CameraShaker::ShakeDirection::Both},
{"微弱[短]", 10, 2.0f, 0.0008f, CameraShaker::ShakeDirection::Both},
{"", 25, 2.5f, 0.0025f, CameraShaker::ShakeDirection::Both},
{"", 25, 2.5f, 0.004f, CameraShaker::ShakeDirection::Both},
{"", 30, 3.0f, 0.008f, CameraShaker::ShakeDirection::Both},
{"最強", 45, 3.5f, 0.015f, CameraShaker::ShakeDirection::Both},
{"超最強", 45, 3.5f, 0.05f, CameraShaker::ShakeDirection::Both},
{"長い微弱", 60, 6.0f, 0.0025f, CameraShaker::ShakeDirection::Both},
{"長い弱", 60, 6.0f, 0.004f, CameraShaker::ShakeDirection::Both},
{"船内振動", 100, 6.0f, 0.0005f, CameraShaker::ShakeDirection::Both},
{"弱[縦]", 25, 2.5f, 0.004f, CameraShaker::ShakeDirection::Vertical},
};

CameraShaker::CameraShaker() : NerveExecutor("カメラ振動") {
initNerve(&NrvCameraShaker.Wait, 0);
mEditedShake = {"NULL", 0, 0.0f, 0.0f, ShakeDirection::Both};
}

void CameraShaker::update(const char* shakeLoop) {
if (shakeLoop) {
mShakeLoop = isEqualString(shakeLoop, "") ? &WeakShakeLoop : nullptr;
if (isNerve(this, &NrvCameraShaker.Wait))
setNerve(this, &NrvCameraShaker.ShakeLoop);
} else {
mShakeLoop = nullptr;
if (isNerve(this, &NrvCameraShaker.ShakeLoop))
setNerve(this, &NrvCameraShaker.Wait);
}

updateNerve();
}

void CameraShaker::startShakeByAction(const char* name, const char* unused1, const char* unused2,
s32 steps) {
startShakeByName(name, steps);
}

void CameraShaker::startShakeByName(const char* name, s32 steps) {
int index = -1;
if (isEqualString(name, "微弱"))
index = 0;
else if (isEqualString(name, "微弱[短]"))
index = 1;
else if (isEqualString(name, ""))
index = 2;
else if (isEqualString(name, ""))
index = 3;
else if (isEqualString(name, ""))
index = 4;
else if (isEqualString(name, "最強"))
index = 5;
else if (isEqualString(name, "超最強"))
index = 6;
else if (isEqualString(name, "長い微弱"))
index = 7;
else if (isEqualString(name, "長い弱"))
index = 8;
else if (isEqualString(name, "船内振動"))
index = 9;
else if (isEqualString(name, "弱[縦]"))
index = 10;

startShakeByIndex(index, steps);
}

void CameraShaker::startShakeByHitReaction(const char* name, const char* unused1,
const char* unused2, s32 steps) {
startShakeByName(name, steps);
}

void CameraShaker::exeWait() {
if (isFirstStep(this)) {
mActiveShake = nullptr;
mShakeLoop = nullptr;
}
mOffset = {0.0f, 0.0f};
}

void CameraShaker::exeShake() {
if (isGreaterEqualStep(this, mActiveShake->mSteps)) {
if (mShakeLoop) {
setNerve(this, &NrvCameraShaker.ShakeLoop);
} else {
mOffset = {0.0f, 0.0f};
mActiveShake = nullptr;
setNerve(this, &NrvCameraShaker.Wait);
}
return;
}

f32 shakeSpeed = (mActiveShake->mSpeed * 360.0f) / mActiveShake->mSteps;
f32 currentShakeStrength =
sead::Mathf::cos(sead::Mathf::deg2rad(shakeSpeed * getNerveStep(this)));
f32 shakeOffset =
currentShakeStrength * (mActiveShake->mStrength *
(mActiveShake->mSteps - getNerveStep(this)) / mActiveShake->mSteps);
mOffset = {shakeOffset, shakeOffset};
if (mActiveShake->mDirection == ShakeDirection::Vertical)
mOffset.x = 0.0f;
}

void CameraShaker::exeShakeLoop() {
s32 nerveStep = getNerveStep(this);
f32 shakeStep = nerveStep <= 0 ? 0.0f : nerveStep / mShakeLoop->mSpeed * sead::Mathf::pi2();
f32 shakeOffset = mShakeLoop->mStrength * sead::Mathf::cos(shakeStep);
mOffset = {shakeOffset, shakeOffset};
if (mShakeLoop->mDirection == ShakeDirection::Vertical)
mOffset.x = 0.0f;
}

void CameraShaker::startShakeByIndex(s32 index, s32 steps) {
const ShakeInfo& shake = ShakeInfos[index];
if (mActiveShake && (*mActiveShake > shake))
return;

mActiveShake = &shake;

if (steps >= 1) {
ShakeInfo shake2 = shake;
mEditedShake = {shake.mName, steps, shake.mSpeed, shake.mStrength, shake.mDirection};
mActiveShake = &mEditedShake;
mEditedShake.mSpeed = ((f32)steps / (f32)shake2.mSteps) * shake.mSpeed;
}

setNerve(this, &Shake);
}

} // namespace al
72 changes: 72 additions & 0 deletions lib/al/Library/Camera/CameraShaker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once

#include <math/seadVector.h>

#include "Library/Nerve/NerveExecutor.h"

namespace al {

class CameraShaker : public NerveExecutor {
public:
enum class ShakeDirection : s32 { Both, Vertical };

struct ShakeInfo {
const char* mName = nullptr;
s32 mSteps = 0;
f32 mSpeed = 0.0f;
f32 mStrength = 0.0f;
ShakeDirection mDirection = ShakeDirection::Both;

bool operator>(const ShakeInfo& other) const {
if (mStrength < other.mStrength)
return false;
if (other.mStrength < mStrength)
return true;

if (other.mSteps > 0 && mSteps < 0)
return false;
if (other.mSteps < 0 && mSteps > 0)
return true;

if (mSteps < other.mSteps)
return false;
if (other.mSteps < mSteps)
return true;

s32 otherDirection = (s32)other.mDirection;
s32 direction = (s32)mDirection;
if (otherDirection < direction)
return false;
if (direction < otherDirection)
return true;

if (mSpeed < other.mSpeed)
return true;
return false;
}
};

CameraShaker();

void update(const char* shakeLoop);
void startShakeByAction(const char* name, const char* unused1, const char* unused2, s32 steps);
void startShakeByName(const char* name, s32 steps);
void startShakeByHitReaction(const char* name, const char* unused1, const char* unused2,
s32 steps);

void exeWait();
void exeShake();
void exeShakeLoop();

void startShakeByIndex(s32 index, s32 steps);

private:
sead::Vector2f mOffset = {0.0f, 0.0f};
const ShakeInfo* mActiveShake = nullptr;
const ShakeInfo* mShakeLoop = nullptr;
ShakeInfo mEditedShake = {};
};

static_assert(sizeof(CameraShaker) == 0x40);

} // namespace al

0 comments on commit 617833d

Please sign in to comment.