Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
300 lines
8.9 KiB
C++
300 lines
8.9 KiB
C++
// CameraStateEngine.cpp ********************************************//
|
|
// Copyright Microsoft Corporation, 2001 //
|
|
// Created Owner Modification //
|
|
// -------- ------ ------------- //
|
|
// 3/7/2001 sdemar class definition for spectator state engine //
|
|
//*******************************************************************//
|
|
#include "CameraStateEngine.h"
|
|
using namespace MSRSpectator;
|
|
#include "SpectatorDebug.h"
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
#include "MW4.hpp"
|
|
#include "MWApplication.hpp"
|
|
#include "GameOS\GameOS.hpp"
|
|
#include "Mech.hpp"
|
|
|
|
|
|
|
|
CCameraStateEngine::CCameraStateEngine()
|
|
:
|
|
m_cameraState(STATE_STD_OBSERVERMODE),
|
|
m_cameraDist(NO_RANGE),
|
|
m_fSelectState(false),
|
|
m_distanceBetween(0.0f),
|
|
m_fNewShot(true),
|
|
m_fPrevWasOverShoulder(false)
|
|
|
|
{
|
|
m_stateTimer.Initialize(3);
|
|
m_dampTimer.Expire();
|
|
}
|
|
|
|
|
|
CCameraStateEngine::~CCameraStateEngine()
|
|
{
|
|
// stubbed
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::TestInstance(void) const
|
|
{
|
|
// stubbed, required for Check_Object()
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::ForceStateChange()
|
|
{
|
|
m_stateTimer.Expire();
|
|
m_fSelectState = true;
|
|
NullSpectatorState();
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::NullSpectatorState()
|
|
{
|
|
if (m_stateTimer.CheckExpired())
|
|
m_stateTimer.Initialize(1.5);
|
|
m_cameraState = STATE_STD_OBSERVERMODE;
|
|
m_cameraDist = NO_RANGE;
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::BumpStateTimer(double addAmt)
|
|
{
|
|
double timeRemaining = m_stateTimer.GetTimeRemaining();
|
|
if (timeRemaining > 0.0 && timeRemaining < addAmt)
|
|
m_stateTimer.Initialize(timeRemaining + addAmt);
|
|
else
|
|
m_stateTimer.Initialize(addAmt);
|
|
|
|
|
|
m_fSelectState = false;
|
|
}
|
|
|
|
|
|
|
|
double CCameraStateEngine::GetDampTimerRemaining()
|
|
{
|
|
return m_dampTimer.GetTimeRemaining();
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::InitDampTimer(double inTime)
|
|
{
|
|
m_dampTimer.Initialize(inTime);
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::ExpireDampTimer()
|
|
{
|
|
m_dampTimer.Expire();
|
|
}
|
|
|
|
|
|
int CCameraStateEngine::GetCameraStateToExecute(bool& stateChanged, int& cameraDist)
|
|
{
|
|
// NOTE, normally in a state engine, code would execute here per state.
|
|
// However we want to keep the game specific code in the game components.
|
|
// In our case that is camera work. So all we do here is monitor the
|
|
// state timer condition as to whether its time for a new state.
|
|
|
|
if (m_stateTimer.CheckExpired())
|
|
{
|
|
m_fSelectState = true;
|
|
}
|
|
|
|
stateChanged = m_fSelectState;
|
|
|
|
// And we return the camera state to the game engine so it can deal with
|
|
// executing the current MW4 Spectator specific cameras.
|
|
// NOTE: We execute once more on current camera because we may need to store
|
|
// game parameters to transition between this and the upcoming camera.
|
|
cameraDist = m_cameraDist;
|
|
return m_cameraState;
|
|
}
|
|
|
|
|
|
void CCameraStateEngine::StateTransitionExecute(bool fIsSamePairing, float distanceBetween)
|
|
{
|
|
// Here is where we do some basic camera choosing based on distance. We also
|
|
// randomly choose between cameras good at a given distance to break things up
|
|
// a little more. Since we are depending on indeterminate action you will adjust this
|
|
// section as appropriate for the kind of action you will encounter in your game.
|
|
|
|
// If the spectator mode ever becomes a cached-time process this section will change
|
|
// dramatically as you will be able to include logic for predictive decision making.
|
|
// Such as being able to look ahead in the data stream to see an event of interest about to
|
|
// happen somewhere in the world. In those situations you may want to deliberately move
|
|
// or place a camera before the event occurs to get a more interesting shot.
|
|
|
|
if (m_fSelectState == true)
|
|
{
|
|
m_fSelectState = false;
|
|
|
|
if (distanceBetween <= MAX_SIDE_DIST)
|
|
{
|
|
if (rand() % 3 == 0)
|
|
{ // 33.3%
|
|
m_stateTimer.Initialize(1.5);
|
|
m_cameraState = STATE_FIXED_TRACKING_SHOT;
|
|
m_cameraDist = MEDIUMSHOT;
|
|
}
|
|
else
|
|
{ // 66.6%
|
|
m_stateTimer.Initialize(2.0);
|
|
m_cameraState = STATE_SIDE_SHOT;
|
|
m_cameraDist = NO_RANGE;
|
|
}
|
|
}
|
|
else if ((MAX_SIDE_DIST < distanceBetween) && (distanceBetween <= 210.0f))
|
|
{
|
|
// over shoulder shots require some attention. Its possible for our hero
|
|
// to be engaging two or more enemys in random order. To keep the camera
|
|
// from radically jogging from one to another enemy, we use a transitioning
|
|
// shot.
|
|
if (m_fPrevWasOverShoulder || ((rand() % 3) != 0))
|
|
{ // 66.6%
|
|
m_fPrevWasOverShoulder = false;
|
|
m_stateTimer.Initialize(1.0);
|
|
m_cameraState = STATE_FRONT_SHOT;
|
|
m_cameraDist = CLOSESHOT;
|
|
}
|
|
else
|
|
{ // 33.3%
|
|
m_fPrevWasOverShoulder = true;
|
|
m_stateTimer.Initialize(3.0);
|
|
m_cameraState = STATE_OVERSHOULDER_SHOT;
|
|
m_cameraDist = MEDIUMSHOT;
|
|
}
|
|
}
|
|
else if ((210.0f < distanceBetween) && (distanceBetween <= 290.0f))
|
|
{
|
|
int cameraState, cameraDist;
|
|
do {
|
|
switch(rand() % 3) {
|
|
case 0:
|
|
cameraState = STATE_FRONT_SHOT;
|
|
break;
|
|
case 1:
|
|
cameraState = STATE_OVERSHOULDER_SHOT;
|
|
break;
|
|
default:
|
|
cameraState = STATE_FIXED_TRACKING_SHOT;
|
|
break;
|
|
}
|
|
switch(rand() % 3) {
|
|
case 0:
|
|
cameraDist = CLOSESHOT;
|
|
break;
|
|
case 1:
|
|
cameraDist = MEDIUMSHOT;
|
|
break;
|
|
default:
|
|
cameraDist = LONGSHOT;
|
|
break;
|
|
}
|
|
} while(((cameraState == m_cameraState) && (cameraDist == m_cameraDist)) || ((cameraState == STATE_OVERSHOULDER_SHOT) && m_fPrevWasOverShoulder));
|
|
switch(cameraState) {
|
|
default:
|
|
m_fPrevWasOverShoulder = false;
|
|
m_stateTimer.Initialize(2.0);
|
|
break;
|
|
case STATE_STD_OBSERVERMODE:
|
|
m_fPrevWasOverShoulder = true;
|
|
m_stateTimer.Initialize(3.0);
|
|
break;
|
|
}
|
|
m_cameraState = cameraState;
|
|
//m_cameraDist = cameraDist;
|
|
if (cameraState == STATE_FRONT_SHOT) {
|
|
m_cameraDist = MEDIUMSHOT;
|
|
} else {
|
|
m_cameraDist = LONGSHOT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int cameraState, cameraDist;
|
|
do {
|
|
switch(rand() % 3) {
|
|
case 0:
|
|
cameraState = STATE_FRONT_SHOT;
|
|
break;
|
|
case 1:
|
|
cameraState = STATE_OVERSHOULDER_SHOT;
|
|
break;
|
|
case 2:
|
|
cameraState = STATE_FIXED_TRACKING_SHOT;
|
|
default:
|
|
cameraState = STATE_STD_OBSERVERMODE;
|
|
break;
|
|
}
|
|
if (cameraState == STATE_STD_OBSERVERMODE) {
|
|
cameraDist = NO_RANGE;
|
|
} else {
|
|
switch(rand() % 3) {
|
|
case 0:
|
|
cameraDist = CLOSESHOT;
|
|
break;
|
|
case 1:
|
|
cameraDist = MEDIUMSHOT;
|
|
break;
|
|
default:
|
|
cameraDist = LONGSHOT;
|
|
break;
|
|
}
|
|
}
|
|
} while(((cameraState == m_cameraState) && (cameraDist == m_cameraDist)) || ((cameraState == STATE_OVERSHOULDER_SHOT) && m_fPrevWasOverShoulder));
|
|
switch(cameraState) {
|
|
default:
|
|
m_fPrevWasOverShoulder = false;
|
|
m_stateTimer.Initialize(1.5);
|
|
break;
|
|
case STATE_FIXED_TRACKING_SHOT:
|
|
m_fPrevWasOverShoulder = false;
|
|
m_stateTimer.Initialize(2.0);
|
|
break;
|
|
case STATE_STD_OBSERVERMODE:
|
|
m_fPrevWasOverShoulder = true;
|
|
m_stateTimer.Initialize(3.0);
|
|
break;
|
|
}
|
|
m_cameraState = cameraState;
|
|
//m_cameraDist = cameraDist;
|
|
switch (cameraState)
|
|
{
|
|
case STATE_FIXED_TRACKING_SHOT:
|
|
m_cameraDist = LONGSHOT;
|
|
break;
|
|
|
|
case STATE_FRONT_SHOT:
|
|
m_cameraDist = CLOSESHOT;
|
|
break;
|
|
|
|
case STATE_OVERSHOULDER_SHOT:
|
|
m_cameraDist = CLOSESHOT;
|
|
break;
|
|
case STATE_STD_OBSERVERMODE:
|
|
m_cameraDist = NO_RANGE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool CCameraStateEngine::GetIsTimeToSelectNewShot()
|
|
{
|
|
return m_fSelectState;
|
|
}
|
|
|
|
|
|
bool CCameraStateEngine::fIsValidSideDistance(float dist) const
|
|
{
|
|
return (dist >= 4.0f && dist <= MAX_SIDE_DIST);
|
|
} |