📄 shapeimage.cc
字号:
*mat = getRenderTransform();
}
void ShapeBase::getRenderImageTransform(U32 imageSlot,StringTableEntry nodeName,MatrixF* mat)
{
getRenderImageTransform( imageSlot, getNodeIndex( imageSlot, nodeName ), mat );
}
void ShapeBase::getRenderMuzzleTransform(U32 imageSlot,MatrixF* mat)
{
// Muzzle transform in world space
MountedImage& image = mMountedImageList[imageSlot];
if (image.dataBlock)
getRenderImageTransform(imageSlot,image.dataBlock->muzzleNode,mat);
else
*mat = getRenderTransform();
}
void ShapeBase::getRetractionTransform(U32 imageSlot,MatrixF* mat)
{
// Muzzle transform in world space
MountedImage& image = mMountedImageList[imageSlot];
if (image.dataBlock) {
if (image.dataBlock->retractNode != -1)
getImageTransform(imageSlot,image.dataBlock->retractNode,mat);
else
getImageTransform(imageSlot,image.dataBlock->muzzleNode,mat);
} else {
*mat = getTransform();
}
}
void ShapeBase::getRenderRetractionTransform(U32 imageSlot,MatrixF* mat)
{
// Muzzle transform in world space
MountedImage& image = mMountedImageList[imageSlot];
if (image.dataBlock) {
if (image.dataBlock->retractNode != -1)
getRenderImageTransform(imageSlot,image.dataBlock->retractNode,mat);
else
getRenderImageTransform(imageSlot,image.dataBlock->muzzleNode,mat);
} else {
*mat = getRenderTransform();
}
}
//----------------------------------------------------------------------------
S32 ShapeBase::getNodeIndex(U32 imageSlot,StringTableEntry nodeName)
{
MountedImage& image = mMountedImageList[imageSlot];
if (image.dataBlock)
return image.dataBlock->shape->findNode(nodeName);
else
return -1;
}
// Modify muzzle if needed to aim at whatever is straight in front of eye. Let the
// caller know if we actually modified the result.
bool ShapeBase::getCorrectedAim(const MatrixF& muzzleMat, VectorF* result)
{
const F32 pullInD = 6.0;
const F32 maxAdjD = 500;
VectorF aheadVec(0, maxAdjD, 0);
MatrixF eyeMat;
Point3F eyePos;
getEyeTransform(&eyeMat);
eyeMat.getColumn(3, &eyePos);
eyeMat.mulV(aheadVec);
Point3F aheadPoint = (eyePos + aheadVec);
// Should we check if muzzle point is really close to eye? Does that happen?
Point3F muzzlePos;
muzzleMat.getColumn(3, &muzzlePos);
Point3F collidePoint;
VectorF collideVector;
disableCollision();
RayInfo rinfo;
if (getContainer()->castRay(eyePos, aheadPoint, 0xFFFFFFFF, &rinfo))
collideVector = ((collidePoint = rinfo.point) - eyePos);
else
collideVector = ((collidePoint = aheadPoint) - eyePos);
enableCollision();
// For close collision we want to NOT aim at ground since we're bending
// the ray here as it is. But we don't want to pop, so adjust continuously.
F32 lenSq = collideVector.lenSquared();
if (lenSq < (pullInD * pullInD) && lenSq > 0.04)
{
F32 len = mSqrt(lenSq);
F32 mid = pullInD; // (pullInD + len) / 2.0;
// This gives us point beyond to focus on-
collideVector *= (mid / len);
collidePoint = (eyePos + collideVector);
}
VectorF muzzleToCollide = (collidePoint - muzzlePos);
lenSq = muzzleToCollide.lenSquared();
if (lenSq > 0.04)
{
muzzleToCollide *= (1 / mSqrt(lenSq));
* result = muzzleToCollide;
return true;
}
return false;
}
//----------------------------------------------------------------------------
void ShapeBase::updateMass()
{
if (mDataBlock) {
F32 imass = 0;
for (U32 i = 0; i < MaxMountedImages; i++) {
MountedImage& image = mMountedImageList[i];
if (image.dataBlock)
imass += image.dataBlock->mass;
}
//
mMass = mDataBlock->mass + imass;
mOneOverMass = 1 / mMass;
}
}
void ShapeBase::onImageRecoil(U32,ShapeBaseImageData::StateData::RecoilState)
{
}
//----------------------------------------------------------------------------
void ShapeBase::setImage(U32 imageSlot, ShapeBaseImageData* imageData, StringHandle& skinNameHandle, bool loaded, bool ammo, bool triggerDown, bool target)
{
MountedImage& image = mMountedImageList[imageSlot];
// If we already have this datablock...
if (image.dataBlock == imageData) {
// Mark that there is not a datablock change pending.
image.nextImage = InvalidImagePtr;
// Change the skin handle if necessary.
if (image.skinNameHandle != skinNameHandle) {
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
// Serverside, note the skin handle and tell the client.
setMaskBits(ImageMaskN << imageSlot);
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
image.skinNameHandle = skinNameHandle;
}
else {
#endif
// Clientside, do the reskin.
image.skinNameHandle = skinNameHandle;
if (image.shapeInstance) {
image.shapeInstance->reSkin(skinNameHandle);
}
}
}
return;
}
// Check to see if we need to delay image changes until state change.
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
if (imageData && image.dataBlock && !image.state->allowImageChange) {
image.nextImage = imageData;
image.nextSkinNameHandle = skinNameHandle;
image.nextLoaded = loaded;
return;
}
}
// Mark that updates are happenin'.
setMaskBits(ImageMaskN << imageSlot);
// Notify script unmount since we're swapping datablocks.
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (image.dataBlock)
#else
if (image.dataBlock && !isGhost())
#endif
{
scriptCallback(imageSlot,"onUnmount");
}
// Stop anything currently going on with the image.
resetImageSlot(imageSlot);
// If we're just unselecting the current shape without swapping
// in a new one, then bail.
if (!imageData) {
return;
}
// Otherwise, init the new shape.
image.dataBlock = imageData;
image.state = &image.dataBlock->state[0];
image.skinNameHandle = skinNameHandle;
image.shapeInstance = new TSShapeInstance(image.dataBlock->shape, isClientObject());
if (isClientObject()) {
if (image.shapeInstance) {
image.shapeInstance->cloneMaterialList();
image.shapeInstance->reSkin(skinNameHandle);
}
}
image.loaded = loaded;
image.ammo = ammo;
image.triggerDown = triggerDown;
image.target = target;
// The server needs the shape loaded for muzzle mount nodes
// but it doesn't need to run any of the animations.
image.ambientThread = 0;
image.animThread = 0;
image.flashThread = 0;
image.spinThread = 0;
if (isGhost()) {
if (image.dataBlock->isAnimated) {
image.animThread = image.shapeInstance->addThread();
image.shapeInstance->setTimeScale(image.animThread,0);
}
if (image.dataBlock->hasFlash) {
image.flashThread = image.shapeInstance->addThread();
image.shapeInstance->setTimeScale(image.flashThread,0);
}
if (image.dataBlock->ambientSequence != -1) {
image.ambientThread = image.shapeInstance->addThread();
image.shapeInstance->setTimeScale(image.ambientThread,1);
image.shapeInstance->setSequence(image.ambientThread,
image.dataBlock->ambientSequence,0);
}
if (image.dataBlock->spinSequence != -1) {
image.spinThread = image.shapeInstance->addThread();
image.shapeInstance->setTimeScale(image.spinThread,1);
image.shapeInstance->setSequence(image.spinThread,
image.dataBlock->spinSequence,0);
}
}
// Set the image to its starting state.
setImageState(imageSlot, 0, true);
// Update the mass for the mount object.
updateMass();
// Notify script mount.
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
scriptCallback(imageSlot,"onMount");
}
// Done.
}
//----------------------------------------------------------------------------
void ShapeBase::resetImageSlot(U32 imageSlot)
{
// Clear out current image
MountedImage& image = mMountedImageList[imageSlot];
delete image.shapeInstance;
image.shapeInstance = 0;
if (image.animSound) {
alxStop(image.animSound);
image.animSound = 0;
}
for (S32 i = 0; i < MaxImageEmitters; i++) {
MountedImage::ImageEmitter& em = image.emitter[i];
if (bool(em.emitter)) {
em.emitter->deleteWhenEmpty();
em.emitter = 0;
}
}
image.dataBlock = 0;
image.nextImage = InvalidImagePtr;
image.skinNameHandle = StringHandle();
image.nextSkinNameHandle = StringHandle();
image.state = 0;
image.delayTime = 0;
image.ammo = false;
image.triggerDown = false;
image.loaded = false;
image.lightStart = 0;
// image.light.fLight.fType = TSLight::LightInvalid;
updateMass();
}
//----------------------------------------------------------------------------
bool ShapeBase::getImageTriggerState(U32 imageSlot)
{
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!mMountedImageList[imageSlot].dataBlock)
return false;
#else
if (isGhost() || !mMountedImageList[imageSlot].dataBlock)
return false;
#endif
return mMountedImageList[imageSlot].triggerDown;
}
void ShapeBase::setImageTriggerState(U32 imageSlot,bool trigger)
{
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if ( !mMountedImageList[imageSlot].dataBlock)
return;
#else
if (isGhost() || !mMountedImageList[imageSlot].dataBlock)
return;
#endif
MountedImage& image = mMountedImageList[imageSlot];
if (trigger) {
if (!image.triggerDown && image.dataBlock) {
image.triggerDown = true;
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
setMaskBits(ImageMaskN << imageSlot);
updateImageState(imageSlot,0);
}
}
}
else
if (image.triggerDown) {
image.triggerDown = false;
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
setMaskBits(ImageMaskN << imageSlot);
updateImageState(imageSlot,0);
}
}
}
//----------------------------------------------------------------------------
U32 ShapeBase::getImageFireState(U32 imageSlot)
{
MountedImage& image = mMountedImageList[imageSlot];
// If there is no fire state, then try state 0
if (image.dataBlock && image.dataBlock->fireState != -1)
return image.dataBlock->fireState;
return 0;
}
//----------------------------------------------------------------------------
void ShapeBase::setImageState(U32 imageSlot, U32 newState,bool force)
{
if (!mMountedImageList[imageSlot].dataBlock)
return;
MountedImage& image = mMountedImageList[imageSlot];
// The client never enters the initial fire state on its own, but it
// will continue to set that state...
if (isGhost() && !force && newState == image.dataBlock->fireState)
{
if (image.state != &image.dataBlock->state[newState])
return;
}
// Eject shell casing on every state change
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -