//===========================================================================// // File: mechai.hpp // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 07/13/99 AHF Created File // //---------------------------------------------------------------------------// // Copyright (C) 1999, Microsoft // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #pragma once #include "ai.hpp" #include "aiutils.hpp" #include "rail_move.hpp" #include "vehicle.hpp" #include "path.hpp" #include "aiMoveData.hpp" #include "obstacle.hpp" namespace MechWarrior4 { class Dropship; class FieldBase; class CCheapMover; typedef MechWarrior4::AI__CreateMessage MoverAI__CreateMessage; //########################################################################## //########################### MoverAI ################################# //########################################################################## class MoverAI : public MechWarrior4::AI { typedef AI inherited; friend class CMoveData; friend class CPatrolData; friend class CSemiPatrolData; friend class CRigidPatrolData; friend class CFollowData; friend class CLookoutData; friend class CFleeData; friend class CSitData; friend class CMoveLocPointData; friend class CMoveObjectData; public: static void InitializeClass(); static void TerminateClass(); static ClassData *DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Inheritance Support // public: typedef MoverAI__CreateMessage CreateMessage; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Run-time Construction and Destruction Support // public: virtual void Save (MemoryStream *stream); virtual void Load (MemoryStream *stream); static MoverAI* Make(CreateMessage *message,ReplicatorID *base_id); virtual void NotifyRespawned(); protected: MoverAI(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element); virtual ~MoverAI(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Message Support // public: enum { DebugTextMessageID = MechWarrior4::AI::NextMessageID, NextMessageID }; void DebugTextMessageHandler(Adept::ReceiverDataMessageOf *message); protected: static const MessageEntry MessageEntries[]; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MoveHead Support // protected: enum HeadHit { LEFT_INSIDE_HIT, RIGHT_INSIDE_HIT, TOP_INSIDE_HIT, BOTTOM_INSIDE_HIT, LEFT_OUTSIDE_HIT, RIGHT_OUTSIDE_HIT, TOP_OUTSIDE_HIT, BOTTOM_OUTSIDE_HIT, NO_HIT }; Stuff::Point3D m_TopLeft,m_TopRight,m_BottomLeft,m_BottomRight; // coords of rectangle top is start Stuff::Point3D m_StartPoint,m_EndPoint; void ConstructRect (const Stuff::Point3D& start,const Stuff::Point3D& end,Stuff::Scalar width); HeadHit HeadPointInRect (const LinearMatrix4D& loc,Scalar speed,Stuff::Scalar delta); bool Intersect (const Stuff::Point3D& start,const Stuff::Point3D& end,const Stuff::Point3D& p1,const Stuff::Point3D& p2); Stuff::Point3D LeftHeadPoint (const Point3D& loc,const Stuff::Point3D& head); Stuff::Point3D RightHeadPoint (const Point3D& loc,const Stuff::Point3D& head); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Execution Support // protected: static bool m_AIJumpAllowed; MechWarrior4::Vehicle *m_Vehicle; MechWarrior4::MWObject *m_MWObject; CMoveData *m_CurMove; MW4AI::CRailPath *m_CurPath; Stuff::Point3D m_MoveHead,m_OutVec,m_OldMoveHead; Stuff::Point3D m_NewMoveHead,m_NewOutVec; Stuff::Scalar m_SpeedRequest,m_NewSpeedRequest; Stuff::Scalar m_EndSpeedRequest, m_NewEndSpeedRequest; Stuff::Scalar m_OrderSpeed; Stuff::Time m_StartJump,m_BurnTime; bool m_NeedHeadingAdjust,m_NeedSpeedAdjust; bool m_Jumping; bool m_JumpRequested; int m_FailCount; // # of times path calc has failed for current path CCheapMover *m_CheapMover; Stuff::Scalar m_TimeNotMoving; Stuff::Point3D m_CombatLeash; Stuff::Scalar m_CombatLeashRadius; virtual void SetOrderSpeed (Stuff::Scalar newvalue); virtual void ExecutePath (Stuff::Time till); virtual void ExecuteMoveCommand (Stuff::Time till); virtual void ExecuteMoveHead (Stuff::Time till); virtual void ExecuteMoveHeadCollision (Stuff::Time till); virtual void ExecutePostPath (Stuff::Time till); virtual void PathDone (Stuff::Time till,bool failed=false); virtual bool Jump (Stuff::Time till,const Stuff::Point3D& dest,bool request=false); virtual bool RequestJump (Stuff::Time till); virtual bool AllowTenMeter (void); public: virtual void PreCollisionExecute(Stuff::Time till); virtual void Info (void (*printCallback)(char* s)); virtual void Die (void); // LinearMatrix4D GetAILocalToWorld (void); bool ReactToCollision(Stuff::DynamicArrayOf *collisions,bool& shoulddamage); // return false to not handle collision MechWarrior4::Vehicle *getVehicle (void) { return m_Vehicle; } MW4AI::CRailPath* getCurPath (void) { return m_CurPath; } virtual void TurnOn (void); virtual void TurnOff (void); inline void SetCombatLeash(const Stuff::Point3D& center, Stuff::Scalar radius); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Dropship Support // public: enum DROP_STATE { DROP_NOT_ACTIVE, // not boarding a dropship DROP_FIRST_POINT, // approaching wait point DROP_SECOND_POINT, // approaching point outside doors DROP_THIRD_POINT, // approaching center of dropship DROP_FOURTH_POINT, // approaching final point DROP_DONE // done boarding }; protected: Stuff::Point3D m_DropShipWait; // point to wait to board drop ship Stuff::Point3D m_DropShipBoard; // point outside doors Stuff::Point3D m_DropShipCenter; // point at center of dropship Stuff::Point3D m_DropShipFinal; // final point to stand in drop ship DROP_STATE m_BoardingDropShip; std::vector m_OtherDropShipBoarders; int m_DropShipID; // which of the five we are Dropship *m_DropShip; bool m_ReadyToStart; // can be told to start boarding have reached wait point bool m_CanStartBoard; // previous person has reached center, so can start boarding void NextBoardDropShip (void); void CheckDropBoard (Stuff::Time delta); void StartDropShipBoard (void) { m_CanStartBoard = true; } public: void AddDropshipBoarder (int id,MoverAI *who); void CreateDropShipPoints (int id,Dropship *drop); void PrepareBoardDropShip (void); DROP_STATE DropState (void) const { return m_BoardingDropShip; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FieldBase Support // public: enum FIELDBASE_STATE { FIELDBASE_NOT_ACTIVE, // not entering a field base FIELDBASE_ENTER, // entering a fieldbase FIELDBASE_HEAL, // healing in fieldbase FIELDBASE_EXIT, // exiting a fieldbase FIELDBASE_DEAD // exiting from dead fieldbase }; protected: Stuff::Point3D m_FieldBaseEnter; // point to wait to board drop ship Stuff::Point3D m_FieldBaseExit; // point outside doors FIELDBASE_STATE m_EnteringFieldBase; FieldBase *m_FieldBase; bool m_FieldBaseReverse; void CheckFieldBase (Stuff::Time delta); public: void FieldBaseDead (void); void NextFieldBase (bool frommover=false); bool CreateFieldBasePoints (FieldBase *base); void PrepareEnterFieldBase (void); FIELDBASE_STATE FieldBaseState (void) const { return m_EnteringFieldBase; } virtual void FinishFieldBase (void); static bool g_AlwaysIgnoreObstacles; bool ExitedFieldBaseRecently() const; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Obstacle Support // protected: bool m_PathBlocked; MW4AI::CPathRequest *m_ObstacleRequest; MWObject *m_RamTarget; Stuff::Point3D m_PathBlockedCell; MW4AI::Rect4D *m_PathBlockedRect; int m_PathBlockedRectTimeDelta; stlport::vector m_ObstacleList; stlport::vector m_PathLock; // in BLOCK_GRID_RES coordinates stlport::vector m_LockedRects; Stuff::Time m_LockTime; Stuff::Time m_RecalcTime; bool m_PathBad; stlport::vector m_TempLockRects; // bool m_ObstacleAvoidMode; Point3D m_ObstacleAvoidPoint; stlport::vector m_TempLock; // in BLOCK_GRID_RES coordinates Stuff::Scalar m_LastTimeFinishedFieldBase; bool m_ShouldEndFieldBase; // void CheckObstacle (Stuff::Time till); // void AddObstacle (Entity *); virtual bool PointIsOK(const Stuff::Point3D& point) const; bool LockSquare (const Point3D& loc,Stuff::Scalar rad,Point3D& culprit); bool ObstacleNearBy (const Point3D& loc); void LancemateFieldBasePoint (Stuff::Point3D &pt,FieldBase *base); bool CheckSquare (const Point3D& loc,Stuff::Scalar rad,int dir,int mask,bool tenmeter); void AddTempLockRect (MW4AI::Rect4D *area) { m_TempLockRects.push_back (area); } void AddTempLockRect (const MW4AI::Rect4D& area) { MW4AI::Rect4D *rect; rect = new MW4AI::Rect4D (area); m_TempLockRects.push_back (rect); } void ClearTempLockRects (void); void CalcTempLock (void); void CalcUnTempLock (void); virtual void NotifyNoPath(void); virtual void NotifyReachedDestination(void); virtual void NotifyCollided(Entity *who); bool LockedByMe (const Stuff::Point3D& loc) const { return (MW4AI::Blocker (loc) == (MWObject *) this); } bool AddLockCell (const Stuff::Point3D& loc); // true if can lock cell bool AddLockRect (MW4AI::Rect4D *p1,bool carecollide,Stuff::Time till); void ClearRamLock (void); void RamLock (void); bool EqualRamTarget (Entity *target); virtual void HandleObstacle (MW4AI::Rect4D *p1,Adept::Entity *p2); public: virtual void ClearPathLock (bool quitting,bool fromram); virtual bool PathLock (bool secondpass,bool fromram); virtual void CalcPathLock (MW4AI::CPathRequest *reg); virtual void CalcPathUnlock (MW4AI::CPathRequest *reg); void RecalcPath (Stuff::Time till); void SetRamTarget (MWObject *obj); void SlopeCollide (void); void HandleObstacle (MW4AI::Rect4D *p1) { HandleObstacle (p1,NULL); } void HandleObstacle (Adept::Entity *p1) { HandleObstacle (NULL,p1); } void HandleObstacle (void) { HandleObstacle (NULL,NULL); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Order Support // public: static void DisableAIJumping (void) { m_AIJumpAllowed = false; } virtual void Shutdown (void) { ClearMoveOrder (); inherited::Shutdown (); } virtual void orderMoveLookOut (void); virtual bool orderMoveTo (Path *,int speed,int type,bool forwards,bool clear); virtual bool orderMoveToSemi (Path *,int speed,int type,bool forwards,bool clear); virtual bool orderMoveToRigid (Path *,int speed,int type,bool forwards,bool clear); virtual int orderMoveFlee (Entity *away,int speed); virtual bool orderMoveResumePatrol (Path *,int speed,int type,bool forwards,bool clear); virtual bool orderMoveResumePatrolSemi (Path *,int speed,int type,bool forwards,bool clear); virtual bool orderMoveResumePatrolRigid (Path *,int speed,int type,bool forwards,bool clear); virtual void orderMoveFollow (Entity *who,int offsetx,int offsetz,int maxspeed); virtual void orderMoveSit (bool shutdown); virtual bool orderMoveToLocPoint (const Stuff::Point3D& where,int speed,bool forwards,bool clear); virtual bool orderMoveToObject (Entity *what,int speed); virtual void ClearMoveOrder (void); virtual void NewPath (MW4AI::CRailPath *path,bool overridemove=false); protected: virtual Stuff::Scalar GetMinSpeed() const { return (0); } public: virtual void SetMoveHead (const Stuff::Point3D& head,Stuff::Scalar speed,const Stuff::Point3D& outvec = Stuff::Point3D (-1,-1,-1),Stuff::Scalar endspeed = 0); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Command Support // protected: virtual void ExecuteMoveCommand (MW4AI::CommandEntry *command); virtual void ExecuteHighCommand (MW4AI::CommandEntry *command); virtual void ExecuteLowCommand (MW4AI::CommandEntry *command); MW4AI::CommandEntry *CreateMoveToCommand (const Stuff::Point3D& where,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (MOVETO_LOWID,false,start); Check_Pointer (toret); toret->DataPoint3D (where); return toret; } MW4AI::CommandEntry *CreateTurnToCommand (const Stuff::Point3D& where,bool reverse,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (TURNTO_LOWID,false,start); Check_Pointer (toret); toret->DataPoint3D (where); toret->DataBoolean (reverse); return toret; } MW4AI::CommandEntry *CreateTrackCommand (const Stuff::Point3D& where,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (TRACK_LOWID,false,start); Check_Pointer (toret); toret->DataPoint3D (where); return toret; } MW4AI::CommandEntry *CreateKillTurnToCommand (Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (KILLTURNTO_LOWID,false,start); Check_Pointer (toret); return toret; } MW4AI::CommandEntry *CreateKillTrackCommand (Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (KILLTRACK_LOWID,false,start); Check_Pointer (toret); return toret; } MW4AI::CommandEntry *CreateTrackToCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (TRACKTO_LOWID,false,start); Check_Pointer (toret); toret->DataScalar (amount); return toret; } MW4AI::CommandEntry *CreateTurnCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (TURN_LOWID,false,start); Check_Pointer (toret); toret->DataScalar (amount); return toret; } MW4AI::CommandEntry *CreateSetSpeedCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (SETSPEED_LOWID,false,start); Check_Pointer (toret); toret->DataScalar (amount); return toret; } public: enum { TELEPORT_HIGHID = MechWarrior4::AI::NextHighCommandID, MOVE_HIGHID, FLEE_HIGHID, FORMONSPOT_HIGHID, FOLLOW_HIGHID, NextHighCommandID }; enum { MOVETO_LOWID = MechWarrior4::AI::NextLowCommandID, TURNTO_LOWID, KILLTURNTO_LOWID, TRACK_LOWID, TRACKTO_LOWID, KILLTRACK_LOWID, TURN_LOWID, SETSPEED_LOWID, NextLowCommandID }; MW4AI::CommandEntry *CreateTeleportCommand (Stuff::Point3D where,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (TELEPORT_HIGHID,true,start); Check_Pointer (toret); toret->DataPoint3D (where); return toret; } MW4AI::CommandEntry *CreateMoveCommand (CMoveData *data,Stuff::Time start = gos_GetElapsedTime ()) { MW4AI::CommandEntry *toret; toret = CreateBaseCommand (MOVE_HIGHID,true,start); Check_Pointer (toret); toret->DataPtr (data); return toret; } MW4AI::CommandEntry *CreateFleeCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { return CreateBaseCommand (FLEE_HIGHID,true,start); } MW4AI::CommandEntry *CreateFormOnSpotCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { return CreateBaseCommand (FORMONSPOT_HIGHID,true,start); } MW4AI::CommandEntry *CreateFollowCommand (Stuff::Scalar amount,Stuff::Time start = gos_GetElapsedTime ()) { return CreateBaseCommand (FOLLOW_HIGHID,true,start); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Support // public: void TestInstance() const; }; inline void MoverAI::SetCombatLeash(const Stuff::Point3D& center, Stuff::Scalar radius) { m_CombatLeash = center; m_CombatLeashRadius = radius; } }