Commit 9622f93d authored by Daniel Buckmaster's avatar Daniel Buckmaster

Fix weapon image camera shake.

parent 2dd23e45
......@@ -940,8 +940,6 @@ ShapeBase::ShapeBase()
for (i = 0; i < MaxTriggerKeys; i++)
mTrigger[i] = false;
mWeaponCamShake = NULL;
}
......@@ -1063,15 +1061,7 @@ void ShapeBase::onRemove()
if ( isClientObject() )
{
mCubeReflector.unregisterReflector();
if ( mWeaponCamShake )
{
if ( mWeaponCamShake->isAdded )
gCamFXMgr.removeFX( mWeaponCamShake );
SAFE_DELETE( mWeaponCamShake );
}
mCubeReflector.unregisterReflector();
}
}
......@@ -3161,40 +3151,9 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
{
if ( imageData->lightType == ShapeBaseImageData::WeaponFireLight )
image.lightStart = Sim::getCurrentTime();
// HACK: Only works properly if you are in control
// of the one and only shapeBase object in the scene
// which fires an image that uses camera shake.
if ( imageData->shakeCamera )
{
if ( !mWeaponCamShake )
{
mWeaponCamShake = new CameraShake();
mWeaponCamShake->remoteControlled = true;
}
mWeaponCamShake->init();
mWeaponCamShake->setFrequency( imageData->camShakeFreq );
mWeaponCamShake->setAmplitude( imageData->camShakeAmp );
if ( !mWeaponCamShake->isAdded )
{
gCamFXMgr.addFX( mWeaponCamShake );
mWeaponCamShake->isAdded = true;
}
}
}
updateImageState(i,0);
if ( !image.triggerDown && !image.altTriggerDown )
{
if ( mWeaponCamShake && mWeaponCamShake->isAdded )
{
gCamFXMgr.removeFX( mWeaponCamShake );
mWeaponCamShake->isAdded = false;
}
}
}
else
{
......
......@@ -324,7 +324,10 @@ struct ShapeBaseImageData: public GameBaseData {
/// @{
bool shakeCamera;
VectorF camShakeFreq;
VectorF camShakeAmp;
VectorF camShakeAmp;
F32 camShakeDuration;
F32 camShakeRadius;
F32 camShakeFalloff;
/// @}
/// Maximum number of sounds this image can play at a time.
......@@ -903,9 +906,6 @@ protected:
bool mFlipFadeVal;
/// Camera shake caused by weapon fire.
CameraShake *mWeaponCamShake;
public:
/// @name Collision Notification
......@@ -1101,6 +1101,7 @@ protected:
virtual void onImageAnimThreadChange(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState, const char* anim, F32 pos, F32 timeScale, bool reset=false);
virtual void onImageAnimThreadUpdate(U32 imageSlot, S32 imageShapeIndex, F32 dt);
virtual void ejectShellCasing( U32 imageSlot );
virtual void shakeCamera( U32 imageSlot );
virtual void updateDamageLevel();
virtual void updateDamageState();
virtual void onImpact(SceneObject* obj, VectorF vec);
......
......@@ -44,6 +44,7 @@
#include "sfx/sfxTypes.h"
#include "scene/sceneManager.h"
#include "core/stream/fileStream.h"
#include "T3D/fx/cameraFXMgr.h"
//----------------------------------------------------------------------------
......@@ -297,6 +298,9 @@ ShapeBaseImageData::ShapeBaseImageData()
shakeCamera = false;
camShakeFreq = Point3F::Zero;
camShakeAmp = Point3F::Zero;
camShakeDuration = 1.5f;
camShakeRadius = 3.0f;
camShakeFalloff = 10.0f;
}
ShapeBaseImageData::~ShapeBaseImageData()
......@@ -739,10 +743,7 @@ void ShapeBaseImageData::initPersistFields()
"@see lightType");
addField( "shakeCamera", TypeBool, Offset(shakeCamera, ShapeBaseImageData),
"@brief Flag indicating whether the camera should shake when this Image fires.\n\n"
"@note Camera shake only works properly if the player is in control of "
"the one and only shapeBase object in the scene which fires an Image that "
"uses camera shake." );
"@brief Flag indicating whether the camera should shake when this Image fires.\n\n" );
addField( "camShakeFreq", TypePoint3F, Offset(camShakeFreq, ShapeBaseImageData),
"@brief Frequency of the camera shaking effect.\n\n"
......@@ -752,6 +753,16 @@ void ShapeBaseImageData::initPersistFields()
"@brief Amplitude of the camera shaking effect.\n\n"
"@see shakeCamera" );
addField( "camShakeDuration", TypeF32, Offset(camShakeDuration, ShapeBaseImageData),
"Duration (in seconds) to shake the camera." );
addField( "camShakeRadius", TypeF32, Offset(camShakeRadius, ShapeBaseImageData),
"Radial distance that a camera's position must be within relative to the "
"center of the explosion to be shaken." );
addField( "camShakeFalloff", TypeF32, Offset(camShakeFalloff, ShapeBaseImageData),
"Falloff value for the camera shake." );
addField( "casing", TYPEID< DebrisData >(), Offset(casing, ShapeBaseImageData),
"@brief DebrisData datablock to use for ejected casings.\n\n"
"@see stateEjectShell" );
......@@ -1028,6 +1039,9 @@ void ShapeBaseImageData::packData(BitStream* stream)
{
mathWrite( *stream, camShakeFreq );
mathWrite( *stream, camShakeAmp );
stream->write( camShakeDuration );
stream->write( camShakeRadius );
stream->write( camShakeFalloff );
}
mathWrite( *stream, shellExitDir );
......@@ -1208,7 +1222,10 @@ void ShapeBaseImageData::unpackData(BitStream* stream)
if ( shakeCamera )
{
mathRead( *stream, &camShakeFreq );
mathRead( *stream, &camShakeAmp );
mathRead( *stream, &camShakeAmp );
stream->read( &camShakeDuration );
stream->read( &camShakeRadius );
stream->read( &camShakeFalloff );
}
mathRead( *stream, &shellExitDir );
......@@ -2596,6 +2613,10 @@ void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
ejectShellCasing( imageSlot );
}
// Shake camera on client.
if (isGhost() && nextStateData.fire && image.dataBlock->shakeCamera) {
shakeCamera( imageSlot );
}
// Server must animate the shape if it is a firestate...
if (isServerObject() && (image.dataBlock->state[newState].fire || image.dataBlock->state[newState].altFire))
......@@ -3342,3 +3363,57 @@ void ShapeBase::ejectShellCasing( U32 imageSlot )
casing->init( shellPos, shellVel );
}
void ShapeBase::shakeCamera( U32 imageSlot )
{
MountedImage& image = mMountedImageList[imageSlot];
ShapeBaseImageData* imageData = image.dataBlock;
if (!imageData->shakeCamera)
return;
// Warning: this logic was duplicated from Explosion.
// first check if explosion is near camera
GameConnection* connection = GameConnection::getConnectionToServer();
ShapeBase *obj = dynamic_cast<ShapeBase*>(connection->getControlObject());
bool applyShake = true;
if (obj)
{
ShapeBase* cObj = obj;
while ((cObj = cObj->getControlObject()) != 0)
{
if (cObj->useObjsEyePoint())
{
applyShake = false;
break;
}
}
}
if (applyShake && obj)
{
VectorF diff;
getMuzzlePoint(imageSlot, &diff);
diff = obj->getPosition() - diff;
F32 dist = diff.len();
if (dist < imageData->camShakeRadius)
{
CameraShake *camShake = new CameraShake;
camShake->setDuration(imageData->camShakeDuration);
camShake->setFrequency(imageData->camShakeFreq);
F32 falloff = dist / imageData->camShakeRadius;
falloff = 1.0f + falloff * 10.0f;
falloff = 1.0f / (falloff * falloff);
VectorF shakeAmp = imageData->camShakeAmp * falloff;
camShake->setAmplitude(shakeAmp);
camShake->setFalloff(imageData->camShakeFalloff);
camShake->init();
gCamFXMgr.addFX(camShake);
}
}
}
\ No newline at end of file
......@@ -192,9 +192,9 @@ datablock ShapeBaseImageData(RyderWeaponImage)
lightBrightness = 2;
// Shake camera while firing.
shakeCamera = false;
camShakeFreq = "0 0 0";
camShakeAmp = "0 0 0";
shakeCamera = "1";
camShakeFreq = "10 10 10";
camShakeAmp = "5 5 5";
// Images have a state system which controls how the animations
// are run, which sounds are played, script callbacks, etc. This
......@@ -361,4 +361,5 @@ datablock ShapeBaseImageData(RyderWeaponImage)
stateSequenceTransitionOut[13] = true;
stateAllowImageChange[13] = false;
stateSequence[13] = "sprint";
camShakeDuration = "0.2";
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment