📄 shapeimage.cc
字号:
ShapeBaseImageData::StateData& nextStateData = image.dataBlock->state[newState];
if (isGhost() && nextStateData.ejectShell) {
ejectShellCasing( imageSlot );
}
// Server must animate the shape if it is a firestate...
if (newState == image.dataBlock->fireState && isServerObject())
mShapeInstance->animate();
// If going back into the same state, just reset the timer
// and invoke the script callback
if (!force && image.state == &image.dataBlock->state[newState]) {
image.delayTime = image.state->timeoutValue;
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (image.state->script)
#else
if (image.state->script && !isGhost())
#endif
scriptCallback(imageSlot,image.state->script);
// If this is a flash sequence, we need to select a new position for the
// animation if we're returning to that state...
if (image.animThread && image.state->sequence != -1 && image.state->flashSequence) {
F32 randomPos = Platform::getRandom();
image.shapeInstance->setPos(image.animThread, randomPos);
image.shapeInstance->setTimeScale(image.animThread, 0);
if (image.flashThread)
image.shapeInstance->setPos(image.flashThread, 0);
}
return;
}
F32 lastDelay = image.delayTime;
ShapeBaseImageData::StateData& lastState = *image.state;
image.state = &image.dataBlock->state[newState];
//
// Do state cleanup first...
//
ShapeBaseImageData& imageData = *image.dataBlock;
ShapeBaseImageData::StateData& stateData = *image.state;
// Stop any looping sounds or animations use in the last state.
if (image.animSound && image.animLoopingSound) {
alxStop(image.animSound);
image.animSound = 0;
}
// Mount pending images
if (image.nextImage != InvalidImagePtr && stateData.allowImageChange) {
setImage(imageSlot,image.nextImage,image.nextSkinNameHandle,image.nextLoaded);
return;
}
// Reset cyclic sequences back to the first frame to turn it off
// (the first key frame should be it's off state).
if (image.animThread && image.dataBlock->shape->sequences[image.shapeInstance->getSequence(image.animThread)].isCyclic()) {
image.shapeInstance->setPos(image.animThread,0);
image.shapeInstance->setTimeScale(image.animThread,0);
}
if (image.flashThread) {
image.shapeInstance->setPos(image.flashThread,0);
image.shapeInstance->setTimeScale(image.flashThread,0);
}
// Check for immediate transitions
S32 ns;
if ((ns = stateData.transition.loaded[image.loaded]) != -1) {
setImageState(imageSlot,ns);
return;
}
//if (!imageData.usesEnergy)
if ((ns = stateData.transition.ammo[image.ammo]) != -1) {
setImageState(imageSlot,ns);
return;
}
if ((ns = stateData.transition.target[image.target]) != -1) {
setImageState(imageSlot, ns);
return;
}
if ((ns = stateData.transition.wet[image.wet]) != -1) {
setImageState(imageSlot, ns);
return;
}
if ((ns = stateData.transition.trigger[image.triggerDown]) != -1) {
setImageState(imageSlot,ns);
return;
}
//
// Initialize the new state...
//
image.delayTime = stateData.timeoutValue;
if (stateData.loaded != ShapeBaseImageData::StateData::IgnoreLoaded)
image.loaded = stateData.loaded == ShapeBaseImageData::StateData::Loaded;
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (newState == imageData.fireState)
#else
if (!isGhost() && newState == imageData.fireState)
#endif
{
setMaskBits(ImageMaskN << imageSlot);
image.fireCount = (image.fireCount + 1) & 0x7;
}
// Apply recoil
if (stateData.recoil != ShapeBaseImageData::StateData::NoRecoil)
onImageRecoil(imageSlot,stateData.recoil);
// Play sound
if (stateData.sound && isGhost()) {
Point3F vel = getVelocity();
image.animSound = alxPlay(stateData.sound, &getRenderTransform(), &vel);
ALint value = 0;
alxGetSourcei(image.animSound, AL_LOOPING, &value);
image.animLoopingSound = (value == AL_TRUE);
}
// Play animation
if (image.animThread && stateData.sequence != -1) {
image.shapeInstance->setSequence(image.animThread,stateData.sequence,
stateData.direction ? 0 : 1);
if (stateData.flashSequence == false) {
F32 timeScale = (stateData.scaleAnimation && stateData.timeoutValue) ?
image.shapeInstance->getDuration(image.animThread) / stateData.timeoutValue :
1;
image.shapeInstance->setTimeScale(image.animThread, stateData.direction ? timeScale :
-timeScale);
} else {
F32 randomPos = Platform::getRandom();
image.shapeInstance->setPos(image.animThread, randomPos);
image.shapeInstance->setTimeScale(image.animThread, 0);
image.shapeInstance->setSequence(image.flashThread, stateData.sequenceVis, 0);
image.shapeInstance->setPos(image.flashThread, 0);
F32 timeScale = (stateData.scaleAnimation && stateData.timeoutValue) ?
image.shapeInstance->getDuration(image.animThread) / stateData.timeoutValue :
1;
image.shapeInstance->setTimeScale(image.flashThread, timeScale);
}
}
// Start particle emitter on the client
if (isGhost() && stateData.emitter)
startImageEmitter(image,stateData);
// Start spin thread
if (image.spinThread) {
switch (stateData.spin) {
case ShapeBaseImageData::StateData::IgnoreSpin:
image.shapeInstance->setTimeScale(image.spinThread, image.shapeInstance->getTimeScale(image.spinThread));
break;
case ShapeBaseImageData::StateData::NoSpin:
image.shapeInstance->setTimeScale(image.spinThread,0);
break;
case ShapeBaseImageData::StateData::SpinUp:
if (lastState.spin == ShapeBaseImageData::StateData::SpinDown)
image.delayTime *= 1.0f - (lastDelay / stateData.timeoutValue);
break;
case ShapeBaseImageData::StateData::SpinDown:
if (lastState.spin == ShapeBaseImageData::StateData::SpinUp)
image.delayTime *= 1.0f - (lastDelay / stateData.timeoutValue);
break;
case ShapeBaseImageData::StateData::FullSpin:
image.shapeInstance->setTimeScale(image.spinThread,1);
break;
}
}
// Script callback on server
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (stateData.script && stateData.script[0])
#else
if (stateData.script && stateData.script[0] && !isGhost())
#endif
scriptCallback(imageSlot,stateData.script);
// If there is a zero timeout, and a timeout transition, then
// go ahead and transition imediately.
if (!image.delayTime)
{
if ((ns = stateData.transition.timeout) != -1)
{
setImageState(imageSlot,ns);
return;
}
}
}
//----------------------------------------------------------------------------
void ShapeBase::updateImageState(U32 imageSlot,F32 dt)
{
if (!mMountedImageList[imageSlot].dataBlock)
return;
MountedImage& image = mMountedImageList[imageSlot];
ShapeBaseImageData& imageData = *image.dataBlock;
ShapeBaseImageData::StateData& stateData = *image.state;
image.delayTime -= dt;
// Energy management
if (imageData.usesEnergy) {
F32 newEnergy = getEnergyLevel() - stateData.energyDrain * dt;
if (newEnergy < 0)
newEnergy = 0;
setEnergyLevel(newEnergy);
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
bool ammo = newEnergy > imageData.minEnergy;
if (ammo != image.ammo) {
setMaskBits(ImageMaskN << imageSlot);
image.ammo = ammo;
}
}
}
// Check for transitions. On some states we must wait for the
// full timeout value before moving on.
S32 ns;
if (image.delayTime <= 0 || !stateData.waitForTimeout) {
if ((ns = stateData.transition.loaded[image.loaded]) != -1) {
setImageState(imageSlot,ns);
return;
}
if ((ns = stateData.transition.ammo[image.ammo]) != -1) {
setImageState(imageSlot,ns);
return;
}
if ((ns = stateData.transition.target[image.target]) != -1) {
setImageState(imageSlot,ns);
return;
}
if ((ns = stateData.transition.wet[image.wet]) != -1) {
setImageState(imageSlot,ns);
return;
}
if ((ns = stateData.transition.trigger[image.triggerDown]) != -1) {
setImageState(imageSlot,ns);
return;
}
if (image.delayTime <= 0 &&
(ns = stateData.transition.timeout) != -1) {
setImageState(imageSlot,ns);
return;
}
}
// Update the spinning thread timeScale
if (image.spinThread) {
float timeScale;
switch (stateData.spin) {
case ShapeBaseImageData::StateData::IgnoreSpin:
case ShapeBaseImageData::StateData::NoSpin:
case ShapeBaseImageData::StateData::FullSpin: {
timeScale = 0;
image.shapeInstance->setTimeScale(image.spinThread, image.shapeInstance->getTimeScale(image.spinThread));
break;
}
case ShapeBaseImageData::StateData::SpinUp: {
timeScale = 1.0f - image.delayTime / stateData.timeoutValue;
image.shapeInstance->setTimeScale(image.spinThread,timeScale);
break;
}
case ShapeBaseImageData::StateData::SpinDown: {
timeScale = image.delayTime / stateData.timeoutValue;
image.shapeInstance->setTimeScale(image.spinThread,timeScale);
break;
}
}
}
}
//----------------------------------------------------------------------------
void ShapeBase::updateImageAnimation(U32 imageSlot, F32 dt)
{
if (!mMountedImageList[imageSlot].dataBlock)
return;
MountedImage& image = mMountedImageList[imageSlot];
// Advance animation threads
if (image.ambientThread)
image.shapeInstance->advanceTime(dt,image.ambientThread);
if (image.animThread)
image.shapeInstance->advanceTime(dt,image.animThread);
if (image.spinThread)
image.shapeInstance->advanceTime(dt,image.spinThread);
if (image.flashThread)
image.shapeInstance->advanceTime(dt,image.flashThread);
// Update any playing sound.
if (image.animSound)
alxSourceMatrixF(image.animSound, &getRenderTransform());
// Particle emission
for (S32 i = 0; i < MaxImageEmitters; i++) {
MountedImage::ImageEmitter& em = image.emitter[i];
if (bool(em.emitter)) {
if (em.time > 0) {
em.time -= dt;
MatrixF mat;
getRenderImageTransform(imageSlot,em.node,&mat);
Point3F pos,axis;
mat.getColumn(3,&pos);
mat.getColumn(1,&axis);
em.emitter->emitParticles(pos,true,axis,getVelocity(),(U32) (dt * 1000));
}
else {
em.emitter->deleteWhenEmpty();
em.emitter = 0;
}
}
}
}
//----------------------------------------------------------------------------
void ShapeBase::startImageEmitter(MountedImage& image,ShapeBaseImageData::StateData& state)
{
MountedImage::ImageEmitter* bem = 0;
MountedImage::ImageEmitter* em = image.emitter;
MountedImage::ImageEmitter* ee = &image.emitter[MaxImageEmitters];
// If we are already emitting the same particles from the same
// node, then simply extend the time. Otherwise, find an empty
// emitter slot, or grab the one with the least amount of time left.
for (; em != ee; em++) {
if (bool(em->emitter)) {
if (state.emitter == em->emitter->getDataBlock() && state.emitterNode == em->node) {
if (state.emitterTime > em->time)
em->time = state.emitterTime;
return;
}
if (!bem || (bool(bem->emitter) && bem->time > em->time))
bem = em;
}
else
bem = em;
}
bem->time = state.emitterTime;
bem->node = state.emitterNode;
bem->emitter = new ParticleEmitter;
bem->emitter->onNewDataBlock(state.emitter);
if( !bem->emitter->registerObject() )
delete bem->emitter;
}
//----------------------------------------------------------------------------
Light* ShapeBase::getImageLight(U32 imageSlot)
{
MountedImage& image = mMountedImageList[imageSlot];
if (!image.dataBlock)
return 0;
ShapeBaseImageData& imageData = *image.dataBlock;
if (imageData.lightType == ShapeBaseImageData::NoLight)
return 0;
F32 intensity;
F32 delta = Sim::getCurrentTime() - image.lightStart;
switch (imageData.lightType) {
case ShapeBaseImageData::ConstantLight:
in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -