📄 shapebase.cc
字号:
Thread& st = mScriptThread[i];
if (st.sequence != -1) {
// TG: Need to see about supressing non-cyclic sounds
// if the sequences were actived before the object was
// ghosted.
// TG: Cyclic animations need to have a random pos if
// they were started before the object was ghosted.
// If there was something running on the old shape, the thread
// needs to be reset. Otherwise we assume that it's been
// initialized either by the constructor or from the server.
bool reset = st.thread != 0;
st.thread = 0;
setThreadSequence(i,st.sequence,reset);
}
}
// get rid of current shadow...we'll generate new one when needed
delete mShadow;
mShadow = NULL;
if (mDataBlock->damageSequence != -1) {
mDamageThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mDamageThread,
mDataBlock->damageSequence,0);
}
if (mDataBlock->hulkSequence != -1) {
mHulkThread = mShapeInstance->addThread();
mShapeInstance->setSequence(mHulkThread,
mDataBlock->hulkSequence,0);
}
}
if (isGhost() && mSkinNameHandle.isValidString() && mShapeInstance) {
mShapeInstance->reSkin(mSkinNameHandle);
mSkinHash = _StringTable::hashString(mSkinNameHandle.getString());
}
//Skin modifier
if (isGhost() && mShapeInstance)
{
mShapeInstance->updateModifiers();
}
//
mEnergy = 0;
mDamage = 0;
mDamageState = Enabled;
mRepairReserve = 0;
updateMass();
updateDamageLevel();
updateDamageState();
mDrag = mDataBlock->drag;
mCameraFov = mDataBlock->cameraDefaultFov;
return true;
}
void ShapeBase::onDeleteNotify(SimObject* obj)
{
if (obj == getProcessAfter())
clearProcessAfter();
Parent::onDeleteNotify(obj);
if (obj == mMount.object)
unmount();
}
void ShapeBase::onImpact(SceneObject* obj, VectorF vec)
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
char buff1[256];
char buff2[32];
dSprintf(buff1,sizeof(buff1),"%g %g %g",vec.x, vec.y, vec.z);
dSprintf(buff2,sizeof(buff2),"%g",vec.len());
Con::executef(mDataBlock,5,"onImpact",scriptThis(), obj->getIdString(), buff1, buff2);
}
}
void ShapeBase::onImpact(VectorF vec)
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
char buff1[256];
char buff2[32];
dSprintf(buff1,sizeof(buff1),"%g %g %g",vec.x, vec.y, vec.z);
dSprintf(buff2,sizeof(buff2),"%g",vec.len());
Con::executef(mDataBlock,5,"onImpact",scriptThis(), "0", buff1, buff2);
}
}
//----------------------------------------------------------------------------
void ShapeBase::processTick(const Move* move)
{
#ifdef TGE_RPG /// TGE_Move
/// 相机管理
//if(move)
//{
// m_rotCamera.x += move->pitch;
// m_rotCamera.x = mClampF(m_rotCamera.x ,ms_fCameraMinPitch*M_PI_DIV180,ms_fCameraMaxPitch*M_PI_DIV180);
// m_rotCamera.z += move->yaw;
// m_rotCamera.z = mFmod(m_rotCamera.z, M_2PI_F);
// m_fCameraDist += move->z;
// m_fCameraDist = mClampF(move->z, mDataBlock->cameraMinDist, mDataBlock->cameraMaxDist);
//}
#endif
// Energy management
if (mDamageState == Enabled && mDataBlock->inheritEnergyFromMount == false) {
F32 store = mEnergy;
mEnergy += mRechargeRate;
if (mEnergy > mDataBlock->maxEnergy)
mEnergy = mDataBlock->maxEnergy;
else
if (mEnergy < 0)
mEnergy = 0;
// Virtual setEnergyLevel is used here by some derived classes to
// decide whether they really want to set the energy mask bit.
if (mEnergy != store)
setEnergyLevel(mEnergy);
}
// Repair management
if (mDataBlock->isInvincible == false)
{
F32 store = mDamage;
mDamage -= mRepairRate;
mDamage = mClampF(mDamage, 0.f, mDataBlock->maxDamage);
if (mRepairReserve > mDamage)
mRepairReserve = mDamage;
if (mRepairReserve > 0.0)
{
F32 rate = getMin(mDataBlock->repairRate, mRepairReserve);
mDamage -= rate;
mRepairReserve -= rate;
}
if (store != mDamage)
{
updateDamageLevel();
if (isServerObject()) {
char delta[100];
dSprintf(delta,sizeof(delta),"%g",mDamage - store);
setMaskBits(DamageMask);
Con::executef(mDataBlock,3,"onDamage",scriptThis(),delta);
}
}
}
if (isServerObject()) {
// Server only...
advanceThreads(TickSec);
updateServerAudio();
// update wet state
setImageWetState(0, mWaterCoverage > 0.4); // more than 40 percent covered
if(mFading)
{
F32 dt = TickMs / 1000.0;
F32 newFadeET = mFadeElapsedTime + dt;
if(mFadeElapsedTime < mFadeDelay && newFadeET >= mFadeDelay)
setMaskBits(CloakMask);
mFadeElapsedTime = newFadeET;
if(mFadeElapsedTime > mFadeTime + mFadeDelay)
{
mFadeVal = F32(!mFadeOut);
mFading = false;
}
}
}
// Advance images
for (int i = 0; i < MaxMountedImages; i++)
{
if (mMountedImageList[i].dataBlock != NULL)
updateImageState(i, TickSec);
}
// Call script on trigger state changes
if (move && mDataBlock && isServerObject()) {
for (S32 i = 0; i < MaxTriggerKeys; i++) {
if (move->trigger[i] != mTrigger[i]) {
mTrigger[i] = move->trigger[i];
char buf1[20],buf2[20];
dSprintf(buf1,sizeof(buf1),"%d",i);
dSprintf(buf2,sizeof(buf2),"%d",(move->trigger[i]?1:0));
Con::executef(mDataBlock,4,"onTrigger",scriptThis(),buf1,buf2);
}
}
}
// Update the damage flash and the whiteout
//
if (mDamageFlash > 0.0)
{
mDamageFlash -= sDamageFlashDec;
if (mDamageFlash <= 0.0)
mDamageFlash = 0.0;
}
if (mWhiteOut > 0.0)
{
mWhiteOut -= sWhiteoutDec;
if (mWhiteOut <= 0.0)
mWhiteOut = 0.0;
}
}
void ShapeBase::advanceTime(F32 dt)
{
// On the client, the shape threads and images are
// advanced at framerate.
advanceThreads(dt);
updateAudioPos();
for (int i = 0; i < MaxMountedImages; i++)
if (mMountedImageList[i].dataBlock)
updateImageAnimation(i,dt);
// Cloaking takes 0.5 seconds
if (mCloaked && mCloakLevel != 1.0) {
mCloakLevel += dt * 2;
if (mCloakLevel >= 1.0)
mCloakLevel = 1.0;
} else if (!mCloaked && mCloakLevel != 0.0) {
mCloakLevel -= dt * 2;
if (mCloakLevel <= 0.0)
mCloakLevel = 0.0;
}
if(mInvincibleOn)
updateInvincibleEffect(dt);
if(mFading)
{
mFadeElapsedTime += dt;
if(mFadeElapsedTime > mFadeTime)
{
mFadeVal = F32(!mFadeOut);
mFading = false;
}
else
{
mFadeVal = mFadeElapsedTime / mFadeTime;
if(mFadeOut)
mFadeVal = 1 - mFadeVal;
}
}
}
//----------------------------------------------------------------------------
//void ShapeBase::setControllingClient(GameConnection* client)
//{
// mControllingClient = client;
//
// // piggybacks on the cloak update
// setMaskBits(CloakMask);
//}
void ShapeBase::setControllingObject(ShapeBase* obj)
{
if (obj) {
setProcessTick(false);
// Even though we don't processTick, we still need to
// process after the controller in case anyone is mounted
// on this object.
processAfter(obj);
}
else {
setProcessTick(true);
clearProcessAfter();
// Catch the case of the controlling object actually
// mounted on this object.
if (mControllingObject->mMount.object == this)
mControllingObject->processAfter(this);
}
mControllingObject = obj;
}
ShapeBase* ShapeBase::getControlObject()
{
return 0;
}
void ShapeBase::setControlObject(ShapeBase*)
{
}
bool ShapeBase::isFirstPerson()
{
// Always first person as far as the server is concerned.
if (!isGhost())
return true;
if (GameConnection* con = getControllingClient())
return con->getControlObject() == this && con->isFirstPerson();
return false;
}
// Camera: (in degrees) ------------------------------------------------------
F32 ShapeBase::getCameraFov()
{
return(mCameraFov);
}
F32 ShapeBase::getDefaultCameraFov()
{
return(mDataBlock->cameraDefaultFov);
}
bool ShapeBase::isValidCameraFov(F32 fov)
{
return((fov >= mDataBlock->cameraMinFov) && (fov <= mDataBlock->cameraMaxFov));
}
void ShapeBase::setCameraFov(F32 fov)
{
mCameraFov = mClampF(fov, mDataBlock->cameraMinFov, mDataBlock->cameraMaxFov);
}
//----------------------------------------------------------------------------
static void scopeCallback(SceneObject* obj, void *conPtr)
{
NetConnection * ptr = reinterpret_cast<NetConnection*>(conPtr);
if (obj->isScopeable())
ptr->objectInScope(obj);
}
void ShapeBase::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery * query)
{
// update the camera query
query->camera = this;
// bool grabEye = true;
if(GameConnection * con = dynamic_cast<GameConnection*>(cr))
{
// get the fov from the connection (in deg)
F32 fov;
if (con->getControlCameraFov(&fov))
{
query->fov = mDegToRad(fov/2);
query->sinFov = mSin(query->fov);
query->cosFov = mCos(query->fov);
}
}
// failed to query the camera info?
// if(grabEye) LH - always use eye as good enough, avoid camera animate
{
MatrixF eyeTransform;
getEyeTransform(&eyeTransform);
eyeTransform.getColumn(3, &query->pos);
eyeTransform.getColumn(1, &query->orientation);
}
// grab the visible distance from the sky
Sky * sky = gServerSceneGraph->getCurrentSky();
if(sky)
query->visibleDistance = sky->getVisibleDistance();
else
query->visibleDistance = 1000.f;
// First, we are certainly in scope, and whatever we're riding is too...
cr->objectInScope(this);
if (isMounted())
cr->objectInScope(mMount.object);
if (mSceneManager == NULL)
{
// Scope everything...
gServerContainer.findObjects(0xFFFFFFFF,scopeCallback,cr);
return;
}
// update the scenemanager
mSceneManager->scopeScene(query->pos, query->visibleDistance, cr);
// let the (game)connection do some scoping of its own (commandermap...)
cr->doneScopingScene();
}
//----------------------------------------------------------------------------
F32 ShapeBase::getEnergyLevel()
{
if (mDataBlock->inheritEnergyFromMount == false)
return mEnergy;
else if (isMounted()) {
return getObjectMount()->getEnergyLevel();
} else {
return 0.0f;
}
}
F32 ShapeBase::getEnergyValue()
{
if (mDataBlock->inheritEnergyFromMount == false) {
F32 maxEnergy = mDataBlock->maxEnergy;
if ( maxEnergy > 0.f )
return (mEnergy / mDataBlock->maxEnergy);
} else if (isMounted()) {
F32 maxEnergy = getObjectMount()->mDataBlock->maxEnergy;
if ( maxEnergy > 0.f )
return (getObjectMount()->getEnergyLevel() / maxEnergy);
}
return 0.0f;
}
void ShapeBase::setEnergyLevel(F32 energy)
{
if (mDataBlock->inheritEnergyFromMount == false) {
if (mDamageState == Enabled) {
mEnergy = (energy > mDataBlock->maxEnergy)?
mDataBlock->maxEnergy: (energy < 0)? 0: energy;
}
} else {
// Pass the set onto whatever we're mounted to...
if (isMounted())
getObjectMount()->setEnergyLevel(energy);
}
}
void ShapeBase::setDamageLevel(F32 damage)
{
if (!mDataBlock->isInvincible) {
F32 store = mDamage;
mDamage = mClampF(damage, 0.f, mDataBlock->maxDamage);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -