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

cMonsterServer.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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 cMonsterServer.cpp
  19. * Implements functionality for the cMonsterServer class.
  20. * Processes monster actions and sends the data to the client.
  21. *
  22. * Author: G70mb2
  23. */
  24. #include "cMonsterServer.h"
  25. #include "WorldManager.h"
  26. #include "MasterServer.h"
  27. #include <algorithm>
  28. DWORD cMonsterServer::m_dwStatus;
  29. time_t cMonsterServer::longtime;
  30. time_t cMonsterServer::NextActionTime;
  31. /**
  32. * Processes monster actions.
  33. *
  34. * This member function is called when a monster is set to perform a given action.
  35. * It processess the actual packets that will be delivered based upon the input values. @see SimpleAI
  36. * Inputs determine whether the monster state: idle, under attack, move to attacker,
  37. * there is a user within range, attack users, break off attack, change combat mode.
  38. *
  39. * @param dwMonGUID - The GUID of the monstser to perform an action
  40. * @param dwEvent - A numerical value represention the monster's current state.
  41. * @param dwEngaged -
  42. * @param dwTarget - The GUID of the target for the monster to attack.
  43. */
  44. void cMonsterServer::ProcessAction( DWORD dwMonGUID, DWORD dwEvent, DWORD dwEngaged, DWORD dwTarget )
  45. {
  46. cObject *pcMonster = cWorldManager::FindObject( dwMonGUID );
  47. if(pcMonster) // If not a valid Monster Object, do nothing
  48. {
  49. cModels* pcModel = cModels::FindModel( pcMonster->GetMonsterModelID() );
  50. int iRand = rand();
  51. int iRand2 = rand();
  52. iRand = iRand + iRand2;
  53. iRand = (iRand > 6400) ? iRand % 6400 : iRand;
  54. iRand = (iRand < 1600) ? 1600 + iRand : iRand;
  55. if( pcModel )
  56. {
  57. switch( dwEvent )
  58. {
  59. case 0x0: // Idle
  60. {
  61. WORD wAnimation;
  62. int IdleAnim = iRand/1000;
  63. switch( IdleAnim )
  64. {
  65. case 0:
  66. {
  67. wAnimation = pcModel->m_cAnimations.m_wIdle[0];
  68. pcMonster->m_bIdleAnim++;
  69. break;
  70. }
  71. case 1:
  72. {
  73. wAnimation = pcModel->m_cAnimations.m_wIdle[1];//0x53L;
  74. pcMonster->m_bIdleAnim++;
  75. break;
  76. }
  77. case 2:
  78. {
  79. wAnimation = pcModel->m_cAnimations.m_wIdle[2];//0x52L;
  80. pcMonster->m_bIdleAnim++;
  81. break;
  82. }
  83. case 3:
  84. {
  85. wAnimation = pcModel->m_cAnimations.m_wIdle[3];//0x50L;
  86. pcMonster->m_bIdleAnim++;
  87. break;
  88. }
  89. case 4:
  90. {
  91. wAnimation = pcModel->m_cAnimations.m_wIdle[4];//0x53L;
  92. pcMonster->m_bIdleAnim++;
  93. break;
  94. }
  95. case 5:
  96. {
  97. wAnimation = pcModel->m_cAnimations.m_wIdle[5];//0x52L;
  98. pcMonster->m_bIdleAnim = 0;
  99. break;
  100. }
  101. }
  102. //cMessage cMonAnim = pcMonster->Animation( wAnimation, 1.0f );
  103. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->Animation( wAnimation, 1.0f ), 3 );
  104. break;
  105. }
  106. case 0x1: // Under attack
  107. {
  108. float flHeading, flDistance;
  109. cClient* pcTargetObj = cClient::FindClient( dwTarget );
  110. if( pcTargetObj)
  111. {
  112. flHeading = pcMonster->GetHeadingTarget( pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  113. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->TurnToTarget(flHeading,dwTarget ), 3 );
  114. }
  115. flDistance = pcMonster->GetRange( pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  116. if ( flDistance < 0.8f)
  117. {
  118. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  119. }
  120. else
  121. {
  122. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 2, 1 );
  123. }
  124. break;
  125. }
  126. case 0x2: // Move to attacker
  127. {
  128. float flDistance;
  129. cClient* pcTargetObj = cClient::FindClient( dwTarget );
  130. cMonster* pcMon = (cMonster *) pcMonster;
  131. pcMon->m_fHasTarget = false;
  132. if( pcTargetObj)
  133. {
  134. pcMon->m_fHasTarget = true;
  135. pcMon->m_dwTargetGUID = dwTarget;
  136. SimpleAI::SetMoving( pcMonster->GetGUID() );
  137. flDistance = pcMonster->GetRange(pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  138. if ( flDistance < 1.0f )
  139. {
  140. //cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->MoveTarget( pcTargetObj ), 3 );
  141. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  142. //pcMonster->SetLocation(&pcTargetObj->m_pcAvatar->m_Location);
  143. }
  144. else
  145. {
  146. // Break off the chase if target is too far away
  147. if(flDistance > 3)//pcMonster->m_dwChase )
  148. {
  149. SimpleAI::SetAttackComplete( dwMonGUID );
  150. SimpleAI::SetAction( dwMonGUID, 3, 0);
  151. }
  152. else
  153. {
  154. SimpleAI::SetAttackEvent( dwMonGUID,dwTarget, 2, 3 );
  155. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->MoveToTarget( pcTargetObj ), 3 );
  156. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  157. }
  158. }
  159. }
  160. else
  161. {
  162. SimpleAI::SetAction( dwMonGUID, 0, 2);
  163. }
  164. break;
  165. }
  166. case 0x3: // Return to spawn point
  167. {
  168. float flDistance;
  169. flDistance = pcMonster->GetRange( pcMonster->m_SpawnLoc.m_dwLandBlock, pcMonster->m_SpawnLoc.m_flX, pcMonster->m_SpawnLoc.m_flY, pcMonster->m_SpawnLoc.m_flZ );
  170. if(( flDistance > 0.4f )&&( flDistance < pcMonster->m_dwChase))
  171. {
  172. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->ReturnToSpawn( ), 3 );
  173. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  174. SimpleAI::SetAction( dwMonGUID, 3, 4);
  175. }
  176. else if(flDistance > pcMonster->m_dwChase)
  177. {
  178. // Jump back to spawn point
  179. cWorldManager::MoveRemObject( pcMonster );
  180. pcMonster->SetLocation(&pcMonster->m_SpawnLoc);
  181. cWorldManager::MoveAddObject( pcMonster );
  182. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  183. SimpleAI::SetAction( dwMonGUID, 0, 1 );
  184. }
  185. else
  186. {
  187. SimpleAI::SetAction( dwMonGUID, 0, 1 );
  188. }
  189. break;
  190. }
  191. case 0x4: // There is a user within range
  192. {
  193. SimpleAI::SetAction( dwMonGUID, 2, 3 );
  194. break;
  195. }
  196. case 0x5: // Attack user
  197. {
  198. DWORD dwDamageType = 0x4;
  199. float flDamageSlider = rand() % 2;
  200. float intRange;
  201. int AttackAnim = iRand/1000;
  202. WORD wAttackAnim;
  203. switch( AttackAnim )
  204. {
  205. case 0:
  206. {
  207. wAttackAnim = pcModel->m_cAnimations.m_wAttack[0];
  208. /*
  209. #ifdef _DEBUG
  210. char szPacketA[120];
  211. sprintf( szPacketA, "Attack Animation #: %d",AttackAnim);
  212. cMasterServer::ServerMessage( ColorBlue,NULL,(char *)szPacketA);
  213. #endif
  214. */
  215. break;
  216. }
  217. case 1:
  218. {
  219. wAttackAnim = pcModel->m_cAnimations.m_wAttack[1];
  220. break;
  221. }
  222. case 2:
  223. {
  224. wAttackAnim = pcModel->m_cAnimations.m_wAttack[2];
  225. break;
  226. }
  227. case 3:
  228. {
  229. wAttackAnim = pcModel->m_cAnimations.m_wAttack[3];
  230. break;
  231. }
  232. case 4:
  233. {
  234. wAttackAnim = pcModel->m_cAnimations.m_wAttack[4];
  235. break;
  236. }
  237. case 5:
  238. {
  239. wAttackAnim = pcModel->m_cAnimations.m_wAttack[5];
  240. break;
  241. }
  242. }
  243. cClient* pcTargetObj = cClient::FindClient( dwTarget );
  244. cMonster* pcMon = (cMonster *) pcMonster;
  245. pcMon->m_fHasTarget = false;
  246. if( pcTargetObj)
  247. {
  248. pcMon->m_fHasTarget = true;
  249. pcMon->m_dwTargetGUID = dwTarget;
  250. SimpleAI::SetMoving( pcMonster->GetGUID() );
  251. // Check range to target
  252. intRange = pcMonster->GetRange( pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  253. if( intRange < 1.5f)
  254. {
  255. //Take a swing
  256. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->ChangeCombatMode( false ), 3 );
  257. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->CombatAnimation( dwTarget,wAttackAnim ), 3 );
  258. WORD wTotalOpponentHealth = pcTargetObj->m_pcAvatar->GetTotalHealth();
  259. //Now perform a very basic combat calculation..nowhere near accurate.
  260. srand( timeGetTime( ) );
  261. float flMaxDamage = rand( )/27;
  262. //Cubem0j0: Add strength to the monster's attack damage.
  263. //float mob_damage = pcModel->mob_strength / 2.5;
  264. DWORD dwTrueDamage = pcMonster->CalculateDamage(pcModel->mob_strength / pcTargetObj->m_pcAvatar->ALDamageReduction(pcTargetObj->m_pcAvatar->Armor_Level), 3.0f, 3.0f);
  265. double dSeverity = ( double ) wTotalOpponentHealth / dwTrueDamage;
  266. /* CubeM0j0: Adjust for AL */
  267. UINT dwTrue2 = dwTrueDamage;
  268. //if(dwTrue2 < 0)
  269. // dwTrue2 = 0;
  270. int iNewHealth;
  271. //CubeM0j0: Check to see what the new numbers are.
  272. //#ifdef _DEBUG
  273. // char szPacketA[100];
  274. // sprintf( szPacketA, "dwTrueDamage: %d, dwTrue2: %d, Severity: %d",dwTrueDamage,dwTrue2,dSeverity);
  275. // cMasterServer::ServerMessage( ColorGreen,NULL,(char *)szPacketA);
  276. //#endif
  277. BOOL fKilledPlayer = FALSE;
  278. //Following variable(s) only used if there is a kill
  279. cMessage cmAnim;
  280. cMessage cmHealthLoss = pcTargetObj->m_pcAvatar->DecrementHealth( dwTrue2, iNewHealth );
  281. pcTargetObj->AddPacket( WORLD_SERVER, cmHealthLoss, 4 );
  282. if( iNewHealth <= 0 )
  283. {
  284. fKilledPlayer = TRUE;
  285. //cMessage cmKill = pcTargetObj->m_pcAvatar->SetHealth( pcTargetObj->m_pcAvatar->GetTotalHealth( ) );
  286. //cMessage Anim = pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE, 0 );
  287. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE, 0 ), 3 );
  288. //cMessage cAnim = pcTargetObj->m_pcAvatar->Animation( pcModel->m_cAnimations.m_wAttack[0], 2.0f );
  289. cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, pcTargetObj->m_pcAvatar->Animation( pcModel->m_cAnimations.m_wAttack[0], 2.0f ), 3 );
  290. cMasterServer::Corpse( pcTargetObj );
  291. //cMessage Alive = pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE, 0 );
  292. cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE, 0 ), 3 );
  293. cWorldManager::TeleportAvatar( pcTargetObj, cMasterServer::m_StartingLoc );
  294. cMasterServer::ServerMessage( ColorGreen, pcTargetObj, "You have been restored to Health." );
  295. // cMessage cmSetFlag;
  296. // cmSetFlag << 0x022CL << BYTE(0) << pcTargetObj->m_pcAvatar->GetGUID() << 0x04L << 0;
  297. // cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, cmSetFlag, 4 );
  298. // pcTargetObj->m_pcAvatar->m_fIsPK = false;
  299. char szDeathNotice[200];
  300. wsprintf( szDeathNotice, "%s has killed %s", pcMonster->m_strName.c_str(), pcTargetObj->m_pcAvatar->m_strName.c_str( ) );
  301. // cMessage cmDeathNotice;
  302. // cmDeathNotice << 0xF62C << szDeathNotice << ColorGreen;
  303. // cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, cmDeathNotice, 4 );
  304. pcTargetObj->AddPacket( WORLD_SERVER, pcTargetObj->m_pcAvatar->SetHealth( pcTargetObj->m_pcAvatar->GetTotalHealth( ) ), 4 );
  305. SimpleAI::SetAttackComplete( dwMonGUID );
  306. SimpleAI::SetTargetKilled( dwTarget );
  307. }
  308. else
  309. {
  310. cmAnim << pcMonster->CombatAnimation( dwTarget, wAttackAnim );
  311. //Cubem0j0: implementation of different hit locations.
  312. BYTE loc;
  313. int iloc = rand()%8;
  314. switch(iloc)
  315. {
  316. case 0:
  317. loc = 0x0;
  318. break;
  319. case 1:
  320. loc = 0x1;
  321. break;
  322. case 2:
  323. loc = 0x2;
  324. break;
  325. case 3:
  326. loc = 0x3;
  327. break;
  328. case 4:
  329. loc = 0x4;
  330. break;
  331. case 5:
  332. loc = 0x5;
  333. break;
  334. case 6:
  335. loc = 0x6;
  336. break;
  337. case 7:
  338. loc = 0x7;
  339. break;
  340. case 8:
  341. loc = 0x8;
  342. break;
  343. }
  344. //cMessage cmDamageRecieveMessage = pcTargetObj->m_pcAvatar->RecieveDamageMessage( ++pcTargetObj->m_dwF7B0Sequence, pcMonster->m_strName, dwDamageType, dSeverity, dwTrue2, loc);
  345. pcTargetObj->AddPacket( WORLD_SERVER, pcTargetObj->m_pcAvatar->RecieveDamageMessage( ++pcTargetObj->m_dwF7B0Sequence, pcMonster->m_strName, dwDamageType, dSeverity, dwTrue2, loc), 4 );
  346. //SimpleAI::SetAttackComplete( dwMonGUID );
  347. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  348. }
  349. } // End range check
  350. else
  351. {
  352. SimpleAI::SetAttackEvent( dwMonGUID,dwTarget, 2, 0 );
  353. }
  354. }// End validaiton check
  355. break;
  356. }
  357. case 0x6: // Break off attack
  358. {
  359. SimpleAI::SetAction( dwMonGUID, 3, 7 );
  360. break;
  361. }
  362. case 0x7: // Change combat mode
  363. {
  364. if( pcMonster->m_fCombatMode == false )// Enter Melee Mode
  365. {
  366. //cMessage Anim = pcMonster->ChangeCombatMode( true );
  367. cWorldManager::SendToAllInFocus( pcMonster->m_Location, pcMonster->ChangeCombatMode( true ), 3 );
  368. pcMonster->m_fCombatMode = true;
  369. }
  370. else // Leave combat
  371. {
  372. //cMessage Anim = pcMonster->ChangeCombatMode( false );
  373. cWorldManager::SendToAllInFocus( pcMonster->m_Location, pcMonster->ChangeCombatMode( false ), 3 );
  374. pcMonster->m_fCombatMode = false;
  375. SimpleAI::SetAction( dwMonGUID, 0, 7 );
  376. }
  377. break;
  378. }
  379. } // End switch
  380. } // End pcModel check
  381. }
  382. else
  383. {
  384. cMasterServer::ServerMessage( ColorBlue, NULL, "Monster Action Processing Error" );
  385. }
  386. // End check
  387. }
  388. //Karki
  389. void cMonsterServer::ProcessPetAction( DWORD dwMonGUID, DWORD dwEvent, DWORD dwEngaged, DWORD dwTarget, DWORD dwOwner )
  390. {
  391. //cMasterServer::ServerMessage( ColorBlue, NULL, "Pet Action Process Recieved" );
  392. cObject *pcPet = cWorldManager::FindObject( dwMonGUID );
  393. if(pcPet) // If not a valid Monster Object do nothing
  394. {
  395. cModels* pcModel = cModels::FindModel( pcPet->GetMonsterModelID() );
  396. int iRand = rand();
  397. int iRand2 = rand();
  398. iRand = iRand + iRand2;
  399. iRand = (iRand > 6400) ? iRand % 6400 : iRand;
  400. iRand = (iRand < 1600) ? 1600 + iRand : iRand;
  401. if( pcModel )
  402. {
  403. switch( dwEvent )
  404. {
  405. case 0x0: // Idle
  406. {
  407. WORD wAnimation;
  408. float FollowRangeCheck;
  409. //Pet follow check
  410. cClient* pcPetTarget = cClient::FindClient( dwOwner );
  411. //cMasterServer::ServerMessage( ColorBlue, NULL, "Monster is Idle" );
  412. //cMasterServer::ServerMessage( ColorBlue, NULL, "%d is my Owner", dwOwner );
  413. //cMasterServer::ServerMessage( ColorBlue, NULL, "Owner = %d", pcPetTarget->FindClient( dwOwner) );
  414. if( pcPetTarget)
  415. {
  416. //cMasterServer::ServerMessage( ColorBlue, NULL, "Follow Checking" );
  417. // Check Range to Target
  418. FollowRangeCheck = pcPet->GetRange( pcPetTarget->m_pcAvatar->m_Location.m_dwLandBlock, pcPetTarget->m_pcAvatar->m_Location.m_flX, pcPetTarget->m_pcAvatar->m_Location.m_flY, pcPetTarget->m_pcAvatar->m_Location.m_flZ );
  419. //cMasterServer::ServerMessage( ColorBlue, NULL, "Range is %d", FollowRangeCheck );
  420. if( FollowRangeCheck >= .6)
  421. {
  422. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, pcPet->MoveToTarget( pcPetTarget ), 3 );
  423. cWorldManager::SendToAllWithin( 10, pcPet->m_Location, pcPet->SetPosition( ), 3 );
  424. //cMasterServer::ServerMessage( ColorBlue, NULL, "Following" );
  425. }
  426. }
  427. int IdleAnim = iRand/1000;
  428. switch( IdleAnim )
  429. {
  430. case 0:
  431. {
  432. wAnimation = pcModel->m_cAnimations.m_wIdle[0];
  433. pcPet->m_bIdleAnim++;
  434. break;
  435. }
  436. case 1:
  437. {
  438. wAnimation = pcModel->m_cAnimations.m_wIdle[1];//0x53L;
  439. pcPet->m_bIdleAnim++;
  440. break;
  441. }
  442. case 2:
  443. {
  444. wAnimation = pcModel->m_cAnimations.m_wIdle[2];//0x52L;
  445. pcPet->m_bIdleAnim++;
  446. break;
  447. }
  448. case 3:
  449. {
  450. wAnimation = pcModel->m_cAnimations.m_wIdle[3];//0x50L;
  451. pcPet->m_bIdleAnim++;
  452. break;
  453. }
  454. case 4:
  455. {
  456. wAnimation = pcModel->m_cAnimations.m_wIdle[4];//0x53L;
  457. pcPet->m_bIdleAnim++;
  458. break;
  459. }
  460. case 5:
  461. {
  462. wAnimation = pcModel->m_cAnimations.m_wIdle[5];//0x52L;
  463. pcPet->m_bIdleAnim = 0;
  464. break;
  465. }
  466. }
  467. cMessage cMonAnim = pcPet->Animation( wAnimation, 1.0f );
  468. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, cMonAnim, 3 );
  469. break;
  470. }
  471. /*
  472. case 0x1: // Under attack
  473. {
  474. float flHeading, flDistance;
  475. cClient* pcTargetObj = cClient::FindClient( dwTarget );
  476. if( pcTargetObj)
  477. {
  478. flHeading = pcMonster->GetHeadingTarget( pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  479. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->TurnToTarget(flHeading,dwTarget ), 3 );
  480. }
  481. flDistance = pcMonster->GetRange( pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  482. if ( flDistance < 0.8f)
  483. {
  484. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  485. }
  486. else
  487. {
  488. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 2, 1 );
  489. }
  490. break;
  491. }
  492. case 0x2: // Move to attacker
  493. {
  494. float flDistance;
  495. cClient* pcTargetObj = cClient::FindClient( dwTarget );
  496. if( pcTargetObj)
  497. {
  498. flDistance = pcMonster->GetRange(pcTargetObj->m_pcAvatar->m_Location.m_dwLandBlock, pcTargetObj->m_pcAvatar->m_Location.m_flX, pcTargetObj->m_pcAvatar->m_Location.m_flY, pcTargetObj->m_pcAvatar->m_Location.m_flZ );
  499. if ( flDistance < 1.0f )
  500. {
  501. //cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->MoveTarget( pcTargetObj ), 3 );
  502. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  503. pcMonster->SetLocation(&pcTargetObj->m_pcAvatar->m_Location);
  504. }
  505. else
  506. {
  507. // Break off the chase if the target is too far away
  508. if(flDistance > 3)//pcMonster->m_dwChase )
  509. {
  510. SimpleAI::SetAttackComplete( dwMonGUID );
  511. SimpleAI::SetAction( dwMonGUID, 3, 0);
  512. }
  513. else
  514. {
  515. SimpleAI::SetAttackEvent( dwMonGUID,dwTarget, 2, 3 );
  516. cWorldManager::SendToAllWithin( 5, pcMonster->m_Location, pcMonster->MoveToTarget( pcTargetObj ), 3 );
  517. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  518. }
  519. }
  520. }
  521. else
  522. {
  523. SimpleAI::SetAction( dwMonGUID, 0, 2);
  524. }
  525. break;
  526. }
  527. case 0x3: // Return to spawn point
  528. {
  529. float flDistance;
  530. flDistance = pcMonster->GetRange( pcMonster->m_SpawnLoc.m_dwLandBlock, pcMonster->m_SpawnLoc.m_flX, pcMonster->m_SpawnLoc.m_flY, pcMonster->m_SpawnLoc.m_flZ );
  531. if(( flDistance > 0.4f )&&( flDistance < pcMonster->m_dwChase))
  532. {
  533. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->ReturnToSpawn( ), 3 );
  534. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  535. SimpleAI::SetAction( dwMonGUID, 3, 4);
  536. }
  537. else if(flDistance > pcMonster->m_dwChase)
  538. {
  539. // Jump back to Spawn Point
  540. cWorldManager::MoveRemObject( pcMonster );
  541. pcMonster->SetLocation(&pcMonster->m_SpawnLoc);
  542. cWorldManager::MoveAddObject( pcMonster );
  543. cWorldManager::SendToAllWithin( 10, pcMonster->m_Location, pcMonster->SetPosition( ), 3 );
  544. SimpleAI::SetAction( dwMonGUID, 0, 1 );
  545. }
  546. else
  547. {
  548. SimpleAI::SetAction( dwMonGUID, 0, 1 );
  549. }
  550. break;
  551. }
  552. case 0x4: // There is a user within range
  553. {
  554. SimpleAI::SetAction( dwMonGUID, 2, 3 );
  555. break;
  556. }
  557. */
  558. case 0x5: // Attack user
  559. {
  560. DWORD dwDamageType = 0x4;
  561. float flDamageSlider = rand() % 2;
  562. //float intRange;
  563. int AttackAnim = iRand/1000;
  564. WORD wAttackAnim;
  565. switch( AttackAnim )
  566. {
  567. case 0:
  568. {
  569. wAttackAnim = pcModel->m_cAnimations.m_wAttack[0];
  570. break;
  571. }
  572. case 1:
  573. {
  574. wAttackAnim = pcModel->m_cAnimations.m_wAttack[1];
  575. break;
  576. }
  577. case 2:
  578. {
  579. wAttackAnim = pcModel->m_cAnimations.m_wAttack[2];
  580. break;
  581. }
  582. case 3:
  583. {
  584. wAttackAnim = pcModel->m_cAnimations.m_wAttack[3];
  585. break;
  586. }
  587. case 4:
  588. {
  589. wAttackAnim = pcModel->m_cAnimations.m_wAttack[4];
  590. break;
  591. }
  592. case 5:
  593. {
  594. wAttackAnim = pcModel->m_cAnimations.m_wAttack[5];
  595. break;
  596. }
  597. }
  598. /* Broken pet vombat vode
  599. cObject* pcTargetObj = cWorldManager::FindObject( dwTarget );
  600. if( pcTargetObj)
  601. {
  602. // Check range to target
  603. intRange = pcPet->GetRange( pcTarget->m_Location.m_dwLandBlock, pcTarget->m_Location.m_flX, pcTarget->m_Location.m_flY, pcTarget->m_Location.m_flZ );
  604. if( intRange < 1.5f)
  605. {
  606. //Take a swing
  607. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, pcPet->ChangeCombatMode( false ), 3 );
  608. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, pcPet->CombatAnimation( dwTarget,wAttackAnim ), 3 );
  609. WORD wTotalOpponentHealth = pcTarget->GetTotalHealth();
  610. //Now perform a very basic combat calculation..no where near accurate.
  611. srand( timeGetTime( ) );
  612. float flMaxDamage = rand( )/27;
  613. DWORD dwTrueDamage = pcPet->CalculateDamage(3.0f, 0.0f);
  614. double dSeverity = ( double ) wTotalOpponentHealth / dwTrueDamage;
  615. int iNewHealth;
  616. BOOL fKilledPlayer = FALSE;
  617. //Following variable(s) only used if there is a kill
  618. cMessage cmAnim;
  619. cMessage cmHealthLoss = pcTargetObj->m_pcAvatar->DecrementHealth( dwTrueDamage, iNewHealth );
  620. pcTargetObj->AddPacket( WORLD_SERVER, cmHealthLoss, 4 );
  621. if( iNewHealth <= 0 )
  622. {
  623. fKilledPlayer = TRUE;
  624. cMessage cmKill = pcTargetObj->m_pcAvatar->SetHealth( pcTargetObj->m_pcAvatar->GetTotalHealth( ) );
  625. cMessage Anim = pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE );
  626. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, Anim, 3 );
  627. cMessage cAnim = pcTargetObj->m_pcAvatar->Animation( pcModel->m_cAnimations.m_wAttack[0], 2.0f );
  628. cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, cAnim, 3 );
  629. cMasterServer::Corpse( pcTargetObj );
  630. cMessage Alive = pcTargetObj->m_pcAvatar->ChangeCombatMode( FALSE );
  631. cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, Alive, 3 );
  632. cWorldManager::TeleportAvatar( pcTargetObj, cMasterServer::m_StartingLoc );
  633. cMasterServer::ServerMessage( ColorGreen, pcTargetObj, "You have been restored to Health." );
  634. cMessage cmSetFlag;
  635. cmSetFlag << 0x022CL << BYTE(0) << pcTargetObj->m_pcAvatar->GetGUID() << 0x04L << 0;
  636. cWorldManager::SendToAllInFocus( pcTargetObj->m_pcAvatar->m_Location, cmSetFlag, 4 );
  637. pcTargetObj->m_pcAvatar->m_fIsPK = false;
  638. char szDeathNotice[200];
  639. wsprintf( szDeathNotice, "%s has killed %s", pcPet->m_strName.c_str(), pcTargetObj->m_pcAvatar->m_strName.c_str( ) );
  640. cMessage cmDeathNotice;
  641. cmDeathNotice << 0xF62C << szDeathNotice << ColorGreen;
  642. cWorldManager::SendToAllWithin( 5, pcPet->m_Location, cmDeathNotice, 4 );
  643. pcTargetObj->AddPacket( WORLD_SERVER, cmKill, 4 );
  644. SimpleAI::SetAttackComplete( dwMonGUID );
  645. SimpleAI::SetTargetKilled( dwTarget );
  646. }
  647. else
  648. {
  649. cmAnim << pcPet->CombatAnimation( dwTarget, wAttackAnim );
  650. cMessage cmDamageRecieveMessage = pcTargetObj->m_pcAvatar->RecieveDamageMessage( ++pcTargetObj->m_dwF7B0Sequence, pcPet->m_strName, dwDamageType, dSeverity, dwTrueDamage, 0x7 );
  651. pcTargetObj->AddPacket( WORLD_SERVER, cmDamageRecieveMessage, 4 );
  652. //SimpleAI::SetAttackComplete( dwMonGUID );
  653. SimpleAI::SetAttackEvent( dwMonGUID, dwTarget, 5, 1 );
  654. }
  655. } // End range check
  656. else
  657. {
  658. SimpleAI::SetAttackEvent( dwMonGUID,dwTarget, 2, 0 );
  659. }
  660. }// End validaiton check
  661. */
  662. break;
  663. }
  664. /*
  665. case 0x6: // Break off attack
  666. {
  667. SimpleAI::SetAction( dwMonGUID, 3, 7 );
  668. break;
  669. }
  670. case 0x7: // Change combat mode
  671. {
  672. if( pcMonster->m_fCombatMode == false )// Enter Melee Mode
  673. {
  674. cMessage Anim = pcMonster->ChangeCombatMode( true );
  675. cWorldManager::SendToAllInFocus( pcMonster->m_Location, Anim, 3 );
  676. pcMonster->m_fCombatMode = true;
  677. }
  678. else // Leave combat
  679. {
  680. cMessage Anim = pcMonster->ChangeCombatMode( false );
  681. cWorldManager::SendToAllInFocus( pcMonster->m_Location, Anim, 3 );
  682. pcMonster->m_fCombatMode = false;
  683. SimpleAI::SetAction( dwMonGUID, 0, 7 );
  684. }
  685. break;
  686. }
  687. */
  688. } // End switch
  689. } // End pcModel check
  690. }
  691. else
  692. {
  693. cMasterServer::ServerMessage( ColorBlue, NULL, "Monster Action Processing Error" );
  694. }
  695. // End check
  696. }