Basic Weapon Sway
by Bryce · 04/05/2010 (1:57 pm) · 22 comments
This resource will implement weapon sway in your project. An alternative to a motionless weapon image floating on your screen, weapon sway adds a bit more life to it. When the player turns, the weapon will move a bit in that direction, and when the player stops turning, the weapon creeps back to its original position. It adds a bit more of a natural feel if you ask me.
Issues:
1)Since the $mvPitch and $mvYaw values are updated too inconsistently to produce smooth sway, I have a function that gets these values once every 10th of a second. This most likely won't work networked.
2)Sometimes flickers. I only have this issue with Torque 3D. I'll look into it. EDIT: See comment #11 for the fix
3)Overall, this is an extremely hacky implementation of sway, just an FYI.
Implementation:
Open up T3D/player.h
In struct PlayerData: public ShapeBaseData {, under F32 minImpactSpeed;, add
In class Player: public ShapeBase, under S32 mJumpDelay;, add
Open up T3D/player.cpp
In PlayerData::PlayerData(), under minImpactSpeed = 25.0f;, add
In PlayerData::initPersistFields(), under addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, PlayerData));, add
Find stream->write(minImpactSpeed);, and under it, add
Find stream->read(&minImpactSpeed);. Under it, add
Find mReversePending = 0;, and under it, stick in
In Player::processTick(const Move* move), find updatePos();. Under it, add
In Player::RenderMountedImage, under world.mul(nmat,offsetMat);, add
In this same block, locate world.setPosition( world.getPosition() + displace);, and change it to
That's it for engine changes. Compile, good luck. You should get a lot of warnings about “truncation from 'double' to 'F32'” with Visual C++. I'm not exactly sure what causes it, I don't do a lot of T3D engine coding. Anyone care to shine some light on this?
Anyway. Scripts. Open game/scripts/client/default.bind.cs, and locate
Underneath it, add
Now, find
Change it to
Now, open up art/datablocks/player.cs, go to the DefaultPlayerData datablock, and add in
Do this for your other player datablocks if you have them.
Go into your game, and give it a try! Good luck, and happy Torque'ing!
Issues:
1)Since the $mvPitch and $mvYaw values are updated too inconsistently to produce smooth sway, I have a function that gets these values once every 10th of a second. This most likely won't work networked.
2)Sometimes flickers. I only have this issue with Torque 3D. I'll look into it. EDIT: See comment #11 for the fix
3)Overall, this is an extremely hacky implementation of sway, just an FYI.
Implementation:
Open up T3D/player.h
In struct PlayerData: public ShapeBaseData {, under F32 minImpactSpeed;, add
// weapon sway F32 weaponSwayAmtX; F32 weaponSwayAmtZ; F32 weaponSwayResetX; F32 weaponSwayResetZ;
In class Player: public ShapeBase, under S32 mJumpDelay;, add
F32 mSwayX; F32 mSwayZ; F32 Yaw; F32 Pitch;
Open up T3D/player.cpp
In PlayerData::PlayerData(), under minImpactSpeed = 25.0f;, add
weaponSwayAmtX = 0.0005; weaponSwayAmtZ = 0.0005; weaponSwayResetX = 0.0005; weaponSwayResetZ = 0.0005;
In PlayerData::initPersistFields(), under addField("minImpactSpeed", TypeF32, Offset(minImpactSpeed, PlayerData));, add
addField("weaponSwayAmtX", TypeF32, Offset(weaponSwayAmtX, PlayerData));
addField("weaponSwayAmtZ", TypeF32, Offset(weaponSwayAmtZ, PlayerData));
addField("weaponSwayResetX", TypeF32, Offset(weaponSwayResetX, PlayerData));
addField("weaponSwayResetZ", TypeF32, Offset(weaponSwayResetZ, PlayerData));Find stream->write(minImpactSpeed);, and under it, add
stream->write(weaponSwayAmtX); stream->write(weaponSwayAmtZ); stream->write(weaponSwayResetX); stream->write(weaponSwayResetZ);
Find stream->read(&minImpactSpeed);. Under it, add
stream->read(&weaponSwayAmtX); stream->read(&weaponSwayAmtZ); stream->read(&weaponSwayResetX); stream->read(&weaponSwayResetZ);
Find mReversePending = 0;, and under it, stick in
mSwayX = 0; mSwayZ = 0;
In Player::processTick(const Move* move), find updatePos();. Under it, add
// weapon sway
F32 amtX;
F32 amtZ;
F32 resetX;
F32 resetZ;
F32 limitX;
F32 limitZ;
amtX = mDataBlock->weaponSwayAmtX;
amtZ = mDataBlock->weaponSwayAmtZ;
resetX = mDataBlock->weaponSwayResetX;
resetZ = mDataBlock->weaponSwayResetZ;
limitX = 0.02 * 0.2;
limitZ = 0.02 * 0.2;
if (Yaw > 0 && Yaw != 0 && mSwayX < limitX)
mSwayX += amtX;
if (Yaw < 0 && Yaw != 0 && mSwayX > -limitX)
mSwayX -= amtX;
// Yaw sway
if (Yaw == 0)
{
if (mSwayX < 0)
mSwayX += resetX;
if (mSwayX > 0)
mSwayX -= resetX;
}
// Now do pitch sway
if (Pitch > 0 && Pitch != 0 && mSwayZ < limitZ)
mSwayZ += amtZ;
if (Pitch < 0 && Pitch != 0 && mSwayZ > -limitZ)
mSwayZ -= amtZ;
if (Pitch == 0)
{
if (mSwayZ < 0)
mSwayZ += resetZ;
if (mSwayZ > 0)
mSwayZ -= resetZ;
}In Player::RenderMountedImage, under world.mul(nmat,offsetMat);, add
GameConnection* con = getControllingClient();
Yaw = Con::getFloatVariable("$swayYaw");
Pitch = Con::getFloatVariable("$swayPitch");
if (con->isAIControlled())
{
mSwayX = 0;
mSwayZ = 0;
}
Point3F swayDisplace;
swayDisplace.x = mSwayX;
swayDisplace.y = 0.0f;
swayDisplace.z = mSwayZ;In this same block, locate world.setPosition( world.getPosition() + displace);, and change it to
world.setPosition( world.getPosition() + displace + swayDisplace);
That's it for engine changes. Compile, good luck. You should get a lot of warnings about “truncation from 'double' to 'F32'” with Visual C++. I'm not exactly sure what causes it, I don't do a lot of T3D engine coding. Anyone care to shine some light on this?
Anyway. Scripts. Open game/scripts/client/default.bind.cs, and locate
function panDown( %val )
{
$mvPitchUpSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}Underneath it, add
function getTurnValues()
{
$gettingTurnValues = true;
$swayYaw = $mvYaw;
$swayPitch = $mvPitch;
schedule(100,0,getTurnValues);
}Now, find
function getMouseAdjustAmount(%val)
{
// based on a default camera FOV of 90'
return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
}Change it to
function getMouseAdjustAmount(%val)
{
if (!$gettingTurnValues)
getTurnValues();
// based on a default camera FOV of 90'
return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
}Now, open up art/datablocks/player.cs, go to the DefaultPlayerData datablock, and add in
// Weapon sway weaponSwayAmtX = 0.0012; weaponSwayAmtZ = 0.0012; weaponSwayResetX = 0.0010; weaponSwayResetZ = 0.0010;
Do this for your other player datablocks if you have them.
Go into your game, and give it a try! Good luck, and happy Torque'ing!
#2
04/05/2010 (2:43 pm)
ya good resorce will bookmark it with the other ones I have saved.
#3
04/05/2010 (2:44 pm)
Thank you Bryce. Very useful!
#4
04/05/2010 (3:29 pm)
So I take it that this resource won't work on multiplayer?
#5
04/05/2010 (3:31 pm)
@Tek0: I haven't tested, but it's extremely likely that something will go wrong.
#6
04/06/2010 (2:10 am)
Thanks man, I really appreciate this!
#7
Awesome resource man ... will give it a bash. :)
04/06/2010 (3:19 am)
Oooo ... pawned at the end. ;)Awesome resource man ... will give it a bash. :)
#8
EDIT2: Edited the picture

So whats happening is that when i do a 360 turn, 75% of the degrees i turn the weapon disappears or moves like five meters in front of me. I think this might be related to your 2. known issue. Anyone else experienced this?
EDIT: if shooting while the weapon is far away, it will reset back players hand, and then if you turn it will mess up again.
04/06/2010 (7:06 am)
Worked perfectly, except from ->EDIT2: Edited the picture

So whats happening is that when i do a 360 turn, 75% of the degrees i turn the weapon disappears or moves like five meters in front of me. I think this might be related to your 2. known issue. Anyone else experienced this?
EDIT: if shooting while the weapon is far away, it will reset back players hand, and then if you turn it will mess up again.
#9
04/06/2010 (2:00 pm)
@Marcus - seeing the same thing here. Only just implemented it so I haven't looked into it yet but something's definitely acting odd!
#10
then it works fine. Which makes no sense!
04/06/2010 (4:05 pm)
Update: if I add a console message to the last bit of engine code above:Con::errorf("swayDisplace.x: %f, swayDisplace.z: %f.", swayDisplace.x, swayDisplace.z);
world.setPosition(world.getPosition() + displace + swayDisplace);then it works fine. Which makes no sense!
#11
In Player::RenderMountedImage, after:
Add:
You may notice I've used mSwayX = 0.0f rather than just 0. I've added the f when initialising all floating point variables - that gets rid of the truncation from double to F32 warnings.
04/06/2010 (4:17 pm)
Looks like it was the undefined y value of swayDisplace causing the problem. Got it working now.In Player::RenderMountedImage, after:
mSwayX = 0.0f; mSwayZ = 0.0f; } Point3F swayDisplace; swayDisplace.x = mSwayX; swayDisplace.z = mSwayZ;
Add:
swayDisplace.y = 0.0f
You may notice I've used mSwayX = 0.0f rather than just 0. I've added the f when initialising all floating point variables - that gets rid of the truncation from double to F32 warnings.
#12
04/06/2010 (4:22 pm)
Thanks Eikon. Your fix worked just fine.
#13
@Bryce: Thanks for an excellent resource - the 'weapon stuck to screen' view has bugged me for years!
04/06/2010 (4:38 pm)
@Marcus: Glad to hear it.@Bryce: Thanks for an excellent resource - the 'weapon stuck to screen' view has bugged me for years!
#14
04/11/2010 (7:04 pm)
Has anyone tried this in multiplayer?
#15
05/01/2010 (6:59 pm)
-removed-
#16
08/04/2010 (9:14 pm)
I'm going to attempt this in multiplayer as soon as I get the chance, so let me see if it works or does not.
#17
08/04/2010 (9:15 pm)
It just might. The thing I'm most worried about is if one person's sway, particularly the host's, will affect everyone else's view.
#18
08/04/2010 (9:23 pm)
Alright, I'll look for that when I test it, I'll post my results here within two hours, for some reason I'm having trouble with the TorquePowered.com website...
#19
EDIT: It actually looks as if from that point on its no longer TGE compatible. :(
08/04/2010 (9:37 pm)
Bryce, I'm attempting this in TGE 1.5.2, because I have not yet gotten T3D, and I've been able to follow it through up to the point where I have to find: "In Player::RenderMountedImage, under world.mul(nmat,offsetMat);, add." I do not have a world.mul (nmat, offsetMat); in the file. Where should I add it for TGE?EDIT: It actually looks as if from that point on its no longer TGE compatible. :(
#20
Good luck :)
08/06/2010 (6:45 pm)
I originally implemented this in TGE, and used the same function that's used to push the weapon out of walls, glTranslate(x,y,z). I don't know exactly how I did it, because I lost my original TGE code in a crash, but I think it was something along the lines of this somewhere in Player::RenderMountedImage :F32 sX = Con::getFloatVariable("$swayYaw");
F32 sZ = Con::getFloatVariable("$swayPitch");
glTranslatef(sX,0,sZ);Good luck :)

Torque Owner Cyril Rousselet
Gallica Game Studio