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

Corpse.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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 Corpse.cpp
  19. * Implements functionality for corpses.
  20. *
  21. * This class is referenced whenever a corpse is created, used, or assessed.
  22. *
  23. * Author: Cubem0j0
  24. */
  25. #include "Client.h"
  26. #include "MasterServer.h"
  27. #include "Object.h"
  28. #include "WorldManager.h"
  29. #include "TreasureGen.h"
  30. /***************
  31. * constructors
  32. **************/
  33. /**
  34. * Handles the creation of corpses.
  35. *
  36. * Called whenever a corpses object should be initialized.
  37. */
  38. cCorpse::cCorpse( WORD type, DWORD dwGUID, cLocation& Loc, char *szName, char *szDesc)
  39. {
  40. //SetLocation( pcLoc );
  41. m_dwGUID = dwGUID;//cWorldManager::NewGUID_Object( );
  42. m_strName.assign( szName );
  43. m_strDescription.assign( szDesc );
  44. m_dwModel = type;
  45. m_dwType = 0;
  46. m_fStatic = false;
  47. m_dwDoorState = 0x0CL;
  48. CopyMemory( &m_Location, &Loc, sizeof( cLocation ) );
  49. //Set the objects state
  50. this->SetState(0);
  51. }
  52. /**********
  53. * methods
  54. *********/
  55. /**
  56. * Handles the message sent for the creation of a corpse in the world.
  57. *
  58. * This function is called whenever a corpse should be created in the world for a client.
  59. * @return cMessage - Returns a server message to the client.
  60. */
  61. cMessage cCorpse::CreatePacket( )
  62. {
  63. cMessage cmCreate;
  64. unsigned char bUnknown[] = {
  65. 0x00, 0x00, 0x3D, 0x00, 0x02, 0xF0, 0xB5, 0x02, 0x11, 0x00, 0x00, 0x00,
  66. };
  67. cModels *pcMonster = cModels::FindModel(this->m_MonsterModelID);
  68. #ifdef _DEBUG
  69. cMasterServer::ServerMessage( ColorYellow,NULL,"m_dwModel = %d",this->m_MonsterModelID);
  70. #endif
  71. if(pcMonster)
  72. {
  73. cmCreate << 0xF745L << m_dwGUID << BYTE(0x11); //0x11 is a constant
  74. cmCreate << pcMonster->m_bPaletteChange
  75. << pcMonster->m_bTextureChange
  76. << pcMonster->m_bModelChange;
  77. // The Model Vectors
  78. if ( pcMonster->m_bPaletteChange != 0)
  79. {
  80. for (int i = 0; i < pcMonster->m_bPaletteChange; i++)
  81. {
  82. cmCreate.pasteData((UCHAR*)&pcMonster->m_vectorPal[i],sizeof(pcMonster->m_vectorPal[i]));
  83. }
  84. }
  85. if (pcMonster->m_bPaletteChange != 0)
  86. {
  87. cmCreate << WORD( pcMonster->m_wUnknown1 );
  88. }
  89. if ( pcMonster->m_bTextureChange != 0)
  90. {
  91. for (int i = 0; i < pcMonster->m_bTextureChange; i++)
  92. {
  93. cmCreate.pasteData((UCHAR*)&pcMonster->m_vectorTex[i],sizeof(pcMonster->m_vectorTex[i]));
  94. }
  95. }
  96. if ( pcMonster->m_bModelChange != 0)
  97. {
  98. for (int i = 0; i < pcMonster->m_bModelChange; i++)
  99. {
  100. cmCreate.pasteData((UCHAR*)&pcMonster->m_vectorMod[i],sizeof(pcMonster->m_vectorMod[i]));
  101. }
  102. }
  103. }
  104. cmCreate.pasteAlign(4);
  105. DWORD dwFlags = 0x00019883L;
  106. cmCreate << dwFlags;
  107. cmCreate << WORD( 0x0414 );
  108. cmCreate << WORD( 0x000C );
  109. // MASK 0x00010000 unknown Bytes - Starting Animation
  110. cmCreate << 0x0CL;
  111. cmCreate.pasteData(bUnknown,sizeof(bUnknown));
  112. cmCreate << 0x0L;
  113. // MASK 0x00008000 -- Location
  114. if ( !m_fIsOwned )
  115. cmCreate.CannedData( (BYTE *)&m_Location, sizeof( cLocation ) );
  116. // MASK 0x00000002 -- Animation Set
  117. DWORD dwAnimC = 0x09000000L + m_wAnimConfig;
  118. cmCreate << dwAnimC;
  119. // MASK 0x00000800 -- Sound Set
  120. DWORD dwSoundSet = 0x20000000L + m_wSoundSet;
  121. cmCreate << dwSoundSet;
  122. // MASK 0x00001000 -- Particle Effects (unknown_blue)
  123. cmCreate << 0x3400006EL;//0x00000000L;
  124. // MASK 0x00000001 -- ModelNumber
  125. DWORD dwModel = 0x02000000L + m_dwModel;
  126. cmCreate << dwModel;
  127. cmCreate << float(m_flScale);
  128. // SeaGreens
  129. WORD wNuminteracts = 0x0;
  130. WORD wNumbubbles = 0x0;
  131. WORD wNumJumps = 0x0;
  132. WORD wNumOverrides = 0x0;
  133. WORD wUnkFlag8 = 0x0;
  134. WORD wUnkFlag10 = 0x0;
  135. cmCreate << m_wPositionSequence
  136. << m_wNumAnims //wNuminteracts
  137. << wNumbubbles
  138. << wNumJumps
  139. << m_wNumPortals
  140. << m_wNumAnims
  141. << wNumOverrides
  142. << wUnkFlag8
  143. << m_wNumLogins
  144. << wUnkFlag10;
  145. DWORD dwFlags2 = 0x00200036;
  146. cmCreate << dwFlags2 << m_strName.c_str( ) << WORD(m_wModel) << WORD(m_wIcon);//WORD( 0x019C ) << WORD( 0x1317 );;//WORD( 0x0116 ) << WORD( 0x1317 );
  147. /* Category of object:
  148. 0x00000001 Melee Weapon
  149. 0x00000002 Armor
  150. 0x00000004 Clothing
  151. 0x00000008 Jewelry
  152. 0x00000010 Creature (Player/NPC/Monster)
  153. 0x00000020 Food
  154. 0x00000040 Pyreals
  155. 0x00000080 Miscellaneous
  156. 0x00000100 Missile Weapons/Ammunition
  157. 0x00000200 Containers
  158. 0x00000400 Wrapped Fletching Supplies, House Decorations
  159. 0x00000800 Gems, Pack dolls, Decorative Statues
  160. 0x00001000 Spell Components
  161. 0x00002000 Books, Parchment, Scrolls, Signs, Statues
  162. 0x00004000 Keys, Lockpicks
  163. 0x00008000 Casting Item (wand, orb, staff)
  164. 0x00010000 Portal
  165. 0x00020000 Lockable
  166. 0x00040000 Trade Notes
  167. 0x00080000 Mana Stones, Mana Charges
  168. 0x00100000 Services
  169. 0x00200000 unknown (no longer plants)
  170. 0x00400000 Cooking Ingredients and Supplies, Plants, Dye Pots
  171. 0x00800000 Loose Fletching Supplies
  172. 0x01000000 unknown
  173. 0x02000000 unknown
  174. 0x04000000 Alchemy Ingredients and Supplies, Oils, Dye Vials
  175. 0x08000000 unknown
  176. 0x10000000 Lifestone
  177. 0x20000000 Ust
  178. 0x40000000 Salvage
  179. 0x80000000 unknown
  180. */
  181. DWORD dwObjectFlags1 = 0x0200L;
  182. cmCreate << dwObjectFlags1;
  183. /* Behavior of object:
  184. 0x00000001 can be opened (false if locked)
  185. 0x00000002 can be inscribed
  186. 0x00000004 cannot be picked up
  187. 0x00000008 is a player
  188. 0x00000010 is not an npc
  189. 0x00000020 unknown
  190. 0x00000040 unknown
  191. 0x00000080 cannot be selected
  192. 0x00000100 can be read
  193. 0x00000200 is a merchant
  194. 0x00000400 is a pk altar
  195. 0x00000800 is an npk altar
  196. 0x00001000 is a door
  197. 0x00002000 is a corpse
  198. 0x00004000 can be attuned to (lifestone)
  199. 0x00008000 adds to health, stamina or mana
  200. 0x00010000 is a healing kit
  201. 0x00020000 is a lockpick
  202. 0x00040000 is a portal
  203. 0x00800000 is a foci
  204. 0x04000000 has an extra flags DWORD
  205. */
  206. DWORD dwObjectFlags2 = 0x2015L;
  207. cmCreate << dwObjectFlags2;
  208. /* Masked against dwFlags2 in reverse order:
  209. 0x00000002 - Item Slots
  210. 0x00000004 - Pack Slots
  211. 0x00000008 - Value
  212. 0x00000010 - Unknown1
  213. 0x00000020 - Approach Distance
  214. 0x00200000 - Burden
  215. */
  216. cmCreate << BYTE (0x78); //78 is item slots. (120)
  217. cmCreate << BYTE (0x00); //00 is pack slots
  218. //cmCreate << DWORD (0x000009C4); //Value
  219. cmCreate << DWORD (0x00000030); //Unknown
  220. cmCreate << float(3.0); //Approach Distance.
  221. cmCreate << WORD (0x0000); //Burden
  222. return cmCreate;
  223. }
  224. /**
  225. * Handles the actions of corpse objects.
  226. *
  227. * This function is called whenever a corpse is used.
  228. */
  229. void cCorpse::Action(cClient* who)
  230. {
  231. //Logic for open/close
  232. switch (GetState())
  233. {
  234. case 0:
  235. {
  236. /*
  237. char szCommand[100];
  238. RETCODE retcode;
  239. int ItemType;
  240. DWORD dwItemModelID;
  241. int test;
  242. test = 70;
  243. sprintf( szCommand, "SELECT * FROM monsters_loot where dwModelID = %d;", this->GetType());
  244. #ifdef _DEBUG
  245. cMasterServer::ServerMessage( ColorYellow,NULL,"This GUID: %d, This Monster Model: %d",this->GetGUID(),this->GetMonsterModelID());
  246. #endif
  247. retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  248. retcode = SQLExecute( cDatabase::m_hStmt );
  249. int iCol = 3;
  250. retcode = SQLBindCol( cDatabase::m_hStmt, iCol++, SQL_C_LONG, &ItemType, sizeof( INT ), NULL ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  251. retcode = SQLBindCol( cDatabase::m_hStmt, iCol++, SQL_C_LONG, &dwItemModelID, sizeof( DWORD ), NULL ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  252. who->m_pcAvatar->m_CorpseTarget = this->GetGUID();
  253. cMessage cmSetPackContents;
  254. cmSetPackContents << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x0196L << m_dwGUID;
  255. for ( int i = 0; SQLFetch( cDatabase::m_hStmt ) == SQL_SUCCESS; i++ )
  256. {
  257. //Cubem0j0: We find the model number so we can get some vars.
  258. cItemModels *pcModel = cItemModels::FindModel(dwItemModelID);
  259. switch(ItemType)
  260. {
  261. case 1:
  262. {
  263. cWeapon* aWeapon = new cWeapon(cWorldManager::NewGUID_Object(),this->GetGUID(),dwItemModelID,1.0,TRUE,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_wBurden,pcModel->m_dwValue,pcModel->m_bWieldType);
  264. who->AddPacket( WORLD_SERVER, aWeapon->CreatePacketContainer(this->GetGUID(),pcModel->m_dwModelID),3);
  265. this->AddInventory(aWeapon);
  266. cmSetPackContents << 0x01L << aWeapon->GetGUID() << 0x0L;
  267. #ifdef _DEBUG
  268. cMasterServer::ServerMessage( ColorYellow,NULL,"Case 1");
  269. #endif
  270. break;
  271. }
  272. case 2:
  273. {
  274. cFood* aFood = new cFood(cWorldManager::NewGUID_Object(),this->GetGUID(),dwItemModelID,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_wBurden,pcModel->m_dwValue);
  275. who->AddPacket( WORLD_SERVER, aFood->CreatePacketContainer(this->GetGUID(),pcModel->m_dwModelID),3);
  276. this->AddInventory(aFood);
  277. cmSetPackContents << aFood->GetGUID() << 0x0L;
  278. break;
  279. }
  280. case 3:
  281. {
  282. cArmor* aArmor = new cArmor(cWorldManager::NewGUID_Object(),this->GetGUID(),dwItemModelID,1.0,TRUE,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_dwValue,pcModel->m_wBurden);
  283. who->AddPacket( WORLD_SERVER, aArmor->CreatePacketContainer(this->GetGUID(),pcModel->m_dwModelID),3);
  284. this->AddInventory(aArmor);
  285. cmSetPackContents << aArmor->GetGUID() << 0x0L;
  286. break;
  287. }
  288. case 8:
  289. {
  290. cWands* aWand = new cWands(cWorldManager::NewGUID_Object(),this->GetGUID(),dwItemModelID,1.0,TRUE,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_dwValue,pcModel->m_wBurden);
  291. who->AddPacket( WORLD_SERVER, aWand->CreatePacketContainer(this->GetGUID(),pcModel->m_dwModelID),3);
  292. this->AddInventory(aWand);
  293. cmSetPackContents << aWand->GetGUID() << 0x0L;
  294. break;
  295. }
  296. case 13:
  297. {
  298. cSpellComps* aReg = new cSpellComps(cWorldManager::NewGUID_Object(),this->GetGUID(),dwItemModelID,1.0,TRUE,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_dwValue,pcModel->m_wBurden);
  299. who->AddPacket( WORLD_SERVER, aReg->CreatePacketContainer(this->GetGUID(),pcModel->m_dwModelID),3);
  300. this->AddInventory(aReg);
  301. //cmSetPackContents << 0x01L << aReg->GetGUID() << 0x0L;
  302. break;
  303. }
  304. }
  305. who->AddPacket(WORLD_SERVER,cmSetPackContents,4);
  306. }
  307. */
  308. //I just explicitly use a model ID here, I will change this to a function later.
  309. cItemModels *pcModel = cItemModels::FindModel(147);
  310. //Use the Item Container classes to create the item in a corpse/chest.
  311. cLockpicks* Lockpicks = new cLockpicks(cWorldManager::NewGUID_Object(),this->GetGUID(),pcModel->m_dwModelNumber,1.0,TRUE,pcModel->m_wIcon,pcModel->m_strName,pcModel->m_strDescription,pcModel->m_wUses,pcModel->m_wUseLimit);
  312. //Need a way for the cObject class to find the Item Model ID
  313. Lockpicks->m_dwItemModelID = pcModel->m_dwModelID;
  314. //Send the create packet
  315. who->AddPacket(WORLD_SERVER,Lockpicks->CreatePacketContainer(this->GetGUID(),Lockpicks->GetItemModelID()),3);
  316. #ifdef _DEBUG
  317. cMasterServer::ServerMessage( ColorYellow,NULL,"ItemModelID is: %d",Lockpicks->GetItemModelID());
  318. #endif
  319. //Add the item to the corpse inventory.
  320. this->AddInventory(Lockpicks);
  321. //SQL Done
  322. // retcode = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )
  323. // retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN( 0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL )
  324. //Set the GUID of the corpse on the avatar (this is used in find the item in the corpses inventory)
  325. who->m_pcAvatar->m_CorpseTarget = this->GetGUID();
  326. if(this->FindInventory(Lockpicks->GetGUID()))
  327. {
  328. #ifdef _DEBUG
  329. cMasterServer::ServerMessage( ColorYellow,NULL,"Item Found");
  330. #endif
  331. }
  332. //Display the item slots in the chest (0x0196)
  333. cMessage cmSetPackContents;
  334. cmSetPackContents << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x0196L << m_dwGUID
  335. << 0x01L << Lockpicks->GetGUID() << 0x0L;
  336. who->AddPacket(WORLD_SERVER,cmSetPackContents,4);
  337. cMessage cmActionComplete;
  338. cmActionComplete << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x01C7L << 0L;
  339. who->AddPacket(WORLD_SERVER,cmActionComplete,4);
  340. this->SetState(1);
  341. break;
  342. }
  343. case 1:
  344. {
  345. #ifdef _DEBUG
  346. cMasterServer::ServerMessage(ColorYellow,NULL,"m_wState is %d",m_wState);
  347. #endif
  348. //Close Container
  349. cMessage cmCloseContainer;
  350. cmCloseContainer << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x0052L << m_dwGUID;
  351. who->AddPacket(WORLD_SERVER,cmCloseContainer,4);
  352. cMessage cmActionComplete;
  353. cmActionComplete << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x01C7L << 0L;
  354. who->AddPacket(WORLD_SERVER,cmActionComplete,4);
  355. this->SetState(0);
  356. break;
  357. }
  358. }
  359. }
  360. /**
  361. * Handles the assessment of corpse objects.
  362. *
  363. * This function is called whenever a corpse is assessed by a client.
  364. * Returns a server message to the client.
  365. */
  366. void cCorpse::Assess(cClient *pcAssesser)
  367. {
  368. cMessage cmAssess;
  369. DWORD flags = 0x00000009;
  370. cmAssess << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID() << ++pcAssesser->m_dwF7B0Sequence << 0xC9L << m_dwGUID
  371. << flags
  372. << 0x01L //Success = 0x01, Failure = 0x00
  373. << WORD(0x0002)
  374. << WORD(0x0010)
  375. << 0x13L //Value
  376. << 0x00L //Corpse always zero.
  377. << 0x05L //Burden
  378. << 0xCCL //for now, static amount it eventuall should add up all the item bu's
  379. << WORD(0x0001) //Count (as above) total number of DWORDS
  380. << WORD(0x0008) //Unknown
  381. << 0x10L
  382. << this->m_strDescription.c_str(); //This is the "Killed by" message when ID'd.
  383. pcAssesser->AddPacket(WORLD_SERVER,cmAssess,4);
  384. }