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

Monster.cpp 40KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  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 Monster.cpp
  19. * Implements functionality for monsters.
  20. *
  21. * Includes member functions to control the movement, attacking, respawning, animation, and assessment of monsters.
  22. */
  23. #include "Client.h"
  24. #include "MasterServer.h"
  25. #include "Object.h"
  26. #include "WorldManager.h"
  27. #include "CorpseCleaner.h"
  28. #include "Database.h"
  29. #include "Job.h"
  30. #include "cSpell.h"
  31. /***************
  32. * constructors
  33. **************/
  34. /**
  35. * Handles the creation of monsters.
  36. *
  37. * Called whenever a monster object should be initialized.
  38. * @return cMessage - Returns a Create Object (0x0000F745) server message.
  39. */
  40. cMonster::cMonster( DWORD dwGUID, DWORD dwModelID, cLocation *pcLoc, char *szName, char *szDesc, cMonStats *pcmsStats, DWORD dwRespawn, DWORD dwDecay, DWORD dwChase, DWORD dwInfluence, DWORD dwExp_Value, DWORD dwHealth, DWORD dwStamina, DWORD dwMana )
  41. : m_dwMonsterModelID( dwModelID )
  42. {
  43. SetLocation( pcLoc );
  44. SetSpawnLoc( pcLoc );
  45. m_dwGUID = dwGUID;
  46. m_dwMonsterModelID = dwModelID;
  47. m_fDeadOrAlive = true; // true = Alive, false = Dead
  48. m_strName.assign( szName );
  49. m_strDescription.assign( szDesc );
  50. m_wNumMovements = 0x0000;
  51. m_wNumAnimInteracts = 0x0000;
  52. m_wNumBubbleModes = 0x0000;
  53. m_wNumJumps = 0x0000;
  54. m_wNumPortals = 0x0000;
  55. m_wAnimCount = 0x0000;
  56. m_wNumOverrides = 0x0000;
  57. m_wNumLogins = 0x0001;
  58. m_fStatic = TRUE;
  59. m_dwObjectFlags1 = 0x0L;
  60. m_dwObjectFlags2 = 0x0L;
  61. m_wNumAnims = 0x0000;
  62. m_wCurAnim = 0x0000;
  63. m_wMeleeSequence = 0x0000;
  64. m_dwF7B0Sequence = 0x00000000;
  65. m_bStatSequence = 0x00;
  66. m_fCombatMode = false;
  67. m_dwReSpawn = dwRespawn;
  68. m_dwDecay = dwDecay;
  69. m_dwChase = dwChase;
  70. m_dwInfluence = dwInfluence;
  71. m_dwExp_Value = dwExp_Value;
  72. m_iPosUpdateCount = 10;
  73. // Set the Character Stats to 0 for safety
  74. //Cubem0j0: Modified this, monster vitals are not always the same as pc's.
  75. m_dwLevel = pcmsStats->m_dwLevel;
  76. m_dwMaxHealth = dwHealth;
  77. m_dwStr = pcmsStats->m_dwStr;
  78. m_dwEnd = pcmsStats->m_dwEnd;
  79. m_dwQuick = pcmsStats->m_dwQuick;
  80. m_dwCoord = pcmsStats->m_dwCoord;
  81. m_dwFocus = pcmsStats->m_dwFocus;
  82. m_dwSelf = pcmsStats->m_dwSelf;
  83. m_dwMaxStamina = dwStamina;
  84. m_dwMaxMana = dwMana;
  85. m_dwSpecies = pcmsStats->m_dwSpecies;
  86. m_dwCurrenthealth = m_dwMaxHealth;
  87. m_dwCurrentStamina = m_dwMaxStamina;
  88. m_dwCurrentMana = m_dwMaxMana;
  89. m_bIdleAnim = 0;
  90. m_bCombatMode = 0;
  91. static BYTE bAnimate[8] = {
  92. 0x00, 0x00, 0x3D, 0x00, 0x00, 0xF0, 0xB5, 0x02,
  93. };
  94. cModels *pcModel = cModels::FindModel( m_dwMonsterModelID );
  95. if( pcModel )
  96. {
  97. m_dwUnknownCount = pcModel->m_dwUnknownCount;
  98. CopyMemory( &m_bInitialAnimation[0], pcModel->m_bInitialAnimation, pcModel->m_dwUnknownCount);
  99. }
  100. else
  101. {
  102. m_dwUnknownCount = sizeof(bAnimate);
  103. CopyMemory( &m_bInitialAnimation[0], &bAnimate, 8);
  104. }
  105. SimpleAI::AddMonster( m_dwGUID );
  106. }
  107. /**********
  108. * methods
  109. *********/
  110. /**
  111. * Handles the message sent for the creation of monsters.
  112. *
  113. * This member function is called whenever a monster should be created for a client.
  114. * @return cMessage - Returns a Create Object (0x0000F745) server message.
  115. */
  116. cMessage cMonster::CreatePacket()
  117. {
  118. cMessage cmReturn;
  119. cModels *pcModel = cModels::FindModel( m_dwMonsterModelID );
  120. DWORD dwFlags1;
  121. if( pcModel )
  122. {
  123. DWORD dwUnkDatEntry2 = 0x0L;
  124. m_dwObjectFlags1 = pcModel->m_dwObjectFlags1;
  125. m_dwObjectFlags2 = pcModel->m_dwObjectFlags2;
  126. cmReturn << 0xF745L << m_dwGUID << BYTE(0x11); //0x11 is a constant
  127. cmReturn << pcModel->m_bPaletteChange
  128. << pcModel->m_bTextureChange
  129. << pcModel->m_bModelChange;
  130. // The Model Vectors
  131. if ( pcModel->m_bPaletteChange != 0)
  132. {
  133. for (int i = 0; i < pcModel->m_bPaletteChange; i++)
  134. {
  135. cmReturn.pasteData((UCHAR*)&pcModel->m_vectorPal[i],sizeof(pcModel->m_vectorPal[i]));
  136. }
  137. }
  138. if (pcModel->m_bPaletteChange != 0)
  139. {
  140. cmReturn << WORD( pcModel->m_wUnknown1 );
  141. }
  142. if ( pcModel->m_bTextureChange != 0)
  143. {
  144. for (int i = 0; i < pcModel->m_bTextureChange; i++)
  145. {
  146. cmReturn.pasteData((UCHAR*)&pcModel->m_vectorTex[i],sizeof(pcModel->m_vectorTex[i]));
  147. }
  148. }
  149. if ( pcModel->m_bModelChange != 0)
  150. {
  151. for (int i = 0; i < pcModel->m_bModelChange; i++)
  152. {
  153. cmReturn.pasteData((UCHAR*)&pcModel->m_vectorMod[i],sizeof(pcModel->m_vectorMod[i]));
  154. }
  155. }
  156. // End Model Vectors
  157. dwFlags1 = pcModel->m_dwFlags1;
  158. if( pcModel->m_dwFlags1 & 0x40)
  159. {
  160. dwFlags1 = dwFlags1 - 0x40;
  161. }
  162. if( pcModel->m_dwFlags1 & 0x20)
  163. {
  164. dwFlags1 = dwFlags1 - 0x20;
  165. }
  166. cmReturn.pasteAlign(4);
  167. cmReturn << dwFlags1;
  168. cmReturn << WORD(pcModel->m_wPortalMode)
  169. << WORD(pcModel->m_wUnknown_1);
  170. // Mask against dwFlags1
  171. // Choose Valid Sections Masking Against Flags1
  172. //Flags1 & 0x00010000
  173. if (pcModel->m_dwFlags1 & 0x00010000 )
  174. {
  175. cmReturn << m_dwUnknownCount; //pcModel->m_dwUnknownCount;
  176. // Vector of UnknownCount
  177. for ( int i = 0;i < m_dwUnknownCount; i++)
  178. {
  179. //pcModel->m_dwUnknownCount; i++) {
  180. cmReturn << m_bInitialAnimation[i]; //pcModel->m_bInitialAnimation[i];
  181. }
  182. cmReturn << pcModel->m_dwUnknownDword;
  183. }
  184. // Flags1 & 0x00020000
  185. if (pcModel->m_dwFlags1 & 0x00020000)
  186. {
  187. cmReturn << pcModel->m_dwUnknown;
  188. }
  189. // Flags1 & 0x00008000 - Location Data
  190. if (pcModel->m_dwFlags1 & 0x00008000)
  191. {
  192. cmReturn.pasteData( (UCHAR*)&m_Location, sizeof(m_Location) );
  193. }
  194. // Flags1 & 0x00000002 - Animation Config
  195. if (pcModel->m_dwFlags1 & 0x00000002)
  196. {
  197. //Format = 0x09000000
  198. cmReturn << 0x09000000 + pcModel->m_wAnimConfig;
  199. }
  200. // Flags1 & 0x00000800 - sound Set
  201. if (pcModel->m_dwFlags1 & 0x00000800)
  202. {
  203. //Format = 0x20000001;
  204. cmReturn << 0x20000000 + pcModel->m_wSoundSet;
  205. }
  206. // Flags1 & 0x00001000 - Particle Effects ?
  207. if (pcModel->m_dwFlags1 & 0x00001000)
  208. {
  209. //Format = 0x34000004;
  210. cmReturn << 0x34000000 + pcModel->m_dwUnknown_Blue;
  211. }
  212. // Flags1 & 0x00000001 - Object's Model Number
  213. if (pcModel->m_dwFlags1 & 0x00000001)
  214. {
  215. //Format = 0x02000001;
  216. cmReturn << 0x02000000 + pcModel->m_dwModelNumber;
  217. }
  218. // Flags1 & 0x00000080 - Unknown_Green This represents Model Scale
  219. if (pcModel->m_dwFlags1 & 0x00000080)
  220. {
  221. if(pcModel->m_flScale == 0)
  222. {
  223. cmReturn << 1.0f;
  224. }
  225. else
  226. {
  227. cmReturn << pcModel->m_flScale; // Scale?
  228. }
  229. }
  230. // Flags1 & 0x00040000 - Unknown
  231. if (pcModel->m_dwFlags1 & 0x00040000)
  232. {
  233. //Format = 0x02000001;
  234. cmReturn << 0x02000000 + pcModel->m_dwUnknown_LightGrey;
  235. }
  236. // Unknown Trios
  237. // Flags1 & 0x00000004
  238. if (pcModel->m_dwFlags1 & 0x00000004)
  239. {
  240. cmReturn << pcModel->m_dwTrio1[0] << pcModel->m_dwTrio1[1] << pcModel->m_dwTrio1[2];
  241. }
  242. // Flags1 & 0x00000008
  243. if (pcModel->m_dwFlags1 & 0x00000008)
  244. {
  245. cmReturn << pcModel->m_dwTrio2[0] << pcModel->m_dwTrio2[1] << pcModel->m_dwTrio2[2];
  246. }
  247. // Flags1 & 0x00000010
  248. if (pcModel->m_dwFlags1 & 0x00000010)
  249. {
  250. cmReturn << pcModel->m_dwTrio3[0] << pcModel->m_dwTrio3[1] << pcModel->m_dwTrio3[2];
  251. }
  252. // Unknown Values
  253. // Flags1 & 0x00002000
  254. if (pcModel->m_dwFlags1 & 0x00002000)
  255. {
  256. cmReturn << pcModel->m_dwMedGrey;
  257. }
  258. // Flags1 & 0x00004000
  259. if (pcModel->m_dwFlags1 & 0x00004000)
  260. {
  261. cmReturn << pcModel->m_dwBlueGrey;
  262. }
  263. // This set of Data is found in every Create Object Packet
  264. cmReturn << m_wNumMovements;
  265. cmReturn << m_wNumAnimInteracts;
  266. cmReturn << m_wNumBubbleModes;
  267. cmReturn << m_wNumJumps;
  268. cmReturn << m_wNumPortals;
  269. cmReturn << m_wAnimCount;
  270. cmReturn << m_wNumOverrides;
  271. cmReturn << pcModel->m_wSeagreen8;
  272. cmReturn << m_wNumLogins;
  273. cmReturn << pcModel->m_wSeagreen10;
  274. cmReturn << pcModel->m_dwFlags2; // Object Flags
  275. cmReturn << Name( ); // Objects Name
  276. cmReturn << pcModel->m_wModel; // Objects Model
  277. cmReturn << pcModel->m_wIcon; // Objects Icon
  278. cmReturn << pcModel->m_dwObjectFlags1; // Object Flags
  279. cmReturn << pcModel->m_dwObjectFlags2; // Object Flags
  280. pcModel->mob_strength = m_dwStr;
  281. //Cubem0j0: Approach distance used in combat routine
  282. this->m_fApproachDistance = 0.3f;
  283. // Choose Valid Sections Masking Against Flags2
  284. // Flags2 & 0x00000002 - Item Slots
  285. if (pcModel->m_dwFlags2 & 0x00000002)
  286. {
  287. cmReturn << pcModel->m_bItemSlots;
  288. }
  289. // Flags2 & 0x00000004 - Pack Slots
  290. if (pcModel->m_dwFlags2 & 0x00000004)
  291. {
  292. cmReturn << pcModel->m_bPackSlots;
  293. }
  294. // Flags2 & 0x04000000 - Behavior
  295. //if (pcModel->m_dwFlags2 & 0x04000000)
  296. //{
  297. // cmReturn << pcModel->m_bBehavior;
  298. //}
  299. // Flags2 & 0x00000010
  300. if (pcModel->m_dwFlags2 & 0x00000010)
  301. {
  302. cmReturn << pcModel->m_dwUnknown_v2;
  303. }
  304. // Flags2 & 0x00800000
  305. if (pcModel->m_dwFlags2 & 0x00800000)
  306. {
  307. cmReturn << pcModel->m_dwUnknown_v6;
  308. }
  309. return cmReturn;
  310. }
  311. else
  312. {
  313. cmReturn << 0xF755L << DWORD(1) << DWORD(124) << 0x3F2B4E94L;
  314. return cmReturn;
  315. }
  316. }
  317. /**
  318. * Handles the respawning of monster objects .
  319. *
  320. * This member function is called whenever a monster should be respawned.
  321. *
  322. * @param *pcObject - A pointer to the monster object to be respawned.
  323. */
  324. void cMonster::ReSpawn( cObject *pcObject )
  325. {
  326. m_fDeadOrAlive = true;
  327. m_fCombatMode = false;
  328. m_dwCurrenthealth = m_dwMaxHealth;
  329. static BYTE bAnimate[8] = {
  330. 0x00, 0x00, 0x3D, 0x00, 0x00, 0xF0, 0xB5, 0x02,
  331. };
  332. m_dwUnknownCount = sizeof(bAnimate);
  333. CopyMemory( &m_bInitialAnimation[0], &bAnimate, 8);
  334. cWorldManager::MoveRemObject( this );
  335. SetLocation( m_SpawnLoc );
  336. cWorldManager::AddObject( this, true );
  337. SimpleAI::AddMonster( m_dwGUID );
  338. }
  339. void cMonster::MonsterCorpse( )
  340. {
  341. }
  342. cMessage cMonster::Animation( WORD wAnim, float flPlaySpeed)
  343. {
  344. // Animation Group 3 Event type
  345. cMessage cAnim;
  346. static BYTE bAnimate[] = {
  347. 0x4C, 0xF7, 0x00, 0x00, // Type
  348. 0x3F, 0x41, 0xD1, 0x0B, // dwGUID
  349. 0x00, 0x00, // numLogins
  350. 0x01, 0x00, // Sequence
  351. 0x01, 0x00, // numAnims
  352. 0x00, 0x00, // activity 0x0 - idle 0x1 - active
  353. 0x00, // Animation Type
  354. 0x00, // type Flags
  355. 0x3D, 0x00, // Stance Mode 0x3D standing
  356. 0x43, 0xE0, 0xB5, 0x02, // flags
  357. 0x3D, 0x00, // Stance Mode 2
  358. 0x00, 0x00, // Animation ID
  359. 0x00, 0x00, 0xC0, 0x3F, // flPlaySpeed (1.5)
  360. 0x79, 0xFA, 0x29, 0x01,
  361. };
  362. ++m_wCurAnim;
  363. ++m_wMeleeSequence;
  364. CopyMemory( &bAnimate[04], &m_dwGUID, 4 );
  365. CopyMemory( &bAnimate[8], &m_wNumLogins, 2 );
  366. CopyMemory( &bAnimate[10], &m_wCurAnim, 2 );
  367. CopyMemory( &bAnimate[12], &m_wMeleeSequence, 2 );
  368. CopyMemory( &bAnimate[26], &wAnim, 2 );
  369. CopyMemory( &bAnimate[28], &flPlaySpeed, 4 );
  370. cAnim.CannedData( bAnimate, sizeof( bAnimate ) );
  371. return cAnim;
  372. }
  373. /**
  374. * Handles functionality for when monster objects are physically attacked.
  375. *
  376. * This member function is called whenever a monster is physically attacked.
  377. *
  378. * @param *who - A pointer to the client physically attacking the monster.
  379. * @param flDamageSlider - The value of the client's damage slider.
  380. * @Param F7B0 Sequence - The given client's F7B0 sequence number.
  381. */
  382. void cMonster::Attack(cClient* who, float flDamageSlider, DWORD F7B0Sequence)
  383. {
  384. // This is for Combat Routines
  385. DWORD dwDamageType = 0x04;
  386. /*
  387. if (who->m_pcAvatar->myWeapon->m_fEquipped == 1)
  388. dwDamageType = who->m_pcAvatar->myWeapon->m_dwDamageType;
  389. */
  390. //cMessage Anim = who->m_pcAvatar->CombatAnimation( GetGUID() );
  391. cWorldManager::SendToAllInFocus( who->m_pcAvatar->m_Location, who->m_pcAvatar->CombatAnimation( GetGUID() ), 3 );
  392. WORD wTotalOpponentHealth = GetTotalHealth();
  393. DWORD dwDamage = who->m_pcAvatar->CalculateDamage( NULL, flDamageSlider, 0.0f );
  394. double dSeverity = ( double ) wTotalOpponentHealth / dwDamage;
  395. int iNewHealth;
  396. BOOL fKilledPlayer = FALSE;
  397. cMessage cmHealthLoss;
  398. m_dwCurrenthealth -= dwDamage;
  399. iNewHealth = m_dwCurrenthealth;
  400. double flHealthStat = ((( double )100/ m_dwMaxHealth)* m_dwCurrenthealth)/100;
  401. cmHealthLoss << 0xF7B0L
  402. << who->m_pcAvatar->GetGUID()
  403. << F7B0Sequence
  404. << 0x01C0L
  405. << m_dwGUID
  406. << float(flHealthStat);
  407. who->AddPacket( WORLD_SERVER, cmHealthLoss, 4 );
  408. if( iNewHealth <= 0 )
  409. {
  410. cMessage cmHealthLoss;
  411. //set health to 0
  412. m_dwCurrenthealth = 0;
  413. cmHealthLoss << 0xF7B0L
  414. << who->m_pcAvatar->GetGUID()
  415. << F7B0Sequence
  416. << 0x01C0L
  417. << m_dwGUID
  418. << float(flHealthStat);
  419. who->AddPacket( WORLD_SERVER, cmHealthLoss, 4 );
  420. //m_fDeadOrAlive = false;
  421. char szDeathNotice[200];
  422. wsprintf( szDeathNotice, "%s has killed %s", who->m_pcAvatar->m_strName.c_str(), m_strName.c_str( ) );
  423. //This line actually makes the monster not continue to fight:
  424. SimpleAI::RemoveMonster( m_dwGUID );
  425. //Death notice and animation
  426. cMessage cmDeathNotice;
  427. cmDeathNotice << 0xF62C << szDeathNotice << ColorGreen;
  428. cWorldManager::SendToAllInFocus( who->m_pcAvatar->m_Location, cmDeathNotice, 4 );
  429. cMessage cMonAnim = Animation( 0x11L, 1.5f );
  430. cWorldManager::SendToAllInFocus( who->m_pcAvatar->m_Location, cMonAnim, 3 );
  431. static BYTE bDead[12] = {
  432. 0x00, 0x00, 0x3D, 0x00, 0x02, 0xF0, 0xB5, 0x02, 0x11, 0x00, 0x00, 0x00,
  433. };
  434. m_dwUnknownCount = sizeof(bDead);
  435. CopyMemory( &m_bInitialAnimation[0], &bDead, 12);
  436. //cMasterServer::m_pcCorpse->AddCorpse(m_dwGUID,m_dwDecay,m_dwReSpawn);
  437. m_fDeadOrAlive = false;
  438. if(m_fDeadOrAlive == false)
  439. {
  440. //cMessage cmUpdateXP = who->m_pcAvatar->UpdateUnassignedExp(m_dwExp_Value);
  441. who->AddPacket( WORLD_SERVER, who->m_pcAvatar->UpdateUnassignedExp(m_dwExp_Value), 4 );
  442. who->m_pcAvatar->UpdateUnassignedXPDB(who,m_dwExp_Value);
  443. //Update DB Unassigned experience
  444. //char szCommand[100];
  445. //RETCODE retcode;
  446. //sprintf( szCommand, "UPDATE avatar set UnassignedXP = UnassignedXP + %i WHERE AvatarGUID = %lu;",m_dwExp_Value,who->m_pcAvatar->GetGUID( ));
  447. //retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  448. //retcode = SQLExecute( cDatabase::m_hStmt );
  449. //retcode = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  450. //retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  451. //cMessage cmUpdateXP2 = who->m_pcAvatar->UpdateTotalExp(m_dwExp_Value);
  452. who->AddPacket( WORLD_SERVER, who->m_pcAvatar->UpdateTotalExp(m_dwExp_Value), 4);
  453. who->m_pcAvatar->UpdateTotalXPDB(who,m_dwExp_Value);
  454. //Update DB Total experience
  455. //char szCommand2[100];
  456. //RETCODE retcode2;
  457. //sprintf( szCommand2, "UPDATE avatar set TotalXP = TotalXP + %i WHERE AvatarGUID = %lu;",m_dwExp_Value,who->m_pcAvatar->GetGUID( ));
  458. //retcode2 = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand2, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  459. //retcode2 = SQLExecute( cDatabase::m_hStmt );
  460. //retcode2 = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  461. //retcode2 = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  462. //check to see if we gained a level
  463. //cMessage cmUpdateLevel = who->m_pcAvatar->UpdateLevel();
  464. who->AddPacket( WORLD_SERVER, who->m_pcAvatar->UpdateLevel(), 4);
  465. who->m_pcAvatar->UpdateLevelDB(who);
  466. //Update level in DB
  467. //char szCommand3[100];
  468. // RETCODE retcode3;
  469. // sprintf( szCommand3, "UPDATE avatar set Level = %i WHERE AvatarGUID = %lu;",who->m_pcAvatar->m_cStats.m_dwLevel,who->m_pcAvatar->GetGUID( ));
  470. // retcode3 = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand3, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  471. // retcode3 = SQLExecute( cDatabase::m_hStmt );
  472. // retcode3 = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  473. // retcode3 = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  474. //Test to update Pyreals...seems to work.
  475. //cMessage GivePy = who->m_pcAvatar->UpdatePyreals(100,1);
  476. who->AddPacket( WORLD_SERVER, who->m_pcAvatar->UpdatePyreals(100,1), 4);
  477. cObject* pcMonster = cWorldManager::FindObject( m_dwGUID );
  478. cModels* pcModel = cModels::FindModel( m_dwMonsterModelID );
  479. if(pcModel)
  480. {
  481. char CorpseName[100];
  482. char KilledBy[255];
  483. //Name of the corpse
  484. sprintf(CorpseName,"Corpse of %s",pcMonster->m_strName.c_str( ));
  485. //Who killed it (its description)
  486. sprintf(KilledBy,"Killed by %s",who->m_pcAvatar->m_strName.c_str());
  487. cCorpse* moncor = new cCorpse(pcModel->m_dwModelNumber,cWorldManager::NewGUID_Object(),pcMonster->m_Location,CorpseName,KilledBy);
  488. moncor->SetData(pcModel->m_wAnimConfig,pcModel->m_wSoundSet,pcModel->m_wModel,WORD(0x1070),m_dwMonsterModelID,pcModel->m_flScale);
  489. //Add a copy of the monster as a corpse.
  490. cWorldManager::AddObject(moncor,true);
  491. //Make it disappear after 120 seconds.
  492. CorpseCleaner::AddCorpse(moncor->GetGUID(),120,0);
  493. //Remove the real monster
  494. cMessage cmRemModel;
  495. cmRemModel << 0xF747L << m_dwGUID << DWORD( 1 );
  496. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, cmRemModel, 3 );
  497. SimpleAI::RemoveMonster(m_dwGUID);
  498. cWorldManager::RemoveObject( pcMonster );
  499. }
  500. }
  501. SimpleAI::SetAttackComplete( m_dwGUID );
  502. }
  503. else
  504. {
  505. //cMessage cmDamageDoneMessage = who->m_pcAvatar->DoDamageMessage( ++who->m_dwF7B0Sequence, m_strName, dwDamageType, dSeverity, dwDamage);
  506. who->AddPacket( WORLD_SERVER, who->m_pcAvatar->DoDamageMessage( ++who->m_dwF7B0Sequence, m_strName, dwDamageType, dSeverity, dwDamage), 4 );
  507. //Cubem0j0: Reduce stamina for combat, this is a test NEED TO FINISH THIS :)
  508. int iShieldBurden = 200; //Will eventually be Shields actual burden units.
  509. int iWeaponBurden = 100; //Will eventually be weapons actual burden units.
  510. int iTrueBurden = (iWeaponBurden * 1.5 ) + iShieldBurden;
  511. int iNewStamina = who->m_pcAvatar->GetTotalStamina();
  512. switch(iTrueBurden)
  513. {
  514. case 0-220:
  515. {
  516. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(2,iNewStamina);
  517. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  518. }
  519. break;
  520. case 221-998:
  521. {
  522. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(3,iNewStamina);
  523. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  524. }
  525. break;
  526. case 999-1665:
  527. {
  528. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(4,iNewStamina);
  529. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  530. }
  531. break;
  532. case 1666-2355:
  533. {
  534. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(5,iNewStamina);
  535. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  536. }
  537. break;
  538. case 2356-3023:
  539. {
  540. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(6,iNewStamina);
  541. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  542. }
  543. break;
  544. case 3024-3450:
  545. {
  546. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(7,iNewStamina);
  547. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  548. }
  549. break;
  550. case 3451-4110:
  551. {
  552. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(8,iNewStamina);
  553. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  554. }
  555. break;
  556. default:
  557. {
  558. cMessage cmReduceStamina = who->m_pcAvatar->DecrementStamina(1,iNewStamina);
  559. who->AddPacket(WORLD_SERVER,cmReduceStamina,4);
  560. }
  561. break;
  562. }
  563. }
  564. }
  565. /**
  566. * Handles functionality for when spells are cast on monster objects.
  567. *
  568. * This member function is called whenever a spell is cast on a monster.
  569. *
  570. * @param *who - A pointer to the client who cast the spell.
  571. * @param *pcWarSpell - A pointer to the war spell cast by the client.
  572. * @param F7B0Sequence - The given client's F7B0 sequence number.
  573. */
  574. void cMonster::SpellAttack(cClient* who, cWarSpell* pcWarSpell, DWORD F7B0Sequence)
  575. {
  576. // This is for Spell Routines
  577. std::string strDamage1, strDamage2;
  578. cMagicModels *pcModel = cMagicModels::FindModel( pcWarSpell->m_dwSpellModel );
  579. cSpell *pcSpell = cSpell::FindSpell( pcWarSpell->m_dwSpellID );
  580. if (pcModel)
  581. {
  582. switch(pcModel->m_dwModelNumber)
  583. {
  584. case 0x03FC:
  585. {
  586. strDamage1 = "slice";
  587. strDamage2 = "slices";
  588. break;
  589. }
  590. case 0x03F3:
  591. {
  592. strDamage1 = "pierce";
  593. strDamage2 = "pierces";
  594. break;
  595. }
  596. case 0x03FA:
  597. {
  598. strDamage1 = "crush";
  599. strDamage2 = "crushes";
  600. break;
  601. }
  602. case 0x03F4:
  603. {
  604. strDamage1 = "freeze";
  605. strDamage2 = "freezes";
  606. break;
  607. }
  608. case 0x040D:
  609. {
  610. strDamage1 = "burn";
  611. strDamage2 = "burns";
  612. break;
  613. }
  614. case 0x03F6:
  615. {
  616. strDamage1 = "sear";
  617. strDamage2 = "sears";
  618. break;
  619. }
  620. case 0x03F0:
  621. {
  622. strDamage1 = "shock";
  623. strDamage2 = "shocks";
  624. break;
  625. }
  626. default:
  627. {
  628. strDamage1 = "hurt";
  629. strDamage2 = "hurts";
  630. break;
  631. }
  632. }
  633. }
  634. WORD wTotalOpponentHealth = GetTotalHealth();
  635. srand( timeGetTime( ) );
  636. int minDam = 61;
  637. int maxDam = 120;
  638. if (pcSpell)
  639. {
  640. switch(pcSpell->m_dwLevel)
  641. {
  642. case 1:
  643. {
  644. minDam = 8;
  645. maxDam = 15;
  646. break;
  647. }
  648. case 2:
  649. {
  650. minDam = 13;
  651. maxDam = 25;
  652. break;
  653. }
  654. case 3:
  655. {
  656. minDam = 18;
  657. maxDam = 35;
  658. break;
  659. }
  660. case 4:
  661. {
  662. minDam = 31;
  663. maxDam = 60;
  664. break;
  665. }
  666. case 5:
  667. {
  668. minDam = 46;
  669. maxDam = 90;
  670. break;
  671. }
  672. case 6:
  673. {
  674. minDam = 61;
  675. maxDam = 120;
  676. break;
  677. }
  678. case 7:
  679. {
  680. minDam = 110;
  681. maxDam = 180;
  682. break;
  683. }
  684. }
  685. }
  686. DWORD dwDamage = rand() % (maxDam-minDam) + minDam;
  687. double dSeverity = ( double ) wTotalOpponentHealth / dwDamage;
  688. int iNewHealth;
  689. BOOL fKilledPlayer = FALSE;
  690. cMessage cmHealthLoss;
  691. m_dwCurrenthealth -= dwDamage;
  692. if (m_dwCurrenthealth < 0)
  693. m_dwCurrenthealth = 0;
  694. iNewHealth = m_dwCurrenthealth;
  695. double flHealthStat = ((( double )100/ m_dwMaxHealth)* m_dwCurrenthealth)/100;
  696. cmHealthLoss << 0xF7B0L
  697. << who->m_pcAvatar->GetGUID()
  698. << F7B0Sequence
  699. << 0x01C0L
  700. << m_dwGUID
  701. << float(flHealthStat);
  702. who->AddPacket( WORLD_SERVER, cmHealthLoss, 4 );
  703. char szDamage1[200];
  704. char szDamage2[200];
  705. wsprintf( szDamage1, "You %s %s for %d points of damage with %s!", strDamage1.c_str(), m_strName.c_str(), dwDamage, pcSpell->m_strName.c_str() );
  706. wsprintf( szDamage2, "%s %s %s for %d points of damage!", who->m_pcAvatar->m_strName.c_str(), strDamage1.c_str(), m_strName.c_str(), dwDamage );
  707. cMessage cmDamage1;
  708. cMessage cmDamage2;
  709. cmDamage1 << 0xF62C << szDamage1 << ColorPink;
  710. cmDamage2 << 0xF62C << szDamage2 << ColorPink;
  711. who->AddPacket( WORLD_SERVER, cmDamage1, 4 );
  712. cWorldManager::SendToOthersInFocus( who->m_pcAvatar->m_Location, who, cmDamage2, 4 );
  713. //if the monster is killed
  714. if( iNewHealth <= 0 )
  715. {
  716. //This line actually makes the monster discontinue fighting
  717. SimpleAI::RemoveMonster( m_dwGUID );
  718. //Death notice and animation
  719. char szDeathNotice[200];
  720. char szDeathNotice2[200];
  721. wsprintf( szDeathNotice, "%s has killed %s!", who->m_pcAvatar->m_strName.c_str(), m_strName.c_str( ) );
  722. wsprintf( szDeathNotice2, "You have killed %s!", m_strName.c_str( ) );
  723. cMessage cmDeathNotice;
  724. cMessage cmDeathNotice2;
  725. cmDeathNotice << 0xF62C << szDeathNotice << ColorGreen;
  726. cmDeathNotice2 << 0xF62C << szDeathNotice2 << ColorGreen;
  727. cWorldManager::SendToOthersInFocus( who->m_pcAvatar->m_Location, who, cmDeathNotice, 4 );
  728. who->AddPacket( WORLD_SERVER, cmDeathNotice2, 4 );
  729. cMessage cMonAnim = Animation( 0x11L, 1.5f );
  730. cWorldManager::SendToAllInFocus( who->m_pcAvatar->m_Location, cMonAnim, 3 );
  731. static BYTE bDead[12] = {
  732. 0x00, 0x00, 0x3D, 0x00, 0x02, 0xF0, 0xB5, 0x02, 0x11, 0x00, 0x00, 0x00,
  733. };
  734. m_dwUnknownCount = sizeof(bDead);
  735. CopyMemory( &m_bInitialAnimation[0], &bDead, 12);
  736. //cMasterServer::m_pcCorpse->AddCorpse(m_dwGUID,m_dwDecay,m_dwReSpawn);
  737. m_fDeadOrAlive = false;
  738. if(m_fDeadOrAlive == false)
  739. {
  740. who->m_pcAvatar->UpdateHuntingExp(m_dwExp_Value);
  741. //Update DB Unassigned experience
  742. char szCommand[512];
  743. RETCODE retcode;
  744. sprintf( szCommand, "UPDATE avatar set UnassignedXP = UnassignedXP + %i WHERE AvatarGUID = %lu;",m_dwExp_Value,who->m_pcAvatar->GetGUID( ));
  745. retcode = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  746. retcode = SQLExecute( cDatabase::m_hStmt );
  747. retcode = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  748. retcode = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  749. cMessage cmUpdateXP2 = who->m_pcAvatar->UpdateTotalExp(m_dwExp_Value);
  750. who->AddPacket( WORLD_SERVER, cmUpdateXP2, 4);
  751. //Update DB Total experience
  752. char szCommand2[512];
  753. RETCODE retcode2;
  754. sprintf( szCommand2, "UPDATE avatar set TotalXP = TotalXP + %i WHERE AvatarGUID = %lu;",m_dwExp_Value,who->m_pcAvatar->GetGUID( ));
  755. retcode2 = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand2, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  756. retcode2 = SQLExecute( cDatabase::m_hStmt );
  757. retcode2 = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  758. retcode2 = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  759. //check to see if we gained a level
  760. cMessage cmUpdateLevel = who->m_pcAvatar->UpdateLevel();
  761. who->AddPacket( WORLD_SERVER, cmUpdateLevel, 4);
  762. //Update level in DB
  763. char szCommand3[512];
  764. RETCODE retcode3;
  765. sprintf( szCommand3, "UPDATE avatar set Level = %i WHERE AvatarGUID = %lu;",who->m_pcAvatar->m_cStats.m_dwLevel,who->m_pcAvatar->GetGUID( ));
  766. retcode3 = SQLPrepare( cDatabase::m_hStmt, (unsigned char *)szCommand3, SQL_NTS ); CHECKRETURN(1, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  767. retcode3 = SQLExecute( cDatabase::m_hStmt );
  768. retcode3 = SQLCloseCursor( cDatabase::m_hStmt ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  769. retcode3 = SQLFreeStmt( cDatabase::m_hStmt, SQL_UNBIND ); CHECKRETURN(0, SQL_HANDLE_STMT, cDatabase::m_hStmt, NULL)
  770. //Test to update Pyreals...seems to work.
  771. cMessage GivePy = who->m_pcAvatar->UpdatePyreals(100,1);
  772. who->AddPacket( WORLD_SERVER, GivePy, 4);
  773. // It works :)
  774. cMonsterDeathParam* MonsterDeathParam = new cMonsterDeathParam( m_dwGUID, m_dwMonsterModelID, who->m_pcAvatar->GetGUID() );
  775. int iJob = cMasterServer::m_pcJobPool->CreateJob( &cMonster::DeathAnimation, (LPVOID) MonsterDeathParam, NULL, "MonsterDeath", 20, 1 );
  776. }
  777. SimpleAI::SetAttackComplete( m_dwGUID );
  778. }
  779. }
  780. /**
  781. * Handles the death animation for a killed monster.
  782. */
  783. int cMonster::DeathAnimation( LPVOID wp, LPVOID lp )
  784. {
  785. cMonsterDeathParam* MonsterDeathParam = (cMonsterDeathParam *) wp;
  786. cObject* pcMonster = cWorldManager::FindObject( MonsterDeathParam->GetMonsterGUID() );
  787. cModels* pcModel = cModels::FindModel( MonsterDeathParam->GetMonsterModelID() );
  788. cClient* pcClient = cClient::FindClient( MonsterDeathParam->GetClientGUID() );
  789. if(pcModel)
  790. {
  791. char CorpseName[100];
  792. char KilledBy[255];
  793. //Name of the corpse
  794. sprintf(CorpseName,"Corpse of %s",pcMonster->m_strName.c_str( ));
  795. //Who killed it (it's description)
  796. sprintf(KilledBy,"Killed by %s",pcClient->m_pcAvatar->m_strName.c_str());
  797. cCorpse* moncor = new cCorpse(pcModel->m_dwModelNumber,cWorldManager::NewGUID_Object(),pcMonster->m_Location,CorpseName,KilledBy);
  798. moncor->SetData(pcModel->m_wAnimConfig,pcModel->m_wSoundSet,pcModel->m_wModel,WORD(0x1070),MonsterDeathParam->GetMonsterModelID(),pcModel->m_flScale);
  799. //Add a copy of the monster as a corpse.
  800. cWorldManager::AddObject(moncor,true);
  801. //Make it disappear after 120 seconds.
  802. CorpseCleaner::AddCorpse(moncor->GetGUID(),120,0);
  803. //Remove the real monster
  804. cMessage cmRemModel;
  805. cmRemModel << 0xF747L << MonsterDeathParam->GetMonsterGUID() << DWORD( 1 );
  806. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, cmRemModel, 3 );
  807. SimpleAI::RemoveMonster(MonsterDeathParam->GetMonsterGUID());
  808. cWorldManager::RemoveObject( pcMonster );
  809. }
  810. SAFEDELETE( MonsterDeathParam )
  811. return -1;
  812. }
  813. /**
  814. * Handles the actions of monster objects.
  815. *
  816. * This member function is called whenever a monster should perform an action.
  817. */
  818. void cMonster::Action(cClient* who)
  819. {
  820. // Need to figure out action types for Monsters
  821. cMessage cmActionComplete;
  822. cmActionComplete << 0xF7B0L << who->m_pcAvatar->GetGUID( ) << ++who->m_dwF7B0Sequence << 0x01C7L << 0L;
  823. who->AddPacket(WORLD_SERVER,cmActionComplete,4);
  824. }
  825. /**
  826. * Handles the assessment of monster objects.
  827. *
  828. * This member function is called whenever a monster is assessed by a client.
  829. * Returns a Game Event (0x0000F7B0) server message of type Identify Object (0x000000C9).
  830. */
  831. void cMonster::Assess(cClient *pcAssesser)
  832. {
  833. cMessage cmAssess;
  834. WORD wAnimation;
  835. wAnimation = 0x54L;
  836. int iRand = rand();
  837. iRand = (iRand > 6400) ? iRand % 6400 : iRand;
  838. iRand = (iRand < 1600) ? 1600 + iRand : iRand;
  839. iRand = iRand/2500;
  840. DWORD dwSuccess;
  841. if(iRand > 1)
  842. {
  843. dwSuccess = 0x1L;
  844. }
  845. else
  846. {
  847. dwSuccess = 0x0L;
  848. }
  849. DWORD dwCharacterFlags; // Needs Decoding
  850. dwCharacterFlags = 0x0CL; // 0x04 - Level, Health | 0x08 - Stats
  851. cmAssess << 0xF7B0L
  852. << pcAssesser->m_pcAvatar->GetGUID( )
  853. << ++pcAssesser->m_dwF7B0Sequence
  854. << 0xC9L
  855. << m_dwGUID
  856. << 0x100L // Flags 0x00000100 - Character Data
  857. << dwSuccess;//0x1L;
  858. cModels *pcModel = cModels::FindModel( m_dwMonsterModelID );
  859. if( pcModel )
  860. {
  861. m_dwSpecies = pcModel->m_dwSpecies;
  862. }
  863. // Process the Flag Specified Data
  864. cmAssess << dwCharacterFlags
  865. // Mask 0x04
  866. << m_dwLevel
  867. << m_dwCurrenthealth
  868. << m_dwMaxHealth
  869. // Mask 0x08
  870. << m_dwStr
  871. << m_dwEnd
  872. << m_dwQuick
  873. << m_dwCoord
  874. << m_dwFocus
  875. << m_dwSelf
  876. << m_dwCurrentStamina
  877. << m_dwCurrentMana
  878. << m_dwMaxStamina
  879. << m_dwMaxMana
  880. // End Mask
  881. << m_dwSpecies;
  882. pcAssesser->AddPacket(WORLD_SERVER,cmAssess,4);
  883. // The Action has been completed
  884. cMessage cmActionComplete;
  885. cmActionComplete << 0xF7B0L << pcAssesser->m_pcAvatar->GetGUID( ) << ++pcAssesser->m_dwF7B0Sequence << 0x01C7L << 0L;
  886. pcAssesser->AddPacket(WORLD_SERVER,cmActionComplete,4);
  887. }
  888. /**
  889. * Handles the message sent for clients' melee attacking of monsters.
  890. *
  891. * This member function is called whenever a client physically attacks a monster.
  892. * @return cMessage - Returns a Game Event (0x0000F7B0) server message of type Inflict Melee damage (0x000001B1).
  893. */
  894. cMessage cMonster::DoDamageMessage(DWORD F7B0seq,std::string target,DWORD damagetype,double severity,DWORD amount)
  895. {
  896. cMessage cmRet;
  897. cmRet << 0xF7B0L << m_dwGUID << F7B0seq << 0x01B1L << target.c_str() << damagetype << severity << amount;
  898. return cmRet;
  899. }
  900. /**
  901. * Handles the message sent for the melee attacking of clients by monsters.
  902. *
  903. * This member function is called whenever a client is physically attacked by a monster.
  904. * @return cMessage - Returns a Game Event (0x0000F7B0) server message of type Receieve Melee damage (0x000001B2).
  905. */
  906. cMessage cMonster::RecieveDamageMessage(DWORD F7B0seq,std::string giver,DWORD damagetype,double severity,DWORD amount,DWORD location)
  907. {
  908. cMessage cmRet;
  909. cmRet << 0xF7B0L << m_dwGUID << F7B0seq << 0x01B2L << giver.c_str() << damagetype << severity << amount << location;
  910. return cmRet;
  911. }
  912. /**
  913. * Handles the message sent for the updating of creatures' health bars.
  914. *
  915. * This member function is called whenever a monster's health should be updated for a client.
  916. * @return cMessage - Returns a Game Event (0x0000F7B0) server message of type Update Health (0x000001C0).
  917. */
  918. cMessage cMonster::DecrementHealth(DWORD dwGUID, WORD amount,signed int &newhealth)
  919. {
  920. m_dwCurrenthealth -= amount;
  921. newhealth = m_dwCurrenthealth;
  922. cMessage cmRet;
  923. //cmRet << 0xF7B0L << m_dwGUID << F7B0seq << 0x1C0L << m_dwGUID << static_cast<float> (m_dwCurrenthealth);
  924. return cmRet;
  925. }
  926. cMessage cMonster::SetHealth(DWORD dwNewHealth)
  927. {
  928. m_dwCurrenthealth = static_cast<signed int>(dwNewHealth);
  929. cMessage cmRet;
  930. cmRet << 0x244L << m_bStatSequence++ << 0x2L << dwNewHealth;
  931. return cmRet;
  932. }
  933. /**
  934. * Handles the message sent for the setting of creatures' health bars.
  935. *
  936. * This member function is called when a monster's health should be altered for a client.
  937. * @return cMessage - Returns a Game Event (0x0000F7B0) server message of type Update Health (0x000001C0).
  938. */
  939. cMessage cMonster::AdjustBar(DWORD dwGUID, DWORD F7B0Sequence )
  940. {
  941. cMessage cmHealthLoss;
  942. double flHealthStat = ((( double )100/ m_dwMaxHealth)* m_dwCurrenthealth)/100;
  943. cmHealthLoss << 0xF7B0L << dwGUID << F7B0Sequence << 0x01C0L << m_dwGUID << float(flHealthStat);
  944. return cmHealthLoss;
  945. }
  946. cMessage cMonster::ChangeCombatMode(bool fMode )
  947. {
  948. cMessage cmRet;
  949. cModels *pcModel = cModels::FindModel( m_dwMonsterModelID );
  950. unsigned char Canim4 [] = {
  951. 0x4C, 0xF7, 0x00, 0x00, // 00 - 03
  952. 0xE6, 0xD2, 0x09, 0x50, // 04 - 07
  953. 0x3D, 0x00, 0x07, 0x00, // 08 - 11
  954. 0x01, 0x00, 0x00, 0x00, // 12 - 15
  955. 0x00, 0x00, 0x3C, 0x00, // 16 - 19
  956. 0x01, 0x00, 0x00, 0x00, // 20 - 23
  957. 0x3C, 0x00, 0x00, 0x00, // 24 - 27
  958. };
  959. CopyMemory(&Canim4[4],&m_dwGUID,4);
  960. CopyMemory( &Canim4[8], &m_wNumLogins, 2 );
  961. m_wCurAnim++;
  962. CopyMemory(&Canim4[10],&m_wCurAnim,2);
  963. m_wMeleeSequence++;
  964. CopyMemory(&Canim4[12],&m_wMeleeSequence,2);
  965. //CopyMemory(&Canim4[24],&pcModel->m_cAnimations.m_wStance[int(fMode)],2);
  966. cmRet.pasteData(Canim4,sizeof(Canim4));
  967. return cmRet;
  968. }
  969. cMessage cMonster::CombatAnimation(DWORD dwTarget, WORD wAttackAnim )
  970. {
  971. cMessage cmRet;
  972. unsigned char Canimation [] = {
  973. 0x4C, 0xF7, 0x00, 0x00,
  974. 0xE6, 0xD2, 0x09, 0x50, // object
  975. 0x3C, 0x00, 0x18, 0x00, // numLogins, sequence
  976. 0x03, 0x00, 0x00, 0x00, // numAnims, activity
  977. 0x00, 0x01, 0x00, 0x00, // Anim type, type flag
  978. 0xC1, 0x80, 0x99, 0xB1,
  979. 0x63, 0x00, 0x00, 0x00,
  980. 0x60, 0x00, 0x60, 0x00,
  981. 0x01, 0x00, 0xE4, 0x38,
  982. 0x8E, 0x3F, 0x00, 0x00,
  983. 0x20, 0x8B, 0x99, 0xB1, // dwTarget
  984. };
  985. CopyMemory(&Canimation[4],&m_dwGUID,4);
  986. CopyMemory( &Canimation[8], &m_wNumLogins, 2 );
  987. m_wCurAnim++;
  988. CopyMemory(&Canimation[10],&m_wCurAnim,2);
  989. m_wMeleeSequence++;
  990. CopyMemory(&Canimation[12],&m_wMeleeSequence,2);
  991. CopyMemory(&Canimation[0x28],&dwTarget,4);
  992. CopyMemory(&Canimation[0x20],&m_wCurAnim,2);
  993. CopyMemory(&Canimation[24],&wAttackAnim,2);
  994. cmRet.pasteData(Canimation,sizeof(Canimation));
  995. return cmRet;
  996. }
  997. cMessage cMonster::TurnToTarget( float flHeading, DWORD dwTargetGUID )
  998. {
  999. cMessage cmTurnToTarget;
  1000. cmTurnToTarget << 0xF74CL
  1001. << m_dwGUID
  1002. << m_wNumLogins
  1003. << ++m_wCurAnim
  1004. << ++m_wMeleeSequence
  1005. << WORD(0x0000)
  1006. << BYTE(0x08)
  1007. << BYTE(0x00)
  1008. << WORD(0x003D)
  1009. << dwTargetGUID
  1010. << flHeading
  1011. << 0x1139EE0F
  1012. << 1.0f
  1013. << 0x00000000;
  1014. return cmTurnToTarget;
  1015. }
  1016. cMessage cMonster::MoveToTarget( cClient *pcWho )
  1017. {
  1018. // pcWho is the target client
  1019. cMessage cmMoveToTarget;
  1020. float flDistance;
  1021. float flHeadingTarget;
  1022. DWORD dwFlags;
  1023. dwFlags = 0x1279EFF0;
  1024. flHeadingTarget = GetHeadingTarget( pcWho->m_pcAvatar->m_Location.m_dwLandBlock,pcWho->m_pcAvatar->m_Location.m_flX,pcWho->m_pcAvatar->m_Location.m_flY,pcWho->m_pcAvatar->m_Location.m_flZ);
  1025. flDistance = GetRange( pcWho->m_pcAvatar->m_Location.m_dwLandBlock, pcWho->m_pcAvatar->m_Location.m_flX, pcWho->m_pcAvatar->m_Location.m_flY, pcWho->m_pcAvatar->m_Location.m_flZ );
  1026. cmMoveToTarget << 0xF74CL
  1027. << m_dwGUID
  1028. << m_wNumLogins
  1029. << ++m_wCurAnim
  1030. << ++m_wMeleeSequence
  1031. << WORD(0x0000)
  1032. << BYTE(0x06)
  1033. << BYTE(0x00)
  1034. << WORD(0x003E);
  1035. // Who/Where we are Moving to
  1036. cmMoveToTarget << pcWho->m_pcAvatar->GetGUID( )
  1037. << m_Location.m_dwLandBlock
  1038. << m_Location.m_flX
  1039. << m_Location.m_flY
  1040. << m_Location.m_flZ
  1041. << dwFlags
  1042. << 0.0f
  1043. << 0.1f
  1044. << 75.0f
  1045. << 1.0f
  1046. << 15.0f
  1047. << flHeadingTarget
  1048. << 1.8201754f;
  1049. //cLocation tempLoc;
  1050. //tempLoc = EstimateLoc(flHeadingTarget,10,flDistance,2.0f);
  1051. //cWorldManager::MoveRemObject( this );
  1052. //SetLocation(tempLoc.m_dwLandBlock,tempLoc.m_flX,tempLoc.m_flY,tempLoc.m_flZ,tempLoc.m_flA,tempLoc.m_flW);
  1053. //cWorldManager::MoveAddObject( this );
  1054. //flDistance = GetRange( pcWho->m_pcAvatar->m_Location.m_dwLandBlock, pcWho->m_pcAvatar->m_Location.m_flX, pcWho->m_pcAvatar->m_Location.m_flY, pcWho->m_pcAvatar->m_Location.m_flZ );
  1055. //char Command2[100];
  1056. //sprintf(Command2,"Range After Move: %f \r\n",flDistance);
  1057. //UpdateConsole(Command2);
  1058. return cmMoveToTarget;
  1059. }
  1060. //////////////////////
  1061. cMessage cMonster::MoveTarget( cClient *pcWho )
  1062. {
  1063. // pcWho is the target client
  1064. cMessage cmMoveToTarget;
  1065. float flHeadingTarget;
  1066. DWORD dwFlags;
  1067. dwFlags = 0x1279EFF0;
  1068. flHeadingTarget = GetHeadingTarget(pcWho->m_pcAvatar->m_Location.m_dwLandBlock,pcWho->m_pcAvatar->m_Location.m_flX,pcWho->m_pcAvatar->m_Location.m_flY,pcWho->m_pcAvatar->m_Location.m_flZ);
  1069. cmMoveToTarget << 0xF74CL
  1070. << m_dwGUID
  1071. << m_wNumLogins
  1072. << ++m_wCurAnim
  1073. << ++m_wMeleeSequence
  1074. << WORD(0x0000)
  1075. << BYTE(0x06)
  1076. << BYTE(0x00)
  1077. << WORD(0x003E);
  1078. cmMoveToTarget << pcWho->m_pcAvatar->GetGUID( )
  1079. << pcWho->m_pcAvatar->m_Location.m_dwLandBlock
  1080. << pcWho->m_pcAvatar->m_Location.m_flX
  1081. << pcWho->m_pcAvatar->m_Location.m_flY
  1082. << pcWho->m_pcAvatar->m_Location.m_flZ
  1083. << dwFlags
  1084. << 0.0f
  1085. << 0.1f
  1086. << 75.0f
  1087. << 1.0f
  1088. << 15.0f
  1089. << flHeadingTarget
  1090. << 1.8201754f;
  1091. cLocation tempLoc;
  1092. //cWorldManager::MoveRemObject( this );
  1093. //SetLocation(&pcWho->m_pcAvatar->m_Location);
  1094. //cWorldManager::MoveAddObject( this );
  1095. return cmMoveToTarget;
  1096. }
  1097. //////////////////////////////////////////////
  1098. cMessage cMonster::ReturnToSpawn( )
  1099. {
  1100. cMessage cmReturnToSpawn;
  1101. float flHeadingTarget = 0.0f;
  1102. DWORD dwFlags;
  1103. float flDistance = 1.0f;
  1104. dwFlags = 0x1291EE0F;
  1105. flHeadingTarget = GetHeadingTarget(m_SpawnLoc.m_dwLandBlock,m_SpawnLoc.m_flX,m_SpawnLoc.m_flY,m_SpawnLoc.m_flZ);
  1106. flDistance = GetRange(m_SpawnLoc.m_dwLandBlock, m_SpawnLoc.m_flX, m_SpawnLoc.m_flY, m_SpawnLoc.m_flZ );
  1107. cLocation tempLoc;
  1108. tempLoc = EstimateLoc(flHeadingTarget,10,flDistance,2.5f);
  1109. cmReturnToSpawn << 0xF74CL
  1110. << m_dwGUID
  1111. << m_wNumLogins
  1112. << ++m_wCurAnim
  1113. << ++m_wMeleeSequence
  1114. << WORD(0x0000)
  1115. << BYTE(0x07)
  1116. << BYTE(0x00)
  1117. << WORD(0x003D);
  1118. // Animation Type 0x07
  1119. cmReturnToSpawn << tempLoc.m_dwLandBlock
  1120. << tempLoc.m_flX
  1121. << tempLoc.m_flY
  1122. << tempLoc.m_flZ
  1123. << dwFlags
  1124. << 0.0f
  1125. << 1.0f
  1126. << DWORD(0x7F7FFFFF)
  1127. << 0.8f // Speed
  1128. << 5.0f
  1129. << flHeadingTarget
  1130. << 1.5f;//1.6346154f;
  1131. //cWorldManager::MoveRemObject( this );
  1132. //SetLocation(tempLoc.m_dwLandBlock,tempLoc.m_flX,tempLoc.m_flY,tempLoc.m_flZ,tempLoc.m_flA,tempLoc.m_flW);
  1133. //cWorldManager::MoveAddObject( this );
  1134. //flDistance = GetRange(m_SpawnLoc.m_dwLandBlock, m_SpawnLoc.m_flX, m_SpawnLoc.m_flY, m_SpawnLoc.m_flZ ); char Command2[100];
  1135. //sprintf(Command2,"Range After Move: %f \r\n",flDistance);
  1136. //UpdateConsole(Command2);
  1137. return cmReturnToSpawn;
  1138. }
  1139. cMessage cMonster::SetPosition()
  1140. {
  1141. cMessage cmSetPosition;
  1142. DWORD dwFlags = 0x34L;
  1143. cmSetPosition << 0xF748L
  1144. << m_dwGUID
  1145. << 0x34L;
  1146. cmSetPosition << m_Location.m_dwLandBlock
  1147. << m_Location.m_flX
  1148. << m_Location.m_flY
  1149. << m_Location.m_flZ
  1150. << m_Location.m_flA
  1151. //<< m_Location.m_flB
  1152. //<< m_Location.m_flC
  1153. << m_Location.m_flW;
  1154. return cmSetPosition;
  1155. }