123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- //-----------------------------------------------------------------------------
- // 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.
- //-----------------------------------------------------------------------------
- #ifndef _AITURRETSHAPE_H_
- #define _AITURRETSHAPE_H_
- #ifndef _TURRETSHAPE_H_
- #include "T3D/turret/turretShape.h"
- #endif
- //----------------------------------------------------------------------------
- class AITurretShapeData: public TurretShapeData {
- typedef TurretShapeData Parent;
- public:
- enum Constants {
- MaxStates = 31, ///< We get one less than state bits because of
- /// the way data is packed.
- NumStateBits = 5,
- };
- struct StateData {
- StateData();
- const char* name; ///< State name
- /// @name Transition states
- ///
- /// @{
- ///
- struct Transition {
- S32 rest[2]; ///< NotAtRest/AtRest (NotStatic/Static)
- S32 target[2]; ///< NoTarget/Target
- S32 activated[2]; ///< Deactivated/Activated
- S32 timeout; ///< Transition after delay
- } transition;
- /// @}
- /// @name State attributes
- /// @{
- bool fire; ///< Can only have one fire state
- bool scan; ///< Perform a continuous scan looking for targets
- bool scaleAnimation; ///< Scale animation to fit the state timeout
- bool direction; ///< Animation direction
- 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
- S32 sequence; ///< Main thread sequence ID.
- ///
- ///
- const char* script; ///< Function on datablock to call when we enter this state; passed the id of
- /// the imageSlot.
- /// @}
- };
- /// @name State Data
- /// Individual state data used to initialize struct array
- /// @{
- const char* stateName [MaxStates];
- const char* stateTransitionAtRest [MaxStates];
- const char* stateTransitionNotAtRest [MaxStates];
- const char* stateTransitionTarget [MaxStates];
- const char* stateTransitionNoTarget [MaxStates];
- const char* stateTransitionActivated [MaxStates];
- const char* stateTransitionDeactivated [MaxStates];
- const char* stateTransitionTimeout [MaxStates];
- F32 stateTimeoutValue [MaxStates];
- bool stateWaitForTimeout [MaxStates];
- bool stateFire [MaxStates];
- bool stateScan [MaxStates];
- bool stateScaleAnimation [MaxStates];
- bool stateDirection [MaxStates];
- const char* stateSequence [MaxStates];
- const char* stateScript [MaxStates];
- /// @}
- /// @name State Array
- ///
- /// State array is initialized onAdd from the individual state
- /// struct array elements.
- ///
- /// @{
- StateData state[MaxStates]; ///< Array of states.
- bool statesLoaded; ///< Are the states loaded yet?
- S32 fireState; ///< The ID of the fire state.
- bool isAnimated; ///< This image contains at least one animated states
- /// @}
- F32 maxScanHeading; ///< Maximum heading angle from center to scan, in degrees
- F32 maxScanPitch; ///< Maximum pitch angle from center to scan, in degrees
- F32 maxScanDistance; ///< Maximum distance to scan to
- S32 scanTickFrequency; ///< How often should we perform a scan
- S32 scanTickFrequencyVariance; ///< Random amount that should be added to the scan tick frequency
- F32 trackLostTargetTime; ///< How long after the turret has lost the target should it still track it (in seconds)
- S32 scanNode; ///< The node on the shape we will scan from
- S32 aimNode; ///< The node on the shape we will aim from
- F32 maxWeaponRange; ///< Maximum range of the weapons, which may be different than the max scan distance
- F32 weaponLeadVelocity; ///< Velocity used to lead target (if value <= 0, don't lead target).
- public:
- AITurretShapeData();
- DECLARE_CONOBJECT(AITurretShapeData);
- static void initPersistFields();
- virtual bool onAdd();
- virtual bool preload(bool server, String &errorStr);
- virtual void packData(BitStream* stream);
- virtual void unpackData(BitStream* stream);
- S32 lookupState(const char* name); ///< Get a state by name.
- };
- //----------------------------------------------------------------------------
- // As shipped, AITurretShape plus the chain of classes it inherits from, consumes
- // all 32 mask-bits. AFX uses one additional mask-bit in GameBase, which pushes
- // AITurretShape over the mask-bit limit which will cause runtime crashes. As
- // a workaround, AFX modifies AITurretShape so that it reuses the TurretUpdateMask
- // defined by TurretShape rather than adding a unique TurretStateMask. This will
- // make AITurretShape's network updates slightly less efficient, but should be
- // acceptable for most uses of AITurretShape. If you plan to populate your levels
- // with many AITurretShape objects, consider restoring it to use of a unique
- // bit-mask, but if you do that, you will have to eliminate at use of at least one
- // bit by one of it's parent classes. (FYI ShapeBase uses 20 bits.)
- //
- // Comment out this define if you want AITurretShape to define it's own bit-mask.
- #define AFX_REUSE_TURRETSHAPE_MASKBITS
- class AITurretShape: public TurretShape
- {
- typedef TurretShape Parent;
- protected:
- #ifdef AFX_REUSE_TURRETSHAPE_MASKBITS
- enum MaskBits {
- TurretStateMask = Parent::TurretUpdateMask,
- NextFreeMask = Parent::NextFreeMask
- };
- #else // ORIGINAL CODE
- enum MaskBits {
- TurretStateMask = Parent::NextFreeMask,
- NextFreeMask = Parent::NextFreeMask << 1
- };
- #endif
- struct TargetInfo
- {
- SimObjectPtr<ShapeBase> target; ///< Current target
- Point3F lastPos; ///< The target's last known position
- VectorF lastVel; ///< The target's last known velocity
- SimTime lastSightTime; ///< The last time we saw the target
- bool hadValidTarget; ///< Did we previously have a valid target?
- TargetInfo() {reset();}
- void reset()
- {
- target = NULL;
- lastPos.zero();
- lastVel.zero();
- lastSightTime = 0;
- hadValidTarget = false;
- }
- // Check if we currently have a valid target
- bool isValid() const {return target != NULL;}
- // Check if we used to have a target
- bool hadTarget() const {return hadValidTarget;}
- };
- // Static attributes
- AITurretShapeData* mDataBlock;
- F32 mScanHeading;
- F32 mScanPitch;
- F32 mScanDistance;
- F32 mScanDistanceSquared;
- Box3F mScanBox;
- Box3F mTransformedScanBox;
- S32 mScanTickFrequency;
- S32 mScanTickFrequencyVariance;
- S32 mTicksToNextScan;
- F32 mWeaponRangeSquared;
- F32 mWeaponLeadVelocitySquared;
- SimSet mIgnoreObjects; ///< Ignore these objects when targeting
- bool mScanForTargets;
- bool mTrackTarget;
- TargetInfo mTarget; ///< Information on the current target
- SimObjectList mPotentialTargets;
- AITurretShapeData::StateData *mState;
- F32 mStateDelayTime; ///< Time till next state.
- bool mStateActive; ///< Is the turret active?
- TSThread *mStateAnimThread;
- void _initState();
- void _updateTurretState(F32 dt);
- /// Utility function to call state script functions on the datablock
- /// @param function Function
- void _scriptCallback(const char* function);
- void _setScanBox();
- void _cleanupPotentialTargets();
- void _performScan();
- void _lostTarget();
- void _gainedTarget(ShapeBase* target);
- void _trackTarget(F32 dt);
- void _cleanupTargetAndTurret();
- bool _testTargetLineOfSight(Point3F& aimPoint, ShapeBase* target, Point3F& sightPoint);
- /// ObjectRenderInst delegate hooked up in prepBatchRender
- /// if GameBase::gShowBoundingBox is true.
- void _renderScanner( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
- public:
- MatrixF mScanWorkspaceScanMat;
- MatrixF mScanWorkspaceScanWorldMat;
- public:
- AITurretShape();
- virtual ~AITurretShape();
- static void initPersistFields();
- bool onAdd();
- void onRemove();
- bool onNewDataBlock(GameBaseData *dptr, bool reload);
- void addToIgnoreList(ShapeBase* obj);
- void removeFromIgnoreList(ShapeBase* obj);
- void clearIgnoreList();
- S32 ignoreListCount();
- SimObject* getIgnoreListObject(S32 index);
- void setTurretStateName(const char* newState, bool force=false);
- void setTurretState(U32 newState, bool force=false);
- void activateTurret() {mStateActive = true;}
- void deactivateTurret() {mStateActive = false;}
- void startScanForTargets() {mScanForTargets = true;}
- void stopScanForTargets() {mScanForTargets = false;}
- void startTrackingTarget() {mTrackTarget = true;}
- void stopTrackingTarget() {mTrackTarget = false;}
- ShapeBase* getTarget() {return mTarget.target;}
- bool hasTarget() {return mTarget.target != NULL;}
- void resetTarget() {mTarget.reset();}
- void addPotentialTarget(ShapeBase* shape);
- void setWeaponLeadVelocity(F32 velocity) {mWeaponLeadVelocitySquared = velocity * velocity;}
- F32 getWeaponLeadVelocity() {return mSqrt(mWeaponLeadVelocitySquared);}
- void setAllGunsFiring(bool fire);
- void setGunSlotFiring(S32 slot, bool fire);
- virtual void setTransform(const MatrixF &mat);
- void getScanTransform(MatrixF& mat);
- void getAimTransform(MatrixF& mat);
- F32 getMaxScanHeading() const {return mScanHeading;}
- F32 getMaxScanPitch() const {return mScanPitch;}
- F32 getMaxScanDistance() const {return mScanDistance;}
- F32 getMaxScanDistanceSquared() const {return mScanDistanceSquared;}
- void recenterTurret();
- virtual void processTick(const Move *move);
- virtual void advanceTime(F32 dt);
- virtual U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
- virtual void unpackUpdate(NetConnection *conn, BitStream *stream);
- void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex );
- DECLARE_CONOBJECT(AITurretShape);
- };
- #endif // _AITURRETSHAPE_H_
|