I found a strange behavior for the physics of kickables objects, which also affects markers.
It might explains why dynamic objects appear to be floating somewhere in the Age on the next link-in, and why some markers in a few places can't be collected.
I was not sure if it has already been found, so I thought it might be a good idea to post this here.
Recently I found something strange in my Simulation.0.elf log file:
- Code: Select all
Physical JumpBlocker loaded out of range state. Forcing initial state to server.
[others]
Physical JumpBlocker fell to -2014.5 (-2000.0 is the max). Suppressing.
Diafero wrote:Hans recently showed me a bug which I could now reproduce and narrow down: It seems that if you create a marker mission and add a marker of which the z coordinate is below -2000, it is not possible to collect that marker. When you play the mission, you can see it, but when you go through it, nothing happens. The only age I found that goes so deep is Vaiskor 2. I found a mountain there where you can easily walk across this invisible border, and indeed from a bunch of markers I placed there, all the ones below -2000 where non-collectable (-2007 did not work, -1991 worked). This happens both online and offline. Does anyone have any idea what this could be caused by? 2000 does not sound like a number overflow, and besides, markers in the outer scene of Gahreesen (which is at z value +10000) work fine.
Is there an UU version of Vaiskor 2, so one could verify if this is POTS-specific?
As this sounded quite strange to me, I looked for "is the max)" in the MOULa C++ files.
I found it in the file plPXPhysical.cpp:
- Code: Select all
void plPXPhysical::SendNewLocation(hsBool synchTransform, hsBool isSynchUpdate)
{
// we only send if:
// - the body is active or forceUpdate is on
// - the mass is non-zero
// - the physical is not passive
hsBool bodyActive = !fActor->isSleeping();
hsBool dynamic = fActor->isDynamic();
if ((bodyActive || isSynchUpdate) && dynamic)// && fInitialTransform)
{
plProfile_Inc(MaySendLocation);
if (!GetProperty(plSimulationInterface::kPassive))
{
hsMatrix44 curl2w = fCachedLocal2World;
// we're going to cache the transform before sending so we can recognize if it comes back
IGetTransformGlobal(fCachedLocal2World);
if (!CompareMatrices(curl2w, fCachedLocal2World, .0001f))
{
plProfile_Inc(LocationsSent);
plProfile_BeginLap(PhysicsUpdates, GetKeyName());
// quick peek at the translation...last time it was corrupted because we applied a non-unit quaternion
// hsAssert(real_finite(fCachedLocal2World.fMap[0][3]) &&
// real_finite(fCachedLocal2World.fMap[1][3]) &&
// real_finite(fCachedLocal2World.fMap[2][3]), "Bad transform outgoing");
if (fCachedLocal2World.GetTranslate().fZ < kMaxNegativeZPos)
{
SimLog("Physical %s fell to %.1f (%.1f is the max). Suppressing.", GetKeyName(), fCachedLocal2World.GetTranslate().fZ, kMaxNegativeZPos);
// Since this has probably been falling for a while, and thus not getting any syncs,
// make sure to save it's current pos so we'll know to reset it later
DirtySynchState(kSDLPhysical, plSynchedObject::kBCastToClients);
IEnable(false);
}
hsMatrix44 w2l;
fCachedLocal2World.GetInverse(&w2l);
plCorrectionMsg *pCorrMsg = TRACKED_NEW plCorrectionMsg(GetObjectKey(), fCachedLocal2World, w2l, synchTransform);
pCorrMsg->Send();
if (fProxyGen)
fProxyGen->SetTransform(fCachedLocal2World, w2l);
plProfile_EndLap(PhysicsUpdates, GetKeyName());
}
}
}
}
- Code: Select all
if (fCachedLocal2World.GetTranslate().fZ < kMaxNegativeZPos) // kMaxNegativeZPos has a value of -2000.0
{
SimLog("Physical %s fell to %.1f (%.1f is the max). Suppressing.", GetKeyName(), fCachedLocal2World.GetTranslate().fZ, kMaxNegativeZPos);
// Since this has probably been falling for a while, and thus not getting any syncs,
// make sure to save it's current pos so we'll know to reset it later
DirtySynchState(kSDLPhysical, plSynchedObject::kBCastToClients);
IEnable(false);
}
I don't know if it can be fixed, but if it could freeze the physics of only kickables objects it would be great.