Clone of UAS2 @ https://github.com/drudgedance/uas2

DatFile.cpp 45KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. /*
  2. * This file is part of UAS2.
  3. *
  4. * UAS2 is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * UAS2 is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. * You should have received a copy of the GNU General Public License
  14. * along with UASv1; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /**
  18. * @file DatFile.cpp
  19. * Handles the general operations relating to the database.
  20. *
  21. * Includes the functionality to create accounts, create, delete, and load avatars,
  22. * and to initalize the Global Unique Identifier (GUID) values.
  23. */
  24. #include "Avatar.h"
  25. #include "DatFile.h"
  26. /**
  27. * Navigates the Character Creation Information (0x0E000002) file in the
  28. * portal.dat. This file contains the starting locations, race- and
  29. * gender-specific clothing and color selections, and the male and female
  30. * palette, texture, and model information. This model information includes
  31. * the female/male models, skin shade, hair color, hair shade, hair style,
  32. * eye color, forehead style, chin style, and nose style.
  33. *
  34. * @param *pcAvatar - A pointer to the avatar whose information should be loaded or updated.
  35. *
  36. * Author: eLeM
  37. */
  38. void cPortalDat::LoadStartingInfo( cAvatar *pcAvatar )
  39. {
  40. DWORD dwRace = pcAvatar->m_wRace;
  41. DWORD dwSex = pcAvatar->m_wGender;
  42. WORD wClass = pcAvatar->m_wClass;
  43. double dblSkinShade = pcAvatar->m_dblSkinShade;
  44. DWORD dwHairColor = pcAvatar->m_wHairColor;
  45. double dblHairShade = pcAvatar->m_dblHairShade;
  46. DWORD dwHairStyle = pcAvatar->m_wHairStyle;
  47. DWORD dwEyeColor = pcAvatar->m_wEyeColor;
  48. DWORD dwForeheadTexture = pcAvatar->m_wHead;
  49. DWORD dwNoseTexture = pcAvatar->m_wNose;
  50. DWORD dwChinTexture = pcAvatar->m_wChin;
  51. /* Inputs */
  52. //dwRace - Determines the proper race to reference
  53. //dwSex - Determines the proper gender to reference
  54. //dwClass - Determines the proper class/profession to reference
  55. //dblSkinShade - Determines the palette selected from the skin palette list
  56. //dwHairColor - Determines the palette list selected from the list of hair color palette lists
  57. //dblHairShade - Determines the palette selected from the selected hair color palette list
  58. //dwHairStyle - Determines the texture selected from the list of hair style textures
  59. //dwEyeColor - Determines the palette selected from the list of eye color palettes
  60. //dwForeheadTexture - Determines the textures selected from the list of forehead textures
  61. //dwNoseTexture - Determines the texture selected from the list of nose textures
  62. //dwChinTexture - Determines the texture selected from the list of chin textures
  63. //Model variables
  64. //Used to populate any character palette, texture, and model information fetched by the function
  65. pcAvatar->m_wBasicPaletteVector = 0;
  66. pcAvatar->m_wBasicTextureVector = 0;
  67. pcAvatar->m_wBasicModelVector = 0;
  68. char portalFile[9];
  69. sprintf(portalFile,"%08x",0x0E000002 ); //Character Creation Objects
  70. //* Character Creation Objects (0x0E000002) Algorithm *//
  71. //This algorithm fetches starting character information from the portal.dat,
  72. //The data can be used to populate the character-based palette, texture, and model informtion.
  73. // char szData[255];
  74. UCHAR *buf;
  75. //DWORD fileNum;
  76. DWORD startingRegionsCount;
  77. //Load data from the portal.dat file
  78. cPortalDat::Load_PortalDat(buf, portalFile);
  79. int readIndex = 0;
  80. //memcpy(&fileNum,buf,4);
  81. readIndex += 4; //the first 4 bytes list the index for which we searched
  82. readIndex += 4*8; //Eight UI Text DWORDs
  83. memcpy(&startingRegionsCount,buf + readIndex,4); readIndex += 4;
  84. for (int xIndex = 0; xIndex < startingRegionsCount; ++xIndex)
  85. {
  86. WORD regionNameLength;
  87. char szRegionName[40];
  88. DWORD locationCount;
  89. memcpy(&regionNameLength,buf + readIndex,2); readIndex += 2;
  90. memcpy(&szRegionName,buf + readIndex,regionNameLength); readIndex += regionNameLength;
  91. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  92. memcpy(&locationCount,buf + readIndex,4); readIndex += 4;
  93. for (int yIndex = 0; yIndex < locationCount; yIndex++)
  94. {
  95. // DWORD landblock;
  96. // DWORD positionX, positionY, positionZ;
  97. // DWORD oritentationW,oritentationX,oritentationY,oritentationZ;
  98. readIndex += 4*8; //region landblock,x,y,z,w,x,y,z information
  99. }
  100. }
  101. DWORD raceCount;
  102. memcpy(&raceCount,buf + readIndex,4); readIndex += 4;
  103. for (int rIndex = 0; rIndex < raceCount; rIndex++)
  104. {
  105. WORD raceNameLength;
  106. char szRaceName[40];
  107. // DWORD raceUIGraphic
  108. // DWORD raceUIText;
  109. DWORD genderCount;
  110. memcpy(&raceNameLength,buf + readIndex,2); readIndex += 2;
  111. memcpy(&szRaceName,buf + readIndex,raceNameLength); readIndex += raceNameLength;
  112. //Determine if this is the avatar's race
  113. if (rIndex == dwRace)
  114. {
  115. memcpy(pcAvatar->m_strRaceName,szRaceName,raceNameLength);
  116. pcAvatar->m_strRaceName[raceNameLength] = '\0';
  117. }
  118. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  119. readIndex += 4; //raceUIGraphic
  120. readIndex += 4; //unknown
  121. readIndex += 4; //raceUIText
  122. readIndex += 4; //unknown
  123. readIndex += 4*8; //Eight unknown DWORDs
  124. memcpy(&genderCount,buf + readIndex,4); readIndex += 4;
  125. for (int gIndex = 0; gIndex < genderCount; gIndex++)
  126. {
  127. WORD genderNameLength;
  128. char szGenderName[40];
  129. DWORD genderModel;
  130. BYTE hPaletteCount,hTextureCount,hModelCount;
  131. DWORD unknownCount;
  132. DWORD namePrefixCount;
  133. DWORD classCount;
  134. DWORD unknown1;
  135. memcpy(&genderNameLength,buf + readIndex,2); readIndex += 2;
  136. memcpy(&szGenderName,buf + readIndex,genderNameLength); readIndex += genderNameLength;
  137. //Determine if this is the avatar's gender
  138. if (rIndex == dwRace && gIndex == dwSex)
  139. {
  140. memcpy(pcAvatar->m_strSexName,szGenderName,genderNameLength);
  141. pcAvatar->m_strSexName[genderNameLength] = '\0';
  142. }
  143. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  144. memcpy(&genderModel,buf + readIndex,4); readIndex += 4;
  145. /*
  146. sprintf(szData,"%04x\r\n",genderModel);
  147. UpdateConsole(szData);
  148. */
  149. readIndex += 4*3; //Three unknown DWORDs
  150. readIndex += 1; //BYTE 11
  151. memcpy(&hPaletteCount,buf + readIndex,1); readIndex += 1; //Palette Count
  152. memcpy(&hTextureCount,buf + readIndex,1); readIndex += 1; //Texture Count
  153. memcpy(&hModelCount,buf + readIndex,1); readIndex += 1; //Model Count
  154. for (int pIndex = 0; pIndex < hPaletteCount; ++pIndex) //Palettes
  155. {
  156. WORD newPalette;
  157. BYTE palOffset;
  158. UCHAR palLength;
  159. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  160. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  161. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  162. if (rIndex == dwRace && gIndex == dwSex)
  163. {
  164. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  165. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  166. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  167. pcAvatar->m_wBasicPaletteVector++;
  168. }
  169. }
  170. for (int tIndex = 0; tIndex < hTextureCount; ++tIndex) //Textures
  171. {
  172. BYTE modelIndex;
  173. WORD textureMask;
  174. WORD texture;
  175. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  176. memcpy(&textureMask,buf+readIndex,2); readIndex += 2;
  177. memcpy(&texture,buf+readIndex,2); readIndex += 2;
  178. if (rIndex == dwRace && gIndex == dwSex)
  179. {
  180. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_bModelIndex = BYTE(modelIndex);
  181. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wOldTexture = WORD(textureMask);
  182. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wNewTexture = WORD(texture);
  183. pcAvatar->m_wBasicTextureVector++;
  184. }
  185. }
  186. for (int mIndex = 0; mIndex < hModelCount; ++mIndex) //Models
  187. {
  188. BYTE modelIndex;
  189. WORD model;
  190. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  191. memcpy(&model,buf+readIndex,2); readIndex += 2;
  192. if (rIndex == dwRace && gIndex == dwSex)
  193. {
  194. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_bModelIndex = BYTE(modelIndex);
  195. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_wNewModel = WORD(model);
  196. pcAvatar->m_wBasicModelVector++;
  197. }
  198. }
  199. if (hTextureCount > 0 && hModelCount == 0)
  200. readIndex += 3; //Every texture has corresponding model information
  201. readIndex += 1; //BYTE -- constant zero
  202. readIndex += 4*2; //Two unknown DWORDs
  203. memcpy(&namePrefixCount,buf + readIndex,4); readIndex += 4;
  204. //Loop through name prefixes (i.e., Gharu'ndim "-al" and "ibn")
  205. for (int zIndex = 0; zIndex < namePrefixCount; ++zIndex)
  206. {
  207. WORD namePrefixLength;
  208. char szNamePrefix[40];
  209. memcpy(&namePrefixLength,buf + readIndex,2); readIndex += 2;
  210. memcpy(&szNamePrefix,buf + readIndex,namePrefixLength); readIndex += namePrefixLength;
  211. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  212. }
  213. readIndex += 4*5; //Five unknown DWORDs
  214. memcpy(&unknownCount,buf + readIndex,4); readIndex += 4;
  215. for (zIndex = 0; zIndex < unknownCount; ++zIndex)
  216. {
  217. readIndex += 4*3; //Three unknown DWORDs
  218. }
  219. memcpy(&classCount,buf + readIndex,4); readIndex += 4;
  220. /*
  221. sprintf(szData,"%04x\r\n",classCount);
  222. UpdateConsole(szData);
  223. */
  224. for (int cIndex = 0; cIndex < classCount; ++cIndex)
  225. {
  226. WORD classNameLength;
  227. char szClassName[40];
  228. DWORD classUIGraphic;
  229. DWORD classUIText;
  230. DWORD valueUnknown1;
  231. DWORD valueStrength;
  232. DWORD valueEndurance;
  233. DWORD valueCoordination;
  234. DWORD valueQuickness;
  235. DWORD valueFocus;
  236. DWORD valueSelf;
  237. DWORD countTrain;
  238. DWORD countSpecialize;
  239. DWORD countUnknown;
  240. DWORD skillNum;
  241. memcpy(&classNameLength,buf + readIndex,2); readIndex += 2;
  242. memcpy(&szClassName,buf + readIndex,classNameLength); readIndex += classNameLength;
  243. //Determine if this is the avatar's class
  244. if (rIndex == dwRace && gIndex == dwSex)
  245. {
  246. if (cIndex == wClass)
  247. {
  248. memcpy(pcAvatar->m_strClassName,szClassName,classNameLength);
  249. pcAvatar->m_strClassName[classNameLength] = '\0';
  250. }
  251. }
  252. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  253. memcpy(&classUIGraphic,buf + readIndex,4); readIndex += 4;
  254. memcpy(&classUIText,buf + readIndex,4); readIndex += 4;
  255. memcpy(&valueUnknown1,buf + readIndex,4); readIndex += 4;
  256. memcpy(&valueStrength,buf + readIndex,4); readIndex += 4;
  257. memcpy(&valueEndurance,buf + readIndex,4); readIndex += 4;
  258. memcpy(&valueCoordination,buf + readIndex,4); readIndex += 4;
  259. memcpy(&valueQuickness,buf + readIndex,4); readIndex += 4;
  260. memcpy(&valueFocus,buf + readIndex,4); readIndex += 4;
  261. memcpy(&valueSelf,buf + readIndex,4); readIndex += 4;
  262. memcpy(&countTrain,buf + readIndex,4); readIndex += 4;
  263. for (int skillTIndex = 0; skillTIndex < countTrain; ++skillTIndex)
  264. {
  265. memcpy(&skillNum,buf + readIndex,4); readIndex += 4;
  266. }
  267. memcpy(&countSpecialize,buf + readIndex,4);readIndex += 4;
  268. for (int skillSIndex = 0; skillSIndex < countSpecialize; ++skillSIndex)
  269. {
  270. memcpy(&skillNum,buf + readIndex,4); readIndex += 4;
  271. }
  272. memcpy(&countUnknown,buf + readIndex,4); readIndex += 4;
  273. }
  274. memcpy(&unknown1,buf + readIndex,4); readIndex += 4; //Unknown DWORD
  275. DWORD humanPalette;
  276. DWORD skinPaletteList;
  277. DWORD hairColorPaletteListCount;
  278. DWORD hairColorPaletteList;
  279. DWORD hairStyleCount;
  280. DWORD eyeColorPaletteCount;
  281. DWORD foreheadTextureCount;
  282. DWORD noseTextureCount;
  283. DWORD chinTextureCount;
  284. // DWORD paletteFileNum;
  285. DWORD paletteCount;
  286. int palReadIndex;
  287. char szPalFile[9];
  288. UCHAR *palBuf;
  289. int intPalette;
  290. memcpy(&humanPalette,buf + readIndex,4); readIndex += 4; //Human palette (0x0400007E)
  291. /* Determine skin color information */
  292. //Each skin color has a single CLUT list associated with it
  293. //If a palette from the list is used, the palette is determined via the dblSkinShade input value
  294. memcpy(&skinPaletteList,buf + readIndex,4); readIndex += 4; //Skin CLUT List (0x0F000000 value)
  295. /*
  296. sprintf(szData,"Palette ID: %08x\r\n",skinPaletteList);
  297. UpdateConsole(szData);
  298. */
  299. sprintf(szPalFile,"%08x",skinPaletteList);
  300. //Load palette data from the portal.dat file
  301. cPortalDat::Load_PortalDat(palBuf, szPalFile);
  302. palReadIndex = 0;
  303. palReadIndex += 4; //the first 4 bytes list the index for which we searched
  304. memcpy(&paletteCount,palBuf+palReadIndex,4);
  305. palReadIndex += 4;
  306. /*
  307. sprintf(szData,"Palette Count: %08x\r\n",paletteCount);
  308. UpdateConsole(szData);
  309. */
  310. //Calculate the palette to be used
  311. intPalette = CalcPalette(paletteCount,dblSkinShade);
  312. //Loop through the specific palettes (0x04000000 values)
  313. for (zIndex = 0; zIndex < paletteCount; ++zIndex)
  314. {
  315. DWORD palette;
  316. memcpy(&palette,palBuf+palReadIndex,4);
  317. palReadIndex += 4;
  318. /*
  319. sprintf(szData,"Palette: %08x\r\n",palette);
  320. UpdateConsole(szData);
  321. */
  322. if (zIndex == intPalette)
  323. {
  324. if (rIndex == dwRace && gIndex == dwSex)
  325. {
  326. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(palette | 0x04000000);
  327. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(0x00);
  328. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(0x18);
  329. pcAvatar->m_wBasicPaletteVector++;
  330. }
  331. }
  332. }
  333. free(palBuf);
  334. /* Determine hair color information */
  335. //Each hair color has a list of palette lists associated with it
  336. //If a palette list is used, the list is determined via the dwHairStyle input value
  337. //The palette choosen from the palette list is determined via the dblHairShade input value
  338. memcpy(&hairColorPaletteListCount,buf + readIndex,4); readIndex += 4;
  339. for (int wIndex = 0; wIndex < hairColorPaletteListCount; ++wIndex)
  340. {
  341. memcpy(&hairColorPaletteList,buf + readIndex,4); readIndex += 4; //Hair color CLUT List (0x0F000000 value)
  342. /*
  343. sprintf(szData,"Palette ID: %08x\r\n",hairColorPaletteList);
  344. UpdateConsole(szData);
  345. */
  346. if (wIndex == dwHairColor)
  347. {
  348. sprintf(szPalFile,"%08x",hairColorPaletteList);
  349. //Load palette data from the portal.dat file
  350. cPortalDat::Load_PortalDat(palBuf, szPalFile);
  351. palReadIndex = 0;
  352. palReadIndex += 4; //the first 4 bytes list the index for which we searched
  353. memcpy(&paletteCount,palBuf+palReadIndex,4);
  354. palReadIndex += 4;
  355. /*
  356. sprintf(szData,"Palette Count: %08x\r\n",paletteCount);
  357. UpdateConsole(szData);
  358. */
  359. //Calculate the palette to be used
  360. intPalette = CalcPalette(paletteCount,dblHairShade);
  361. //Loop through the specific palettes (0x04000000 values)
  362. for (zIndex = 0; zIndex < paletteCount; ++zIndex)
  363. {
  364. DWORD palette;
  365. memcpy(&palette,palBuf+palReadIndex,4);
  366. palReadIndex += 4;
  367. /*
  368. sprintf(szData,"Palette: %08x\r\n",palette);
  369. UpdateConsole(szData);
  370. */
  371. if (zIndex == intPalette)
  372. {
  373. if (rIndex == dwRace && gIndex == dwSex)
  374. {
  375. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(palette | 0x04000000);
  376. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(0x18);
  377. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(0x08);
  378. pcAvatar->m_wBasicPaletteVector++;
  379. }
  380. }
  381. }
  382. free(palBuf);
  383. }
  384. }
  385. /* Determine hair style information */
  386. //Each hair style has a single texture associated with it and zeroed model information
  387. //Each hair style also has a UI Graphic associated with it
  388. //If a hair style is used, the style is determined by the dwHairStyle input value
  389. memcpy(&hairStyleCount,buf + readIndex,4); readIndex += 4; //Hair style count
  390. //Loop through the hair styles
  391. for (int hairIndex = 0; hairIndex < hairStyleCount; ++hairIndex)
  392. {
  393. DWORD hairStyleUIGraphic;
  394. memcpy(&hairStyleUIGraphic,buf+readIndex,4);readIndex += 4;
  395. readIndex += 4; //Unknown DWORD -- 0x00000000
  396. readIndex += 1; //BYTE 11
  397. memcpy(&hPaletteCount,buf + readIndex,1); readIndex += 1; //Palette Count
  398. memcpy(&hTextureCount,buf + readIndex,1); readIndex += 1; //Texture Count
  399. memcpy(&hModelCount,buf + readIndex,1); readIndex += 1; //Model Count
  400. //Loop through the hair style palette/texture/model information
  401. for (int pIndex = 0; pIndex < hPaletteCount; ++pIndex) //Palettes
  402. {
  403. WORD newPalette;
  404. BYTE palOffset;
  405. BYTE palLength;
  406. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  407. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  408. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  409. if (hairIndex == dwHairStyle)
  410. {
  411. if (rIndex == dwRace && gIndex == dwSex)
  412. {
  413. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  414. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  415. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  416. pcAvatar->m_wBasicPaletteVector++;
  417. }
  418. }
  419. }
  420. for (int tIndex = 0; tIndex < hTextureCount; ++tIndex) //Textures
  421. {
  422. BYTE modelIndex;
  423. WORD textureMask;
  424. WORD texture;
  425. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  426. memcpy(&textureMask,buf+readIndex,2); readIndex += 2;
  427. memcpy(&texture,buf+readIndex,2); readIndex += 2;
  428. if (hairIndex == dwHairStyle)
  429. {
  430. if (rIndex == dwRace && gIndex == dwSex)
  431. {
  432. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_bModelIndex = BYTE(modelIndex);
  433. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wOldTexture = WORD(textureMask);
  434. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wNewTexture = WORD(texture);
  435. pcAvatar->m_wBasicTextureVector++;
  436. }
  437. }
  438. }
  439. for (int mIndex = 0; mIndex < hModelCount; ++mIndex) //Models
  440. {
  441. BYTE modelIndex;
  442. WORD model;
  443. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  444. memcpy(&model,buf+readIndex,2); readIndex += 2;
  445. if (hairIndex == dwHairStyle)
  446. {
  447. if (rIndex == dwRace && gIndex == dwSex)
  448. {
  449. for (int index = 0; index < pcAvatar->m_wBasicModelVector; ++index)
  450. {
  451. if (pcAvatar->m_BasicVectorMod[modelIndex].m_bModelIndex == modelIndex)
  452. {
  453. pcAvatar->m_BasicVectorMod[modelIndex].m_wNewModel = WORD(model);
  454. }
  455. }
  456. }
  457. }
  458. }
  459. if (hTextureCount > 0 && hModelCount == 0)
  460. readIndex += 3; //Every texture has corresponding model information (even if unused)
  461. }
  462. /* Determine eye color palette */
  463. //Each eye color has a single palette associated with it
  464. //If an eye color is used, the style is determined by the dwEyeColor input value
  465. memcpy(&eyeColorPaletteCount,buf + readIndex,4); readIndex += 4;
  466. for (int eyeIndex = 0; eyeIndex < eyeColorPaletteCount; ++eyeIndex)
  467. {
  468. WORD newPalette;
  469. BYTE palOffset;
  470. BYTE palLength;
  471. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  472. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  473. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  474. if (eyeIndex == dwEyeColor)
  475. {
  476. if (rIndex == dwRace && gIndex == dwSex)
  477. {
  478. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  479. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  480. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  481. pcAvatar->m_wBasicPaletteVector++;
  482. }
  483. }
  484. }
  485. /* Determine forehead information */
  486. //Each forehead style has two textures associated with it and zeroed model information
  487. //Only one texture is used: the first is for non-bald characters; the second is for bald characters
  488. //If a forehead style is used, the style is determined by the dwForeheadTexture input value
  489. memcpy(&foreheadTextureCount,buf + readIndex,4); readIndex += 4; //Forehead style count
  490. //Loop through the forehead styles
  491. for (int foreheadIndex = 0; foreheadIndex < foreheadTextureCount; ++foreheadIndex)
  492. {
  493. DWORD unknownUIGraphic;
  494. memcpy(&unknownUIGraphic,buf+readIndex,4); readIndex += 4;
  495. readIndex += 4; //Unknown DWORD -- 0x00000000
  496. //Forehead styles consist of two sets of palette/texture/model information
  497. for (int i = 0; i < 2; ++i)
  498. {
  499. readIndex += 1; //BYTE 11
  500. memcpy(&hPaletteCount,buf + readIndex,1); readIndex += 1; //Palette Count
  501. memcpy(&hTextureCount,buf + readIndex,1); readIndex += 1; //Texture Count
  502. memcpy(&hModelCount,buf + readIndex,1); readIndex += 1; //Model Count
  503. //Loop through the forehead style palette/texture/model information
  504. for (int pIndex = 0; pIndex < hPaletteCount; ++pIndex) //Palettes
  505. {
  506. WORD newPalette;
  507. BYTE palOffset;
  508. BYTE palLength;
  509. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  510. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  511. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  512. if (foreheadIndex == dwForeheadTexture)
  513. {
  514. if (rIndex == dwRace && gIndex == dwSex)
  515. {
  516. if (i == 0 && dwHairStyle != 3 || i == 1 && dwHairStyle == 3)
  517. {
  518. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  519. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  520. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  521. pcAvatar->m_wBasicPaletteVector++;
  522. }
  523. }
  524. }
  525. }
  526. for (int tIndex = 0; tIndex < hTextureCount; ++tIndex) //Textures
  527. {
  528. BYTE modelIndex;
  529. WORD textureMask;
  530. WORD texture;
  531. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  532. memcpy(&textureMask,buf+readIndex,2); readIndex += 2;
  533. memcpy(&texture,buf+readIndex,2); readIndex += 2;
  534. if (foreheadIndex == dwForeheadTexture)
  535. {
  536. if (rIndex == dwRace && gIndex == dwSex)
  537. {
  538. if (i == 0 && dwHairStyle != 3 || i == 1 && dwHairStyle == 3)
  539. {
  540. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_bModelIndex = BYTE(modelIndex);
  541. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wOldTexture = WORD(textureMask);
  542. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wNewTexture = WORD(texture);
  543. pcAvatar->m_wBasicTextureVector++;
  544. }
  545. }
  546. }
  547. }
  548. for (int mIndex = 0; mIndex < hModelCount; ++mIndex) //Models
  549. {
  550. BYTE modelIndex;
  551. WORD model;
  552. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  553. memcpy(&model,buf+readIndex,2); readIndex += 2;
  554. if (foreheadIndex == dwForeheadTexture)
  555. {
  556. if (rIndex == dwRace && gIndex == dwSex)
  557. {
  558. if (i == 0 && dwHairStyle != 3 || i == 1 && dwHairStyle == 3)
  559. {
  560. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_bModelIndex = modelIndex;
  561. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_wNewModel = model;
  562. pcAvatar->m_wBasicModelVector++;
  563. }
  564. }
  565. }
  566. }
  567. if (hTextureCount > 0 && hModelCount == 0)
  568. readIndex += 3; //Every texture has corresponding model information (even if unused)
  569. }
  570. }
  571. /* Determine nose information */
  572. //Each nose style has a single texture associated with it and zeroed model information
  573. //If a nose style is used, the style is determined by the dwNoseTexture input value
  574. memcpy(&noseTextureCount,buf + readIndex,4); readIndex += 4; //Nose style count
  575. //Loop through the nose styles
  576. for (int noseIndex = 0; noseIndex < noseTextureCount; ++noseIndex)
  577. {
  578. readIndex += 4; //Unknown DWORD -- 0x00000000
  579. readIndex += 1; //BYTE 11
  580. memcpy(&hPaletteCount,buf + readIndex,1); readIndex += 1; //Palette Count
  581. memcpy(&hTextureCount,buf + readIndex,1); readIndex += 1; //Texture Count
  582. memcpy(&hModelCount,buf + readIndex,1); readIndex += 1; //Model Count
  583. //Loop through the nose style palette/texture/model information
  584. for (int pIndex = 0; pIndex < hPaletteCount; ++pIndex) //Palettes
  585. {
  586. WORD newPalette;
  587. BYTE palOffset;
  588. BYTE palLength;
  589. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  590. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  591. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  592. if (noseIndex == dwNoseTexture)
  593. {
  594. if (rIndex == dwRace && gIndex == dwSex)
  595. {
  596. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  597. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  598. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  599. pcAvatar->m_wBasicPaletteVector++;
  600. }
  601. }
  602. }
  603. for (int tIndex = 0; tIndex < hTextureCount; ++tIndex) //Textures
  604. {
  605. BYTE modelIndex;
  606. WORD textureMask;
  607. WORD texture;
  608. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  609. memcpy(&textureMask,buf+readIndex,2); readIndex += 2;
  610. memcpy(&texture,buf+readIndex,2); readIndex += 2;
  611. if (noseIndex == dwNoseTexture)
  612. {
  613. if (rIndex == dwRace && gIndex == dwSex)
  614. {
  615. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_bModelIndex = BYTE(modelIndex);
  616. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wOldTexture = WORD(textureMask);
  617. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wNewTexture = WORD(texture);
  618. pcAvatar->m_wBasicTextureVector++;
  619. }
  620. }
  621. }
  622. for (int mIndex = 0; mIndex < hModelCount; ++mIndex) //Models
  623. {
  624. BYTE modelIndex;
  625. WORD model;
  626. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  627. memcpy(&model,buf+readIndex,2); readIndex += 2;
  628. if (noseIndex == dwNoseTexture)
  629. {
  630. if (rIndex == dwRace && gIndex == dwSex)
  631. {
  632. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_bModelIndex = modelIndex;
  633. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_wNewModel = model;
  634. pcAvatar->m_wBasicModelVector++;
  635. }
  636. }
  637. }
  638. if (hTextureCount > 0 && hModelCount == 0)
  639. readIndex += 3; //Every texture has corresponding model information (even if unused)
  640. }
  641. /* Determine chin information */
  642. //Each chin style has a single texture associated with it and zeroed model information
  643. //If a chin style is used, the style is determined by the dwChinTexture input value
  644. memcpy(&chinTextureCount,buf + readIndex,4); readIndex += 4; //Chin style count
  645. //Loop through the chin styles
  646. for (int chinIndex = 0; chinIndex < chinTextureCount; ++chinIndex)
  647. {
  648. readIndex += 4; //Unknown DWORD -- 0x00000000
  649. readIndex += 1; //BYTE 11
  650. memcpy(&hPaletteCount,buf + readIndex,1); readIndex += 1; //Palette Count
  651. memcpy(&hTextureCount,buf + readIndex,1); readIndex += 1; //Texture Count
  652. memcpy(&hModelCount,buf + readIndex,1); readIndex += 1; //Model Count
  653. //Loop through the chin style palette/texture/model information
  654. for (int pIndex = 0; pIndex < hPaletteCount; ++pIndex) //Palettes
  655. {
  656. WORD newPalette;
  657. BYTE palOffset;
  658. BYTE palLength;
  659. memcpy(&newPalette,buf+readIndex,2); readIndex += 2;
  660. memcpy(&palOffset,buf+readIndex,1); readIndex += 1;
  661. memcpy(&palLength,buf+readIndex,1); readIndex += 1;
  662. if (chinIndex == dwChinTexture)
  663. {
  664. if (rIndex == dwRace && gIndex == dwSex)
  665. {
  666. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_wNewPalette = WORD(newPalette);
  667. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucOffset = BYTE(palOffset);
  668. pcAvatar->m_BasicVectorPal[pcAvatar->m_wBasicPaletteVector].m_ucLength = BYTE(palLength);
  669. pcAvatar->m_wBasicPaletteVector++;
  670. }
  671. }
  672. }
  673. for (int tIndex = 0; tIndex < hTextureCount; ++tIndex) //Textures
  674. {
  675. BYTE modelIndex;
  676. WORD textureMask;
  677. WORD texture;
  678. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  679. memcpy(&textureMask,buf+readIndex,2); readIndex += 2;
  680. memcpy(&texture,buf+readIndex,2); readIndex += 2;
  681. if (chinIndex == dwChinTexture)
  682. {
  683. if (rIndex == dwRace && gIndex == dwSex)
  684. {
  685. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_bModelIndex = BYTE(modelIndex);
  686. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wOldTexture = WORD(textureMask);
  687. pcAvatar->m_BasicVectorTex[pcAvatar->m_wBasicTextureVector].m_wNewTexture = WORD(texture);
  688. pcAvatar->m_wBasicTextureVector++;
  689. }
  690. }
  691. }
  692. for (int mIndex = 0; mIndex < hModelCount; ++mIndex) //Models
  693. {
  694. BYTE modelIndex;
  695. WORD model;
  696. memcpy(&modelIndex,buf+readIndex,1); readIndex += 1;
  697. memcpy(&model,buf+readIndex,2); readIndex += 2;
  698. if (chinIndex == dwChinTexture)
  699. {
  700. if (rIndex == dwRace && gIndex == dwSex)
  701. {
  702. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_bModelIndex = modelIndex;
  703. pcAvatar->m_BasicVectorMod[pcAvatar->m_wBasicModelVector].m_wNewModel = model;
  704. pcAvatar->m_wBasicModelVector++;
  705. }
  706. }
  707. }
  708. if (hTextureCount > 0 && hModelCount == 0)
  709. readIndex += 3; //Every texture has corresponding model information (even if unused)
  710. }
  711. /* Apparel Items */
  712. //There are always four types of starting clothing (headgear, shirts, trousers, footwear)
  713. //Each type has a count of its respective number of items.
  714. //Each item has a name, reference to its Complex Model, and an unknown DWORD
  715. //Loop through the headgear
  716. DWORD headgearCount;
  717. DWORD shirtCount;
  718. DWORD trousersCount;
  719. DWORD footwearCount;
  720. memcpy(&headgearCount,buf + readIndex,4); readIndex += 4;
  721. for (int headgearIndex = 0; headgearIndex < headgearCount; ++headgearIndex)
  722. {
  723. WORD apparelNameLength;
  724. char apparelName[40];
  725. DWORD complexModelID;
  726. DWORD unknown1;
  727. memcpy(&apparelNameLength,buf + readIndex,2); readIndex += 2;
  728. memcpy(&apparelName,buf + readIndex,apparelNameLength); readIndex += apparelNameLength;
  729. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  730. memcpy(&complexModelID,buf + readIndex,4); readIndex += 4; //Complex Model (0x10000000 value)
  731. memcpy(&unknown1,buf + readIndex,4); readIndex += 4;
  732. }
  733. memcpy(&shirtCount,buf + readIndex,4); readIndex += 4;
  734. //Loop through the shirts
  735. for (int shirtIndex = 0; shirtIndex < shirtCount; ++shirtIndex)
  736. {
  737. WORD apparelNameLength;
  738. char apparelName[40];
  739. DWORD complexModelID;
  740. DWORD unknown1;
  741. memcpy(&apparelNameLength,buf + readIndex,2); readIndex += 2;
  742. memcpy(&apparelName,buf + readIndex,apparelNameLength); readIndex += apparelNameLength;
  743. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  744. memcpy(&complexModelID,buf + readIndex,4); readIndex += 4; //Complex Model (0x10000000 value)
  745. memcpy(&unknown1,buf + readIndex,4); readIndex += 4;
  746. }
  747. memcpy(&trousersCount,buf + readIndex,4); readIndex += 4;
  748. //Loop through the trousers
  749. for (int trousersIndex = 0; trousersIndex < trousersCount; ++trousersIndex)
  750. {
  751. WORD apparelNameLength;
  752. char apparelName[40];
  753. DWORD complexModelID;
  754. DWORD unknown1;
  755. memcpy(&apparelNameLength,buf + readIndex,2); readIndex += 2;
  756. memcpy(&apparelName,buf + readIndex,apparelNameLength); readIndex += apparelNameLength;
  757. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  758. memcpy(&complexModelID,buf + readIndex,4); readIndex += 4; //Complex Model (0x10000000 value)
  759. memcpy(&unknown1,buf + readIndex,4); readIndex += 4;
  760. }
  761. memcpy(&footwearCount,buf + readIndex,4); readIndex += 4;
  762. //Loop through the footwear
  763. for (int footwearIndex = 0; footwearIndex < footwearCount; ++footwearIndex)
  764. {
  765. WORD apparelNameLength;
  766. char apparelName[40];
  767. DWORD complexModelID;
  768. DWORD unknown1;
  769. memcpy(&apparelNameLength,buf + readIndex,2); readIndex += 2;
  770. memcpy(&apparelName,buf + readIndex,apparelNameLength); readIndex += apparelNameLength;
  771. while (readIndex % 4 != 0) { readIndex++; } //DWORD padding
  772. memcpy(&complexModelID,buf + readIndex,4); readIndex += 4; //Complex Model (0x10000000 value)
  773. memcpy(&unknown1,buf + readIndex,4); readIndex += 4;
  774. }
  775. DWORD apparelColorsCount;
  776. // DWORD apparelColorConstant;
  777. memcpy(&apparelColorsCount,buf + readIndex,4); readIndex += 4;
  778. readIndex +=4; //Unknown DWORD (0x0000000E)
  779. for (int colorIndex = 0; colorIndex < apparelColorsCount; ++colorIndex)
  780. {
  781. DWORD colorNum;
  782. memcpy(&colorNum,buf + readIndex,4); readIndex += 4;
  783. }
  784. }
  785. }
  786. free(buf);
  787. }
  788. /**
  789. * Handles the loading of item models (palette, texture, and model information).
  790. *
  791. * Called whenever an object's p/t/m information should be initialized or updated.
  792. *
  793. * @param *pcObject - A pointer to the object whose p/t/m information will be initialized or updated.
  794. * @param dwModelID - The item model to be used (world, male, female) for the object.
  795. * @param dwColorID - The color of the object.
  796. * @param dblColorValue - The color shade of the object.
  797. */
  798. void cPortalDat::LoadItemModel( cObject *pcObject, DWORD dwModelID, DWORD dwColorID, double dblColorValue )
  799. {
  800. cItemModels *pcModel = cItemModels::FindModel(( pcObject )->GetItemModelID());
  801. //pcModel - Item model instantiation; used to fetch item variables
  802. //dwModelID - 0x00000001 = male; 0x0000004E = female; other
  803. //dwColorID - color ID number; determines the CLUT list looked-up
  804. //dwColorValue - the particlar CLUT from the clut list
  805. if (!pcModel->m_clothingModelLoaded || dwColorID != NULL)
  806. {
  807. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  808. {
  809. pcModel->m_bWearPaletteChange = 0;
  810. pcModel->m_bWearTextureChange = 0;
  811. pcModel->m_bWearModelChange = 0;
  812. }
  813. char portalFile[9];
  814. sprintf(portalFile,"%08x",pcModel->m_PortalLinker);
  815. /* Complex Object (0x10000000) Algorithm */
  816. //This algorithm fetches item model data from the portal.dat,
  817. //The data can be used to populate the item-based palette, texture, and model informtion.
  818. // char szData[16];
  819. UCHAR *buf;
  820. //DWORD fileNum;
  821. WORD modelCount;
  822. WORD modelListUnknown;
  823. cPortalDat::Load_PortalDat(buf, portalFile);
  824. int readIndex = 0;
  825. //memcpy(&fileNum,buf,4);
  826. readIndex += 4; //the first 4 bytes list the index for which we searched
  827. memcpy(&modelCount,buf + readIndex,2);
  828. readIndex += 2;
  829. memcpy(&modelListUnknown,buf + readIndex,2);
  830. readIndex += 2;
  831. /*
  832. sprintf(szData,"%04x %d\r\n",modelCount,d);
  833. UpdateConsole(szData);
  834. sprintf(szData,"%04x\r\n",modelListUnknown);
  835. UpdateConsole(szData);
  836. */
  837. //Loop through the models types (as applicable: world model, male wearable model, female wearable model)
  838. for (int xIndex = 0; xIndex < modelCount; ++xIndex)
  839. {
  840. DWORD modelComplexID;
  841. DWORD modelAmount;
  842. // UpdateConsole("\r\n");
  843. memcpy(&modelComplexID,buf+readIndex,4);
  844. readIndex += 4;
  845. memcpy(&modelAmount,buf+readIndex,4);
  846. readIndex += 4;
  847. /*
  848. sprintf(szData,"Complex Model ID: %08x\r\n",modelComplexID);
  849. UpdateConsole(szData);
  850. sprintf(szData,"Model Amount: %08x\r\n",modelAmount);
  851. UpdateConsole(szData);
  852. */
  853. int mIndex = 0;
  854. int tIndex = 0;
  855. //Loop through the model vectors (double of index ID(?) and sub model (0x01000000 values))
  856. for (int yIndex = 0; yIndex < modelAmount; ++yIndex)
  857. {
  858. DWORD modelIndex; //body part
  859. /*
  860. 0x01 - Left Upper Leg
  861. 0x02 - Left Lower leg
  862. 0x03 - Left Shin
  863. 0x04 - Left Foot
  864. 0x05 - Right Upper leg
  865. 0x06 - Right Lower Leg
  866. 0x07 - Right Shin
  867. 0x08 - Right Foot
  868. 0x09 - Chest
  869. 0x0A - Upper Arm (shoulder) - Left
  870. 0x0B - Wrist - Left Arm
  871. 0x0C - Left Hand
  872. 0x0D - Upper Arm (shoulder) - Right
  873. 0x0E - Wrist - Right Arm
  874. 0x0F - Right Hand
  875. 0x10 - Head
  876. */
  877. DWORD modelID; //location of model in portal.dat
  878. DWORD modelTextureCount;
  879. memcpy(&modelIndex,buf+readIndex,4);
  880. readIndex += 4;
  881. memcpy(&modelID,buf+readIndex,4);
  882. readIndex += 4;
  883. memcpy(&modelTextureCount,buf+readIndex,4);
  884. readIndex += 4;
  885. /*
  886. sprintf(szData,"Model Index: %08x\r\n",modelIndex);
  887. UpdateConsole(szData);
  888. sprintf(szData,"Model ID: %08x\r\n",modelID);
  889. UpdateConsole(szData);
  890. sprintf(szData,"Model Texture Count: %08x\r\n",modelTextureCount);
  891. UpdateConsole(szData);
  892. */
  893. //Update item model information
  894. if (modelComplexID == dwModelID)
  895. {
  896. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  897. {
  898. //fetch item model data for characters
  899. pcModel->m_WearVectorMod[mIndex].m_bModelIndex = BYTE(modelIndex);
  900. pcModel->m_WearVectorMod[mIndex].m_wNewModel = WORD(modelID | 0x01000000);
  901. pcModel->m_bWearModelChange = pcModel->m_bWearModelChange + 1;
  902. }
  903. else
  904. {
  905. //fetch item model data
  906. pcModel->m_vectorMod[mIndex].m_bModelIndex = BYTE(modelIndex);
  907. pcModel->m_vectorMod[mIndex].m_wNewModel = WORD(modelID | 0x01000000);
  908. pcModel->m_bModelChange = pcModel->m_bModelChange + 1;
  909. }
  910. mIndex++;
  911. }
  912. //Loop through the textures (0x04000000 values) to be applied to the given submodel (double of texture mask and texture)
  913. for (int zIndex = 0; zIndex < modelTextureCount; ++zIndex)
  914. {
  915. DWORD modelTextureMask;
  916. DWORD modelTexture;
  917. memcpy(&modelTextureMask,buf+readIndex,4);
  918. readIndex += 4;
  919. memcpy(&modelTexture,buf+readIndex,4);
  920. readIndex += 4;
  921. /*
  922. sprintf(szData,"Model Texture Mask: %08x\r\n",modelTextureMask);
  923. UpdateConsole(szData);
  924. sprintf(szData,"Model Texture: %08x\r\n",modelTexture);
  925. UpdateConsole(szData);
  926. */
  927. //Update item texture information
  928. if (modelComplexID == dwModelID)
  929. {
  930. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  931. {
  932. //fetch item texture data for characters
  933. pcModel->m_WearVectorTex[tIndex].m_bModelIndex = BYTE(modelIndex);
  934. pcModel->m_WearVectorTex[tIndex].m_wOldTexture = WORD(modelTextureMask | 0x05000000);
  935. pcModel->m_WearVectorTex[tIndex].m_wNewTexture = WORD(modelTexture | 0x05000000);
  936. pcModel->m_bWearTextureChange = pcModel->m_bWearTextureChange + 1;
  937. }
  938. else
  939. {
  940. pcModel->m_vectorTex[tIndex].m_bModelIndex = BYTE(modelIndex);
  941. pcModel->m_vectorTex[tIndex].m_wOldTexture = WORD(modelTextureMask | 0x05000000);
  942. pcModel->m_vectorTex[tIndex].m_wNewTexture = WORD(modelTexture | 0x05000000);
  943. pcModel->m_bTextureChange = pcModel->m_bTextureChange + 1;
  944. }
  945. tIndex++;
  946. }
  947. }
  948. }
  949. }
  950. // UpdateConsole("\r\n");
  951. WORD altModelCount;
  952. WORD unknown;
  953. memcpy(&altModelCount,buf+readIndex,2);
  954. readIndex += 2;
  955. memcpy(&unknown,buf+readIndex,2);
  956. readIndex += 2;
  957. /*
  958. sprintf(szData,"Alt Model Count: %08x\r\n",altModelCount);
  959. UpdateConsole(szData);
  960. sprintf(szData,"Unknown: %08x\r\n",unknown);
  961. UpdateConsole(szData);
  962. */
  963. for (int wIndex = 0; wIndex < altModelCount; ++wIndex)
  964. {
  965. // UpdateConsole("\r\n");
  966. int pIndex = 0;
  967. DWORD altModelComplexID; //Color ID
  968. // General colors //
  969. //Similar colors are different hues
  970. //Colors 1-18 are available during character selection
  971. /*
  972. 1 - blue
  973. 2 - blue
  974. 3 - violet
  975. 4 - brown
  976. 5 - blue
  977. 6 - brown
  978. 7 - green
  979. 8 - green
  980. 9 - white/gray/black
  981. 10 - blue
  982. 11 - brown
  983. 12 - blue
  984. 13 - violet
  985. 14 - red
  986. 15 - red
  987. 16 - red
  988. 17 - yellow
  989. 18 - gold
  990. 84 - green
  991. 85 - red
  992. 86 - yellow
  993. 87 - red
  994. 88 - blue
  995. 89 - green
  996. 90 - black
  997. 91 - blue
  998. 92 - violet
  999. 93 - white/gray/black
  1000. */
  1001. DWORD altModelIcon;
  1002. DWORD paletteAmount;
  1003. memcpy(&altModelComplexID,buf+readIndex,4);
  1004. readIndex += 4;
  1005. memcpy(&altModelIcon,buf+readIndex,4); //0x06000000 value
  1006. readIndex += 4;
  1007. memcpy(&paletteAmount,buf+readIndex,4);
  1008. readIndex += 4;
  1009. if (dwColorID)
  1010. if (dwColorID == altModelComplexID)
  1011. pcObject->m_wIcon = altModelIcon;
  1012. /* sprintf(szData,"Alt Complex Model ID: %08x\r\n",altModelComplexID);
  1013. UpdateConsole(szData);
  1014. sprintf(szData,"Alt Model Icon: %08x\r\n",altModelIcon);
  1015. UpdateConsole(szData);
  1016. sprintf(szData,"Palette Amount: %08x\r\n",paletteAmount);
  1017. UpdateConsole(szData);
  1018. */
  1019. //Loop through the model palette list
  1020. for (int xIndex = 0; xIndex < paletteAmount; ++xIndex)
  1021. {
  1022. DWORD paletteVectorAmount;
  1023. memcpy(&paletteVectorAmount,buf+readIndex,4);
  1024. readIndex += 4;
  1025. /*
  1026. sprintf(szData,"Palette Vector Amount: %08x\r\n",paletteVectorAmount);
  1027. UpdateConsole(szData);
  1028. */
  1029. //Loop through the specific palette vector (trio of palette offset, palette length, and CLUT list)
  1030. for (int yIndex = 0; yIndex < paletteVectorAmount; ++yIndex)
  1031. {
  1032. DWORD paletteVectorOffset;
  1033. DWORD paletteVectorValue;
  1034. memcpy(&paletteVectorOffset,buf+readIndex,4);
  1035. readIndex += 4;
  1036. memcpy(&paletteVectorValue,buf+readIndex,4);
  1037. readIndex += 4;
  1038. /*
  1039. sprintf(szData,"Palette Vector Offset: %08x\r\n",paletteVectorOffset);
  1040. UpdateConsole(szData);
  1041. sprintf(szData,"Palette Vector Value: %08x\r\n",paletteVectorValue);
  1042. UpdateConsole(szData);
  1043. */
  1044. if (dwColorID)
  1045. {
  1046. if (dwColorID == altModelComplexID)
  1047. {
  1048. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  1049. {
  1050. //fetch item texture data for characters
  1051. pcObject->m_WearVectorPal[pIndex].m_ucOffset = BYTE(paletteVectorOffset);
  1052. pcObject->m_WearVectorPal[pIndex].m_ucLength = BYTE(paletteVectorValue);
  1053. pcObject->m_bWearPaletteChange = pcObject->m_bWearPaletteChange + 1;
  1054. }
  1055. else
  1056. {
  1057. pcObject->m_vectorPal[pIndex].m_ucOffset = BYTE(paletteVectorOffset);
  1058. pcObject->m_vectorPal[pIndex].m_ucLength = BYTE(paletteVectorValue);
  1059. pcObject->m_bPaletteChange = pcObject->m_bPaletteChange + 1;
  1060. }
  1061. pIndex++;
  1062. }
  1063. }
  1064. }
  1065. DWORD paletteID;
  1066. memcpy(&paletteID,buf+readIndex,4);
  1067. readIndex += 4;
  1068. /*
  1069. sprintf(szData,"Palette ID: %08x\r\n",paletteID);
  1070. UpdateConsole(szData);
  1071. */
  1072. char szPalFile[9];
  1073. sprintf(szPalFile,"%08x",paletteID);
  1074. UCHAR *palBuf;
  1075. //DWORD paletteFileNum;
  1076. DWORD paletteCount;
  1077. //Load palette data from the portal.dat file
  1078. cPortalDat::Load_PortalDat(palBuf, szPalFile);
  1079. int palReadIndex = 0;
  1080. palReadIndex += 4; //the first 4 bytes list the index for which we searched
  1081. memcpy(&paletteCount,palBuf+palReadIndex,4);
  1082. palReadIndex += 4;
  1083. /*
  1084. sprintf(szData,"Palette Count: %08x\r\n",paletteCount);
  1085. UpdateConsole(szData);
  1086. */
  1087. //Calculate the palette to be used
  1088. int intPalette = CalcPalette(paletteCount,dblColorValue);
  1089. //Loop through the specific palettes (0x04000000 values)
  1090. for (int zIndex = 0; zIndex < paletteCount; ++zIndex)
  1091. {
  1092. DWORD palette;
  1093. memcpy(&palette,palBuf+palReadIndex,4);
  1094. palReadIndex += 4;
  1095. /*
  1096. sprintf(szData,"Palette: %08x\r\n",palette);
  1097. UpdateConsole(szData);
  1098. */
  1099. if (dwColorID == altModelComplexID)
  1100. {
  1101. if (zIndex == intPalette)
  1102. {
  1103. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  1104. {
  1105. pcObject->m_WearVectorPal[xIndex].m_wNewPalette = WORD(palette | 0x04000000);
  1106. }
  1107. else
  1108. {
  1109. pcObject->m_vectorPal[xIndex].m_wNewPalette = WORD(palette | 0x04000000);
  1110. }
  1111. }
  1112. }
  1113. }
  1114. free(palBuf);
  1115. }
  1116. }
  1117. free(buf);
  1118. if (dwModelID == 0x02000001 || dwModelID == 0x0200004E)
  1119. pcModel->m_clothingModelLoaded = true;
  1120. }
  1121. }
  1122. /**
  1123. * Determines the CLUT (0x04000000 object in the portal.dat) to be used.
  1124. *
  1125. * The palette to use is determined by rounding the value of numPalettes minus one (as the
  1126. * palettes are zero-indexed) multiplied by the palValue value.
  1127. *
  1128. * @param numPalettes - The number of palettes in the palette list.
  1129. * @param palValue - The shading value used to determine the palette (between 0 and 1).
  1130. *
  1131. * @return palette - The palette index (beginning with 0) to use.
  1132. */
  1133. int cPortalDat::CalcPalette( int numPalettes, double palValue )
  1134. {
  1135. if (palValue == -1)
  1136. {
  1137. return 0;
  1138. }
  1139. else
  1140. {
  1141. int palette = floor( (double)(palValue * (numPalettes - 1)) + .5 );
  1142. if (palette < 0) palette = 0;
  1143. if (palette > (numPalettes - 1)) palette = (numPalettes - 1);
  1144. return palette;
  1145. }
  1146. }