📄 shapebase.cc
字号:
if (store != mDamage) {
updateDamageLevel();
if (isServerObject()) {
setMaskBits(DamageMask);
char delta[100];
dSprintf(delta,sizeof(delta),"%g",mDamage - store);
Con::executef(mDataBlock,3,"onDamage",scriptThis(),delta);
}
}
}
}
//----------------------------------------------------------------------------
static F32 sWaterDensity = 1;
static F32 sWaterViscosity = 15;
static F32 sWaterCoverage = 0;
static U32 sWaterType = 0;
static F32 sWaterHeight = 0.0f;
static void waterFind(SceneObject* obj, void* key)
{
ShapeBase* shape = reinterpret_cast<ShapeBase*>(key);
WaterBlock* wb = dynamic_cast<WaterBlock*>(obj);
AssertFatal(wb != NULL, "Error, not a water block!");
if (wb == NULL)
{
sWaterCoverage = 0;
return;
}
if (wb->isPointSubmergedSimple(shape->getPosition()))
{
const Box3F& wbox = obj->getWorldBox();
const Box3F& sbox = shape->getWorldBox();
sWaterType = wb->getLiquidType();
if (wbox.max.z < sbox.max.z)
sWaterCoverage = (wbox.max.z - sbox.min.z) / (sbox.max.z - sbox.min.z);
else
sWaterCoverage = 1;
sWaterViscosity = wb->getViscosity();
sWaterDensity = wb->getDensity();
sWaterHeight = wb->getSurfaceHeight();
}
}
void physicalZoneFind(SceneObject* obj, void *key)
{
ShapeBase* shape = reinterpret_cast<ShapeBase*>(key);
PhysicalZone* pz = dynamic_cast<PhysicalZone*>(obj);
AssertFatal(pz != NULL, "Error, not a physical zone!");
if (pz == NULL || pz->testObject(shape) == false) {
return;
}
if (pz->isActive()) {
shape->mGravityMod *= pz->getGravityMod();
shape->mAppliedForce += pz->getForce();
}
}
void findRouter(SceneObject* obj, void *key)
{
if (obj->getTypeMask() & WaterObjectType)
waterFind(obj, key);
else if (obj->getTypeMask() & PhysicalZoneObjectType)
physicalZoneFind(obj, key);
else {
AssertFatal(false, "Error, must be either water or physical zone here!");
}
}
void ShapeBase::updateContainer()
{
// Update container drag and buoyancy properties
mDrag = mDataBlock->drag;
mBuoyancy = 0;
sWaterCoverage = 0;
mGravityMod = 1.0;
mAppliedForce.set(0, 0, 0);
mContainer->findObjects(getWorldBox(), WaterObjectType|PhysicalZoneObjectType,findRouter,this);
sWaterCoverage = mClampF(sWaterCoverage,0,1);
mWaterCoverage = sWaterCoverage;
mLiquidType = sWaterType;
mLiquidHeight = sWaterHeight;
if (mWaterCoverage >= 0.1f) {
mDrag = mDataBlock->drag * sWaterViscosity * sWaterCoverage;
mBuoyancy = (sWaterDensity / mDataBlock->density) * sWaterCoverage;
}
}
//----------------------------------------------------------------------------
void ShapeBase::applyRepair(F32 amount)
{
// Repair increases the repair reserve
if (amount > 0 && ((mRepairReserve += amount) > mDamage))
mRepairReserve = mDamage;
}
void ShapeBase::applyDamage(F32 amount)
{
if (amount > 0)
setDamageLevel(mDamage + amount);
}
F32 ShapeBase::getDamageValue()
{
// Return a 0-1 damage value.
return mDamage / mDataBlock->maxDamage;
}
void ShapeBase::updateDamageLevel()
{
if (mDamageThread) {
// mDamage is already 0-1 on the client
if (mDamage >= mDataBlock->destroyedLevel) {
if (getDamageState() == Destroyed)
mShapeInstance->setPos(mDamageThread, 0);
else
mShapeInstance->setPos(mDamageThread, 1);
} else {
mShapeInstance->setPos(mDamageThread, mDamage / mDataBlock->destroyedLevel);
}
}
}
//----------------------------------------------------------------------------
void ShapeBase::setDamageState(DamageState state)
{
if (mDamageState == state)
return;
const char* script = 0;
const char* lastState = 0;
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
if (state != getDamageState())
setMaskBits(DamageMask);
lastState = getDamageStateName();
switch (state) {
case Destroyed: {
if (mDamageState == Enabled)
setDamageState(Disabled);
script = "onDestroyed";
break;
}
case Disabled:
if (mDamageState == Enabled)
script = "onDisabled";
break;
case Enabled:
script = "onEnabled";
break;
}
}
mDamageState = state;
if (mDamageState != Enabled) {
mRepairReserve = 0;
mEnergy = 0;
}
if (script) {
// Like to call the scripts after the state has been intialize.
// This should only end up being called on the server.
Con::executef(mDataBlock,3,script,scriptThis(),lastState);
}
updateDamageState();
updateDamageLevel();
}
bool ShapeBase::setDamageState(const char* state)
{
for (S32 i = 0; i < NumDamageStates; i++)
if (!dStricmp(state,sDamageStateName[i])) {
setDamageState(DamageState(i));
return true;
}
return false;
}
const char* ShapeBase::getDamageStateName()
{
return sDamageStateName[mDamageState];
}
void ShapeBase::updateDamageState()
{
if (mHulkThread) {
F32 pos = (mDamageState == Destroyed)? 1: 0;
if (mShapeInstance->getPos(mHulkThread) != pos) {
mShapeInstance->setPos(mHulkThread,pos);
if (isClientObject())
mShapeInstance->animate();
}
}
}
//----------------------------------------------------------------------------
void ShapeBase::blowUp()
{
Point3F center;
mObjBox.getCenter(¢er);
center += getPosition();
MatrixF trans = getTransform();
trans.setPosition( center );
// explode
Explosion* pExplosion = NULL;
if( pointInWater( (Point3F &)center ) && mDataBlock->underwaterExplosion )
{
pExplosion = new Explosion;
pExplosion->onNewDataBlock(mDataBlock->underwaterExplosion);
}
else
{
if (mDataBlock->explosion)
{
pExplosion = new Explosion;
pExplosion->onNewDataBlock(mDataBlock->explosion);
}
}
if( pExplosion )
{
pExplosion->setTransform(trans);
pExplosion->setInitialState(center, damageDir);
if (pExplosion->registerObject() == false)
{
Con::errorf(ConsoleLogEntry::General, "ShapeBase(%s)::explode: couldn't register explosion",
mDataBlock->getName() );
delete pExplosion;
pExplosion = NULL;
}
}
TSShapeInstance *debShape = NULL;
if( mDataBlock->debrisShape.isNull() )
{
return;
}
else
{
debShape = new TSShapeInstance( mDataBlock->debrisShape, true);
}
Vector< TSPartInstance * > partList;
TSPartInstance::breakShape( debShape, 0, partList, NULL, NULL, 0 );
if( !mDataBlock->debris )
{
mDataBlock->debris = new DebrisData;
}
// cycle through partlist and create debris pieces
for( U32 i=0; i<partList.size(); i++ )
{
//Point3F axis( 0.0, 0.0, 1.0 );
Point3F randomDir = MathUtils::randomDir( damageDir, 0, 50 );
Debris *debris = new Debris;
debris->setPartInstance( partList[i] );
debris->init( center, randomDir );
debris->onNewDataBlock( mDataBlock->debris );
debris->setTransform( trans );
if( !debris->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register debris for class: %s", mDataBlock->getName() );
delete debris;
debris = NULL;
}
else
{
debShape->incDebrisRefCount();
}
}
damageDir.set(0, 0, 1);
}
//----------------------------------------------------------------------------
void ShapeBase::mountObject(ShapeBase* obj,U32 node)
{
// if (obj->mMount.object == this)
// return;
if (obj->mMount.object)
obj->unmount();
// Since the object is mounting to us, nothing should be colliding with it for a while
obj->mConvexList->nukeList();
obj->mMount.object = this;
obj->mMount.node = (node >= 0 && node < ShapeBaseData::NumMountPoints)? node: 0;
obj->mMount.link = mMount.list;
mMount.list = obj;
if (obj != getControllingObject())
obj->processAfter(this);
obj->deleteNotify(this);
obj->setMaskBits(MountedMask);
obj->onMount(this,node);
}
void ShapeBase::unmountObject(ShapeBase* obj)
{
if (obj->mMount.object == this) {
// Find and unlink the object
for(ShapeBase **ptr = & mMount.list; (*ptr); ptr = &((*ptr)->mMount.link) )
{
if(*ptr == obj)
{
*ptr = obj->mMount.link;
break;
}
}
if (obj != getControllingObject())
obj->clearProcessAfter();
obj->clearNotify(this);
obj->mMount.object = 0;
obj->mMount.link = 0;
obj->setMaskBits(MountedMask);
obj->onUnmount(this,obj->mMount.node);
}
}
void ShapeBase::unmount()
{
if (mMount.object)
mMount.object->unmountObject(this);
}
void ShapeBase::onMount(ShapeBase* obj,S32 node)
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
char buff1[32];
dSprintf(buff1,sizeof(buff1),"%d",node);
Con::executef(mDataBlock,4,"onMount",scriptThis(),obj->scriptThis(),buff1);
}
}
void ShapeBase::onUnmount(ShapeBase* obj,S32 node)
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
#endif
{
char buff1[32];
dSprintf(buff1,sizeof(buff1),"%d",node);
Con::executef(mDataBlock,4,"onUnmount",scriptThis(),obj->scriptThis(),buff1);
}
}
S32 ShapeBase::getMountedObjectCount()
{
S32 count = 0;
for (ShapeBase* itr = mMount.list; itr; itr = itr->mMount.link)
count++;
return count;
}
ShapeBase* ShapeBase::getMountedObject(S32 idx)
{
if (idx >= 0) {
S32 count = 0;
for (ShapeBase* itr = mMount.list; itr; itr = itr->mMount.link)
if (count++ == idx)
return itr;
}
return 0;
}
S32 ShapeBase::getMountedObjectNode(S32 idx)
{
if (idx >= 0) {
S32 count = 0;
for (ShapeBase* itr = mMount.list; itr; itr = itr->mMount.link)
if (count++ == idx)
return itr->mMount.node;
}
return -1;
}
ShapeBase* ShapeBase::getMountNodeObject(S32 node)
{
for (ShapeBase* itr = mMount.list; itr; itr = itr->mMount.link)
if (itr->mMount.node == node)
return itr;
return 0;
}
Point3F ShapeBase::getAIRepairPoint()
{
if (mDataBlock->mountPointNode[ShapeBaseData::AIRepairNode] < 0)
return Point3F(0, 0, 0);
MatrixF xf(true);
getMountTransform(ShapeBaseData::AIRepairNode,&xf);
Point3F pos(0, 0, 0);
xf.getColumn(3,&pos);
return pos;
}
//----------------------------------------------------------------------------
void ShapeBase::getEyeTransform(MatrixF* mat)
{
// Returns eye to world space transform
S32 eyeNode = mDataBlock->eyeNode;
if (eyeNode != -1)
mat->mul(getTransform(), mShapeInstance->mNodeTransforms[eyeNode]);
else
*mat = getTransform();
}
void ShapeBase::getRenderEyeTransform(MatrixF* mat)
{
// Returns eye to world space transform
S32 eyeNode = mDataBlock->eyeNode;
if (eyeNode != -1)
mat->mul(getRenderTransform(), mShapeInstance->mNodeTransforms[eyeNode]);
else
*mat = getRenderTransform();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -