Files
mir_server/server/LogicServer/entitysystem/PetSystem.cpp

606 lines
14 KiB
C++
Raw Normal View History

2025-01-09 17:45:40 +08:00
#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;
}