Ever had the need to change the rotation speed of a rotating func_train?
In my latest level, I built a fancy rotating door out of two func_train entities; one to serve as the sliding support, and one to actually rotate out of the way. I figured it should all work, because I knew that the path_corner definition in the FGD file included a "New Train rot. Speed" option.
Possibly I'm missing something, but it just didn't work. The door moved back and forth, but the rotational speed did not change (or, more to the point, the rotational direction did not change!) Eventually I hunted through the code until I found the relevant section, and it seems that the option is just not wired in.
When trying to fix this unfortunate omission, I ran into a couple of other peculiarites, the first being that the definition in the FGD file just did not seem correct. It called for yaw_speed(integer) where the prompt was clearly asking for three numeric values...
Ultimately, in the course of getting it to work, it turned out to be simpler to change the FGD entry. Sadly this means that if you wish to take this code and make use of it, you will need to recompile any existing levels which contain rotating func_trains. I say "sadly", but upon reflection it is possibly a good idea that this code not change the behaviour of any currently working levels...
So anyway, making this work is a very simple two-step process.
First, edit your FGD file. Find the path_corner entry, and replace the "yaw_speed" line with the following:
avelocity(string) : "New Train rot. Speed (y z x)" : "0 0 0"
Using "avelocity" means that no code needs to be written to get the vector value into the engine; it is handled by the initialisation code. (In fact I suspect that yaw_speed would be read, but handled as a single value rather than a vector, so the change is actually required!)
Second, open your dlls\plats.cpp file. Search for "CFuncTrain :: Next" and look through the function until you find the following:
if ( m_pevCurrentTarget && m_pevCurrentTarget->speed != 0 )
{// don't copy speed from target if it is 0 (uninitialized)
pev->speed = m_pevCurrentTarget->speed;
ALERT( at_aiconsole, "Train %s speed to %4.2f\n", STRING(pev->targetname), pev->speed );
}
Directly below that, add the following lines:
if ( m_pevCurrentTarget && m_pevCurrentTarget->avelocity != g_vecZero )
pev->avelocity = m_pevCurrentTarget->avelocity;
Be warned: While this does indeed work, I seem to have a logic problem in there somewhere (in the equality test to g_vecZero) in that it is applying the new angular velocity EVEN IF UNDEFINED, or if avelocity is set to (0,0,0). What this means is that any rotating func_trains you might have in existing levels will cease to rotate! If this is not a problem for you, then go ahead and use this code. Otherwise - well, turns out it breaks at least one of my other levels, so I'll be doing my best to fix it soon! Stay tuned! :)
or even have a no change thing coded in there?
Possibly if the field is blank in Hammer, the avelocity value is not zeroed but nulled. Possibly g_vecZero isn't what I think it is. Possibly a simple "!=" comparison between vectors (or, uh, "Vec_3D" structs) doesn't work the way I think it does; my C++ is a little rusty and I've been spoiled by too much PERL!
I'll dig a little deeper and see what I can find...