📄 item.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "dgl/dgl.h"
#include "core/bitStream.h"
#include "game/game.h"
#include "math/mMath.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "sim/netConnection.h"
#include "game/item.h"
#include "collision/boxConvex.h"
#include "game/shadow.h"
#include "collision/earlyOutPolyList.h"
#include "collision/extrudedPolyList.h"
#include "math/mathIO.h"
//----------------------------------------------------------------------------
const F32 sRotationSpeed = 3.0; // Secs/Rotation
const F32 sAtRestVelocity = 0.15; // Min speed after collision
const S32 sCollisionTimeout = 15; // Timout value in ticks
// Client prediction
static F32 sMinWarpTicks = 0.5; // Fraction of tick at which instant warp occures
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
F32 Item::mGravity = -20;
const U32 sClientCollisionMask = (TerrainObjectType | InteriorObjectType |
StaticShapeObjectType | VehicleObjectType |
PlayerObjectType | StaticTSObjectType);
const U32 sServerCollisionMask = (sClientCollisionMask);
const S32 Item::csmAtRestTimer = 64;
static const U32 sgAllowedDynamicTypes = DamagableItemObjectType;
//----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(ItemData);
ItemData::ItemData()
{
friction = 0;
elasticity = 0;
sticky = false;
gravityMod = 1.0;
maxVelocity = -1;
density = 2;
drag = 0.5;
genericShadowLevel = Item_GenericShadowLevel;
noShadowLevel = Item_NoShadowLevel;
dynamicTypeField = 0;
pickUpName = StringTable->insert("an item");
lightOnlyStatic = false;
lightType = Item::NoLight;
lightColor.set(1.f,1.f,1.f,1.f);
lightTime = 1000;
lightRadius = 10.f;
}
static EnumTable::Enums itemLightEnum[] =
{
{ Item::NoLight, "NoLight" },
{ Item::ConstantLight, "ConstantLight" },
{ Item::PulsingLight, "PulsingLight" }
};
static EnumTable gItemLightTypeTable(Item::NumLightTypes, &itemLightEnum[0]);
void ItemData::initPersistFields()
{
Parent::initPersistFields();
addField("pickUpName", TypeString, Offset(pickUpName, ItemData));
addField("friction", TypeF32, Offset(friction, ItemData));
addField("elasticity", TypeF32, Offset(elasticity, ItemData));
addField("sticky", TypeBool, Offset(sticky, ItemData));
addField("gravityMod", TypeF32, Offset(gravityMod, ItemData));
addField("maxVelocity", TypeF32, Offset(maxVelocity, ItemData));
addField("dynamicType", TypeS32, Offset(dynamicTypeField, ItemData));
addField("lightType", TypeEnum, Offset(lightType, ItemData), 1, &gItemLightTypeTable);
addField("lightColor", TypeColorF, Offset(lightColor, ItemData));
addField("lightTime", TypeS32, Offset(lightTime, ItemData));
addField("lightRadius", TypeF32, Offset(lightRadius, ItemData));
addField("lightOnlyStatic", TypeBool, Offset(lightOnlyStatic, ItemData));
}
void ItemData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->writeFloat(friction, 10);
stream->writeFloat(elasticity, 10);
stream->writeFlag(sticky);
if(stream->writeFlag(gravityMod != 1.0))
stream->writeSignedFloat(gravityMod, 11);
if(stream->writeFlag(maxVelocity != -1))
stream->write(maxVelocity);
if(stream->writeFlag(lightType != Item::NoLight))
{
AssertFatal(Item::NumLightTypes < (1 << 2), "ItemData: light type needs more bits");
stream->writeInt(lightType, 2);
stream->writeFloat(lightColor.red, 7);
stream->writeFloat(lightColor.green, 7);
stream->writeFloat(lightColor.blue, 7);
stream->writeFloat(lightColor.alpha, 7);
stream->write(lightTime);
stream->write(lightRadius);
stream->writeFlag(lightOnlyStatic);
}
}
void ItemData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
friction = stream->readFloat(10);
elasticity = stream->readFloat(10);
sticky = stream->readFlag();
if(stream->readFlag())
gravityMod = stream->readSignedFloat(11);
else
gravityMod = 1.0;
if(stream->readFlag())
stream->read(&maxVelocity);
else
maxVelocity = -1;
if(stream->readFlag())
{
lightType = stream->readInt(2);
lightColor.red = stream->readFloat(7);
lightColor.green = stream->readFloat(7);
lightColor.blue = stream->readFloat(7);
lightColor.alpha = stream->readFloat(7);
stream->read(&lightTime);
stream->read(&lightRadius);
lightOnlyStatic = stream->readFlag();
}
else
lightType = Item::NoLight;
}
//----------------------------------------------------------------------------
IMPLEMENT_CO_NETOBJECT_V1(Item);
Item::Item()
{
mTypeMask |= ItemObjectType;
mDataBlock = 0;
mCollidable = false;
mStatic = false;
mRotate = false;
mVelocity = VectorF(0,0,0);
mAtRest = true;
mAtRestCounter = 0;
mInLiquid = false;
delta.warpTicks = 0;
delta.dt = 1;
mCollisionObject = 0;
mCollisionTimeout = 0;
// mGenerateShadow = true;
mConvex.init(this);
mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);
}
Item::~Item()
{
}
//----------------------------------------------------------------------------
bool Item::onAdd()
{
if (!Parent::onAdd() || !mDataBlock)
return false;
mTypeMask |= (mDataBlock->dynamicTypeField & sgAllowedDynamicTypes);
if (mStatic)
mAtRest = true;
mObjToWorld.getColumn(3,&delta.pos);
// Setup the box for our convex object...
mObjBox.getCenter(&mConvex.mCenter);
mConvex.mSize.x = mObjBox.len_x() / 2.0;
mConvex.mSize.y = mObjBox.len_y() / 2.0;
mConvex.mSize.z = mObjBox.len_z() / 2.0;
mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);
addToScene();
if (isServerObject())
{
scriptOnAdd();
}
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
if (mDataBlock->lightType != NoLight)
#else
else if (mDataBlock->lightType != NoLight)
#endif
{
Sim::getLightSet()->addObject(this);
mDropTime = Sim::getCurrentTime();
}
return true;
}
bool Item::onNewDataBlock(GameBaseData* dptr)
{
mDataBlock = dynamic_cast<ItemData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
return false;
scriptOnNewDataBlock();
return true;
}
void Item::onRemove()
{
mWorkingQueryBox.min.set(-1e9, -1e9, -1e9);
mWorkingQueryBox.max.set(-1e9, -1e9, -1e9);
scriptOnRemove();
removeFromScene();
Parent::onRemove();
}
void Item::onDeleteNotify(SimObject* obj)
{
if (obj == mCollisionObject) {
mCollisionObject = 0;
mCollisionTimeout = 0;
}
}
// Lighting: -----------------------------------------------------------------
void Item::registerLights(LightManager * lightManager, bool lightingScene)
{
if(lightingScene)
return;
if(mDataBlock->lightOnlyStatic && !mStatic)
return;
F32 intensity;
switch(mDataBlock->lightType)
{
case ConstantLight:
intensity = mFadeVal;
break;
case PulsingLight:
{
F32 delta = Sim::getCurrentTime() - mDropTime;
intensity = 0.5f + 0.5f * mSin(M_PI * delta / F32(mDataBlock->lightTime));
intensity = 0.15f + intensity * 0.85f;
intensity *= mFadeVal; // fade out light on flags
break;
}
default:
return;
}
mLight.mColor = mDataBlock->lightColor * intensity;
mLight.mColor.clamp();
mLight.mType = LightInfo::Point;
mLight.mRadius = mDataBlock->lightRadius;
mLight.mPos = getBoxCenter();
lightManager->addLight(&mLight);
}
//----------------------------------------------------------------------------
Point3F Item::getVelocity() const
{
return mVelocity;
}
void Item::setVelocity(const VectorF& vel)
{
mVelocity = vel;
setMaskBits(PositionMask);
mAtRest = false;
mAtRestCounter = 0;
}
void Item::applyImpulse(const Point3F&,const VectorF& vec)
{
// Items ignore angular velocity
VectorF vel;
vel.x = vec.x / mDataBlock->mass;
vel.y = vec.y / mDataBlock->mass;
vel.z = vec.z / mDataBlock->mass;
setVelocity(vel);
}
void Item::setCollisionTimeout(ShapeBase* obj)
{
if (mCollisionObject)
clearNotify(mCollisionObject);
deleteNotify(obj);
mCollisionObject = obj;
mCollisionTimeout = sCollisionTimeout;
setMaskBits(ThrowSrcMask);
}
//----------------------------------------------------------------------------
void Item::processTick(const Move* move)
{
Parent::processTick(move);
//
if (mCollisionObject && !--mCollisionTimeout)
mCollisionObject = 0;
// Warp to catch up to server
if (delta.warpTicks > 0)
{
delta.warpTicks--;
// Set new pos.
MatrixF mat = mObjToWorld;
mat.getColumn(3,&delta.pos);
delta.pos += delta.warpOffset;
mat.setColumn(3,delta.pos);
Parent::setTransform(mat);
// Backstepping
delta.posVec.x = -delta.warpOffset.x;
delta.posVec.y = -delta.warpOffset.y;
delta.posVec.z = -delta.warpOffset.z;
}
else
{
if (isServerObject() && mAtRest && (mStatic == false && mDataBlock->sticky == false))
{
if (++mAtRestCounter > csmAtRestTimer)
{
mAtRest = false;
mAtRestCounter = 0;
setMaskBits(PositionMask);
}
}
if (!mStatic && !mAtRest && isHidden() == false)
{
updateVelocity(TickSec);
updateWorkingCollisionSet(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec);
updatePos(isGhost() ? sClientCollisionMask : sServerCollisionMask, TickSec);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -