📄 shapeimage.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "core/bitStream.h"
#include "ts/tsShapeInstance.h"
#include "console/consoleInternal.h"
#include "console/consoleTypes.h"
#include "game/fx/particleEngine.h"
#include "audio/audioDataBlock.h"
#include "game/shapeBase.h"
#include "game/projectile.h"
#include "game/gameConnection.h"
#include "math/mathIO.h"
#include "game/debris.h"
#include "math/mathUtils.h"
#include "sim/netObject.h"
//----------------------------------------------------------------------------
ShapeBaseImageData* InvalidImagePtr = (ShapeBaseImageData*) 1;
static EnumTable::Enums enumLoadedStates[] =
{
{ ShapeBaseImageData::StateData::IgnoreLoaded, "Ignore" },
{ ShapeBaseImageData::StateData::Loaded, "Loaded" },
{ ShapeBaseImageData::StateData::NotLoaded, "Empty" },
};
static EnumTable EnumLoadedState(3, &enumLoadedStates[0]);
static EnumTable::Enums enumSpinStates[] =
{
{ ShapeBaseImageData::StateData::IgnoreSpin,"Ignore" },
{ ShapeBaseImageData::StateData::NoSpin, "Stop" },
{ ShapeBaseImageData::StateData::SpinUp, "SpinUp" },
{ ShapeBaseImageData::StateData::SpinDown, "SpinDown" },
{ ShapeBaseImageData::StateData::FullSpin, "FullSpeed" },
};
static EnumTable EnumSpinState(5, &enumSpinStates[0]);
static EnumTable::Enums enumRecoilStates[] =
{
{ ShapeBaseImageData::StateData::NoRecoil, "NoRecoil" },
{ ShapeBaseImageData::StateData::LightRecoil, "LightRecoil" },
{ ShapeBaseImageData::StateData::MediumRecoil, "MediumRecoil" },
{ ShapeBaseImageData::StateData::HeavyRecoil, "HeavyRecoil" },
};
static EnumTable EnumRecoilState(4, &enumRecoilStates[0]);
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(ShapeBaseImageData);
ShapeBaseImageData::StateData::StateData()
{
name = 0;
transition.loaded[0] = transition.loaded[1] = -1;
transition.ammo[0] = transition.ammo[1] = -1;
transition.target[0] = transition.target[1] = -1;
transition.trigger[0] = transition.trigger[1] = -1;
transition.wet[0] = transition.wet[1] = -1;
transition.timeout = -1;
waitForTimeout = true;
timeoutValue = 0;
fire = false;
energyDrain = 0;
allowImageChange = true;
loaded = IgnoreLoaded;
spin = IgnoreSpin;
recoil = NoRecoil;
flashSequence = false;
sequence = -1;
sequenceVis = -1;
sound = 0;
emitter = NULL;
script = 0;
ignoreLoadedForReady = false;
}
static ShapeBaseImageData::StateData gDefaultStateData;
//----------------------------------------------------------------------------
ShapeBaseImageData::ShapeBaseImageData()
{
emap = false;
mountPoint = 0;
mountOffset.identity();
eyeOffset.identity();
correctMuzzleVector = true;
firstPerson = true;
useEyeOffset = false;
mass = 0;
usesEnergy = false;
minEnergy = 2;
accuFire = false;
projectile = NULL;
cloakable = true;
lightType = ShapeBaseImageData::NoLight;
lightColor.set(1.f,1.f,1.f,1.f);
lightTime = 1000;
lightRadius = 10.f;
mountTransform.identity();
shapeName = "";
fireState = -1;
computeCRC = false;
//
for (int i = 0; i < MaxStates; i++) {
stateName[i] = 0;
stateTransitionLoaded[i] = 0;
stateTransitionNotLoaded[i] = 0;
stateTransitionAmmo[i] = 0;
stateTransitionNoAmmo[i] = 0;
stateTransitionTarget[i] = 0;
stateTransitionNoTarget[i] = 0;
stateTransitionWet[i] = 0;
stateTransitionNotWet[i] = 0;
stateTransitionTriggerUp[i] = 0;
stateTransitionTriggerDown[i] = 0;
stateTransitionTimeout[i] = 0;
stateWaitForTimeout[i] = true;
stateTimeoutValue[i] = 0;
stateFire[i] = false;
stateEjectShell[i] = false;
stateEnergyDrain[i] = 0;
stateAllowImageChange[i] = true;
stateScaleAnimation[i] = true;
stateDirection[i] = true;
stateLoaded[i] = StateData::IgnoreLoaded;
stateSpin[i] = StateData::IgnoreSpin;
stateRecoil[i] = StateData::NoRecoil;
stateSequence[i] = 0;
stateSequenceRandomFlash[i] = false;
stateSound[i] = 0;
stateScript[i] = 0;
stateEmitter[i] = 0;
stateEmitterTime[i] = 0;
stateEmitterNode[i] = 0;
stateIgnoreLoadedForReady[i] = false;
}
statesLoaded = false;
casing = NULL;
casingID = 0;
shellExitDir.set( 1.0, 0.0, 1.0 );
shellExitDir.normalize();
shellExitVariance = 20.0;
shellVelocity = 1.0;
#ifdef TGE_RPGCLIENT2//TGE_RPGClient2
mCRC = 1;
#endif
}
ShapeBaseImageData::~ShapeBaseImageData()
{
}
bool ShapeBaseImageData::onAdd()
{
if (!Parent::onAdd())
return false;
// Copy state data from the scripting arrays into the
// state structure array. If we have state data already,
// we are on the client and need to leave it alone.
for (U32 i = 0; i < MaxStates; i++) {
StateData& s = state[i];
if (statesLoaded == false) {
s.name = stateName[i];
s.transition.loaded[0] = lookupState(stateTransitionNotLoaded[i]);
s.transition.loaded[1] = lookupState(stateTransitionLoaded[i]);
s.transition.ammo[0] = lookupState(stateTransitionNoAmmo[i]);
s.transition.ammo[1] = lookupState(stateTransitionAmmo[i]);
s.transition.target[0] = lookupState(stateTransitionNoTarget[i]);
s.transition.target[1] = lookupState(stateTransitionTarget[i]);
s.transition.wet[0] = lookupState(stateTransitionNotWet[i]);
s.transition.wet[1] = lookupState(stateTransitionWet[i]);
s.transition.trigger[0] = lookupState(stateTransitionTriggerUp[i]);
s.transition.trigger[1] = lookupState(stateTransitionTriggerDown[i]);
s.transition.timeout = lookupState(stateTransitionTimeout[i]);
s.waitForTimeout = stateWaitForTimeout[i];
s.timeoutValue = stateTimeoutValue[i];
s.fire = stateFire[i];
s.ejectShell = stateEjectShell[i];
s.energyDrain = stateEnergyDrain[i];
s.allowImageChange = stateAllowImageChange[i];
s.scaleAnimation = stateScaleAnimation[i];
s.direction = stateDirection[i];
s.loaded = stateLoaded[i];
s.spin = stateSpin[i];
s.recoil = stateRecoil[i];
s.sequence = -1; // Sequence is resolved in load
s.sequenceVis = -1; // Vis Sequence is resolved in load
s.sound = stateSound[i];
s.script = stateScript[i];
s.emitter = stateEmitter[i];
s.emitterTime = stateEmitterTime[i];
s.emitterNode = -1; // Sequnce is resolved in load
}
// The first state marked as "fire" is the state entered on the
// client when it recieves a fire event.
if (s.fire && fireState == -1)
fireState = i;
}
// Always preload images, this is needed to avoid problems with
// resolving sequences before transmission to a client.
return true;
}
bool ShapeBaseImageData::preload(bool server, char errorBuffer[256])
{
if (!Parent::preload(server, errorBuffer))
return false;
#ifdef TGE_RPG
if(server)
return true;
#endif
// Resolve objects transmitted from server
if (!server) {
if (projectile)
if (Sim::findObject(SimObjectId(projectile), projectile) == false)
Con::errorf(ConsoleLogEntry::General, "Error, unable to load projectile for shapebaseimagedata");
for (U32 i = 0; i < MaxStates; i++) {
if (state[i].emitter)
if (!Sim::findObject(SimObjectId(state[i].emitter), state[i].emitter))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load emitter for image datablock");
if (state[i].sound)
if (!Sim::findObject(SimObjectId(state[i].sound), state[i].sound))
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for image datablock");
}
}
// Use the first person eye offset if it's set.
useEyeOffset = !eyeOffset.isIdentity();
if (shapeName && shapeName[0]) {
// Resolve shapename
shape = ResourceManager->load(shapeName, computeCRC);
if (!bool(shape)) {
dSprintf(errorBuffer, 256, "Unable to load shape: %s", shapeName);
return false;
}
if(computeCRC)
{
Con::printf("Validation required for shape: %s", shapeName);
#ifdef TGE_RPGCLIENT2 // TGE_RPGClientPreload
mCRC = shape.getCRC();
#else
if(server)
mCRC = shape.getCRC();
else if(mCRC != shape.getCRC())
{
dSprintf(errorBuffer, 256, "Shape \"%s\" does not match version on server.",shapeName);
return false;
}
#endif
}
// Resolve nodes & build mount transform
ejectNode = shape->findNode("ejectPoint");
muzzleNode = shape->findNode("muzzlePoint");
retractNode = shape->findNode("retractionPoint");
mountTransform = mountOffset;
S32 node = shape->findNode("mountPoint");
if (node != -1) {
MatrixF total(1);
do {
MatrixF nmat;
QuatF q;
TSTransform::setMatrix(shape->defaultRotations[node].getQuatF(&q),shape->defaultTranslations[node],&nmat);
total.mul(nmat);
node = shape->nodes[node].parentIndex;
}
while(node != -1);
total.inverse();
mountTransform.mul(total);
}
// Resolve state sequence names & emitter nodes
isAnimated = false;
hasFlash = false;
for (U32 i = 0; i < MaxStates; i++) {
StateData& s = state[i];
if (stateSequence[i] && stateSequence[i][0])
s.sequence = shape->findSequence(stateSequence[i]);
if (s.sequence != -1)
{
isAnimated = true;
}
if (stateSequence[i] && stateSequence[i][0] && stateSequenceRandomFlash[i]) {
char bufferVis[128];
dStrncpy(bufferVis, stateSequence[i], 100);
dStrcat(bufferVis, "_vis");
s.sequenceVis = shape->findSequence(bufferVis);
}
if (s.sequenceVis != -1)
{
s.flashSequence = true;
hasFlash = true;
}
s.ignoreLoadedForReady = stateIgnoreLoadedForReady[i];
if (stateEmitterNode[i] && stateEmitterNode[i][0])
s.emitterNode = shape->findNode(stateEmitterNode[i]);
if (s.emitterNode == -1)
s.emitterNode = muzzleNode;
}
ambientSequence = shape->findSequence("ambient");
spinSequence = shape->findSequence("spin");
}
else {
dSprintf(errorBuffer, sizeof(errorBuffer), "Bad Datablock from server");
return false;
}
if( !casing && casingID != 0 )
{
if( !Sim::findObject( SimObjectId( casingID ), casing ) )
{
Con::errorf( ConsoleLogEntry::General, "ShapeBaseImageData::preload: Invalid packet, bad datablockId(casing): 0x%x", casingID );
}
}
TSShapeInstance* pDummy = new TSShapeInstance(shape, !server);
delete pDummy;
return true;
}
S32 ShapeBaseImageData::lookupState(const char* name)
{
if (!name || !name[0])
return -1;
for (U32 i = 0; i < MaxStates; i++)
if (stateName[i] && !dStricmp(name,stateName[i]))
return i;
Con::errorf(ConsoleLogEntry::General,"ShapeBaseImageData:: Could not resolve state \"%s\" for image \"%s\"",name,getName());
return 0;
}
static EnumTable::Enums imageLightEnum[] =
{
{ ShapeBaseImageData::NoLight, "NoLight" },
{ ShapeBaseImageData::ConstantLight, "ConstantLight" },
{ ShapeBaseImageData::PulsingLight, "PulsingLight" },
{ ShapeBaseImageData::WeaponFireLight, "WeaponFireLight" }
};
static EnumTable gImageLightTypeTable(ShapeBaseImageData::NumLightTypes, &imageLightEnum[0]);
void ShapeBaseImageData::initPersistFields()
{
Parent::initPersistFields();
addField("emap", TypeBool, Offset(emap, ShapeBaseImageData));
addField("shapeFile", TypeFilename, Offset(shapeName, ShapeBaseImageData));
addField("projectile", TypeProjectileDataPtr, Offset(projectile, ShapeBaseImageData));
addField("cloakable", TypeBool, Offset(cloakable, ShapeBaseImageData));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -