Files
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

2890 lines
77 KiB
C++
Raw Permalink 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 "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<char>* 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle,CMonster*>::iterator iter = m_MonsterList.begin();
// for (; iter != m_MonsterList.end(); ++iter)
// {
// pMgr->DestroyEntity( iter->first );
// }
std::map<EntityHandle,CMonster*>::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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<int>(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<unsigned int>(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<unsigned int>(PROP_MONSTER_BORNPOINT);
nEntityId = pEntity->GetProperty<int>(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<CAnimal*>(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<EntityHandle> *pNode;
//CLinkedListIterator<EntityHandle> 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<unsigned int>(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<unsigned int>(PROP_ENTITY_ID, (unsigned int)nEntityId) ;
if (EnterScene(pEntity, nX, nY))
{
if (enPet == nType)
{
((CPet*)pEntity)->SetMaster(pOnwer); //宠物的主人
//设置等级,因为需要这个刷属性的
((CPet*)pEntity)->SetProperty<unsigned int>(PROP_CREATURE_LEVEL, (unsigned int)nParam) ;
}
else if(enHero == nType)
{
((CHero*)pEntity)->SetMaster(pOnwer); //宠物的主人
((CPet*)pEntity)->SetProperty<unsigned int>(PROP_CREATURE_LEVEL, (unsigned int)nParam) ;
}
else if(enMonster == nType)
{
pEntity->SetProperty<unsigned int>(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<int>(PROP_MONSTER_LIVE_TIMEOUT, pMonster->GetLiveTime() ); //怪物生命到期时间
if(pOnwer)
{
((CMonster*)pMonster)->SetOwner(pOnwer->GetHandle());
}
CSkillSubSystem & skillSystem = pMonster->GetSkillSystem();
const CVector<CSkillSubSystem::SKILLDATA> & 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<unsigned int>(PROP_CREATURE_HP) > 0 )
{
visibleList.insert(entitys[i].hd);
}
//次元Boss怪物,无论是否在视野中都可见
if ( pEntity->GetType() == enMonster && pEntity->GetProperty<unsigned int>(PROP_ENTITY_ID) == 386 && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty<unsigned int>(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<unsigned int>(PROP_CREATURE_HP) > 0 )
{
visibleList.insert((*it).first);
}
//次元Boss怪物,无论是否在视野中都可见
if ( pEntity->GetType() == enMonster && pEntity->GetProperty<unsigned int>(PROP_ENTITY_ID) == 386 && pEntity->GetFuBen()->GetFbId() == 23 && pEntity->GetSceneID() == 317 && pEntity->GetProperty<unsigned int>(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<EntityHandle> * pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<unsigned int>(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<unsigned int>(PROP_CREATURE_ATTACK_SPEED,)
//放到属性里去刷
//pEntity->SetProperty<unsigned int>(PROP_CREATURE_HP,pConfig->cal.m_AttrValues[aMaxHpAdd].uValue);
//pEntity->SetProperty<unsigned int>(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<unsigned int>(PROP_CREATURE_LEVEL,nLevel);
pEntity->OnLevelUp(nLevel);
}
else
{
pEntity->SetProperty<unsigned int>(PROP_CREATURE_LEVEL,pConfig->nLevel);
}
pEntity->SetProperty<int>(PROP_MONSTER_CIRCLE, pConfig->nCircle);
((CAnimal*)pEntity)->SetCamp(pConfig->bCamp);
//pEntity->SetProperty<unsigned int>(PROP_ENTITY_ID,pConfig->nEntityId);
pEntity->SetEntityName((char*)pConfig->szName);
pEntity->SetProperty<int>(PROP_ENTITY_MODELID,pConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ID,(int)nMonsterId);
pEntity->SetInitFlag(true);
}
else
{
OutputMsg(rmTip,_T("set monster config error"));
}
}
bool CScene::GetPath(CEntity* pEntity, CVector<SMALLCPOINT> &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<int>(PROP_ENTITY_POSX);
INT_PTR nCurrentPosY = pEntity->GetProperty<int>(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<char>& 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<char>& 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(m_MonsterList);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::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<int>(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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(m_MonsterList);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::iterator iter = m_MonsterList.begin();
for (; iter != m_MonsterList.end(); ++iter)
{
CEntity* pEntity = pEntityMgr->GetEntity(iter->first);
#endif
if (pEntity)
{
pEntity->SetProperty<int>(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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(m_MonsterList);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::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<EntityHandle> *pNodeKill;
CLinkedListIterator<EntityHandle> killIt(killMonsterList);
for (pNodeKill = killIt.first(); pNodeKill; pNodeKill = killIt.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNodeKill->m_Data);
if (pEntity != NULL && !pEntity->IsDeath())
{
pEntity->SetProperty<int>(PROP_CREATURE_HP, 0);
if (nDropItem > 0)
{
((CMonster *)pEntity)->OnKilledByEntity(pGmEntity);
}
nCount++;
}
}
return nCount;
}
void CScene::ClearEntity(int nType)
{
CLinkedNode<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle,CMonster*>::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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(m_MonsterList);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(m_MonsterList);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::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<int>(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<EntityHandle> *pNode;
INT_PTR nEntityType = pEntity->GetType();
//CEntityList * pEntityList;
CLinkedListIterator<EntityHandle> 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<EntityHandle,CMonster*>::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<EntityHandle> it(m_PlayList);
for (CLinkedNode<EntityHandle> *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<EntityHandle> it(m_PlayList);
for (CLinkedNode<EntityHandle> *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<int>(PROP_ENTITY_MODELID,npcConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ICON,npcConfig->nIcon);
//((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营
//pEntity->SetProperty<UINT>(PROP_CREATURE_MAXHP,10000);
//pEntity->SetProperty<UINT>(PROP_CREATURE_HP,10000);
//pEntity->SetProperty<UINT>(PROP_CREATURE_MAXMP,10000);
//pEntity->SetProperty<UINT>(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<int>(PROP_ENTITY_MODELID,npcConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ICON,npcConfig->nIcon);
//((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营
//pEntity->SetProperty<UINT>(PROP_CREATURE_MAXHP,10000);
//pEntity->SetProperty<UINT>(PROP_CREATURE_HP,10000);
//pEntity->SetProperty<UINT>(PROP_CREATURE_MAXMP,10000);
//pEntity->SetProperty<UINT>(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<int>(PROP_ENTITY_MODELID,pNpcConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ICON,pNpcConfig->nIcon);
//((CNpc *)pEntity)->SetCamp(pNpcConfig->bCamp); //设置NPC的阵营
pEntity->SetProperty<UINT>(PROP_CREATURE_MAXHP,10000);
pEntity->SetProperty<UINT>(PROP_CREATURE_HP,10000);
pEntity->SetProperty<UINT>(PROP_CREATURE_MAXMP,10000);
pEntity->SetProperty<UINT>(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<int>(PROP_ENTITY_MODELID,npcConfig->nModelId);
pEntity->SetProperty<int>(PROP_ENTITY_ICON,npcConfig->nIcon);
//((CNpc *)pEntity)->SetCamp(npcConfig->bCamp); //设置NPC的阵营
pEntity->SetProperty<UINT>(PROP_CREATURE_MAXHP,10000);
pEntity->SetProperty<UINT>(PROP_CREATURE_HP,10000);
pEntity->SetProperty<UINT>(PROP_CREATURE_MAXMP,10000);
pEntity->SetProperty<UINT>(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<int>(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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> it(list);
for (pNode = it.first(); pNode; pNode = it.next())
{
CEntity* pEntity = pEntityMgr->GetEntity(pNode->m_Data);
#else
std::map<EntityHandle,CMonster*>::iterator iter = GetMonsterList().begin();
for (; iter != GetMonsterList().end() ; ++iter)
{
CEntity* pEntity = pEntityMgr->GetEntity(iter->first);
#endif
if (pEntity && (pEntity->GetProperty<int>(PROP_ENTITY_ID) == nMonsterId))
{
return pEntity;
}
}
return NULL;
}
int CScene::CalcAllActor(int nLevel)
{
int nResult = 0;
EntityHandle handler;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
CLinkedListIterator<EntityHandle> it(m_PlayList);
for (CLinkedNode<EntityHandle> *pNode = it.first(); pNode; pNode = it.next())
{
CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data));
if (pActor && pActor->IsInited() && !pActor->IsDestory() && pActor->GetProperty<int>(PROP_CREATURE_LEVEL) > nLevel)
{
nResult++;
}
}
return nResult;
}
int CScene::CloseSceneAllActor(int nLevel)
{
int nResult = 0;
EntityHandle handler;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
CLinkedListIterator<EntityHandle> it(m_PlayList);
for (CLinkedNode<EntityHandle> *pNode = it.first(); pNode; pNode = it.next())
{
CActor* pActor = (CActor *)(pEntityMgr->GetEntity(pNode->m_Data));
if (pActor && pActor->IsInited() && !pActor->IsDestory() && pActor->GetProperty<int>(PROP_CREATURE_LEVEL) > nLevel)
{
pActor->CloseActor(lwiGmTickActor,false);
nResult++;
}
}
return nResult;
}
int CScene::GetNowSceneGuildList()
{
int nResult = 0;
std::set<int> guildList;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
CLinkedListIterator<EntityHandle> it(m_PlayList);
for (CLinkedNode<EntityHandle> *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<int>(PROP_ACTOR_GUILD_ID);
guildList.insert(nGuildId);
}
}
if(guildList.size() == 1)
{
std::set<int>::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<EntityHandle> *pNode;
CLinkedListIterator<EntityHandle> 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); //修改了一个死循环
}
}