Advertisement
Guest User

Untitled

a guest
Jun 13th, 2011
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 69.40 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, 30 ) - 2;
  427.     attack += ((Stats->Level - Enemy->Stats->Level) * d_attack);
  428.     if(attack<7) attack = 5;
  429.     long int hitpower = (long int)floor(attack + 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 * 2 / 1.5 / 1.5 / 1.5 ));
  434.     if(IsMonster( )) //temp fix to find balance btw monster and player
  435.         hitpower = (long int)floor(attack * (GServer->Config.MonsterDmg/100.00 * 2 / 1.5 / 1.5 / 1.5 / 1.5 ));
  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