Wednesday, January 23, 2013

The Little things...

It is not the big things that are an issue, it is the little things you can live without that are. The little things that are nice to have, seem easy to implement, but you end up making a bunch of nonsence to get it to work. This may not be with Hammer I/O, but as I learned with PUNT, it can be with code.

Last night, I finally tackled something I wanted to do with the PUNT cubes in a while, and that is to make the player be able to pick up the cubes without the Puntgun. Why? Because how I modded the physcannon code, the pickup system is not the greatest. First, there was an animation bug, and no matter how many think functions, bools and other filters I placed, the bug kept coming back. When picking something up with the Puntgun, if you were to double click to pick it up, the model would animate to pickup and drop although the cube remained held. 

Another thing is that randomly, the box would FLY across the map towards you if you tried to pick it up from a far. The pickup distance was made to a short distance to avoid this gameplay issue, but out of the blue you would try to pick it up from a far, and it would work for some odd reason. I was remaking a map that included the player punting a box from a distance. Normally, when you try to pick it up, the gun would shake and play a sound. But this time, the box flew across the gap and into my hands. Welp, you can't have that happen in puzzles like this, time to open Visual Studio....

 You may be asking yourself  "Why couldn't you pick up the cube to begin with? It is just a physics prop, right?" No, its not. It is a CBaseAnimating class with the Physics and Physcannon properties tied to it. The issue is that it's Use function was blank, and we need to tell the box that the player alone can pick this up. The only entity that you can pick up and comes to my mind is the prop_physics entity. And here I find
void CPhysicsProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBasePlayer *pPlayer = ToBasePlayer( pActivator );
if ( pPlayer )
{
if ( HasSpawnFlags( SF_PHYSPROP_ENABLE_PICKUP_OUTPUT ) )
{
m_OnPlayerUse.FireOutput( this, this );
}
pPlayer->PickupObject( this );
}
}

In this function, it is first finding/linking/defining the player. Then it says "If the player hits +use, check a spawn flag and fire an output. Then if so or not, go back to the original function, and make the player pick this up.  Ok, seems easy, I just need to define Use in my header and copy and paste this into my code.

Well, it did not work. I would have guess that Use is called like Precache, Spawn, or Think, but it needs to be called. After looking around in the Alyx file, I notice that there is a SetUse line in the spawn. So replicate that and still nothing. I've spent an hour playing with the Use function, adjusting flags and nothing. Then I noticed that before the Use commands of both the physics prop and Alyx, there was this magical function called "ObjectCaps()" and there it had FCAP_IMPULSE_USE. I'm not to sharp on binding buttons, I've tried before, but I knew what that was when I saw it. Copied and pasted from the Alyx code, and when I pressed Use on my cube, the game crashed. Now we are getting somewhere.

I simplified the ObjectCaps to a basic lines of

int caps = BaseClass::ObjectCaps();

if ( CBasePlayer::CanPickupObject( this, 45, 128 ) )
{
caps |= FCAP_IMPULSE_USE;
}

return caps;

Compiled it and at this point, I did not expect it to work, but as I picked up the box, my eyes widen as I succeeded in doing something very simple. Yeah, I'm not really a pro at this, but after a few hours, I can find myself out of a maze.

So with this being done, we can say Good bye to the physcannon pickup system. It was fun, but it was buggy. The only downside to having the player pickup the box instead of using the physcannon system is that the gun hides instead of acting like a Portalgun and doing an animation when the player picked up something. Meh, it is a small price to pay, and it helps PUNT be less Portal. Besides, it is a cartoon theme, it does not have to make sense!

Flip Flop