Game Development Community

Need help with stupid mount bug

by Manoel Neto · in Torque Game Engine · 12/03/2005 (1:45 pm) · 2 replies

I am being stumped by a nasty stupid bug. If you mount a player to anything else, and call...

player.setScale(%someScale);

...multiple times, you'll see the character rotates around it's Z axis, as well as changing the scale. And calling a setTransform() right after it still makes the character blink for a tick in the wrong rotation before it's corrected.

I investigated it, and it turns out this happens because the mount-relative transform is completely ignored, and you can get the same effect by doing:

player.setTransform(player.getTransform());


This causes nasty "pop" effects when we switch the player between mount points, and I'm not sure how to fix that. I'm trying to, somehow, make player::setTransform convert whatever transform comes in to a mount-relative transform and preserve whatever rotation it has, instead of increment it's own rotation in, but I had no sucess yet.

#1
12/03/2005 (2:34 pm)
Not sure if it's related, however...... I've notice that when setting scale on shapes, it doesn't scale the nodes. I've had to add a little hack in to have it scale the nodes.


img219.imageshack.us/img219/5237/screenshot010000029kg.jpg

I do randomly scaled icicles for one of my magic attacks, then do a ray cast from one end to the other, that's how i discovered that the nodes were in fact not scaled. I even wrote a functions to show me the nodes in question.
#2
12/05/2005 (4:50 am)
I had a similar problem. Nodes were not taking the mountObject scale in account, and they animations were not being updated on the server. I needed to show the game from the player's eye while it was mounted to a vehicle, and the camera was nowhere close to the correct position. It wasn't that hard to fix (I added a "getWorldScale" method to shapeBase, and it multiplies the mountObject's scale by the shape's scale, and returns the result.)

BTW, I somewhat fixed my issue. I didn't quite fix it per see, I just found a way around it.

The problem was the following:

I have a game where the player can ride horses. When the player mounts a horse, I detect where it's mounting from (left or right) and mount it to a node either at the horse's left or right, and play a "mountLeft" or "mountRight" animation.

That makes the player climb the horse nicely. When the animation is done, I switch to a "mountIdle" animation, and mount the player to another node, in the horse's center.

Right there I had faced a problem, because TGE would interpolate between the mountRight/mountLeft (which ended with the player off the bounding box center) and the mountIdle (which had the player right in the bounding box center). I added a quick fix, making Player::setActionThread not use interpolation if the animation contains "mount" on it's name.

The next problem was, all our characters had to be scaled up a bit (damn modellers and their lack of scale), the horses had to grow up too, because the interiors and statics were a bit bigger. But when I mounted a scaled up player to a scaled up horse, the player got even bigger. So I had to set it's scale back to 1 when mounting, and back to it's old scale (1.2) when unmounted. That's when things start braking up.

To mount the player I call mountObject()/setScale()/setTransform() (the setTransform is to zero the player rotation). That caused the player to mount the horse, but be at a wront rotation for a full tick (reducing the $timescale made this more obvious), before adjusting to the right rotation. The same goes for unmounting. If I remove the setScale() calls, everything works as normal.

I found out setScale adjust mObjectScale, and then calls setTransform on the object. It's much like calling setTransform(getTransform()). The player::setTransform method process this and extracts the rotation from getTransform (which returns a world-relative transform, no matter if the shape is mounted or not) and applies it to mount-relative space. I haven't thought of a way to fix that without breaking other things. Maybe implementing player::setScale() and making player::setTransform() convert incoming transforms to mount-relative space if mounted.

But what puzzled me more, was the fact the setScale() wrong transform was overriding my own setTransform call for a whole tick. After some head banging, I found the culpirt was Player::writePacket. It was sending the mangled transform ahead of everything else. For now, my way to get around that was set the client control object to something else while mounting/unmounting, since writePacket is only used for controlObjects.

That sorts the issue, for now. Maybe I should start looking at that resource that implements true hierarchic parenting to shapeBases, because the mounting system has lots of little issues that are likely to bite you if you really need to use it.