Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more spectate free cam controls #392

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/game/CAbstractPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ void CAbstractPlayer::LoadScout() {
}

void CAbstractPlayer::LoadFreeCam() {

itsFreeCam = new CFreeCam(this);
itsFreeCam->BeginScript();
FreshCalc();
itsFreeCam->EndScript();
SetFreeCamState(false);
}

void CAbstractPlayer::WriteDBG(int index, float val) {
Expand Down Expand Up @@ -988,7 +988,11 @@ void CAbstractPlayer::ResetDashboard() {
}

void CAbstractPlayer::ToggleFreeCam() {
freeView = !freeView;
SetFreeCamState(!freeView);
}

void CAbstractPlayer::SetFreeCamState(Boolean state) {
freeView = state;

itsGame->ToggleFreeCam(freeView);
itsFreeCam->ToggleState(freeView);
Expand Down
1 change: 1 addition & 0 deletions src/game/CAbstractPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ class CAbstractPlayer : public CRealMovers {
//

virtual void ToggleFreeCam();
virtual void SetFreeCamState(Boolean state);
virtual Boolean IsFreeCamAttached();
virtual void ControlSoundPoint();
virtual void ControlViewPoint();
Expand Down
121 changes: 56 additions & 65 deletions src/game/CFreeCam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ CFreeCam::CFreeCam(CAbstractPlayer *thePlayer) {

camSpeed = 350;
radius = FIX3(25000);
pitch = FIX3(125); // 45 degrees
heading = 0;

isAttached = false;
action = camInactive;
isActive = kIsActive;
partCount = 0;
Expand All @@ -23,13 +26,15 @@ CFreeCam::CFreeCam(CAbstractPlayer *thePlayer) {
void CFreeCam::ToggleState(Boolean state) {
CAbstractPlayer *spectatePlayer = itsGame->GetSpectatePlayer();

if (state && spectatePlayer != NULL) {
if (state) {
if (action == camInactive) {
itsGame->AddActor(this);
itsPlayer->freeCamIdent = ident;
action = camAnimating;
}
isAttached = true;
if (spectatePlayer != NULL) {
isAttached = true;
}
}
}

Expand All @@ -46,115 +51,101 @@ void CFreeCam::ViewControl(FunctionTable *ft) {
Vector direction;
CAbstractPlayer *spectatePlayer = itsGame->GetSpectatePlayer();

// This sets up the ability for the camera to follow a player
if (isAttached && spectatePlayer != NULL) {
vp->LookAtPart(spectatePlayer->viewPortPart);
}

// Find direction vector for the camera
direction[0] = vp->atPoint[0] - vp->fromPoint[0];
direction[1] = vp->atPoint[1] - vp->fromPoint[1];
direction[2] = vp->atPoint[2] - vp->fromPoint[2];

// Find length of direction vector
Fixed len = FSqrt(FMul(direction[0], direction[0]) + FMul(direction[2], direction[2]));

// Normalize Direction vector
direction[0] = FDivNZ(direction[0], len);
//direction[1] = FDivNZ(direction[1], len);
direction[2] = FDivNZ(direction[2], len);

// Calc the horizontal viewing angle from the direction vector
Fixed heading, pitch;
heading = FOneArcTan2(direction[0], direction[2]);

// Find new direction vector if mouse moved
Fixed xRot=0, zRot=0;
if (ft->mouseDelta.h > 0) {
heading -= FIX3(5);
} else if (ft->mouseDelta.h < 0) {
heading += FIX3(5);
}
xRot = FOneCos(heading);
zRot = FOneSin(heading);
// Mouse movements adjust polar coordinates
heading += FIX3(ft->mouseDelta.h * .2);
pitch -= FIX3(ft->mouseDelta.v * .2);
if (pitch > FIX3(250)) pitch = FIX3(250);
if (pitch < FIX3(10)) pitch = FIX3(10);

// Convert from polar to cartesian
// Find normalized camera position
Fixed xRot=0, yRot=0, zRot=0;
xRot = FMul(FOneCos(heading), FOneSin(pitch));
yRot = FOneCos(pitch);
zRot = FMul(FOneSin(heading), FOneSin(pitch));
direction[0] = xRot;
direction[1] = yRot;
direction[2] = zRot;

// Calc movement distance for each axis
// Calc potential velocity for each axis
Fixed finalXSpeed = FMulDivNZ(direction[0], ToFixed(camSpeed), ToFixed(1000));
Fixed finalYSpeed = FIX3(camSpeed);
Fixed finalZSpeed = FMulDivNZ(direction[2], ToFixed(camSpeed), ToFixed(1000));

// Camera rotation
// Set actual camera position
vp->fromPoint[0] = vp->atPoint[0] - FMul(direction[0], radius);
vp->fromPoint[1] = vp->atPoint[1] + FMul(direction[1], radius);
vp->fromPoint[2] = vp->atPoint[2] - FMul(direction[2], radius);

// Zoom out
if (TESTFUNC(kfuZoomOut, ft->held)) {
radius += FIX3(camSpeed);
if (radius > FIX3(50000)) {
radius = FIX3(50000);
}
}
// Zoom In
if (TESTFUNC(kfuZoomIn, ft->held)) {
radius -= FIX3(camSpeed);
if (radius < FIX3(10000)) {
radius = FIX3(10000);
}
}

// Orthogonal camera movement
if (TESTFUNC(kfuFreeCamForward, ft->held)) {
if (TESTFUNC(kfuForward, ft->held)) {
isAttached = false;
vp->fromPoint[0] += finalXSpeed;
vp->fromPoint[2] += finalZSpeed;
vp->atPoint[0] += finalXSpeed;
vp->atPoint[2] += finalZSpeed;
}
if (TESTFUNC(kfuFreeCamBackward, ft->held)) {
if (TESTFUNC(kfuReverse, ft->held)) {
isAttached = false;
vp->fromPoint[0] -= finalXSpeed;
vp->fromPoint[2] -= finalZSpeed;
vp->atPoint[0] -= finalXSpeed;
vp->atPoint[2] -= finalZSpeed;
}
if (TESTFUNC(kfuFreeCamLeft, ft->held)) {
if (TESTFUNC(kfuLeft, ft->held)) {
isAttached = false;
vp->fromPoint[0] += finalZSpeed;
vp->fromPoint[2] -= finalXSpeed;
vp->atPoint[0] += finalZSpeed;
vp->atPoint[2] -= finalXSpeed;
}
if (TESTFUNC(kfuFreeCamRight, ft->held)) {
if (TESTFUNC(kfuRight, ft->held)) {
isAttached = false;
vp->fromPoint[0] -= finalZSpeed;
vp->fromPoint[2] += finalXSpeed;
vp->atPoint[0] -= finalZSpeed;
vp->atPoint[2] += finalXSpeed;
}

// Handle y-axis movement differently depending on if the camera is attached to a player or not
// Up
if (TESTFUNC(kfuFreeCamUp, ft->held)) {
if (isAttached) {
// Cam is attached so don't move focal point
vp->fromPoint[1] += finalYSpeed;
} else {
vp->fromPoint[1] += finalYSpeed;
// Don't move focal point until threshold is passed
if (vp->fromPoint[1] > yFromThreshold) {
vp->atPoint[1] += finalYSpeed;
}
}
isAttached = false;
vp->atPoint[1] += finalYSpeed;
vp->fromPoint[1] += finalYSpeed;
}
// Down
if (TESTFUNC(kfuFreeCamDown, ft->held)) {
if (isAttached) {
// Cam is attached so don't move focal point
// Cam can't go below focal point
vp->fromPoint[1] -= finalYSpeed;
if (vp->fromPoint[1] < vp->atPoint[1]) {
vp->fromPoint[1] = vp->atPoint[1];
}
} else {
// Don't let camera or focal point go below y=0
// When zero is reached, save the height of the camera
// The focal point will not move on the y-axis until the camera is at least as far away (on y-axis) as the saved threshold
if (vp->atPoint[1] != 0)
vp->atPoint[1] -= finalYSpeed;

if (vp->atPoint[1] < 0) {
yFromThreshold = vp->fromPoint[1];
// Leave camera attached if already at y=0
if (vp->atPoint[1] > 0) {
isAttached = false;
// Focal point should not go below 0
// If focal point does go below zero, move camera by the same amount to keep it at a fixed distance
if (vp->atPoint[1] - finalYSpeed < 0) {
vp->fromPoint[1] -= vp->atPoint[1];
vp->atPoint[1] = 0;
}
vp->fromPoint[1] -= finalYSpeed;
if (vp->fromPoint[1] < 0) {
vp->fromPoint[1] = 0;
} else {
vp->atPoint[1] -= finalYSpeed;
vp->fromPoint[1] -= finalYSpeed;
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/game/CFreeCam.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ class CFreeCam final : public CRealMovers {
CViewParameters *freeParams;

short action;
Fixed radius;
Fixed yFromThreshold;
Fixed radius, heading, pitch;
short camSpeed;
Boolean isAttached;

Expand Down
4 changes: 0 additions & 4 deletions src/game/CPlayerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ void CPlayerManagerImpl::IPlayerManager(CAvaraGame *theGame, short id, CNetManag
{"chatMode", 1 << kfuTypeText},
{"freeCamUp", 1 << kfuFreeCamUp},
{"freeCamDown", 1 << kfuFreeCamDown},
{"freeCamForward", 1 << kfuFreeCamForward},
{"freeCamLeft", 1 << kfuFreeCamLeft},
{"freeCamRight", 1 << kfuFreeCamRight},
{"freeCamBackward", 1 << kfuFreeCamBackward},
{"debug1", 1 << kfuDebug1},
{"debug2", 1 << kfuDebug2}};

Expand Down
4 changes: 0 additions & 4 deletions src/game/KeyFuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ enum {
kfuLookRight,
kfuAimForward,

kfuFreeCamForward,
kfuFreeCamBackward,
kfuFreeCamLeft,
kfuFreeCamRight,
kfuFreeCamUp,
kfuFreeCamDown,

Expand Down
14 changes: 11 additions & 3 deletions src/gui/CApplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,20 @@ bool CApplication::Update(const std::string name, std::string &value) {
}
try {
json updatePref = json::parse("{ \"" + name + "\": " + value + "}");
_prefs.update(updatePref);
WritePrefs(_prefs);

// If the type of the new value is different than the old one
// this will easily cause a crash when reading the json
if (_prefs[name].type_name() == updatePref[name].type_name()) {
_prefs.update(updatePref);
WritePrefs(_prefs);
} else {
SDL_Log("Type mismatch. User added type '%s' did not match existing type '%s'. Prefs were not updated.", _prefs[name].type_name(), updatePref[name].type_name());
return false;
}
}
catch (json::parse_error &ex) {
// User typed in the command to change a pref. The value type did not match for the given pref
SDL_Log("User input value '%s' did not parse to the correct type.", name.c_str());
SDL_Log("User input value for '%s' did not parse to the correct type.", name.c_str());
return false; // Did not update pref
}
return true; // Successfully updated pref
Expand Down
2 changes: 1 addition & 1 deletion src/gui/CRosterWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ std::string CRosterWindow::GetStringStatus(CPlayerManager *player) {
strStatus = "away";
}
if (presence == kzSpectating) {
if (player->LoadingStatusIsIn(kLConnected, kLActive, kLLoaded, kLPaused)) {
if (player->LoadingStatusIsIn(kLConnected, kLActive, kLReady, kLLoaded, kLPaused)) {
strStatus = "spectator";
} else if (strStatus.length() > 0) {
strStatus += "*"; // make this into an eyeball char?
Expand Down
8 changes: 2 additions & 6 deletions src/gui/Preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,8 @@ static json defaultPrefs = {
{"spectatePrevious", "["},
{"scoreboard", "/"},
{"chatMode", "Return"},
{"freeCamUp", "Q"},
{"freeCamDown", "E"},
{"freeCamForward", "W"},
{"freeCamLeft", "A"},
{"freeCamRight", "D"},
{"freeCamBackward", "S"},
{"freeCamUp", "R"},
{"freeCamDown", "F"},
{"debug1", "5"},
{"debug2", "6"}}
},
Expand Down
5 changes: 5 additions & 0 deletions src/tui/CommandManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ bool CommandManager::GetSetPreference(VectorOfArgs vargs) {
//write prefs
itsApp->AddMessageLine(prefName + " changed from " + oldValue + " to " + newValue);
itsApp->CApplication::PrefChanged(prefName);
} else {
itsApp->AddMessageLine("Error: Pref not updated",
MsgAlignment::Left,
MsgCategory::Error
);
}
}
}
Expand Down
Loading