mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-23 08:24:16 +00:00
390 lines
8.6 KiB
C++
390 lines
8.6 KiB
C++
#include "legonavcontroller.h"
|
|
|
|
#include "legoinputmanager.h"
|
|
#include "legoutils.h"
|
|
#include "legovideomanager.h"
|
|
#include "misc.h"
|
|
#include "mxmisc.h"
|
|
#include "mxtimer.h"
|
|
|
|
#include <vec.h>
|
|
|
|
DECOMP_SIZE_ASSERT(LegoNavController, 0x70)
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.1416
|
|
#endif
|
|
#ifdef DTOR
|
|
#undef DTOR
|
|
#endif
|
|
#define DTOR(angle) ((angle) * M_PI / 180.)
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// GLOBAL: LEGO1 0x100f4c28
|
|
int LegoNavController::g_defdeadZone = 40;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c2c
|
|
float LegoNavController::g_defzeroThreshold = 0.001f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c30
|
|
float LegoNavController::g_defmaxLinearVel = 40.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c34
|
|
float LegoNavController::g_defmaxRotationalVel = 20.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c38
|
|
float LegoNavController::g_defmaxLinearAccel = 15.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c3c
|
|
float LegoNavController::g_defmaxRotationalAccel = 30.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c40
|
|
float LegoNavController::g_defminLinearAccel = 4.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c44
|
|
float LegoNavController::g_defminRotationalAccel = 15.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c48
|
|
float LegoNavController::g_defmaxLinearDeccel = 50.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c4c
|
|
float LegoNavController::g_defmaxRotationalDeccel = 50.0f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c50
|
|
float LegoNavController::g_defrotSensitivity = 0.4f;
|
|
|
|
// GLOBAL: LEGO1 0x100f4c54
|
|
MxBool LegoNavController::g_defuseRotationalVel = FALSE;
|
|
|
|
// FUNCTION: LEGO1 0x10054ac0
|
|
LegoNavController::LegoNavController()
|
|
{
|
|
SetToDefaultParams();
|
|
|
|
m_linearVel = 0.0f;
|
|
m_rotationalVel = 0.0f;
|
|
m_targetLinearVel = 0.0f;
|
|
m_targetRotationalVel = 0.0f;
|
|
m_linearAccel = 0.0f;
|
|
m_rotationalAccel = 0.0f;
|
|
m_trackDefault = FALSE;
|
|
m_unk0x5d = FALSE;
|
|
m_unk0x6c = FALSE;
|
|
m_unk0x64 = 0.0f;
|
|
m_unk0x68 = 0.0f;
|
|
m_unk0x60 = 0.0f;
|
|
|
|
m_lastTime = Timer()->GetTime();
|
|
|
|
InputManager()->Register(this);
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054c30
|
|
LegoNavController::~LegoNavController()
|
|
{
|
|
InputManager()->UnRegister(this);
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054ca0
|
|
void LegoNavController::SetControlMax(int p_hMax, int p_vMax)
|
|
{
|
|
m_hMax = p_hMax;
|
|
m_vMax = p_vMax;
|
|
|
|
if (VideoManager()->GetVideoParam().Flags().GetFullScreen()) {
|
|
m_hMax = 640;
|
|
m_vMax = 480;
|
|
}
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054cd0
|
|
void LegoNavController::SetToDefaultParams()
|
|
{
|
|
m_deadZone = g_defdeadZone;
|
|
m_zeroThreshold = g_defzeroThreshold;
|
|
m_maxRotationalAccel = g_defmaxRotationalAccel;
|
|
m_maxLinearAccel = g_defmaxLinearAccel;
|
|
m_minRotationalAccel = g_defminRotationalAccel;
|
|
m_minLinearAccel = g_defminLinearAccel;
|
|
m_maxRotationalDeccel = g_defmaxRotationalDeccel;
|
|
m_maxLinearDeccel = g_defmaxLinearDeccel;
|
|
m_maxRotationalVel = g_defmaxRotationalVel;
|
|
m_maxLinearVel = g_defmaxLinearVel;
|
|
m_useRotationalVel = g_defuseRotationalVel;
|
|
m_rotSensitivity = g_defrotSensitivity;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054d40
|
|
void LegoNavController::GetDefaults(
|
|
int* p_dz,
|
|
float* p_lv,
|
|
float* p_rv,
|
|
float* p_la,
|
|
float* p_ra,
|
|
float* p_ld,
|
|
float* p_rd,
|
|
float* p_lmina,
|
|
float* p_rmina,
|
|
float* p_rs,
|
|
MxBool* p_urs
|
|
)
|
|
{
|
|
*p_dz = g_defdeadZone;
|
|
*p_lv = g_defmaxLinearVel;
|
|
*p_rv = g_defmaxRotationalVel;
|
|
*p_la = g_defmaxLinearAccel;
|
|
*p_ra = g_defmaxRotationalAccel;
|
|
*p_ld = g_defmaxLinearDeccel;
|
|
*p_rd = g_defmaxRotationalDeccel;
|
|
*p_lmina = g_defminLinearAccel;
|
|
*p_rmina = g_defminRotationalAccel;
|
|
*p_rs = g_defrotSensitivity;
|
|
*p_urs = g_defuseRotationalVel;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054dd0
|
|
void LegoNavController::SetDefaults(
|
|
int p_dz,
|
|
float p_lv,
|
|
float p_rv,
|
|
float p_la,
|
|
float p_ra,
|
|
float p_ld,
|
|
float p_rd,
|
|
float p_lmina,
|
|
float p_rmina,
|
|
float p_rs,
|
|
MxBool p_urs
|
|
)
|
|
{
|
|
g_defdeadZone = p_dz;
|
|
g_defmaxLinearVel = p_lv;
|
|
g_defmaxRotationalVel = p_rv;
|
|
g_defmaxLinearAccel = p_la;
|
|
g_defmaxRotationalAccel = p_ra;
|
|
g_defmaxLinearDeccel = p_ld;
|
|
g_defmaxRotationalDeccel = p_rd;
|
|
g_defminLinearAccel = p_lmina;
|
|
g_defminRotationalAccel = p_rmina;
|
|
g_defrotSensitivity = p_rs;
|
|
g_defuseRotationalVel = p_urs;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054e40
|
|
void LegoNavController::SetTargets(int p_hPos, int p_vPos, MxBool p_accel)
|
|
{
|
|
if (m_trackDefault != FALSE) {
|
|
SetToDefaultParams();
|
|
}
|
|
|
|
if (p_accel != FALSE) {
|
|
m_targetRotationalVel = CalculateNewTargetVel(p_hPos, m_hMax / 2, m_maxRotationalVel);
|
|
m_targetLinearVel = CalculateNewTargetVel(m_vMax - p_vPos, m_vMax / 2, m_maxLinearVel);
|
|
m_rotationalAccel = CalculateNewAccel(p_hPos, m_hMax / 2, m_maxRotationalAccel, (int) m_minRotationalAccel);
|
|
m_linearAccel = CalculateNewAccel(m_vMax - p_vPos, m_vMax / 2, m_maxLinearAccel, (int) m_minLinearAccel);
|
|
}
|
|
else {
|
|
m_targetRotationalVel = 0;
|
|
m_targetLinearVel = 0;
|
|
m_linearAccel = m_maxLinearDeccel;
|
|
m_rotationalAccel = m_maxRotationalDeccel;
|
|
}
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054f10
|
|
float LegoNavController::CalculateNewTargetVel(int p_pos, int p_center, float p_max)
|
|
{
|
|
float newVel;
|
|
int diff = p_pos - p_center;
|
|
|
|
if (diff > m_deadZone) {
|
|
newVel = (diff - m_deadZone) * p_max / (p_center - m_deadZone);
|
|
}
|
|
else if (diff < -m_deadZone) {
|
|
newVel = (diff + m_deadZone) * p_max / (p_center - m_deadZone);
|
|
}
|
|
else {
|
|
newVel = 0.0;
|
|
}
|
|
|
|
return newVel;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054f90
|
|
float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_max, int p_min)
|
|
{
|
|
float newAccel;
|
|
int diff = p_pos - p_center;
|
|
|
|
newAccel = Abs(diff) * p_max / p_center;
|
|
|
|
if (newAccel < p_min) {
|
|
newAccel = (float) p_min;
|
|
}
|
|
|
|
return newAccel;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10054fe0
|
|
float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time)
|
|
{
|
|
float newVel = p_currentVel;
|
|
|
|
float velDiff = p_targetVel - p_currentVel;
|
|
int vSign = velDiff > 0 ? 1 : -1;
|
|
|
|
if (Abs(velDiff) > m_zeroThreshold) {
|
|
float deltaVel = p_accel * p_time;
|
|
newVel = p_currentVel + (deltaVel * vSign);
|
|
|
|
if (vSign > 0) {
|
|
newVel = Min(newVel, p_targetVel);
|
|
}
|
|
else {
|
|
newVel = Max(newVel, p_targetVel);
|
|
}
|
|
}
|
|
|
|
return newVel;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x10055080
|
|
MxBool LegoNavController::CalculateNewPosDir(
|
|
const Vector3& p_curPos,
|
|
const Vector3& p_curDir,
|
|
Vector3& p_newPos,
|
|
Vector3& p_newDir,
|
|
const Vector3* p_und
|
|
)
|
|
{
|
|
if (!g_isWorldActive) {
|
|
return FALSE;
|
|
}
|
|
|
|
MxBool changed = FALSE;
|
|
MxBool und = FALSE;
|
|
|
|
MxTime currentTime = Timer()->GetTime();
|
|
float deltaTime = (currentTime - m_lastTime) / 1000.0;
|
|
m_lastTime = currentTime;
|
|
|
|
if (FUN_100558b0() == -1) {
|
|
FUN_10055750(und);
|
|
}
|
|
|
|
if (m_useRotationalVel) {
|
|
m_rotationalVel = CalculateNewVel(m_targetRotationalVel, m_rotationalVel, m_rotationalAccel * 40.0f, deltaTime);
|
|
}
|
|
else {
|
|
m_rotationalVel = m_targetRotationalVel;
|
|
}
|
|
|
|
m_linearVel = CalculateNewVel(m_targetLinearVel, m_linearVel, m_linearAccel, deltaTime);
|
|
|
|
if (und || (Abs(m_rotationalVel) > m_zeroThreshold) || (Abs(m_linearVel) > m_zeroThreshold)) {
|
|
float rot_mat[3][3];
|
|
Mx3DPointFloat delta_pos, new_dir, new_pos;
|
|
|
|
if (m_linearVel < -(m_maxLinearVel * 0.4f)) {
|
|
m_linearVel = -(m_maxLinearVel * 0.4f);
|
|
}
|
|
|
|
VXS3(delta_pos, p_curDir, m_linearVel * deltaTime);
|
|
VPV3(p_newPos, p_curPos, delta_pos);
|
|
|
|
float delta_rad;
|
|
if (m_useRotationalVel) {
|
|
delta_rad = DTOR(m_rotationalVel * deltaTime);
|
|
}
|
|
else {
|
|
delta_rad = DTOR(m_rotationalVel * m_rotSensitivity);
|
|
}
|
|
|
|
if (p_und != NULL && (*p_und)[1] < 0.0f) {
|
|
delta_rad = -delta_rad;
|
|
}
|
|
|
|
IDENTMAT3(rot_mat);
|
|
rot_mat[0][0] = rot_mat[2][2] = cos(delta_rad);
|
|
rot_mat[0][2] = rot_mat[2][0] = sin(delta_rad);
|
|
rot_mat[0][2] *= -1.0f;
|
|
VXM3(p_newDir, p_curDir, rot_mat);
|
|
|
|
changed = TRUE;
|
|
}
|
|
|
|
if (m_unk0x5d) {
|
|
float rot_mat[3][3];
|
|
Mx3DPointFloat delta_pos, new_pos, new_dir;
|
|
|
|
if (changed) {
|
|
SET3(new_pos, p_newPos);
|
|
SET3(new_dir, p_newDir);
|
|
}
|
|
else {
|
|
SET3(new_pos, p_curPos);
|
|
SET3(new_dir, p_curDir);
|
|
}
|
|
|
|
if (m_unk0x64 != 0.0f) {
|
|
delta_pos[0] = new_dir[0] * m_unk0x64;
|
|
delta_pos[1] = new_dir[1] * m_unk0x64;
|
|
delta_pos[2] = new_dir[2] * m_unk0x64;
|
|
}
|
|
else {
|
|
FILLVEC3(delta_pos, 0.0f);
|
|
}
|
|
|
|
delta_pos[1] += m_unk0x60;
|
|
VPV3(p_newPos, new_pos, delta_pos);
|
|
|
|
if (m_unk0x68 != 0.0f) {
|
|
float delta_rad = DTOR(m_unk0x68);
|
|
IDENTMAT3(rot_mat);
|
|
rot_mat[0][0] = rot_mat[2][2] = cos(delta_rad);
|
|
rot_mat[0][2] = rot_mat[2][0] = sin(delta_rad);
|
|
rot_mat[0][2] *= -1.0f;
|
|
VXM3(p_newDir, new_dir, rot_mat);
|
|
}
|
|
else {
|
|
SET3(p_newDir, new_dir);
|
|
}
|
|
|
|
m_unk0x60 = m_unk0x64 = m_unk0x68 = 0.0f;
|
|
m_unk0x5d = FALSE;
|
|
changed = TRUE;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
// STUB: LEGO1 0x10055620
|
|
void LegoNavController::SetLocation(MxU32 p_location)
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
// STUB: LEGO1 0x10055750
|
|
int LegoNavController::FUN_10055750(MxBool& p_und)
|
|
{
|
|
// TODO
|
|
return -1;
|
|
}
|
|
|
|
// STUB: LEGO1 0x100558b0
|
|
int LegoNavController::FUN_100558b0()
|
|
{
|
|
// TODO
|
|
return -1;
|
|
}
|
|
|
|
// STUB: LEGO1 0x10055a60
|
|
MxLong LegoNavController::Notify(MxParam& p_param)
|
|
{
|
|
// TODO
|
|
return 0;
|
|
}
|