Clone of PhatAC @ https://github.com/floaterxk/PhatAC

Database2.cpp 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548
  1. #include "StdAfx.h"
  2. #include "Database2.h"
  3. #include "World.h"
  4. #include "Portal.h"
  5. #include "PhysicsDesc.h"
  6. #include "PublicWeenieDesc.h"
  7. #include "Door.h"
  8. #include "Lifestone.h"
  9. #include "Item.h"
  10. CMYSQLResult::CMYSQLResult(MYSQL_RES *Result)
  11. {
  12. m_Result = Result;
  13. }
  14. CMYSQLResult::~CMYSQLResult()
  15. {
  16. Free();
  17. }
  18. void CMYSQLResult::Free()
  19. {
  20. if (m_Result)
  21. {
  22. mysql_free_result(m_Result);
  23. m_Result = NULL;
  24. }
  25. }
  26. SQLResultRow_t CMYSQLResult::FetchRow()
  27. {
  28. if (!m_Result)
  29. {
  30. return NULL;
  31. }
  32. return (SQLResultRow_t)mysql_fetch_row(m_Result);
  33. }
  34. uint64_t CMYSQLResult::ResultRows()
  35. {
  36. if (!m_Result)
  37. {
  38. return 0;
  39. }
  40. return (uint64_t)mysql_num_rows(m_Result);
  41. }
  42. int CSQLConnection::s_NumConnectAttempts = 0;
  43. CMYSQLConnection::CMYSQLConnection(MYSQL *connection)
  44. {
  45. m_InternalConnection = connection;
  46. }
  47. CMYSQLConnection::~CMYSQLConnection()
  48. {
  49. Close();
  50. }
  51. CMYSQLConnection *CMYSQLConnection::Create(const char *host, unsigned int port, const char *user, const char *password, const char *defaultdatabase)
  52. {
  53. MYSQL *sqlobject = mysql_init(NULL);
  54. if (!sqlobject)
  55. {
  56. return NULL;
  57. }
  58. int connect_timeout = MYSQL_CONNECT_TIMEOUT;
  59. mysql_options(sqlobject, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&connect_timeout);
  60. MYSQL *sqlconnection;
  61. {
  62. s_NumConnectAttempts++;
  63. CStopWatch connectTiming;
  64. sqlconnection = mysql_real_connect(sqlobject, host, user, password, defaultdatabase, port, NULL, 0);
  65. if (sqlconnection && connectTiming.GetElapsed() >= 1.0)
  66. {
  67. LOG(Database, Warning, "mysql_real_connect() took %.1f s!\n", connectTiming.GetElapsed());
  68. }
  69. }
  70. if (sqlconnection == NULL)
  71. {
  72. if (mysql_errno(sqlobject) == EINTR)
  73. {
  74. mysql_close(sqlobject);
  75. sqlobject = mysql_init(NULL);
  76. if (!sqlobject)
  77. {
  78. return NULL;
  79. }
  80. int connect_timeout = MYSQL_CONNECT_TIMEOUT;
  81. mysql_options(sqlobject, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&connect_timeout);
  82. s_NumConnectAttempts++;
  83. CStopWatch connectTiming;
  84. sqlconnection = mysql_real_connect(sqlobject, host, user, password, defaultdatabase, port, NULL, 0);
  85. if (sqlconnection && connectTiming.GetElapsed() >= 1.0)
  86. {
  87. LOG(Database, Warning, "mysql_real_connect() re-attempt took %.1f s!\n", connectTiming.GetElapsed());
  88. }
  89. if (sqlconnection == NULL)
  90. {
  91. LOG(Database, Warning, "Failed to create mysql connection after two tries:\n%s\n", mysql_error(sqlobject));
  92. mysql_close(sqlobject);
  93. return NULL;
  94. }
  95. else
  96. {
  97. LOG(Database, Normal, "Received EINTR while attempting to connect to mysql, but re-attempt succeeded.\n");
  98. }
  99. }
  100. else
  101. {
  102. if (CSQLConnection::s_NumConnectAttempts > 1)
  103. {
  104. // Only show warning if not the first connection attempt
  105. LOG(Database, Warning, "mysql_real_connect() failed:\n%s\n", mysql_error(sqlobject));
  106. }
  107. mysql_close(sqlobject);
  108. return NULL;
  109. }
  110. }
  111. if (sqlconnection)
  112. {
  113. // Disable auto-reconnect (probably already disabled)
  114. sqlconnection->reconnect = 0;
  115. return new CMYSQLConnection(sqlconnection);
  116. }
  117. return NULL;
  118. }
  119. void CMYSQLConnection::Close()
  120. {
  121. if (m_InternalConnection)
  122. {
  123. mysql_close(m_InternalConnection);
  124. m_InternalConnection = NULL;
  125. }
  126. }
  127. bool CMYSQLConnection::Query(const char *query)
  128. {
  129. if (!m_InternalConnection)
  130. {
  131. return false;
  132. }
  133. int errorCode;
  134. {
  135. CStopWatch queryTiming;
  136. errorCode = mysql_query(m_InternalConnection, query);
  137. if (queryTiming.GetElapsed() >= 1.0)
  138. {
  139. LOG(Database, Warning, "MYSQL query \"%s\" took %f seconds.\n", query, queryTiming.GetElapsed());
  140. }
  141. }
  142. if (errorCode != 0)
  143. {
  144. LOG(Database, Error, "MYSQL query errored %d for \"%s\"\n", errorCode, query);
  145. return false;
  146. }
  147. return true;
  148. }
  149. unsigned int CMYSQLConnection::LastError()
  150. {
  151. return m_InternalConnection ? (unsigned int)mysql_errno(m_InternalConnection) : 0;
  152. }
  153. CSQLResult *CMYSQLConnection::GetResult()
  154. {
  155. if (!m_InternalConnection)
  156. {
  157. return NULL;
  158. }
  159. MYSQL_RES *Result = mysql_store_result(m_InternalConnection);
  160. if (!Result)
  161. {
  162. return NULL;
  163. }
  164. return new CMYSQLResult(Result);
  165. }
  166. CDatabase2::CDatabase2()
  167. {
  168. m_pConnection = NULL;
  169. }
  170. CDatabase2::~CDatabase2()
  171. {
  172. if (m_pConnection != nullptr)
  173. {
  174. m_pConnection->Close();
  175. delete m_pConnection;
  176. }
  177. }
  178. void CDatabase2::Tick()
  179. {
  180. }
  181. bool CDatabase2::Query(const char *format, ...)
  182. {
  183. if (!m_pConnection)
  184. {
  185. return false;
  186. }
  187. bool success = false;
  188. va_list args;
  189. va_start(args, format);
  190. int charCount = _vscprintf(format, args) + 1;
  191. char *charBuffer = new char[charCount];
  192. charBuffer[0] = '\0';
  193. _vsnprintf(charBuffer, charCount, format, args);
  194. charBuffer[charCount - 1] = '\0';
  195. if (m_pConnection)
  196. {
  197. success = m_pConnection->Query(charBuffer);
  198. }
  199. delete[] charBuffer;
  200. va_end(args);
  201. return success;
  202. }
  203. CSQLResult *CDatabase2::GetResult()
  204. {
  205. if (!m_pConnection)
  206. {
  207. return NULL;
  208. }
  209. return m_pConnection->GetResult();
  210. }
  211. CMYSQLDatabase::CMYSQLDatabase(const char *host, unsigned int port, const char *user, const char *password, const char *defaultdatabasename)
  212. {
  213. m_DatabaseHost = host;
  214. m_DatabasePort = port;
  215. m_DatabaseUser = user;
  216. m_DatabasePassword = password;
  217. m_DatabaseName = defaultdatabasename;
  218. m_bDisabled = false;
  219. RefreshConnection();
  220. if (!m_pConnection)
  221. {
  222. // If we can't connect the first time, just disable this feature.
  223. LOG(Database, Warning, "MySQL database functionality disabled.\n");
  224. m_bDisabled = true;
  225. }
  226. }
  227. CMYSQLDatabase::~CMYSQLDatabase()
  228. {
  229. }
  230. void CMYSQLDatabase::RefreshConnection()
  231. {
  232. // If we have an old connection, close that one.
  233. if (m_pConnection)
  234. {
  235. delete m_pConnection;
  236. m_pConnection = NULL;
  237. }
  238. m_pConnection = CMYSQLConnection::Create(m_DatabaseHost.c_str(), m_DatabasePort, m_DatabaseUser.c_str(), m_DatabasePassword.c_str(), m_DatabaseName.c_str());
  239. m_fLastRefresh = g_pGlobals->Time();
  240. }
  241. void CMYSQLDatabase::Tick()
  242. {
  243. if (m_fLastRefresh < (g_pGlobals->Time() + 60.0))
  244. {
  245. // Refresh connection every 60 seconds to avoid stale connections.
  246. RefreshConnection();
  247. }
  248. }
  249. CGameDatabase::CGameDatabase()
  250. {
  251. m_bLoadedPortals = false;
  252. }
  253. CGameDatabase::~CGameDatabase()
  254. {
  255. for (auto &data : m_CapturedAerfalleData)
  256. {
  257. delete data;
  258. }
  259. for (auto &data : m_CapturedMonsterData)
  260. {
  261. delete data.second;
  262. }
  263. for (auto &data : m_CapturedItemData)
  264. {
  265. delete data.second;
  266. }
  267. for (auto &data : m_CapturedStaticsData)
  268. {
  269. delete data;
  270. }
  271. for (auto &data : m_CapturedArmorData)
  272. {
  273. delete data.second;
  274. }
  275. }
  276. void CGameDatabase::Init()
  277. {
  278. // Loads from MYSQL database
  279. LoadPortals();
  280. LoadTeleTownList();
  281. LoadMonsterTemplates();
  282. // Load data files for now
  283. LoadCapturedMonsterData();
  284. LoadCapturedItemData();
  285. LoadCapturedArmorData();
  286. LoadStaticsData();
  287. LoadAerfalle();
  288. }
  289. void CGameDatabase::SpawnAerfalle()
  290. {
  291. for (auto pSpawnInfo : m_CapturedAerfalleData)
  292. {
  293. CPhysicsObj *pSpawn;
  294. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_CORPSE)
  295. continue;
  296. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_PLAYER)
  297. continue;
  298. if (pSpawnInfo->physics.state & PhysicsState::MISSILE_PS)
  299. continue;
  300. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_DOOR)
  301. {
  302. pSpawn = new CBaseDoor();
  303. pSpawn->m_PhysicsState = pSpawnInfo->physics.state;
  304. pSpawn->m_WeenieBitfield = pSpawnInfo->weenie._bitfield;
  305. }
  306. else if (pSpawnInfo->weenie._type == ITEM_TYPE::TYPE_CREATURE)
  307. {
  308. pSpawn = new CBaseMonster();
  309. pSpawn->m_PhysicsState = pSpawnInfo->physics.state;
  310. pSpawn->m_WeenieBitfield = pSpawnInfo->weenie._bitfield;
  311. }
  312. else
  313. {
  314. pSpawn = new CPhysicsObj();
  315. pSpawn->m_PhysicsState = pSpawnInfo->physics.state;
  316. pSpawn->m_WeenieBitfield = pSpawnInfo->weenie._bitfield;
  317. }
  318. pSpawn->m_dwGUID = pSpawnInfo->guid; // g_pWorld->GenerateGUID(eDynamicGUID);
  319. pSpawn->m_miBaseModel = pSpawnInfo->appearance;
  320. pSpawn->m_dwModel = pSpawnInfo->physics.setup_id;
  321. pSpawn->m_dwAnimationSet = pSpawnInfo->physics.mtable_id;
  322. pSpawn->m_dwSoundSet = pSpawnInfo->physics.stable_id;
  323. pSpawn->m_dwEffectSet = pSpawnInfo->physics.phstable_id;
  324. pSpawn->m_fScale = pSpawnInfo->physics.object_scale;
  325. pSpawn->m_ItemType = pSpawnInfo->weenie._type;
  326. pSpawn->m_strName = pSpawnInfo->weenie._name;
  327. pSpawn->m_Origin.landcell = pSpawnInfo->physics.pos.objcell_id;
  328. pSpawn->m_Origin.x = pSpawnInfo->physics.pos.frame.m_fOrigin.x;
  329. pSpawn->m_Origin.y = pSpawnInfo->physics.pos.frame.m_fOrigin.y;
  330. pSpawn->m_Origin.z = pSpawnInfo->physics.pos.frame.m_fOrigin.z;
  331. pSpawn->m_Angles.w = pSpawnInfo->physics.pos.frame.qw;
  332. pSpawn->m_Angles.x = pSpawnInfo->physics.pos.frame.qx;
  333. pSpawn->m_Angles.y = pSpawnInfo->physics.pos.frame.qy;
  334. pSpawn->m_Angles.z = pSpawnInfo->physics.pos.frame.qz;
  335. if (pSpawnInfo->physics.movement_buffer)
  336. {
  337. pSpawn->m_AnimOverrideData = pSpawnInfo->physics.movement_buffer;
  338. pSpawn->m_AnimOverrideDataLen = pSpawnInfo->physics.movement_buffer_length;
  339. pSpawn->m_AutonomousMovement = pSpawnInfo->physics.autonomous_movement;
  340. }
  341. pSpawn->m_bDontClear = true;
  342. g_pWorld->CreateEntity(pSpawn);
  343. }
  344. }
  345. void CGameDatabase::LoadAerfalle()
  346. {
  347. // TEMPORARY FOR TESTING DUNGEONS
  348. // Consolidate or remove this method of loading (this was copied and pasted)
  349. BYTE *data;
  350. DWORD length;
  351. if (LoadDataFromFile("aerfalle.dat", &data, &length))
  352. {
  353. BinaryReader reader(data, length);
  354. unsigned int count = reader.ReadDWORD();
  355. for (unsigned int i = 0; i < count; i++)
  356. {
  357. reader.ReadString();
  358. CCapturedWorldObjectInfo *pObjectInfo = new CCapturedWorldObjectInfo;
  359. DWORD a = reader.ReadDWORD(); // size of this
  360. DWORD b = reader.ReadDWORD(); // 0xF745
  361. pObjectInfo->guid = reader.ReadDWORD(); // GUID
  362. reader.ReadBYTE();
  363. BYTE numPalette = reader.ReadBYTE();
  364. BYTE numTex = reader.ReadBYTE();
  365. BYTE numModel = reader.ReadBYTE();
  366. if (numPalette)
  367. {
  368. pObjectInfo->appearance.dwBasePalette = reader.ReadPackedDWORD();
  369. for (int j = 0; j < numPalette; j++)
  370. {
  371. DWORD replacement = reader.ReadPackedDWORD();
  372. BYTE offset = reader.ReadBYTE();
  373. BYTE range = reader.ReadBYTE();
  374. pObjectInfo->appearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  375. }
  376. }
  377. for (int j = 0; j < numTex; j++)
  378. {
  379. BYTE index = reader.ReadBYTE();
  380. DWORD oldT = reader.ReadPackedDWORD();
  381. DWORD newT = reader.ReadPackedDWORD();
  382. pObjectInfo->appearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  383. }
  384. for (int j = 0; j < numModel; j++)
  385. {
  386. BYTE index = reader.ReadBYTE();
  387. DWORD newM = reader.ReadPackedDWORD();
  388. pObjectInfo->appearance.lModels.push_back(ModelRpl(index, newM));
  389. }
  390. reader.ReadAlign();
  391. pObjectInfo->physics.Unpack(reader);
  392. pObjectInfo->weenie.Unpack(reader);
  393. if (!reader.GetLastError())
  394. {
  395. m_CapturedAerfalleData.push_back(pObjectInfo);
  396. }
  397. else
  398. {
  399. DEBUG_BREAK();
  400. delete pObjectInfo;
  401. break;
  402. }
  403. }
  404. delete [] data;
  405. }
  406. }
  407. std::string CGameDatabase::ConvertNameForLookup(std::string name)
  408. {
  409. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  410. name.erase(remove_if(name.begin(), name.end(), isspace), name.end());
  411. return name;
  412. }
  413. void CGameDatabase::LoadStaticsData()
  414. {
  415. // THIS IS ALL TEMPORARY FOR TESTING
  416. unsigned int spawned = 0;
  417. BYTE *data;
  418. DWORD length;
  419. if (LoadDataFromFile("statics.dat", &data, &length))
  420. {
  421. BinaryReader reader(data, length);
  422. unsigned int count = reader.ReadDWORD();
  423. for (unsigned int i = 0; i < count; i++)
  424. {
  425. CCapturedWorldObjectInfo *pObjectInfo = new CCapturedWorldObjectInfo;
  426. reader.ReadString();
  427. DWORD dwObjDataLen = reader.ReadDWORD(); // size of this
  428. reader.ReadDWORD(); // 0xf745
  429. pObjectInfo->guid = reader.ReadDWORD(); // GUID
  430. reader.ReadBYTE();
  431. BYTE numPalette = reader.ReadBYTE();
  432. BYTE numTex = reader.ReadBYTE();
  433. BYTE numModel = reader.ReadBYTE();
  434. if (numPalette)
  435. {
  436. pObjectInfo->appearance.dwBasePalette = reader.ReadPackedDWORD(); // actually packed, fix this
  437. for (int j = 0; j < numPalette; j++)
  438. {
  439. DWORD replacement = reader.ReadPackedDWORD(); // actually packed, fix this
  440. BYTE offset = reader.ReadBYTE();
  441. BYTE range = reader.ReadBYTE();
  442. pObjectInfo->appearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  443. }
  444. }
  445. for (int j = 0; j < numTex; j++)
  446. {
  447. BYTE index = reader.ReadBYTE();
  448. DWORD oldT = reader.ReadPackedDWORD();
  449. DWORD newT = reader.ReadPackedDWORD();
  450. pObjectInfo->appearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  451. }
  452. for (int j = 0; j < numModel; j++)
  453. {
  454. BYTE index = reader.ReadBYTE();
  455. DWORD newM = reader.ReadPackedDWORD();
  456. pObjectInfo->appearance.lModels.push_back(ModelRpl(index, newM));
  457. }
  458. reader.ReadAlign();
  459. pObjectInfo->physics.Unpack(reader);
  460. pObjectInfo->weenie.Unpack(reader);
  461. if (reader.GetLastError())
  462. {
  463. DEBUG_BREAK();
  464. delete pObjectInfo;
  465. break;
  466. }
  467. DWORD dwIDDataLen = reader.ReadDWORD();
  468. DWORD offsetStart = reader.GetOffset();
  469. if (dwIDDataLen > 0)
  470. {
  471. BinaryReader idReader(reader.GetDataPtr(), dwIDDataLen);
  472. idReader.ReadDWORD(); // 0xf7b0
  473. idReader.ReadDWORD(); // character
  474. idReader.ReadDWORD(); // sequence
  475. idReader.ReadDWORD(); // game event (0xc9)
  476. idReader.ReadDWORD(); // object
  477. DWORD flags = idReader.ReadDWORD(); // flags
  478. idReader.ReadDWORD(); // success
  479. enum AppraisalProfilePackHeader {
  480. Packed_None = 0,
  481. Packed_IntStats = (1 << 0),
  482. Packed_BoolStats = (1 << 1),
  483. Packed_FloatStats = (1 << 2),
  484. Packed_StringStats = (1 << 3),
  485. Packed_SpellList = (1 << 4),
  486. Packed_WeaponProfile = (1 << 5),
  487. Packed_HookProfile = (1 << 6),
  488. Packed_ArmorProfile = (1 << 7),
  489. Packed_CreatureProfile = (1 << 8),
  490. Packed_ArmorEnchant = (1 << 9),
  491. Packed_ResistEnchant = (1 << 10),
  492. Packed_WeaponEnchant = (1 << 11),
  493. Packed_DataIDStats = (1 << 12),
  494. Packed_Int64Stats = (1 << 13),
  495. Packed_ArmorLevels = (1 << 14)
  496. };
  497. if (flags & Packed_IntStats)
  498. {
  499. pObjectInfo->dwordProperties = idReader.ReadMap<DWORD, DWORD>();
  500. }
  501. if (flags & Packed_Int64Stats)
  502. pObjectInfo->qwordProperties = idReader.ReadMap<DWORD, UINT64>();
  503. if (flags & Packed_BoolStats)
  504. pObjectInfo->boolProperties = idReader.ReadMap<DWORD, DWORD>();
  505. if (flags & Packed_FloatStats)
  506. pObjectInfo->floatProperties = idReader.ReadMap<DWORD, double>();
  507. if (idReader.GetLastError())
  508. {
  509. DEBUG_BREAK();
  510. }
  511. }
  512. reader.SetOffset(offsetStart + dwIDDataLen);
  513. m_CapturedStaticsData.push_back(pObjectInfo);
  514. }
  515. delete [] data;
  516. }
  517. for (auto pSpawnInfo : m_CapturedStaticsData)
  518. {
  519. CPhysicsObj *pSpawn;
  520. if (pSpawnInfo->guid >= 0x80000000)
  521. continue; // Dynamic perhaps
  522. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_CORPSE)
  523. continue;
  524. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_PLAYER)
  525. continue;
  526. if (pSpawnInfo->physics.state & PhysicsState::MISSILE_PS)
  527. continue;
  528. if (pSpawnInfo->weenie._bitfield & BitfieldIndex::BF_DOOR)
  529. pSpawn = new CBaseDoor();
  530. else if (pSpawnInfo->weenie._type == ITEM_TYPE::TYPE_CREATURE)
  531. pSpawn = new CBaseMonster();
  532. else if (pSpawnInfo->weenie._type == ITEM_TYPE::TYPE_PORTAL)
  533. pSpawn = new CPortal();
  534. else if (pSpawnInfo->weenie._type == ITEM_TYPE::TYPE_LIFESTONE)
  535. pSpawn = new CBaseLifestone();
  536. else
  537. pSpawn = new CPhysicsObj();
  538. pSpawn->m_dwGUID = pSpawnInfo->guid; // g_pWorld->GenerateGUID(eDynamicGUID);
  539. pSpawn->m_miBaseModel = pSpawnInfo->appearance;
  540. pSpawn->m_dwModel = pSpawnInfo->physics.setup_id;
  541. pSpawn->m_dwAnimationSet = pSpawnInfo->physics.mtable_id;
  542. pSpawn->m_dwSoundSet = pSpawnInfo->physics.stable_id;
  543. pSpawn->m_dwEffectSet = pSpawnInfo->physics.phstable_id;
  544. pSpawn->m_fScale = pSpawnInfo->physics.object_scale;
  545. pSpawn->m_ItemType = pSpawnInfo->weenie._type;
  546. pSpawn->m_strName = pSpawnInfo->weenie._name;
  547. pSpawn->m_Origin.landcell = pSpawnInfo->physics.pos.objcell_id;
  548. pSpawn->m_Origin.x = pSpawnInfo->physics.pos.frame.m_fOrigin.x;
  549. pSpawn->m_Origin.y = pSpawnInfo->physics.pos.frame.m_fOrigin.y;
  550. pSpawn->m_Origin.z = pSpawnInfo->physics.pos.frame.m_fOrigin.z;
  551. pSpawn->m_Angles.w = pSpawnInfo->physics.pos.frame.qw;
  552. pSpawn->m_Angles.x = pSpawnInfo->physics.pos.frame.qx;
  553. pSpawn->m_Angles.y = pSpawnInfo->physics.pos.frame.qy;
  554. pSpawn->m_Angles.z = pSpawnInfo->physics.pos.frame.qz;
  555. if (pSpawnInfo->physics.movement_buffer)
  556. {
  557. pSpawn->m_AnimOverrideData = pSpawnInfo->physics.movement_buffer;
  558. pSpawn->m_AnimOverrideDataLen = pSpawnInfo->physics.movement_buffer_length;
  559. pSpawn->m_AutonomousMovement = pSpawnInfo->physics.autonomous_movement;
  560. }
  561. pSpawn->m_bDontClear = true;
  562. pSpawn->m_RadarVis = pSpawnInfo->weenie._radar_enum;
  563. pSpawn->m_BlipColor = pSpawnInfo->weenie._blipColor;
  564. pSpawn->m_TargetType = pSpawnInfo->weenie._targetType;
  565. pSpawn->m_wTypeID = pSpawnInfo->weenie._wcid;
  566. pSpawn->m_Value = pSpawnInfo->weenie._value;
  567. pSpawn->m_Burden = pSpawnInfo->weenie._burden;
  568. pSpawn->m_PhysicsState = pSpawnInfo->physics.state;
  569. pSpawn->m_Translucency = pSpawnInfo->physics.translucency;
  570. pSpawn->m_WeenieBitfield = pSpawnInfo->weenie._bitfield;
  571. g_pWorld->CreateEntity(pSpawn);
  572. spawned++;
  573. }
  574. if (!spawned)
  575. {
  576. LOG(Temp, Warning, "Spawn data not included. Spawning functionality may be limited.\n");
  577. }
  578. }
  579. CCapturedWorldObjectInfo *CGameDatabase::GetRandomCapturedMonsterData()
  580. {
  581. DWORD numMonsters = m_CapturedMonsterDataList.size();
  582. if (numMonsters < 1)
  583. return NULL;
  584. int monster = RandomLong(0, numMonsters - 1);
  585. return m_CapturedMonsterDataList[monster];
  586. }
  587. CCapturedWorldObjectInfo *CGameDatabase::GetCapturedMonsterData(const char *name)
  588. {
  589. std::map<std::string, CCapturedWorldObjectInfo *>::iterator i = m_CapturedMonsterData.find(ConvertNameForLookup(name));
  590. if (i == m_CapturedMonsterData.end())
  591. return NULL;
  592. return i->second;
  593. }
  594. void CGameDatabase::LoadCapturedMonsterData()
  595. {
  596. // THIS IS ALL TEMPORARY FOR TESTING
  597. // Consolidate or remove this method of loading (this was copied and pasted)
  598. BYTE *data;
  599. DWORD length;
  600. if (LoadDataFromFile("monsters.dat", &data, &length))
  601. {
  602. BinaryReader reader(data, length);
  603. unsigned int count = reader.ReadDWORD();
  604. for (unsigned int i = 0; i < count; i++)
  605. {
  606. CCapturedWorldObjectInfo *pMonsterInfo = new CCapturedWorldObjectInfo;
  607. pMonsterInfo->m_ObjName = reader.ReadString();
  608. DWORD dwObjDataLen = reader.ReadDWORD(); // size of this
  609. reader.ReadDWORD(); // 0xf745
  610. DWORD dwGUID = reader.ReadDWORD(); // GUID
  611. reader.ReadBYTE();
  612. BYTE numPalette = reader.ReadBYTE();
  613. BYTE numTex = reader.ReadBYTE();
  614. BYTE numModel = reader.ReadBYTE();
  615. if (numPalette)
  616. {
  617. pMonsterInfo->appearance.dwBasePalette = reader.ReadPackedDWORD(); // actually packed, fix this
  618. for (int j = 0; j < numPalette; j++)
  619. {
  620. DWORD replacement = reader.ReadPackedDWORD(); // actually packed, fix this
  621. BYTE offset = reader.ReadBYTE();
  622. BYTE range = reader.ReadBYTE();
  623. pMonsterInfo->appearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  624. }
  625. }
  626. for (int j = 0; j < numTex; j++)
  627. {
  628. BYTE index = reader.ReadBYTE();
  629. DWORD oldT = reader.ReadPackedDWORD();
  630. DWORD newT = reader.ReadPackedDWORD();
  631. pMonsterInfo->appearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  632. }
  633. for (int j = 0; j < numModel; j++)
  634. {
  635. BYTE index = reader.ReadBYTE();
  636. DWORD newM = reader.ReadPackedDWORD();
  637. pMonsterInfo->appearance.lModels.push_back(ModelRpl(index, newM));
  638. }
  639. reader.ReadAlign();
  640. pMonsterInfo->physics.Unpack(reader);
  641. pMonsterInfo->weenie.Unpack(reader);
  642. if (reader.GetLastError())
  643. {
  644. DEBUG_BREAK();
  645. delete pMonsterInfo;
  646. break;
  647. }
  648. DWORD dwIDDataLen = reader.ReadDWORD();
  649. DWORD offsetStart = reader.GetOffset();
  650. if (dwIDDataLen > 0)
  651. {
  652. BinaryReader idReader(reader.GetDataPtr(), dwIDDataLen);
  653. idReader.ReadDWORD(); // 0xf7b0
  654. idReader.ReadDWORD(); // character
  655. idReader.ReadDWORD(); // sequence
  656. idReader.ReadDWORD(); // game event (0xc9)
  657. idReader.ReadDWORD(); // object
  658. DWORD flags = idReader.ReadDWORD(); // flags
  659. idReader.ReadDWORD(); // success
  660. enum AppraisalProfilePackHeader {
  661. Packed_None = 0,
  662. Packed_IntStats = (1 << 0),
  663. Packed_BoolStats = (1 << 1),
  664. Packed_FloatStats = (1 << 2),
  665. Packed_StringStats = (1 << 3),
  666. Packed_SpellList = (1 << 4),
  667. Packed_WeaponProfile = (1 << 5),
  668. Packed_HookProfile = (1 << 6),
  669. Packed_ArmorProfile = (1 << 7),
  670. Packed_CreatureProfile = (1 << 8),
  671. Packed_ArmorEnchant = (1 << 9),
  672. Packed_ResistEnchant = (1 << 10),
  673. Packed_WeaponEnchant = (1 << 11),
  674. Packed_DataIDStats = (1 << 12),
  675. Packed_Int64Stats = (1 << 13),
  676. Packed_ArmorLevels = (1 << 14)
  677. };
  678. if (idReader.GetLastError())
  679. {
  680. DEBUG_BREAK();
  681. }
  682. if (flags & Packed_IntStats)
  683. {
  684. pMonsterInfo->dwordProperties = idReader.ReadMap<DWORD, DWORD>();
  685. }
  686. if (idReader.GetLastError())
  687. {
  688. DEBUG_BREAK();
  689. }
  690. if (flags & Packed_Int64Stats)
  691. {
  692. pMonsterInfo->qwordProperties = idReader.ReadMap<DWORD, UINT64>();
  693. }
  694. if (idReader.GetLastError())
  695. {
  696. DEBUG_BREAK();
  697. }
  698. if (flags & Packed_BoolStats)
  699. {
  700. pMonsterInfo->boolProperties = idReader.ReadMap<DWORD, DWORD>();
  701. }
  702. if (idReader.GetLastError())
  703. {
  704. DEBUG_BREAK();
  705. }
  706. if (flags & Packed_FloatStats)
  707. {
  708. pMonsterInfo->floatProperties = idReader.ReadMap<DWORD, double>();
  709. }
  710. if (idReader.GetLastError())
  711. {
  712. DEBUG_BREAK();
  713. }
  714. /* ... etc ...
  715. if (flags & Packed_StringStats)
  716. pMonsterInfo->stringProperties = idReader.ReadMap<DWORD>();
  717. if (flags & Packed_DataIDStats)
  718. pMonsterInfo->dataIDProperties = idReader.ReadMap<DWORD, DWORD>();
  719. */
  720. }
  721. reader.SetOffset(offsetStart + dwIDDataLen);
  722. m_CapturedMonsterData.insert(std::pair<std::string, CCapturedWorldObjectInfo*>(ConvertNameForLookup(pMonsterInfo->m_ObjName), pMonsterInfo));
  723. if (!(pMonsterInfo->weenie._bitfield & BitfieldIndex::BF_PLAYER))
  724. {
  725. m_CapturedMonsterDataList.push_back(pMonsterInfo);
  726. }
  727. }
  728. delete [] data;
  729. }
  730. }
  731. CCapturedWorldObjectInfo *CGameDatabase::GetRandomCapturedItemData()
  732. {
  733. DWORD numItems = m_CapturedItemDataList.size();
  734. if (numItems < 1)
  735. {
  736. return NULL;
  737. }
  738. int Item = RandomLong(0, numItems - 1);
  739. return m_CapturedItemDataList[Item];
  740. }
  741. CCapturedWorldObjectInfo *CGameDatabase::GetCapturedItemData(const char *name)
  742. {
  743. std::map<std::string, CCapturedWorldObjectInfo *>::iterator i = m_CapturedItemData.find(ConvertNameForLookup(name));
  744. if (i == m_CapturedItemData.end())
  745. return NULL;
  746. return i->second;
  747. }
  748. void CGameDatabase::LoadCapturedItemData()
  749. {
  750. // THIS IS ALL TEMPORARY FOR TESTING
  751. // Consolidate or remove this method of loading (this was copied and pasted)
  752. BYTE *data;
  753. DWORD length;
  754. if (LoadDataFromFile("items.dat", &data, &length))
  755. {
  756. BinaryReader reader(data, length);
  757. unsigned int count = reader.ReadDWORD();
  758. for (unsigned int i = 0; i < count; i++)
  759. {
  760. CCapturedWorldObjectInfo *pItemInfo = new CCapturedWorldObjectInfo;
  761. pItemInfo->m_ObjName = reader.ReadString();
  762. std::transform(pItemInfo->m_ObjName.begin(), pItemInfo->m_ObjName.end(), pItemInfo->m_ObjName.begin(), ::tolower);
  763. pItemInfo->m_ObjName.erase(remove_if(pItemInfo->m_ObjName.begin(), pItemInfo->m_ObjName.end(), isspace), pItemInfo->m_ObjName.end());
  764. // make all lowercase and ignore spaces for searching purposes
  765. DWORD dwObjDataLen = reader.ReadDWORD(); // size of this
  766. DWORD offset_start = reader.GetOffset();
  767. reader.ReadDWORD(); // 0xf745
  768. DWORD dwGUID = reader.ReadDWORD(); // GUID
  769. reader.ReadBYTE();
  770. BYTE numPalette = reader.ReadBYTE();
  771. BYTE numTex = reader.ReadBYTE();
  772. BYTE numModel = reader.ReadBYTE();
  773. if (numPalette)
  774. {
  775. pItemInfo->appearance.dwBasePalette = reader.ReadPackedDWORD(); // actually packed, fix this
  776. for (int j = 0; j < numPalette; j++)
  777. {
  778. DWORD replacement = reader.ReadPackedDWORD(); // actually packed, fix this
  779. BYTE offset = reader.ReadBYTE();
  780. BYTE range = reader.ReadBYTE();
  781. pItemInfo->appearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  782. }
  783. }
  784. for (int j = 0; j < numTex; j++)
  785. {
  786. BYTE index = reader.ReadBYTE();
  787. DWORD oldT = reader.ReadPackedDWORD();
  788. DWORD newT = reader.ReadPackedDWORD();
  789. pItemInfo->appearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  790. }
  791. for (int j = 0; j < numModel; j++)
  792. {
  793. BYTE index = reader.ReadBYTE();
  794. DWORD newM = reader.ReadPackedDWORD();
  795. pItemInfo->appearance.lModels.push_back(ModelRpl(index, newM));
  796. }
  797. reader.ReadAlign();
  798. pItemInfo->physics.Unpack(reader);
  799. pItemInfo->weenie.Unpack(reader);
  800. if (reader.GetLastError())
  801. {
  802. delete pItemInfo;
  803. break;
  804. }
  805. if (reader.GetOffset() != (offset_start + dwObjDataLen))
  806. {
  807. DEBUG_BREAK();
  808. }
  809. DWORD dwIDDataLen = reader.ReadDWORD();
  810. DWORD offsetStart = reader.GetOffset();
  811. if (dwIDDataLen > 0)
  812. {
  813. BinaryReader idReader(reader.GetDataPtr(), dwIDDataLen);
  814. idReader.ReadDWORD(); // 0xf7b0
  815. idReader.ReadDWORD(); // character
  816. idReader.ReadDWORD(); // sequence
  817. idReader.ReadDWORD(); // game event (0xc9)
  818. idReader.ReadDWORD(); // object
  819. DWORD flags = idReader.ReadDWORD(); // flags
  820. idReader.ReadDWORD(); // success
  821. enum AppraisalProfilePackHeader {
  822. Packed_None = 0,
  823. Packed_IntStats = (1 << 0),
  824. Packed_BoolStats = (1 << 1),
  825. Packed_FloatStats = (1 << 2),
  826. Packed_StringStats = (1 << 3),
  827. Packed_SpellList = (1 << 4),
  828. Packed_WeaponProfile = (1 << 5),
  829. Packed_HookProfile = (1 << 6),
  830. Packed_ArmorProfile = (1 << 7),
  831. Packed_CreatureProfile = (1 << 8),
  832. Packed_ArmorEnchant = (1 << 9),
  833. Packed_ResistEnchant = (1 << 10),
  834. Packed_WeaponEnchant = (1 << 11),
  835. Packed_DataIDStats = (1 << 12),
  836. Packed_Int64Stats = (1 << 13),
  837. Packed_ArmorLevels = (1 << 14)
  838. };
  839. if (idReader.GetLastError())
  840. {
  841. DEBUG_BREAK();
  842. }
  843. if (flags & Packed_IntStats)
  844. {
  845. pItemInfo->dwordProperties = idReader.ReadMap<DWORD, DWORD>();
  846. }
  847. if (idReader.GetLastError())
  848. {
  849. DEBUG_BREAK();
  850. }
  851. if (flags & Packed_Int64Stats)
  852. {
  853. pItemInfo->qwordProperties = idReader.ReadMap<DWORD, UINT64>();
  854. }
  855. if (idReader.GetLastError())
  856. {
  857. DEBUG_BREAK();
  858. }
  859. if (flags & Packed_BoolStats)
  860. {
  861. pItemInfo->boolProperties = idReader.ReadMap<DWORD, DWORD>();
  862. }
  863. if (idReader.GetLastError())
  864. {
  865. DEBUG_BREAK();
  866. }
  867. if (flags & Packed_FloatStats)
  868. {
  869. pItemInfo->floatProperties = idReader.ReadMap<DWORD, double>();
  870. }
  871. if (idReader.GetLastError())
  872. {
  873. DEBUG_BREAK();
  874. }
  875. /*
  876. if (flags & Packed_StringStats)
  877. pItemInfo->stringProperties = idReader.ReadMap<DWORD>();
  878. if (flags & Packed_DataIDStats)
  879. pItemInfo->dataIDProperties = idReader.ReadMap<DWORD, DWORD>();
  880. */
  881. }
  882. reader.SetOffset(offsetStart + dwIDDataLen);
  883. m_CapturedItemData.insert(std::pair<std::string, CCapturedWorldObjectInfo*>(pItemInfo->m_ObjName, pItemInfo));
  884. if (!(pItemInfo->weenie._bitfield & BitfieldIndex::BF_PLAYER))
  885. {
  886. m_CapturedItemDataList.push_back(pItemInfo);
  887. }
  888. }
  889. delete [] data;
  890. }
  891. }
  892. CCapturedWorldObjectInfo *CGameDatabase::GetRandomCapturedArmorData()
  893. {
  894. DWORD numItems = m_CapturedArmorDataList.size();
  895. if (numItems < 1)
  896. return NULL;
  897. int Item = RandomLong(0, numItems - 1);
  898. return m_CapturedArmorDataList[Item];
  899. }
  900. CCapturedWorldObjectInfo *CGameDatabase::GetCapturedArmorData(const char *name)
  901. {
  902. std::string searchName = name;
  903. std::transform(searchName.begin(), searchName.end(), searchName.begin(), ::tolower);
  904. searchName.erase(remove_if(searchName.begin(), searchName.end(), isspace), searchName.end());
  905. std::map<std::string, CCapturedWorldObjectInfo *>::iterator i = m_CapturedArmorData.find(searchName);
  906. if (i == m_CapturedArmorData.end())
  907. return NULL;
  908. return i->second;
  909. }
  910. void CGameDatabase::LoadCapturedArmorData()
  911. {
  912. // THIS IS ALL TEMPORARY FOR TESTING
  913. // Consolidate or remove this method of loading (this was copied and pasted)
  914. BYTE *data;
  915. DWORD length;
  916. if (LoadDataFromFile("armor.dat", &data, &length))
  917. {
  918. BinaryReader reader(data, length);
  919. unsigned int count = reader.ReadDWORD();
  920. for (unsigned int i = 0; i < count; i++)
  921. {
  922. CCapturedWorldObjectInfo *pItemInfo = new CCapturedWorldObjectInfo;
  923. pItemInfo->m_ObjName = reader.ReadString();
  924. std::transform(pItemInfo->m_ObjName.begin(), pItemInfo->m_ObjName.end(), pItemInfo->m_ObjName.begin(), ::tolower);
  925. pItemInfo->m_ObjName.erase(remove_if(pItemInfo->m_ObjName.begin(), pItemInfo->m_ObjName.end(), isspace), pItemInfo->m_ObjName.end());
  926. // make all lowercase and ignore spaces for searching purposes
  927. DWORD dwObjDataLen = reader.ReadDWORD(); // size of this
  928. DWORD offset_start = reader.GetOffset();
  929. reader.ReadDWORD(); // 0xf745
  930. DWORD dwGUID = reader.ReadDWORD(); // GUID
  931. reader.ReadBYTE();
  932. BYTE numPalette = reader.ReadBYTE();
  933. BYTE numTex = reader.ReadBYTE();
  934. BYTE numModel = reader.ReadBYTE();
  935. if (numPalette)
  936. {
  937. pItemInfo->appearance.dwBasePalette = reader.ReadPackedDWORD(); // actually packed, fix this
  938. for (int j = 0; j < numPalette; j++)
  939. {
  940. DWORD replacement = reader.ReadPackedDWORD(); // actually packed, fix this
  941. BYTE offset = reader.ReadBYTE();
  942. BYTE range = reader.ReadBYTE();
  943. pItemInfo->appearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  944. }
  945. }
  946. for (int j = 0; j < numTex; j++)
  947. {
  948. BYTE index = reader.ReadBYTE();
  949. DWORD oldT = reader.ReadPackedDWORD();
  950. DWORD newT = reader.ReadPackedDWORD();
  951. pItemInfo->appearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  952. }
  953. for (int j = 0; j < numModel; j++)
  954. {
  955. BYTE index = reader.ReadBYTE();
  956. DWORD newM = reader.ReadPackedDWORD();
  957. pItemInfo->appearance.lModels.push_back(ModelRpl(index, newM));
  958. }
  959. reader.ReadAlign();
  960. pItemInfo->physics.Unpack(reader);
  961. pItemInfo->weenie.Unpack(reader);
  962. if (reader.GetLastError())
  963. {
  964. delete pItemInfo;
  965. break;
  966. }
  967. if (reader.GetOffset() != (offset_start + dwObjDataLen))
  968. {
  969. DEBUG_BREAK();
  970. }
  971. DWORD dwIDDataLen = reader.ReadDWORD();
  972. DWORD offsetStart = reader.GetOffset();
  973. if (dwIDDataLen > 0)
  974. {
  975. BinaryReader idReader(reader.GetDataPtr(), dwIDDataLen);
  976. idReader.ReadDWORD(); // 0xf7b0
  977. idReader.ReadDWORD(); // character
  978. idReader.ReadDWORD(); // sequence
  979. idReader.ReadDWORD(); // game event (0xc9)
  980. idReader.ReadDWORD(); // object
  981. DWORD flags = idReader.ReadDWORD(); // flags
  982. idReader.ReadDWORD(); // success
  983. enum AppraisalProfilePackHeader {
  984. Packed_None = 0,
  985. Packed_IntStats = (1 << 0),
  986. Packed_BoolStats = (1 << 1),
  987. Packed_FloatStats = (1 << 2),
  988. Packed_StringStats = (1 << 3),
  989. Packed_SpellList = (1 << 4),
  990. Packed_WeaponProfile = (1 << 5),
  991. Packed_HookProfile = (1 << 6),
  992. Packed_ArmorProfile = (1 << 7),
  993. Packed_CreatureProfile = (1 << 8),
  994. Packed_ArmorEnchant = (1 << 9),
  995. Packed_ResistEnchant = (1 << 10),
  996. Packed_WeaponEnchant = (1 << 11),
  997. Packed_DataIDStats = (1 << 12),
  998. Packed_Int64Stats = (1 << 13),
  999. Packed_ArmorLevels = (1 << 14)
  1000. };
  1001. if (idReader.GetLastError())
  1002. {
  1003. DEBUG_BREAK();
  1004. }
  1005. if (flags & Packed_IntStats)
  1006. pItemInfo->dwordProperties = idReader.ReadMap<DWORD, DWORD>();
  1007. if (idReader.GetLastError())
  1008. {
  1009. DEBUG_BREAK();
  1010. }
  1011. if (flags & Packed_Int64Stats)
  1012. {
  1013. pItemInfo->qwordProperties = idReader.ReadMap<DWORD, UINT64>();
  1014. }
  1015. if (idReader.GetLastError())
  1016. {
  1017. DEBUG_BREAK();
  1018. }
  1019. if (flags & Packed_BoolStats)
  1020. {
  1021. pItemInfo->boolProperties = idReader.ReadMap<DWORD, DWORD>();
  1022. }
  1023. if (idReader.GetLastError())
  1024. {
  1025. DEBUG_BREAK();
  1026. }
  1027. if (flags & Packed_FloatStats)
  1028. {
  1029. pItemInfo->floatProperties = idReader.ReadMap<DWORD, double>();
  1030. }
  1031. if (idReader.GetLastError())
  1032. {
  1033. DEBUG_BREAK();
  1034. }
  1035. /* .... etc...
  1036. if (flags & Packed_StringStats)
  1037. pItemInfo->stringProperties = idReader.ReadMap<DWORD>();
  1038. if (flags & Packed_DataIDStats)
  1039. pItemInfo->dataIDProperties = idReader.ReadMap<DWORD, DWORD>();
  1040. */
  1041. }
  1042. reader.SetOffset(offsetStart + dwIDDataLen);
  1043. DWORD dwWornModelDataLen = reader.ReadDWORD();
  1044. offsetStart = reader.GetOffset();
  1045. {
  1046. reader.ReadBYTE();
  1047. numPalette = reader.ReadBYTE();
  1048. numTex = reader.ReadBYTE();
  1049. numModel = reader.ReadBYTE();
  1050. if (numPalette)
  1051. {
  1052. pItemInfo->wornAppearance.dwBasePalette = reader.ReadPackedDWORD(); // actually packed, fix this
  1053. for (int j = 0; j < numPalette; j++)
  1054. {
  1055. DWORD replacement = reader.ReadPackedDWORD(); // actually packed, fix this
  1056. BYTE offset = reader.ReadBYTE();
  1057. BYTE range = reader.ReadBYTE();
  1058. pItemInfo->wornAppearance.lPalettes.push_back(PaletteRpl(replacement, offset, range));
  1059. }
  1060. }
  1061. for (int j = 0; j < numTex; j++)
  1062. {
  1063. BYTE index = reader.ReadBYTE();
  1064. DWORD oldT = reader.ReadPackedDWORD();
  1065. DWORD newT = reader.ReadPackedDWORD();
  1066. pItemInfo->wornAppearance.lTextures.push_back(TextureRpl(index, oldT, newT));
  1067. }
  1068. for (int j = 0; j < numModel; j++)
  1069. {
  1070. BYTE index = reader.ReadBYTE();
  1071. DWORD newM = reader.ReadPackedDWORD();
  1072. pItemInfo->wornAppearance.lModels.push_back(ModelRpl(index, newM));
  1073. }
  1074. }
  1075. reader.SetOffset(offsetStart + dwWornModelDataLen);
  1076. m_CapturedArmorData.insert(std::pair<std::string, CCapturedWorldObjectInfo*>(pItemInfo->m_ObjName, pItemInfo));
  1077. m_CapturedArmorDataList.push_back(pItemInfo);
  1078. }
  1079. delete [] data;
  1080. }
  1081. }
  1082. DWORD ParseDWORDFromStringHex(const char *hex)
  1083. {
  1084. return strtoul(hex, NULL, 16);
  1085. }
  1086. float ParseFloatFromStringHex(const char *hex)
  1087. {
  1088. DWORD hexVal = ParseDWORDFromStringHex(hex);
  1089. return *((float *)&hexVal);
  1090. }
  1091. void CGameDatabase::LoadTeleTownList()
  1092. {
  1093. bool bQuerySuccess = g_pDB2->Query("SELECT `ID`, `Description`, `Command`, `Landblock`, `Position_X`, `Position_Y`, `Position_Z`, `Orientation_W`, `Orientation_X`, `Orientation_Y`, `Orientation_Z` from tele_locations");
  1094. if (bQuerySuccess)
  1095. {
  1096. CSQLResult *Result = g_pDB2->GetResult();
  1097. if (Result)
  1098. {
  1099. SQLResultRow_t ResultRow;
  1100. while (ResultRow = Result->FetchRow())
  1101. {
  1102. TeleTownList_t t;
  1103. t.m_teleString = ResultRow[2];
  1104. t.loc.landcell = ParseDWORDFromStringHex(ResultRow[3]);
  1105. t.loc.x = ParseFloatFromStringHex(ResultRow[4]);
  1106. t.loc.y = ParseFloatFromStringHex(ResultRow[5]);
  1107. t.loc.z = ParseFloatFromStringHex(ResultRow[6]);
  1108. t.heading.w = ParseFloatFromStringHex(ResultRow[7]);
  1109. t.heading.x = ParseFloatFromStringHex(ResultRow[8]);
  1110. t.heading.y = ParseFloatFromStringHex(ResultRow[9]);
  1111. t.heading.z = ParseFloatFromStringHex(ResultRow[10]);
  1112. g_pWorld->InsertTeleportLocation(t);
  1113. }
  1114. LOG(World, Normal, "Added %d teleport locations.\n", Result->ResultRows());
  1115. }
  1116. }
  1117. }
  1118. void CGameDatabase::LoadPortals()
  1119. {
  1120. // From database Miach provided.
  1121. bool bQuerySuccess = g_pDB2->Query("SELECT name, color, Landblock, Position_X, Position_Y, Position_Z, Orientation_W, Orientation_X, Orientation_Y, Orientation_Z, Dest_Landblock, Dest_Position_X, Dest_Position_Y, Dest_Position_Z, Dest_Orientation_W, Dest_Orientation_X, Dest_Orientation_Y, Dest_Orientation_Z FROM gameobjects_portals ORDER BY ID ASC");
  1122. if (bQuerySuccess)
  1123. {
  1124. CSQLResult *Result = g_pDB2->GetResult();
  1125. if (Result)
  1126. {
  1127. int portalCount = 0;
  1128. SQLResultRow_t ResultRow;
  1129. while (ResultRow = Result->FetchRow())
  1130. {
  1131. CPortal *pPortal = new CPortal();
  1132. pPortal->m_dwGUID = g_pWorld->GenerateGUID(eDynamicGUID);
  1133. pPortal->m_strName = ResultRow[0];
  1134. // ResultRow[1] Color by cmoski
  1135. std::string strColor = ResultRow[1];
  1136. if (strColor == "blue")
  1137. pPortal->m_dwModel = 0x20005D2;
  1138. else if (strColor == "green")
  1139. pPortal->m_dwModel = 0x20005D3;
  1140. else if (strColor == "orange")
  1141. pPortal->m_dwModel = 0x20005D4;
  1142. else if (strColor == "red")
  1143. pPortal->m_dwModel = 0x20005D5;
  1144. else if (strColor == "yellow")
  1145. pPortal->m_dwModel = 0x20005D6;
  1146. else if (strColor == "purple")
  1147. pPortal->m_dwModel = 0x20001B3;
  1148. else if (strColor == "white")
  1149. pPortal->m_dwModel = 0x20001B3;
  1150. else
  1151. pPortal->m_dwModel = 0x20001B3;
  1152. pPortal->m_Origin.landcell = ParseDWORDFromStringHex(ResultRow[2]);
  1153. pPortal->m_Origin.x = ParseFloatFromStringHex(ResultRow[3]);
  1154. pPortal->m_Origin.y = ParseFloatFromStringHex(ResultRow[4]);
  1155. pPortal->m_Origin.z = ParseFloatFromStringHex(ResultRow[5]);
  1156. pPortal->m_Angles.w = ParseFloatFromStringHex(ResultRow[6]);
  1157. pPortal->m_Angles.x = ParseFloatFromStringHex(ResultRow[7]);
  1158. pPortal->m_Angles.y = ParseFloatFromStringHex(ResultRow[8]);
  1159. pPortal->m_Angles.z = ParseFloatFromStringHex(ResultRow[9]);
  1160. pPortal->m_bHasDestination = true;
  1161. pPortal->m_Destination.origin.landcell = ParseDWORDFromStringHex(ResultRow[10]);
  1162. pPortal->m_Destination.origin.x = ParseFloatFromStringHex(ResultRow[11]);
  1163. pPortal->m_Destination.origin.y = ParseFloatFromStringHex(ResultRow[12]);
  1164. pPortal->m_Destination.origin.z = ParseFloatFromStringHex(ResultRow[13]);
  1165. pPortal->m_Destination.angles.w = ParseFloatFromStringHex(ResultRow[14]);
  1166. pPortal->m_Destination.angles.x = ParseFloatFromStringHex(ResultRow[15]);
  1167. pPortal->m_Destination.angles.y = ParseFloatFromStringHex(ResultRow[16]);
  1168. pPortal->m_Destination.angles.z = ParseFloatFromStringHex(ResultRow[17]);
  1169. g_pWorld->CreateEntity(pPortal);
  1170. portalCount++;
  1171. }
  1172. LOG(World, Normal, "Spawned %d portals.\n", portalCount);
  1173. delete Result;
  1174. if (portalCount > 0)
  1175. {
  1176. m_bLoadedPortals = true;
  1177. }
  1178. }
  1179. }
  1180. }
  1181. void CGameDatabase::LoadMonsterTemplates()
  1182. {
  1183. }
  1184. CPhysicsObj *CGameDatabase::CreateFromCapturedData(CCapturedWorldObjectInfo *pObjectInfo)
  1185. {
  1186. if (!pObjectInfo)
  1187. {
  1188. return NULL;
  1189. }
  1190. CPhysicsObj *pObject;
  1191. if (pObjectInfo->weenie._type & ITEM_TYPE::TYPE_CREATURE)
  1192. {
  1193. pObject = new CBaseMonster();
  1194. }
  1195. else if (pObjectInfo->weenie._location ||
  1196. (pObjectInfo->weenie._type &
  1197. (ITEM_TYPE::TYPE_ARMOR | ITEM_TYPE::TYPE_CLOTHING | ITEM_TYPE::TYPE_FOOD | ITEM_TYPE::TYPE_JEWELRY |
  1198. ITEM_TYPE::TYPE_KEY | ITEM_TYPE::TYPE_MAGIC_WIELDABLE | ITEM_TYPE::TYPE_MANASTONE | ITEM_TYPE::TYPE_CLOTHING |
  1199. ITEM_TYPE::TYPE_FOOD | ITEM_TYPE::TYPE_JEWELRY | ITEM_TYPE::TYPE_KEY | ITEM_TYPE::TYPE_MAGIC_WIELDABLE |
  1200. ITEM_TYPE::TYPE_MANASTONE | ITEM_TYPE::TYPE_MELEE_WEAPON | ITEM_TYPE::TYPE_MISSILE_WEAPON | ITEM_TYPE::TYPE_MONEY |
  1201. ITEM_TYPE::TYPE_PROMISSORY_NOTE | ITEM_TYPE::TYPE_SPELL_COMPONENTS)))
  1202. {
  1203. pObject = new CBaseItem();
  1204. }
  1205. else
  1206. {
  1207. pObject = new CPhysicsObj();
  1208. }
  1209. pObject->m_dwGUID = pObjectInfo->guid;
  1210. pObject->m_miBaseModel = pObjectInfo->appearance;
  1211. pObject->m_dwModel = pObjectInfo->physics.setup_id;
  1212. pObject->m_dwAnimationSet = pObjectInfo->physics.mtable_id;
  1213. pObject->m_dwSoundSet = pObjectInfo->physics.stable_id;
  1214. pObject->m_dwEffectSet = pObjectInfo->physics.phstable_id;
  1215. pObject->m_fScale = pObjectInfo->physics.object_scale;
  1216. pObject->m_ItemType = pObjectInfo->weenie._type;
  1217. pObject->m_strName = pObjectInfo->weenie._name;
  1218. pObject->m_Origin.landcell = pObjectInfo->physics.pos.objcell_id;
  1219. pObject->m_Origin.x = pObjectInfo->physics.pos.frame.m_fOrigin.x;
  1220. pObject->m_Origin.y = pObjectInfo->physics.pos.frame.m_fOrigin.y;
  1221. pObject->m_Origin.z = pObjectInfo->physics.pos.frame.m_fOrigin.z;
  1222. pObject->m_Angles.w = pObjectInfo->physics.pos.frame.qw;
  1223. pObject->m_Angles.x = pObjectInfo->physics.pos.frame.qx;
  1224. pObject->m_Angles.y = pObjectInfo->physics.pos.frame.qy;
  1225. pObject->m_Angles.z = pObjectInfo->physics.pos.frame.qz;
  1226. if (pObjectInfo->physics.movement_buffer)
  1227. {
  1228. pObject->m_AnimOverrideData = pObjectInfo->physics.movement_buffer;
  1229. pObject->m_AnimOverrideDataLen = pObjectInfo->physics.movement_buffer_length;
  1230. pObject->m_AutonomousMovement = pObjectInfo->physics.autonomous_movement;
  1231. }
  1232. pObject->m_wIcon = pObjectInfo->weenie._iconID & 0xFFFFFF;
  1233. pObject->m_UIEffects = pObjectInfo->weenie._effects;
  1234. pObject->m_dwEquipSlot = pObjectInfo->weenie._combatUse; // This isn't correct.
  1235. pObject->m_dwEquipType = pObjectInfo->weenie._combatUse;
  1236. pObject->m_dwCoverage1 = pObjectInfo->weenie._valid_locations;
  1237. pObject->m_dwCoverage2 = pObjectInfo->weenie._location;
  1238. pObject->m_dwCoverage3 = pObjectInfo->weenie._priority;
  1239. pObject->m_dwordProperties = pObjectInfo->dwordProperties;
  1240. pObject->m_qwordProperties = pObjectInfo->qwordProperties;
  1241. pObject->m_boolProperties = pObjectInfo->boolProperties;
  1242. pObject->m_floatProperties = pObjectInfo->floatProperties;
  1243. pObject->m_stringProperties = pObjectInfo->stringProperties;
  1244. pObject->m_dataIDProperties = pObjectInfo->dataIDProperties;
  1245. pObject->m_miWornModel = pObjectInfo->wornAppearance;
  1246. return pObject;
  1247. }