Iron Sights
by Chris Byars · in Torque Game Engine · 07/20/2006 (6:16 pm) · 18 replies
I use an iron sight system for some of my weapons that simply changes the eyeOffSet. (Necessary for bitmap oriented scope overlays to move the weapon to the center to see flare/smoke effects, and necessary for the handgun to actually look through the sights of the handgun) Client calls commandToServer, which gets the mounted image that the player is holding, and calls the corresponding WeaponZoom method. WeaponZoom for making it centered perfectly and aligned to fire straight, WeaponUnZoom to return it to normal when you're done zooming.
And in the corresponding weapon *.cs file:
Unfortunately this type of setup does not work networked. Works for all the clients, no problem, however when a client calls their zoom, the server player's eyeOffSet gets modified as well if they're using the same weapon. How should I set something like this up to work per client rather than modify the overall ShapeBaseImageData value?
Thanks for any information.
function serverCmdWeaponZoom(%client)
{
%currentWeapon = %client.player.getMountedImage($WeaponSlot);
%currentWeapon.WeaponZoom(%client.player);
}
function serverCmdWeaponUnZoom(%client)
{
%currentWeapon = %client.player.getMountedImage($WeaponSlot);
%currentWeapon.WeaponUnZoom(%client.player);
}And in the corresponding weapon *.cs file:
function handgunImage::WeaponZoom(%this, %obj, %slot)
{
%this.eyeOffSet = "0.002 0.8 -0.019";
}
function handgunImage::WeaponUnZoom(%this, %obj, %slot)
{
%this.eyeOffSet = "0.085 0.57 -0.09";
}Unfortunately this type of setup does not work networked. Works for all the clients, no problem, however when a client calls their zoom, the server player's eyeOffSet gets modified as well if they're using the same weapon. How should I set something like this up to work per client rather than modify the overall ShapeBaseImageData value?
Thanks for any information.
#2
I feel bad so I'll give you a hint.
- Get rid of:
And replace it with a function derived from ShapeBase. This function should switch between some eyeOffset values specied in your weapon's Image DataBlock.
Good luck, sorry I couldn't be of any further help. Maybe someone else will help you if you're still stuck.
- Tim
07/21/2006 (7:48 am)
I have a solution for this but I have a 'Complete FPS Weapon Solutions Pack' nearing completion and subsequent release. My pack includes code as well as models (amongst other things) and I am a little hesitant to release code from my pack, sorry.I feel bad so I'll give you a hint.
- Get rid of:
function handgunImage::WeaponZoom(%this, %obj, %slot)
{
%this.eyeOffSet = "0.002 0.8 -0.019";
}
function handgunImage::WeaponUnZoom(%this, %obj, %slot)
{
%this.eyeOffSet = "0.085 0.57 -0.09";
}And replace it with a function derived from ShapeBase. This function should switch between some eyeOffset values specied in your weapon's Image DataBlock.
Good luck, sorry I couldn't be of any further help. Maybe someone else will help you if you're still stuck.
- Tim
#3
So your function would require the eyeOffSet values already stated in the datablock ShapeBaseImageData(handgunImage), and it would switch between them depending on what the client calls. How would this be any different than me changing the image's eyeOffSet. Would still affect the server player, no?
07/24/2006 (3:32 pm)
Alright, I can't seem to figure this one out. (Things like this really throw me.) I can't conceptualize how it would work. :/Quote:And replace it with a function derived from ShapeBase. This function should switch between some eyeOffset values specied in your weapon's Image DataBlock.
So your function would require the eyeOffSet values already stated in the datablock ShapeBaseImageData(handgunImage), and it would switch between them depending on what the client calls. How would this be any different than me changing the image's eyeOffSet. Would still affect the server player, no?
#4
07/24/2006 (5:27 pm)
Tim is being silly, just listen to what Stefan said. You need to move the variable to be defined in the object instead of the datablock, so you can change it dynamically.
#5
07/24/2006 (6:15 pm)
Is there a way to do this in script, like Tim's undisclosed method? I'm rather incompetant in the source. :)
#6
Though really I think eyeOffset is a retarded half hack and you should not use it at all and have your animations match up so it looks like it supposed to in first person. That's what all the modern games are starting to do now anyways.
07/24/2006 (9:05 pm)
No. Tim is talking about adding a function in source I think, he's just confusing terms by saying Datablock. It's not very hard at all to move a value from datablock to object and be able to update. You really should learn at least that much by now.Though really I think eyeOffset is a retarded half hack and you should not use it at all and have your animations match up so it looks like it supposed to in first person. That's what all the modern games are starting to do now anyways.
#7
I do know enough to do this in the source (negate my last post), I'm just inquiring for other options/insight.
07/24/2006 (9:11 pm)
You do it your way, I do it my way; it gets the job done in the way I like it. I very much prefer the eyeOffSet LOD way I manage first and third person in TGE/TSE. First and third (including the player) can be syncronized perfectly, while having more control over the weapon handling in first person.I do know enough to do this in the source (negate my last post), I'm just inquiring for other options/insight.
#8
07/24/2006 (11:28 pm)
I'm not being silly and I haven't made any changes to source to get this working and I'm not confusing terms ;)
#9
07/25/2006 (12:04 am)
How can you possibly change a value that is read in source from the datablock from script? Unless you have some crazy hack involving swapping the mounted ShapeImage, I can't think of any way.
#10
Start on the client.
Add in your keybinding:
Function to server.
Last thing for the client, a couple of functions to handle adjusting and returning offset when instructed by the server.
Now to the server.
Finally, add some new values to each weapon script that is to have an adjustable eyeOffset.
This goes in the ShapeBaseImageData section.
Voila, adjustable eyeOffsets across a network!
[edit]Tidied up some code[/edit]
07/25/2006 (12:26 am)
Ok C2 (and Paul), here's a crude way of achieving what you need. It's not a crazy hack (maybe a little) and it will work across a network. Not the most elegant way of doing things but far from the worse. Buy my weapon pack (when released) if you want professional code : PStart on the client.
Add in your keybinding:
moveMap.bind(mouse0, "button2", toggleEyeOffset);
Function to server.
function toggleEyeOffset( %val )
{
if ( %val == 1 )
commandToServer( 'AdjustEyeOffset' );
else if ( %val == 0 )
commandToServer( 'ReturnEyeOffset' );
}Last thing for the client, a couple of functions to handle adjusting and returning offset when instructed by the server.
function clientCmdAdjustEyeOffset(%client,%curWeapon,%offset)
{
%curWeapon.eyeOffset = %offset;
echo("-->Adjusting EyeOffset to " @ %offset);
}
function clientCmdReturnEyeOffset(%client,%curWeapon,%offset)
{
%curWeapon.eyeOffset = %offset;
echo("-->Returning EyeOffset to " @ %offset);
}Now to the server.
function serverCmdAdjustEyeOffset(%client,%val)
{
%curWeapon = %client.player.getMountedImage($WeaponSlot);
%offset = %curWeapon.adjustedEyeOffset;
%canAdjustEyeOffset = %curWeapon.adjustEyeOffset;
if(%canAdjustEyeOffset)
{
commandToClient(%client,'AdjustEyeOffset',%client,%curWeapon,%offset);
%weaponName = %curWeapon.item.getName();
echo("-->Current Weapon is " @ %weaponName);
}
else if(!%canAdjustEyeOffset)
{
echo("-->Weapon does not have adjustable eyeOffset");
return;
}
}
function serverCmdReturnEyeOffset(%client,%val)
{
%curWeapon = %client.player.getMountedImage($WeaponSlot);
%offset = %curWeapon.normalEyeOffset;
%canAdjustEyeOffset = %curWeapon.adjustEyeOffset;
if(%canAdjustEyeOffset)
{
commandToClient(%client,'ReturnEyeOffset',%client,%curWeapon,%offset);
}
else if(!%canAdjustEyeOffset)
{
return;
}
}Finally, add some new values to each weapon script that is to have an adjustable eyeOffset.
This goes in the ShapeBaseImageData section.
datablock ShapeBaseImageData(desertEagleImage)
{
// Basic Item properties
shapeFile = "~/data/shapes/weapon/desertEagle/weapon.dts";
emap = true;
// Specify mount point & offset for 3rd person, and eye offset
// for first person rendering.
mountPoint = 0;
eyeOffset = "0.01 0.25 -0.42"; //(xyz)
// Added for adjustable eyeOffset
adjustEyeOffset = true;
normalEyeOffset = "0.01 0.25 -0.42"; //This should always match eyeOffset
//value listed above
adjustedEyeOffset = "-0.0840 0.175 -0.355"; //This is the eyeOffet value we
//switch to on zoom
// Added for adjustable eyeOffsetVoila, adjustable eyeOffsets across a network!
[edit]Tidied up some code[/edit]
#11
07/25/2006 (1:06 am)
Since the eyeOffset isn't used in the muzzlePoint/Vector calcs (or anywhere by server code I think) I guess you can get away with that. It's still a bad idea, coz' for _most_ values that won't at all. Though actually I'm a little surprised it's working, since I'd have thought the ghosted datablock would have a different ID on a client. Or are datablocks not ghosted, but replicated I guess? Have to ask Stephen about that tommorow.
#12
That has nothing to do with it. Look at weapon.cs and inventory.cs to see my point. If that were the case, it would be impossible to cycle weapons etc.
Edit: Actually a better example is the ammo class!
07/25/2006 (1:18 am)
It's not pretty but it works flawlessly. Single player, network, dedicated server you name it, it works.Quote:
Though actually I'm a little surprised it's working, since I'd have thought the ghosted datablock would have a different ID on a client.
That has nothing to do with it. Look at weapon.cs and inventory.cs to see my point. If that were the case, it would be impossible to cycle weapons etc.
Edit: Actually a better example is the ammo class!
#13
07/25/2006 (1:44 am)
I don't see what those have to do with anything, they all use server data with generic or named client commands. You're sending an ID not a named reference, but I did a quick test and it seems like it's because the datablocks have the same ID between client and server. That's not the case with objects so I wasn't sure if datablocks were different.
#14
Myself, I'd rather keep stuff clean and optimized in source as long as it's easy enough to implement, which this one was.
07/25/2006 (2:03 am)
If Tim's solution works, then it's all good and very cool.Myself, I'd rather keep stuff clean and optimized in source as long as it's easy enough to implement, which this one was.
#15
Now people have an option, learn how to program in C or use my scripted method :)
07/25/2006 (7:44 am)
It works and I agree with what you said Stefan, however I'm not prepared to give away my code for reasons stated earlier. Doesn't look like anyone else is either so I don't feel so bad now.Now people have an option, learn how to program in C or use my scripted method :)
#16
07/29/2006 (7:39 am)
Tim whats the ETA of your pack,any pic tasters?
#17
07/31/2006 (3:17 pm)
Just in case anyone else is confused on this point, datablocks _are_ handled differently from other game objects. They have the first set (1000?) IDs allocated, and they are same on all clients. Just ran across this factoid myself a little while ago and had to have Ben Garney clear it up for me.
#18
The Datablock is a "common stuff" for an object, created with this datablock.
Let's take into example the Player (assuming the stock SDK):
in file ~/server/scripts/player.cs we can see the description of datablock:
Then, in ~/server/scripts/game.cs
function GameConnection::createPlayer(%this, %spawnPoint)
we create a player itself:
But when you change something in DATABLOCK - all players derivered from this datablock are affected.
When the client joins the game, it first, loads all datablocks about evrything that server knows about. Then, almost before "jumping in" the server starts sending the "items/object" with their own attributes.
Hope this is understandable, as I had a heavy working day today, fixed lots of bugs (YES!) and now it's more then 2am already and I feel too tired (plus, english is not my first language).
Good luck! :)
07/31/2006 (3:28 pm)
Actualy, it have nothing related with ID's.The Datablock is a "common stuff" for an object, created with this datablock.
Let's take into example the Player (assuming the stock SDK):
in file ~/server/scripts/player.cs we can see the description of datablock:
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/player/player.dts";
[i]........ skipping...[/i]
runForce = 48 * 90;
runEnergyDrain = 0;
minRunEnergy = 0;
maxForwardSpeed = 14;
maxBackwardSpeed = 13;
maxSideSpeed = 13;
[i]........ skipping...[/i]
};here we see, that our "PlayerBody" datablock contains basic information - the DTS (shapeFile) of an object, the max speed, etc.Then, in ~/server/scripts/game.cs
function GameConnection::createPlayer(%this, %spawnPoint)
we create a player itself:
[i]........ skipping...[/i]
%player = new Player() {
dataBlock = PlayerBody;
client = %this;
};
[i]........ skipping...[/i]Now, with %player we have AN OBJECT, that created from DATABLOCK. On object you can set transform, scale it, etc. And if you scale PLAYER, the only single player is affected.But when you change something in DATABLOCK - all players derivered from this datablock are affected.
When the client joins the game, it first, loads all datablocks about evrything that server knows about. Then, almost before "jumping in" the server starts sending the "items/object" with their own attributes.
Hope this is understandable, as I had a heavy working day today, fixed lots of bugs (YES!) and now it's more then 2am already and I feel too tired (plus, english is not my first language).
Good luck! :)
Torque Owner Stefan Lundmark