.qc (dot qc) - the group for quake c coders of all denominations. If you make quake one mods and write code in quake c, join our group! I'll try to answer any quake c questions - please post your inquiry in the forums...
Or how to tell where the gun aim is pointing and how to get there...
Posted by numbersix on Oct 2nd, 2011
Intermediate Server Side Coding.
What is a vector?
Dictionary.reference.com - "a quantity possessing both magnitude and direction, represented by an arrow the direction of which indicates the direction of the quantity and the length of which is proportional to the magnitude."
Game space concept: a single 3D point with an arrow heading some direction away from the point. The arrow point is the direction and the length of the arrow is the magnitude. This might seem like a simple concept, but it is not.
If you were to follow the vector from the origin point you would end up where it is pointing.
What is an angle?
Dictionary.reference.com - "c. the amount of
rotation needed to bring one line or plane into coincidence with
another, generally measured in radians or in degrees, minutes, and
Game space concept: start with a facing angle of 0 degrees, and rotate some arbitrary degrees less than 360. This is referenced as Yaw. Then from that angle look some degrees up or down (generally restricted to less than 90 degrees) - this is referenced pitch.
The game engine (since the original quake 1 engine) stores this value in an entity variable vector named ".angles". The vector that points to the gun aim (center screen where the player is looking in just about every first person shooter...) in an entity variable vector named ".v_angle"
If you were to start a darkplaces game, with only one player connected, pull down the console and enter:
prvm_edict server 1
You would see two entries among the many listed:
angles ' 30.0000 14.8700 0.0000'
v_angle ' -90.0000 14.8700 0.0000'
These are accessed in quake c with:
where self is a memory pointer to the entity in question.
Each vector is composed of 3 floating point values (as shown) that can be accessed in quake c:
When working with the angles variable, _x is the pitch (how far the player ent is looking up and down from a horizontal plane at 0 degrees pitch.) This is a rotation around the y axis. The _y is the yaw component - how far away from 0 degrees the player ent is rotated around the z axis.
It is interesting to note that when characters in Star Trek refer to a bearing angle mark some other angle with regards to piloting their ship that bearing is yaw, and the mark is pitch.
Note: there are a couple caveats about the _x representation of pitch that need to be understood.
So, what can you do with this information?
Well, if the auto-aim feature is off (and it should be, unless you are a wimpy fps player) and you fire a: rocket, nail, or lightning bolt the self.v_angle is where that shot is going. If its a hit-scan weapon like a shotgun, the v_angle vector is followed till it hits a solid object or something that takes damage.
But other things can happen as well. Brass can be ejected from guns. The origin the object is fired from can be adjusted to conform to the exact point of the gun barrel. I did this for the visible weapons upgrade starting with painkeep 2.0.
There are 3 more vectors related to any vector - you can get them with this quake c:
That gives 3 normals:
A normal is a vector of length unit 1 - v_forward points exactly where v_angle points but with length 1. v_up points up 90 degrees from v_forward. This is not directly up but is rotated with the pitch of v_forward. Likewise v_right points right, rotated 90 degrees right from v_forward.
These are used to calculated distances along each vector. With v_forward you can find out what is 200 units in front of the gun aim:
p = pointcontents(self.origin + (v_forward * 200));
pointcontents is a quake c builtin that returns one of several CONTENT_* values.
CONTENT_EMPTY = -1;
CONTENT_SOLID = -2;
CONTENT_WATER = -3;
CONTENT_SLIME = -4;
CONTENT_LAVA = -5;
CONTENT_SKY = -6;
So if empty space was 200 units along the gun aim, CONTENT_EMPTY would be assigned to p.
That explains how you get to a point along the vector of the gun aim.
Now say you want to point your player in a certain direction. You can NOT assign the vector to v_angle. You have to change self.angles.
You take a direction vector v1:
vector v1, v2;
v1 = func_providing_vector_facing()
v2 = vectoangles(v1);
self.angles_y = v2_y;
This changes the self entity facing without adjusting the pitch angle. If you wanted the pitch angle as well:
self.angles = v2;
NOTE: to actually change a player entity facing angle or pitch you need a bit more code.
If you want to go from pitch and yaw to a vector you use makevectors noted above:
You should now understand the relationship between the gun aim vector and entity facing angles.
This concept is used over and over in quake c programming.
Note: about using pitch for calculations. This is from an old code segment that used pitch:
// This corrects an ID mistake. They had the pitch angle in
dir2_x = dir2_x * -1;
If anyone wants to know how (if it does) affects quake c coding, I'll leave that for the comments section and the forum boards.
When you test it - pitch angle is from 30 (looking straight up) to -30 (looking straight down).
This would seem to support the reverse comment (adding degrees to pitch should look down and vice versa) and if you are calculating degrees from the plane at 0 degrees pitch, the max of 30 is 1/3 of the 90 degree angle.