#include "StdAfx.h" #include "EntityGrid.h" #include "Scene.h" #include "../LogicServer.h" using namespace wylib::container; bool binarySearch(int* vList, INT_PTR nCount,INT_PTR nValue) { INT_PTR low = 0; INT_PTR high = nCount - 1; while (low <= high) { INT_PTR mid = ((UINT_PTR) (low + high)) >> 1; int nMidValue = vList[mid]; if (nMidValue< nValue) low = mid + 1; else if (nMidValue > nValue) high = mid - 1; else return true; // key found } return false; // key not found. } CScene::CScene() :m_AStar() { m_vRefreshMonster = NULL; m_pMapData = NULL; m_pSceneData = NULL; m_Grid.SetScene(this); m_pMapAreaTable = NULL; m_pTelePortTable = NULL; m_restTime = 0; m_nRefreshtime = 0; #ifndef MONSTER_MANAGER_BY_SCENE #else m_MonInterator = m_MonsterList.end(); #endif } CScene::~CScene() { //释放所有的实体 m_Grid.Release(); m_Grid.SetScene(this); if (m_vRefreshMonster) { GFreeBuffer(m_vRefreshMonster); m_vRefreshMonster = NULL; } ReleaseConfig(); #ifndef MONSTER_MANAGER_BY_SCENE #else m_MonsterList.clear(); m_MonInterator = m_MonsterList.end(); #endif } BOOL CScene::Init(SCENECONFIG* pData,CAbstractMap* pMapData,CFuBen* pFb,CObjectAllocator* dataAlloc,bool boRun) { SF_TIME_CHECK(); //检测性能 DECLARE_TIME_PROF("CScene::Init"); m_pSrcSceneData = pData; // 复制一份场景配置文件(主要是区域属性) CloneSceneConfig(pData); // 刷怪配置 if (m_vRefreshMonster) { GFreeBuffer(m_vRefreshMonster); m_vRefreshMonster = NULL; } SetFuBen(pFb); // 获取对应的地图数据(场景宽、高 和网格信息) m_pMapData = pMapData; m_nWidth = pMapData->getWidth(); m_nHeight = pMapData->getHeight(); m_Grid.Init((int)m_nHeight,(int)m_nWidth); m_Grid.SetScene(this); m_AStar.initFromMap(m_pMapData); #ifndef MONSTER_MANAGER_BY_SCENE #else m_MonsterList.clear(); m_MonInterator = m_MonsterList.end(); #endif return TRUE; } void CScene::CreateNpcTransport(bool boRun) { if (m_pSceneData) { CreateNpc(m_pSceneData,boRun); // 创建npc CreateTeleport(); // 创建传送门 } } BOOL CScene::Reset() { //m_Grid要保证角色和怪物清理出去 //m_Grid.Reset(); //删除场景的实体 //NPC不删除 CLinkedNode *pNode; CLinkedListIterator it; CEntityManager* pMgr = GetGlobalLogicEngine()->GetEntityMgr(); //销毁怪物 #ifndef MONSTER_MANAGER_BY_SCENE it.setList(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { pMgr->DestroyEntity( pNode->m_Data); } m_MonsterList.clear(); #else // std::map::iterator iter = m_MonsterList.begin(); // for (; iter != m_MonsterList.end(); ++iter) // { // pMgr->DestroyEntity( iter->first ); // } std::map::iterator iter = m_MonInterator; while (iter != m_MonsterList.end()) { pMgr->DestroyEntity( iter->first );//删除时,会触发 CScene::RemoveEntity, m_MonInterator自增; if (iter == m_MonInterator) break; iter = m_MonInterator; } m_MonsterList.clear(); m_MonInterator = m_MonsterList.end(); #endif //删除掉落物品 it.setList(m_dropItemList); for (pNode = it.first(); pNode; pNode = it.next()) { pMgr->DestroyEntity( pNode->m_Data); } m_dropItemList.clear(); //删除火 it.setList(m_fireList); for (pNode = it.first(); pNode; pNode = it.next()) { pMgr->DestroyEntity( pNode->m_Data); } m_fireList.clear(); //重置npc it.setList(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pMgr->GetEntity(pNode->m_Data); if (pEntity != NULL && pEntity->GetType() == enNpc) { ((CNpc*)pEntity)->ResetScript(); pEntity->SetInitFlag(false); } } //重新copy配置文件 CloneSceneConfig(m_pSrcSceneData); m_restTime = 0; //遍历所有NPC,调用reset //m_PlayList要清空 m_PlayList.clear(); m_petList.clear(); m_heroList.clear(); m_DeathList.clear(); return TRUE; } void CScene::DestroySceneEntity() { } void CScene::OnReuse() { CLinkedNode *pNode; CLinkedListIterator it(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(pNode->m_Data); if (pEntity != NULL && pEntity->GetType() == enNpc) { pEntity->SetInitFlag(true);//使npc的logicrun能执行 } } if (!m_vRefreshMonster) { m_vRefreshMonster = (REFRESHVALUE*)GAllocBuffer(sizeof(REFRESHVALUE)*(m_pSceneData->vRefreshList.nCount)); } ResetRefreshList(&m_pSceneData->vRefreshList); } void CScene::Clone(CScene& DstScene,bool boRun) { m_Grid.SetScene(this); //clone刷怪点信息 if (m_pSceneData && boRun) { DstScene.SetRefreshList(&m_pSceneData->vRefreshList); } DstScene.m_pMapAreaTable = this->m_pMapAreaTable; DstScene.m_pTelePortTable = this->m_pTelePortTable; } bool CScene::CanPassScence(CActor* pActor) { if( !pActor ) return false; return true; } bool CScene::CanEnter(CActor* pActor,INT_PTR x,INT_PTR y,bool bState) { if(SCENEAREA* pArea = GetAreaAttri(x,y)) { int nLevel = pActor->GetProperty(PROP_CREATURE_LEVEL); bool boGm = pActor->GetGmLevel() > 0; //进入场景的最低等级 if (HasMapAttribute(x,y,aaSceneLevel,pArea) && !boGm) { AreaAttri& attri = pArea->attri[aaSceneLevel]; if(attri.pValues) { int nCircle = 0; if ( attri.nCount > 1 && attri.pValues[1] ) { nCircle = attri.pValues[1]; } if(!pActor->CheckLevel(attri.pValues[0], nCircle)) { if(bState) //pActor->SendOldTipmsgFormatWithId(tpUnderMinLevel,ttDialog,nCircle,attri.pValues[0]); pActor->SendTipmsgWithId(tmLevelLowernoenter,tstUI); return false; } } } //进入场景的最高等级 if (HasMapAttribute(x,y,aaSceneMaxLevel,pArea) && !boGm) { AreaAttri& attri = pArea->attri[aaSceneMaxLevel]; if(attri.pValues) { if(nLevel > attri.pValues[0]) { if(bState) //pActor->SendOldTipmsgFormatWithId(tpUpMaxLevel,ttDialog,attri.pValues[0]); pActor->SendTipmsgWithId(tmLevelExceednoenter,tstUI); return false; } } } } // if(IsTelePort(x,y) == true) //传过去点是传送门 // { // bool boTelePort = false; // int nIndex = m_pTelePortTable[y*m_nWidth+x]; // if (GetSceneData() && nIndex <= GetSceneData()->TeleportList.nCount) // { // TeleportConfig& config = GetSceneData()->TeleportList.pList[nIndex -1]; // CEntity * pEntity = GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(config.nHandle); // if (pEntity != NULL) // { // boTelePort = pEntity->GetAttriFlag().DenySee; // } // } // if (!boTelePort) // { // OutputMsg(rmError, _T("::%s want to MoveTo telepot(posX:%d posY:%d)"), pActor->GetEntityName(), x, y); // return false; // } // } return true; } bool CScene::EnterScene(CEntity * pEntity,INT_PTR nPosX,INT_PTR nPosY, int nType,int nValue, int nParam) { if (pEntity == NULL) return false; // 判断是否同屏传送 int nCurPosX = 0,nCurPosY = 0; pEntity->GetPosition(nCurPosX, nCurPosY); //pLastScence有可能是NULL CFuBen *pLastFuben = pEntity->GetFuBen(); //获取实体上一个的副本 CScene *pLastScence = pEntity->GetScene(); //获取实体上一个的场景 bool bState = true; if (pLastScence == NULL) bState = false; INT_PTR nEntityType = pEntity ->GetType(); if (enNpc == nEntityType && pEntity->IsInited()) { OutputMsg(rmError, _T("%s:npc[%s] try to enter to scene, X:%d,Y:%d, is Stoped"), __FUNCTION__, pEntity->GetEntityName(),(int)nPosX,(int)nPosY); return false; } bool isActor = nEntityType == enActor; // 进入判断 bool bCanAlwaysEnter = false; INT_PTR nDir = -1; if (pEntity->IsMonster()) { PMONSTERCONFIG pConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(pEntity->GetProperty(PROP_ENTITY_ID)); if (pConfig != NULL) { EntityFlags* pFlag = pConfig->pflags; if (pFlag->CanAlwaysEnter) bCanAlwaysEnter = true; nDir = (INT_PTR)(pConfig->btDir != 255? pConfig->btDir : -1); } } else if(nEntityType == enActor || nEntityType == enHero || nEntityType == enPet) { bCanAlwaysEnter = true; //玩家进入场景是要强制进入的 } if(!isActor && m_Grid.GetMoveablePoint(pEntity,this,nPosX,nPosY,nPosX,nPosY,bCanAlwaysEnter) == false) { OutputMsg(rmError, _T("%s:Entity[%s] Grid can't get moveable point; X:%d,Y:%d"), __FUNCTION__, pEntity->GetEntityName(),(int)nPosX,(int)nPosY); return false; } else { if (!m_Grid.CanAddEntity(pEntity,nPosX,nPosY,true,bCanAlwaysEnter)) { OutputMsg(rmError, _T("%s:Entity[%s] 当前点不能站人; X:%d,Y:%d"), __FUNCTION__, pEntity->GetEntityName(),(int)nPosX,(int)nPosY); return false; } else if( isActor && !CanEnter( (CActor*)pEntity,nPosX,nPosY,bState)) { OutputMsg(rmError, _T("%s:Actor[%s] 不满足进入场景条件; X:%d,Y:%d"), __FUNCTION__, pEntity->GetEntityName(),(int)nPosX,(int)nPosY); return false; } } // 先发一次属性变化 if (isActor) ((CActor *)pEntity)->GetObserverSystem()->UpdateActorEntityProp(); // 跨场景及跨格子处理 CFuBen* pFb = pEntity->GetFuBen(); int nOldX=0,nOldY=0; pEntity->GetPosition(nOldX, nOldY); if(pLastScence != this) { bool CanPass = true; if( isActor ) { CanPass = CanPassScence((CActor*)pEntity); } if(CanPass == false) return false; if (pLastScence) pLastScence->ExitScene(pEntity);//会在原来的网格删除这个 if (m_Grid.MoveTo(pEntity,nPosX,nPosY,true,bCanAlwaysEnter) != seSucc) { OutputMsg(rmNormal, _T("------Grid::MoveTo failed %s posX:%d posY:%d"), pEntity->GetEntityName(), (int)nPosX, (int)nPosY); return false; } if (pEntity->IsInited() && nEntityType == enPet) { if (CActor* pMaster = ((CPet *)pEntity)->GetMaster()) { ((CActor *)pMaster)->GetObserverSystem()->EntityAppear(pEntity->GetHandle(), pEntity); } } } else { if (/*isInObserverList || */(pLastFuben == GetFuBen() && pLastScence == this)) { if (!((CAnimal*)pEntity)->GetMoveSystem()->InstantMove(nPosX,nPosY,1,nType,nValue)) return false; } else { if (m_Grid.MoveTo(pEntity,nPosX,nPosY,false,bCanAlwaysEnter) != seSucc) return false; } } if (isActor && (pLastFuben != GetFuBen() || pLastScence != this)) { ((CActor *)pEntity)->OnEnterScene(nType, nValue, nParam); } // 记录实例链表 if(pLastScence != this) { switch(nEntityType) { case enActor: m_PlayList.linkAtLast(pEntity->GetHandle()); if(pLastScence) ((CActor *)pEntity)->NeedBroadSceneEffect(GetSceneId(),pLastScence->GetSceneId()); break; case enMonster: case enGatherMonster: ((CMonster*)pEntity)->SetBornPoint(nPosX,nPosY); pEntity->SetDir(nDir); #ifndef MONSTER_MANAGER_BY_SCENE m_MonsterList.linkAtLast(pEntity->GetHandle()); #else m_MonsterList[pEntity->GetHandle()] = (CMonster*)pEntity; #endif if (m_pFb) { m_pFb->AddMonsterTotal();//统计副本中的怪物总数 } break; case enTransfer: m_TeleportList.linkAtLast(pEntity->GetHandle()); break; case enNpc: m_NpcList.linkAtLast(pEntity->GetHandle()); break; case enPet: m_petList.linkAtLast(pEntity->GetHandle()); break; case enHero: m_heroList.linkAtLast(pEntity->GetHandle()); break; case enDropItem: m_dropItemList.linkAtLast(pEntity->GetHandle()); break; case enFire: m_fireList.linkAtLast(pEntity->GetHandle()); break; } } CFuBen *pFB = GetFuBen(); if (pLastScence != this && pFB) pFB->UpdateFbPlayerCountAndAverageLevel(pEntity, true); // // 事件处理 // if (pFB && pFB->IsFb() && nEntityType != enNpc && pLastFuben != GetFuBen()) // { // if (pLastScence != this) // pFB->UpdateFbPlayerCountAndAverageLevel(pEntity, true); // // 进入副本事件 // CScriptValueList paramList; // paramList << (int)CFubenSystem::enOnEnter; // paramList << (int)pFB->GetConfig()->nFbConfType; // paramList << (int)pFB->GetFbId(); // paramList << (int)pFB->GetConfig()->nFbEnterType; // paramList << pFB; // paramList << (int)GetSceneId(); // paramList << pEntity; // if(!GetGlobalLogicEngine()->GetGlobalNpc()->GetScript().CallModule("FubenDispatcher","OnEvent", paramList, paramList, 1)) // { // OutputMsg(rmError,"[FubenSystem] OnEvent OnEnter 错误,副本ID=%d,副本类型=%d !",pFB->GetFbId(),pFB->GetConfig()->nFbConfType); // } // } return true; } bool CScene::EnterSceneRandPt(CEntity *pEntity, INT_PTR nPosX, INT_PTR nPosY, INT_PTR nWeight, INT_PTR nHeight, int nType , int nValue, int nParam) { if (0 == nWeight && 0 == nHeight) { return EnterScene(pEntity, nPosX, nPosY, nType,nValue,nParam); } //选择随机点传送 int nMinX = (int)__max(nPosX - nWeight, 0); int nMaxX = (int)__min(nPosX + nWeight, m_Grid.m_nCol-1); int nMinY = (int)__max(nPosY - nHeight, 0); int nMaxY = (int)__min(nPosY + nHeight, m_Grid.m_nRow-1); int nX, nY = 0; if (!GetRandomPoint(pEntity, nMinX, nMinY, nMaxX, nMaxY, nX, nY)) { //OutputMsg(rmError, "%s error! Can not find pos to move!", __FUNCTION__); //return false; nX = (int)nPosX; nY = (int)nPosY; } return EnterScene(pEntity, nX, nY,nType,nValue,nParam); } void CScene::ExitScene(CEntity * pEntity) { INT_PTR nEntityType = pEntity->GetType(); unsigned int nBornPointID; int nEntityId; CFuBen *pFuBen = ((CActor*)pEntity)->GetFuBen(); int nFubenId = 0; if( pFuBen ) { nFubenId = pFuBen->GetFbId(); } switch(nEntityType) { case enActor: ((CActor*)pEntity)->OnPreExitScene(); //exit之前,要做 RemoveEntity(pEntity); break; //新的实体 case enNpc: case enPet: case enHero: case enFire: RemoveEntity(pEntity); break; case enMonster: case enGatherMonster: //当怪物(实体)死亡时,通知刷怪点 nBornPointID = pEntity->GetProperty(PROP_MONSTER_BORNPOINT); nEntityId = pEntity->GetProperty(PROP_ENTITY_ID); if (m_pSceneData && nBornPointID >=0 && nBornPointID < (unsigned int)m_pSceneData->vRefreshList.nCount) { REFRESHCONFIG* rc = m_pSceneData->vRefreshList.pList + nBornPointID; if (rc->nEntityId == nEntityId)//怪物id要相等 { REFRESHVALUE* refresh = m_vRefreshMonster+ nBornPointID; if(refresh->nCurrCount >0) { refresh->nCurrCount--; } } } RemoveEntity(pEntity); break; } m_Grid.DeleteEntity(pEntity); if (pEntity->GetType() == enActor) { if (CAnimal* pAnimal = dynamic_cast(pEntity)) pAnimal->GetObserverSystem()->ClearEntityList(); } } void CScene::RefreshMonster() { TICKCOUNT nCurrent = GetLogicCurrTickCount(); //当前的tickcount int nCount = m_pSceneData ? m_pSceneData->vRefreshList.nCount:0; CMonsterProvider& md = GetLogicServer()->GetDataProvider()->GetMonsterConfig(); INT_PTR nUserCount = GetGlobalLogicEngine()->getOnlinceCount(); for(int i = 0; i < nCount; i++) { //检查每个刷怪点 REFRESHCONFIG* pRefreshConf = m_pSceneData->vRefreshList.pList + i; // 刷怪点静态配置 REFRESHVALUE* pData = m_vRefreshMonster + i; // 刷怪点动态数据(当前刷怪点下次刷怪时间、当前怪物数量) PMONSTERCONFIG pMonsterConfig = md.GetMonsterData(pRefreshConf->nEntityId); // 怪物配置信息 if (!pMonsterConfig) continue; if(pData->nNextTime > nCurrent) { continue; } // 怪物的数目根据在线总人数计算 int nCreateCount = (int)GetRefreshMonsterCount(pRefreshConf, pMonsterConfig, nUserCount); nCreateCount = nCreateCount - pData->nCurrCount;//需要补刷的数量 //unsigned long pointCount = pRefreshConf->nPointsCount; if (/*pointCount > 0 &&*/ nCreateCount > 0 ) { //unsigned long seed = 0; for(; nCreateCount > 0; nCreateCount-- ) { //seed = wrand(pointCount); INT_PTR nMonsterPosX = 0;//pRefreshConf->Points[seed].x; INT_PTR nMonsterPosY = 0;//pRefreshConf->Points[seed].y; if (!GetMobMonsterXY(pRefreshConf,nMonsterPosX,nMonsterPosY)) { continue; } CEntity* pEntity = CreateEntityAndEnterScene(pRefreshConf->nEntityId, pMonsterConfig->btEntityType, nMonsterPosX,nMonsterPosY,i,NULL, pRefreshConf->nLiveTime); if (pEntity != NULL) { pData->nCurrCount++; //SetMonsterConfig(pEntity, i, pRefreshConf->nEntityId); } } } } } INT_PTR CScene::GetRefreshMonsterCount( REFRESHCONFIG* pRefreshConf, PMONSTERCONFIG pMC, INT_PTR nOnlinePlayerCnt) { static const INT_PTR nCountBase = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nOnlineCountBase; //以1000人为基数 INT_PTR nResult = pRefreshConf->nCount; if (m_pFb && m_pFb->IsFb()) return nResult; if (MONSTERCONFIG::mtBoss == pMC->btMonsterType || MONSTERCONFIG::mtToumu == pMC->btMonsterType || pMC->pflags->DenyAddNumber) return nResult; INT_PTR nRestCount = nOnlinePlayerCnt - nCountBase; if (nRestCount > 0) { INT_PTR nAddCount = (INT_PTR)((float)(pRefreshConf->nCount) * ( (float)nRestCount / (float)nCountBase )); nAddCount = nAddCount <= 0?1:nAddCount; nAddCount = nAddCount > pRefreshConf->nCount?pRefreshConf->nCount:nAddCount;//最多增加1倍 nResult = pRefreshConf->nCount + nAddCount; } return nResult; } int CScene::GetFlushTime(int nMonsId, TICKCOUNT nCurTick,bool bsec,bool bDie) { int nCount = m_pSceneData ? m_pSceneData->vRefreshList.nCount : 0; for (int i = 0; i < nCount; i++) { REFRESHCONFIG * pRefreshCfg = m_pSceneData->vRefreshList.pList + i; REFRESHVALUE * pRefreshVal = m_vRefreshMonster + i; if(NULL == pRefreshCfg || NULL == pRefreshVal) return 0; int nDeadDigSec = 0; if (nMonsId == pRefreshCfg->nEntityId) { if (pRefreshVal->nCurrCount > 0 || pRefreshVal->nNextTime <= nCurTick) { // if(bsec && GetBossIsDieById(nMonsId)) //boss之家怪物死亡尸体还在 // { // nDeadDigSec = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBossDeadRemDig; // } } int nFlushTime = (int)((pRefreshVal->nNextTime - nCurTick)/60000); if(bsec) { nCurTick = GetLogicCurrTickCount(); nFlushTime = (int)((pRefreshVal->nNextTime - nCurTick)/1000); } if (nFlushTime <= 0) { return 1; } nFlushTime += nDeadDigSec; return nFlushTime; } } return 0; } bool CScene::GetBossIsDieById(int nMonsId) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); INT_PTR nDeathCount = m_DeathList.count(); for(INT_PTR i= nDeathCount -1; i >=0; i--) { EntityHandle hd =m_DeathList[i]; CEntity* pEntity = pEntityMgr->GetEntity(hd); if(pEntity) { if (enMonster == pEntity->GetType()) { CMonster* pMonster = (CMonster*)pEntity; if(pMonster->GetId() == nMonsId) return true; } } } return false; } bool CScene::RunOne() { DECLARE_TIME_PROF("CScene::RunOne"); TICKCOUNT dwCurr = _getTickCount(); //这里要使用当前的逻辑时间 //清除掉死亡的怪物 if (m_5s.CheckAndSet(dwCurr)) { //检查死亡的实体 UINT nNow = GetGlobalLogicEngine()->getMiniDateTime(); CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); //CLinkedNode *pNode; //CLinkedListIterator it(m_DeathList); INT_PTR nDeathCount = m_DeathList.count(); for(INT_PTR i= nDeathCount -1; i >=0; i--) { EntityHandle hd =m_DeathList[i]; CEntity* pEntity = pEntityMgr->GetEntity(hd); if (pEntity) { CCreature* pCreature = ((CCreature*)pEntity); //这里的实体居然是活的 //if (pCreature->GetDeathTime() < nNow) //{ if (enMonster == pEntity->GetType() || enGatherMonster == pEntity->GetType()) { CMonster* pMonster = (CMonster*)pEntity; pMonster->OnEntityDestroy(); pEntityMgr->DestroyEntity(hd); } else { pEntityMgr->DestroyEntity(hd); } m_DeathList.remove(i); //} } else { OutputMsg(rmWaning,_T("CScene::RunOne() Destroy death entity entity is NULL,Hd=%lld"),(Uint64)hd); m_DeathList.remove(i); } } int x = 0; int y = 0; GetAreaCenter(x, y); SCENEAREA* pArea = GetAreaAttri(x,y); int nNowTime = time(NULL); if ((pArea && HasMapAttribute(x, y, aaOverTimeTick))) { if(nNowTime >= m_nRefreshtime) { if(m_nRefreshtime) KickOutAllActor(); int nNowTime = time(NULL); int nNextTime = 0; AreaAttri& attri = pArea->attri[aaOverTimeTick]; if ( attri.nCount > 0) { for (INT_PTR i = 0; i < attri.nCount; i++) { int nTime = getNowZeroTime() +attri.pValues[i]; if(nNowTime >= nTime) { int nextDay = getNowZeroTime() + attri.pValues[i] + 24*3600; if(nNextTime == 0) nNextTime = nextDay; if(nextDay < nNextTime) nNextTime = nextDay; } else{ nNextTime = nTime; break; } } m_nRefreshtime = nNextTime; } } } CreateWaitNpc(); } //本函数主要执行刷怪的逻辑,玩家数量大于0才刷怪 (改为主场景才这样刷怪,具体副本具体实现) if ((!m_pFb->IsFb() ||m_pFb->is_use_default_create_monster()) && m_PlayList.count() > 0) { if (m_500msTimer.CheckAndSet(dwCurr)) { CLogicDataProvider *pProvider = GetLogicServer()->GetDataProvider(); static int nTotalTime = pProvider->GetGlobalConfig().nSceneRefreshMonsterTime; int nCount = m_pSceneData?m_pSceneData->vRefreshList.nCount:0; INT_PTR nUserCount = GetGlobalLogicEngine()->getOnlinceCount(); for(int i = 0; i < nCount; i++) { if (i != CFuBenManager::m_RefreshPara.nRefreshPos) continue; //检查每个刷怪点 REFRESHCONFIG* pRefreshConf = m_pSceneData->vRefreshList.pList + i; REFRESHVALUE* pData = m_vRefreshMonster + i; PMONSTERCONFIG pMonsterConfig = pProvider->GetMonsterConfig().GetMonsterData(pRefreshConf->nEntityId); if (!pMonsterConfig) continue; if (pData->nNextTime < dwCurr)//到刷怪的时候了 { //怪物的数目根据在线总人数计算 int nCreateCount = (int)GetRefreshMonsterCount(pRefreshConf, pMonsterConfig, nUserCount); nCreateCount = nCreateCount - pData->nCurrCount;//需要补刷的数量 if (nCreateCount > 0) { for(; nCreateCount > 0; nCreateCount-- ) { //seed = wrand(pointCount); INT_PTR nMonsterPosX = 0;//pRefreshConf->Points[seed].x; INT_PTR nMonsterPosY = 0;//pRefreshConf->Points[seed].y; if (!GetMobMonsterXY(pRefreshConf,nMonsterPosX,nMonsterPosY)) { continue; } //这里属于配置有问题 switch (pMonsterConfig->btEntityType ) { case enActor: case enHero: case enPet: continue; } CEntity* pEntity = CreateEntityAndEnterScene(pRefreshConf->nEntityId, pMonsterConfig->btEntityType, nMonsterPosX,nMonsterPosY, i, NULL, pRefreshConf->nLiveTime); if (pEntity != NULL) { pData->nCurrCount++; } } } pData->nNextTime = pRefreshConf->nNextRefreshTime + dwCurr; if ((_getTickCount() - dwCurr ) > nTotalTime) { OutputMsg(rmTip,_T("场景%d第%d条刷怪时间%d过长"),GetSceneId(), i,_getTickCount() - dwCurr); return true; } } CFuBenManager::m_RefreshPara.nRefreshPos = i + 1; } // GetGlobalLogicEngine()->GetBossMgr().CreateBossEntity(this); } if (m_1s.CheckAndSet(dwCurr)) { bool isFb = GetFuBen()->IsFb(); //判断场景时间是否到,如果到的话触发脚本事件,脚本将所有玩家踢出 if ( isFb && m_restTime != 0 && GetGlobalLogicEngine()->getMiniDateTime() > m_restTime ) { m_restTime = 0; } } } if (m_PlayList.count() > 0) { #ifndef MONSTER_MANAGER_BY_SCENE #else CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); while (m_MonInterator != m_MonsterList.end()) { CEntity* pEntity = pEntityMgr->GetEntity(m_MonInterator->first); pEntity->RunOne(dwCurr); if( _getTickCount() - dwCurr > 4 ) //每个地图的怪物逻辑遍历不要超过4毫秒 { if (m_MonInterator != m_MonsterList.end()) ++m_MonInterator; return true; } if (m_MonInterator != m_MonsterList.end()) ++m_MonInterator; } if (m_MonInterator == m_MonsterList.end()) { m_MonInterator = m_MonsterList.begin(); } #endif } return false; } void CScene::Trace() { TICKCOUNT nTick = GetGlobalLogicEngine()->getTickCount(); TICKCOUNT nLastRun = m_5s.GetNextTime(); //上次刷新的时间 int tickDis =(int)(nTick - nLastRun) ; if(tickDis < 0 ) { tickDis =0; } OutputMsg(rmNormal,"name=%s,death=%d,playcount=%d,rundis=%d ms", GetSceneName(),(int)m_DeathList.count(),(int)m_PlayList.count(), tickDis); } void CScene::_AddDeathEntity(CEntity* pEntity, LPCSTR file, INT_PTR line) { if (!pEntity) return; bool boAddToList = true; INT_PTR entityType = pEntity->GetType(); //尝试去销毁npc if(entityType == enNpc) { OutputMsg(rmWaning,"%s Try to destroy npc %s",__FUNCTION__,pEntity->GetEntityName()); return ; } else if (enActor == entityType || enHero == entityType || enPet == entityType ) { return;//玩家死亡不在这里处理 } else if(entityType == enFire) { GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(pEntity->GetHandle()); return; } else if (enMonster == entityType || enGatherMonster == entityType) { // CMonster *pMonster =(CMonster*)pEntity; // if(pMonster->GetMonsterType() == MONSTERCONFIG::mtBoss) // { // if(pMonster->GetBossReferId() > 0) // { // GetGlobalLogicEngine()->GetBossMgr().BossCallLuaScript(pMonster->GetBossReferId() , CBossSystem::enOnBossDeath); // } // } if(pEntity->GetAttriFlag().CanReuse) { unsigned int nBornPointID = pEntity->GetProperty(PROP_MONSTER_BORNPOINT); boAddToList = false; CEntityMsg msg(CEntityMsg::emReUseMonster, pEntity->GetHandle()); msg.dwDelay = 5000; pEntity->PostEntityMsg(msg); if (m_pSceneData && nBornPointID >=0 && nBornPointID < (unsigned int)m_pSceneData->vRefreshList.nCount) { REFRESHVALUE* refresh = m_vRefreshMonster+ nBornPointID; refresh->nCurrCount++; } return; } } if (boAddToList && pEntity->isAnimal()) { CCreature* pCreature = ((CCreature*)pEntity); if(pCreature->IsInDeathList()) return; //已经在场景里了 pCreature->SetDestoryTime(DEATHTIME); // 所有实体删除事件固定2秒? //m_DeathList.linkAtLast(pEntity->GetHandle()); m_DeathList.add(pEntity->GetHandle()); if(pEntity->GetType() == enMonster && GetFuBen()->GetFbId()==0 ) { CMonster *pMonster =(CMonster*)pEntity; if(pMonster->GetMonsterType() == MONSTERCONFIG::mtBoss) { OutputMsg(rmNormal, "%s liveTime is over,_AddDeathEntity bossLiveTime = %d,file=%s,line=%d", (char*)pMonster->GetEntityName(),(int)pMonster->GetLiveTime(), (char*)file,(int)line); } } } } CEntity* CScene::CreateEntityAndEnterScene(INT_PTR nEntityId, INT_PTR nType, INT_PTR nX, INT_PTR nY, INT_PTR nParam, CActor* pOnwer, INT_PTR nLiveTime, INT_PTR nBornLevel, char* szMonsterName, INT_PTR nForceVesterId, INT_PTR nInitMonsterPercent ) { EntityHandle hHandle; CEntity* pEntity = GetGlobalLogicEngine()->GetEntityMgr()->CreateEntity((int)nType, hHandle); if (pEntity) { pEntity->SetProperty(PROP_ENTITY_ID, (unsigned int)nEntityId) ; if (EnterScene(pEntity, nX, nY)) { if (enPet == nType) { ((CPet*)pEntity)->SetMaster(pOnwer); //宠物的主人 //设置等级,因为需要这个刷属性的 ((CPet*)pEntity)->SetProperty(PROP_CREATURE_LEVEL, (unsigned int)nParam) ; } else if(enHero == nType) { ((CHero*)pEntity)->SetMaster(pOnwer); //宠物的主人 ((CPet*)pEntity)->SetProperty(PROP_CREATURE_LEVEL, (unsigned int)nParam) ; } else if(enMonster == nType) { pEntity->SetProperty(PROP_MONSTER_INITHPPERCENT,(unsigned int)nInitMonsterPercent); } if (!pEntity->Init(NULL, 0)) { GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(hHandle); pEntity =NULL; } else { if (enMonster == nType || enGatherMonster == nType) { PMONSTERCONFIG pMonConf = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(nEntityId); // 怪物刷新脚本处理(当前的处理方式是通过对需要执行脚本怪物在刷新的时候执行registerMonsterMob函数设置此变量。并非在怪物中支持配置) if (pMonConf && pMonConf->pflags->bMobTriggerScript) { pEntity->SetEntityName((char*)pMonConf->szName); CScriptValueList arg; arg << pEntity; arg << nEntityId; arg << this->GetSceneId(); arg << nX; arg << nY; GetGlobalLogicEngine()->GetMonFuncNpc()->GetScript().Call("OnMonsterMob", arg, arg, 0); } if( pMonConf->btMonsterType == tagMonsterConfig::mtBoss ) //BOSS创建,记录日志 { if( GetLogicServer()->GetLocalClient() ) { } } SetMonsterConfig(pEntity, nParam,nEntityId,nBornLevel); CMonster *pMonster = ((CMonster*)pEntity); pMonster->SetLiveTime((unsigned int)nLiveTime); //设置生命周期 pMonster->SetProperty(PROP_MONSTER_LIVE_TIMEOUT, pMonster->GetLiveTime() ); //怪物生命到期时间 if(pOnwer) { ((CMonster*)pMonster)->SetOwner(pOnwer->GetHandle()); } CSkillSubSystem & skillSystem = pMonster->GetSkillSystem(); const CVector & skills= skillSystem.GetSkills(); for(INT_PTR i=0; i< skills.count();i++) { if(skills[i].bEvent == mSkillEventBorn) { skillSystem.LaunchSkill(skills[i].nSkillID,0,0,true); } } if (enMonster == nType || enGatherMonster == nType) { ((CMonster *)pEntity)->MonsterSay(mstCreate); } if( enMonster == nType) { CMonster *pMonster = (CMonster *)pEntity; pMonster->SetForceVesterId((unsigned int)nForceVesterId); //设置怪物的强制归属 if( szMonsterName ) { //pMonster->ResetShowName(szMonsterName); pMonster->ChangeShowName(12, szMonsterName); } if (pMonster->GetMonsterType() == MONSTERCONFIG::mtBoss && GetFuBen()->GetFbId()==0) { OutputMsg(rmTip,"Boss Enter scene %s,scene=%s,x=%d,y=%d",pMonster->GetEntityName(),GetSceneName(),(int)nX,(int)nY); } if (pMonster->GetAttriFlag().DenyAttackedByActor) { pMonster->AddState(esStateDenyAttackedByActor); } } } } } else { GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(hHandle); pEntity = NULL; } } return pEntity; } bool CScene::GetSeqVisibleList(int nPosX,int nPosY, SequenceEntityList& visibleList, int nLeft,int nRight,int nUp,int nDown) { int nMinX = __max(nPosX + nLeft,0); int nMaxX = __min(nPosX + nRight,m_Grid.m_nCol-1); int nMinY = __max(nPosY + nUp,0); int nMaxY = __min(nPosY + nDown,m_Grid.m_nRow-1); visibleList.clear(); typedef typename EntityPosVector::iterator Iter; for (int j = nMinX; j <= nMaxX; j++) { MapEntityGrid* pGrid = m_Grid.GetList(j); if (pGrid) { EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = 0; i < entitys.count(); i++) { int nPosY = entitys[i].pos; if(nPosY >= nMinY && nPosY <= nMaxY ) { if(CEntity *pEntity = GetEntityFromHandle(entitys[i].hd)) { if (pEntity->IsInited()) visibleList.insert(entitys[i].hd); } } } #else Iter it; Iter end = entitys.end(); for (it = entitys.begin(); it != end; it++) { int nPosY = (*it).second; if(nPosY >= nMinY && nPosY <= nMaxY ) { if(CEntity *pEntity = GetEntityFromHandle((*it).first)) { if (pEntity->IsInited()) visibleList.insert((*it).first); } } } #endif } } for (int j = 0, nMaxXPos = GetSceneWidth(); j <= nMaxXPos; j++) { MapEntityGrid* pGrid = m_Grid.GetList(j); if (pGrid) { EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = 0; i < entitys.count(); i++) { if(CEntity *pEntity = GetEntityFromHandle(entitys[i].hd)) { int nPostionY = entitys[i].pos; if (pEntity->IsInited()) { //次元Boss归属玩家,无论是否在视野中都可见 if ( pEntity->GetType() == enActor && ((CActor *)pEntity)->IsBeLongBossActor() && pEntity->GetFuBen() && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty(PROP_CREATURE_HP) > 0 ) { visibleList.insert(entitys[i].hd); } //次元Boss怪物,无论是否在视野中都可见 if ( pEntity->GetType() == enMonster && pEntity->GetProperty(PROP_ENTITY_ID) == 386 && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty(PROP_CREATURE_HP) > 0 ) { visibleList.insert(entitys[i].hd); } } } } #else Iter it; Iter end = entitys.end(); for (it = entitys.begin(); it != end; it++) { if(CEntity *pEntity = GetEntityFromHandle((*it).first)) { if (pEntity->IsInited()) { //次元Boss归属玩家,无论是否在视野中都可见 if ( pEntity->GetType() == enActor && ((CActor *)pEntity)->IsBeLongBossActor() && pEntity->GetFuBen() && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty(PROP_CREATURE_HP) > 0 ) { visibleList.insert((*it).first); } //次元Boss怪物,无论是否在视野中都可见 if ( pEntity->GetType() == enMonster && pEntity->GetProperty(PROP_ENTITY_ID) == 386 && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty(PROP_CREATURE_HP) > 0 ) { visibleList.insert((*it).first); } } } } #endif } } return true; } bool CScene::GetVisibleList(int nPosX,int nPosY, CObserverEntityList& vVisibleList, int nLeft, int nRight, int nUp, int nDown, bool *pbActorInVisibleList) { int nMinX = __max(nPosX + nLeft,0); int nMaxX = __min(nPosX + nRight,m_Grid.m_nCol-1); int nMinY = __max(nPosY + nUp,0); int nMaxY = __min(nPosY + nDown,m_Grid.m_nRow-1); vVisibleList.clear(); bool bActorInVisibleList = false; for (int j = nMinX; j <= nMaxX; j++) { MapEntityGrid* pGrid = m_Grid.GetList(j); if (pGrid) { EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = 0; i < entitys.count(); i++) { if (!bActorInVisibleList && entitys[i].hd.GetType() == enActor) bActorInVisibleList = true; int nPosY = entitys[i].pos; if( nPosY >= nMinY && nPosY <= nMaxY) { EntityHandleTag entityTag; entityTag.m_handle = entitys[i].hd; entityTag.m_tag = eENTITY_APPEAR_UNCHANGE; vVisibleList.linkAtLast(entityTag); } } #else typedef typename EntityPosVector::iterator Iter; Iter it = entitys.begin(), end = entitys.end(); for (; it != end; it++) { if (!bActorInVisibleList && (*it).first.GetType() == enActor) bActorInVisibleList = true; int nPosY = (*it).second; if( nPosY >= nMinY && nPosY <= nMaxY) { EntityHandleTag entityTag; entityTag.m_handle = (*it).first; entityTag.m_tag = eENTITY_APPEAR_UNCHANGE; vVisibleList.linkAtLast(entityTag); } } #endif } } if (pbActorInVisibleList) *pbActorInVisibleList = bActorInVisibleList; return true; } bool CScene::GetVisibleList(CEntity * pEntity, EntityVector& vVisibleList, int nLeft, int nRight, int nUp, int nDown) { if(pEntity == NULL) return false; int nPosX,nPosY; pEntity->GetPosition(nPosX,nPosY); return GetVisibleList(nPosX,nPosY,vVisibleList,nLeft,nRight,nUp,nDown); } bool CScene::GetVisibleList(int nPosX,int nPosY, EntityVector& vVisibleList, int nLeft, int nRight, int nUp, int nDown) { int nMinX = __max(nPosX + nLeft,0); int nMaxX = __min(nPosX + nRight, m_Grid.m_nCol-1); int nMinY = __max(nPosY + nUp,0); int nMaxY = __min(nPosY + nDown, m_Grid.m_nRow-1); vVisibleList.clear(); int j = 0; for (j = nMinX; j <= nMaxX; j++) { MapEntityGrid* pGrid = m_Grid.GetList(j); if (pGrid) { #ifndef GRID_USE_STL_MAP for(INT_PTR i=pGrid->m_entitys.count()-1; i>-1; i-- ) { int nPos = pGrid->m_entitys[i].pos; if( nPos>= nMinY && nPos <= nMaxY) { vVisibleList.add( pGrid->m_entitys[i].hd); } } #else EntityPosVector& entitys = pGrid->m_entitys; typedef typename EntityPosVector::iterator Iter; Iter it = entitys.begin(), end = entitys.end(); for (; it != end; it++) { int nPos = (*it).second; if( nPos>= nMinY && nPos <= nMaxY) { vVisibleList.add((*it).first); } } #endif } } return true; } void CScene::ClearIncorrectHandle( CEntity * pEntity, int nLeft, int nRight, int nUp, int nDown) { int nPosX,nPosY; pEntity->GetPosition(nPosX,nPosY); int nMinX = __max(nPosX + nLeft,0); int nMaxX = __min(nPosX + nRight,m_Grid.m_nCol-1); int nMinY = __max(nPosY + nUp,0); int nMaxY = __min(nPosY + nDown,m_Grid.m_nRow-1); for (int j = nMinX; j <= nMaxX; j++) { MapEntityGrid* pGrid = m_Grid.GetList(j); if (pGrid) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = entitys.count()-1; i >= 0; i--) { int nPosY = entitys[i].pos; if(nPosY >= nMinY && nPosY <= nMaxY) { CEntity* pEntity = pEntityMgr->GetEntity(entitys[i].hd); if (!pEntity) entitys.remove(i); } } #else typedef typename EntityPosVector::iterator Iter; Iter it = entitys.begin(), end = entitys.end(); for (; it != end; it++) { int nPosY = (*it).second; if(nPosY >= nMinY && nPosY <= nMaxY ) { CEntity* pEntity = pEntityMgr->GetEntity((*it).first); if (!pEntity) entitys.erase(it--); } } #endif } } } void CScene::SetRefreshList(REFRESHLIST* list) { if (m_vRefreshMonster) { GFreeBuffer(m_vRefreshMonster); m_vRefreshMonster = NULL; } m_vRefreshMonster = (REFRESHVALUE*)GAllocBuffer(sizeof(REFRESHVALUE)*(list->nCount)); ResetRefreshList(list); } CNpc * CScene::GetNpc(int nNpcId) { CLinkedNode * pNode; CLinkedListIterator it(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity * pEntity = GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(pNode->m_Data); if (pEntity != NULL && pEntity->GetId() == nNpcId) { return (CNpc *)pEntity; } } return NULL; } CNpc* CScene::GetNpc(LPCSTR sName) { if (sName == NULL || sName[0] == 0) return NULL; CLinkedNode *pNode; CLinkedListIterator it(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(pNode->m_Data); if (pEntity != NULL && strcmp(pEntity->GetEntityName(),sName) == 0) { return (CNpc*)pEntity; } } return NULL; } void CScene::SetNpcCanSeeFlag(bool bSet) { CLinkedNode *pNode; CLinkedListIterator it(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(pNode->m_Data); if (pEntity != NULL) { NPCCONFIG* npcConfig = ((CNpc*)pEntity)->GetConfig(); if(npcConfig && npcConfig->bCanHideFlag == true) ((CNpc*)pEntity)->GetAttriFlag().DenySee = bSet; } } } CNpc* CScene::GetNpcAtXY(const INT_PTR nX, const INT_PTR nY) { MapEntityGrid* pGrid = m_Grid.GetList(nX); if (pGrid) { EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = entitys.count()-1; i >-1; i--) { if (entitys[i].hd.GetType() == enNpc && entitys[i].pos == nY) { return (CNpc*)GetEntityFromHandle(entitys[i].hd); } } #else typedef typename EntityPosVector::iterator Iter; Iter it = entitys.begin(), end = entitys.end(); for (; it != end; it++) { if ((*it).first.GetType() == enNpc && (*it).second == nY) { return (CNpc*)GetEntityFromHandle((*it).first); } } #endif } return NULL; } int CScene::GetEntityCountAtXY(const int nX, const int nY, const int nEntityType) { int nResult = 0; MapEntityGrid* pGrid = m_Grid.GetList(nX); if (pGrid) { EntityPosVector& entitys = pGrid->m_entitys; #ifndef GRID_USE_STL_MAP for (INT_PTR i = 0; i < entitys.count(); i++) { if (entitys[i].hd.GetType() == nEntityType || nEntityType < 0) { nResult++; } } #else typedef typename EntityPosVector::iterator Iter; Iter it = entitys.begin(), end = entitys.end(); for (; it != end; it++) { if ((*it).first.GetType() == nEntityType || nEntityType < 0) { nResult++; } } #endif } return nResult; } INT_PTR CScene::ReloadNpcScript(LPCTSTR szNpcName) { INT_PTR result = 0; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedNode *pNode; CLinkedListIterator it(m_NpcList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if (pEntity && pEntity->GetType() == enNpc) { CNpc* pNpc = ((CNpc*)pEntity); NPCCONFIG* pConfig = pNpc->GetConfig(); if (pConfig && (szNpcName == NULL || strcmp(szNpcName, pConfig->sName)==0)) result += pNpc->LoadScript(pConfig->sScript,true); } } return result; } void CScene::ExitAllActor() { if (!m_pFb->IsFb()) return; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedNode *pNode; CLinkedListIterator it(m_PlayList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if (pEntity && pEntity->GetType() == enActor) { ((CActor*)pEntity)->ReturnToStaticScene(); } m_PlayList.remove(pNode); //修改了一个死循环 } } void CScene::SetMonsterConfig( CEntity* pEntity, INT_PTR bornPoint, INT_PTR nMonsterId, INT_PTR nBornLevel ) { if (!pEntity) return; pEntity->SetProperty(PROP_MONSTER_BORNPOINT,(unsigned int)bornPoint); PMONSTERCONFIG pConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(nMonsterId); if (pConfig) { if(bornPoint >= 0 && bornPoint < m_pSceneData->vRefreshList.nCount) { REFRESHCONFIG* pSceneRefreshConfig = m_pSceneData->vRefreshList.pList + bornPoint; if (pSceneRefreshConfig && pSceneRefreshConfig->nNextRefreshTime == 0) //能否被重用 { EntityFlags & flags = pEntity->GetAttriFlag(); flags.CanReuse =true; } } //pEntity->SetProperty(PROP_CREATURE_ATTACK_SPEED,) //放到属性里去刷 //pEntity->SetProperty(PROP_CREATURE_HP,pConfig->cal.m_AttrValues[aMaxHpAdd].uValue); //pEntity->SetProperty(PROP_CREATURE_MP,pConfig->cal.m_AttrValues[aMaxMpAdd].uValue); if ( nBornLevel > 0 ) { unsigned int nLevel = (unsigned int)(pConfig->nOriginalLevel+nBornLevel); pConfig->nLevel = nLevel; pEntity->SetProperty(PROP_CREATURE_LEVEL,nLevel); pEntity->OnLevelUp(nLevel); } else { pEntity->SetProperty(PROP_CREATURE_LEVEL,pConfig->nLevel); } pEntity->SetProperty(PROP_MONSTER_CIRCLE, pConfig->nCircle); ((CAnimal*)pEntity)->SetCamp(pConfig->bCamp); //pEntity->SetProperty(PROP_ENTITY_ID,pConfig->nEntityId); pEntity->SetEntityName((char*)pConfig->szName); pEntity->SetProperty(PROP_ENTITY_MODELID,pConfig->nModelId); pEntity->SetProperty(PROP_ENTITY_ID,(int)nMonsterId); pEntity->SetInitFlag(true); } else { OutputMsg(rmTip,_T("set monster config error")); } } bool CScene::GetPath(CEntity* pEntity, CVector &outPaths, int targetX, int targetY) { if (!pEntity) return false; #if _DEBUG struct timespec tp_begin; clock_gettime(CLOCK_MONOTONIC_RAW, &tp_begin); #endif INT_PTR nCurrentPosX = pEntity->GetProperty(PROP_ENTITY_POSX); INT_PTR nCurrentPosY = pEntity->GetProperty(PROP_ENTITY_POSY); bool ret = m_AStar.getPath(pEntity->GetType(), nCurrentPosX, nCurrentPosY, targetX, targetY, outPaths, this); #if _DEBUG struct timespec tp_end; clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end); int secdiff = tp_end.tv_sec - tp_begin.tv_sec; long long nsecdiff = tp_end.tv_nsec - tp_begin.tv_nsec; if ((secdiff > 0) || nsecdiff > 100 * 1000 * 1000) { OutputMsg(rmError,_T("%s %lld 寻路时间太长!sec:%d, nano:%lld"), pEntity->GetEntityName(), (Uint64)(pEntity->GetHandle()), secdiff, nsecdiff); } #endif return ret; } void CScene::SetAreaConfig(CObjectAllocator& dataAlloc) { if (!m_pSceneData) return; if (m_pSceneData->vAreaList.nCount <= 0) { m_pMapAreaTable = NULL; return; } size_t dwAreaDataSize = sizeof(m_pMapAreaTable[0])*m_nWidth*m_nHeight; m_pMapAreaTable = (PBYTE)dataAlloc.allocObjects(dwAreaDataSize); ZeroMemory(m_pMapAreaTable, dwAreaDataSize); //生成区域地图 CAreaRegion region; region.setSize(m_nWidth, m_nHeight); for (int i = 0; i < m_pSceneData->vAreaList.nCount; i++) { SCENEAREA& area = m_pSceneData->vAreaList.pList[i]; //直接将区域数据生成到地图区域数据内存中 if (!region.addArea(area.lpPoints,area.nPointCount, i, m_pMapAreaTable)) { OutputMsg(rmError,_T("generate area error!sceneid=%d,areaid=%d"),GetSceneId(),i); continue; } } } void CScene::SetTelePortTable(CObjectAllocator& dataAlloc) { if (!m_pSceneData) return; size_t nSize = sizeof(m_pTelePortTable[0])*m_nWidth*m_nHeight; m_pTelePortTable= (PBYTE)dataAlloc.allocObjects(nSize); ZeroMemory(m_pTelePortTable,nSize); // 在传送门的周围计算每个点。记录的是传送门的索引(based 1),传送门的xy坐标往外nDist距离的点都算传送点 for (int i = 0; i < m_pSceneData->TeleportList.nCount; i++) { TeleportConfig& config = m_pSceneData->TeleportList.pList[i]; int nDist = config.nDist; INT_PTR nStartX = __max(0,config.nPosX - nDist); INT_PTR nEndX = __min(m_nWidth,config.nPosX + nDist); INT_PTR nStartY = __max(0,config.nPosY - nDist); INT_PTR nEndY = __min(m_nHeight,config.nPosY + nDist); for (INT_PTR x = nStartX; x <= nEndX; x++) { for (INT_PTR y = nStartY; y <= nEndY; y++) { // 要能走的地方才能传送,避免跳跃的时候传送。 这里记录每个格子对应的传送门索引(从1开始) if (m_pMapData->canMove((DWORD)x,(DWORD)y)) { m_pTelePortTable[y*m_nWidth+x] = i+1; } } } } } bool CScene::HasMapAttribute(INT_PTR nPosX, INT_PTR nPosY, BYTE bType, SCENEAREA* pArea) { if (!m_pSceneData) return false; if (aaNoAttri == bType || bType >= aaAttriCount) return false; if (!pArea) { pArea = GetAreaAttri(nPosX, nPosY); if (!pArea) return false; } // 感觉这里存在数据冗余。attri本身就是类型的数组,怎么具体的属性数据里头又有bType??? if (pArea->attri[bType].bType == bType) { return true; } return false; } bool CScene::HasMapAttribute(INT_PTR nPosX, INT_PTR nPosY, BYTE bType, int value , SCENEAREA* pArea) { if (!m_pSceneData) return false; if (aaNoAttri == bType || bType >= aaAttriCount) return false; if (!pArea) { pArea = GetAreaAttri(nPosX,nPosY); if (!pArea) return false; } if (pArea->attri[bType].bType == bType) { AreaAttri& attri = pArea->attri[bType]; return binarySearch(attri.pValues,attri.nCount,value); } return false; } bool CScene::GetMapAttriValue(INT_PTR nPosX, INT_PTR nPosY, BYTE bType, int& value, SCENEAREA* pArea) { value = 0; if (!m_pSceneData) return false; if (aaNoAttri == bType || bType >= aaAttriCount) return false; if (!pArea) { pArea = GetAreaAttri(nPosX,nPosY); if (!pArea) return false; } if (pArea->attri[bType].bType == bType) { AreaAttri& attri = pArea->attri[bType]; if (attri.nCount > 0) { value = attri.pValues[0]; return true; } } return false; } SCENEAREA* CScene::GetAreaAttri(INT_PTR x, INT_PTR y) { if (!m_pSceneData || !m_pSceneData->vAreaList.pList) return NULL; if (x <0 || x >= m_nWidth || y < 0 || y >= m_nHeight) { return NULL; } if(m_pMapAreaTable ==NULL) { return NULL; } BYTE index = m_pMapAreaTable[y * m_nWidth + x]; if (index >= m_pSceneData->vAreaList.nCount) { OutputMsg(rmError,_T("map attribut data error!sceneid=%d, x,y=%d,%d, index=%d, count=%d"), m_pSceneData->nScenceId, x, y, index, m_pSceneData->vAreaList.nCount); return NULL; } return &(m_pSceneData->vAreaList.pList[index]); } int CScene::GetAreaListIndex(INT_PTR x, INT_PTR y) { if (!m_pSceneData || !m_pSceneData->vAreaList.pList) return -1; if (x <0 || x >= m_nWidth || y < 0 || y >= m_nHeight) { return -1; } if(m_pMapAreaTable ==NULL) { return -1; } BYTE index = m_pMapAreaTable[y * m_nWidth + x]; if (index >= m_pSceneData->vAreaList.nCount) { OutputMsg(rmError,_T("map attribut data error!sceneid=%d, x,y=%d,%d, index=%d, count=%d"), m_pSceneData->nScenceId, x, y, index, m_pSceneData->vAreaList.nCount); return -1; } return index; } void CScene::GetAreaCenter(int& nPosX, int& nPosY) { if (!m_pSceneData || !m_pSceneData->vAreaList.pList) return; if (nPosX < 0 || nPosX >= m_nWidth || nPosY < 0 || nPosY >= m_nHeight) return; if (!m_pMapAreaTable) return; BYTE index = m_pMapAreaTable[nPosY * m_nWidth + nPosX]; SCENEAREA& area = m_pSceneData->vAreaList.pList[index]; nPosX = area.Center[0]; nPosY = area.Center[1]; } void CScene::GetFirstAreaCenterPoint(int &nPosX, int &nPosY) { if (!m_pSceneData || !m_pSceneData->vAreaList.pList) return; SCENEAREA& area = m_pSceneData->vAreaList.pList[0]; nPosX = area.Center[0]; nPosY = area.Center[1]; } void CScene::GetRangeAreaCrossPoint(CEntity* pEntity, int &nPosX, int& nPosY) { if (!m_pSceneData || !m_pSceneData->vAreaList.pList) return; int nRandomX, nRandomY = 0; SCENEAREA& pArea = m_pSceneData->vAreaList.pList[0]; if ( pArea.nPointCount >= 3 && GetRandomPoint(pEntity, pArea.lpPoints[0].x, pArea.lpPoints[0].y, pArea.lpPoints[2].x, pArea.lpPoints[2].y, nRandomX, nRandomY)) { nPosX = nRandomX; nPosY = nRandomY; } } bool CScene::IsSameArea(INT_PTR nOldX, INT_PTR nOldY, INT_PTR nNewX, INT_PTR nNewY) { if (nOldX < 0 || nOldX >= m_nWidth || nOldY < 0 || nOldY >= m_nHeight) { return false; } if (nNewX < 0 || nNewX >= m_nWidth || nNewY < 0 || nNewY >= m_nHeight) { return false; } if (!m_pMapAreaTable) { return true; } return m_pMapAreaTable[nOldY * m_nWidth + nOldX] == m_pMapAreaTable[nNewY * m_nWidth + nNewX]; } bool CScene::IsTelePort(INT_PTR nX, INT_PTR nY) { if (nX >= m_nWidth || nY >= m_nHeight) { OutputMsg(rmError, _T("%s error x:%d,y:%d,real width:%d,height:%d"), __FUNCTION__, (int)nX, (int)nY,(int)m_nWidth,(int)m_nHeight); return false; } return m_pTelePortTable[nY*m_nWidth+nX] != 0; } int CScene::GetMonsterCount(int nMonsterId, EntityHandle hHandle) { int result = 0; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); #ifndef MONSTER_MANAGER_BY_SCENE CLinkedNode *pNode; CLinkedListIterator it(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity) { if ( (nMonsterId == 0 || pEntity->GetProperty(PROP_ENTITY_ID) == nMonsterId) && (hHandle == 0 || hHandle == ((CMonster*)pEntity)->GetOwner()) && !((CMonster*)pEntity)->HasState(esStateDeath) ) { result++; } } else { OutputMsg(rmError,_T("GetMonsterCount 有一个不存在的实体")); } } return result; } void CScene::KillAllMonster(CEntity * pGmEntity) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); #ifndef MONSTER_MANAGER_BY_SCENE CLinkedNode *pNode; CLinkedListIterator it(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity) { pEntity->SetProperty(PROP_CREATURE_HP, 0); ((CMonster *)pEntity)->OnKilledByEntity(pGmEntity); } } } int CScene::KillMonsterByName(const char * sName, CEntity * pGmEntity, byte nDropItem) { int nCount = 0; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CEntityList killMonsterList; #ifndef MONSTER_MANAGER_BY_SCENE CLinkedNode *pNode; CLinkedListIterator it(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity != NULL && !pEntity->IsDeath() && _stricmp(pEntity->GetEntityName(), sName) == 0) { killMonsterList.linkAtLast(pEntity->GetHandle()); } } CLinkedNode *pNodeKill; CLinkedListIterator killIt(killMonsterList); for (pNodeKill = killIt.first(); pNodeKill; pNodeKill = killIt.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNodeKill->m_Data); if (pEntity != NULL && !pEntity->IsDeath()) { pEntity->SetProperty(PROP_CREATURE_HP, 0); if (nDropItem > 0) { ((CMonster *)pEntity)->OnKilledByEntity(pGmEntity); } nCount++; } } return nCount; } void CScene::ClearEntity(int nType) { CLinkedNode *pNode; CLinkedListIterator it; bool flag =true; switch (nType) { case enNpc: it.setList(m_NpcList); break; case enActor: it.setList(m_PlayList); break; case enMonster: case enGatherMonster: #ifndef MONSTER_MANAGER_BY_SCENE it.setList(m_MonsterList); #else { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); if (pEntity != NULL) { EntityHandle handle = pEntity->GetHandle(); if (pEntity->IsDeath()) { ClearDeathEntity(handle); } pEntityMgr->DestroyEntity(handle); } } return; } #endif break; case enTransfer: it.setList(m_TeleportList); break; case enPet: it.setList(m_petList); break; case enHero: it.setList(m_heroList); break; case enDropItem: it.setList(m_dropItemList); break; case enFire: it.setList(m_fireList); break; default: flag =false; break; } if(flag) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if(!pEntity)continue; EntityHandle handle = pEntity->GetHandle(); if (pEntity->IsDeath()) { ClearDeathEntity(handle); } pEntityMgr->DestroyEntity(handle); } } } void CScene::ClearDeathEntity(EntityHandle handle) { for(INT_PTR i= m_DeathList.count() -1; i >=0; i--) { EntityHandle hd = m_DeathList[i]; if (hd == handle) { m_DeathList.remove(i); break; } } } INT_PTR CScene::GetLiveMonsterCount() { int result = 0; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); #ifndef MONSTER_MANAGER_BY_SCENE CLinkedNode *pNode; CLinkedListIterator it(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity && !pEntity->IsDeath()) { result ++; } } return result; } bool CScene::IsKillAllMonster( int nMonsterId, EntityHandle hHandle) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); #ifndef MONSTER_MANAGER_BY_SCENE CLinkedNode *pNode; CLinkedListIterator it(m_MonsterList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = m_MonsterList.begin(); for (; iter != m_MonsterList.end(); ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity) { if ( (nMonsterId == 0 || pEntity->GetProperty(PROP_ENTITY_ID) == nMonsterId) && (hHandle == 0 || hHandle == ((CMonster*)pEntity)->GetOwner()) && !((CMonster*)pEntity)->HasState(esStateDeath) ) { return false; } } else { OutputMsg(rmError,_T("GetMonsterCount 有一个不存在的实体")); } } return true; } void CScene::RemoveEntity(CEntity* pEntity) { const EntityHandle& handle = pEntity->GetHandle(); CLinkedNode *pNode; INT_PTR nEntityType = pEntity->GetType(); //CEntityList * pEntityList; CLinkedListIterator it; bool flag =true; switch (nEntityType) { case enNpc: it.setList(m_NpcList); break; case enActor: it.setList(m_PlayList); break; case enMonster: case enGatherMonster: #ifndef MONSTER_MANAGER_BY_SCENE it.setList(m_MonsterList); #else { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); std::map::iterator iter = m_MonsterList.find(handle); if (iter != m_MonsterList.end()) { if (m_MonInterator == iter) { m_MonsterList.erase(m_MonInterator++); if (m_MonInterator == m_MonsterList.end()) m_MonInterator = m_MonsterList.begin(); } else m_MonsterList.erase(iter); } return; } #endif break; case enTransfer: it.setList(m_TeleportList); break; case enPet: it.setList(m_petList); break; case enHero: it.setList(m_heroList); break; case enDropItem: it.setList(m_dropItemList); break; case enFire: it.setList(m_fireList); break; default: flag =false; break; } if(flag) { for (pNode = it.first(); pNode; pNode = it.next()) { if (handle == pNode->m_Data) { it.remove(pNode); break; } } } } void CScene::Broadcast(char *pData, SIZE_T size) { EntityHandle handler; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedListIterator it(m_PlayList); for (CLinkedNode *pNode = it.first(); pNode; pNode = it.next()) { CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data)); if (pActor && pActor->IsInited()) { CActorPacket pack; CDataPacket &data = pActor->AllocPacket(pack); data.writeBuf(pData, size); pack.flush(); } } } void CScene::BroadcastNewAttr() { EntityHandle handler; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedListIterator it(m_PlayList); for (CLinkedNode *pNode = it.first(); pNode; pNode = it.next()) { CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data)); if (pActor && pActor->IsInited()) { int x,y; pActor->GetPosition(x,y); SCENEAREA* pArea = GetAreaAttri(x,y); //直接返回区域属性,后面的函数判断直接用这个,避免多次获取 if(pArea) { GetGrid().SendAreaConfig(pArea,pActor); } } } } int CScene::GetSceneTime() { if (m_restTime == 0) return 0; int restTime = m_restTime - GetGlobalLogicEngine()->getMiniDateTime(); return restTime < 0 ? 0 : restTime; } void CScene::SetSceneTime(UINT nTime) { m_restTime = GetGlobalLogicEngine()->getMiniDateTime() + nTime; } INT_PTR CScene::GetAreaCount() { return m_pSceneData?m_pSceneData->vAreaList.nCount:0; } bool CScene::SetAreaAttri(INT_PTR nIndex, INT_PTR nType, int* pValues, INT_PTR nCount, LPCSTR sFunc, Uint64 hNpc, int noTips) { if (m_pSceneData && nIndex >= 0 && nIndex < m_pSceneData->vAreaList.nCount && nType > aaNoAttri && nType < aaAttriCount) { SCENEAREA* pArea = m_pSceneData->vAreaList.pList + nIndex; if (pArea) { pArea->NoTips = noTips; AreaAttri& attri = pArea->attri[nType]; attri.bType = (BYTE)nType; attri.nCount = (WORD)nCount; attri.hNpc = hNpc; if (attri.sFunc) { GFreeBuffer(attri.sFunc); attri.sFunc = NULL; } if (sFunc) { INT_PTR len = strlen(sFunc); attri.sFunc = (char*) GAllocBuffer(len+1); strcpy(attri.sFunc,sFunc); attri.sFunc[len] = 0; } if (attri.pValues) { GFreeBuffer(attri.pValues); attri.pValues = NULL; attri.nCount = 0; } if (nCount > 0 && pValues) { int size = (int)(sizeof(pValues[0])*nCount); attri.pValues = (int*)GAllocBuffer(size); memcpy(attri.pValues,pValues,size); attri.nCount = (WORD)nCount; } INT_PTR nIndex1 = nType / 32; INT_PTR nBit = nType % 32; pArea->attrBits[nIndex1] |= (1 << nBit); bool result = CEnvirConfig::checkParam(pArea,nType); //这里要广播消息 if (result) { } BroadcastNewAttr(); return result; } return true; } return false; } bool CScene::CreateNpc( SCENECONFIG* pData ,bool bInited) { DECLARE_TIME_PROF("CScene::CreateNpc"); int nOpenday = GetLogicServer()->GetDaysSinceOpenServer(); for (int i = 0; i < pData->NpcList.nCount; i++) { NPCPOS * npcPos = pData->NpcList.pPosList + i; NPCCONFIG * npcConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetNpcData(npcPos->nId); if (NULL == npcConfig) { //OutputMsg(rmError, _T("在创建场景[%s]中,没有找到npcId[%d]的配置"), pData->szScenceName, npcPos->nId); continue; } if(npcConfig->nOpenDay && npcConfig->nOpenDay > nOpenday) { m_waitNpcLists.push_back(*npcPos); continue; } CEntity* pEntity = CreateEntityAndEnterScene(npcPos->nId,enNpc,npcPos->nPosX,npcPos->nPosY); // npc不需要id if (pEntity != NULL) { ((CNpc*)pEntity)->SetConfig(npcConfig); ((CNpc *)pEntity)->InitNPCAi(); if (pEntity->GetEntityName()[0] == 0) { pEntity->SetEntityName((char*)npcConfig->sName); } pEntity->SetTitle(npcConfig->sTitle); pEntity->SetProperty(PROP_ENTITY_MODELID,npcConfig->nModelId); pEntity->SetProperty(PROP_ENTITY_ICON,npcConfig->nIcon); //((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营 //pEntity->SetProperty(PROP_CREATURE_MAXHP,10000); //pEntity->SetProperty(PROP_CREATURE_HP,10000); //pEntity->SetProperty(PROP_CREATURE_MAXMP,10000); //pEntity->SetProperty(PROP_CREATURE_MP,10000); //if (npcConfig->bCanHideFlag) //设置不可见 //{ // ((CNpc*)pEntity)->GetAttriFlag().DenySee = npcConfig->bCanHideFlag; //} /*if (!((CNpc*)pEntity)->LoadScript()) { OutputMsg(rmError,_T("load npc script error!sceneid=%d,npcName=%s,scenename=%s,scriptFile=%s"), GetSceneId(),npcConfig->sName,GetSceneName(),npcConfig->sScript); return false; }*/ pEntity->SetInitFlag(bInited);//如果是创建备用的,这个设置成false } else { //不应该有失败的情况 OutputMsg(rmError,_T("Create NPC error!!!Npc Name =%s,SceneId=%d"),npcConfig->sName,GetSceneId()); } } return true; } bool CScene::CreateWaitNpc() { if(!m_waitNpcLists.size()) { return true; } DECLARE_TIME_PROF("CScene::CreateWaitNpc"); int nOpenday = GetLogicServer()->GetDaysSinceOpenServer(); auto nIt = m_waitNpcLists.begin(); for(; nIt != m_waitNpcLists.end();) { NPCPOS npcPos = *nIt; NPCCONFIG * npcConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetNpcData(npcPos.nId); if (NULL == npcConfig) { //OutputMsg(rmError, _T("在创建场景[%s]中,没有找到npcId[%d]的配置"), pData->szScenceName, npcPos->nId); nIt++; continue; } if(npcConfig->nOpenDay && npcConfig->nOpenDay > nOpenday) { nIt++; continue; } CEntity* pEntity = CreateEntityAndEnterScene(npcPos.nId,enNpc,npcPos.nPosX,npcPos.nPosY); // npc不需要id if (pEntity != NULL) { ((CNpc*)pEntity)->SetConfig(npcConfig); ((CNpc *)pEntity)->InitNPCAi(); if (pEntity->GetEntityName()[0] == 0) { pEntity->SetEntityName((char*)npcConfig->sName); } pEntity->SetTitle(npcConfig->sTitle); pEntity->SetProperty(PROP_ENTITY_MODELID,npcConfig->nModelId); pEntity->SetProperty(PROP_ENTITY_ICON,npcConfig->nIcon); //((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营 //pEntity->SetProperty(PROP_CREATURE_MAXHP,10000); //pEntity->SetProperty(PROP_CREATURE_HP,10000); //pEntity->SetProperty(PROP_CREATURE_MAXMP,10000); //pEntity->SetProperty(PROP_CREATURE_MP,10000); //if (npcConfig->bCanHideFlag) //设置不可见 //{ // ((CNpc*)pEntity)->GetAttriFlag().DenySee = npcConfig->bCanHideFlag; //} /*if (!((CNpc*)pEntity)->LoadScript()) { OutputMsg(rmError,_T("load npc script error!sceneid=%d,npcName=%s,scenename=%s,scriptFile=%s"), GetSceneId(),npcConfig->sName,GetSceneName(),npcConfig->sScript); return false; }*/ pEntity->SetInitFlag(true);//如果是创建备用的,这个设置成false } nIt = m_waitNpcLists.erase(nIt); } return true; } bool CScene::GmCreateNpcById(int nNpcID, int nX, int nY) { NPCCONFIG * pNpcConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetNpcData(nNpcID); if(pNpcConfig != NULL) { CEntity* pEntity = CreateEntityAndEnterScene(nNpcID,enNpc,nX, nY); // npc不需要id if (pEntity != NULL) { ((CNpc*)pEntity)->SetConfig(pNpcConfig); ((CNpc *)pEntity)->InitNPCAi(); pEntity->SetEntityName((char*)pNpcConfig->sName); pEntity->SetTitle(pNpcConfig->sTitle); pEntity->SetProperty(PROP_ENTITY_MODELID,pNpcConfig->nModelId); pEntity->SetProperty(PROP_ENTITY_ICON,pNpcConfig->nIcon); //((CNpc *)pEntity)->SetCamp(pNpcConfig->bCamp); //设置NPC的阵营 pEntity->SetProperty(PROP_CREATURE_MAXHP,10000); pEntity->SetProperty(PROP_CREATURE_HP,10000); pEntity->SetProperty(PROP_CREATURE_MAXMP,10000); pEntity->SetProperty(PROP_CREATURE_MP,10000); pEntity->SetInitFlag(true);//如果是创建备用的,这个设置成false return true; } } return false; } bool CScene::GmCreateNpcByName(char* npcName) { if(!npcName) return false; if(!m_pSceneData) return false; for (int i = 0; i < m_pSceneData->NpcList.nCount; i++) { NPCPOS* npcPos = m_pSceneData->NpcList.pPosList + i; NPCCONFIG * npcConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetNpcData(npcPos->nId); if (NULL == npcConfig) { continue; } if(strcmp(npcName,npcConfig->sName) == 0) { CEntity* pEntity = CreateEntityAndEnterScene(npcPos->nId,enNpc,npcPos->nPosX,npcPos->nPosY); // npc不需要id if (pEntity != NULL) { ((CNpc*)pEntity)->SetConfig(npcConfig); ((CNpc *)pEntity)->InitNPCAi(); pEntity->SetEntityName((char*)npcConfig->sName); pEntity->SetTitle(npcConfig->sTitle); pEntity->SetProperty(PROP_ENTITY_MODELID,npcConfig->nModelId); pEntity->SetProperty(PROP_ENTITY_ICON,npcConfig->nIcon); //((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营 pEntity->SetProperty(PROP_CREATURE_MAXHP,10000); pEntity->SetProperty(PROP_CREATURE_HP,10000); pEntity->SetProperty(PROP_CREATURE_MAXMP,10000); pEntity->SetProperty(PROP_CREATURE_MP,10000); //if (npcConfig->bCanHideFlag) //设置不可见 //{ // ((CNpc*)pEntity)->GetAttriFlag().DenySee = npcConfig->bCanHideFlag; //} if (!((CNpc*)pEntity)->LoadScript()) { OutputMsg(rmError,_T("gmCreate npc script error!sceneid=%d,npcName=%s,scenename=%s,scriptFile=%s"), GetSceneId(),npcConfig->sName,GetSceneName(),npcConfig->sScript); return false; } pEntity->SetInitFlag(true);//如果是创建备用的,这个设置成false return true; } } } return false; } void CScene::ResetRefreshList(REFRESHLIST* list) { TICKCOUNT dwTime = GetLogicCurrTickCount(); for (int i = 0; i < list->nCount; i++) { REFRESHVALUE* data = m_vRefreshMonster + i; REFRESHCONFIG* pConfig = list->pList + i; data->nCurrCount = 0; data->nNextTime = dwTime + pConfig->nFirstTime; } } void CScene::CreateTeleport() { for (int i = 0; i < m_pSceneData->TeleportList.nCount; i++) { TeleportConfig* pConfig = m_pSceneData->TeleportList.pList + i; CEntity* pEntity = CreateEntityAndEnterScene(0, enTransfer, pConfig->nPosX, pConfig->nPosY); if (pEntity != NULL) { pEntity->SetProperty(PROP_ENTITY_MODELID, pConfig->nModelId); pEntity->SetEntityName(pConfig->szName); pConfig->nHandle = pEntity->GetHandle(); // 设置传送门的目标点坐标 ((CTransfer*)pEntity)->SetParams(pConfig->nSceneId,pConfig->nToPosX,pConfig->nToPosY); pEntity->SetInitFlag(true); if (!pConfig->bUse) { pEntity->GetAttriFlag().DenySee = true; } } else { // 不应该有失败的情况 OutputMsg(rmError,_T("Create Teleport error!!!Scene Name =%s,SceneId=%d"), GetSceneName(), GetSceneId()); } } } void CScene::CloneSceneConfig( SCENECONFIG* pData ) { // 区域属性、刷怪动态属性 ReleaseConfig();//释放原有的 m_pSceneData = pData; if (pData) { m_pSceneData = (SCENECONFIG*)GAllocBuffer(sizeof(SCENECONFIG)); memcpy(m_pSceneData,pData,sizeof(SCENECONFIG)); //区域属性复制一份 if (pData->vAreaList.pList) { int sz = sizeof(SCENEAREA)*pData->vAreaList.nCount; m_pSceneData->vAreaList.pList = (SCENEAREA*)GAllocBuffer(sz); memcpy(m_pSceneData->vAreaList.pList,pData->vAreaList.pList,sz); for ( INT_PTR i = 0; i < m_pSceneData->vAreaList.nCount; i++) { SCENEAREA* pArea = m_pSceneData->vAreaList.pList + i; for (INT_PTR j = 0; j < aaAttriCount; j++) { AreaAttri& attri = pArea->attri[j]; if (attri.pValues) { int size = sizeof(attri.pValues[0])*(attri.nCount); int* pTemp = attri.pValues; attri.pValues = (int*)GAllocBuffer(size); memcpy(attri.pValues,pTemp,size); } if (attri.sFunc) { LPCSTR sTemp = attri.sFunc; INT_PTR len = ArrayCount(sTemp); attri.sFunc = (char*) GAllocBuffer(len+1); strcpy(attri.sFunc,sTemp); attri.sFunc[len] = 0; } } } } } } void CScene::ReleaseConfig() { if (m_pSceneData) { if (m_pSceneData->vAreaList.pList) { for ( INT_PTR i = 0; i < m_pSceneData->vAreaList.nCount; i++) { SCENEAREA* pArea = m_pSceneData->vAreaList.pList + i; for (INT_PTR j = 0; j < aaAttriCount; j++) { AreaAttri& attri = pArea->attri[j]; if (attri.pValues) { GFreeBuffer(attri.pValues); attri.pValues = NULL; } if (attri.sFunc) { GFreeBuffer(attri.sFunc); attri.sFunc = NULL; } } } GFreeBuffer(m_pSceneData->vAreaList.pList); m_pSceneData->vAreaList.pList = NULL; } GFreeBuffer(m_pSceneData); m_pSceneData = NULL; } } bool CScene::GetRandomPoint(CEntity *pEntity, int nP1_x, int nP1_y, int nP2_x, int nP2_y, int &nResult_x, int &nResult_y) { //选择随机点传送 int nMinX = __min(nP1_x, nP2_x); int nMaxX = __max(nP1_x, nP2_x); int nMinY = __min(nP1_y, nP2_y); int nMaxY = __max(nP1_y, nP2_y); INT_PTR nGridCount = (nMaxX - nMinX + 1) * (nMaxY - nMinY + 1); do { INT_PTR nRandomX = nP1_x; if (nMaxX > nMinX) nRandomX = (rand() % (nMaxX - nMinX)) + nMinX; INT_PTR nRandomY = nP1_y; if (nMaxY > nMinY) nRandomY = (rand() % (nMaxY - nMinY)) + nMinY; if (m_Grid.CanAddEntity(pEntity, nRandomX, nRandomY,false)) { nResult_x = (int)nRandomX; nResult_y = (int)nRandomY; break; } nGridCount--; } while (nGridCount > 0); if (nResult_x < 0 || nResult_x >= m_Grid.m_nCol || nResult_y < 0 || nResult_y >= m_Grid.m_nRow) return false; return true; } void CScene::SendMsg(LPCSTR sMsg, int nType) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedNode *pNode; CLinkedListIterator it(GetPlayList()); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if (pEntity && pEntity->GetType() == enActor) { ((CActor*)pEntity)->SendTipmsg(sMsg,nType); } } } void CScene::SendSecneShortCutMsg(LPCSTR sMsg) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedNode *pNode; CLinkedListIterator it(GetPlayList()); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if (pEntity && pEntity->GetType() == enActor) { ((CActor*)pEntity)->SendShortCutMsg(sMsg); } } } bool CScene::GetRandomPointByEntityType(int nEntityType, int nP1_x, int nP1_y, int nP2_x, int nP2_y, int &nResult_x, int &nResult_y, bool canAlwaysEnter,bool bForcePos) { //选择随机点传送 int nMinX = __min(nP1_x, nP2_x); int nMaxX = __max(nP1_x, nP2_x); int nMinY = __min(nP1_y, nP2_y); int nMaxY = __max(nP1_y, nP2_y); int nRangeX = (nMaxX - nMinX + 1); int nRangeY = (nMaxY - nMinY + 1); INT_PTR nGridCount = nRangeX * nRangeY; do { INT_PTR nRandomX = nP1_x; if (nMaxX > nMinX) nRandomX = (rand() % nRangeX) + nMinX; INT_PTR nRandomY = nP1_y; if (nMaxY > nMinY) nRandomY = (rand() % nRangeY) + nMinY; if( bForcePos ) //改点强制允许创建(玩玩该坐标点就是玩家坐标点,才能保证是合法的坐标) { nResult_x = (int)nRandomX; nResult_y = (int)nRandomY; break; } if (m_Grid.CanCross(nEntityType, nRandomX, nRandomY,canAlwaysEnter) && !IsTelePort(nRandomX,nRandomY)) { nResult_x = (int)nRandomX; nResult_y = (int)nRandomY; break; } nGridCount--; } while (nGridCount > 0); if (nResult_x < 0 || nResult_x >= m_Grid.m_nCol || nResult_y < 0 || nResult_y >= m_Grid.m_nRow) return false; return true; } bool CScene::GetMobMonsterXY(REFRESHCONFIG* pRefreshConf, INT_PTR &nX, INT_PTR &nY) { bool boResult = false; if (!pRefreshConf) { return boResult; } int nMinX = pRefreshConf->nMobX - pRefreshConf->nMobRange; int nMaxX = pRefreshConf->nMobRange * 2 + 0; nX = nMinX + wrand(nMaxX); int nMinY = pRefreshConf->nMobY - pRefreshConf->nMobRange; int nMaxY = pRefreshConf->nMobRange * 2 + 0; nY = nMinY + wrand(nMaxY); int nWhileCount = 0; INT_PTR nCenterX,nCenterY; if ( CanMove( nX, nY )) { boResult = true; } else { //nCenterX = nX - 6; //nCenterY = nY - 6; while( nWhileCount < 100 ) { //nX = nCenterX + wrand(14); //nY = nCenterY + wrand(14); nX = nMinX + wrand(nMaxX); nY = nMinY + wrand(nMaxY); if (CanMove(nX,nY)) { boResult = true; break; } nWhileCount++; } } if ( !boResult ) { nX = pRefreshConf->nMobX; nY = pRefreshConf->nMobY; boResult = true; } return boResult; } CEntity* CScene::getMonsterPtrById(int nMonsterId ) { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); #ifndef MONSTER_MANAGER_BY_SCENE CEntityList& list = GetMonsterList(); CLinkedNode *pNode; CLinkedListIterator it(list); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); #else std::map::iterator iter = GetMonsterList().begin(); for (; iter != GetMonsterList().end() ; ++iter) { CEntity* pEntity = pEntityMgr->GetEntity(iter->first); #endif if (pEntity && (pEntity->GetProperty(PROP_ENTITY_ID) == nMonsterId)) { return pEntity; } } return NULL; } int CScene::CalcAllActor(int nLevel) { int nResult = 0; EntityHandle handler; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedListIterator it(m_PlayList); for (CLinkedNode *pNode = it.first(); pNode; pNode = it.next()) { CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data)); if (pActor && pActor->IsInited() && !pActor->IsDestory() && pActor->GetProperty(PROP_CREATURE_LEVEL) > nLevel) { nResult++; } } return nResult; } int CScene::CloseSceneAllActor(int nLevel) { int nResult = 0; EntityHandle handler; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedListIterator it(m_PlayList); for (CLinkedNode *pNode = it.first(); pNode; pNode = it.next()) { CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data)); if (pActor && pActor->IsInited() && !pActor->IsDestory() && pActor->GetProperty(PROP_CREATURE_LEVEL) > nLevel) { pActor->CloseActor(lwiGmTickActor,false); nResult++; } } return nResult; } int CScene::GetNowSceneGuildList() { int nResult = 0; std::set guildList; CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedListIterator it(m_PlayList); for (CLinkedNode *pNode = it.first(); pNode; pNode = it.next()) { CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data)); if (pActor && pActor->IsInited() && !pActor->IsDestory() && !pActor->IsDeath()) { int nGuildId=pActor->GetProperty(PROP_ACTOR_GUILD_ID); guildList.insert(nGuildId); } } if(guildList.size() == 1) { std::set::iterator it = guildList.begin(); for(; it != guildList.end(); it++) return *it; } return nResult; } void CScene::ResetSceneConfig() { CloneSceneConfig(m_pSrcSceneData); BroadcastNewAttr(); } void CScene::KickOutAllActor() { CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr(); CLinkedNode *pNode; CLinkedListIterator it(m_PlayList); for (pNode = it.first(); pNode; pNode = it.next()) { CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data); if (pEntity && pEntity->GetType() == enActor) { ((CActor*)pEntity)->ReturnCity(); } m_PlayList.remove(pNode); //修改了一个死循环 } }