Files
mir_server/server/LogicServer/skill/SkillSubSystem.h

450 lines
14 KiB
C
Raw Normal View History

2025-01-09 17:45:40 +08:00
#pragma once
/***************************************************************/
/*
/* 实体技能子系统
/* 实体释放技能
/* 技能冷却
/* 伤害计算
/***************************************************************/
#pragma once
class CAnimal;
//class CSkillCondition;
class CSkillSubSystem:
public CEntitySubSystem<enSkillSystemID,CSkillSubSystem,CAnimal>
{
public:
typedef CEntitySubSystem<enSkillSystemID,CSkillSubSystem,CAnimal> Inherid;
CSkillSubSystem()
{
m_currentSingSkillID =0; //
m_bDamage2HpFlag =false;
m_attackMusicRate =-1; //攻击的声音的概率
m_attackMusicID =-1; //攻击的声音的ID
};
const static int GATHER_SKILL_ID =999; //采集的技能ID用一个特殊的用于采集
//这里除了需要存盘的数据以外还加了技能精确到ms的cd以后可能还添加一些新的东西
typedef struct tagSkillData:
public ONESKILLDBDATA
{
TICKCOUNT tick; //技能的cd 时间
BYTE bEvent; //技能在什么事件下调用,用于怪物的需求
BYTE bMjMask; //秘籍的掩码,表示哪个效果是开启的
BYTE bIsClose; //技能是否已关闭
BYTE bIsPassive; //是否为被动技能
BYTE bPriority; //优先级
int nSingTime; //吟唱时间
int nCoolDownTime; //技能的冷却时间
unsigned int nLastDbCd; //DB里存储的CD时间用于存储
unsigned int nSkillType; //技能类型
tagSkillData(){memset(this,0,sizeof(*this)); } //清理
}SKILLDATA,*PSKILLDATA;
typedef struct tagSkillPointResult
{
PSKILLONERANGE pRange; //技能的指针
EntityVector& entityList; //实体列表
INT_PTR nPosX; //作用中心点的x
INT_PTR nPosY; //作用中心点的y
}SKILLPOINTRESULT,*PSKILLPOINTRESULT;
/*
* Comments:(),使使
* Param EntityHandle targetHandle:
* Param INT_PTR nActionID:
* Param INT_PTR nEffectID : id
* @Return INT_PTR: ,0
*/
INT_PTR NearAttack(EntityHandle targetHandle, INT_PTR nActionID,INT_PTR nEffectID);
void NoticeOneSkillData(PSKILLDATA pSkillData);
/**
* ()
*/
void SwitchSkill(INT_PTR nSkillID, bool nFlag);
void InitNextSkillFlag();
INT_PTR CheckNextSkillFlag(CEntity* pTargetEntity);
void UpdateNextSkillFlag();
INT_PTR OnBuffExpire(CDynamicBuff *pBuff);
/*
* Comments:
* Param INT_PTR nSkillID:ID
* Param INT_PTR nPosX: x
* Param INT_PTR nPosY:y
* bool bNoCd : cdcd的cd
* @Return INT_PTR:使0使
*/
INT_PTR LaunchSkill(INT_PTR nSkillID,INT_PTR nPosX = 0, INT_PTR nPosY = 0, bool bNoCd = false);
// 实际发射技能(即时/延时执行技能)
INT_PTR RealLaunchSkill(INT_PTR nSkillID,
CScene* pScene, INT_PTR nDir, INT_PTR nCurPosX, INT_PTR nCurPosY,
CEntity* pTargetEntity, INT_PTR nMousesPosX, INT_PTR nMousesPosY);
// 单范围技能作用(选择目标,并生效技能)
INT_PTR SkillApplyOneRange(int nSkillID, PSKILLDATA pSkillData,PSKILLONERANGE pRange,
CEntity* pTargetEntity,CScene* pScene,int nCurPosX,int nCurPosY,int nMousesPosX, int nMousesPosY, int nSpellDir);
// 单格技能效果
void SkillApplyOneGrid(PSKILLONERANGE pRange, EntityVector& entityList,
INT_PTR nPosX,INT_PTR nPosY,INT_PTR nSkillID,PSKILLDATA pSkillData,int nCurPosX,int nCurPosY);
/*
* Comments:
* Param PACTORDBDATA pData:
* @Return void:
*/
void Save(PACTORDBDATA pData);
//DB返回数据
VOID OnDbRetData(INT_PTR nCmd,INT_PTR nErrorCode,CDataPacketReader & reader );
/*
* Comments:
* Param INT_PTR nCmd:
* Param CDataPacketReader & packet:,
* @Return void:
*/
void ProcessNetData(INT_PTR nCmd,CDataPacketReader &packet );
//定时检查,用于检测吟唱的结束
VOID OnTimeCheck(TICKCOUNT nTick);
/*
* Comments:
* Param void * data:
* Param SIZE_T size:
* @Return bool:true,false
*/
bool Initialize(void *data,SIZE_T size);
//当等级满足了自动学习可以学习的技能
//void AutoLearnSkill();
//转职学习技能
void AutoLearnVocSkill(int nLevel = 1);
/*
* Comments:
* Param bool isPositive:
* @Return void:
*/
void EndSingSpell(bool isPositive =true);
/*
* Comments: 使
* Param INT_PTR nSkillID: ID
* Param nLevelID:
* Param bool bIsClose:
* Param bool bForce:
* Param bool bSort;
* @Return INT_PTR: 0
*/
INT_PTR LearnSkill(INT_PTR nSkillID, INT_PTR nLevelID =1,bool bIsClose=false, bool bForce=false, bool bSort = false);
//清空内存
inline void Destroy()
{
m_skillList.empty();
// m_entityList.empty();
}
//进入游戏
virtual void OnEnterGame();
// 进入场景
void OnEnterScene()
{
// 开启半月弯刀
SwitchSkill(4,1);
}
/*
* Comments:
* Param INT_PTR nSkillID: ID
* Param INT_PTR nLevelID:
* Param bool bForce:
* @Return INT_PTR: 0
*/
INT_PTR GetLearnSkillErrorCode(INT_PTR nSkillID, INT_PTR nLevelID, bool bForce=false);
/*
* Comments:
* Param INT_PTR nSkillID: ID
* @Return INT_PTR: 0
*/
inline INT_PTR GetSkillLevel(INT_PTR nSkillID)
{
for (INT_PTR i =0 ; i< m_skillList.count();i ++)
{
if(m_skillList[i].nSkillID ==nSkillID )
{
return m_skillList[i].nLevel;
}
}
return 0;
}
//计算被动技能的属性提升属性
VOID CalcAttributes(CAttrCalc &calc);
/*
* Comments:
* Param INT_PTR nSkillID:ID
* Param INT_PTR nSkillLevel:
* Param INT_PTR nMjMask:mask
* Param CAttrCalc & calc:
* @Return VOID:
*/
VOID CalcOneSkillAttr(INT_PTR nSkillID,INT_PTR nSkillLevel,CAttrCalc &calc);
//遗忘被动技能时的处理
void OnForgetPassSkill(const OneSkillData* pSkill, int nSkillLevel);
//判断是否启用技能CD
bool GetEnableCD();
//设置技能CD启用与否
void SetEnableCD(bool boEnable);
//计算2个实体的攻击距离= max( abs(x1-x2), abs(y1-y2) )
inline INT_PTR GetAttackDistance(CEntity * pStrEntity, CEntity * pTargetEntity)
{
if(pStrEntity == pTargetEntity) return 0;
int x1,y1,x2,y2;
pStrEntity->GetPosition(x1,y1);
pTargetEntity->GetPosition(x2,y2);
return __max( abs(x1-x2), abs(y1-y2));
}
/*
* Comments:
* Param INT_PTR nSkillID:ID
* @Return PONESKILLDBDATA:
*/
inline PSKILLDATA GetSkillInfoPtr(INT_PTR nSkillID)
{
for (INT_PTR i =0 ; i< m_skillList.count();i ++)
{
if(m_skillList[i].nSkillID ==nSkillID )
{
return &m_skillList[i];
}
}
return NULL;
}
//获取技能释放的时候和目标的距离怪物ai使用的,如果没有设定距离,返回-1
INT_PTR GetSpellTargetDistance( INT_PTR nSkillID, INT_PTR nSkillLevel);
//获取技能的列表
inline const CVector<SKILLDATA> & GetSkills(){return m_skillList;}
//获取技能的结果
inline CSkillResult * GetSkillResult(){return &m_skillResult;}
/*
* Comments:
* Param EntityHandle hTarget:
* Param INT_PTR nPosX: X
* Param INT_PTR nPosY: Y
* Param BYTE dir:
* @Return void:
*/
void GatherMonster(EntityHandle hTarget, int nPosX, int nPosY, BYTE nNewDir);
/*
* Comments:
* Param INT_PTR nSkillID: ID
* Param INT_PTR nLevelID:
* Param bool isCloseD:
* @Return void:
*/
void StartRealLearnSkill(INT_PTR nSkillID, INT_PTR nLevelID,bool isClose =false);
/*
* Comments:
* Param INT_PTR nSkillID:id
* Param bool isClose:
* @Return void:
*/
void SetSkillClose(INT_PTR nSkillID, bool isClose);
/*
* Comments:
* Param INT_PTR nSkillId: ID
* @Return bool:truefalse
*/
bool ForgetSkill(INT_PTR nSkillId);
/*
* Comments:
* Param INT_PTR nSkillId: ID
* @Return bool:truefalse
*/
bool ForgetSkillByClass(INT_PTR nSkillClass);
/*
* Comments:
* Param INT_PTR nSkillClass:
* @Return void:
*/
void CheckSkillOnConditionChange(INT_PTR nSkillClass);
/*
* Comments:CD
* Param INT_PTR nSkill:id
* @Return void:
*/
void DelSkillCdTemporary(INT_PTR nSkill);
//设置主动攻击别人的标志 myEntity 主动攻击 pEntity 被攻击
void SetInitiativeAttack(CEntity * myEntity,CEntity * pEntity);
//当跳转场景时停止采集
void StopGather();
//采集对脚本回调
bool GathMonsterCallBack(CEntity* pMonster);
//召唤宠物技能的数量发生变化
void SendPetSkillCountChange(INT_PTR nSkillId, INT_PTR nCount);
public:
/* 计算坐标旋转
* cX X
* cY Y
* nX X相对坐标
* nY Y相对坐标
* nDir (07)
* &nNewX X
* &nNewY Y
*/
static void PositionRotation(INT_PTR cX, INT_PTR cY, INT_PTR nX, INT_PTR nY, INT_PTR nDir, INT_PTR &nNewX, INT_PTR &nNewY);
//获取坐标
static void GetPosition(INT_PTR nX, INT_PTR nY, INT_PTR nDir, INT_PTR nStep, INT_PTR &nNewX, INT_PTR &nNewY);
//获取方向
static INT_PTR GetDirection(INT_PTR nX, INT_PTR nY, INT_PTR nTargetX, INT_PTR nTargetY);
/*
* Comments:,(nX,nY)(nRotateTargetX,nRotateTargetY)nNewXnNewY
* Param int nRotateTargetX:x
* Param int nRotateTargetY:y
* Param int nX:x
* Param int nY:y
* Param int & nNewX:x
* Param int & nNewY:y
* @Return void:
*/
static void AccurateRotation( INT_PTR nRotateTargetX,INT_PTR nRotateTargetY,INT_PTR nX,INT_PTR nY,INT_PTR &nNewX,INT_PTR &nNewY);
//发送已经学习的技能列表
void SendLearnSkill();
void OnLevelUp(int nLevel);
private:
/*
* Comments:
* Param INT_PTR nSkillId:ID
* Param INT_PTR nFlag:
* @Return void:
*/
void HandSetSkillOpen(INT_PTR nSkillId,INT_PTR nFlag);
//客户端同步一个技能的CD
void OnGetCd(INT_PTR nSkillID);
//设置默认技能
void SetDefaultSkill(INT_PTR nSkillID);
/*
* Comments: 广使
* Param INT_PTR nSkillID: ID
* Param INT_PTR nLevel:
* Param EntityHandle hHandle:
* Param INT_PTR nDir:
* INT_PTR INT_PTR nAuxParam :
* @Return :
*/
inline void BroadSpellSkill(INT_PTR nSkillID,INT_PTR nLevel,INT_PTR nDir,INT_PTR nAuxParam, unsigned short nX = 0, unsigned short nY = 0);
//释放技能的时候是否需要使用客户端上发的方向
//使用技能以及开始吟唱技能的客户端消息中增加了一个dir:Byte数据
//用于表示角色的施法面向。仅在目标handle为0 或 为角色自己的handle鼠标位置为角色自己的位置时有意义
INT_PTR CheckSpellTarget(INT_PTR nSkillID,EntityHandle nTarget, WORD &nDestX, WORD &nDestY, INT_PTR nDir);
//检测释放当前的技能能否通过特殊的buff的判断如果能通过返回0否则返回错误的ID
inline INT_PTR CheckSpecialBuff(const OneSkillData * pSkill);
bool CheckGather(class CMonster *pTarget, int nPosX, int nPosY, BYTE nDir);
void BroadGather();
//重设技能的CD时间
void ResetSkillCd( PSKILLDATA pSkill,const SKILLONELEVEL * pLevel);
//存盘的时候是否有长CD的技能如果都是短cd的技能考虑技能的cd不存盘
bool HasLongCdSkill();
//开始一个技能的CD
void HandStartSkillCD(INT_PTR nSkillId);
public:
CTimer<1000> m_singTimer; //吟唱定时器
private:
CVector<SKILLDATA> m_skillList ;//已经学习的技能列表
TICKCOUNT m_CommonCd; //公共的CD
CSkillCondition m_targetCondition; //目标筛选条件
CSkillResult m_skillResult;
WORD m_currentSingSkillID; //当前吟唱的技能的ID
WORD m_wReserver; //保留
WORD m_wMousePosX; //鼠标点中场景的点的x坐标
WORD m_wMousePosY; //鼠标点中场景的点的Y坐标
EntityHandle m_hSingTarget; //吟唱的目标
bool m_bDamage2HpFlag; //伤害输出给自己加血的开关w开启了造成了伤害才能给自己加血防止aoe一个技能加很多次血
BYTE m_attackMusicRate; //攻击的声音的概率
int m_attackMusicID; //攻击的声音的ID
public:
//跨服数据
void SendMsg2CrossServer(int nType);
//跨服数据初始化
VOID OnCrossInitData(std::vector<CSkillSubSystem::SKILLDATA>& skillData);
};