Files
mir_server/server/LogicServer/entitysystem/PetSystem.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

606 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "PetSystem.h"
CPetSystem::~CPetSystem()
{
Destroy();
}
VOID CPetSystem::ProcessNetData(INT_PTR nCmd,CDataPacketReader &packet )
{
if(m_pEntity ==NULL) return;
if(m_pEntity->GetHandle().GetType() != enActor) return;
bool hasSendTipmsg =false;
int nCurrentStatus =0;
if(nCmd == cPetSetBattleState) //改变宠物的出战状态
{
CPet * pPet;
unsigned char nStatus = 0;
packet >> nStatus;
for(INT_PTR i=0; i< m_pets.count(); i++)
{
pPet= (CPet*)GetEntityFromHandle(m_pets[i].handle);
if(pPet != NULL)//&& pPet->GetLiveTime() == 0)
{
nCurrentStatus = pPet->GetBattleStatus();
if(nCurrentStatus == CPet::PET_BATTLE_STATUE_STAY && nStatus == CPet::PET_BATTLE_STATUE_FOLLOW)
{
pPet->SetBattleStatus(CPet::PET_BATTLE_STATUE_FOLLOW); //设置移动状态
}
else if(nCurrentStatus == CPet::PET_BATTLE_STATUE_FOLLOW && nStatus == CPet::PET_BATTLE_STATUE_STAY)
{
pPet->SetTarget(0);
pPet->SetBattleStatus(CPet::PET_BATTLE_STATUE_STAY);
if ( pPet->GetMoveSystem()->GetMotionType() == CMovementSystem::mtMotionTypeFollow )
{
pPet->GetMoveSystem()->MoveFollow(m_pEntity,1);
}
}
}
}
}
else if(nCmd == cRecallPet)
{
RecallPet();
}
else if(nCmd == cRemoveBattlePet)
{
RemoveBattlePet();
}
}
void CPetSystem::RecallPet()
{
CPet * pPet = NULL;
INT_PTR nPox = m_pEntity->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nPoy = m_pEntity->GetProperty<int>(PROP_ENTITY_POSY);
INT_PTR nDir = (m_pEntity->GetProperty<int>(PROP_ENTITY_DIR) + 4) & 7; //玩家反方向
INT_PTR nNewPox = nPox, nNewPoy = nPoy;
CEntityGrid::NewPosition(nNewPox,nNewPoy,nDir,1);
CFuBen * pFb = m_pEntity->GetFuBen(); //副本的指针
CScene * pScene = m_pEntity->GetScene(); //场景指针
if (!pScene) return;
for (INT_PTR i = 0; i < m_pets.count(); i++)
{
pPet = (CPet *)GetEntityFromHandle(m_pets[i].handle);
if (pPet != NULL)// && pPet->GetLiveTime() == 0)
{
pPet->SetTarget(0);
CFuBen * pLasfb = pPet->GetFuBen();
CScene * pLastScene = pPet->GetScene();
bool result = pFb->Enter(pPet,pScene->GetSceneId(),nNewPox,nNewPoy,0,0,0,0,-1,pLastScene,pLasfb);
if (!result)
{
pFb->Enter(pPet,pScene->GetSceneId(),nPox,nPoy,0,0,0,0,-1,pLastScene,pLasfb);
}
//pPet->SetBattleStatus(CPet::PET_BATTLE_STATUE_FOLLOW);
// if ( pPet->GetMoveSystem()->GetMotionType() != CMovementSystem::mtMotionTypeFollow )
// {
// pPet->GetMoveSystem()->MoveFollow(m_pEntity);
// }
// if (pPet->MoveToEntity(m_pEntity,0,0,1) == false)
// if (pPet->MoveToEntity(m_pEntity,0,0,2) == false)
// if (pPet->MoveToEntity(m_pEntity,0,0,3) == false)
// pPet->MoveToEntity(m_pEntity,0,0,0);
}
}
}
void CPetSystem::RemoveBattlePet()
{
if (m_pEntity == NULL || m_pEntity->GetType() != enActor || ((CActor*)m_pEntity)->IsDeath())
{
return;
}
Destroy();
}
//攻击别人
void CPetSystem::OnAttackOther(CAnimal * pEntity)
{
if (!pEntity || pEntity->IsDeath())
{
return;
}
CPet * pPet;
for(INT_PTR i=0; i< m_pets.count(); i++)
{
pPet= (CPet*)GetEntityFromHandle(m_pets[i].handle);
if ( pPet )
{
CEntity* pTarget = GetEntityFromHandle(pPet->GetTarget());
if ( pPet->GetAI() && //pPet->GetBattleStatus() != CPet::PET_BATTLE_STATUE_STAY &&
//pPet->GetLiveTime() == 0 &&
(!pTarget || pTarget->GetHandle() != pEntity->GetHandle()) )
{
pPet->GetAI()->AttackedBy(pEntity);
}
}
}
}
//被攻击
void CPetSystem::OnAttacked(CAnimal *pEntity)
{
if (!pEntity || pEntity->IsDeath())
{
return;
}
CPet * pPet;
for(INT_PTR i=0; i< m_pets.count(); i++)
{
pPet= (CPet*)GetEntityFromHandle(m_pets[i].handle);
if ( pPet )
{
CEntity* pTarget = GetEntityFromHandle(pPet->GetTarget());
if ( pPet->GetAI() &&// pPet->GetBattleStatus() != CPet::PET_BATTLE_STATUE_STAY &&
//pPet->GetLiveTime() == 0 &&
(!pTarget || pTarget->GetHandle() != pEntity->GetHandle()))
{
pPet->GetAI()->AttackedBy(pEntity);
}
}
}
}
//死亡
void CPetSystem::OnDeath()
{
Destroy(); //把所有的宠物干掉
}
//Runtime
VOID CPetSystem::OnTimeCheck( TICKCOUNT curTick )
{
if (!m_pEntity || m_pEntity->GetType() != enActor)
{
return;
}
if(m_10Sec.CheckAndSet(curTick, true))
{
unsigned int nNow = GetGlobalLogicEngine()->getMiniDateTime();
INT_PTR nLen = m_pets.count();
for (INT_PTR i = nLen -1; i >=0; i--)
{
CEntity *pEntity =GetEntityFromHandle(m_pets[i].handle); //实体的句柄
if(pEntity && !((CPet*)pEntity)->IsLiveTime(nNow))
{
char sPetName[128];
strncpy(sPetName, pEntity->GetEntityName(), sizeof(sPetName));
if(RemovePet(m_pets[i].nId))
{
char sText[1024] = {0};
LPCTSTR sNotice = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpPetRemove);
sprintf_s(sText, sizeof(sText), sNotice, sPetName);
((CActor*)m_pEntity)->SendTipmsg(sText, ttFlyTip);
}
}
}
}
}
bool CPetSystem::AddPet(INT_PTR PetId,INT_PTR nLevel, INT_PTR nAiId,INT_PTR nLiveSecs, INT_PTR nInheritPercent,INT_PTR nSkillId,int nTarPosX,int nTarPosY)
{
CScene *pScene = m_pEntity->GetScene();
if(pScene ==NULL) return false;
const PMONSTERCONFIG pConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(PetId);
if(pConfig ==NULL)
{
OutputMsg(rmError,"no pet id=%d",PetId);
return false;
}
if (m_pEntity->HasState(esStateDeath))
{
OutputMsg(rmNormal, _T("在创建道士宠物时,玩家是死亡状态"));
return false;
}
INT_PTR nJobCount = GetJobPetCount();
if (nLiveSecs == 0 && nJobCount >= 1)
{
OutputMsg(rmNormal, _T("这里手动判断道士宠物是否大于2个目前来看已大于2个啦"));
return false;
}
//一共48个从里边到外边遍历找到一个合适的位置
static int s_matrix[][2] =
{
// 原点
{0,0},
//第1圈8个
{0,-1},
{0,-2},
{0,-3},
{-1,-1},
{-1,-2},
{-1,-3},
{1,-1},
{1,-2},
{1,-3},
//第2圈16个
{-2,-1},
{-2,-2},
{-2,-3},
{2,-1},
{2,-2},
{2,-3},
{-1,0},
{-2,0},
{1,0},
{2,0},
{0,1},
{-1,-1},
{-2,-1},
{1,1},
{2,1},
{0,2},
//第3圈24个
{-1,-2},
{-2,-2},
{1,2},
{2,2},
{0,3},
{-1,-3},
{-3,-2},
{1,3},
{2,3},
{0,0},
};
int nPosX,nPosY;
m_pEntity->GetPosition(nPosX,nPosY); //获取玩家当前的位置
if (nTarPosX && nTarPosY)
{
nPosX = nTarPosX;
nPosY = nTarPosY;
}
//优先刷在自己的前面,如果自己的前面有怪物了,则刷在旁边的一个点
INT_PTR nNewRelX,nNewRealY; //相对坐标x,y
int nDir = m_pEntity->GetProperty<int>(PROP_ENTITY_DIR);
//计算出玩家正前方一个点新坐标
//在周围找一个可以刷的地方
INT_PTR nDX, nDY;
//这里先轮一次如果旁边48个格子都有了那么进行第2次遍历不过这种情况是比较少的
for(INT_PTR j=0; j< ArrayCount(s_matrix); j++)
{
CSkillSubSystem::PositionRotation( 0, 0,s_matrix[j][0], s_matrix[j][1], nDir, nNewRelX, nNewRealY);
nDX = nPosX + nNewRelX;
nDY = nPosY + nNewRealY;
if(pScene->CanCross(enPet,nDX,nDY,false,false))
{
goto lb_mob;
}
}
return false;
lb_mob:
unsigned int nId = GenPetId(); //产生一个宠物的id
//创建一个宠物
CEntity *pEntity = pScene->CreateEntityAndEnterScene(pConfig->nEntityId,enPet,nDX,nDY,nLevel,m_pEntity);
if(pEntity ==NULL) return false;
CPet *pPet = (CPet*) pEntity;
char sAllName[512];
_asncpytA( sAllName, pConfig->szName);
// if(pEntity->GetAttriFlag().ShowNameByNumber == false)//宠物也根据配置,不显示最后的数字
// {
// INT_PTR nLen = strlen(sAllName);
// if (nLen > 2)
// {
// if (sAllName[nLen-1] >='0' && sAllName[nLen-1] <='9')
// {
// sAllName[nLen-1]=0;
// }
// if (sAllName[nLen - 2] >= '0' && sAllName[nLen - 2] <='9')
// {
// sAllName[nLen - 2] = 0;
// }
// }
// }
//sprintf_s(sAllName,sizeof(sAllName),"%s\\%s",sAllName, m_pEntity->GetEntityName());
// pPet->ChangeName(sAllName);
pPet->SetPetId(nId);
pEntity->SetEntityName(sAllName);
pEntity->SetProperty<int>(PROP_ENTITY_MODELID,pConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ICON, 1);
//pEntity->SetProperty<int>(PROP_CREATURE_LEVEL,nLevel);
pPet->SetMaster(m_pEntity);
pPet->SetInheritPercent((int)nInheritPercent);
pPet->GetPropertySystem().ResertProperty();//要计算人物继承属性所以设置master之后需要重新计算
pPet->InitAi((int)nAiId);
if(NULL == pPet->GetAI())
{
GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(pEntity->GetHandle(),false);
return false;
}
pEntity->SetInitFlag(true);//如果是创建备用的这个设置成false
if( pPet->GetAI())
pPet->GetAI()->RefreshSkillDis(); //重新刷新技能
//pPet->GetAttriFlag().DenyUseNearAttack =true; //宠物都不肉搏
pPet->SetLiveTime((int)nLiveSecs);
int nAttackSpd = pPet->GetProperty<int>(PROP_CREATURE_ATTACK_SPEED);
if(nAttackSpd > 0)
{
pPet->SetAttackInterval(nAttackSpd);
}
if (nLiveSecs == 0 && !m_pEntity->HasState(esStateOwnPet))
{
m_pEntity->AddState(esStateOwnPet);
}
CSkillSubSystem & skillSystem = pPet->GetSkillSystem();
const CVector<CSkillSubSystem::SKILLDATA> & skills= skillSystem.GetSkills();
INT_PTR nCount = skills.count();
for(INT_PTR i=0; i< nCount;i++)
{
CSkillSubSystem::SKILLDATA *pSkill = &skills[i];
if(pSkill->bEvent == mSkillEventBorn)
{
skillSystem.LaunchSkill(pSkill->nSkillID);
}
}
//获得宠物的升级经验
int nLevelUpExp =GetLogicServer()->GetDataProvider()->GetPetProvider().GetMaxExp(nLevel,0);
PETDATA data;
data.nConfigId = (int)pConfig->nEntityId;
data.nId = nId; //宠物的ID
data.handle = pEntity->GetHandle();
data.nSkillId = (int)nSkillId;
m_pets.add(data);
SendPetCount();
int nStatus = ((CActor*)m_pEntity)->GetProperty<unsigned int>(PROP_ACTOR_PET_STATUS);
pPet->SetBattleStatus(nStatus);
SendPetSkillCountChange(data.nConfigId, data.nSkillId);
return true;
}
void CPetSystem::Destroy()
{
RemoveAllPets();
}
void CPetSystem::SendPetCount()
{
if (m_pEntity && m_pEntity->IsInited())
{
CActorPacket pack;
CDataPacket &data=((CActor*)m_pEntity)->AllocPacket(pack);
data << (BYTE)(enPetSystemID) << (BYTE)sPetCount << (BYTE)GetPetCount();
pack.flush();
}
}
void CPetSystem::RemoveAllPets()
{
INT_PTR nCount = m_pets.count();
for (INT_PTR i = nCount - 1; i > -1; --i)
{
RemovePetByPos(i);
}
m_pets.clear();
SendPetCount();
}
void CPetSystem::OnActorLoginOut()
{
GetGlobalLogicEngine()->GetEntityMgr()->CachePet(m_pEntity,&m_pets,10*60*1000);
}
void CPetSystem::OnEnterGame()
{
GetGlobalLogicEngine()->GetEntityMgr()->UnCachePet(m_pEntity,&m_pets,m_pEntity->GetScene());
}
void CPetSystem::OnEnterScene()
{
int nActorType = m_pEntity->GetHandle().GetType();
if (nActorType == enActor)
{
if (((CActor*)m_pEntity)->OnGetIsTestSimulator()
|| ((CActor*)m_pEntity)->OnGetIsSimulator())
{
return;
}
}
SendPetCount();
}
unsigned int CPetSystem::GenPetId()
{
unsigned int ID=0;
for(INT_PTR i=0; i< m_pets.count();i ++)
{
if(m_pets[i].nId > ID)
{
ID = m_pets[i].nId;
}
}
ID ++;
return ID;
}
void CPetSystem::SendPetSkillCountChange(int nPetConfigId, int nSkillId)
{
//改用技能通知,用来客户端挂机检查
INT_PTR nCount = GetPetCountByConfigId((int)nPetConfigId);
m_pEntity->GetSkillSystem().SendPetSkillCountChange(nSkillId,nCount);
}
void CPetSystem::RemovePetByPos(INT_PTR nPos)
{
PPETDATA pPetData = GetPetData(nPos);
if (!pPetData)
{
return;
}
EntityHandle petHandle = pPetData->handle;
int nPetConfigId = pPetData->nConfigId;
int nSkillId = pPetData->nSkillId;
m_pets.remove(nPos);//注意pPetData指向已经变了,不能直接用
CEntity *pEntity =GetEntityFromHandle(petHandle); //实体的句柄
if(pEntity)
{
if (pEntity->GetType() == enPet)
{
SendPetSkillCountChange(nPetConfigId, nSkillId);
}
GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(petHandle, true); //玩家下线的时候要把自己创建的宠物删除
}
if (m_pets.count() == 0 && m_pEntity->HasState(esStateOwnPet))
{
m_pEntity->RemoveState(esStateOwnPet);
}
SendPetCount();
}
bool CPetSystem::RemovePet(int nPetId)
{
if (m_pEntity == NULL || m_pEntity->GetType() != enActor || ((CActor*)m_pEntity)->IsDeath())
{
return false;
}
INT_PTR nPos = GetPetPos(nPetId) ;
if (nPos <0) return false;
RemovePetByPos(nPos);
return true;
}
INT_PTR CPetSystem::RemoveAllPetByConfigId(int nConfigId)
{
if (m_pEntity == NULL || m_pEntity->GetType() != enActor || ((CActor*)m_pEntity)->IsDeath())
{
return 0;
}
INT_PTR nRemoveCount = 0;
for (INT_PTR i = m_pets.count() - 1; i > -1; --i)
{
PETDATA &data = m_pets[i];
if (data.nConfigId != nConfigId)
{
continue;
}
RemovePetByPos(i);
nRemoveCount++;
}
SendPetCount();
return nRemoveCount;
}
int CPetSystem::GetPetCountByConfigId( int nPetId )
{
int nCount = 0;
for(INT_PTR i=0; i< m_pets.count();i ++)
{
if(m_pets[i].nConfigId == nPetId)
{
nCount++;
}
}
return nCount;
}
int CPetSystem::GetPetCountBySkillId(int nSkillId)
{
int nCount = 0;
for(INT_PTR i=0; i< m_pets.count();i ++)
{
if(m_pets[i].nSkillId == nSkillId)
{
nCount++;
}
}
return nCount;
}
int CPetSystem::GetJobPetCount()
{
int nCount = 0;
CPet * pPet = NULL;
INT_PTR nAllPetCount = m_pets.count();
for (INT_PTR i = 0; i < nAllPetCount; i++)
{
pPet = (CPet *)GetEntityFromHandle(m_pets[i].handle);
if (pPet != NULL && pPet->GetLiveTime() == 0)
{
nCount++;
}
}
return nCount;
}
CPet *CPetSystem::GetTopJobPet()
{
CPet *pPet = NULL, *pRetPet = NULL;
INT_PTR nAllPetCount = m_pets.count();
INT_PTR nCurLevel = 0, nMaxLevel = 0;
for (INT_PTR i = 0; i < nAllPetCount; i++)
{
pPet = (CPet *)GetEntityFromHandle(m_pets[i].handle);
if (pPet == NULL || pPet->GetLiveTime() != 0)
{
continue;
}
nCurLevel = pPet->GetProperty<int>(PROP_CREATURE_LEVEL);
if (nCurLevel > nMaxLevel)
{
nMaxLevel = nCurLevel;
pRetPet = pPet;
}
}
return pRetPet;
}
bool CPetSystem::IsMyJobPet( CPet * pOutPet )
{
INT_PTR nAllPetCount = m_pets.count();
for (INT_PTR i = 0; i < nAllPetCount; i++)
{
CPet * pPet = (CPet *)GetEntityFromHandle(m_pets[i].handle);
if (pPet == NULL || pPet->GetLiveTime() != 0)
{
continue;
}
if (pOutPet == pPet )
{
return true;
}
}
return false;
}