1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015 |
- #include "StdAfx.h"
- #include "World.h"
- #include "Client.h"
- #include "PhysicsObj.h"
- #include "Monster.h"
- #include "Player.h"
- #include "ChatMsgs.h"
- //Database access
- #include "Database.h"
- #include "CharacterDatabase.h"
- #include "TurbineDungeon.h"
- #include "GameMode.h"
- CWorld::CWorld()
- {
- LOG(Temp, Normal, "Initializing World..\n");
- m_dwHintStaticGUID = 0x10000000;
- m_dwHintPlayerGUID = 0x50000000;
- m_dwHintItemGUID = 0x60000000;
- m_dwHintDynamicGUID = 0xC0000000;
- ZeroMemory(m_pBlocks, sizeof(m_pBlocks));
- LoadStateFile();
- LoadDungeonsFile();
- LoadMOTD();
- EnumerateDungeonsFromCellData();
- m_fLastSave = g_pGlobals->Time();
- m_pGameMode = NULL;
- }
- void CWorld::SaveWorld()
- {
- SaveDungeonsFile();
- SaveStateFile();
- }
- CWorld::~CWorld()
- {
- if (m_pGameMode)
- {
- delete m_pGameMode;
- m_pGameMode = NULL;
- }
- for (LandblockVector::iterator it = m_vBlocks.begin(); it != m_vBlocks.end(); it++)
- delete (*it);
- m_vBlocks.clear();
- SaveWorld();
- m_mDungeons.clear();
- for (DungeonDescMap::iterator it = m_mDungeonDescs.begin(); it != m_mDungeonDescs.end(); it++)
- {
- DungeonDesc_t* pdd = &it->second;
- SafeDeleteArray(pdd->szDungeonName);
- SafeDeleteArray(pdd->szDescription);
- SafeDeleteArray(pdd->szAuthor);
- }
- m_mDungeonDescs.clear();
- }
- loc_t CWorld::FindDungeonDrop()
- {
- if (m_mDungeons.empty())
- {
- loc_t di;
- memset(&di, 0, sizeof(di));
- return di;
- }
- LocationMap::iterator dit = m_mDungeons.begin();
- long index = RandomLong(0, (long)m_mDungeons.size() - 1);
- while (index > 0) {
- index--;
- dit++;
- }
- return dit->second;
- }
- loc_t CWorld::FindDungeonDrop(WORD wBlockID)
- {
- LocationMap::iterator i = m_mDungeons.upper_bound(((DWORD(wBlockID) << 16) + 0x100) - 1);
- if ((i == m_mDungeons.end()) || (BLOCK_WORD(i->second.landcell) != wBlockID))
- {
- loc_t di;
- memset(&di, 0, sizeof(di));
- return di;
- }
- return i->second;
- }
- void CWorld::LoadStateFile()
- {
- FILE *ws = g_pDB->DataFileOpen("worldstate");
- if (ws)
- {
- fread(&m_dwHintStaticGUID, sizeof(DWORD), 1, ws);
- fread(&m_dwHintItemGUID, sizeof(DWORD), 1, ws);
- fread(&m_dwHintPlayerGUID, sizeof(DWORD), 1, ws);
- fread(&m_dwHintDynamicGUID, sizeof(DWORD), 1, ws);
- fclose(ws);
- }
- }
- void CWorld::SaveStateFile()
- {
- FILE *ws = g_pDB->DataFileCreate("worldstate");
- if (ws)
- {
- fwrite(&m_dwHintStaticGUID, sizeof(DWORD), 1, ws);
- fwrite(&m_dwHintItemGUID, sizeof(DWORD), 1, ws);
- fwrite(&m_dwHintPlayerGUID, sizeof(DWORD), 1, ws);
- fwrite(&m_dwHintDynamicGUID, sizeof(DWORD), 1, ws);
- fclose(ws);
- }
- else
- MsgBox(MB_ICONHAND, "Error opening WorldState file! Close NOW to avoid corruption!");
- }
- const char* CWorld::GetMOTD()
- {
- return m_strMOTD.c_str();
- }
- void CWorld::LoadMOTD()
- {
- FILE *motd = g_pDB->DataFileOpen("motd.txt", "rt");
- if (motd)
- {
- long lFileSize = fsize(motd);
- char* pcFileData = new char[lFileSize + 1];
- long lEnd = (long)fread(pcFileData, sizeof(char), lFileSize, motd);
- pcFileData[lEnd] = 0;
- m_strMOTD = pcFileData;
- delete[] pcFileData;
- fclose(motd);
- }
- else
- m_strMOTD = "No MOTD set.";
- }
- void CWorld::LoadDungeonsFile()
- {
- FILE *wd = g_pDB->DataFileOpen("worlddesc");
- if (wd)
- {
- long lSize = fsize(wd);
- BYTE* pbData = new BYTE[lSize];
- long lRead = (long)fread(pbData, sizeof(BYTE), lSize, wd);
- BinaryReader input(pbData, lRead);
- DWORD dwDungeonCount = input.ReadDWORD();
- if (!input.GetLastError())
- {
- for (DWORD i = 0; i < dwDungeonCount; i++)
- {
- DungeonDesc_t dd;
- dd.wBlockID = input.ReadWORD();
- dd.szDungeonName = input.ReadString();
- dd.szAuthor = input.ReadString();
- dd.szDescription = input.ReadString();
- loc_t* origin = (loc_t *)input.ReadArray(sizeof(loc_t));
- heading_t* angles = (heading_t *)input.ReadArray(sizeof(heading_t));
- if (input.GetLastError()) break;
- //Avoid using a buffer thats going to be deleted.
- dd.szDungeonName = _strdup(dd.szDungeonName);
- dd.szAuthor = _strdup(dd.szAuthor);
- dd.szDescription = _strdup(dd.szDescription);
- memcpy(&dd.origin, origin, sizeof(loc_t));
- memcpy(&dd.angles, angles, sizeof(heading_t));
- m_mDungeonDescs[dd.wBlockID] = dd;
- }
- }
- delete[] pbData;
- fclose(wd);
- }
- }
- void CWorld::SaveDungeonsFile()
- {
- FILE *wd = g_pDB->DataFileCreate("worlddesc");
- if (wd)
- {
- BinaryWriter output;
- output.WriteDWORD((DWORD)m_mDungeonDescs.size());
- for (DungeonDescMap::iterator i = m_mDungeonDescs.begin(); i != m_mDungeonDescs.end(); i++)
- {
- output.WriteWORD(i->second.wBlockID);
- output.WriteString(i->second.szDungeonName);
- output.WriteString(i->second.szAuthor);
- output.WriteString(i->second.szDescription);
- output.AppendData(i->second.origin);
- output.AppendData(i->second.angles);
- }
- fwrite(output.GetData(), output.GetSize(), sizeof(BYTE), wd);
- fclose(wd);
- }
- else
- MsgBox(MB_ICONHAND, "Error opening WorldDesc file! Close NOW to avoid corruption!");
- }
- BOOL CWorld::DungeonExists(WORD wBlockID)
- {
- LocationMap::iterator i = m_mDungeons.upper_bound(((DWORD(wBlockID) << 16) + 0x100) - 1);
- if ((i == m_mDungeons.end()) || (BLOCK_WORD(i->second.landcell) != wBlockID))
- return FALSE;
- return TRUE;
- }
- LocationMap* CWorld::GetDungeons()
- {
- return &m_mDungeons;
- }
- DungeonDescMap* CWorld::GetDungeonDescs()
- {
- return &m_mDungeonDescs;
- }
- DungeonDesc_t* CWorld::GetDungeonDesc(const char* szDungeonName)
- {
- DungeonDescMap::iterator i = m_mDungeonDescs.begin();
- DungeonDescMap::iterator iend = m_mDungeonDescs.end();
- while (i != iend)
- {
- if (!stricmp(szDungeonName, i->second.szDungeonName))
- return &i->second;
- i++;
- }
- return NULL;
- }
- DungeonDesc_t* CWorld::GetDungeonDesc(WORD wBlockID)
- {
- DungeonDescMap::iterator it = m_mDungeonDescs.find(wBlockID);
- if (it != m_mDungeonDescs.end())
- return &it->second;
- else
- return NULL;
- }
- void CWorld::SetDungeonDesc(WORD wBlockID, const char* szDungeonName, const char* szAuthor, const char* szDescription, loc_t origin, heading_t angles)
- {
- DungeonDescMap::iterator it = m_mDungeonDescs.find(wBlockID);
- if (it != m_mDungeonDescs.end())
- {
- DungeonDesc_t* pdd = &it->second;
- SafeDeleteArray(pdd->szDungeonName);
- SafeDeleteArray(pdd->szDescription);
- SafeDeleteArray(pdd->szAuthor);
- m_mDungeonDescs.erase(it);
- }
- DungeonDesc_t dd;
- dd.wBlockID = wBlockID;
- dd.szDungeonName = _strdup(szDungeonName);
- dd.szAuthor = _strdup(szAuthor);
- dd.szDescription = _strdup(szDescription);
- dd.origin = origin;
- dd.angles = angles;
- m_mDungeonDescs[wBlockID] = dd;
- }
- void CWorld::InitializeHintGUIDs()
- {
- _CHARDESC dummy;
- CCharacterDatabase *CharDB = g_pDB->CharDB();
- while (CharDB->GetCharacterDesc(m_dwHintPlayerGUID, &dummy))
- m_dwHintPlayerGUID++;
- }
- //Hackish.
- DWORD CWorld::GenerateGUID(eGUIDClass type)
- {
- switch (type)
- {
- case ePresetGUID: return 0;
- case ePlayerGUID:
- {
- // 0x50000000 - 0x60000000
- if (m_dwHintPlayerGUID >= 0x60000000)
- {
- LOG(Temp, Normal, "Player GUID overflow!\n");
- return 0;
- }
- _CHARDESC dummy;
- CCharacterDatabase *CharDB = g_pDB->CharDB();
- while (CharDB->GetCharacterDesc(m_dwHintPlayerGUID, &dummy))
- m_dwHintPlayerGUID++;
- //Temporary, use and increment the hint counter.
- return (m_dwHintPlayerGUID++);
- }
- case eStaticGUID:
- {
- /* 0x10000000 - 0x50000000 */
- if (m_dwHintStaticGUID >= 0x50000000)
- {
- LOG(Temp, Normal, "Static GUID overflow!\n");
- return 0;
- }
- //Temporary, use and increment the hint counter.
- return (m_dwHintStaticGUID++);
- }
- case eDynamicGUID:
- {
- // 0xC0000000 - 0xF0000000
- if (m_dwHintDynamicGUID >= 0xF0000000)
- {
- LOG(Temp, Normal, "Dynamic GUID overflow!\n");
- return 0;
- }
- //Temporary, use and increment the hint counter.
- return (m_dwHintDynamicGUID++);
- }
- case eItemGUID:
- {
- // 0x60000000 - 0xC0000000
- if (m_dwHintItemGUID >= 0xC0000000)
- {
- LOG(Temp, Normal, "Item GUID overflow!\n");
- return 0;
- }
- //Temporary, use and increment the hint counter.
- return (m_dwHintItemGUID++);
- }
- }
- return 0;
- }
- void CWorld::ClearAllSpawns()
- {
- for (DWORD i = 0; i < (256 * 256); i++)
- {
- if (m_pBlocks[i])
- m_pBlocks[i]->ClearSpawns();
- }
- }
- CLandBlock* CWorld::GetLandblock(WORD wHeader)
- {
- return m_pBlocks[wHeader];
- }
- CLandBlock* CWorld::ActivateBlock(WORD wHeader)
- {
- CLandBlock **ppBlock = &m_pBlocks[wHeader];
- CLandBlock *pBlock;
- #if _DEBUG
- pBlock = *ppBlock;
- if (pBlock != NULL)
- {
- LOG(Temp, Normal, "Landblock already active!\n");
- return pBlock;
- }
- #endif
- pBlock = new CLandBlock(this, wHeader);
- m_vSpawns.push_back(pBlock);
- *ppBlock = pBlock;
- return pBlock;
- }
- void CWorld::CreateEntity(CPhysicsObj *pEntity)
- {
- pEntity->Precache();
- #if _DEBUG
- if (!pEntity->m_dwGUID)
- {
- LOG(Temp, Normal, "Null entid being placed in world.\n");
- return;
- }
- #endif
- WORD wHeader = BLOCK_WORD(pEntity->GetLandcell());
- if (pEntity->IsPlayer())
- {
- DWORD dwGUID = pEntity->m_dwGUID;
- m_mAllPlayers.insert(std::pair< DWORD, CBasePlayer* >(dwGUID, (CBasePlayer *)pEntity));
- BroadcastGlobal(ServerBroadcast("System", csprintf("%s has logged in.", pEntity->GetName()), 1), PRIVATE_MSG, dwGUID, FALSE, TRUE);
- }
- CLandBlock *pBlock = m_pBlocks[wHeader];
- if (pBlock)
- {
- if (pBlock->FindEntity(pEntity->m_dwGUID))
- {
- // DEBUGOUT("Not spawning duplicate entity!\n");
- // Already exists.
- delete pEntity;
- return;
- }
- }
- if (!pBlock)
- pBlock = ActivateBlock(wHeader);
- pBlock->Insert(pEntity, 0, TRUE);
- pEntity->MakeAware(pEntity);
- pEntity->Spawn();
- }
- void CWorld::InsertTeleportLocation(TeleTownList_s l)
- {
- m_vTeleTown.push_back(l);
- }
- std::string CWorld::GetTeleportList()
- {
- std::string result;
- for each (TeleTownList_s var in m_vTeleTown)
- {
- result.append(var.m_teleString).append(", ");
- }
- if (result.back() == 0x20) { //Get out behind of bad formatting
- result.pop_back();
- result.pop_back();
- }
- return result;
- }
- TeleTownList_s CWorld::GetTeleportLocation(std::string location)
- {
- TeleTownList_s val;
- std::transform(location.begin(), location.end(), location.begin(), ::tolower);
- for each (TeleTownList_s var in m_vTeleTown)
- {
- //Lets waste a bunch of time with this.. Hey, if its the first one on the list its O(1)
- std::string town = var.m_teleString;
- std::transform(town.begin(), town.end(), town.begin(), ::tolower);
- if (town.find(location) != std::string::npos) {
- val = var;
- break;
- }
- }
- return val;
- }
- void CWorld::InsertEntity(CPhysicsObj *pEntity, BOOL bSilent)
- {
- WORD wHeader = BLOCK_WORD(pEntity->GetLandcell());
- CLandBlock *pBlock = m_pBlocks[wHeader];
- if (!pBlock)
- pBlock = ActivateBlock(wHeader);
- if (bSilent)
- pBlock->Insert(pEntity, wHeader);
- else
- pBlock->Insert(pEntity);
- if (pEntity->IsPlayer())
- m_mAllPlayers.insert(std::pair< DWORD, CBasePlayer* >(pEntity->m_dwGUID, (CBasePlayer *)pEntity));
- }
- void CWorld::JuggleEntity(WORD wOld, CPhysicsObj* pEntity)
- {
- if (!pEntity->HasOwner())
- {
- WORD wHeader = BLOCK_WORD(pEntity->GetLandcell());
- CLandBlock *pBlock = GetLandblock(wHeader);
- if (!pBlock)
- pBlock = ActivateBlock(wHeader);
- pBlock->Insert(pEntity, wOld);
- }
- }
- PlayerMap* CWorld::GetPlayers()
- {
- return &m_mAllPlayers;
- }
- //==================================================
- //Global, player search by GUID.
- //==================================================
- CBasePlayer* CWorld::FindPlayer(DWORD dwGUID)
- {
- PlayerMap::iterator result = m_mAllPlayers.find(dwGUID);
- if (result == m_mAllPlayers.end())
- return NULL;
- return result->second;
- }
- //==================================================
- //Global, case insensitive player name search.
- //==================================================
- CBasePlayer* CWorld::FindPlayer(const char *szName)
- {
- if (*szName == '+')
- szName++;
- PlayerMap::iterator pit = m_mAllPlayers.begin();
- PlayerMap::iterator pend = m_mAllPlayers.end();
- while (pit != pend)
- {
- CBasePlayer *pPlayer = pit->second;
- if (pPlayer)
- {
- const char* szPN = pPlayer->GetName();
- if (*szPN == '+')
- szPN++;
- if (!stricmp(szName, szPN))
- return pPlayer;
- }
- pit++;
- }
- return NULL;
- }
- void CWorld::BroadcastPVS(DWORD dwCell, void *_data, DWORD _len, WORD _group, DWORD ignore_ent, BOOL _game_event)
- {
- if (!dwCell)
- return;
- // Don't ask.
- WORD block = BLOCK_WORD(dwCell);
- WORD cell = CELL_WORD(dwCell);
- DWORD basex = BASE_OFFSET(BLOCK_X(block), CELL_X(cell));
- DWORD basey = BASE_OFFSET(BLOCK_Y(block), CELL_Y(cell));
- DWORD minx = basex;
- DWORD maxx = basex;
- DWORD miny = basey;
- DWORD maxy = basey;
- //if ( cell < 0xFF ) //indoor structure
- {
- if (minx >= (dwMinimumCellX + PVC_RANGE)) minx -= PVC_RANGE; else minx = dwMinimumCellX;
- if (maxx <= (dwMaximumCellX - PVC_RANGE)) maxx += PVC_RANGE; else maxx = dwMaximumCellX;
- if (miny >= (dwMinimumCellY + PVC_RANGE)) miny -= PVC_RANGE; else miny = dwMinimumCellY;
- if (maxy <= (dwMaximumCellY - PVC_RANGE)) maxy += PVC_RANGE; else maxy = dwMaximumCellY;
- }
- minx = BLOCK_OFFSET(minx) << 8;
- miny = BLOCK_OFFSET(miny);
- maxx = BLOCK_OFFSET(maxx) << 8;
- maxy = BLOCK_OFFSET(maxy);
- for (DWORD xit = minx; xit <= maxx; xit += 0x100) {
- for (DWORD yit = miny; yit <= maxy; yit += 1)
- {
- CLandBlock* pBlock = m_pBlocks[xit | yit];
- if (pBlock)
- pBlock->Broadcast(_data, _len, _group, ignore_ent, _game_event);
- }
- }
- }
- void CWorld::BroadcastGlobal(BinaryWriter *food, WORD _group, DWORD ignore_ent, BOOL _game_event, BOOL del)
- {
- BroadcastGlobal(food->GetData(), food->GetSize(), _group, ignore_ent, _game_event);
- if (del)
- delete food;
- }
- void CWorld::BroadcastGlobal(void *_data, DWORD _len, WORD _group, DWORD ignore_ent, BOOL _game_event)
- {
- //This is a.. very.. very bad.
- #if TRUE
- //We could send with the player map.
- PlayerMap::iterator pit = m_mAllPlayers.begin();
- PlayerMap::iterator pend = m_mAllPlayers.end();
- while (pit != pend)
- {
- CBasePlayer *pPlayer;
- if (pPlayer = pit->second)
- {
- if (!ignore_ent || (pPlayer->m_dwGUID != ignore_ent))
- pPlayer->SendNetMessage(_data, _len, _group, _game_event);
- }
- pit++;
- }
- #else
- //We could also send by landblocks instead.
- LandblockVector::iterator lit = m_vBlocks.begin();
- LandblockVector::iterator lend = m_vBlocks.end();
- while (lit != lend)
- {
- CLandBlock *pBlock;
- if (pBlock = (*lit))
- pBlock->Broadcast(_data, _len, _group, ignore_ent, _game_event);
- lit++;
- }
- #endif
- }
- void CWorld::Test()
- {
- LOG(Temp, Normal, "<CWorld::Test()>\n");
- LOG(Temp, Normal, "Portal: v%lu, %lu files.\n", g_pPortal->GetVersion(), g_pPortal->GetFileCount());
- LOG(Temp, Normal, "Cell: v%lu, %u files.\n", g_pCell->GetVersion(), g_pCell->GetFileCount());
- LOG(Temp, Normal, "%u players:\n", m_mAllPlayers.size());
- for (PlayerMap::iterator pit = m_mAllPlayers.begin(); pit != m_mAllPlayers.end(); pit++)
- {
- CBasePlayer* pPlayer = pit->second;
- LOG(Temp, Normal, "%08X %s\n", pPlayer->m_dwGUID, pPlayer->GetName());
- }
- LOG(Temp, Normal, "%u active blocks:\n", m_vBlocks.size());
- for (LandblockVector::iterator it = m_vBlocks.begin(); it != m_vBlocks.end(); it++)
- {
- CLandBlock* pBlock = *it;
- LOG(Temp, Normal, "%08X %lu players %lu live %lu dormant\n", pBlock->GetHeader() << 16, pBlock->PlayerCount(), pBlock->LiveCount(), pBlock->DormantCount());
- }
- LOG(Temp, Normal, "</CWorld::Test()>\n");
- }
- void CWorld::RemoveEntity(CPhysicsObj *pEntity)
- {
- if (!pEntity)
- {
- return;
- }
- if (m_pGameMode)
- {
- m_pGameMode->OnRemoveEntity(pEntity);
- }
- DWORD dwGUID = pEntity->m_dwGUID;
- if (pEntity->IsPlayer())
- {
- m_mAllPlayers.erase(dwGUID);
- BroadcastGlobal(ServerBroadcast("System", csprintf("%s has logged out.", pEntity->GetName()), 1), PRIVATE_MSG, dwGUID, FALSE, TRUE);
- }
- CLandBlock* pBlock = pEntity->GetBlock();
- if (!pBlock)
- {
- pEntity->Save();
- DELETE_ENTITY(pEntity);
- }
- else
- {
- pBlock->Destroy(pEntity);
- }
- }
- void CWorld::Think()
- {
- LandblockVector::iterator lit = m_vBlocks.begin();
- LandblockVector::iterator lend = m_vBlocks.end();
- while (lit != lend)
- {
- CLandBlock *pBlock = *lit;
- if (pBlock->Think())
- lit++;
- else
- {
- //dead
- lit = m_vBlocks.erase(lit);
- lend = m_vBlocks.end();
- m_pBlocks[pBlock->GetHeader()] = NULL;
- delete pBlock;
- }
- }
- if (!m_vSpawns.empty())
- {
- std::copy(m_vSpawns.begin(), m_vSpawns.end(), std::back_inserter(m_vBlocks));
- m_vSpawns.clear();
- }
- if ((m_fLastSave + 300.0f) <= g_pGlobals->Time())
- {
- SaveWorld();
- m_fLastSave = g_pGlobals->Time();
- }
- if (m_pGameMode)
- {
- m_pGameMode->Think();
- }
- }
- CGameMode *CWorld::GetGameMode()
- {
- return m_pGameMode;
- }
- void CWorld::SetNewGameMode(CGameMode *pGameMode)
- {
- if (pGameMode)
- {
- g_pWorld->BroadcastGlobal(ServerText(csprintf("Setting game mode to %s", pGameMode->GetName())), PRIVATE_MSG);
- }
- else
- {
- if (!pGameMode && m_pGameMode)
- {
- g_pWorld->BroadcastGlobal(ServerText(csprintf("Turning off game mode %s", m_pGameMode->GetName())), PRIVATE_MSG);
- }
- }
- if (m_pGameMode)
- {
- delete m_pGameMode;
- }
- m_pGameMode = pGameMode;
- }
- void CWorld::EnumNearby(CPhysicsObj *pSource, float fRange, std::list<CPhysicsObj *> *pResults)
- {
- // Enumerate nearby world objects
- if (pSource != NULL && !pSource->HasOwner())
- {
- DWORD dwCell = pSource->GetLandcell();
- WORD block = BLOCK_WORD(dwCell);
- WORD cell = CELL_WORD(dwCell);
- DWORD basex = BASE_OFFSET(BLOCK_X(block), CELL_X(cell));
- DWORD basey = BASE_OFFSET(BLOCK_Y(block), CELL_Y(cell));
- DWORD minx = basex;
- DWORD maxx = basex;
- DWORD miny = basey;
- DWORD maxy = basey;
- //if ( cell < 0xFF ) // indoor structure
- {
- if (minx >= (dwMinimumCellX + PVC_RANGE)) minx -= PVC_RANGE; else minx = dwMinimumCellX;
- if (maxx <= (dwMaximumCellX - PVC_RANGE)) maxx += PVC_RANGE; else maxx = dwMaximumCellX;
- if (miny >= (dwMinimumCellY + PVC_RANGE)) miny -= PVC_RANGE; else miny = dwMinimumCellY;
- if (maxy <= (dwMaximumCellY - PVC_RANGE)) maxy += PVC_RANGE; else maxy = dwMaximumCellY;
- }
- minx = BLOCK_OFFSET(minx) << 8;
- miny = BLOCK_OFFSET(miny);
- maxx = BLOCK_OFFSET(maxx) << 8;
- maxy = BLOCK_OFFSET(maxy);
- for (DWORD xit = minx; xit <= maxx; xit += 0x100) {
- for (DWORD yit = miny; yit <= maxy; yit += 1)
- {
- CLandBlock* pBlock = m_pBlocks[xit | yit];
- if (pBlock)
- {
- pBlock->EnumNearby(pSource, fRange, pResults);
- }
- }
- }
- }
- }
- CPhysicsObj* CWorld::FindWithinPVS(CPhysicsObj *pSource, DWORD dwGUID)
- {
- if (!pSource)
- return NULL;
- //Find nearby world objects.
- if (!pSource->HasOwner())
- {
- DWORD dwCell = pSource->GetLandcell();
- WORD block = BLOCK_WORD(dwCell);
- WORD cell = CELL_WORD(dwCell);
- DWORD basex = BASE_OFFSET(BLOCK_X(block), CELL_X(cell));
- DWORD basey = BASE_OFFSET(BLOCK_Y(block), CELL_Y(cell));
- DWORD minx = basex;
- DWORD maxx = basex;
- DWORD miny = basey;
- DWORD maxy = basey;
- //if ( cell < 0xFF ) //indoor structure
- {
- if (minx >= (dwMinimumCellX + PVC_RANGE)) minx -= PVC_RANGE; else minx = dwMinimumCellX;
- if (maxx <= (dwMaximumCellX - PVC_RANGE)) maxx += PVC_RANGE; else maxx = dwMaximumCellX;
- if (miny >= (dwMinimumCellY + PVC_RANGE)) miny -= PVC_RANGE; else miny = dwMinimumCellY;
- if (maxy <= (dwMaximumCellY - PVC_RANGE)) maxy += PVC_RANGE; else maxy = dwMaximumCellY;
- }
- minx = BLOCK_OFFSET(minx) << 8;
- miny = BLOCK_OFFSET(miny);
- maxx = BLOCK_OFFSET(maxx) << 8;
- maxy = BLOCK_OFFSET(maxy);
- for (DWORD xit = minx; xit <= maxx; xit += 0x100) {
- for (DWORD yit = miny; yit <= maxy; yit += 1)
- {
- CLandBlock* pBlock = m_pBlocks[xit | yit];
- if (pBlock)
- {
- CPhysicsObj *pEntity = pBlock->FindEntity(dwGUID);
- if (pEntity)
- return pEntity;
- }
- }
- }
- }
- if (pSource->Container_HasContents())
- return (CPhysicsObj *)pSource->Container_FindItem(dwGUID);
- return NULL;
- }
- void CWorld::EnumerateDungeonsFromCellData()
- {
- // TODO Need to fix dungeon parsing for ToD first. Broke because of that.
- return;
- // This creates a list of dungeons
- FILEMAP* pFiles = g_pCell->GetFiles();
- FILEMAP::iterator i = pFiles->begin();
- FILEMAP::iterator iend = pFiles->end();
- while (i != iend)
- {
- DWORD dwID = i->first;
- if (((dwID & 0xFFFF) >= 0xFFFE) || ((dwID & 0xFFFF) < 0x100))
- {
- i++;
- continue;
- }
- TURBINEFILE* pGeometryFile = g_pCell->GetFile(dwID);
- BYTE *_data, *data;
- _data = data = pGeometryFile->GetData();
- DWORD dwGeoFlags = *((DWORD *)data);
- if (!(dwGeoFlags & 9))
- {
- data += sizeof(DWORD);
- DWORD dungeonID = *((DWORD*)data);
- data += sizeof(DWORD);
- UCHAR textureCount = *((UCHAR *)data);
- data += sizeof(UCHAR);
- UCHAR connectionCount = *((UCHAR *)data);
- data += sizeof(UCHAR);
- USHORT visibleBlocksCount = *((USHORT *)data);
- data += sizeof(USHORT);
- data += textureCount * sizeof(USHORT);
- if (textureCount & 1)
- data += sizeof(USHORT);
- WORD blockID = *((WORD *)data);
- data += sizeof(WORD);
- WORD partNum = *((WORD *)data);
- data += sizeof(WORD);
- loc_t di;
- di.landcell = dungeonID;
- float _xTrans = *((float *)data);
- data += sizeof(float);
- float _yTrans = *((float *)data);
- data += sizeof(float);
- float _zTrans = *((float *)data);
- data += sizeof(float);
- float rw = *((float *)data);
- data += sizeof(float);
- float rx = *((float *)data);
- data += sizeof(float);
- float ry = *((float *)data);
- data += sizeof(float);
- float rz = *((float *)data);
- data += sizeof(float);
- #if 0 //This code look for the dropsite models in dungeons.
- if (dwGeoFlags & 2)
- {
- data += sizeof(DWORD) * connectionCount * 2;
- data += sizeof(USHORT) * visibleBlocksCount;
- if (visibleBlocksCount & 1)
- data += sizeof(USHORT);
- DWORD numObjects = *((DWORD *)data);
- data += sizeof(DWORD);
- for (unsigned int h = 0; h < numObjects; h++)
- {
- DWORD dwModelID = *((DWORD *)data);
- data += sizeof(DWORD);
- if ((dwModelID >= 0x02000C39 && dwModelID <= 0x02000C48) || (dwModelID == 0x02000F4A)) {
- //OutputConsole( "%08X has drop site[%08X] @ %f %f %f\r\n", dwID, dwModelID,
- // ((float*)data)[0], ((float*)data)[1], ((float*)data)[2]);
- break;
- }
- data += sizeof(float) * 7;
- }
- }
- #endif
- //if ( BLOCK_WORD( dwID ) == 0xF924 )
- // OutputConsole( "%08X %04X %04X\r\n", dwGeoFlags, blockID, partNum );
- DUNGEON* pDungeon = g_pPortal->GetDungeon(0x0D000000 + blockID);
- if (pDungeon)
- {
- loc_t Point = pDungeon->FindLandingZone(partNum);
- if (Point.landcell)
- {
- Vector pt(Point.x, Point.y, Point.z);
- matrix mm;
- mm.defineByQuaternion(rw, rx, ry, rz);
- mm.applyToVector(pt);
- //Point.x = pt.x;
- //Point.y = pt.y;
- //Point.z = pt.z;
- di.x = (float)(_xTrans + pt.x);
- di.y = (float)(_yTrans + pt.y);
- di.z = (float)(_zTrans + pt.z + 0.025f);
- //if ( BLOCK_WORD( dwID ) == 0xF924 )
- // LOG(Temp, Normal, "%f %f %f\n", di.x, di.y, di.z );
- m_mDungeons[dungeonID] = di;
- //506e0108
- }
- else
- {
- delete pGeometryFile;
- i++;
- continue;
- }
- //50520100 is broke
- //54500000 is broke
- }
- else
- {
- LOG(Temp, Normal, "Dungeon block mismatch. Are portal/cell versions inconsistant?\n");
- }
- }
- delete pGeometryFile;
- if (dwID < (DWORD)(0 - 0x10100))
- i = pFiles->upper_bound(((dwID & 0xFFFF0000) + 0x10100) - 1);
- else
- break;
- }
- }
|