Clone of Akilla's ac2d @ https://github.com/deregtd/AC2D

cCharInfo.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. #include "stdafx.h"
  2. #include "cCharInfo.h"
  3. cCharInfo::cCharInfo()
  4. {
  5. m_dwTotalBurden = 0;
  6. m_dwTotalPyreal = 0;
  7. m_qwTotalXP = 0;
  8. m_qwUnassignedXP = 0;
  9. m_dwUnassignedCredits = 0;
  10. m_dwLevel = 0;
  11. m_dwRank = 0;
  12. m_dwDeaths = 0;
  13. m_dwBirth = 0;
  14. m_dwAge = 0;
  15. m_bMovementDisabled = false;
  16. m_sName = "";
  17. m_sGender = "";
  18. m_sRace = "";
  19. m_sClass = "";
  20. m_lCorpses.clear();
  21. m_dwGUID = 0;
  22. m_dwPatron = 0;
  23. m_dwMonarch = 0;
  24. m_fVitae = 1.0f;
  25. m_lSpellbook.clear();
  26. for (int i=0;i<7;i++)
  27. m_lSpellBar[i].clear();
  28. m_lCompBuyer.clear();
  29. m_dwOptions = 0;
  30. for (int i=0;i<10;i++)
  31. m_dwShortcut[i] = 0;
  32. m_dwMaxSkill = 0;
  33. // ZeroMemory(m_siStat, sizeof(m_siStat));
  34. // ZeroMemory(m_siSecStat, sizeof(m_siSecStat));
  35. m_lEnchantments.clear();
  36. LoadSpellsTable();
  37. LoadSkillsTable();
  38. LoadStatsTable();
  39. LoadSecStatsTable();
  40. m_aiMonarch = m_aiPatron = m_aiChar = NULL;
  41. m_vVassals.clear();
  42. }
  43. cCharInfo::~cCharInfo()
  44. {
  45. for (std::list<cEnchantment *>::iterator tpi = m_lEnchantments.begin(); tpi != m_lEnchantments.end(); tpi++)
  46. delete *tpi;
  47. }
  48. void cCharInfo::LoadSpellsTable()
  49. {
  50. //Parse Spell Table
  51. cPortalFile *PF = m_Portal->OpenEntry(0x0E00000E);
  52. cByteStream *BS = new cByteStream(PF->data, PF->length);
  53. BS->ReadBegin();
  54. DWORD dwID = BS->ReadDWORD();
  55. WORD wCount = BS->ReadWORD();
  56. BS->ReadWORD();
  57. stInternalSpell IS;
  58. memset( &IS, 0, sizeof( IS ) );
  59. //FILE *out = fopen("c:\\spells.csv", "wt");
  60. // Loop through the spell table.
  61. for( int i = 0; i < wCount; i++ )
  62. {
  63. IS.dwSpellID = BS->ReadDWORD();
  64. char *temp = BS->ReadEncodedString();
  65. IS.szName = temp;
  66. delete []temp;
  67. temp = BS->ReadEncodedString();
  68. IS.szDesc = temp;
  69. delete []temp;
  70. IS.dwSchool = BS->ReadDWORD();
  71. IS.dwIcon = BS->ReadDWORD();
  72. IS.dwEffect = BS->ReadDWORD();
  73. IS.dwFlags = BS->ReadDWORD();
  74. IS.dwManaCost = BS->ReadDWORD();
  75. IS.fRangeBase = BS->ReadFloat();
  76. IS.fRangeModifier = BS->ReadFloat();
  77. IS.dwDifficulty = BS->ReadDWORD();
  78. IS.fEconomy = BS->ReadFloat();
  79. IS.dwVersion = BS->ReadDWORD();
  80. IS.fSpeed = BS->ReadFloat();
  81. IS.dwType = BS->ReadDWORD();
  82. IS.dwID2 = BS->ReadDWORD();
  83. if( IS.dwType == 1 || IS.dwType == 7 || IS.dwType == 12 )
  84. {
  85. IS.dDuration = BS->ReadDouble();
  86. }
  87. if( IS.dwType == 1 || IS.dwType == 12 )
  88. {
  89. IS.dwUnk2 = BS->ReadDWORD();
  90. IS.dwUnk3 = BS->ReadDWORD();
  91. }
  92. memcpy(IS.pdwComps, BS->ReadGroup(sizeof(DWORD) * 8), sizeof(DWORD) * 8);
  93. IS.dwEffectOnCaster = BS->ReadDWORD();
  94. IS.dwEffectOnTarget = BS->ReadDWORD();
  95. memcpy(IS.pdwMisc, BS->ReadGroup(sizeof(DWORD) * 4), sizeof(DWORD) * 4);
  96. IS.dwSortOrder = BS->ReadDWORD();
  97. IS.dwTargetMask = BS->ReadDWORD();
  98. IS.dwUnk6 = BS->ReadDWORD();
  99. if( IS.dwFlags & 0x80 )
  100. IS.Researchable = false;
  101. else
  102. IS.Researchable = true;
  103. if (IS.dwDifficulty < 40) IS.iLevel = 1;
  104. else if (IS.dwDifficulty < 80) IS.iLevel = 2;
  105. else if (IS.dwDifficulty < 120) IS.iLevel = 3;
  106. else if (IS.dwDifficulty < 180) IS.iLevel = 4;
  107. else if (IS.dwDifficulty < 230) IS.iLevel = 5;
  108. else if (IS.dwDifficulty < 290) IS.iLevel = 6;
  109. else if (IS.dwDifficulty < 370) IS.iLevel = 7;
  110. else IS.iLevel = 8;
  111. m_mSpell[ IS.dwSpellID ] = IS;
  112. /* fprintf(out, "%i,%s,\"%04X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"\n",
  113. IS.dwSpellID, IS.szName.c_str(), IS.dwEffect, IS.dwFlags, IS.dwIcon, IS.dwTargetMask, IS.dwEffect,
  114. IS.dwEffectOnCaster, IS.dwEffectOnTarget);
  115. fflush(out);*/
  116. }
  117. //fclose(out);
  118. delete BS;
  119. }
  120. void cCharInfo::LoadSkillsTable()
  121. {
  122. //Parse Spell Table
  123. cPortalFile *PF = m_Portal->OpenEntry(0x0E000004);
  124. cByteStream *BS = new cByteStream(PF->data, PF->length);
  125. BS->ReadBegin();
  126. DWORD dwID = BS->ReadDWORD();
  127. WORD wCount = BS->ReadWORD();
  128. BS->ReadWORD();
  129. stInternalSkill SI;
  130. memset( &SI, 0, sizeof( SI ) );
  131. // FILE *out = fopen("c:\\skills.csv","wt");
  132. for (int i=0; i<wCount; i++)
  133. {
  134. SI.dwID = BS->ReadDWORD();
  135. char *temp = BS->ReadString();
  136. SI.szDescription = temp;
  137. delete []temp;
  138. temp = BS->ReadString();
  139. SI.szName = temp;
  140. delete []temp;
  141. SI.dwIcon = BS->ReadDWORD();
  142. SI.dwTrainCost = BS->ReadDWORD();
  143. SI.dwSpecCost = BS->ReadDWORD();
  144. SI.dwType = BS->ReadDWORD();
  145. SI.dwUnk1 = BS->ReadDWORD();
  146. DWORD dwUse = BS->ReadDWORD();
  147. SI.bUsableUntrained = (dwUse == 1);
  148. SI.dwUnk0 = BS->ReadDWORD();
  149. DWORD dwAttrib1Valid = BS->ReadDWORD();
  150. DWORD dwAttrib2Valid = BS->ReadDWORD();
  151. SI.dwAttribDivisor = BS->ReadDWORD();
  152. SI.dwAttrib1 = (eAttributeID) BS->ReadDWORD();
  153. SI.dwAttrib2 = (eAttributeID) BS->ReadDWORD();
  154. if (!dwAttrib1Valid) SI.dwAttrib1 = eAttrNULL;
  155. if (!dwAttrib2Valid) SI.dwAttrib2 = eAttrNULL;
  156. SI.dXPTimerLimit = BS->ReadDouble();
  157. SI.dXPTimerStart = BS->ReadDouble();
  158. SI.dUnk1 = BS->ReadDouble();
  159. SI.dwInc = 0;
  160. SI.dwTrained = SI.bUsableUntrained ? eTrainUntrained : eTrainUnusable;
  161. SI.dwXP = 0;
  162. SI.dwBonus = 0;
  163. SI.dwBuffed = 0;
  164. // fprintf(out, "%i,%s\n",SI.dwID, SI.szName.c_str());
  165. m_mSkill[SI.dwID] = SI;
  166. if (SI.dwID > m_dwMaxSkill)
  167. m_dwMaxSkill = SI.dwID;
  168. }
  169. delete BS;
  170. // fclose(out);
  171. }
  172. void cCharInfo::LoadStatsTable()
  173. {
  174. DWORD dwIcons[6] = {
  175. 0x060002C8,
  176. 0x060002C4,
  177. 0x060002C6,
  178. 0x060002C9,
  179. 0x060002C5,
  180. 0x060002C7
  181. };
  182. char szNames[6][25] = {
  183. "Strength",
  184. "Endurance",
  185. "Quickness",
  186. "Coordination",
  187. "Focus",
  188. "Self"
  189. };
  190. char szDescs[6][100] = {
  191. "Measures your character's muscular power.",
  192. "Measures how healthy your character is.",
  193. "Measures your character's reflexes.",
  194. "Measures how fast your character is.",
  195. "Measures your character's mind and senses.",
  196. "Measures your character's willpower."
  197. };
  198. stStatInfo SI;
  199. memset( &SI, 0, sizeof( SI ) );
  200. for (int i=1; i<=6; i++)
  201. {
  202. SI.dwID = i;
  203. SI.dwIcon = dwIcons[i-1];
  204. SI.szDescription = szDescs[i-1];
  205. SI.szName = szNames[i-1];
  206. m_mStat[SI.dwID] = SI;
  207. }
  208. }
  209. void cCharInfo::LoadSecStatsTable()
  210. {
  211. DWORD dwIcons[3] = {
  212. 0x060013B1,
  213. 0x0600138B,
  214. 0x06001380
  215. };
  216. char szNames[3][25] = {
  217. "Health",
  218. "Stamina",
  219. "Mana"
  220. };
  221. char szDescs[3][100] = {
  222. "If you run out of health, you will die!",
  223. "Affects your actions and movement.",
  224. "Affects how much magic you can cast."
  225. };
  226. eAttributeID aiAttribs[3] = {
  227. eAttrEndurance,
  228. eAttrEndurance,
  229. eAttrSelf
  230. };
  231. DWORD dwDivisors[3] = {
  232. 2,
  233. 1,
  234. 1
  235. };
  236. stSecStatInfo SI;
  237. memset( &SI, 0, sizeof( SI ) );
  238. for (int i=2; i<=6; i+=2)
  239. {
  240. SI.dwID = i;
  241. SI.dwIcon = dwIcons[(i >> 1) - 1];
  242. SI.szDescription = szDescs[(i >> 1) - 1];
  243. SI.szName = szNames[(i >> 1) - 1];
  244. SI.dwAttrib = aiAttribs[(i >> 1) - 1];
  245. SI.dwAttribDivisor = dwDivisors[(i >> 1) - 1];
  246. m_mSecStat[SI.dwID] = SI;
  247. }
  248. }
  249. void cCharInfo::SetGUID(DWORD dwGUID)
  250. {
  251. m_dwGUID = dwGUID;
  252. }
  253. void cCharInfo::ParseLogin(cMessage *Msg)
  254. {
  255. Lock();
  256. //CharacterPropertyData start
  257. DWORD flags1 = Msg->ReadDWORD();
  258. DWORD unknown1 = Msg->ReadDWORD(); //always 0x0A
  259. if (flags1 & 0x00000001) //dword properties
  260. {
  261. WORD countStats = Msg->ReadWORD();
  262. WORD unknownStats = Msg->ReadWORD();
  263. for (int i=0;i<countStats;i++)
  264. {
  265. DWORD key = Msg->ReadDWORD();
  266. DWORD value = Msg->ReadDWORD();
  267. UpdateStatisticDW(key, value);
  268. }
  269. }
  270. if (flags1 & 0x00000080) //qword properties
  271. {
  272. WORD countQWord = Msg->ReadWORD();
  273. WORD unknownQWord = Msg->ReadWORD();
  274. for (int i=0;i<countQWord;i++)
  275. {
  276. DWORD key = Msg->ReadDWORD();
  277. QWORD value = Msg->ReadQWORD();
  278. UpdateStatisticQW(key, value);
  279. }
  280. }
  281. if (flags1 & 0x00000002) //bool properties
  282. {
  283. WORD countBools = Msg->ReadWORD();
  284. WORD unknownBools = Msg->ReadWORD();
  285. for (int i=0;i<countBools;i++)
  286. {
  287. DWORD key = Msg->ReadDWORD();
  288. DWORD value = Msg->ReadDWORD();
  289. UpdateStatisticBool(key, (value == 1));
  290. }
  291. }
  292. if (flags1 & 0x00000004) //double properties
  293. {
  294. WORD countDoubles = Msg->ReadWORD();
  295. WORD unknownDoubles = Msg->ReadWORD();
  296. for (int i=0;i<countDoubles;i++)
  297. {
  298. DWORD key = Msg->ReadDWORD();
  299. double value = Msg->ReadDouble();
  300. }
  301. }
  302. if (flags1 & 0x00000010) //string properties
  303. {
  304. WORD countStrings = Msg->ReadWORD();
  305. WORD unknownStrings = Msg->ReadWORD();
  306. for (int i=0;i<countStrings;i++)
  307. {
  308. DWORD key = Msg->ReadDWORD();
  309. char * string = Msg->ReadString();
  310. switch (key)
  311. {
  312. case 1: m_sName = string; break;
  313. // case 3: m_sGender = string; break;
  314. // case 4: m_sRace = string; break;
  315. case 5: m_sClass = string; break; //class = title
  316. }
  317. delete []string;
  318. }
  319. }
  320. if (flags1 & 0x00000040) //resource prpoerties
  321. {
  322. WORD countResources = Msg->ReadWORD();
  323. WORD unknownResources = Msg->ReadWORD();
  324. for (int i=0;i<countResources;i++)
  325. {
  326. DWORD key = Msg->ReadDWORD();
  327. DWORD value = Msg->ReadDWORD();
  328. }
  329. }
  330. if (flags1 & 0x00000008) //link properties
  331. {
  332. WORD countLinks = Msg->ReadWORD();
  333. WORD unknownLinks = Msg->ReadWORD();
  334. for (int i=0;i<countLinks;i++)
  335. {
  336. DWORD key = Msg->ReadDWORD();
  337. DWORD value = Msg->ReadDWORD();
  338. }
  339. }
  340. if (flags1 & 0x00000020) //position properties (corpses?)
  341. {
  342. WORD countCorpse = Msg->ReadWORD();
  343. WORD unknownCorpse = Msg->ReadWORD();
  344. for (int i=0;i<countCorpse;i++)
  345. {
  346. DWORD key = Msg->ReadDWORD();
  347. stLocation tploc;
  348. memcpy(&tploc, Msg->ReadGroup(sizeof(stLocation)), sizeof(stLocation));
  349. m_lCorpses.push_back(tploc);
  350. }
  351. }
  352. //CharacterPropertyData end
  353. //CharacterVectorData start
  354. DWORD flags2 = Msg->ReadDWORD();
  355. DWORD unknown2 = Msg->ReadDWORD(); //always 1
  356. if (flags2 & 0x00000001)
  357. {
  358. DWORD attributeMask = Msg->ReadDWORD(); //mask it if we want but it's always 1FF (all of them...)
  359. for (int i=1;i<=6;i++)
  360. {
  361. m_mStat[i].dwInc = Msg->ReadDWORD();
  362. m_mStat[i].dwInitial = Msg->ReadDWORD();
  363. m_mStat[i].dwXP = Msg->ReadDWORD();
  364. }
  365. for (int i=2;i<=6;i+=2)
  366. {
  367. m_mSecStat[i].dwInc = Msg->ReadDWORD();
  368. m_mSecStat[i].dwUnknown = Msg->ReadDWORD();
  369. m_mSecStat[i].dwXP = Msg->ReadDWORD();
  370. m_mSecStat[i].dwCurrent = Msg->ReadDWORD();
  371. }
  372. }
  373. if (flags2 & 0x00000002)
  374. {
  375. WORD skillCount = Msg->ReadWORD();
  376. WORD skillUnknown = Msg->ReadWORD();
  377. for (int i=0;i<skillCount;i++)
  378. {
  379. DWORD skillID = Msg->ReadDWORD();
  380. if (GetSkillValid(skillID))
  381. {
  382. stInternalSkill *sk = GetSkillInfo(skillID);
  383. sk->dwInc = Msg->ReadWORD();
  384. WORD unknown1 = Msg->ReadWORD();
  385. sk->dwTrained = (eTrainingType) Msg->ReadDWORD();
  386. if (sk->dwTrained == eTrainUntrained)
  387. sk->dwTrained = sk->bUsableUntrained ? eTrainUntrained : eTrainUnusable;
  388. sk->dwXP = Msg->ReadDWORD();
  389. sk->dwBonus = Msg->ReadDWORD();
  390. DWORD difficulty = Msg->ReadDWORD();
  391. double unknown2skill = Msg->ReadDouble();
  392. }
  393. else
  394. {
  395. Msg->ReadWORD();
  396. Msg->ReadWORD();
  397. Msg->ReadDWORD();
  398. Msg->ReadDWORD();
  399. Msg->ReadDWORD();
  400. Msg->ReadDWORD();
  401. Msg->ReadDouble();
  402. //weird unlisted skills..?
  403. }
  404. }
  405. }
  406. if (flags2 & 0x00000100)
  407. {
  408. //spellbook
  409. WORD spellbookCount = Msg->ReadWORD();
  410. WORD spellbookUnknown = Msg->ReadWORD();
  411. for (int i=0;i<spellbookCount;i++)
  412. {
  413. DWORD spell = Msg->ReadDWORD();
  414. float charge = Msg->ReadFloat();
  415. m_lSpellbook.insert(spell);
  416. }
  417. }
  418. if (flags2 & 0x00000200)
  419. {
  420. //enchantments
  421. DWORD enchantmentMask = Msg->ReadDWORD();
  422. if (enchantmentMask & 1)
  423. {
  424. //life magic
  425. DWORD lifeSpellCount = Msg->ReadDWORD();
  426. for (int i=0;i<(int)lifeSpellCount;i++)
  427. {
  428. cEnchantment *tpench = new cEnchantment();
  429. tpench->Unpack(Msg);
  430. AddEnchantment(tpench);
  431. }
  432. }
  433. if (enchantmentMask & 2)
  434. {
  435. //critter magic
  436. DWORD creatureSpellCount = Msg->ReadDWORD();
  437. for (int i=0;i<(int)creatureSpellCount;i++)
  438. {
  439. cEnchantment *tpench = new cEnchantment();
  440. tpench->Unpack(Msg);
  441. AddEnchantment(tpench);
  442. }
  443. }
  444. if (enchantmentMask & 4)
  445. {
  446. //vitae
  447. cEnchantment *tpench = new cEnchantment();
  448. tpench->Unpack(Msg);
  449. AddEnchantment(tpench);
  450. }
  451. if (enchantmentMask & 8)
  452. {
  453. //cooldowns
  454. DWORD cooldownCount = Msg->ReadDWORD();
  455. for (int i=0;i<(int)cooldownCount;i++)
  456. {
  457. cEnchantment *tpench = new cEnchantment();
  458. tpench->Unpack(Msg);
  459. AddEnchantment(tpench);
  460. }
  461. }
  462. }
  463. //CharacterVectorData End
  464. //CharacterOptionData Start
  465. DWORD flags3 = Msg->ReadDWORD();
  466. m_dwOptions = Msg->ReadDWORD();
  467. if (flags3 & 0x1)
  468. {
  469. DWORD shortcutCount = Msg->ReadDWORD();
  470. for (int i=0;i<(int)shortcutCount;i++)
  471. {
  472. DWORD position = Msg->ReadDWORD();
  473. m_dwShortcut[position] = Msg->ReadDWORD();
  474. DWORD unknown3 = Msg->ReadDWORD();
  475. }
  476. }
  477. //spellbars
  478. int spellBarCount = 8;
  479. //if (flags3 & 0x10)
  480. // spellBarCount = 7;
  481. for (int i=0;i<spellBarCount;i++)
  482. {
  483. DWORD tabxCount = Msg->ReadDWORD();
  484. for (int h=0;h<(int)tabxCount;h++)
  485. {
  486. DWORD spell = Msg->ReadDWORD();
  487. m_lSpellBar[i].push_back(spell);
  488. }
  489. }
  490. if (flags3 & 0x8)
  491. {
  492. WORD compBuyerCount = Msg->ReadWORD();
  493. WORD compBuyerUnknown = Msg->ReadWORD();
  494. for (int i=0;i<compBuyerCount;i++)
  495. {
  496. DWORD compModel = Msg->ReadDWORD();
  497. DWORD compRefill = Msg->ReadDWORD();
  498. m_lCompBuyer.push_back(std::pair<DWORD,DWORD>(compModel, compRefill));
  499. }
  500. }
  501. if (flags3 & 0x20)
  502. {
  503. DWORD unk20mask3 = Msg->ReadDWORD();
  504. }
  505. if (flags3 & 0x40)
  506. {
  507. DWORD characterOptions2 = Msg->ReadDWORD();
  508. }
  509. if (flags3 & 0x00000100)
  510. {
  511. DWORD unk100_1 = Msg->ReadDWORD();
  512. WORD optionStringsCount = Msg->ReadWORD();
  513. WORD optionStringsUnknown = Msg->ReadWORD();
  514. for (int i=0;i<optionStringsCount;i++)
  515. {
  516. DWORD key = Msg->ReadDWORD();
  517. char * string = Msg->ReadString();
  518. delete []string;
  519. }
  520. }
  521. if (flags3 & 0x00000200)
  522. {
  523. DWORD unk200_1 = Msg->ReadDWORD();
  524. BYTE unk200_2 = Msg->ReadByte();
  525. BYTE optionPropertyCount = Msg->ReadByte();
  526. for (int i=0; i<optionPropertyCount; i++)
  527. {
  528. cPropertyType cPT;
  529. cPT.Unpack(Msg);
  530. }
  531. Msg->ReadAlign();
  532. }
  533. //CharacterOptionData Finish
  534. DWORD inventoryCount = Msg->ReadDWORD();
  535. for (int i=0;i<(int)inventoryCount;i++)
  536. {
  537. DWORD object = Msg->ReadDWORD();
  538. DWORD isContainer = Msg->ReadDWORD();
  539. //backpack tracking...
  540. }
  541. DWORD equipmentCount = Msg->ReadDWORD();
  542. for (int i=0;i<(int)equipmentCount;i++)
  543. {
  544. DWORD object = Msg->ReadDWORD();
  545. DWORD EquipMask = Msg->ReadDWORD();
  546. DWORD unknown3 = Msg->ReadDWORD();
  547. //equipped item tracking...
  548. }
  549. Unlock();
  550. RecalcStats();
  551. RecalcSecStats();
  552. RecalcSkills();
  553. }
  554. void cCharInfo::ParseAllegiance(cMessage *Msg)
  555. {
  556. Lock();
  557. DWORD unk0 = Msg->ReadDWORD();
  558. DWORD allegSize = Msg->ReadDWORD();
  559. DWORD followers = Msg->ReadDWORD();
  560. WORD recordCount = Msg->ReadWORD();
  561. WORD unk1 = Msg->ReadWORD();
  562. Msg->ReadGroup(sizeof(DWORD)*17);
  563. char *allegianceName = Msg->ReadString();
  564. delete []allegianceName;
  565. Msg->ReadGroup(sizeof(DWORD)*2);
  566. if (recordCount == 0)
  567. Msg->ReadDWORD();
  568. //Clean up the last batch..
  569. if (m_aiMonarch)
  570. {
  571. delete m_aiMonarch;
  572. m_aiMonarch = NULL;
  573. }
  574. if (m_aiPatron)
  575. {
  576. delete m_aiPatron;
  577. m_aiPatron = NULL;
  578. }
  579. if (m_aiChar)
  580. {
  581. delete m_aiChar;
  582. m_aiChar = NULL;
  583. }
  584. for (std::vector<stAllegianceInfo *>::iterator i = m_vVassals.begin(); i != m_vVassals.end(); i++)
  585. delete *i;
  586. m_vVassals.clear();
  587. std::vector<stAllegianceInfo *> vRawAllegs;
  588. for (int i=0; i<recordCount; i++)
  589. {
  590. stAllegianceInfo *AI = new stAllegianceInfo;
  591. AI->dwParent = Msg->ReadDWORD();
  592. AI->dwGUID = Msg->ReadDWORD();
  593. AI->dwPendingXP = Msg->ReadDWORD();
  594. AI->qwXP = Msg->ReadQWORD();
  595. AI->bGender = Msg->ReadByte();
  596. AI->bRace = Msg->ReadByte();
  597. AI->bRank = Msg->ReadByte();
  598. Msg->ReadAlign();
  599. AI->bOnline = (Msg->ReadDWORD() > 0);
  600. AI->wLoyalty = Msg->ReadWORD();
  601. AI->wLeadership = Msg->ReadWORD();
  602. AI->dUnknown = Msg->ReadDouble();
  603. char *temp = Msg->ReadString();
  604. AI->szName = temp;
  605. delete []temp;
  606. vRawAllegs.push_back(AI);
  607. }
  608. if ( vRawAllegs.size() == 0 )
  609. {
  610. //this outta never happen
  611. return;
  612. }
  613. //Now parse it out
  614. std::vector<stAllegianceInfo *>::iterator j = vRawAllegs.begin();
  615. //we now 'know' that the monarch is the first entry, always
  616. if ( (*j)->dwGUID != m_dwGUID ) //i'm not the monarch, so find out who is
  617. {
  618. if ( (*(j + 1))->dwGUID != m_dwGUID ) //i'm not a direct either
  619. {
  620. m_aiMonarch = *j;
  621. j = vRawAllegs.erase( j ); // this is my patron now
  622. }
  623. m_aiPatron = *j;
  624. j = vRawAllegs.erase( j );
  625. }
  626. // we've taken care of any possible patron & monarch,
  627. // so i'm all that's left
  628. m_aiChar = *j;
  629. j = vRawAllegs.erase( j );
  630. //Get race and gender from here now... Only way to do it...
  631. if (m_aiChar->bGender == 1) m_sGender = "Male";
  632. if (m_aiChar->bGender == 2) m_sGender = "Female";
  633. if (m_aiChar->bRace == 1) m_sRace = "Aluvian";
  634. if (m_aiChar->bRace == 2) m_sRace = "Gharu'ndim";
  635. if (m_aiChar->bRace == 3) m_sRace = "Sho";
  636. //The remainder *should* all be vassals
  637. while( vRawAllegs.size() > 0 )
  638. {
  639. //Vassal
  640. m_vVassals.push_back(*j);
  641. j = vRawAllegs.erase( j );
  642. }
  643. }
  644. void cCharInfo::ParseFriendsUpdate(cMessage *Msg)
  645. {
  646. DWORD friendsCount = Msg->ReadDWORD();
  647. for (int i=0; i<(int)friendsCount; i++)
  648. {
  649. DWORD friendID = Msg->ReadDWORD();
  650. bool online = Msg->ReadDWORD() == 1;
  651. DWORD unknown1 = Msg->ReadDWORD();
  652. char * name = Msg->ReadString();
  653. delete []name;
  654. DWORD outFriendsCount = Msg->ReadDWORD();
  655. for (int h=0; h<(int)outFriendsCount; h++)
  656. {
  657. DWORD outFriend = Msg->ReadDWORD();
  658. }
  659. DWORD inFriendsCount = Msg->ReadDWORD();
  660. for (int h=0; h<(int)inFriendsCount; h++)
  661. {
  662. DWORD inFriend = Msg->ReadDWORD();
  663. }
  664. }
  665. DWORD friendsUpdateType = Msg->ReadDWORD();
  666. /* 0x0000 Full friends list (at log in)
  667. 0x0001 Friend added
  668. 0x0002 Friend removed
  669. 0x0004 Friend logged in or out*/
  670. }
  671. void cCharInfo::ParseTitleList(cMessage *Msg)
  672. {
  673. DWORD unknown = Msg->ReadDWORD();
  674. DWORD current = Msg->ReadDWORD();
  675. DWORD count = Msg->ReadDWORD();
  676. for (int i=0; i<(int)count; i++)
  677. {
  678. DWORD title = Msg->ReadDWORD();
  679. }
  680. }
  681. void cCharInfo::ParseSquelches(cMessage *Msg)
  682. {
  683. m_vSquelchedUsers.clear();
  684. stSquelchedUser SU;
  685. DWORD unknown0 = Msg->ReadDWORD();
  686. WORD squelchCount = Msg->ReadWORD();
  687. WORD squelchUnknown = Msg->ReadWORD();
  688. for (int i=0; i<squelchCount; i++)
  689. {
  690. SU.dwGUID = Msg->ReadDWORD();
  691. DWORD unknown1 = Msg->ReadDWORD();
  692. DWORD unknown2 = Msg->ReadDWORD();
  693. DWORD unknown3 = Msg->ReadDWORD();
  694. DWORD unknown4 = Msg->ReadDWORD();
  695. DWORD unknown5 = Msg->ReadDWORD();
  696. char *temp = Msg->ReadString();
  697. SU.szName = temp;
  698. delete []temp;
  699. DWORD unknown6 = Msg->ReadDWORD();
  700. m_vSquelchedUsers.push_back(SU);
  701. }
  702. }
  703. void cCharInfo::UpdateStatisticBool(DWORD Property, bool Value)
  704. {
  705. //?..
  706. }
  707. void cCharInfo::UpdateStatisticQW(DWORD Statistic, QWORD Value)
  708. {
  709. if (Statistic == 1) m_qwTotalXP = Value;
  710. else if (Statistic == 2) m_qwUnassignedXP = Value;
  711. }
  712. void cCharInfo::UpdateStatisticDW(DWORD Statistic, DWORD Value)
  713. {
  714. /*0x05 Total Burden
  715. 0x14 Total Pyreal
  716. 0x15 Total Experience
  717. 0x16 Unassigned Experience
  718. 0x18 Unassigned Skill Points
  719. 0x19 Level
  720. 0x1e Rank
  721. 0x28 Movement Disabled (1 indicates movement should be ignored)
  722. 0x2B Deaths
  723. 0x2F Unknown2
  724. 0x62 Birth - Unix Time Seconds
  725. 0x7D Age - Seconds
  726. 0x81 Unknown3
  727. 0x8B Unknown4*/
  728. Lock();
  729. switch (Statistic)
  730. {
  731. case 0x05:
  732. m_dwTotalBurden = Value;
  733. break;
  734. case 0x14:
  735. m_dwTotalPyreal = Value;
  736. break;
  737. /* case 0x15:
  738. m_qwTotalXP = Value;
  739. break;
  740. case 0x16:
  741. m_qwUnassignedXP = Value;
  742. break;*/
  743. case 0x18:
  744. m_dwUnassignedCredits = Value;
  745. break;
  746. case 0x19:
  747. m_dwLevel = Value;
  748. break;
  749. case 0x1e:
  750. m_dwRank = Value;
  751. break;
  752. case 0x28:
  753. m_bMovementDisabled = (Value == 1);
  754. break;
  755. case 0x2B:
  756. m_dwDeaths = Value;
  757. break;
  758. case 0x2F:
  759. //unknown2 = Value;
  760. break;
  761. case 0x62:
  762. m_dwBirth = Value;
  763. break;
  764. case 0x7D:
  765. m_dwAge = Value;
  766. break;
  767. case 0x81:
  768. //unknown3 = Value;
  769. break;
  770. case 0x8B:
  771. //unknown4 = Value;
  772. break;
  773. };
  774. Unlock();
  775. }
  776. void cCharInfo::UpdateSkill(DWORD Skill, DWORD Inc, DWORD Trained, DWORD XP, DWORD Bonus)
  777. {
  778. Lock();
  779. m_mSkill[Skill].dwInc = Inc;
  780. m_mSkill[Skill].dwTrained = (eTrainingType) Trained;
  781. if (m_mSkill[Skill].dwTrained == eTrainUntrained)
  782. m_mSkill[Skill].dwTrained = m_mSkill[Skill].bUsableUntrained ? eTrainUntrained : eTrainUnusable;
  783. m_mSkill[Skill].dwXP = XP;
  784. m_mSkill[Skill].dwBonus = Bonus;
  785. Unlock();
  786. }
  787. void cCharInfo::UpdateSkillTrain(DWORD Skill, DWORD Trained)
  788. {
  789. Lock();
  790. m_mSkill[Skill].dwTrained = (eTrainingType) Trained;
  791. if (m_mSkill[Skill].dwTrained == eTrainUntrained)
  792. m_mSkill[Skill].dwTrained = m_mSkill[Skill].bUsableUntrained ? eTrainUntrained : eTrainUnusable;
  793. Unlock();
  794. }
  795. void cCharInfo::UpdateAttribute(DWORD Attribute, DWORD Increment, DWORD Initial, DWORD XP)
  796. {
  797. Lock();
  798. m_mStat[Attribute].dwInc = Increment;
  799. m_mStat[Attribute].dwInitial = Initial;
  800. m_mStat[Attribute].dwXP = XP;
  801. Unlock();
  802. }
  803. void cCharInfo::UpdateSecondaryAttribute(DWORD Attribute, DWORD Increment, DWORD XP)
  804. {
  805. Lock();
  806. m_mSecStat[Attribute].dwInc = Increment;
  807. m_mSecStat[Attribute].dwXP = XP;
  808. Unlock();
  809. }
  810. void cCharInfo::UpdateVital(DWORD Vital, DWORD Value)
  811. {
  812. Lock();
  813. m_mSecStat[Vital].dwCurrent = Value;
  814. Unlock();
  815. }
  816. void cCharInfo::AddSpellToBook(DWORD Spell)
  817. {
  818. Lock();
  819. m_lSpellbook.insert(Spell);
  820. Unlock();
  821. }
  822. void cCharInfo::RemoveSpellFromBook(DWORD Spell)
  823. {
  824. Lock();
  825. m_lSpellbook.erase(Spell);
  826. Unlock();
  827. }
  828. void cCharInfo::AddEnchantment(cEnchantment *Enchantment)
  829. {
  830. Lock();
  831. if (Enchantment->wSpellID == 666)
  832. {
  833. //vitae
  834. m_fVitae = Enchantment->fAdjustment;
  835. }
  836. m_lEnchantments.push_back(Enchantment);
  837. //(copied from charstats)
  838. Enchantment->dwExpireTime = (DWORD) time(NULL);
  839. // duration of the spell plus the (negative) number the server sends us indicating how many seconds have elapsed
  840. Enchantment->dwExpireTime += (long(Enchantment->dDuration + 0.5f) + long(Enchantment->dTimeElapsed + 0.5f));
  841. switch (Enchantment->dwAffectMask & 0x13)
  842. {
  843. case 0x01: //Primary Stat
  844. {
  845. RecalcStat(Enchantment->dwAffected);
  846. RecalcSecStats();
  847. RecalcSkills();
  848. }
  849. break;
  850. case 0x02: //Secondary Stat
  851. {
  852. RecalcSecStat(Enchantment->dwAffected);
  853. }
  854. break;
  855. case 0x10: //Skill
  856. {
  857. RecalcSkill(Enchantment->dwAffected);
  858. }
  859. break;
  860. }
  861. Unlock();
  862. }
  863. void cCharInfo::RemoveEnchantment(WORD spell, WORD layer)
  864. {
  865. Lock();
  866. for (std::list<cEnchantment *>::iterator i = m_lEnchantments.begin(); i != m_lEnchantments.end(); i++)
  867. {
  868. if (((*i)->wSpellID == spell) && ((*i)->wLayer == layer))
  869. {
  870. DWORD AffectMask = (*i)->dwAffectMask, Affected = (*i)->dwAffected;
  871. delete *i;
  872. m_lEnchantments.erase(i);
  873. Unlock();
  874. if ((AffectMask & 0x013) == 0x01)
  875. {
  876. RecalcStat(Affected);
  877. RecalcSecStats();
  878. RecalcSkills();
  879. }
  880. else if ((AffectMask & 0x013) == 0x02)
  881. {
  882. RecalcSecStats();
  883. }
  884. else if ((AffectMask & 0x013) == 0x10)
  885. {
  886. RecalcSkill(Affected);
  887. }
  888. return;
  889. }
  890. }
  891. Unlock();
  892. }
  893. void cCharInfo::RemoveAllEnchantments()
  894. {
  895. Lock();
  896. for (std::list<cEnchantment *>::iterator i = m_lEnchantments.begin(); i != m_lEnchantments.end(); i++)
  897. delete *i;
  898. m_lEnchantments.clear();
  899. Unlock();
  900. RecalcStats();
  901. RecalcSecStats();
  902. RecalcSkills();
  903. }
  904. void cCharInfo::RecalcStats()
  905. {
  906. for (int i=1;i<=6;i++)
  907. RecalcStat(i);
  908. }
  909. void cCharInfo::RecalcStat(int Stat)
  910. {
  911. Lock();
  912. std::map<DWORD, float> FamilyMap;
  913. for (std::list< cEnchantment * >::iterator tpi = m_lEnchantments.begin(); tpi != m_lEnchantments.end(); tpi++)
  914. {
  915. if ((((*tpi)->dwAffectMask & 0x13) == 0x01) && ((*tpi)->dwAffected == Stat))
  916. {
  917. if (abs(FamilyMap[(*tpi)->dwFamily]) <= abs((*tpi)->fAdjustment))
  918. FamilyMap[(*tpi)->dwFamily] = (*tpi)->fAdjustment;
  919. }
  920. }
  921. //Calc Base
  922. m_mStat[Stat].dwBase = m_mStat[Stat].dwInitial + m_mStat[Stat].dwInc;
  923. //Calc Buffed
  924. float tpsf = (float) m_mStat[Stat].dwBase;
  925. for (std::map<DWORD, float>::iterator tpf = FamilyMap.begin(); tpf != FamilyMap.end(); tpf++)
  926. tpsf += (*tpf).second;
  927. m_mStat[Stat].dwBuffed = static_cast <DWORD> (tpsf);
  928. Unlock();
  929. }
  930. void cCharInfo::RecalcSecStats()
  931. {
  932. for (int i=2;i<=6;i+=2)
  933. RecalcSecStat(i);
  934. }
  935. void cCharInfo::RecalcSecStat(int SecStat)
  936. {
  937. Lock();
  938. std::map<DWORD, float> FamilyMap;
  939. for (std::list< cEnchantment * >::iterator tpi = m_lEnchantments.begin(); tpi != m_lEnchantments.end(); tpi++)
  940. {
  941. if( (((*tpi)->dwAffectMask & 0x13) == 0x02) && ((*tpi)->dwAffected == SecStat) )
  942. {
  943. if (abs(FamilyMap[(*tpi)->dwFamily]) <= abs((*tpi)->fAdjustment))
  944. FamilyMap[(*tpi)->dwFamily] = (*tpi)->fAdjustment;
  945. }
  946. }
  947. //Calc Base
  948. m_mSecStat[SecStat].dwBase = (DWORD) ceilf((float) m_mSecStat[SecStat].dwInc + (float) m_mStat[m_mSecStat[SecStat].dwAttrib].dwBase/(float) m_mSecStat[SecStat].dwAttribDivisor);
  949. //Calc Buffed
  950. float tpsf = (float) m_mSecStat[SecStat].dwInc;
  951. tpsf += (float) m_mStat[m_mSecStat[SecStat].dwAttrib].dwBuffed/(float) m_mSecStat[SecStat].dwAttribDivisor;
  952. for (std::map<DWORD, float>::iterator tpf = FamilyMap.begin(); tpf != FamilyMap.end(); tpf++)
  953. tpsf += (*tpf).second;
  954. m_mSecStat[SecStat].dwBuffed = (DWORD) ceilf(tpsf); //static_cast <DWORD> (tpsf);
  955. Unlock();
  956. }
  957. void cCharInfo::RecalcSkills()
  958. {
  959. for (int i=0;i<MAX_SKILLS;i++)
  960. {
  961. if (GetSkillValid(i))
  962. RecalcSkill(i);
  963. }
  964. }
  965. void cCharInfo::RecalcSkill(int Skill)
  966. {
  967. Lock();
  968. std::map<DWORD, float> FamilyMap;
  969. for (std::list<cEnchantment *>::iterator tpi = m_lEnchantments.begin(); tpi != m_lEnchantments.end(); tpi++)
  970. {
  971. if ((((*tpi)->dwAffectMask & 0x13) == 0x10) && ((*tpi)->dwAffected == Skill))
  972. {
  973. if (abs(FamilyMap[(*tpi)->dwFamily]) <= abs((*tpi)->fAdjustment))
  974. FamilyMap[(*tpi)->dwFamily] = (*tpi)->fAdjustment;
  975. }
  976. }
  977. //Calc Base
  978. float TPS = 0;
  979. if (m_mSkill[Skill].dwTrained != eTrainUnusable)
  980. {
  981. if (m_mSkill[Skill].dwAttrib1 != eAttrNULL)
  982. TPS += m_mStat[m_mSkill[Skill].dwAttrib1].dwBase;
  983. if (m_mSkill[Skill].dwAttrib2 != eAttrNULL)
  984. TPS += m_mStat[m_mSkill[Skill].dwAttrib2].dwBase;
  985. TPS /= (float) m_mSkill[Skill].dwAttribDivisor;
  986. TPS += m_mSkill[Skill].dwInc + m_mSkill[Skill].dwBonus/* + 0.5f*/;
  987. }
  988. m_mSkill[Skill].dwBase = (DWORD) ceilf(TPS);
  989. //Calc Buffed
  990. TPS = 0;
  991. if (m_mSkill[Skill].dwTrained != eTrainUnusable)
  992. {
  993. if (m_mSkill[Skill].dwAttrib1 != eAttrNULL)
  994. TPS += m_mStat[m_mSkill[Skill].dwAttrib1].dwBuffed;
  995. if (m_mSkill[Skill].dwAttrib2 != eAttrNULL)
  996. TPS += m_mStat[m_mSkill[Skill].dwAttrib2].dwBuffed;
  997. TPS /= (float) m_mSkill[Skill].dwAttribDivisor;
  998. TPS += m_mSkill[Skill].dwInc + m_mSkill[Skill].dwBonus/* + 0.5f*/;
  999. }
  1000. for (std::map<DWORD, float>::iterator tpf = FamilyMap.begin(); tpf != FamilyMap.end(); tpf++)
  1001. TPS += (*tpf).second;
  1002. m_mSkill[Skill].dwBuffed = (DWORD) ceilf(TPS); //static_cast <DWORD> (TPS);
  1003. Unlock();
  1004. }
  1005. void cCharInfo::AddCorpse(stLocation Loc)
  1006. {
  1007. Lock();
  1008. m_lCorpses.push_back(Loc);
  1009. Unlock();
  1010. }
  1011. float cCharInfo::GetVitae()
  1012. {
  1013. Lock();
  1014. float toret = m_fVitae;
  1015. Unlock();
  1016. return toret;
  1017. }
  1018. std::list<DWORD> * cCharInfo::GetSpellBar(int iBar)
  1019. {
  1020. return &m_lSpellBar[iBar];
  1021. /* if (m_lSpellBar[iBar].begin() == m_lSpellBar[iBar].end())
  1022. return 0;
  1023. else
  1024. return m_lSpellBar[iBar].begin();*/
  1025. }
  1026. int cCharInfo::GetSpellBarCount(int iBar)
  1027. {
  1028. return (int) m_lSpellBar[iBar].size();
  1029. }
  1030. stInternalSpell * cCharInfo::GetSpellInfo(DWORD SpellID)
  1031. {
  1032. return &m_mSpell[SpellID];
  1033. }
  1034. DWORD cCharInfo::GetMaxSkill()
  1035. {
  1036. return m_dwMaxSkill;
  1037. }
  1038. int cCharInfo::GetSkillCount()
  1039. {
  1040. return (int) m_mSkill.size();
  1041. }
  1042. bool cCharInfo::GetSkillValid(DWORD dwSkill)
  1043. {
  1044. return (m_mSkill.find(dwSkill) != m_mSkill.end());
  1045. }
  1046. stInternalSkill * cCharInfo::GetSkillInfo(DWORD dwSkill)
  1047. {
  1048. return &m_mSkill[dwSkill];
  1049. }
  1050. stStatInfo * cCharInfo::GetStat(DWORD dwStat)
  1051. {
  1052. return &m_mStat[dwStat];
  1053. }
  1054. stSecStatInfo * cCharInfo::GetSecStat(DWORD dwSecStat)
  1055. {
  1056. return &m_mSecStat[dwSecStat];
  1057. }