#include "StdAfx.h" #include "ObjectManager.h" #include "SYItem.h" #include "SYMount.h" #ifdef _DEBUG #include "Console.h" #endif // CObjectManager::CObjectManager() { m_pkLocalPlayer = NULL; m_uiLocalPlayerID = -1; pickentry nullentry; nullentry.penter = NiPoint3::ZERO; nullentry.enter = -FLT_MAX; nullentry.id = INVALID_OBJECT_ID; nullentry.obj = 0; nullentry.weight = 0; m_leastPickList.Clear(nullentry); m_ClientObjectGuid = 1; m_kObjectPicker.SetIntersectType(NiPick::TRIANGLE_INTERSECT);//使用三角形进行picker m_kObjectPicker.SetReturnTexture( false ); m_kObjectPicker.SetReturnNormal( false ); m_kObjectPicker.SetReturnSmoothNormal(false); m_kObjectPicker.SetReturnColor( false ); m_kObjectPicker.SetCoordinateType(NiPick::WORLD_COORDINATES); m_kObjectPicker.SetPickType( NiPick::FIND_FIRST ); m_kObjectPicker.SetSortType( NiPick::NO_SORT ); m_kBoundPicker.SetIntersectType(NiPick::BOUND_INTERSECT);//使用三角形进行picker m_kBoundPicker.SetReturnTexture( false ); m_kBoundPicker.SetReturnNormal( false ); m_kBoundPicker.SetReturnSmoothNormal(false); m_kBoundPicker.SetReturnColor( false ); m_kBoundPicker.SetCoordinateType(NiPick::WORLD_COORDINATES); m_kBoundPicker.SetPickType( NiPick::FIND_FIRST ); m_kBoundPicker.SetSortType( NiPick::NO_SORT ); } CObjectManager::~CObjectManager() { RemoveAll(); } bool CObjectManager::AddObject(UpdateObj* pkObject) { if (!pkObject) return false; ui64 guid = pkObject->GetGUID(); m_ObjectMap[guid] = pkObject; if( pkObject->GetTypeID() < TYPEID_UNUSED ) m_setObjectByType[pkObject->GetTypeID()].insert( pkObject ); AddToIDList(pkObject); return true; } void CObjectManager::AddToIDList(UpdateObj* pkObject) { if (!pkObject) return; ui64 uiGUID = pkObject->GetGUID(); int iIDType = GetIDT(pkObject); if (iIDType != -1) m_IDMAP[iIDType].insert(IDMAP::value_type(uiGUID, uiGUID)); } int CObjectManager::GetIDT(UpdateObj* pkObject) { int iIDType = -1; if (pkObject->isType(HIGHGUID_TYPE_ITEM) || pkObject->isType(HIGHGUID_TYPE_CONTAINER)) { iIDType = IDT_ITEM; } else if (pkObject->isType(HIGHGUID_TYPE_UNIT) || pkObject->isType(HIGHGUID_TYPE_PLAYER) || pkObject->isType(HIGHGUID_TYPE_PET)) { if (pkObject->GetGUID() == m_uiLocalPlayerID) { iIDType = IDT_LOCALPLAYER; } else { iIDType = IDT_CHAR; } } else if (pkObject->isType(HIGHGUID_TYPE_CORPSE)) { iIDType = IDT_CORPSE; } else if (pkObject->isType(HIGHGUID_TYPE_GAMEOBJECT)) { iIDType = IDT_SCENEOBJECT; } return iIDType; } void CObjectManager::RemoveGroupObjects(IDGroup eGroupType) { NIASSERT (eGroupType >= IDT_CHAR && eGroupType < IDT_NUM); if (eGroupType <= IDT_CHAR && eGroupType >= IDT_NUM) return; std::vector deleteList; IDMAP::iterator it = m_IDMAP[eGroupType].begin(); for (it; it != m_IDMAP[eGroupType].end(); ++it) { ui64 uiGUID = it->second; deleteList.push_back(uiGUID); } for (unsigned int i=0; isecond; if (pkObj) { char szBuffer[64]; int i = GetIDT(pkObj); NiSprintf(szBuffer, 64,"%d\n", i); OutputDebugString(szBuffer); if (g_pkConsole) g_pkConsole->Printf(szBuffer); } ++it; } } #endif //_DEBUG void CObjectManager::RemoveAll() { ObjectMap::const_iterator itr; for( itr = m_ObjectMap.begin(); itr != m_ObjectMap.end(); itr++ ) { if( itr->second == m_pkLocalPlayer ) m_pkLocalPlayer = NULL; NiDelete itr->second; } m_ObjectMap.clear(); for( int i = 0; i < TYPEID_UNUSED; ++i ) m_setObjectByType[i].clear(); for (unsigned int ui= 0; ui< IDT_NUM; ui++) { m_IDMAP[ui].clear(); } } void CObjectManager::RemoveObject(ui64 guid) { //直接删除, 在对象的Construct和Deconstruct里面要处理好和其他对象的关系 ObjectMap::iterator iter = m_ObjectMap.find(guid); if( iter != m_ObjectMap.end() ) { UpdateObj* p = iter->second; if( p->GetTypeID() < TYPEID_UNUSED ) m_setObjectByType[p->GetTypeID()].erase( p ); if( p == m_pkLocalPlayer ) m_pkLocalPlayer = NULL; int iIDType = GetIDT(p); if (iIDType != -1) { m_IDMAP[iIDType].erase(guid); } NiDelete p; m_ObjectMap.erase(iter); } } UpdateObj* CObjectManager::GetObjectByEntry(ui8 type, ui32 entry) { ObjectMap::iterator itr = m_ObjectMap.begin(); for( ; itr != m_ObjectMap.end(); ++itr ) { UpdateObj* pObj = itr->second; if( pObj->isType(type) && pObj->GetUInt32Value(OBJECT_FIELD_ENTRY) == entry ) { return pObj; } } return NULL; } UpdateObj* CObjectManager::GetObject(ui64 guid) { if( guid == 0 ) return NULL; ObjectMap::const_iterator iter = m_ObjectMap.find(guid); if( iter != m_ObjectMap.end() ) { return iter->second; } return NULL; } UpdateObj* CObjectManager::GetObjectByName(const NiFixedString& kName) { // ObjectMap::const_iterator itr; // for( itr = m_ObjectMap.begin(); itr != m_ObjectMap.end(); itr++ ) // { // if( itr->second->GetName() == kName ) // return itr->second; // } return NULL; } const stdext::hash_set& CObjectManager::GetObjectByType(ui8 type) const { /* ObjectMap::iterator itr = m_ObjectMap.begin(); for( ; itr != m_ObjectMap.end(); ++itr ) { UpdateObj* pObj = itr->second; if( pObj->isType(type)) { vList.push_back(pObj); } } */ return m_setObjectByType[type]; } ////////////////////////////////////////////////////////////////////////// CPlayer* CObjectManager::CreatePlayer(ui64 guid, BOOL bLocSelf, bool bInWorld /*= true*/) { CPlayer* pkPlayer = NULL; if (bLocSelf) { pkPlayer = NiNew CPlayerLocal; m_uiLocalPlayerID = guid; } else { pkPlayer = NiNew CPlayer; } if (!pkPlayer) return 0; pkPlayer->SetInWorld(bInWorld); pkPlayer->SetGUID(guid); AddObject(pkPlayer); return pkPlayer; } CPlayer* CObjectManager::GetPlayer(ui64 guid) { return (CPlayer*)GetObject(guid); } void CObjectManager::SetLocalPlayer(CPlayerLocal* pkPlayer) { NIASSERT(pkPlayer && pkPlayer->IsLocalPlayer()); m_pkLocalPlayer = (CPlayerLocal*)pkPlayer; m_uiLocalPlayerID = pkPlayer->GetGUID(); } CCreature* CObjectManager::CreateCreature(ui64 guid) { CCreature* pkMonster = NiNew CCreature; pkMonster->SetInWorld(true); pkMonster->SetGUID(guid); AddObject(pkMonster); return pkMonster; } SYItem* CObjectManager::CreateSYItem(ui64 guid) { SYItem* pSYItem = (SYItem*)GetObject(guid); if( !pSYItem || pSYItem->isType(TYPE_ITEM) ) { pSYItem = NiNew SYItem; pSYItem->SetGUID(guid); AddObject(pSYItem); } return pSYItem; } SYItemBag* CObjectManager::CreateSYBag(ui64 guid) { SYItemBag* pSYItem = (SYItemBag*)GetObject(guid); if( !pSYItem || pSYItem->isType(TYPE_CONTAINER) ) { pSYItem = NiNew SYItemBag; pSYItem->SetGUID(guid); AddObject(pSYItem); } return pSYItem; } CSceneItem* CObjectManager::CreateSceneItem(ui64 guid, bool isContainer) { CSceneItem* pkGameItem = NiNew CSceneItem; pkGameItem->Init( isContainer ); pkGameItem->SetGUID(guid); AddObject(pkGameItem); return pkGameItem; } CDynamicObj* CObjectManager::CreateDynamicObj(ui64 guid) { CDynamicObj* pkDYOBJ = NiNew CDynamicObj; pkDYOBJ->SetGUID(guid); AddObject(pkDYOBJ); return pkDYOBJ; } CSceneGameObj* CObjectManager::CreateSceneGameObj(ui64 guid) { CSceneGameObj* pkSGO = NiNew CSceneGameObj; pkSGO->SetGUID(guid); AddObject(pkSGO); return pkSGO; } void CObjectManager::AddObjBaseInfo(ui64 guid, sObjBaseInfo baseInfo) { m_ObjBaseMap[guid] = baseInfo; } sObjBaseInfo* CObjectManager::GetObjBaseInfo(ui64 guid) { ObjBaseMap::const_iterator iter = m_ObjBaseMap.find(guid); if( iter != m_ObjBaseMap.end() ) { return (sObjBaseInfo*)&(iter->second); } return NULL; } // *untested code* // ray-aabb test along one axis bool rayAABBIntersect1D(float start, float dir, float length, float min, float max, float& enter, float& exit) { // ray parallel to direction if(fabs(dir) < 1.0E-8) return (start >= min && start <= max); // intersection params float t0, t1; t0 = (min - start) / dir; t1 = (max - start) / dir; // sort intersections if(t0 > t1) swap(t0, t1); // reduce interval if(t0 > enter) enter = t0; if(t1 < exit) exit = t1; // ray misses the box if(exit < enter) return false; // intersections outside ray boundaries if(exit < 0.0f || enter > length) return false; return true; } bool rayAABBIntersect(NiPoint3 start, NiPoint3 dir, float length, NiPoint3 min, NiPoint3 max, NiPoint3& penter, NiPoint3& pexit, float& ent, float& ex) { float enter = -FLT_MAX, exit = FLT_MAX; if(!rayAABBIntersect1D(start.x, dir.x, length, min.x, max.x, enter, exit)) return false; if(!rayAABBIntersect1D(start.y, dir.y, length, min.y, max.y, enter, exit)) return false; if(!rayAABBIntersect1D(start.z, dir.z, length, min.z, max.z, enter, exit)) return false; ent = enter; ex = exit; penter = start + dir * enter; pexit = start + dir * exit; return true; } CGameObject* CObjectManager::PickObject(const NiPoint3& ptOrig, const NiPoint3& vDir, NiPoint3& ptPickPos, bool first /*= false*/, bool bLoot /*= false*/, int iIncWeight /*= 0*/) { std::vector pickList; IDMAP::iterator it = m_IDMAP[IDT_CHAR].begin(); for (it; it != m_IDMAP[IDT_CHAR].end(); ++it) { ui64 uiGUID = it->second; pickList.push_back(uiGUID); } it = m_IDMAP[IDT_CORPSE].begin(); for (it; it != m_IDMAP[IDT_CORPSE].end(); ++it) { ui64 uiGUID = it->second; pickList.push_back(uiGUID); } it = m_IDMAP[IDT_SCENEOBJECT].begin(); for(it; it != m_IDMAP[IDT_SCENEOBJECT].end(); ++it) { ui64 uiGUID = it->second; pickList.push_back(uiGUID); } it = m_IDMAP[IDT_ITEM].begin(); for (it; it != m_IDMAP[IDT_ITEM].end(); ++it) { ui64 uiGuid = it->second; UpdateObj* pkObj = GetObject(uiGuid); if (pkObj && pkObj->IsMapItem() ) { pickList.push_back(uiGuid); } } static const unsigned int sc_uiLeastPickObjNumLimit = 5; static const unsigned int sc_uiInitWeight = 1; std::list potential; int iHitCount = 0; for (unsigned int ui = 0; ui < pickList.size(); ui++) { CGameObject* pkObject = (CGameObject*)GetObject(pickList[ui]); extern bool g_bHiddenPlayer; if(g_bHiddenPlayer && pkObject->GetAsPlayer() && pkObject != m_pkLocalPlayer) continue; if ( !pkObject ) continue; NiPoint3 kPos = pkObject->GetPosition(); NiPoint3 vObjRay = kPos - ptOrig; float fDistance = (kPos - ptOrig).Length(); float fAngle = vDir.Dot(vObjRay); if ( fAngle < 0.738) // eraliy exit continue; NiBound kBound; if (!pkObject->GetPickBound(kBound)) continue; NiPoint3 kMin, kMax; kBound.GetAABB(kMin, kMax); NiPoint3 center = (kMin + kMax)/2.f; kMin = (kMin - center) * 1.3f + center; kMax = (kMax - center) * 1.3f + center; float fEnter, fExit; NiPoint3 enter, exit; bool bret = false; const NiPoint3& kCameraPos = m_pkLocalPlayer->GetCamera().GetTranslate(); const NiPoint3& kTargetPos = pkObject->GetPosition(); float fDistanceToCamera = (kTargetPos - kCameraPos).Length(); if ( pkObject->HasAnimBound() ) { m_kBoundPicker.SetTarget( pkObject->GetSceneNode() ); bret = m_kBoundPicker.PickObjects(ptOrig, vDir); fEnter = fDistanceToCamera; } else bret = rayAABBIntersect(ptOrig, vDir, 300, kMin, kMax, enter, exit, fEnter, fExit); if (bret) { if ( fDistanceToCamera <= 1400.0f && pkObject->HasAnimBound() ) { if ( pkObject->IsPick(m_kObjectPicker, ptOrig, vDir) ) { if (first) { ptPickPos = enter; return pkObject; } pickentry entry; entry.id = pkObject->GetGUID(); entry.enter = fEnter; entry.obj = pkObject; entry.penter = enter; entry.weight = 1; potential.push_back(entry); if (++iHitCount >= sc_uiLeastPickObjNumLimit) break; } } else { if (first) { ptPickPos = enter; return pkObject; } pickentry entry; entry.id = pkObject->GetGUID(); entry.enter = fDistance; entry.obj = pkObject; entry.penter = enter; entry.weight = 1; potential.push_back(entry); if (++iHitCount >= sc_uiLeastPickObjNumLimit) break; } } } if (iHitCount >= 1) { std::list::iterator it2 = potential.begin(); float fLastMinDistance = 99999.0f; ui64 nRetObjectID = NULL; while (it2 != potential.end()) { pickentry& newentry = *it2; if ( newentry.enter < fLastMinDistance ) { fLastMinDistance = newentry.enter; nRetObjectID = newentry.id; } ++it2; } return (CGameObject*)GetObject(nRetObjectID); //potential.sort(); //int ind = -1; //int lastweight = 0; //unsigned int ui = 0; //std::list::iterator it = potential.begin(); //if(bLoot) //{ // while (it != potential.end()) // { // if (it->id != m_leastPickList[ui].id && it->obj->IsLootAble()) // { // pickentry& newentry = *it; // newentry.weight++; // m_leastPickList.AddHead(newentry); // ptPickPos = m_leastPickList[ind].penter; // return (CGameObject*)GetObject(newentry.id); // } // ++it; // } //} //it = potential.begin(); //if (it->id != m_leastPickList[ui].id) //{ // pickentry& newentry = *it; // newentry.weight++; // m_leastPickList.AddHead(newentry); // ind = 0; //} //lastweight = m_leastPickList[ui].weight; //while (ind == -1 && it != potential.end() && ui < 5) //{ // pickentry& entry = m_leastPickList[ui]; // if (it->id != entry.id) // { // entry = *it; // entry.weight++; // ind = ui; // break; // } // ++ui; // ++it; //} //if (ind == -1) //{ // ind = 0; // for (unsigned int ui = 1; ui < 5; ui++) // { // pickentry nullentry; // nullentry.penter = NiPoint3::ZERO; // nullentry.enter = -FLT_MAX; // nullentry.id = INVALID_OBJECT_ID; // nullentry.obj = 0; // nullentry.weight = 0; // m_leastPickList[ui] = nullentry; // } //} //ptPickPos = m_leastPickList[ind].penter; //return (CGameObject*)GetObject(m_leastPickList[ind].id); } return 0; } CGameObject* CObjectManager::FindNearByObj(CGameObject* pkLocalPlayer, float fRadius, UINT Groups, float& fDistance) { NiPoint3 kPos = pkLocalPlayer->GetPosition(); CGameObject* pkReturnObj = NULL; CGameObject* pkGameObj = NULL; switch(Groups) { case GOT_SCENEOBJECT: { IDMAP::iterator it = m_IDMAP[IDT_LOCALPLAYER].begin(); for (it; it != m_IDMAP[IDT_LOCALPLAYER].end(); ++it) { ui64 uiGUID = it->second; CGameObject* pkObject = (CGameObject*)GetObject(uiGUID); NIASSERT(pkObject); if (pkObject) { fDistance = (kPos - pkObject->GetPosition()).Length(); if(fDistance < fRadius) { fRadius = fDistance; pkReturnObj = pkObject; } } } } break; default: fDistance = -FLT_MAX; } return pkReturnObj; } CPlayer* CObjectManager::CreateClientPlayer() { ui64 guid = GenClientGuid(); CPlayer* pkPlayer = NiNew CPlayer; pkPlayer->SetGUID(guid); pkPlayer->SetClientObject(true); m_ClientObjectMap[guid] = pkPlayer; return pkPlayer; } CPlayer* CObjectManager::GetClientPlayer(ui64 guid) { ObjectMap::const_iterator iter = m_ClientObjectMap.find(guid); if( iter != m_ClientObjectMap.end() ) { return (CPlayer*)iter->second; } return NULL; } void CObjectManager::RemoveClientPlayer(ui64 guid) { ObjectMap::iterator iter = m_ClientObjectMap.find(guid); if( iter != m_ClientObjectMap.end() ) { NiDelete iter->second; m_ClientObjectMap.erase(iter); } }