//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames // Copyright (C) 2015 Faust Logic, Inc. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// #ifndef _SHAPEBASE_H_ #define _SHAPEBASE_H_ #ifndef __RESOURCE_H__ #include "core/resource.h" #endif #ifndef _GAMEBASE_H_ #include "T3D/gameBase/gameBase.h" #endif #ifndef _MOVEMANAGER_H_ #include "T3D/gameBase/moveManager.h" #endif #ifndef _COLOR_H_ #include "core/color.h" #endif #ifndef _CONVEX_H_ #include "collision/convex.h" #endif #ifndef _SCENERENDERSTATE_H_ #include "scene/sceneRenderState.h" #endif #ifndef _NETSTRINGTABLE_H_ #include "sim/netStringTable.h" #endif #ifndef _RENDERPASSMANAGER_H_ #include "renderInstance/renderPassManager.h" #endif #ifndef _TSSHAPE_H_ #include "ts/tsShape.h" #endif #ifndef _BITVECTOR_H_ #include "core/bitVector.h" #endif #ifndef _LIGHTINFO_H_ #include "lighting/lightInfo.h" #endif #ifndef _REFLECTOR_H_ #include "scene/reflector.h" #endif #ifndef _DYNAMIC_CONSOLETYPES_H_ #include "console/dynamicTypes.h" #endif #ifndef SHAPEASSET_H #include "T3D/assets/ShapeAsset.h" #endif // Need full definition visible for SimObjectPtr #include "T3D/fx/particleEmitter.h" #include "T3D/assets/SoundAsset.h" class GFXCubemap; class TSShapeInstance; class SceneRenderState; class TSThread; class GameConnection; struct CameraScopeQuery; class ProjectileData; class ExplosionData; struct DebrisData; class ShapeBase; class SFXSource; class SFXTrack; class SFXProfile; typedef void* Light; const F32 gGravity = -20; //-------------------------------------------------------------------------- extern void collisionFilter(SceneObject* object,S32 key); extern void defaultFilter(SceneObject* object,S32 key); //-------------------------------------------------------------------------- class ShapeBaseConvex : public Convex { typedef Convex Parent; friend class ShapeBase; friend class Vehicle; friend class RigidShape; protected: ShapeBase* pShapeBase; MatrixF* nodeTransform; public: MatrixF* transform; U32 hullId; Box3F box; public: ShapeBaseConvex() :pShapeBase(NULL), transform(NULL), hullId(0), nodeTransform(0) { mType = ShapeBaseConvexType; } ShapeBaseConvex(const ShapeBaseConvex& cv) { mObject = cv.mObject; pShapeBase = cv.pShapeBase; hullId = cv.hullId; nodeTransform = cv.nodeTransform; box = cv.box; transform = 0; } void findNodeTransform(); const MatrixF& getTransform() const; Box3F getBoundingBox() const; Box3F getBoundingBox(const MatrixF& mat, const Point3F& scale) const; Point3F support(const VectorF& v) const; void getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf); void getPolyList(AbstractPolyList* list); }; //-------------------------------------------------------------------------- struct ShapeBaseImageData: public GameBaseData { private: typedef GameBaseData Parent; public: enum Constants { MaxStates = 31, ///< We get one less than state bits because of /// the way data is packed. MaxShapes = 2, ///< The number of allowed shapes per image. Only /// the first shape is required. MaxGenericTriggers = 4, ///< The number of generic triggers for the image. StandardImageShape = 0, ///< Shape index used for the standard image shape FirstPersonImageShape = 1, ///< Shape index used for the optional first person image shape NumStateBits = 5, }; enum LightType { NoLight = 0, ConstantLight, SpotLight, PulsingLight, WeaponFireLight, NumLightTypes }; struct StateData { StateData(); const char* name; ///< State name /// @name Transition states /// /// @{ /// struct Transition { S32 loaded[2]; ///< NotLoaded/Loaded S32 ammo[2]; ///< Noammo/ammo S32 target[2]; ///< target/noTarget S32 trigger[2]; ///< Trigger up/down S32 altTrigger[2]; ///< Second trigger up/down S32 wet[2]; ///< wet/notWet S32 motion[2]; ///< NoMotion/Motion S32 timeout; ///< Transition after delay S32 genericTrigger[ShapeBaseImageData::MaxGenericTriggers][2]; ///< Generic trigger Out/In } transition; bool ignoreLoadedForReady; /// @} /// @name State attributes /// @{ bool fire; ///< Can only have one fire state bool altFire; ///< Can only have one alternate fire state bool reload; ///< Can only have one reload state bool ejectShell; ///< Should we eject a shell casing in this state? bool allowImageChange; ///< Can we switch to another image while in this state? /// /// For instance, if we have a rocket launcher, the player /// shouldn't be able to switch out while firing. So, /// you'd set allowImageChange to false in firing states, and /// true the rest of the time. bool scaleAnimation; ///< Scale animation to fit the state timeout bool scaleAnimationFP; ///< Scale animation to fit the state timeout while in first person bool direction; ///< Animation direction bool sequenceTransitionIn; ///< Do we transition to the state's sequence when we enter the state? bool sequenceTransitionOut; ///< Do we transition to the new state's sequence when we leave the state? bool sequenceNeverTransition; ///< Never allow a transition to this sequence. Often used for a fire sequence. F32 sequenceTransitionTime; ///< The time to transition in or out of a sequence. bool waitForTimeout; ///< Require the timeout to pass before advancing to the next /// state. F32 timeoutValue; ///< A timeout value; the effect of this value is determined /// by the flags scaleAnimation and waitForTimeout F32 energyDrain; ///< Sets the energy drain rate per second of this state. /// /// Energy is drained at energyDrain units/sec as long as /// we are in this state. enum LoadedState { IgnoreLoaded, ///< Don't change loaded state. Loaded, ///< Set us as loaded. NotLoaded, ///< Set us as not loaded. NumLoadedBits = 3 ///< How many bits to allocate to representing this state. (3 states needs 2 bits) } loaded; ///< Is the image considered loaded? enum SpinState { IgnoreSpin, ///< Don't change spin state. NoSpin, ///< Mark us as having no spin (ie, stop spinning). SpinUp, ///< Mark us as spinning up. SpinDown, ///< Mark us as spinning down. FullSpin, ///< Mark us as being at full spin. NumSpinBits = 3 ///< How many bits to allocate to representing this state. (5 states needs 3 bits) } spin; ///< Spin thread state. (Used to control spinning weapons, e.g. chainguns) enum RecoilState { NoRecoil, LightRecoil, MediumRecoil, HeavyRecoil, NumRecoilBits = 3 } recoil; ///< Recoil thread state. /// /// @note At this point, the only check being done is to see if we're in a /// state which isn't NoRecoil; ie, no differentiation is made between /// Light/Medium/Heavy recoils. Player::onImageRecoil() is the place /// where this is handled. bool flashSequence[MaxShapes];///< Is this a muzzle flash sequence? /// /// A muzzle flash sequence is used as a source to randomly display frames from, /// so if this is a flashSequence, we'll display a random piece each frame. S32 sequence[MaxShapes]; ///< Main thread sequence ID. /// /// S32 sequenceVis[MaxShapes]; ///< Visibility thread sequence. StringTableEntry shapeSequence; ///< Sequence that is played on mounting shape bool shapeSequenceScale; ///< Should the mounting shape's sequence playback be scaled /// to the length of the state. const char* script; ///< Function on datablock to call when we enter this state; passed the id of /// the imageSlot. ParticleEmitterData* emitter; ///< A particle emitter; this emitter will emit as long as the gun is in this /// this state. //SFXTrack* sound; F32 emitterTime; ///< S32 emitterNode[MaxShapes]; ///< Node ID on the shape to emit from SoundAsset* sound; SFXTrack* soundTrack; /// collisionDetails; ///< Detail level used to collide with. /// /// These are detail IDs, see TSShape::findDetail() Vector collisionBounds; ///< Detail level bounding boxes. Vector LOSDetails; ///< Detail level used to perform line-of-sight queries against. /// /// These are detail IDs, see TSShape::findDetail() /// @} /// @name Misc. Settings /// @{ bool firstPersonOnly; ///< Do we allow only first person view of this image? bool useEyePoint; ///< Do we use this object's eye point to view from? bool isInvincible; ///< If set, object cannot take damage (won't show up with damage bar either) bool renderWhenDestroyed; ///< If set, will not render this object when destroyed. bool inheritEnergyFromMount; /// @} virtual bool preload(bool server, String &errorStr); void computeAccelerator(U32 i); S32 findMountPoint(U32 n); /// @name Infrastructure /// The derived class should provide the following: /// @{ DECLARE_CONOBJECT(ShapeBaseData); ShapeBaseData(); ~ShapeBaseData(); static void initPersistFields(); virtual void packData(BitStream* stream); virtual void unpackData(BitStream* stream); /// @} /// @name Callbacks /// @{ DECLARE_CALLBACK( void, onEnabled, ( ShapeBase* obj, const char* lastState ) ); DECLARE_CALLBACK( void, onDisabled, ( ShapeBase* obj, const char* lastState ) ); DECLARE_CALLBACK( void, onDestroyed, ( ShapeBase* obj, const char* lastState ) ); DECLARE_CALLBACK( void, onImpact, ( ShapeBase* obj, SceneObject* collObj, VectorF vec, F32 len ) ); DECLARE_CALLBACK( void, onCollision, ( ShapeBase* obj, SceneObject* collObj, VectorF vec, F32 len ) ); DECLARE_CALLBACK( void, onDamage, ( ShapeBase* obj, F32 delta ) ); DECLARE_CALLBACK( void, onTrigger, ( ShapeBase* obj, S32 index, bool state ) ); DECLARE_CALLBACK( void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name)); DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) ); /// @} struct TextureTagRemapping { char* old_tag; char* new_tag; }; StringTableEntry remap_txr_tags; char* remap_buffer; Vector txr_tag_remappings; bool silent_bbox_check; void onShapeChanged() {} void onDebrisChanged() {} public: ShapeBaseData(const ShapeBaseData&, bool = false); }; //---------------------------------------------------------------------------- class WaterObject; class CameraShake; /// ShapeBase is the renderable shape from which most of the scriptable objects /// are derived, including the player, vehicle and items classes. ShapeBase /// provides basic shape loading, audio channels, and animation as well as damage /// (and damage states), energy, and the ability to mount images and objects. /// /// @nosubgrouping class ShapeBase : public GameBase, public ISceneLight { friend class ShapeBaseConvex; friend struct ShapeBaseImageData; friend void waterFind(SceneObject*, void*); friend void physicalZoneFind(SceneObject*, void*); public: typedef GameBase Parent; enum PublicConstants { ThreadSequenceBits = 6, MaxSequenceIndex = (1 << ThreadSequenceBits) - 1, EnergyLevelBits = 5, DamageLevelBits = 6, DamageStateBits = 2, // The thread and image limits should not be changed without // also changing the ShapeBaseMasks enum values declared // further down. MaxSoundThreads = 4, ///< Should be a power of 2 MaxScriptThreads = 4, ///< Should be a power of 2 MaxMountedImages = 4, ///< Should be a power of 2 MaxImageEmitters = 3, NumImageBits = 3, CollisionTimeoutValue = 250 ///< Timeout in ms. }; /// This enum indexes into the sDamageStateName array enum DamageState { Enabled, Disabled, Destroyed, NumDamageStates, NumDamageStateBits = 2, ///< Should be log2 of the number of states. }; protected: ShapeBaseData* mDataBlock; ///< Datablock bool mIsAiControlled; ///< Is this object AI controlled? //GameConnection* mControllingClient; ///< Controlling client ShapeBase* mControllingObject; ///< Controlling object bool mTrigger[MaxTriggerKeys]; ///< What triggers are set, if any. /// @name Scripted Sound /// @{ struct SoundThread { bool play; ///< Are we playing this sound? SimTime timeout; ///< Time until we stop playing this sound. AssetPtr asset; ///< Asset on server SFXSource* sound; ///< Sound on client }; SoundThread mSoundThread[MaxSoundThreads]; /// @} /// @name Scripted Animation Threads /// @{ struct Thread { /// State of the animation thread. enum State { Play, Stop, Pause, Destroy }; TSThread* thread; ///< Pointer to 3space data. State state; ///< State of the thread S32 sequence; ///< The animation sequence which is running in this thread. F32 timescale; ///< Timescale bool atEnd; ///< Are we at the end of this thread? F32 position; }; Thread mScriptThread[MaxScriptThreads]; /// @} /// @name Motion /// @{ bool mMoveMotion; ///< Indicates that a Move has come in requesting x, y or z motion /// @} protected: // ShapeBase pointer to our mount object if it is ShapeBase, else it is NULL. ShapeBase *mShapeBaseMount; /// @name Mounted Images /// @{ /// An image mounted on a shapebase. struct MountedImage { ShapeBaseImageData* dataBlock; ShapeBaseImageData::StateData *state; ShapeBaseImageData* nextImage; NetStringHandle skinNameHandle; NetStringHandle nextSkinNameHandle; String appliedSkinName; NetStringHandle scriptAnimPrefix; ///< The script based anim prefix /// @name State /// /// Variables tracking the state machine /// representing this specific mounted image. /// @{ bool loaded; ///< Is the image loaded? bool nextLoaded; ///< Is the next state going to result in the image being loaded? F32 delayTime; ///< Time till next state. F32 rDT; ///< Remainder delta time. Used internally. U32 fireCount; ///< Fire skip count. /// /// This is incremented every time the triggerDown bit is changed, /// so that the engine won't be too confused if the player toggles the /// trigger a bunch of times in a short period. /// /// @note The network deals with this variable at 3-bit precision, so it /// can only range 0-7. /// /// @see ShapeBase::setImageState() U32 altFireCount; ///< Alternate fire skip count. ///< @see fireCount U32 reloadCount; ///< Reload skip count. ///< @see fireCount bool triggerDown; ///< Is the trigger down? bool altTriggerDown; ///< Is the second trigger down? bool ammo; ///< Do we have ammo? /// /// May be true based on either energy OR ammo. bool target; ///< Have we acquired a targer? bool wet; ///< Is the weapon wet? bool motion; ///< Is the player in motion? bool genericTrigger[ShapeBaseImageData::MaxGenericTriggers]; ///< Generic triggers not assigned to anything in particular. These /// may be used to indicate some transition should occur. /// @} /// @name 3space /// /// Handles to threads and shapeinstances in the 3space system. /// @{ TSShapeInstance* shapeInstance[ShapeBaseImageData::MaxShapes]; TSThread *ambientThread[ShapeBaseImageData::MaxShapes]; TSThread *visThread[ShapeBaseImageData::MaxShapes]; TSThread *animThread[ShapeBaseImageData::MaxShapes]; TSThread *flashThread[ShapeBaseImageData::MaxShapes]; TSThread *spinThread[ShapeBaseImageData::MaxShapes]; bool doAnimateAllShapes; ///< Should all threads animate across all shapes to keep them in sync? bool forceAnimateAllShapes; ///< If the mounted image's owner is being controlled by the client /// and the image's datablock animateAllShapes field is true /// then set this to true and pass along to the client. This will help /// in the cases where the client's control object is ghosted but does /// not yet have its controlling client set correctly due to networking /// order of operations. All this for the MountedImage::updateDoAnimateAllShapes() /// optimization. U32 lastShapeIndex; ///< Tracks the last shape index. /// @} /// @name Effects /// /// Variables relating to lights, sounds, and particles. /// @{ SimTime lightStart; ///< Starting time for light flashes. LightInfo* lightInfo; ///< The real light (if any) associated with this weapon image. Vector mSoundSources; ///< Vector of currently playing sounds void updateSoundSources(const MatrixF& renderTransform); void addSoundSource(SFXSource* source); /// Represent the state of a specific particle emitter on the image. struct ImageEmitter { S32 node; F32 time; SimObjectPtr emitter; }; ImageEmitter emitter[MaxImageEmitters]; /// @} // MountedImage(); ~MountedImage(); void updateDoAnimateAllShapes(const ShapeBase* owner); }; MountedImage mMountedImageList[MaxMountedImages]; /// @} /// @name Render settings /// @{ TSShapeInstance* mShapeInstance; Convex * mConvexList; NetStringHandle mSkinNameHandle; String mAppliedSkinName; NetStringHandle mShapeNameHandle; ///< Name sent to client /// @} /// @name Physical Properties /// @{ S32 mAiPose; ///< Current pose. F32 mEnergy; ///< Current enery level. F32 mRechargeRate; ///< Energy recharge rate (in units/tick). F32 mMass; ///< Mass. F32 mOneOverMass; ///< Inverse of mass. /// @note This is used to optimize certain physics calculations. /// @} /// @name Physical Properties /// /// Properties for the current object, which are calculated /// based on the container we are in. /// /// @see ShapeBase::updateContainer() /// @see ShapeBase::mContainer /// @{ F32 mDrag; ///< Drag. F32 mBuoyancy; ///< Buoyancy factor. String mLiquidType; ///< Type of liquid (if any) we are in. F32 mLiquidHeight; ///< Height of liquid around us (from 0..1). F32 mWaterCoverage; ///< Percent of this object covered by water Point3F mAppliedForce; F32 mNetGravity; /// @} F32 mDamageFlash; F32 mWhiteOut; bool mFlipFadeVal; public: /// @name Collision Notification /// This is used to keep us from spamming collision notifications. When /// a collision occurs, we add to this list; then we don't notify anyone /// of the collision until the CollisionTimeout expires (which by default /// occurs in 1/10 of a second). /// /// @see notifyCollision(), queueCollision() /// @{ struct CollisionTimeout { CollisionTimeout* next; SceneObject* object; U32 objectNumber; SimTime expireTime; VectorF vector; }; CollisionTimeout* mTimeoutList; static CollisionTimeout* sFreeTimeoutList; /// Go through all the items in the collision queue and call onCollision on them all /// @see onCollision void notifyCollision(); /// Add a collision to the queue of collisions waiting to be handled @see onCollision /// @param object Object collision occurs with /// @param vec Vector along which collision occurs void queueCollision( SceneObject *object, const VectorF &vec); /// @see SceneObject virtual void onCollision( SceneObject *object, const VectorF &vec ); /// @} protected: /// @name Damage /// @{ F32 mDamage; F32 mRepairRate; F32 mRepairReserve; DamageState mDamageState; TSThread *mDamageThread; TSThread *mHulkThread; VectorF damageDir; /// @} /// @name Cloaking /// @{ bool mCloaked; F32 mCloakLevel; // TextureHandle mCloakTexture; /// @} /// @name Fading /// @{ bool mFadeOut; bool mFading; F32 mFadeVal; F32 mFadeElapsedTime; F32 mFadeTime; F32 mFadeDelay; public: F32 getFadeVal() { return mFadeVal; } /// @} protected: /// @name Control info /// @{ F32 mCameraFov; ///< The camera vertical FOV in degrees. bool mIsControlled; ///< Client side controlled flag /// @} public: static U32 sLastRenderFrame; protected: U32 mLastRenderFrame; F32 mLastRenderDistance; /// Do a reskin if necessary. virtual void reSkin(); /// This recalculates the total mass of the object, and all mounted objects void updateMass(); /// @name Image Manipulation /// @{ /// Utility function to call script functions which have to do with ShapeBase /// objects. /// @param imageSlot Image Slot id /// @param function Function void scriptCallback(U32 imageSlot,const char* function); /// Assign a ShapeBaseImage to an image slot /// @param imageSlot Image Slot ID /// @param imageData ShapeBaseImageData to assign /// @param skinNameHandle Skin texture name /// @param loaded Is the image loaded? /// @param ammo Does the image have ammo? /// @param triggerDown Is the trigger on this image down? /// @param altTriggerDown Is the second trigger on this image down? /// @param target Does the image have a target? virtual void setImage( U32 imageSlot, ShapeBaseImageData* imageData, NetStringHandle &skinNameHandle, bool loaded = true, bool ammo = false, bool triggerDown = false, bool altTriggerDown = false, bool motion = false, bool genericTrigger0 = false, bool genericTrigger1 = false, bool genericTrigger2 = false, bool genericTrigger3 = false, bool target = false ); /// Clear out an image slot /// @param imageSlot Image slot id void resetImageSlot(U32 imageSlot); /// Get the firing action state of the image /// @param imageSlot Image slot id U32 getImageFireState(U32 imageSlot); /// Get the alternate firing action state of the image /// @param imageSlot Image slot id U32 getImageAltFireState(U32 imageSlot); /// Get the reload action state of the image /// @param imageSlot Image slot id U32 getImageReloadState(U32 imageSlot); /// Sets the state of the image by state index /// @param imageSlot Image slot id /// @param state State id /// @param force Force image to state or let it finish then change void setImageState(U32 imageSlot, U32 state, bool force = false); void updateAnimThread(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState=NULL); /// Get the animation prefix for the image /// @param imageSlot Image slot id /// @param imageShapeIndex Shape index (1st person, etc.) used to look up the prefix text virtual const char* getImageAnimPrefix(U32 imageSlot, S32 imageShapeIndex) { return ""; } /// Advance animation on a image /// @param imageSlot Image slot id /// @param dt Change in time since last animation update void updateImageAnimation(U32 imageSlot, F32 dt); /// Advance state of image /// @param imageSlot Image slot id /// @param dt Change in time since last state update void updateImageState(U32 imageSlot,F32 dt); /// Start up the particle emitter for the this shapebase /// @param image Mounted image /// @param state State of shape base image void startImageEmitter(MountedImage &image,ShapeBaseImageData::StateData &state); /// Get light information for a mounted image /// @param imageSlot Image slot id Light* getImageLight(U32 imageSlot); /// Get the shape index to use for a mounted image /// @param image Mounted image U32 getImageShapeIndex(const MountedImage& image) const; /// @} /// Prune out non looping sounds from the sound manager which have expired void updateServerAudio(); /// Updates the audio state of the supplied sound /// @param st Sound void updateAudioState(SoundThread& st); /// Recalculates the spacial sound based on the current position of the object /// emitting the sound. void updateAudioPos(); /// Update bouyency and drag properties void updateContainer(); /// @name Events /// @{ virtual void onDeleteNotify(SimObject*); virtual void onImage(U32 imageSlot, bool unmount); virtual void onImageRecoil(U32 imageSlot,ShapeBaseImageData::StateData::RecoilState); virtual void onImageStateAnimation(U32 imageSlot, const char* seqName, bool direction, bool scaleToState, F32 stateTimeOutValue); virtual void onImageAnimThreadChange(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState, const char* anim, F32 pos, F32 timeScale, bool reset=false); virtual void onImageAnimThreadUpdate(U32 imageSlot, S32 imageShapeIndex, F32 dt); virtual void ejectShellCasing( U32 imageSlot ); virtual void shakeCamera( U32 imageSlot ); virtual void updateDamageLevel(); virtual void updateDamageState(); virtual void onImpact(SceneObject* obj, const VectorF& vec); virtual void onImpact(const VectorF& vec); /// @} /// The inner prep render function that does the /// standard work to render the shapes. void _prepRenderImage( SceneRenderState* state, bool renderSelf, bool renderMountedImages ); /// Renders the shape bounds as well as the /// bounds of all mounted shape images. void _renderBoundingBox( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance* ); void emitDust( ParticleEmitter* emitter, F32 triggerHeight, const Point3F& offset, U32 numMilliseconds, const Point3F& axis = Point3F::Zero ); public: ShapeBase(); ~ShapeBase(); TSShapeInstance* getShapeInstance() { return mShapeInstance; } static void initPersistFields(); static bool _setFieldSkin( void *object, const char *index, const char *data ); static const char *_getFieldSkin( void *object, const char *data ); /// @name Network state masks /// @{ /// enum ShapeBaseMasks { NameMask = Parent::NextFreeMask, DamageMask = Parent::NextFreeMask << 1, NoWarpMask = Parent::NextFreeMask << 2, CloakMask = Parent::NextFreeMask << 3, SkinMask = Parent::NextFreeMask << 4, MeshHiddenMask = Parent::NextFreeMask << 5, SoundMaskN = Parent::NextFreeMask << 6, ///< Extends + MaxSoundThreads bits ThreadMaskN = SoundMaskN << MaxSoundThreads, ///< Extends + MaxScriptThreads bits ImageMaskN = ThreadMaskN << MaxScriptThreads, ///< Extends + MaxMountedImage bits NextFreeMask = ImageMaskN << MaxMountedImages }; enum BaseMaskConstants { SoundMask = (SoundMaskN << MaxSoundThreads) - SoundMaskN, ThreadMask = (ThreadMaskN << MaxScriptThreads) - ThreadMaskN, ImageMask = (ImageMaskN << MaxMountedImages) - ImageMaskN }; /// @} static F32 sWhiteoutDec; static F32 sDamageFlashDec; static F32 sFullCorrectionDistance; static F32 sCloakSpeed; // Time to cloak, in seconds CubeReflector mCubeReflector; /// @name Initialization /// @{ bool onAdd(); void onRemove(); void onSceneRemove(); static void consoleInit(); bool onNewDataBlock( GameBaseData *dptr, bool reload ); /// @} /// @name Name & Skin tags /// @{ void setShapeName(const char*); const char* getShapeName(); void setSkinName(const char*); const char* getSkinName(); /// @} /// @name Mesh Visibility /// @{ protected: /// A bit vector of the meshes forced to be hidden. BitVector mMeshHidden; /// Sync the shape instance with the hidden mesh bit vector. void _updateHiddenMeshes(); public: /// Change the hidden state on all the meshes. void setAllMeshesHidden( bool forceHidden ); /// Set the force hidden state on a mesh. void setMeshHidden( S32 meshIndex, bool forceHidden ); /// Set the force hidden state on a named mesh. void setMeshHidden( const char *meshName, bool forceHidden ); #ifndef TORQUE_SHIPPING /// Prints the list of meshes and their visibility state /// to the console for debugging purposes. void dumpMeshVisibility(); #endif /// @} public: /// @name Basic attributes /// @{ /// Sets the amount of damage on this object. void setDamageLevel(F32 damage); /// Changes the object's damage state. /// @param state New state of the object void setDamageState(DamageState state); /// Changes the object's damage state, based on a named state. /// @see setDamageState /// @param state New state of the object as a string. bool setDamageState(const char* state); /// Returns the name of the current damage state as a string. const char* getDamageStateName(); /// Returns the current damage state. DamageState getDamageState() { return mDamageState; } /// Returns true if the object is destroyed. bool isDestroyed() { return mDamageState == Destroyed; } /// Sets the rate at which the object regenerates damage. /// /// @param rate Repair rate in units/second. void setRepairRate(F32 rate) { mRepairRate = rate; } /// Returns damage amount. F32 getDamageLevel() { return mDamage; } /// Returns the damage percentage. /// /// @return Damage factor, between 0.0 - 1.0 F32 getDamageValue(); /// Returns the datablock.maxDamage value F32 getMaxDamage(); /// Returns the rate at which the object regenerates damage F32 getRepairRate() { return mRepairRate; } /// Adds damage to an object /// @param amount Amount of of damage to add void applyDamage(F32 amount); /// Removes damage to an object /// @param amount Amount to repair object by void applyRepair(F32 amount); /// Sets the direction from which the damage is coming /// @param vec Vector indicating the direction of the damage void setDamageDir(const VectorF& vec) { damageDir = vec; } /// Sets the level of energy for this object /// @param energy Level of energy to assign to this object virtual void setEnergyLevel(F32 energy); /// Sets the rate at which the energy replentishes itself /// @param rate Rate at which energy restores void setRechargeRate(F32 rate) { mRechargeRate = rate; } /// Returns the amount of energy in the object F32 getEnergyLevel(); /// Returns the percentage of energy, 0.0 - 1.0 F32 getEnergyValue(); /// Returns the recharge rate F32 getRechargeRate() { return mRechargeRate; } /// Makes the shape explode. virtual void blowUp(); /// @} /// @name Script sounds /// @{ /// Plays an audio sound from a mounted object /// @param slot Mount slot ID void playAudio(U32 slot, StringTableEntry assetId); /// Stops audio from a mounted object /// @param slot Mount slot ID void stopAudio(U32 slot); /// @} /// @name Script animation /// @{ const char *getThreadSequenceName( U32 slot ); /// Sets the animation thread for a mounted object /// @param slot Mount slot ID /// @param seq Sequence id /// @param reset Reset the sequence bool setThreadSequence(U32 slot, S32 seq, bool reset = true); /// Update the animation thread /// @param st Thread to update void updateThread(Thread& st); /// Stop the current thread from playing on a mounted object /// @param slot Mount slot ID bool stopThread(U32 slot); /// Destroys the given animation thread /// @param slot Mount slot ID bool destroyThread(U32 slot); /// Pause the running animation thread /// @param slot Mount slot ID bool pauseThread(U32 slot); /// Start playing the running animation thread again /// @param slot Mount slot ID bool playThread(U32 slot); /// Set the thread position /// @param slot Mount slot ID /// @param pos Position bool setThreadPosition( U32 slot, F32 pos ); /// Toggle the thread as reversed or normal (For example, sidestep-right reversed is sidestep-left) /// @param slot Mount slot ID /// @param forward True if the animation is to be played normally bool setThreadDir(U32 slot,bool forward); /// Set the thread time scale /// @param slot Mount slot ID /// @param timescale Timescale bool setThreadTimeScale( U32 slot, F32 timeScale ); /// Advance all animation threads attached to this shapebase /// @param dt Change in time from last call to this function void advanceThreads(F32 dt); /// @} /// @name Cloaking /// @{ /// Force uncloaking of object /// @param reason Reason this is being forced to uncloak, this is passed directly to script control void forceUncloak(const char *reason); /// Set cloaked state of object /// @param cloaked True if object is cloaked void setCloakedState(bool cloaked); /// Returns true if object is cloaked bool getCloakedState(); /// Returns level of cloaking, as it's not an instant "now you see it, now you don't" F32 getCloakLevel(); /// @} /// @name Mounted objects /// @{ virtual void onMount( SceneObject *obj, S32 node ); virtual void onUnmount( SceneObject *obj,S32 node ); virtual void getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat ); virtual void getRenderMountTransform( F32 delta, S32 index, const MatrixF &xfm, MatrixF *outMat ); /// @} /// Returns where the AI should be to repair this object /// /// @note Legacy code from Tribes 2, but still works Point3F getAIRepairPoint(); /// @name Mounted Images /// @{ /// Mount an image (ShapeBaseImage) onto an image slot /// @param image ShapeBaseImage to mount /// @param imageSlot Image mount point /// @param loaded True if weapon is loaded (it assumes it's a weapon) /// @param skinNameHandle Skin name for object virtual bool mountImage(ShapeBaseImageData* image,U32 imageSlot,bool loaded, NetStringHandle &skinNameHandle); /// Unmount an image from a slot /// @param imageSlot Mount point virtual bool unmountImage(U32 imageSlot); /// Gets the information on the image mounted in a slot /// @param imageSlot Mount point ShapeBaseImageData* getMountedImage(U32 imageSlot); /// Gets the mounted image on on a slot /// @param imageSlot Mount Point MountedImage* getImageStruct(U32 imageSlot); TSShapeInstance* getImageShapeInstance(U32 imageSlot) { const MountedImage &image = mMountedImageList[imageSlot]; U32 imageShapeIndex = getImageShapeIndex(image); if(image.dataBlock && image.shapeInstance[imageShapeIndex]) return image.shapeInstance[imageShapeIndex]; return NULL; } /// Gets the next image which will be put in an image slot /// @see setImageState /// @param imageSlot mount Point ShapeBaseImageData* getPendingImage(U32 imageSlot); /// Returns true if the mounted image is firing /// @param imageSlot Mountpoint bool isImageFiring(U32 imageSlot); /// Returns true if the mounted image is alternate firing /// @param imageSlot Mountpoint bool isImageAltFiring(U32 imageSlot); /// Returns true if the mounted image is reloading /// @param imageSlot Mountpoint bool isImageReloading(U32 imageSlot); /// This will return true if, when triggered, the object will fire. /// @param imageSlot mount point /// @param ns Used internally for recursion, do not mess with /// @param depth Used internally for recursion, do not mess with bool isImageReady(U32 imageSlot,U32 ns = (U32)-1,U32 depth = 0); /// Returns true if the specified image is mounted /// @param image ShapeBase image bool isImageMounted(ShapeBaseImageData* image); /// Returns the slot which the image specified is mounted on /// @param image Image to test for S32 getMountSlot(ShapeBaseImageData* image); /// Returns the skin for the image in a slot /// @param imageSlot Image slot to get the skin from NetStringHandle getImageSkinTag(U32 imageSlot); /// Check if the given state exists on the mounted Image /// @param imageSlot Image slot id /// @param state Image state to check for bool hasImageState(U32 imageSlot, const char* state); /// Returns the image state as a string /// @param imageSlot Image slot to check state const char* getImageState(U32 imageSlot); /// Sets the generic trigger state of the image /// @param imageSlot Image slot /// @param trigger Generic trigger number 0-3 /// @param state True if generic trigger is down void setImageGenericTriggerState(U32 imageSlot, U32 trigger, bool state); /// Returns the generic trigger state of the image /// @param imageSlot Image slot /// @param trigger Generic trigger number 0-3 bool getImageGenericTriggerState(U32 imageSlot, U32 trigger); /// Sets the trigger state of the image (Ie trigger pulled down on gun) /// @param imageSlot Image slot /// @param trigger True if trigger is down void setImageTriggerState(U32 imageSlot,bool trigger); /// Returns the trigger state of the image /// @param imageSlot Image slot bool getImageTriggerState(U32 imageSlot); /// Sets the alt trigger state of the image (Ie trigger pulled down on gun) /// @param imageSlot Image slot /// @param trigger True if trigger is down void setImageAltTriggerState( U32 imageSlot, bool trigger ); /// Returns the alt trigger state of the image /// @param imageSlot Image slot bool getImageAltTriggerState( U32 imageSlot ); /// Sets the flag if the image uses ammo or energy /// @param imageSlot Image slot /// @param ammo True if the weapon uses ammo, not energy void setImageAmmoState(U32 imageSlot,bool ammo); /// Returns true if the image uses ammo, not energy /// @param imageSlot Image slot bool getImageAmmoState(U32 imageSlot); /// Sets the image as wet or not, IE if you wanted a gun not to function underwater /// @param imageSlot Image slot /// @param wet True if image is wet void setImageWetState(U32 imageSlot,bool wet); /// Returns true if image is wet /// @param imageSlot image slot bool getImageWetState(U32 imageSlot); /// Sets the image as in motion or not, IE if you wanted a gun not to sway while the player is in motion /// @param imageSlot Image slot /// @param motion True if image is in motion void setImageMotionState(U32 imageSlot,bool motion); /// Returns true if image is in motion /// @param imageSlot image slot bool getImageMotionState(U32 imageSlot); /// Sets the flag if the image has a target /// @param imageSlot Image slot /// @param ammo True if the weapon has a target void setImageTargetState(U32 imageSlot,bool ammo); /// Returns true if the image has a target /// @param imageSlot Image slot bool getImageTargetState(U32 imageSlot); /// Sets the flag of if the image is loaded with ammo /// @param imageSlot Image slot /// @param loaded True if object is loaded with ammo void setImageLoadedState(U32 imageSlot,bool loaded); /// Returns true if object is loaded with ammo /// @param imageSlot Image slot bool getImageLoadedState(U32 imageSlot); /// Set the script animation prefix for the image /// @param imageSlot Image slot id /// @param prefix The prefix applied to the image void setImageScriptAnimPrefix(U32 imageSlot, NetStringHandle prefix); /// Get the script animation prefix for the image /// @param imageSlot Image slot id /// @param imageShapeIndex Shape index (1st person, etc.) used to look up the prefix text NetStringHandle getImageScriptAnimPrefix(U32 imageSlot); /// Modify muzzle, if needed, to aim at whatever is straight in front of eye. /// Returns true if result is actually modified. /// @param muzMat Muzzle transform (in/out) /// @param result Corrected muzzle vector (out) bool getCorrectedAim(const MatrixF& muzMat, VectorF* result); /// Gets the muzzle vector of a specified slot /// @param imageSlot Image slot to check transform for /// @param vec Muzzle vector (out) virtual void getMuzzleVector(U32 imageSlot,VectorF* vec); /// Gets the point of the muzzle of the image /// @param imageSlot Image slot /// @param pos Muzzle point (out) void getMuzzlePoint(U32 imageSlot,Point3F* pos); /// @} /// @name Transforms /// @{ /// Gets the minimum viewing distance, maximum viewing distance, camera offsetand rotation /// for this object, if the world were to be viewed through its eyes /// @param min Minimum viewing distance /// @param max Maximum viewing distance /// @param offset Offset of the camera from the origin in local space /// @param rot Rotation matrix virtual void getCameraParameters(F32 *min,F32* max,Point3F* offset,MatrixF* rot); /// Gets the camera to world space transform matrix /// @todo Find out what pos does /// @param pos TODO: Find out what this does /// @param mat Camera transform (out) virtual void getCameraTransform(F32* pos,MatrixF* mat); /// Gets the view transform for a particular eye, taking into account the current absolute /// orient and position values of the display device. virtual void getEyeCameraTransform( IDisplayDevice *display, U32 eyeId, MatrixF *outMat ); /// Gets the index of a node inside a mounted image given the name /// @param imageSlot Image slot /// @param nodeName Node name S32 getNodeIndex(U32 imageSlot,StringTableEntry nodeName); /// @} /// @name Object Transforms /// @{ /// Returns the eye transform of this shape, IE the eyes of a player /// @param mat Eye transform (out) virtual void getEyeTransform(MatrixF* mat); /// Returns the eye transform of this shape without including mounted images, IE the eyes of a player /// @param mat Eye transform (out) virtual void getEyeBaseTransform(MatrixF* mat, bool includeBank); /// The retraction transform is the muzzle transform in world space. /// /// If the gun is pushed back, for instance, if the player ran against something, /// the muzzle of the gun gets pushed back towards the player, towards this location. /// @param imageSlot Image slot /// @param mat Transform (out) virtual void getRetractionTransform(U32 imageSlot,MatrixF* mat); /// Muzzle transform of mounted object in world space /// @param imageSlot Image slot /// @param mat Muzzle transform (out) virtual void getMuzzleTransform(U32 imageSlot,MatrixF* mat); /// Gets the transform of a mounted image in world space /// @param imageSlot Image slot /// @param mat Transform (out) virtual void getImageTransform(U32 imageSlot,MatrixF* mat); /// Gets the transform of a node on a mounted image in world space /// @param imageSlot Image Slot /// @param node node on image /// @param mat Transform (out) virtual void getImageTransform(U32 imageSlot,S32 node, MatrixF* mat); /// Gets the transform of a node on a mounted image in world space /// @param imageSlot Image Slot /// @param nodeName Name of node on image /// @param mat Transform (out) virtual void getImageTransform(U32 imageSlot, StringTableEntry nodeName, MatrixF* mat); ///@} /// @name Render transforms /// Render transforms are different from object transforms in that the render transform of an object /// is where, in world space, the object is actually rendered. The object transform is the /// absolute position of the object, as in where it should be. /// /// The render transforms typically vary from object transforms due to client side prediction. /// /// Other than that, these functions are identical to their object-transform counterparts /// /// @note These are meaningless on the server. /// @{ virtual void getRenderRetractionTransform(U32 index,MatrixF* mat); virtual void getRenderMuzzleTransform(U32 index,MatrixF* mat); virtual void getRenderImageTransform(U32 imageSlot,MatrixF* mat,bool noEyeOffset=false); virtual void getRenderImageTransform(U32 index,S32 node, MatrixF* mat); virtual void getRenderImageTransform(U32 index, StringTableEntry nodeName, MatrixF* mat); virtual void getRenderMuzzleVector(U32 imageSlot,VectorF* vec); virtual void getRenderMuzzlePoint(U32 imageSlot,Point3F* pos); virtual void getRenderEyeTransform(MatrixF* mat); virtual void getRenderEyeBaseTransform(MatrixF* mat, bool includeBank); /// @} /// @name Screen Flashing /// @{ /// Returns the level of screenflash that should be used virtual F32 getDamageFlash() const; /// Sets the flash level /// @param amt Level of flash virtual void setDamageFlash(const F32 amt); /// White out is the flash-grenade blindness effect /// This returns the level of flash to create virtual F32 getWhiteOut() const; /// Set the level of flash blindness virtual void setWhiteOut(const F32); /// @} /// @name Movement & velocity /// @{ /// Sets the velocity of this object /// @param vel Velocity vector virtual void setVelocity(const VectorF& vel); /// Applies an impulse force to this object /// @param pos Position where impulse came from in world space /// @param vec Velocity vector (Impulse force F = m * v) virtual void applyImpulse(const Point3F& pos,const VectorF& vec); /// @} /// @name Cameras and Control /// @{ /// Returns the object controlling this object ShapeBase* getControllingObject() { return mControllingObject; } /// Sets the controlling object /// @param obj New controlling object virtual void setControllingObject(ShapeBase* obj); /// virtual void setControllingClient( GameConnection* connection ); /// Returns the object this is controlling virtual ShapeBase* getControlObject(); /// sets the object this is controlling /// @param obj New controlled object virtual void setControlObject(ShapeBase *obj); /// Returns true if this object is controlling by something bool isControlled() { return(mIsControlled); } /// Returns true if this object is being used as a camera in first person bool isFirstPerson() const; /// Returns true if the camera uses this objects eye point (defined by modeler) bool useObjsEyePoint() const; /// Returns true if this object can only be used as a first person camera bool onlyFirstPerson() const; /// Returns the vertical field of view in degrees for /// this object if used as a camera. virtual F32 getCameraFov() { return mCameraFov; } /// Returns the default vertical field of view in degrees /// if this object is used as a camera. virtual F32 getDefaultCameraFov() { return mDataBlock->cameraDefaultFov; } /// Sets the vertical field of view in degrees for this /// object if used as a camera. /// @param yfov The vertical FOV in degrees to test. virtual void setCameraFov(F32 fov); /// Returns true if the vertical FOV in degrees is within /// allowable parameters of the datablock. /// @param yfov The vertical FOV in degrees to test. /// @see ShapeBaseData::cameraMinFov /// @see ShapeBaseData::cameraMaxFov virtual bool isValidCameraFov(F32 fov); /// @} void processTick(const Move *move); void advanceTime(F32 dt); /// @name Rendering /// @{ /// Returns the renderable shape of this object TSShape const* getShape(); /// @see SceneObject virtual void prepRenderImage( SceneRenderState* state ); /// Used from ShapeBase::_prepRenderImage() to submit render /// instances for the main shape or its mounted elements. virtual void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex ); /// Preprender logic virtual void calcClassRenderData() { } /// Virtualize this so other classes may override it for custom reasons. virtual void renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRenderState *state ); /// @} /// Control object scoping void onCameraScopeQuery(NetConnection *cr, CameraScopeQuery *camInfo); bool castRay(const Point3F &start, const Point3F &end, RayInfo* info); bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo* info); bool buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF& sphere); void buildConvex(const Box3F& box, Convex* convex); /// @name Rendering /// @{ /// Increments the last rendered frame number static void incRenderFrame() { sLastRenderFrame++; } /// Returns true if the last frame calculated rendered bool didRenderLastRender() { return mLastRenderFrame == sLastRenderFrame; } /// Sets the state of this object as hidden or not. If an object is hidden /// it is removed entirely from collisions, it is not ghosted and is /// essentially "non existant" as far as simulation is concerned. /// @param hidden True if object is to be hidden virtual void setHidden(bool hidden); /// Returns true if this object can be damaged bool isInvincible(); /// Start fade of object in/out /// @param fadeTime Time fade should take /// @param fadeDelay Delay before starting fade /// @param fadeOut True if object is fading out, false if fading in. void startFade( F32 fadeTime, F32 fadeDelay = 0.0, bool fadeOut = true ); /// Traverses mounted objects and registers light sources with the light manager /// @param lightManager Light manager to register with /// @param lightingScene Set to true if the scene is being lit, in which case these lights will not be used //void registerLights(LightManager * lightManager, bool lightingScene); // ISceneLight virtual void submitLights( LightManager *lm, bool staticLighting ); virtual LightInfo* getLight() { return NULL; } /// @} /// Returns true if the point specified is in the water /// @param point Point to test in world space bool pointInWater( Point3F &point ); /// Returns the percentage of this object covered by water F32 getWaterCoverage() { return mWaterCoverage; } /// Returns the height of the liquid on this object F32 getLiquidHeight() { return mLiquidHeight; } virtual WaterObject* getCurrentWaterObject(); void setCurrentWaterObject( WaterObject *obj ); void setTransform(const MatrixF & mat); virtual F32 getMass() const { return mMass; } /// @name Network /// @{ F32 getUpdatePriority(CameraScopeQuery *focusObject, U32 updateMask, S32 updateSkips); U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream); void unpackUpdate(NetConnection *conn, BitStream *stream); void writePacketData(GameConnection *conn, BitStream *stream); void readPacketData(GameConnection *conn, BitStream *stream); /// @} DECLARE_CONOBJECT(ShapeBase); protected: DECLARE_CALLBACK( F32, validateCameraFov, (F32 fov) ); public: class CollisionEventCallback { public: virtual void collisionNotify(SceneObject* shape0, SceneObject* shape1, const VectorF& vel)=0; }; private: Vector collision_callbacks; void notifyCollisionCallbacks(SceneObject*, const VectorF& vel); public: void registerCollisionCallback(CollisionEventCallback*); void unregisterCollisionCallback(CollisionEventCallback*); protected: enum { ANIM_OVERRIDDEN = BIT(0), BLOCK_USER_CONTROL = BIT(1), IS_DEATH_ANIM = BIT(2), BAD_ANIM_ID = 999999999, BLENDED_CLIP = 0x80000000, }; struct BlendThread { TSThread* thread; U32 tag; }; Vector blend_clips; static U32 unique_anim_tag_counter; U8 anim_clip_flags; S32 last_anim_id; U32 last_anim_tag; U32 last_anim_lock_tag; S32 saved_seq_id; F32 saved_pos; F32 saved_rate; U32 playBlendAnimation(S32 seq_id, F32 pos, F32 rate); void restoreBlendAnimation(U32 tag); public: U32 playAnimation(const char* name, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim); F32 getAnimationDuration(const char* name); virtual void restoreAnimation(U32 tag); virtual U32 getAnimationID(const char* name); virtual U32 playAnimationByID(U32 anim_id, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim); virtual F32 getAnimationDurationByID(U32 anim_id); virtual bool isBlendAnimation(const char* name); virtual const char* getLastClipName(U32 clip_tag); virtual void unlockAnimation(U32 tag, bool force=false) { } virtual U32 lockAnimation() { return 0; } virtual bool isAnimationLocked() const { return false; } virtual void setSelectionFlags(U8 flags); }; //------------------------------------------------------------------------------ // inlines //------------------------------------------------------------------------------ inline bool ShapeBase::getCloakedState() { return(mCloaked); } inline F32 ShapeBase::getCloakLevel() { return(mCloakLevel); } inline const char* ShapeBase::getShapeName() { return mShapeNameHandle.getString(); } inline const char* ShapeBase::getSkinName() { return mSkinNameHandle.getString(); } inline WaterObject* ShapeBase::getCurrentWaterObject() { if ( isMounted() && mShapeBaseMount ) return mShapeBaseMount->getCurrentWaterObject(); return mCurrentWaterObject; } #endif // _H_SHAPEBASE_