Advertisement
Guest User

Untitled

a guest
Jun 6th, 2011
555
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 69.35 KB | None | 0 0
  1. /*
  2. Fixed by Aukemon0(NL) aka Nyaa-Sensei
  3. */
  4. #include "character.h"
  5. #include "worldserver.h"
  6.  
  7. void CCharacter::DoAttack( )
  8. {
  9. /*
  10. if(IsSummon())
  11. Log(MSG_INFO,"Someone attacks type=%i,skillid=%i",Battle->atktype,Battle->skillid);
  12. */
  13.  
  14. //osptest begin
  15. if(IsSummon())
  16. {
  17. CCharacter* Enemy = GetCharTarget( );
  18. if(Enemy == NULL && Battle->atktype != SKILL_AOE && Battle->atktype != BUFF_AOE)
  19. {
  20. //LogDebug("No Enemy found");
  21. ClearBattle( Battle );
  22. return;
  23. }
  24. //LogDebug("Client id: %i Enemy client id: %i",clientid, Enemy->clientid);
  25. if(this == Enemy) //summoned monster is attacking itself. It has been observed to happen
  26. {
  27. //Log(MSG_INFO,"Clearing Battle for this summon");
  28. ClearBattle( Battle );
  29. return;
  30. }
  31. }
  32. //osptest end
  33.  
  34. //LMA: If we're dead, why are we still fighting?
  35. if(IsDead())
  36. {
  37. ClearBattle(Battle);
  38. return;
  39. }
  40.  
  41. CMap* map = GServer->MapList.Index[Position->Map];
  42. switch(Battle->atktype)
  43. {
  44. case NORMAL_ATTACK://normal attack
  45. {
  46. CCharacter* Enemy = GetCharTarget( );
  47. if(Enemy==NULL)
  48. {
  49. ClearBattle( Battle );
  50. return;
  51. }
  52.  
  53. //osptest
  54. if(Enemy == this)
  55. {
  56. //Log(MSG_INFO,"WTF?? I AM trying to attack myself");
  57. ClearBattle( Battle );
  58. }
  59. //osptest end
  60.  
  61. //LMA: Some logs.
  62. /*
  63. if(map->id==8)
  64. {
  65. bool is_ok=false;
  66. bool is_reached=false;
  67. bool can_attack=false;
  68.  
  69. float distance = GServer->distance( Position->current, Enemy->Position->current );
  70. is_reached=IsTargetReached( Enemy );
  71. can_attack=CanAttack( );
  72.  
  73. if(is_reached&&can_attack)
  74. is_ok=true;
  75.  
  76. if(IsMonster())
  77. {
  78. Log(MSG_INFO,"monster has reached? %i (%.2f/%.2f), canattack? %i, will attack? %i",is_reached,distance,Stats->Attack_Distance,can_attack,is_ok);
  79.  
  80. if (is_ok)
  81. Log(MSG_INFO,"NORMAL_ATTACK, monster %i has reached %i (%.2f<=%.2f)",clientid,Enemy->clientid,distance,Stats->Attack_Distance);
  82. else
  83. Log(MSG_INFO,"NORMAL_ATTACK, monster %i hasn't reached? %i (%.2f>%.2f)",clientid,Enemy->clientid,distance,Stats->Attack_Distance);
  84. }
  85. else
  86. {
  87. Log(MSG_INFO,"player has reached? %i (%.2f/%.2f), canattack? %i, will attack? %i",is_reached,distance,Stats->Attack_Distance,can_attack,is_ok);
  88.  
  89. if (is_ok)
  90. Log(MSG_INFO,"NORMAL_ATTACK, player %i has reached %i (%.2f<=%.2f)",clientid,Enemy->clientid,distance,Stats->Attack_Distance);
  91. else
  92. Log(MSG_INFO,"NORMAL_ATTACK, player %i hasn't reached? %i (%.2f>%.2f)",clientid,Enemy->clientid,distance,Stats->Attack_Distance);
  93. }
  94.  
  95. }
  96. */
  97. //End of logs.
  98.  
  99.  
  100. if(IsTargetReached( Enemy ) && CanAttack( ))
  101. {
  102. if(IsMonster())
  103. {
  104. // Log(MSG_INFO,"monster Doing a normal attack");
  105. }
  106. else
  107. {
  108. // Log(MSG_INFO,"player Doing a normal attack");
  109. }
  110.  
  111. NormalAttack( Enemy );
  112.  
  113. if (Enemy->IsMonster()) // do monster AI script when monster is attacked.
  114. {
  115. CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map);
  116.  
  117. if(monster!=NULL)
  118. {
  119. if(!monster->IsDead())
  120. {
  121. /*Log(MSG_INFO,"Monster %i is attacked, doing his AI 3, HP: %I64i",monster->clientid,monster->Stats->HP);
  122. monster->DoAi(monster->thisnpc->AI, 3);*/
  123.  
  124. //LMA: Doing is_attacked from time to time, not at each attack...
  125. if(0<=GServer->round((clock( ) - monster->nextAi_attacked)))
  126. {
  127. monster->nextAi_attacked=clock();
  128. clock_t temp=monster->nextAi_attacked;
  129. // Log(MSG_INFO,"Monster %i is attacked, doing his AI 3, HP: %I64i",monster->clientid,monster->Stats->HP);
  130. monster->DoAi(monster->thisnpc->AI, 3);
  131.  
  132. if (temp==monster->nextAi_attacked)
  133. {
  134. //LMA: AI Timer by default, some AIP can change this.
  135. monster->nextAi_attacked+=monster->thisnpc->AiTimer;
  136. }
  137.  
  138. //Log(MSG_INFO,"Clock is %u, next is_attacked at %u, so in %u",clock(),monster->thisnpc->AiTimer,monster->thisnpc->AiTimer-clock());
  139. // Log(MSG_INFO,"Clock is %u, next is_attacked at %u, so in %u",clock(),monster->nextAi_attacked,monster->nextAi_attacked-clock());
  140.  
  141. }
  142.  
  143. }
  144.  
  145. }
  146.  
  147. }
  148.  
  149. }
  150. else
  151. {
  152.  
  153. /*if(IsPlayer())
  154. {
  155. if(!IsTargetReached( Enemy ))
  156. Log(MSG_INFO,"Player %i hasn't reached his enemy (%i) yet (%.2f,%.2f) (%.2f,%.2f)",this->clientid,this->Battle->atktarget,this->Position->current.x,this->Position->current.y,this->Position->destiny.x,this->Position->destiny.y);
  157. }
  158. else
  159. {
  160. if(!IsTargetReached( Enemy ))
  161. Log(MSG_INFO,"Monster %i hasn't reached his enemy (%i) yet (%.2f,%.2f) (%.2f,%.2f)",this->clientid,this->Battle->atktarget,this->Position->current.x,this->Position->current.y,this->Position->destiny.x,this->Position->destiny.y);
  162. }*/
  163.  
  164. }
  165.  
  166. }
  167. break;
  168. case SKILL_ATTACK://skill attack
  169. {
  170. CCharacter* Enemy = GetCharTarget( );
  171. if(Enemy==NULL)
  172. {
  173. ClearBattle( Battle );
  174. return;
  175. }
  176. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  177. if(skill==NULL)
  178. {
  179. ClearBattle( Battle );
  180. return;
  181. }
  182. if(IsTargetReached( Enemy, skill ) && CanAttack( ))
  183. {
  184. SkillAttack( Enemy, skill );
  185.  
  186. if (Enemy->IsMonster())
  187. {
  188. CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map);
  189.  
  190. if(monster!=NULL)
  191. monster->DoAi(monster->thisnpc->AI, 3);
  192. }
  193.  
  194. }
  195.  
  196. }
  197. break;
  198. case MONSTER_SKILL_ATTACK://LMA: monster skill attack
  199. {
  200. CCharacter* Enemy = GetCharTarget( );
  201. if(Enemy==NULL)
  202. {
  203. ClearBattle( Battle );
  204. return;
  205. }
  206. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  207. if(skill==NULL)
  208. {
  209. ClearBattle( Battle );
  210. return;
  211. }
  212. if(IsTargetReached( Enemy, skill ) && CanAttack( ))
  213. SkillAttack( Enemy, skill );
  214. }
  215. break;
  216. case SUMMON_BUFF://Summon buffs (support)
  217. {
  218. //LMA: For summon that buff player :)
  219. if (Battle->bufftarget==0)
  220. break;
  221. CCharacter* master = GetCharBuffTarget( );
  222. if(master==NULL)
  223. {
  224. ClearBattle( Battle );
  225. return;
  226. }
  227. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  228. if(skill==NULL)
  229. {
  230. ClearBattle( Battle );
  231. return;
  232. }
  233. if(IsTargetReached( master, skill ) && CanAttack( ))
  234. SummonBuffSkill( master, skill );
  235. }
  236. break;
  237. case MONSTER_SKILL_BUFF://LMA: monster buffs
  238. {
  239. CCharacter* Enemy= GetCharTarget( );
  240. if(Enemy==NULL)
  241. {
  242. ClearBattle( Battle );
  243. return;
  244. }
  245. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  246. if(skill==NULL)
  247. {
  248. ClearBattle( Battle );
  249. return;
  250. }
  251.  
  252. if(IsTargetReached( Enemy, skill ) && CanAttack( ))
  253. {
  254. BuffSkill( Enemy, skill );
  255. }
  256.  
  257. }
  258. break;
  259. case SKILL_BUFF://buffs
  260. {
  261. //osptest
  262. CCharacter* Enemy = GetCharTarget( );
  263. if(Enemy == NULL)
  264. {
  265. //LogDebug("this target is NULL");
  266. ClearBattle( Battle );
  267. return;
  268. }
  269.  
  270. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  271.  
  272. if(skill == NULL)
  273. {
  274. //LogDebug("this skill is NULL");
  275. //ClearBattle( Battle );
  276. return;
  277. }
  278.  
  279. //LogDebug("Called skill buff code for skill %i",skill->id);
  280. if(IsTargetReached( Enemy, skill ) && CanAttack( ))
  281. {
  282. //LogDebug("Skill successfully cast");
  283. //BuffSkill( Enemy, skill );
  284.  
  285. if(IsPlayer())
  286. {
  287. CPlayer* plkiller=(CPlayer*) this;
  288. // Log(MSG_WARNING,"Before Buff skill Player %i (%s) targets cid %i",clientid,plkiller->CharInfo->charname,plkiller->Battle->target);
  289. }
  290.  
  291. BuffSkill( Enemy, skill );
  292.  
  293. if(IsPlayer())
  294. {
  295. CPlayer* plkiller=(CPlayer*) this;
  296. // Log(MSG_WARNING,"After Buff skill Player %i (%s) targets cid %i",clientid,plkiller->CharInfo->charname,plkiller->Battle->target);
  297. }
  298.  
  299. }
  300. //osptest end
  301. }
  302. break; //LMA: break was missing?
  303. case SKILL_AOE:
  304. case SKILL_SELF:
  305. case AOE_TARGET:
  306. {
  307. CCharacter* Enemy = NULL;
  308. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  309. if(skill==NULL)
  310. {
  311. ClearBattle( Battle );
  312. return;
  313. }
  314. if(Battle->atktype==AOE_TARGET)
  315. {
  316. //LMA 2008/09/02: new version, the target is a zone, not a monster... so we stick with aoedestiny ;)
  317. float distance=GServer->distance( Position->current, Position->aoedestiny );
  318. //Log(MSG_INFO,"distance %f / range: %i, current: %.2f,%.2f, aoe: %.2f,%.2f",distance,skill->range,Position->current.x,Position->current.y,Position->aoedestiny.x,Position->aoedestiny.y);
  319. //osprose: canattacl
  320. if(distance<=skill->range&&CanAttack( ))
  321. {
  322. // Log(MSG_INFO,"[DoAttack] In AOE_TARGET time for AoeSkill");
  323. AoeSkill( skill, NULL ); //LMA: no specific Enemy in Zone.
  324. }
  325. else
  326. {
  327. //LMA: Too verbose...
  328. //Log(MSG_INFO,"[DoAttack] In AOE_TARGET not reached or can't attack");
  329. }
  330.  
  331. }
  332. else
  333. {
  334. if(Enemy==NULL)
  335. {
  336. // Log(MSG_INFO,"player %i: default AOE attack (%i/%i) %i for enemy NULL ", clientid,Battle->atktype,AOE_TARGET,skill->id);
  337.  
  338. if (skill->atkpower == 0)//Like Howl Skill soldier (AOE Def down) or Detect skill have 0 atkpower
  339. {
  340. // Log(MSG_INFO,"[DoAttack] AoeDebuff");
  341. AoeDebuff( skill, NULL );
  342. }
  343. else
  344. {
  345. AoeSkill( skill, Enemy );
  346. }
  347. }
  348. else
  349. {
  350. // Log(MSG_INFO,"player %i: default AOE attack (%i/%i) %i for enemy %i ", clientid,Battle->atktype,AOE_TARGET,skill->id,Enemy->clientid);
  351. AoeSkill( skill, Enemy );
  352. }
  353.  
  354. //AoeSkill( skill, Enemy );
  355. }
  356. }
  357. break;
  358. case BUFF_SELF:
  359. {
  360. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  361. if(skill==NULL)
  362. {
  363. //osprose
  364. //ClearBattle( Battle );
  365. return;
  366. }
  367. BuffSkill( this, skill );
  368. }
  369. break;
  370. case MONSTER_BUFF_SELF: //LMA: monster selfs buffs.
  371. {
  372. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  373. if(skill==NULL)
  374. {
  375. ClearBattle( Battle );
  376. return;
  377. }
  378. BuffSkill( this, skill );
  379. }
  380. break;
  381. case BUFF_AOE:
  382. {
  383. CSkills* skill = GServer->GetSkillByID( Battle->skillid );
  384. if(skill==NULL)
  385. {
  386. ClearBattle( Battle );
  387. return;
  388. }
  389.  
  390. //osprose
  391. AoeBuff( skill );
  392. //osprose end
  393. }
  394. break;
  395. default:
  396. {
  397. return;
  398. }
  399. break;
  400. }
  401.  
  402. }
  403.  
  404. // do normal attack
  405. void CCharacter::NormalAttack( CCharacter* Enemy )
  406. {
  407. //LMA: Sometimes it's fired several times, no need to kill several times ;)
  408. bool is_already_dead=Enemy->IsDead();
  409.  
  410. Position->destiny = Position->current;
  411.  
  412. //LMA: Log
  413. if(IsPlayer())
  414. // Log(MSG_INFO,"Forcing destiny to current (%.2f,%.2f), (%.2f,%.2f)",Position->current.x,Position->current.y,Position->destiny .x,Position->destiny .y);
  415.  
  416.  
  417. reduceItemsLifeSpan( false );
  418.  
  419. Enemy->OnBeAttacked( this );
  420.  
  421. float attack = (float)Stats->Attack_Power - ((Enemy->Stats->Magic_Defense+Enemy->Stats->Defense )/5);
  422. if(attack<0) attack = 5;
  423. attack *= 0.95;
  424. float d_attack = attack / 99;
  425. if(attack<0) attack = 7;
  426. attack += (float)GServer->RandNumber( 0, 7 ) - 2;
  427. attack += ((Stats->Level - Enemy->Stats->Level) * d_attack);
  428. if(attack<7) attack = 5;
  429. long int hitpower = (long int)floor(attack + GServer->RandNumber(0, 4));
  430. /*if(IsPlayer( ))
  431. hitpower = (long int)floor(attack * 1.2 );*/
  432. if(IsPlayer( )) //temp fix to find balance btw monster and player
  433. hitpower = (long int)floor(attack * (GServer->Config.PlayerDmg/100.00));
  434. if(IsMonster( )) //temp fix to find balance btw monster and player
  435. hitpower = (long int)floor(attack * (GServer->Config.MonsterDmg/100.00));
  436.  
  437. if(IsPlayer())//Add Dmg
  438. {
  439. if( Stats->ExtraDamage_add !=0 )
  440. {
  441. long int hitsave=hitpower;
  442. hitpower += ((hitpower * Stats->ExtraDamage_add) / 100);
  443. // Log(MSG_INFO,"ExtraDmg Normal atk: before %i, after %i (ED: %i)",hitsave,hitpower,Stats->ExtraDamage_add);
  444. }
  445. }
  446.  
  447. bool critical = false;
  448. if(hitpower<=0)
  449. {
  450. hitpower = 0;
  451. }
  452. else
  453. {
  454. if(GServer->RandNumber(0,300)<Stats->Critical)
  455. {
  456. hitpower = (long int)floor(hitpower*1.5);
  457. critical = true;
  458. }
  459. }
  460. // dodge
  461. unsigned int hitvalue = (unsigned int)floor(Stats->Accury * 50 / Enemy->Stats->Dodge);
  462. if(hitvalue>100) hitvalue = 100;
  463. if(GServer->RandNumber( 0, 100 )>hitvalue)
  464. hitpower = 0; // dodged
  465. if(!Enemy->IsSummon( ) && Enemy->IsMonster( ))
  466. {
  467. Enemy->AddDamage( this, (long long) hitpower );
  468. Enemy->damagecounter += (long long) hitpower;// is for AI
  469. }
  470.  
  471. Enemy->Stats->HP -= (long long) hitpower;
  472.  
  473. if (Enemy->IsMonster())
  474. {
  475. // Log(MSG_INFO,"Normal Attack, monster HP %I64i, hitpower %li",Enemy->Stats->HP,hitpower);
  476. }
  477. else
  478. {
  479. // Log(MSG_INFO,"Normal Attack, Player HP %I64i, hitpower %li",Enemy->Stats->HP,hitpower);
  480. }
  481.  
  482. // actually the target was hit, if it was sleeping, set duration of
  483. // sleep to 0. map process will remove sleep then at next player-update
  484. if (Enemy->Status->Sleep != 0xff) {
  485. Enemy->MagicStatus[Enemy->Status->Sleep].Duration = 0;
  486. }
  487.  
  488. //if (IsPlayer())
  489. //printf("Target suffered %i physical damage, %i HP still remain \n", hitpower, Enemy->Stats->HP);
  490. //else printf("Mob did %i physical damage, %i HP still remain \n", hitpower, Enemy->Stats->HP);
  491. Enemy->reduceItemsLifeSpan(true);
  492.  
  493. //LMA: forcing the HP amount value, only when it's supposed to be dead side.
  494. if(Enemy->IsMonster()&&Enemy->IsDead())
  495. {
  496. BEGINPACKET( pak, 0x79f );
  497. ADDWORD ( pak, Enemy->clientid );
  498. ADDDWORD ( pak, 1);
  499. GServer->SendToVisible( &pak, Enemy );
  500. // Log(MSG_INFO,"death atk for %i, amount: %i",Enemy->clientid,hitpower);
  501. }
  502.  
  503. BEGINPACKET( pak, 0x799 );
  504. ADDWORD ( pak, clientid );
  505. //ADDWORD ( pak, Battle->atktarget );
  506. ADDWORD ( pak, Enemy->clientid );
  507. // Log(MSG_INFO,"pak 799 : clientid %i, Enemy->clientid %i",clientid,Enemy->clientid);
  508.  
  509. //LMA: little test (see TESTDEATH)
  510. //ADDDWORD ( pak, hitpower );
  511.  
  512. if(Enemy->IsDead())
  513. {
  514. //LMA: UW handling, we add the handling for other quests as well...
  515. //if (!is_already_dead&&(GServer->MapList.Index[Position->Map]->QSDkilling>0||GServer->MapList.Index[Position->Map]->QSDDeath>0)&&IsPlayer()&&Enemy->IsPlayer())
  516. if (!is_already_dead&&((GServer->MapList.Index[Position->Map]->QSDkilling>0&&IsPlayer()&&Enemy->IsPlayer())||(GServer->MapList.Index[Position->Map]->QSDDeath&&Enemy->IsPlayer())))
  517. {
  518. //Log(MSG_INFO,"UWKILL begin normal atk");
  519. UWKill(Enemy);
  520. }
  521.  
  522. //LMA: test for quest hack (stackable).
  523. #ifdef QHACK
  524. if(!is_already_dead&&Enemy->die_quest!=0&&Enemy->IsMonster()&&IsPlayer())
  525. {
  526. QuestKill(Enemy->die_quest);
  527. }
  528. #endif
  529. //LMA END
  530.  
  531. //LMA: TESTDEATH :: We try to force the DEATH
  532. //ADDDWORD ( pak, Enemy->Stats->MaxHP );
  533. ADDDWORD ( pak, hitpower );
  534.  
  535. //Logs.
  536. /*if(IsPlayer()&&Enemy->IsPlayer())
  537. {
  538. CPlayer* plkilled=(CPlayer*) Enemy;
  539. CPlayer* plkiller=(CPlayer*) this;
  540. Log(MSG_INFO,"NA CID %i (%s) killed %i (%s) (NORMAL_ATTACK).",clientid,plkiller->CharInfo->charname,Enemy->clientid,plkilled->CharInfo->charname);
  541. }
  542. else
  543. {
  544. Log(MSG_INFO,"NA CID %i killed %i (NORMAL_ATTACK).",clientid,Enemy->clientid);
  545. }*/
  546.  
  547. CDrop* thisdrop = NULL;
  548. // Log(MSG_WARNING,"Dead, critical %i",critical);
  549.  
  550. //LMA: Seems that 24 is for critical and skill? We disable critical final hit for now.
  551. //ADDDWORD ( pak, critical?28:16 );
  552. ADDDWORD ( pak, 16 );
  553. if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( ))
  554. {
  555. //LMA: looping the drops (double drop medal for example).
  556. int nb_drops=1;
  557. if (IsPlayer())
  558. {
  559. CPlayer* plkiller=(CPlayer*) this;
  560. nb_drops=plkiller->bonusddrop;
  561. // Log(MSG_INFO,"Drop time, there should be %i drops",nb_drops);
  562. }
  563.  
  564. //No drop if already dead and drop done.
  565. if(Enemy->drop_dead)
  566. {
  567. // Log(MSG_WARNING,"Trying to make a monster (CID %u, type %u) drop again but already did.",Enemy->clientid,Enemy->char_montype);
  568. nb_drops=0;
  569. }
  570.  
  571. for (int k=0;k<nb_drops;k++)
  572. {
  573. thisdrop = Enemy->GetDrop( );
  574. if(thisdrop!=NULL)
  575. {
  576. // Log(MSG_INFO,"Dropping Nb %i",k);
  577. CMap* map = GServer->MapList.Index[thisdrop->posMap];
  578. map->AddDrop( thisdrop );
  579. }
  580.  
  581. }
  582.  
  583. }
  584.  
  585. //GServer->SendToVisible( &pak, Enemy, thisdrop );
  586. GServer->SendToVisible( &pak, Enemy );
  587.  
  588. //LMA: test
  589. //OnEnemyDie( Enemy );
  590. ClearBattle(Battle);
  591. if(!is_already_dead)
  592. TakeExp(Enemy);
  593. //end of test.
  594. //Log(MSG_WARNING,"End of dead packet",);
  595.  
  596.  
  597. //LMA: test packet...
  598. //0x820 - 01 00 00 00
  599. if(Enemy->IsPlayer())
  600. {
  601. CPlayer* plkilled=(CPlayer*) Enemy;
  602. if(plkilled!=NULL)
  603. {
  604. BEGINPACKET( pak, 0x820 );
  605. ADDWORD ( pak, 1 );
  606. ADDWORD ( pak, 0 );
  607. plkilled->client->SendPacket(&pak);
  608. //Log(MSG_WARNING,"NA Packet 820 sent to %s",plkilled->CharInfo->charname);
  609. }
  610.  
  611. }
  612. else if (Enemy->IsMonster())
  613. {
  614. //LMA let's send a suicide packet so monster should be killed twice (not anymore).
  615. }
  616.  
  617. }
  618. else
  619. {
  620. //LMA: TESTDEATH
  621. ADDDWORD ( pak, hitpower );
  622.  
  623. //Logs.
  624. /*if(IsPlayer()&&Enemy->IsPlayer())
  625. {
  626. CPlayer* plkilled=(CPlayer*) Enemy;
  627. CPlayer* plkiller=(CPlayer*) this;
  628. Log(MSG_WARNING,"NA hitpower %i, critical %i, %i (%s) hitting %i (%s)",hitpower,critical,clientid,plkiller->CharInfo->charname,Enemy->clientid,plkilled->CharInfo->charname);
  629. Log(MSG_WARNING,"NA Player %i (%s) targets cid %i",clientid,plkiller->CharInfo->charname,plkiller->Battle->target);
  630. }
  631. else
  632. {
  633. Log(MSG_WARNING,"NA, Not dead, hitpower %i, critical %i (%i hitting %i)",hitpower,critical,clientid,Enemy->clientid);
  634. }*/
  635.  
  636. ADDDWORD ( pak, (hitpower>0?(critical?12:0):0) );
  637. GServer->SendToVisible( &pak, Enemy );
  638. }
  639.  
  640. Battle->lastAtkTime = clock( );
  641. ReduceABC( );
  642.  
  643. //LMA: We take fuel.
  644. if(IsPlayer()&&Status->Stance==DRIVING)
  645. {
  646. CPlayer* plkiller=(CPlayer*) this;
  647.  
  648. if(plkiller->items[136].itemnum==0||plkiller->items[139].itemnum==0)
  649. {
  650. // Log(MSG_WARNING,"%s should be riding but doesn't have a motor %i or weapon %i (normal_attack)?",plkiller->CharInfo->charname,plkiller->items[136].itemnum,plkiller->items[139].itemnum);
  651. return;
  652. }
  653.  
  654. //We take the fuel amount.
  655. //Log(MSG_INFO,"lifespan before %i, sp_value %i",plkiller->items[136].lifespan,plkiller->items[136].sp_value);
  656. plkiller->items[136].sp_value-=(int)plkiller->attack_fuel;
  657. if(plkiller->items[136].sp_value<0)
  658. {
  659. plkiller->items[136].sp_value=0;
  660. }
  661.  
  662. plkiller->items[136].lifespan=(int)(plkiller->items[136].sp_value/10);
  663.  
  664. if(plkiller->items[136].lifespan<0)
  665. {
  666. plkiller->items[136].sp_value=0;
  667. }
  668.  
  669. //Log(MSG_INFO,"lifespan after %i, sp_value %i, attack fuel %.2f",plkiller->items[136].lifespan,plkiller->items[136].sp_value,plkiller->attack_fuel);
  670.  
  671. BEGINPACKET( pak,0x7ce );
  672. ADDWORD ( pak, 0x88 ); //Slot
  673. ADDWORD ( pak, plkiller->items[136].sp_value );
  674. plkiller->client->SendPacket( &pak );
  675.  
  676. //We stop attack if needed
  677. if(plkiller->items[136].lifespan==0)
  678. {
  679. BEGINPACKET( pak, 0x796 );
  680. ADDWORD ( pak, plkiller->clientid );
  681. ADDFLOAT ( pak, plkiller->Position->current.x*100 );
  682. ADDFLOAT ( pak, plkiller->Position->current.y*100 );
  683. ADDWORD ( pak, 0x0000 );
  684. GServer->SendToVisible( &pak, plkiller );
  685.  
  686. //clear battle.
  687. ClearBattle(Battle);
  688. //Log(MSG_INFO,"No more fuel to attack");
  689. }
  690.  
  691. }
  692.  
  693.  
  694. return;
  695. }
  696.  
  697. //LMA: Resuming to NormalAttack on some occasions, mainly after skills (direct and AOEs)
  698. //when the player was in NormalAttack mode before skilling.
  699. bool CCharacter::ResumeNormalAttack( CCharacter* Enemy,bool was_aoe)
  700. {
  701. //LMA: Special case. If the player does a first attack as a skill, he doesn't go to normal attack mode.
  702. if (IsPlayer())
  703. {
  704. //On some AOE we don't have a skilltarget ?
  705. if (Enemy==NULL&&was_aoe)
  706. {
  707. Log(MSG_INFO,"After AOE without specific target.");
  708. }
  709.  
  710. //he was already fighting the monster in normal_attack mode and did a skill, now he has to resume normal_attack.
  711. if(Battle->skilltarget!=0&&Battle->contatk&&(Battle->atktarget==Battle->skilltarget))
  712. {
  713. CCharacter* NAEnemy=NULL;
  714. if(Enemy!=NULL&&(Enemy->clientid==Battle->atktarget))
  715. {
  716. NAEnemy=Enemy;
  717. }
  718. else
  719. {
  720. NAEnemy = GetCharTarget( );
  721. }
  722.  
  723. if (NAEnemy==NULL)
  724. {
  725. Log(MSG_INFO,"after skill, can't find previous target %u, stopping.",Battle->target);
  726. ClearBattle(Battle);
  727. return true;
  728. }
  729.  
  730. //Is the foe dead?
  731. if(NAEnemy->IsDead())
  732. {
  733. Log(MSG_INFO,"after skill, player is stopping battle with %u because he's dead",Battle->target);
  734. ClearBattle(Battle);
  735. return true;
  736. }
  737.  
  738. Log(MSG_INFO,"after skill, player is resuming normal_attack with %u (%u)",Battle->target,NAEnemy->clientid);
  739. Battle->atktype = NORMAL_ATTACK;
  740. Battle->skilltarget = 0;
  741. Battle->atktarget = Battle->target;
  742. Battle->skillid = 0;
  743.  
  744. return true;
  745. }
  746.  
  747. //LMA: this case is mostly after "buffs"
  748. if(Battle->target!=0&&Battle->contatk&&(Battle->atktarget==Battle->target))
  749. {
  750. CCharacter* NAEnemy=NULL;
  751. if(Enemy!=NULL&&(Enemy->clientid==Battle->atktarget))
  752. {
  753. NAEnemy=Enemy;
  754. }
  755. else
  756. {
  757. NAEnemy = GetCharTarget( );
  758. }
  759.  
  760. if (NAEnemy==NULL)
  761. {
  762. Log(MSG_INFO,"2:: after skill, can't find previous target %u, stopping.",Battle->target);
  763. ClearBattle(Battle);
  764. return true;
  765. }
  766.  
  767. //Is the foe dead?
  768. if(NAEnemy->IsDead())
  769. {
  770. Log(MSG_INFO,"2:: after skill, player is stopping battle with %u because he's dead",Battle->target);
  771. ClearBattle(Battle);
  772. return true;
  773. }
  774.  
  775. Log(MSG_INFO,"2:: after skill, player is resuming normal_attack with %u (%u)",Battle->target,NAEnemy->clientid);
  776. Battle->atktype = NORMAL_ATTACK;
  777. Battle->skilltarget = 0;
  778. Battle->atktarget = Battle->target;
  779. Battle->skillid = 0;
  780.  
  781. return true;
  782. }
  783.  
  784. //Stop...
  785. Log(MSG_INFO,"after skill, player is doing nothing.");
  786. ClearBattle(Battle);
  787. }
  788. else
  789. {
  790. Log(MSG_INFO,"after skill, monster is going to normal_attack %u",Battle->target);
  791. Battle->atktype = NORMAL_ATTACK;
  792. Battle->skilltarget = 0;
  793. Battle->atktarget = Battle->target;
  794. Battle->skillid = 0;
  795. }
  796.  
  797.  
  798. return true;
  799. }
  800.  
  801.  
  802. // do skill attack
  803. bool CCharacter::SkillAttack( CCharacter* Enemy, CSkills* skill )
  804. {
  805. Position->destiny = Position->current;
  806. if(Battle->castTime==0)
  807. {
  808. BEGINPACKET( pak, 0x7bb );
  809. ADDWORD ( pak, clientid );
  810. GServer->SendToVisible( &pak, this );
  811. Battle->castTime = clock();
  812. return true;
  813. }
  814. else
  815. {
  816. clock_t etime = clock() - Battle->castTime;
  817. if(etime<SKILL_DELAY)
  818. return true;
  819. }
  820. Battle->castTime = 0;
  821. UseAtkSkill( Enemy, skill );
  822. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  823. if(Stats->MP<0) Stats->MP=0;
  824. if(Battle->contatk)
  825. {
  826. //LMA: Resuming on NormalAttack?
  827. ResumeNormalAttack(Enemy);
  828. }
  829. else
  830. {
  831. //osprose
  832. //ClearBattle( Battle );
  833. Log(MSG_INFO,"after skill, nothing special, not in contact / range?...");
  834.  
  835. //he was already fighting the monster in normal_attack mode and did a skill, now he has to resume normal_attack.
  836. if(Battle->skilltarget!=0&&(Battle->atktarget!=Battle->skilltarget))
  837. {
  838. //Stop...
  839. Log(MSG_INFO,"after skill, player is doing nothing (first attack).");
  840. ClearBattle(Battle);
  841. }
  842.  
  843. }
  844.  
  845. GServer->DoSkillScript( this, skill ); //So far only used for summons
  846. Battle->lastAtkTime = clock( );
  847. return true;
  848. }
  849.  
  850. // do buff skill
  851. bool CCharacter::BuffSkill( CCharacter* Target, CSkills* skill )
  852. {
  853. Position->destiny = Position->current;
  854. if(Battle->castTime==0)
  855. {
  856. BEGINPACKET( pak, 0x7bb );
  857. ADDWORD ( pak, clientid );
  858. GServer->SendToVisible( &pak, (CCharacter*)this );
  859. Battle->castTime = clock();
  860. //Log(MSG_INFO,"7bb battle casttime==0");
  861. return true;
  862. }
  863. else
  864. {
  865. clock_t etime = clock() - Battle->castTime;
  866. if(etime<SKILL_DELAY)
  867. {
  868. //Log(MSG_INFO,"etime<SKILL_DELAY: %i<%i",etime,SKILL_DELAY);
  869. return true;
  870. }
  871.  
  872. }
  873.  
  874. //Log(MSG_INFO,"new stat MP %i",Stats->MP);
  875. //Log(MSG_INFO,"%i Really doing skill %i to %i",clientid,skill->id,Target->clientid);
  876.  
  877. Log(MSG_INFO,"Doing a simple buff BuffSkill");
  878. Battle->castTime = 0;
  879. UseBuffSkill( Target, skill );
  880. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  881. if(Stats->MP<0)
  882. {
  883. Stats->MP=0;
  884. }
  885.  
  886. /*
  887. ClearBattle( Battle );
  888. GServer->DoSkillScript( this, skill );
  889. */
  890.  
  891. //osprose
  892. GServer->DoSkillScript( this, skill );
  893. if(!IsMonster())
  894. {
  895. //LMA: do we have to resume a Normal Attack?
  896. ResumeNormalAttack(NULL,false);
  897. /*
  898. //ClearBattle( Battle ); // clear battle for players when they use buff skills
  899. Battle->bufftarget = 0;
  900. Battle->skilltarget = 0;
  901. Battle->skillid = 0;
  902. //Battle->atktype = NORMAL_ATTACK;
  903. Battle->atktype = 0;*/
  904. }
  905. else //Monsters need to be reset to normal attack and clear skill attacks.
  906. {
  907. Battle->bufftarget = 0;
  908. Battle->skilltarget = 0;
  909. Battle->skillid = 0;
  910. Battle->atktype = NORMAL_ATTACK;
  911. }
  912. //osprose end
  913.  
  914. Battle->lastAtkTime = clock( );
  915. return true;
  916. }
  917.  
  918. // do Debuff skill [netwolf]
  919. bool CCharacter::DebuffSkill( CCharacter* Enemy, CSkills* skill )
  920. {
  921. Position->destiny = Position->current;
  922. if(Battle->castTime==0)
  923. {
  924. BEGINPACKET( pak, 0x7bb );
  925. ADDWORD ( pak, clientid );
  926. GServer->SendToVisible( &pak, (CCharacter*)this );
  927. Battle->castTime = clock();
  928. return true;
  929. }
  930. else
  931. {
  932. clock_t etime = clock() - Battle->castTime;
  933. if(etime<SKILL_DELAY)
  934. return true;
  935. }
  936. Battle->castTime = 0;
  937. UseDebuffSkill( Enemy, skill );
  938. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  939. if(Stats->MP<0) Stats->MP=0;
  940. ClearBattle( Battle );
  941. GServer->DoSkillScript( this, skill );
  942. Battle->lastAtkTime = clock( );
  943. return true;
  944. }
  945.  
  946. //LMA: A summon does a buff skill
  947. //2do: check if master is debuffed.
  948. bool CCharacter::SummonBuffSkill( CCharacter* Target, CSkills* skill )
  949. {
  950. Position->destiny = Position->current;
  951. if(Battle->castTime==0)
  952. {
  953. BEGINPACKET( pak, 0x7bb );
  954. ADDWORD ( pak, clientid );
  955. GServer->SendToVisible( &pak, (CCharacter*)this );
  956. Battle->castTime = clock();
  957. //Log(MSG_INFO,"0x7bb");
  958. return true;
  959. }
  960. else
  961. {
  962. clock_t etime = clock() - Battle->castTime;
  963. if(etime<SKILL_DELAY)
  964. return true;
  965. }
  966.  
  967. //LMA: For now, it seems the summon buff only one time :(
  968. //Log(MSG_INFO,"Real buff skill");
  969. Battle->castTime = 0;
  970. UseBuffSkill( Target, skill );
  971. ClearBattle( Battle );
  972. GServer->DoSkillScript( this, skill );
  973. Battle->lastAtkTime = clock( );
  974. return true;
  975. }
  976.  
  977. // do AoE skill
  978. bool CCharacter::AoeSkill( CSkills* skill, CCharacter* Enemy )
  979. {
  980.  
  981. //LMA: not here since AOE can have NULL Enemy, will be catched later by the call to the skill.
  982. //bool is_already_dead=Enemy->IsDead();
  983. Log(MSG_INFO,"In AOE Skill");
  984. Position->destiny = Position->current;
  985. //Log(MSG_INFO,"Position in AOE: %.2f,%.2f",Position->current.x,Position->current.y);
  986.  
  987. //LMA: handling case of AOE_SKILLS and AOE_TARGET (the target point is not the same).
  988. fPoint goodtarget;
  989. goodtarget=Position->current;
  990. if (Battle->atktype==AOE_TARGET)
  991. {
  992. goodtarget=Position->aoedestiny;
  993. }
  994.  
  995. if(Battle->castTime==0)
  996. {
  997. BEGINPACKET( pak, 0x7bb );
  998. ADDWORD ( pak, clientid );
  999. GServer->SendToVisible( &pak, (CCharacter*)this );
  1000. Battle->castTime = clock();
  1001. return true;
  1002. }
  1003. else
  1004. {
  1005. //LMA: No delay for AOE_TARGET skill (zone)
  1006. if (Battle->atktype!=AOE_TARGET)
  1007. {
  1008. clock_t etime = clock() - Battle->castTime;
  1009. if(etime<SKILL_DELAY)
  1010. return true;
  1011. }
  1012.  
  1013. }
  1014.  
  1015. Battle->castTime = 0;
  1016. CMap* map = GServer->MapList.Index[Position->Map];
  1017.  
  1018. //osprose
  1019. //LMA: pvp ?
  1020. UINT save_atktype=Battle->atktype;
  1021.  
  1022. if(IsPlayer() || IsSummon())
  1023. {
  1024. //monsters.
  1025. for(UINT i=0;i<map->MonsterList.size();i++)
  1026. {
  1027. CMonster* monster = map->MonsterList.at(i);
  1028. if(monster->clientid == clientid) continue;
  1029. if(monster->IsSummon( ) && (map->allowpvp == 0 || monster->owner == clientid)) continue;
  1030. if(GServer->IsMonInCircle( goodtarget,monster->Position->current,(float)skill->aoeradius+1))
  1031. {
  1032. Log(MSG_INFO,"AOE Attack (1) player attacks monster %i (clientID %u) radius %.2f",monster->montype,monster->clientid,(float)skill->aoeradius+1);
  1033.  
  1034. //LMA: we have to since AOE doesn't have a specific target and atkskil resets some values.
  1035. Battle->skilltarget=monster->clientid;
  1036. Battle->skillid=skill->id;
  1037. Battle->atktype = save_atktype;
  1038. UseAtkSkill( (CCharacter*) monster, skill );
  1039.  
  1040. //LMA: TEST is there a "buff/debuff" skill with it too?
  1041. /*
  1042. if (skill->status[0]!=0&&skill->buff[0]!=0&&monster->Stats->HP>0)
  1043. {
  1044. UseBuffSkill( (CCharacter*)monster, skill );
  1045. Log(MSG_INFO,"AOE Attack (1) player buffs monster %i",monster->montype);
  1046. }
  1047. */
  1048.  
  1049. //LMA: AIP time.
  1050. monster->DoAi(monster->thisnpc->AI, 3);
  1051. //END OF TEST.
  1052.  
  1053. }
  1054.  
  1055. }
  1056.  
  1057. //Pvp, group Vs group, here all.
  1058. if(map->allowpvp!=0&&IsPlayer())
  1059. {
  1060. CPlayer* plattacker=(CPlayer*) this;
  1061. for (UINT i=0;i<map->PlayerList.size();i++)
  1062. {
  1063. CPlayer* thisplayer=map->PlayerList.at(i);
  1064. if(thisplayer==NULL)
  1065. {
  1066. continue;
  1067. }
  1068.  
  1069. //not attacking allies.
  1070. if(thisplayer->pvp_id==plattacker->pvp_id)
  1071. {
  1072. continue;
  1073. }
  1074.  
  1075. if(GServer->IsMonInCircle( goodtarget,thisplayer->Position->current,(float)skill->aoeradius+1))
  1076. {
  1077. //LMA: we have to since AOE doesn't have a specific target and atkskil resets some values.
  1078. Battle->skilltarget=thisplayer->clientid;
  1079. Battle->skillid=skill->id;
  1080. Battle->atktype = save_atktype;
  1081. UseAtkSkill( (CCharacter*) thisplayer, skill );
  1082. Log(MSG_WARNING,"AOE Skill pvp player %s",thisplayer->CharInfo->charname);
  1083. }
  1084.  
  1085. }
  1086.  
  1087. }
  1088.  
  1089. }
  1090.  
  1091. if(IsMonster() && !IsSummon())
  1092. {
  1093. for(UINT i=0;i<map->PlayerList.size();i++)
  1094. {
  1095. CPlayer* player = map->PlayerList.at(i);
  1096. if(player->clientid == clientid) continue;
  1097. if(GServer->IsMonInCircle( goodtarget,player->Position->current,(float)skill->aoeradius+1))
  1098. {
  1099. Log(MSG_INFO,"AOE Attack (2) monster attacks player %s radius %.2f",player->CharInfo->charname,(float)skill->aoeradius+1);
  1100. UseAtkSkill( (CCharacter*) player, skill );
  1101. }
  1102.  
  1103. }
  1104. }
  1105. //osprose end
  1106.  
  1107. if(Enemy!=NULL)
  1108. {
  1109. if(!Enemy->IsDead( ))
  1110. {
  1111. Battle->atktarget = Battle->target;
  1112. Battle->atktype = NORMAL_ATTACK;
  1113. Battle->skilltarget = 0;
  1114. Battle->skillid = 0;
  1115. }
  1116. else
  1117. {
  1118. ClearBattle( Battle );
  1119. }
  1120.  
  1121. }
  1122. else
  1123. {
  1124. ResumeNormalAttack(NULL,true);
  1125. //ClearBattle( Battle );
  1126. }
  1127.  
  1128. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  1129. if(Stats->MP<0) Stats->MP=0;
  1130. Battle->lastAtkTime = clock( );
  1131. return true;
  1132. }
  1133.  
  1134. bool CCharacter::AoeBuff( CSkills* skill )
  1135. {
  1136. Position->destiny = Position->current;
  1137.  
  1138. if(Battle->castTime==0)
  1139. {
  1140. BEGINPACKET( pak, 0x7bb );
  1141. ADDWORD ( pak, clientid );
  1142. GServer->SendToVisible( &pak, (CCharacter*)this );
  1143. Battle->castTime = clock();
  1144. return true;
  1145. }
  1146. else
  1147. {
  1148. clock_t etime = clock() - Battle->castTime;
  1149. if(etime<SKILL_DELAY)
  1150. return true;
  1151. }
  1152.  
  1153. Battle->castTime = 0;
  1154. CMap* map = GServer->MapList.Index[Position->Map];
  1155.  
  1156. //checking if buffing party and no party so himself :)
  1157. if(skill->target==1 && GetParty( )==NULL)
  1158. {
  1159. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  1160. if(Stats->MP<0) Stats->MP=0;
  1161.  
  1162. Log(MSG_INFO,"AOEBuffs, buffing only myself");
  1163. UseBuffSkill( this, skill );
  1164.  
  1165. //LMA: do we have to resume a Normal Attack?
  1166. ResumeNormalAttack(NULL,false);
  1167. //ClearBattle( Battle );
  1168. //Battle->lastAtkTime = clock( );
  1169.  
  1170. return true;
  1171. }
  1172.  
  1173. //LMA: Summon don't go there...
  1174. //if(IsMonster())
  1175. if(IsMonster()&&!IsSummon())
  1176. {
  1177. Log(MSG_INFO,"Monster in AOE Buff");
  1178. for(UINT i=0;i<map->MonsterList.size();i++)
  1179. {
  1180. CMonster* monster = map->MonsterList.at(i);
  1181. switch(skill->target)
  1182. {
  1183. case tPartyMember: // party
  1184. break;
  1185. case 2: //tClanMember
  1186. break;
  1187. case 3: //tAlly
  1188. case 7: //tAllCharacters
  1189. case 8: //tAllMembers. all characters
  1190. {
  1191. //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough monster");
  1192. if(GServer->IsMonInCircle( Position->current,monster->Position->current,(float)skill->aoeradius + 1))
  1193. {
  1194. UseBuffSkill( (CCharacter*)monster, skill );
  1195. }
  1196. }
  1197. break;
  1198. case 5: //hostile.
  1199. break;
  1200. }
  1201. }
  1202.  
  1203. }
  1204. else
  1205. {
  1206. //players / summons
  1207. for(UINT i=0;i<map->PlayerList.size();i++)
  1208. {
  1209. CPlayer* player = map->PlayerList.at(i);
  1210. switch(skill->target)
  1211. {
  1212. case 1: // party
  1213. {
  1214. if(player->Party->party==GetParty( ))
  1215. {
  1216. if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius+1))
  1217. {
  1218. UseBuffSkill( (CCharacter*)player, skill );
  1219. }
  1220.  
  1221. }
  1222. }
  1223. break;
  1224. case 2: //clan member
  1225. {
  1226. if (player->Clan == GetClan( ))
  1227. {
  1228. //Log(MSG_INFO,"Applying AOE buff as long as I can find a close enough clan member");
  1229. if(GServer->IsMonInCircle( Position->current, player->Position->current, (float)skill->aoeradius + 1 ) )
  1230. {
  1231. UseBuffSkill( (CCharacter*)player, skill );
  1232. }
  1233.  
  1234. }
  1235. }
  1236. break;
  1237. case 3: //ally
  1238. case 7: //everyone
  1239. case 8: //all characters
  1240. {
  1241. if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius + 1))
  1242. {
  1243. UseBuffSkill( (CCharacter*)player, skill );
  1244. }
  1245.  
  1246. }
  1247. break;
  1248. case 5: //hostile
  1249. break;
  1250. }
  1251. }
  1252.  
  1253. }
  1254.  
  1255.  
  1256. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  1257. if(Stats->MP<0) Stats->MP=0;
  1258.  
  1259. //ClearBattle( Battle );
  1260. //osprose
  1261. Battle->bufftarget = 0;
  1262. Battle->skilltarget = 0;
  1263. Battle->skillid = 0;
  1264.  
  1265. //LMA: no because in weird cases (party+first target buff+aoe buff)
  1266. //a party buffer could attack a buffed one.
  1267. //Battle->atktype = NORMAL_ATTACK;
  1268. Battle->atktype = 0;
  1269. //ClearBattle( Battle );
  1270. //osprose end
  1271.  
  1272. Battle->lastAtkTime = clock( );
  1273.  
  1274. //LMA: do we have to resume a Normal Attack?
  1275. ResumeNormalAttack(NULL,false);
  1276.  
  1277.  
  1278. return true;
  1279. }
  1280.  
  1281. // Aoe Debuff [netwolf]
  1282. bool CCharacter::AoeDebuff( CSkills* skill, CCharacter* Enemy )
  1283. {
  1284. Position->destiny = Position->current;
  1285.  
  1286. if(Battle->castTime==0)
  1287. {
  1288. BEGINPACKET( pak, 0x7bb );
  1289. ADDWORD ( pak, clientid );
  1290. GServer->SendToVisible( &pak, (CCharacter*)this );
  1291. Battle->castTime = clock();
  1292. return true;
  1293. }
  1294. else
  1295. {
  1296. clock_t etime = clock() - Battle->castTime;
  1297. if(etime<SKILL_DELAY)
  1298. return true;
  1299. }
  1300. Battle->castTime = 0;
  1301.  
  1302. CMap* map = GServer->MapList.Index[Position->Map];
  1303. for(UINT i=0;i<map->MonsterList.size();i++)
  1304. {
  1305. CMonster* monster = map->MonsterList.at(i);
  1306. if(monster->clientid==clientid) continue;
  1307. if(IsSummon( ) || IsPlayer( ))
  1308. {
  1309. if(monster->IsSummon( ) && (map->allowpvp==0 || monster->owner==clientid)) continue;
  1310. }
  1311. else
  1312. {
  1313. if(!monster->IsSummon( )) continue;
  1314. }
  1315. if(GServer->IsMonInCircle( Position->current,monster->Position->current,(float)skill->aoeradius+1))
  1316. {
  1317. Log(MSG_INFO,"AOE Debuff (1) monster %i",monster->montype);
  1318. UseDebuffSkill( (CCharacter*) monster, skill );
  1319. }
  1320.  
  1321. }
  1322.  
  1323. if(map->allowpvp!=0 || (IsMonster( ) && !IsSummon( )))
  1324. {
  1325. for(UINT i=0;i<map->PlayerList.size();i++)
  1326. {
  1327. CPlayer* player = map->PlayerList.at(i);
  1328. if(player->clientid==clientid) continue;
  1329. if(GServer->IsMonInCircle( Position->current,player->Position->current,(float)skill->aoeradius+1))
  1330. {
  1331. Log(MSG_INFO,"AOE Debuff (2) player %s",player->CharInfo->charname);
  1332. //UseDebuffSkillTest( (CCharacter*) player, skill );
  1333. UseDebuffSkill( (CCharacter*) player, skill );
  1334. }
  1335.  
  1336. }
  1337. }
  1338.  
  1339. Stats->MP -= (skill->mp - (skill->mp * Stats->MPReduction / 100));
  1340. if(Stats->MP<0) Stats->MP=0;
  1341. //ClearBattle( Battle );
  1342. Battle->lastAtkTime = clock( );
  1343.  
  1344. //LMA: do we have to resume a Normal Attack?
  1345. ResumeNormalAttack(NULL,false);
  1346.  
  1347.  
  1348. return true;
  1349. }
  1350.  
  1351. // use skill attack
  1352. void CCharacter::UseAtkSkill( CCharacter* Enemy, CSkills* skill, bool deBuff )
  1353. {
  1354. //LMA: Sometimes it's fired several times, no need to kill several times ;)
  1355. bool is_already_dead=Enemy->IsDead();
  1356.  
  1357. //We Check if The Skill need a Bow, Gun, Launcher or Crossbow and reduce the number of Arrow, Bullet or Canon the player have by 1 (Client is Buged)
  1358. bool need_arrows=false;
  1359. if(skill->weapon[0]==BOW || skill->weapon[0] == GUN || skill->weapon[0] == LAUNCHER || skill->weapon[0] == CROSSBOW)
  1360. {
  1361. need_arrows=true;
  1362. }
  1363. if(skill->weapon[1]==BOW || skill->weapon[1] == GUN || skill->weapon[1] == LAUNCHER || skill->weapon[1] == CROSSBOW)
  1364. {
  1365. need_arrows=true;
  1366. }
  1367. if (need_arrows)
  1368. {
  1369. ReduceABC(1,false); //We Reduce by 1 because Client is Buged, and we set the flag do_packet to false
  1370. }
  1371.  
  1372. reduceItemsLifeSpan( false );
  1373. Enemy->reduceItemsLifeSpan(true);
  1374.  
  1375. //Skill power calculations LMA/Tomiz : New Way
  1376. long int skillpower=0;
  1377. long int level_diff = Stats->Level - Enemy->Stats->Level;
  1378.  
  1379. //LMA: fix by will1023631
  1380. /*if(Enemy->IsMonster() && skill->formula !=0)
  1381. {
  1382. if(level_diff >= 1)
  1383. {
  1384. skillpower += Stats->Attack_Power * (level_diff / 5) + (level_diff*2);
  1385. }
  1386. else
  1387. {
  1388. skillpower += Stats->Attack_Power - (level_diff / 2);
  1389. }
  1390.  
  1391. }*/
  1392.  
  1393. if(skill->formula !=0)
  1394. {
  1395. skillpower += Stats->Attack_Power;
  1396. }
  1397. unsigned int skill_hitvalue = (unsigned int)floor(Stats->Accury * 50 / Enemy->Stats->Dodge);
  1398. if(skill_hitvalue>100) skill_hitvalue = 100;
  1399. switch(skill->formula)//Magical Or Weapon Type Skill?
  1400. {
  1401. case 1: // Reliable Weapon Attack : Shield Stun, Spin Attack, Weapon Launcher, Seismic Impact, Achilles' Heel Strike, Slugger, Blood Attack,
  1402. // Impact Wave, Heavy Bow Shot, Fierce Cudgeling, Staff Stun, Stun Arrow, Spiral Kick, Aimed Triple Arrow, Point Blank Arrow,
  1403. // Screw Attack, Bloody Assault, Phoenix Slash, Flame Slash, Freezing Assault, Circle Break, Impact Arrow, Sucker Punch,
  1404. // Master Twin Shot, Zulie Boltcher Smash, Zulie Stun, Mastered Triple Shot, Flame Stun Burst, Aimed Triple Shot and Poison Shot
  1405. {
  1406. skillpower+=skill->atkpower +(long int)floor(GetSen( )/2);
  1407. skillpower+=skillpower*GetSen( )/10000;
  1408. skillpower-=skillpower*Enemy->Stats->Defense / 10000;
  1409. skillpower-=Enemy->Stats->Defense * 10 / 100;
  1410. if(GServer->RandNumber( 0, 100 )>skill_hitvalue) skillpower /= 2; // Miss results in damage cut in half.
  1411. }
  1412. break;
  1413. case 2: // Reliable Magic Attack : Soul Wreck, Space Attack, Combat Cry, Wind Storm, Tornado, Voltage Jolt, Icy Hailstorm, Fire Ring,
  1414. // Meteorite Strike, Voltage Shock, Freezing Chill, Tempest, Glaciating Chill, Hurricane, Soul Shock, Soul Electric,
  1415. // Permafrost Chill, Hellfire, Mana Burn, Elemental Bolt, Elemental Spike, Meteorite Flow, Mana Wave, Voltage Storm,
  1416. // Flame Hawk, Phoenix Arrow, Mystic Knife, Plasma Falcon, Sniping, Zulie Storm and Hypno Shot
  1417. {
  1418. skillpower+=skill->atkpower +(long int)floor(GetInt( )/2);
  1419. skillpower+=skillpower*GetInt( )/10000;
  1420. skillpower-=skillpower*Enemy->Stats->Magic_Defense / 10000;
  1421. skillpower-=Enemy->Stats->Magic_Defense * 10 / 100;
  1422. if(GServer->RandNumber( 0, 100 )>skill_hitvalue) skillpower /= 2; // Miss results in damage cut in half.
  1423. }
  1424. break;
  1425. case 3: // (Unreliable) Weapon Attack : Double Attack, Triple Attack, Fatal Thrust, Piercing Lunge, Voltage Crash, Heavy Attack, Leap Attack,
  1426. // Lightning Crasher, Geon Archangel Crumpler, Longinus' Attack, Champion Hit, Taunt Shot, Slow Shot, Clamp Arrow, Double Arrow,
  1427. // Shackle Arrow, Triple Arrow, Double Slash, Focused Impact, Triple Slash, Katar Upper, Dividing Cleave, Poison Arrow,
  1428. // Entangling Arrow, Combo Slash, Crazy-style Slash, Quick-style Assault, Twin Shot, Demolition Expertise, Triple Shot,
  1429. // Shrapnel Burst, Toxic Shot, Cannon Splash Burst and Kill (Anti-Crime)
  1430. {
  1431. skillpower+=skill->atkpower +(long int)floor(GetSen( )/2);
  1432. skillpower+=skillpower*GetSen( )/10000;
  1433. skillpower-=skillpower*Enemy->Stats->Defense / 10000;
  1434. skillpower-=Enemy->Stats->Defense * 10 / 100;
  1435. if(GServer->RandNumber( 0, 100 )>skill_hitvalue) skillpower = 0; // Complete Miss.
  1436. }
  1437. break;
  1438. case 4: // (Unreliable) Magic Attack : Sword Force, Swords of Divinity, Ice Bolt, Frostbiter, Mana Bolt, Mana Spear, Mana Drop,
  1439. // Poison Knife and Venom Knife
  1440. {
  1441. skillpower+=skill->atkpower +(long int)floor(GetInt( )/2);
  1442. skillpower+=skillpower*GetInt( )/10000;
  1443. skillpower-=skillpower*Enemy->Stats->Magic_Defense / 10000;
  1444. skillpower-=Enemy->Stats->Magic_Defense * 10 / 100;
  1445. if(GServer->RandNumber( 0, 100 )>skill_hitvalue) skillpower = 0; // Complete Miss.
  1446. }
  1447. break;
  1448. case 6: // Dual Scratch
  1449. {
  1450. skillpower+=60;
  1451. skillpower+=skillpower*GetSen( )/10000;
  1452. skillpower-=skillpower*Enemy->Stats->Defense / 10000;
  1453. skillpower-=Enemy->Stats->Defense * 10 / 100;
  1454. if(GServer->RandNumber( 0, 100 )>skill_hitvalue) skillpower = 0; // Complete Miss.
  1455. }
  1456. break;
  1457. default:
  1458. {
  1459. skillpower += 5;
  1460. }
  1461. break;
  1462. }
  1463.  
  1464. if(Enemy->IsMonster())
  1465. {
  1466. if(level_diff >= 5)
  1467. {
  1468. skillpower += Stats->Attack_Power * (level_diff / 5) + (level_diff*2);
  1469. }
  1470. else if (level_diff < 5 && level_diff > 0)
  1471. {
  1472. skillpower += Stats->Attack_Power - Stats->Attack_Power*(level_diff / 5);
  1473. }
  1474. else if (level_diff <= 0)
  1475. {
  1476. skillpower += Stats->Attack_Power - (level_diff / 2);
  1477. }
  1478. }
  1479. else if(Enemy->IsPlayer())
  1480. {
  1481. if(level_diff >= 1)
  1482. {
  1483. skillpower += Stats->Attack_Power * (level_diff / 5) + (level_diff*2);
  1484. }
  1485. else
  1486. {
  1487. skillpower += Stats->Attack_Power - (level_diff / 2);
  1488. }
  1489.  
  1490. }
  1491. switch(skill->formula)//Magical Or Weapon Type Skill?
  1492. {
  1493. case 1://Weapon type dmg
  1494. {
  1495. skillpower+=skill->atkpower +(long int)floor(GetSen( )/2);
  1496. skillpower+=skillpower*GetSen( )/10000;
  1497. skillpower-=skillpower*Stats->Defense / 10000;
  1498. skillpower-= Stats->Defense * 5 / 100;
  1499. // Log(MSG_INFO,"%i cast Weapon Dmg Skill with %i sen, Attack power %u, skillpower %li, Deff %u, level diff %li, to %i",clientid,GetSen( ),skill->atkpower,skillpower,Enemy->Stats->Defense,level_diff,Enemy->clientid);
  1500. }
  1501. break;
  1502. case 2://Magical type dmg
  1503. {
  1504. skillpower+=skill->atkpower +(long int)floor(GetInt( )/2);
  1505. skillpower+=skillpower*GetInt( )/10000;
  1506. skillpower-=skillpower*Stats->Magic_Defense / 10000;
  1507. skillpower-= Stats->Magic_Defense * 5 / 100;
  1508. // Log(MSG_INFO,"%i cast Magical Dmg Skill with %i int, Attack power %u, skillpower %li, MDeff %u, level diff %li, to %i",clientid,GetInt( ),skill->atkpower,skillpower,Enemy->Stats->Magic_Defense,level_diff,Enemy->clientid);
  1509. }
  1510. break;
  1511. default:
  1512. {
  1513. skillpower += 5;
  1514. Log(MSG_INFO,"%i cast Unknow Formula Skill (%i), Attack power %u, skillpower %li, Deff %u,MDeff %u, level diff %li, to %i",clientid,skill->formula,skill->atkpower,skillpower,Enemy->Stats->Defense,Enemy->Stats->Magic_Defense,level_diff,Enemy->clientid);
  1515. }
  1516. break;
  1517. }
  1518. //END Skill power calculations LMA/Tomiz : New Way
  1519.  
  1520. //Tell enemy he's attacked & add damage & send the dmg packet
  1521. // Log(MSG_INFO,"Atk Skill damage %li, Enemy HP before %li",skillpower,Enemy->Stats->HP);
  1522.  
  1523. bool bflag = false;
  1524. Enemy->OnBeAttacked( this );
  1525. if(skillpower<=0) skillpower = 0;
  1526. if(IsPlayer())//Add Dmg
  1527. {
  1528. if( Stats->ExtraDamage_add != 0)
  1529. {
  1530. //LMA: ED, Devilking / Arnold
  1531. long int hitsave=skillpower;
  1532. skillpower += ((skillpower * Stats->ExtraDamage_add) / 100);
  1533. // Log(MSG_INFO,"ExtraDmg Skill atk: before %i, after %i (ED: %i)",hitsave,skillpower,Stats->ExtraDamage_add);
  1534. }
  1535. }
  1536. if(!Enemy->IsSummon( ) && Enemy->IsMonster( ))
  1537. {
  1538. Enemy->AddDamage( this, (long long) skillpower );
  1539. Enemy->damagecounter+= (long long) skillpower;// is for AI
  1540. }
  1541. Enemy->Stats->HP -= (long long) skillpower;
  1542. // Log(MSG_INFO,"Atk Skill damage %li, Enemy HP after %li",skillpower,Enemy->Stats->HP);
  1543.  
  1544. // actually the target was hit, if it was sleeping, set duration of
  1545. // sleep to 0. map process will remove sleep then at next player-update
  1546. if (Enemy->Status->Sleep != 0xff) {
  1547. Enemy->MagicStatus[Enemy->Status->Sleep].Duration = 0;
  1548. }
  1549.  
  1550. //LMA: patch by sickb0y
  1551. //Problems with some mage skills.
  1552. /*
  1553. BEGINPACKET( pak, 0x7b6 );
  1554. ADDWORD ( pak, Enemy->clientid );
  1555. ADDWORD ( pak, clientid );
  1556. ADDDWORD ( pak, 0x000007f8 );
  1557. ADDBYTE ( pak, 0x00 );
  1558. ADDDWORD ( pak, skillpower );
  1559. */
  1560.  
  1561. //LMA: forcing the HP amount value, only when it's supposed to be dead side.
  1562. if(Enemy->IsMonster()&&Enemy->IsDead())
  1563. {
  1564. BEGINPACKET( pak, 0x79f );
  1565. ADDWORD ( pak, Enemy->clientid );
  1566. ADDDWORD ( pak, 1);
  1567. GServer->SendToVisible( &pak, Enemy );
  1568. // Log(MSG_INFO,"death skill atk for %i, amount: %i",Enemy->clientid,skillpower);
  1569. }
  1570.  
  1571. unsigned short command = (skill->skilltype == 6 || skill->skilltype == 9) ? 0x799 : 0x7b6;
  1572. BEGINPACKET( pak, command );
  1573.  
  1574. if(command == 0x799)
  1575. {
  1576. ADDWORD ( pak, clientid );
  1577. ADDWORD ( pak, Enemy->clientid );
  1578. //LMA: Skillpower elsewhere.
  1579. //ADDDWORD ( pak, skillpower );
  1580. }
  1581. else
  1582. {
  1583. ADDWORD ( pak, Enemy->clientid );
  1584. ADDWORD ( pak, clientid );
  1585. ADDDWORD ( pak, 0x000007f8 );
  1586. ADDBYTE ( pak, 0x00 );
  1587. //LMA: Skillpower elsewhere.
  1588. //ADDDWORD ( pak, skillpower );
  1589. }
  1590.  
  1591. //end of patch
  1592.  
  1593. //If Enemy is killed
  1594. if(Enemy->IsDead())
  1595. {
  1596. //LMA: Skillpower elsewhere.
  1597. //ADDDWORD ( pak, Enemy->Stats->MaxHP);
  1598. ADDDWORD ( pak, skillpower);
  1599.  
  1600. //LMA: UW handling, adding support for other quests.
  1601. //if (!is_already_dead&&(GServer->MapList.Index[Position->Map]->QSDkilling>0||GServer->MapList.Index[Position->Map]->QSDDeath>0)&&IsPlayer()&&Enemy->IsPlayer())
  1602. if (!is_already_dead&&((GServer->MapList.Index[Position->Map]->QSDkilling>0&&IsPlayer()&&Enemy->IsPlayer())||(GServer->MapList.Index[Position->Map]->QSDDeath&&Enemy->IsPlayer())))
  1603. {
  1604. // Log(MSG_INFO,"UWKILL begin skill atk");
  1605. UWKill(Enemy);
  1606. }
  1607.  
  1608. //LMA: test for quest hack (stackable).
  1609. #ifdef QHACK
  1610. if(!is_already_dead&&Enemy->die_quest!=0&&Enemy->IsMonster()&&IsPlayer())
  1611. {
  1612. QuestKill(Enemy->die_quest);
  1613. }
  1614. #endif
  1615. //LMA END
  1616.  
  1617. // Log(MSG_INFO,"Enemy is dead");
  1618. CDrop* thisdrop = NULL;
  1619. ADDDWORD ( pak, 16 );
  1620.  
  1621. if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( ))
  1622. {
  1623. //LMA: looping the drops (double drop medal for example).
  1624. int nb_drops=1;
  1625. if (IsPlayer())
  1626. {
  1627. CPlayer* plkiller=(CPlayer*) this;
  1628. nb_drops=plkiller->bonusddrop;
  1629. // Log(MSG_INFO,"Drop time, there should be %i drops",nb_drops);
  1630. }
  1631.  
  1632. //No drop if already dead and drop done.
  1633. if(Enemy->drop_dead)
  1634. {
  1635. Log(MSG_WARNING,"Trying to make a monster (CID %u, type %u) drop again but already did.",Enemy->clientid,Enemy->char_montype);
  1636. nb_drops=0;
  1637. }
  1638.  
  1639. for (int k=0;k<nb_drops;k++)
  1640. {
  1641. thisdrop = Enemy->GetDrop( );
  1642. if(thisdrop!=NULL)
  1643. {
  1644. // Log(MSG_INFO,"Dropping Nb %i",k);
  1645. CMap* map = GServer->MapList.Index[thisdrop->posMap];
  1646. map->AddDrop( thisdrop );
  1647. }
  1648.  
  1649. }
  1650.  
  1651. }
  1652.  
  1653. GServer->SendToVisible( &pak, Enemy );
  1654. //LMA: end of test.
  1655.  
  1656. //LMA: test
  1657. //OnEnemyDie( Enemy );
  1658. ClearBattle(Battle);
  1659. if(!is_already_dead)
  1660. {
  1661. TakeExp(Enemy);
  1662. }
  1663. //end of test.
  1664.  
  1665. //LMA: Special Packet to tell if the player is dead?
  1666. if(Enemy->IsPlayer())
  1667. {
  1668. CPlayer* plkilled=(CPlayer*) Enemy;
  1669. if(plkilled!=NULL)
  1670. {
  1671. BEGINPACKET( pak, 0x820 );
  1672. ADDWORD ( pak, 1 );
  1673. ADDWORD ( pak, 0 );
  1674. plkilled->client->SendPacket(&pak);
  1675. Log(MSG_WARNING,"Packet 820 sent to %s",plkilled->CharInfo->charname);
  1676. }
  1677.  
  1678. }
  1679. else if (Enemy->IsMonster())
  1680. {
  1681. //LMA let's send a suicide packet so monster should be killed twice (not anymore).
  1682. }
  1683.  
  1684. }
  1685. else
  1686. {
  1687. //LMA: Skillpower elsewhere.
  1688. ADDDWORD ( pak, skillpower );
  1689.  
  1690. //If enemy is still alive
  1691. Log(MSG_INFO,"The enemy is still alive");
  1692. //ADDDWORD ( pak, 4 );
  1693. ADDDWORD ( pak, 0x00 );
  1694. GServer->SendToVisible( &pak, Enemy );
  1695.  
  1696. //osprose
  1697. //if (deBuff) return;
  1698.  
  1699. //GOTO debuffing section
  1700. //bflag = GServer->AddDeBuffs( skill, Enemy, GetInt( ) );
  1701. bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) ); // send to AddBuffs instead.
  1702.  
  1703. //Send (de)buff information to the whole world
  1704. if(skill->nbuffs>0 && bflag)
  1705. {
  1706. Log(MSG_INFO,"The enemy cliendID %u is being buffed with %u",Battle->skilltarget,Battle->skillid);
  1707. BEGINPACKET( pak, 0x7b5 );
  1708. ADDWORD ( pak, Battle->skilltarget );
  1709. ADDWORD ( pak, clientid );
  1710. ADDWORD ( pak, Battle->skillid );
  1711. ADDWORD ( pak, GetInt( ) );
  1712. ADDBYTE ( pak, skill->nbuffs );
  1713. GServer->SendToVisible( &pak, Enemy );
  1714. }
  1715.  
  1716. //LMA: test, trying to send back the monster HP amount.
  1717. /*if(Enemy->IsMonster())
  1718. {
  1719. //LMA: Trying to update real HP amount.
  1720. Log(MSG_INFO,"Sending back monster HP amount");
  1721. BEGINPACKET( pak, 0x79f );
  1722. ADDWORD ( pak, Enemy->clientid );
  1723. ADDDWORD ( pak, Enemy->Stats->HP );
  1724. GServer->SendToVisible( &pak, Enemy );
  1725. }*/
  1726.  
  1727. }
  1728. if (deBuff) return;
  1729. //Send skill animation to the world
  1730. RESETPACKET( pak, 0x7b9);
  1731. ADDWORD ( pak, clientid);
  1732. ADDWORD ( pak, Battle->skillid);
  1733.  
  1734. //LMA: Is it really used?
  1735. if(command != 0x799)
  1736. {
  1737. ADDWORD ( pak, 1);
  1738. }
  1739.  
  1740. GServer->SendToVisible( &pak, this );
  1741.  
  1742. //osprose
  1743. /*Battle->bufftarget = 0;
  1744. Battle->skilltarget = 0;
  1745. Battle->skillid = 0;
  1746. Battle->atktype = NORMAL_ATTACK;*/
  1747. //osprose end
  1748.  
  1749. return;
  1750. }
  1751.  
  1752. // use buff skill
  1753. void CCharacter::UseBuffSkill( CCharacter* Target, CSkills* skill )
  1754. {
  1755. bool bflag = false;
  1756. bflag = GServer->AddBuffs( skill, Target, GetInt( ) );
  1757. Log(MSG_INFO,"In UseBuffSkills, skill %i, nbuffs %i, bflag %i to %u",skill->id,skill->nbuffs,bflag,Target->clientid);
  1758. if(skill->nbuffs>0 && bflag == true)
  1759. {
  1760. BEGINPACKET( pak, 0x7b5 );
  1761. ADDWORD ( pak, Target->clientid );
  1762. ADDWORD ( pak, clientid );
  1763. ADDWORD ( pak, Battle->skillid );
  1764. ADDWORD ( pak, GetInt( ) );
  1765. ADDBYTE ( pak, skill->nbuffs );
  1766. GServer->SendToVisible( &pak, Target );
  1767. }
  1768. BEGINPACKET( pak, 0x7b9);
  1769. ADDWORD ( pak, clientid);
  1770. ADDWORD ( pak, Battle->skillid);
  1771. ADDWORD ( pak, 1);
  1772. GServer->SendToVisible( &pak, (CCharacter*)this );
  1773.  
  1774. //LMA: Patch for Revive stuff...
  1775. if(skill->skilltype==20&&Target->IsPlayer())
  1776. {
  1777. CPlayer* thisclient = GServer->GetClientByID(Target->clientid,Position->Map);
  1778. if (thisclient==NULL)
  1779. {
  1780. CPlayer* thisclient = GServer->GetClientByID(Target->clientid,Target->Position->Map);
  1781. }
  1782.  
  1783. if (thisclient==NULL)
  1784. {
  1785. Log(MSG_WARNING,"Can't find clientID %i for revive...",Target->clientid);
  1786. return;
  1787. }
  1788.  
  1789. //not exact but should be fair enough...
  1790. Log(MSG_INFO,"before Revive, HP %I64i, Xp %I64i, skill %i",thisclient->Stats->HP,thisclient->CharInfo->Exp,skill->atkpower);
  1791. unsigned long long new_exp=(unsigned long long) (thisclient->CharInfo->Exp*3*skill->atkpower/(100*100));
  1792. thisclient->CharInfo->Exp+=new_exp;
  1793. thisclient->Stats->HP=thisclient->Stats->MaxHP*30/100;
  1794. Log(MSG_INFO,"Revive, new HP %I64i, %I64i, Xp added %I64i, new %I64i",thisclient->Stats->HP,Target->Stats->HP,new_exp,thisclient->CharInfo->Exp);
  1795. BEGINPACKET( pak, 0x79b );
  1796. ADDDWORD ( pak, thisclient->CharInfo->Exp );
  1797. ADDWORD ( pak, thisclient->CharInfo->stamina );
  1798. ADDWORD ( pak, 0 );
  1799. thisclient->client->SendPacket( &pak );
  1800. }
  1801. //End of Patch.
  1802.  
  1803.  
  1804. return;
  1805. }
  1806.  
  1807. // use Debuff skill
  1808. void CCharacter::UseDebuffSkill( CCharacter* Enemy, CSkills* skill )
  1809. {
  1810. bool bflag = false;
  1811. bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) );
  1812. Log(MSG_INFO,"debufskill %i, %i",clientid,Enemy->clientid);
  1813. if(skill->nbuffs>0 && bflag == true)
  1814. {
  1815. //Log(MSG_INFO,"debufskill %i, %i",clientid,Enemy->clientid);
  1816. BEGINPACKET( pak, 0x7b5 );
  1817. ADDWORD ( pak, Enemy->clientid );
  1818. ADDWORD ( pak, clientid );
  1819. ADDWORD ( pak, Battle->skillid );
  1820. ADDWORD ( pak, GetInt( ) );
  1821. ADDBYTE ( pak, skill->nbuffs );
  1822. GServer->SendToVisible( &pak, Enemy );
  1823. //GServer->SendToAllInMap(&pak,this->Position->Map);
  1824. }
  1825. BEGINPACKET( pak, 0x7b9);
  1826. ADDWORD ( pak, clientid);
  1827. ADDWORD ( pak, Battle->skillid);
  1828. //ADDWORD ( pak, 1);
  1829. GServer->SendToVisible( &pak, (CCharacter*)this );
  1830. }
  1831.  
  1832. // Use a skill (gm command)
  1833. bool CCharacter::UseSkill( CSkills* skill, CCharacter *Target )
  1834. {
  1835. if (skill->atkpower > 0)
  1836. {
  1837. Log(MSG_INFO, "Need to do %i%s %s in range %i to target %i",
  1838. ( skill->atkpower ),
  1839. ( (skill->range > 0) ? " AOE" : "" ),
  1840. ( (GServer->isSkillTargetFriendly(skill)) ? "healing" : "damage" ),
  1841. ( skill->range ),
  1842. ( skill->target ) );
  1843. }
  1844. for (int i = 0; i < 2; i++) {
  1845. Log(MSG_INFO, "Status ID: %i", skill->status[i]);
  1846. if (skill->status[i] == 0) continue;
  1847. CStatus* status = GServer->GetStatusByID(skill->status[i]);
  1848. if (status == NULL) continue;
  1849. /************************
  1850. We'll probably need to use status->decrease (Figure out whether buf is up/down
  1851. status->repeat will tell us whether it's a one-time (Stat Boost [2]), repeat
  1852. (Recovery, continueing damage [1]) or Special (Status Effect [3]).
  1853. ************************/
  1854. if (status->repeat == 1) // Continuous
  1855. {
  1856. Log(MSG_INFO, "Need to take stat %i and %s it by %i%s over %i seconds", skill->buff[i],
  1857. ((status->decrease) ? "decrease" : "increase"),
  1858. ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]),
  1859. ((skill->value1[i] != 0) ? "" : "%"), skill->duration);
  1860.  
  1861. } else if (status->repeat == 2) // Once (Stat Boost)
  1862. {
  1863. Log(MSG_INFO, "Need to take stat %i and %s it by %i%s for %i seconds", skill->buff[i],
  1864. ((status->decrease) ? "decrease" : "increase"),
  1865. ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]),
  1866. ((skill->value1[i] != 0) ? "" : "%"), skill->duration);
  1867.  
  1868. } else if (status->repeat == 3) // Status Effect (Poison,etc)
  1869. {
  1870. Log(MSG_INFO, "Need to give user status effect %i for %i seconds", skill->buff[i],
  1871. ((skill->value1[i] != 0) ? skill->value1[i] : skill->value2[i]),
  1872. ( skill->duration ) );
  1873.  
  1874. }
  1875. }
  1876. return true;
  1877. }
  1878.  
  1879. //LMA: We take exp from a dead player.
  1880. bool CCharacter::TakeExp( CCharacter *Target )
  1881. {
  1882. //LMA: We don't take exp from a player if the killer is a Player.
  1883. if(!Target->IsPlayer()||(Target->IsPlayer()&&IsPlayer()))
  1884. {
  1885. return true;
  1886. }
  1887.  
  1888. //no need to take exp from UW.
  1889. if(Position->Map==9)
  1890. {
  1891. return true;
  1892. }
  1893.  
  1894. //We take 3% of his xp.
  1895. CPlayer* thisclient = GServer->GetClientByID(Target->clientid,Target->Position->Map);
  1896. if (thisclient==NULL)
  1897. {
  1898. CPlayer* thisclient = GServer->GetClientByID(Target->clientid,Position->Map);
  1899. }
  1900.  
  1901. if (thisclient==NULL)
  1902. {
  1903. Log(MSG_WARNING,"Can't find clientID %i to take his Exp...",Target->clientid);
  1904. return true;
  1905. }
  1906.  
  1907. Log(MSG_INFO,"Player %i died, Xp before %I64i",Target->clientid,thisclient->CharInfo->Exp);
  1908. unsigned long long new_exp=(unsigned long long) (thisclient->CharInfo->Exp*3/100);
  1909. thisclient->CharInfo->Exp-=new_exp;
  1910. BEGINPACKET( pak, 0x79b );
  1911. ADDDWORD ( pak, thisclient->CharInfo->Exp );
  1912. ADDWORD ( pak, thisclient->CharInfo->stamina );
  1913. ADDWORD ( pak, 0 );
  1914. thisclient->client->SendPacket( &pak );
  1915. Log(MSG_INFO,"Player %i died, Xp taken %I64i, new %I64i",Target->clientid,new_exp,thisclient->CharInfo->Exp);
  1916.  
  1917.  
  1918. return true;
  1919. }
  1920.  
  1921. //LMA: Union war kill (and more generally qsd killing / death trigger).
  1922. void CCharacter::UWKill(CCharacter* Enemy)
  1923. {
  1924. if(!IsPlayer()&&!Enemy->IsPlayer())
  1925. {
  1926. Log(MSG_WARNING,"No player for UWKill");
  1927. return;
  1928. }
  1929.  
  1930. CPlayer* plkiller=NULL;
  1931. CPlayer* plkilled=NULL;
  1932.  
  1933. if(IsPlayer())
  1934. {
  1935. plkiller=(CPlayer*) this;
  1936. }
  1937.  
  1938. if(Enemy->IsPlayer())
  1939. {
  1940. plkilled=(CPlayer*) Enemy;
  1941. }
  1942.  
  1943. int killer_level=0;
  1944. int killed_level=0;
  1945.  
  1946. dword hashkilling = GServer->MapList.Index[Position->Map]->QSDkilling;
  1947. dword hashdeath = GServer->MapList.Index[Position->Map]->QSDDeath;
  1948.  
  1949. //The killer.
  1950. if(hashkilling>0&&plkiller!=NULL)
  1951. {
  1952. plkiller->ExecuteQuestTrigger(hashkilling,true);
  1953. //Log(MSG_WARNING,"quest hash %u to the killer %s",hashkilling,plkiller->CharInfo->charname);
  1954. killer_level=plkiller->Stats->Level;
  1955. }
  1956.  
  1957. //The killed one.
  1958. if(hashkilling>0&&plkilled!=NULL)
  1959. {
  1960. plkilled->ExecuteQuestTrigger(hashdeath,true);
  1961. //Log(MSG_WARNING,"quest hash %u to the killed %s",hashdeath,plkilled->CharInfo->charname);
  1962. killed_level=plkilled->Stats->Level;
  1963. }
  1964.  
  1965. //Let's give some exp points to the killer...
  1966. if(!IsPlayer()||!Enemy->IsPlayer())
  1967. {
  1968. //only if both are players.
  1969. return;
  1970. }
  1971.  
  1972. if(plkiller==NULL)
  1973. {
  1974. return;
  1975. }
  1976.  
  1977. if(plkilled==NULL)
  1978. {
  1979. killed_level=killer_level;
  1980. }
  1981.  
  1982. UINT bonus_exp=GServer->GetColorExp(killer_level,killed_level,7000);
  1983. plkiller->CharInfo->Exp += bonus_exp;
  1984.  
  1985. //LMA: Only if not level up
  1986. if(plkiller->CharInfo->Exp<plkiller->GetLevelEXP())
  1987. {
  1988. BEGINPACKET( pak, 0x79b );
  1989. ADDDWORD ( pak, plkiller->CharInfo->Exp );
  1990. ADDWORD ( pak, plkiller->CharInfo->stamina );
  1991.  
  1992. if(plkilled!=NULL)
  1993. {
  1994. ADDWORD ( pak, plkilled->clientid );
  1995. }
  1996. else
  1997. {
  1998. ADDWORD ( pak, 0 );
  1999. }
  2000.  
  2001. plkiller->client->SendPacket( &pak );
  2002. //Log(MSG_WARNING,"Giving %u exp to %s",bonus_exp,plkiller->CharInfo->charname);
  2003. }
  2004.  
  2005.  
  2006. return;
  2007. }
  2008.  
  2009.  
  2010. //LMA: test for quest hack (stackable).
  2011. #ifdef QHACK
  2012. //LMA: Adding a kill to the special quest kill list for a player.
  2013. void CCharacter::QuestKill(dword die_quest)
  2014. {
  2015. if(!IsPlayer()||die_quest==0)
  2016. {
  2017. return;
  2018. }
  2019.  
  2020. CPlayer* plkiller=(CPlayer*) this;
  2021.  
  2022. //looking for a "free" slot.
  2023. clock_t mytime=clock();
  2024. clock_t oldest_time=mytime;
  2025. int oldest=0;
  2026.  
  2027. for(int k=0;k<10;k++)
  2028. {
  2029. if(plkiller->arr_questid[k].questid==0)
  2030. {
  2031. oldest=k;
  2032. break;
  2033. }
  2034.  
  2035. //looking for time (is it too old?)
  2036. if(mytime>plkiller->arr_questid[k].die_time)
  2037. {
  2038. oldest=k;
  2039. break;
  2040. }
  2041.  
  2042. //is it the oldest? if they are all too recent, it'll be set to 0.
  2043. if(plkiller->arr_questid[k].die_time<oldest_time)
  2044. {
  2045. oldest_time=plkiller->arr_questid[k].die_time;
  2046. oldest=k;
  2047. }
  2048.  
  2049. }
  2050.  
  2051. plkiller->arr_questid[oldest].questid=die_quest;
  2052. plkiller->arr_questid[oldest].die_time=mytime+(CLOCKS_PER_SEC/2);
  2053. Log(MSG_WARNING,"Killing time, offset %i time %u questid %u",oldest,plkiller->arr_questid[oldest].die_time,die_quest);
  2054.  
  2055.  
  2056. return;
  2057. }
  2058. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement