Files

424 lines
14 KiB
C
Raw Permalink Normal View History

2025-01-09 17:45:40 +08:00
#pragma once
/***************************************************************/
/*
/* 实体移动子系统
/* 处理实体的移动包,跳跃包
/* 模拟实体的移动和跳跃
/* 对于 宠物,怪物等需要模拟运动的实体,这里处理这些运动的模拟
/***************************************************************/
#pragma once
//如果需要开启a*寻路的话,就使用这个
#ifndef __USE_ASTAR__SEARCH_
#define __USE_ASTAR__SEARCH_
#endif
class CMovementSystem:
public CEntitySubSystem<enMoveSystemID,CMovementSystem,CAnimal>
{
public:
void HandFlyShoes(CDataPacketReader &packet) ;
//实体的移动的状态
typedef enum tagMotionType
{
mtMotionTypeIdle, //发呆状态
mtMotionTypePatrol, //巡逻,以出生点为中心一个半径的范围里移动
mtMotionTypeChase, //追逐
mtMotionTypeFleeing, //逃避
mtMotionTypeFollow, //跟随(主要是宠物)
mtMotionTypePoint, //往一个点移动
mtMotionTypeReturnHome, //回巢的移动
mtMotionTypeRandomFlee, // 随机乱跑。和flee的差别在于无目标的概念和乱走的差别在于每次跑都是单独的运动不能在一次逃跑中左右晃动。
mtMotionTypeConfused, //迷糊状态,乱走
}MotionType;
#define ASTAR_MAX_MOVE_STEP 1000 //A*算法最大执行多少
#define MOVECHECKTIMER 480000 //多久没动就踢下线
typedef CEntitySubSystem<enMoveSystemID,CMovementSystem,CAnimal> Inherid;
friend class CEntitySubSystem<enMoveSystemID,CMovementSystem,CAnimal>;
enum tagMoveFlag
{
mfTransport =0, //移动的标记
mfMaxMoveFlagID,//非法的标记
};
//处理移动数据
void ProcessNetData(INT_PTR nCmd,CDataPacketReader &packet );
CMovementSystem()
{
m_canMoveTick =0;
m_useAStar =false;
nFlyShoeNpcId = 0;
}
/*
* Comments: nStep格
* Param int nDir:
* Param int nPosX:x
* Param int nPosY:y
* Param int nStep:
* Param int nSendPkgTime:
* Param bool telSelf 广
* Param INT_PTR nMoveSpeed: 0
* Param INT_PTR nCmd : 使
* Param INT_PTR nClientFrame: 使使1使63
01
* Param INT_PTR nSimulateReboundSpeed: ()0
* @Return bool:true,false
*/
bool Move(INT_PTR nDir,INT_PTR nPosX, INT_PTR nPosY,INT_PTR nStep=1, unsigned int nSendPkgTime = 0,bool telSelf =false,
INT_PTR nMoveSpeed =0,INT_PTR nCmd =0,INT_PTR nClientFrame=0,INT_PTR nSimulateReboundSpeed =0) ;
/*
* Comments:
* Param int nPosX: X
* Param int nPosY: Y
* @Return bool:
*/
bool Jump(int nPosX, int nPosY);
/*
* Comments:
* Param int nPosX: x
* Param int nPosY: y
* Param int isUseRand: 使 1使
* @Return bool: true,false
*/
bool InstantMove(int nPosX,int nPosY,int isUseRand=1, unsigned nType=0,unsigned nValue=0);
/*
* Comments:
* Param CScene * pScene:
* Param INT_PTR & nPosX:x
* Param INT_PTR & nPosY:y
* Param INT_PTR nRange:
* @Return bool:truefalse
*/
bool GetMoveablePoint(CScene *pScene,INT_PTR &nPosX,INT_PTR &nPosY,INT_PTR nRange=1);
/*
* Comments:
* Param INT_PTR nMs:ms
* @Return void:
*/
void PostponeMoveTime(INT_PTR nMs);
/*
* Comments:,退
* Param int nStep:
* @Return bool:true,false
*/
bool RapidMove(int nStep);
//向目标冲锋
bool TargetRapidMove(int nTargetPosX, int nTargetPosY, int nMaxStep=0, int nSpeed=40);
/*
* Comments:/退
* Param INT_PTR nDir:退
* Param INT_PTR nStep:退
* @Return bool:truefalse
*/
bool BeatBack(INT_PTR nDir,INT_PTR nStep,bool isBeatback=true);
//定时检查,主要是怪物寻路用的
VOID OnTimeCheck(TICKCOUNT nTick);
/*
* Comments:
* Param INT_PTR nID: IDmfTransport
* Param bool flag:true false
* @Return void:
*/
inline void SetMoveFlag(INT_PTR nID,bool flag)
{
if(nID <0 || nID >= mfMaxMoveFlagID) return;
/*
if(flag )
{
OutputMsg(rmTip,_T("设置标记true"));
}
else
{
OutputMsg(rmTip,_T("设置标记false"));
}
*/
m_moveFlag[nID] = flag ?1:0;
}
/*
* Comments:
* Param INT_PTR nID: IDmfTransport
* @Return bool: true ,false
*/
inline bool GetMoveFlag(INT_PTR nID)
{
if(nID <0 || nID >= mfMaxMoveFlagID) return false;
return m_moveFlag[nID]?true:false;
}
virtual bool Initialize(void *data,SIZE_T size)
{
memset( &m_moveFlag,0,sizeof(m_moveFlag));
return true;
}
//不移动
void MoveIdle();
//归位
void MoveTargetedHome();
//不回巢怪物
void MoveNoReturnHome(INT_PTR nRadius =10,INT_PTR nMinSleepTime =4, INT_PTR nMaxSleepTime=10);
/*
* Comments:
* Param CScene * pScene:
* Param INT_PTR nPosX:x
* Param INT_PTR nPosY:y
* Param bool bFailSendTipmsg:tipmsg
* @Return bool:truefalse
*/
inline bool CanJumpTo(CScene * pScene, INT_PTR nPosX,INT_PTR nPosY,bool bFailSendTipmsg =false);
/*
* Comments:
* Param CAnimal * pTarget:
* Param INT_PTR nDistance:
* Param unsigned int nMaxDist:
* Param bool bStopWhenFailed:
* @Return void:
*/
void MoveFollow(CAnimal* pTarget,INT_PTR nDistance =2, unsigned int nMaxDist = 50, bool bStopWhenFailed = false);
/*
* Comments:
* Param INT_PTR nRadius:
* Param bool bRandStop :
* Param INT_PTR nMinSleepTime:
* Param INT_PTR nMaxSleepTime:
* @Return void:
*/
void MovePatrol(INT_PTR nRadius =10,INT_PTR nMinSleepTime =4, INT_PTR nMaxSleepTime=10);
/*
* Comments:
* Param CAnimal * pTarget:handle
* Param INT_PTR nMinDistance:
* Param INT_PTR nMaxDistance:
* @Return void:
*/
void MoveChase(CAnimal * pTarget,INT_PTR nMinDistance= 2,INT_PTR nMaxDistance = 10);
/*
* Comments:
* Param INT_PTR nSeconds:
* @Return void:
*/
void MoveConfused(INT_PTR nSeconds= 10);
//逃跑,向一个目标相反的方向逃跑
void MoveFleeing(CAnimal * pTarget);
//往一个点移动
void MovePoint(INT_PTR nPosX,INT_PTR nPosY);
/*
* Comments:
* Param INT_PTR nMaxDist:
* Param int nMinTime:
* Param int nMaxTime:
* Param bool bFleeImmediately:
* @Return void:
*/
void MoveRandomFlee(INT_PTR nMaxDist, int nMinTime, int nMaxTime, bool bFleeImmediately = false);
inline static INT_PTR GetDisSqare(INT_PTR nCurrentPosX,INT_PTR nCurrentPosY,INT_PTR nTargetX, INT_PTR nTargetY)
{
nCurrentPosX -= nTargetX;
nCurrentPosY -= nTargetY;
return nCurrentPosX* nCurrentPosX + nCurrentPosY* nCurrentPosY;
}
//重置主角的位置
inline void ResertActorPos(INT_PTR nPosx,INT_PTR nPosY);
//获取当前的运动状态
inline MotionType GetMotionType()
{
return (MotionType)m_motionStack.GetCurrentMotionState().bMotionType;
}
//去掉当前堆栈顶部的运动状态
inline void PopCurrentMotionState()
{
m_motionStack.PopState();
}
inline void ClearMotionStack()
{
for (INT_PTR i = 0; i < MAX_MOTION_TYPE_COUNT; i++)
m_motionStack.PopState();
}
/*
* Comments:广/
* Param INT_PTR nPosX: x
* Param INT_PTR nPosY: y
* Param INT_PTR nCmd:
* @Return void:
*/
inline void BroadcastMove(INT_PTR nPosX, INT_PTR nPosY,INT_PTR nCmd,unsigned nType=0,unsigned nValue=0);
/*
* Comments:
* @Return void:
*/
inline void ClearMovement(){
m_motionStack.Clear();
}
//设置是否使用A* 寻路算法
inline void SetUseAstar(bool flag)
{
m_useAStar = flag;
}
/*
* Comments:npc
* Param int nSceneId:npc所在的场景
* Param char * sNpcName:npc名字
* @Return int:0
*/
int AutoFindPathToNpc( int nSceneId, char * sNpcName);
//获得方位与步子
void GetCalculateMoveParam(INT_PTR nStartX,INT_PTR nStartY,INT_PTR nEndX, INT_PTR nEndY, INT_PTR & nDir,INT_PTR &nStep);
//客户端需要知道飞鞋传送到那个npcid
void SendHandFlyShoesRelust();
private:
//处理
void HandError(CDataPacketReader &packet){}
//收到移动包,进行处理
void HandMove(CDataPacketReader &packet);
//收到移动包,进行处理
void HandRun(CDataPacketReader &packet);
//收到跳跃包,进行处理
void HandJump(CDataPacketReader &packet);
//收到转向包,进行处理
void HandTurn(CDataPacketReader &packet);
//下面这些函数是移动的函数,如果移动成功,那么返回true和下一个点的坐标
//如果移动失败的话,将把这个移动的状态在堆栈删除掉
// 往一点的移
bool OnPointMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
//巡逻移动
bool OnPatrolMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
//追逐目标
bool OnChaseMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
//逃跑
bool OnFleeMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
//跟随
bool OnFollowMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
//迷惑
bool OnConfusedMove(MotionData & data,INT_PTR nCurrentPosX, INT_PTR nNextPosY, INT_PTR &nDir,INT_PTR & nStep);
// 随机逃跑
bool OnRandomFlee(MotionData &data, INT_PTR nCurrPosX, INT_PTR nCurrPosY, INT_PTR &nDir, INT_PTR &nStep);
//计算移动的方向和步子
inline bool CalculateMoveParam(INT_PTR nStartX,INT_PTR nStartY,INT_PTR nEndX, INT_PTR nEndY, INT_PTR & nDir,INT_PTR &nStep,INT_PTR nMinDisSquare=0,INT_PTR nMaxDisSquare =0);
/*
* Comments:
* Param INT_PTR nCurrentPosX:
* Param INT_PTR nCurrentPosY:
* @Return INT_PTR:
*/
//inline INT_PTR GetPosRandMovableDir(INT_PTR nCurrentPosX,INT_PTR nCurrentPosY);
//在一个扇形的区间里查找一个能用的运动点
bool GetFanAvailablePos(INT_PTR nCurrentPosX,INT_PTR nCurrentPosY,INT_PTR &nDir,INT_PTR &nStep);
/*
* Comments:
* Param INT_PTR nCurrentPosX: X
* Param INT_PTR nCurrentPosY: X
* Param INT_PTR & nDir:
* Param INT_PTR nPrevPosX: X
* Param INT_PTR nPrevPosY: X
* @Return bool:truefalse
*/
bool GetNexAvailablePos(INT_PTR nCurrentPosX, INT_PTR nCurrentPosY, INT_PTR &nDir, INT_PTR nPrevPosX, INT_PTR nPrevPosY);
//寻找路径,用于追逐的复杂情况使用
bool FindWay(INT_PTR nCurrentPosX,INT_PTR nCurrentPosY, INT_PTR nTargetPosX,INT_PTR nTargetPosY,INT_PTR &nDir,INT_PTR &nStep);
//当一个移动结束的时候调用
void OnMotionFinish(INT_PTR nMotionType);
/*
* Comments:
* Param INT_PTR nCurretnPosX: X
* Param INT_PTR nCurrentPosY: y
* Param INT_PTR nDesPosX: x
* Param INT_PTR nDesPosY: y
* Param INT_PTR nServerchRadius:
* @Return INT_PTR:
*/
//INT_PTR GetNextMoveDir(INT_PTR nCurretnPosX, INT_PTR nCurrentPosY,INT_PTR nDesPosX,INT_PTR nDesPosY,INT_PTR nServerchRadius=6);
//在90度空间里寻找能够走的方向
//bool Get90AngleAvaibleDir(CScene *pScene,INT_PTR nCurretnPosX, INT_PTR nCurrentPosY,INT_PTR nDesPosX,INT_PTR nDesPosY ,INT_PTR &nDir,bool bOnlyCheckCrossPoint=false);
private:
const static int MAX_MID_POINT_COUNT =32;
CTimer<500> m_timer; //怪物移动计时用的
CTimer<MOVECHECKTIMER> m_tmIdleLowPly;
BYTE m_moveFlag[4] ; //在4个移动标记
CMotionStack m_motionStack; //移动状态堆栈
bool m_useAStar; //是否使用使用A*寻路,因为性能比较低下,需要使用
CVector<SMALLCPOINT> m_searchNodes; //寻路点,把这个记录下来,降低寻路的次数
TICKCOUNT m_canMoveTick; //能够运动的tick,用于野蛮冲撞中,正在野蛮中,将丢弃移动数据包
public:
static CAdvanceAstar * s_pAStar; //寻路的指针
static bool s_boCheckIdleLowPly; //是否检查超低级玩家无操作时踢下线
static byte s_btMinIdlePlyLevel; //小于该等级玩家踢下线
int nFlyShoeNpcId;//npcid
};