// Check For Debuffs void CCharacter::RefreshBuff( ) { bool bflag = false; for( UINT i=0; i<30; i++) { if(MagicStatus[i].Buff==0) continue; clock_t etime = clock() - MagicStatus[i].BuffTime; if( etime >= MagicStatus[i].Duration * CLOCKS_PER_SEC ) { switch(MagicStatus[i].Buff) { case A_ATTACK: if(i<15) Status->Attack_up = 0xff; else Status->Attack_down = 0xff; Stats->Attack_Power = GetAttackPower( ); break; case A_DEFENSE: if(i<15) Status->Defense_up= 0xff; else Status->Defense_down = 0xff; Stats->Defense = GetDefense( ); break; case A_ACCUR: if(i<15) Status->Accury_up= 0xff; else Status->Accury_down = 0xff; Stats->Accury = GetAccury( ); break; case A_MRESIST: if(i<15) Status->Magic_Defense_up = 0xff; else Status->Magic_Defense_down = 0xff; Stats->Magic_Defense = GetMagicDefense( ); break; case A_DODGE: if(i<15) Status->Dodge_up = 0xff; else Status->Dodge_down = 0xff; Stats->Dodge = GetDodge( ); break; case A_DASH: if(i<15) Status->Dash_up = 0xff; else Status->Dash_down = 0xff; Stats->Move_Speed = GetMoveSpeed( ); break; case A_HASTE: if(i < 15) { Status->Haste_up = 0xff; } else { Status->Haste_down = 0xff; } Stats->Attack_Speed = GetAttackSpeed(); break; case A_CRITICAL: if(i<15) Status->Critical_up = 0xff; else Status->Critical_down = 0xff; Stats->Critical = GetCritical( ); break; case A_MAX_HP: if(i<15) Status->HP_up = 0xff; else Status->HP_down = 0xff; Stats->MaxHP = GetMaxHP( ); break; case A_MAX_MP: if(i<15) Status->MP_up = 0xff; else Status->MP_down = 0xff; Stats->MaxMP = GetMaxMP( ); break; case A_STUN: Status->Stuned = 0xff; printf("removing stun\n"); //StartAction2(NULL, 0, 0, true); break; case A_POISON: Status->Poisoned = 0xff; printf("removing poison\n"); break; case A_MUTE: Status->Muted = 0xff; break; case A_GMExtra_Damage: case A_Extra_Damage: if(i<15) { Status->ExtraDamage_up = 0xff; Stats->ExtraDamage = 0; } else Status->ExtraDamage_down = 0xff; break; } MagicStatus[i].Buff = 0; MagicStatus[i].BuffTime = 0; MagicStatus[i].Duration = 0; MagicStatus[i].Value = 0; bflag = true; } else if (MagicStatus[i].Buff == A_POISON && etime > 1*CLOCKS_PER_SEC) //Do poison dmg every 1.5 seconds { Stats->HP -= MagicStatus[i].Value; MagicStatus[i].BuffTime+= 1*CLOCKS_PER_SEC; MagicStatus[i].Duration-=1; printf("did %i poison dmg to the player, still %i seconds and %i HP remain \n", MagicStatus[i].Value, MagicStatus[i].Duration, Stats->HP); //A bunch of messy code to send dmg packet BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, 0 ); ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); ADDDWORD ( pak, MagicStatus[i].Value ); //If Enemy is killed if( IsDead()) { printf("char died\n"); CDrop* thisdrop = NULL; //ADDDWORD ( pak, 16 );//i don't think this one belongs in irose if( !IsSummon( ) && !IsPlayer( )) { thisdrop = GetDrop( ); if( thisdrop!=NULL) { ADDFLOAT ( pak, thisdrop->pos.x*100 ); ADDFLOAT ( pak, thisdrop->pos.y*100 ); if( thisdrop->type==1) { ADDDWORD( pak, 0xccdf );//0xccccccdf ); ADDDWORD( pak, thisdrop->amount ); } else { ADDDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); } ADDWORD ( pak, thisdrop->clientid ); ADDWORD ( pak, thisdrop->owner ); CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } GServer->SendToVisible( &pak, this, thisdrop ); } //If enemy is still alive else { ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, this ); } } } if(bflag) { BEGINPACKET( pak,0x7b7 ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, GServer->BuildBuffs( this ) ); GServer->SendToVisible( &pak, this ); } }
void CCharacter::RefreshBuff( ) { bool bflag = false; for( UINT i=0;i<32;i++) { if(MagicStatus[i].Buff == 0) continue; clock_t etime = clock() - MagicStatus[i].BuffTime; if( etime >= MagicStatus[i].Duration * CLOCKS_PER_SEC ) { Log(MSG_INFO,"Magic Status %i, vanish after: %i", MagicStatus[i].Status, MagicStatus[i].Duration); switch(MagicStatus[i].Status) { case STATUS_HP_8: case STATUS_HP_18: case STATUS_HP_30: case STATUS_HP_43: case STATUS_HP_58: case STATUS_HP_75: case STATUS_SUMMON_HP: case STATUS_HP_92: case STATUS_HP_111: case STATUS_HP_131: case STATUS_HP_152: case STATUS_HP_174: case STATUS_HP_197: case STATUS_HP_221: case STATUS_HP_246: case STATUS_HP_272: case STATUS_HP_299: case STATUS_HP_326: case STATUS_HP_354: case STATUS_HP_383: case STATUS_HP_413: case STATUS_HP_443: case STATUS_HP_475: case STATUS_HP_539: case STATUS_HP_572: case STATUS_HP_5_PC: case 115: { Status->HPHeal = 0xff; } break; case STATUS_MP_6: case STATUS_MP_10: case STATUS_MP_14: case STATUS_MP_18: case STATUS_MP_21: case STATUS_MP_25: case STATUS_MP_29: case STATUS_MP_33: case STATUS_MP_36: case STATUS_MP_40: case STATUS_MP_44: case STATUS_MP_48: case STATUS_MP_51: case STATUS_MP_55: case STATUS_MP_59: case STATUS_MP_63: case STATUS_MP_66: case STATUS_MP_70: case STATUS_MP_74: case STATUS_MP_78: case STATUS_MP_81: case STATUS_MP_85: case STATUS_MP_89: case STATUS_MP_93: case STATUS_MP_96: case 116: { Status->MPHeal = 0xff; } break; case 18: // attack power up case 19: // attack power down case 48: // attack power up { if(i == BUFF_ATTACK_UP_POS) { Status->Attack_up = 0xff; } else { Status->Attack_down = 0xff; } Stats->Attack_Power = GetAttackPower( ); } break; case 20: // def up case 21: // def down case 49: // def up { if(i==BUFF_DEFENSE_UP_POS) { Status->Defense_up= 0xff; } else { Status->Defense_down = 0xff; } Stats->Defense = GetDefense( ); } break; case 24: //Accuracy up case 25: //Accuracy down case 51: //attack Accuracy up. { if(i==BUFF_HITRATE_UP_POS) { Status->Accuracy_up= 0xff; } else { Status->Accuracy_down = 0xff; } Stats->Accuracy = GetAccuracy( ); } break; case 22: // macic resistance up case 23: // magic resistance down case 50: // magic resistance up { if(i==BUFF_MDEFENSE_UP_POS) { Status->Magic_Defense_up = 0xff; } else { Status->Magic_Defense_down = 0xff; } Stats->Magic_Defense = GetMagicDefense( ); } break; case 28: //dodge up case 29: //dodge down case 53: //dodge rate up { if(i==BUFF_DODGE_UP_POS) { Status->Dodge_up = 0xff; } else { Status->Dodge_down = 0xff; } Stats->Dodge = GetDodge( ); } break; case 14: //dash case 15: //slow case 46: //movement speed increased { if(i==BUFF_DASH_UP_POS) { Status->Dash_up = 0xff; } else { Status->Dash_down = 0xff; } Stats->Move_Speed = GetMoveSpeed( ); } break; case 16: // haste attack case 17: // slow attack case 47: // attack speed up { if(i==BUFF_HASTE_UP_POS) { Status->Haste_up = 0xff; } else { Status->Haste_down = 0xff; } //Stats->Attack_Speed_Percent = GetAttackSpeedPercent( ); } break; case 26: // crit up case 27: // crit down case 52: // crit up { if(i==BUFF_CRITICAL_UP_POS) { Status->Critical_up = 0xff; } else { Status->Critical_down = 0xff; } Stats->Critical = GetCritical( ); } break; case 12: // max HP up case 44: // max HP up { if(i==BUFF_MAX_HP_POS) { Status->HP_up = 0xff; } else { Status->HP_down = 0xff; } Stats->MaxHP = GetMaxHP( ); if(Stats->HP > Stats->MaxHP) { Stats->HP = Stats->MaxHP; } } break; case 13: // max MP up case 45: // max MP up { if(i==BUFF_MAX_MP_POS) { Status->MP_up = 0xff; } else { Status->MP_down = 0xff; } Stats->MaxMP = GetMaxMP( ); if(Stats->MP > Stats->MaxMP) { Stats->MP = Stats->MaxMP; } } break; case 32: // faint { Status->Faint = 0xff; Status->CanMove = true; Status->CanCastSkill = true; Status->CanAttack = true; //printf("removing stun\n"); } break; case 7: case 8: case 9: case 10: case 11: case 89: //poisoned { Status->Poisoned = 0xff; //printf("removing poison\n"); } break; case 30: // muted { Status->Muted = 0xff; Status->CanCastSkill = true; } break; case 31: // sleep May need to be fixed later to accomodate multiple status effects. { Status->Sleep = 0xff; Status->CanMove = true; Status->CanCastSkill = true; Status->CanAttack = true; } break; case 36: //A_Extra_Damage: case 54: //A_GMExtra_Damage: case 83: //Valkyrie Charm: { if(i==BUFF_DUMMY_DAMAGE_POS) { Status->ExtraDamage_up = 0xff; Stats->ExtraDamage_add = 0;//We put extardamage add value to 0 if we lost the adddmg buff } else { Status->ExtraDamage_down = 0xff; Stats->ExtraDamage_add = 0;//We put extardamage add value to 0 if we lost the adddmg buff } } break; case 56: //Taunt { Status->Taunt = 0xff; //printf("removing Taunt\n"); } break; case 58: case 61: case 74: case 77: case 78: case 79: case 80: //flame { Status->Flamed = 0xff; } break; case 33://Stealth,Camoflauge { if(IsAttacking( )) { MagicStatus[i].Duration = 0; } Status->Stealth = 0xff; //printf("removing Stealth\n"); } break; case 86://Stealth,Weary { Status->Weary = 0xff; Status->CanCastSkill = true; //printf("removing Weary\n"); } break; case 34://Cloaking { Status->Cloaking = 0xff; //printf("removing Cloaking\n"); } break; case 35: //ShieldDamage: { if(i==BUFF_SHIELD_DAMAGE_POS) { Status->ShieldDamage_up = 0xff; //Stats->ShieldDamage = 0xff; } else { Status->ShieldDamage_down = 0xff; //Stats->ShieldDamage = 0xff; } } break; case 55://Detect { Status->Detect = 0xff; Status->Cloaking = 0xff; Status->Stealth = 0xff; //printf("Detect Done\n"); } break; case 38://Purify { //Buff_Down Status->Attack_down = 0xff; Status->Defense_down = 0xff; Status->Accuracy_down = 0xff; Status->Magic_Defense_down = 0xff; Status->Dodge_down = 0xff; Status->Dash_down = 0xff; Status->Haste_down = 0xff; Status->Critical_down = 0xff; Status->HP_down = 0xff; Status->MP_down = 0xff; Status->ExtraDamage_down = 0xff; Status->ShieldDamage_down = 0xff; Status->ALL_down = 0xff; //Bad Status //Status->Stun = 0xff; Status->Poisoned = 0xff; Status->Muted = 0xff; Status->Sleep = 0xff; Status->Flamed = 0xff; Status->Faint = 0xff; //Stats Stats->Attack_Power = GetAttackPower( ); Stats->Defense = GetDefense( ); Stats->Accuracy = GetAccuracy( ); Stats->Magic_Defense = GetMagicDefense( ); Stats->Dodge = GetDodge( ); Stats->Move_Speed = GetMoveSpeed( ); Stats->Attack_Speed = GetAttackSpeed( ); //Stats->Attack_Speed_Percent = GetAttackSpeedPercent(); Stats->Critical = GetCritical( ); Stats->MaxHP = GetMaxHP( ); Stats->MaxMP = GetMaxMP( ); //printf("Purify Done\n"); } break; case 39:// Dispell { //Buff_Down Status->Attack_down = 0xff; Status->Defense_down = 0xff; Status->Accuracy_down = 0xff; Status->Magic_Defense_down = 0xff; Status->Dodge_down = 0xff; Status->Dash_down = 0xff; Status->Haste_down = 0xff; Status->Critical_down = 0xff; Status->HP_down = 0xff; Status->MP_down = 0xff; Status->ExtraDamage_down = 0xff; Status->ShieldDamage_down = 0xff; Status->ALL_down = 0xff; //Buff_Up Status->Attack_up = 0xff; Status->Defense_up = 0xff; Status->Accuracy_up = 0xff; Status->Magic_Defense_up = 0xff; Status->Dodge_up = 0xff; Status->Dash_up = 0xff; Status->Haste_up = 0xff; Status->Critical_up = 0xff; Status->HP_up = 0xff; Status->MP_up = 0xff; Status->ExtraDamage_up = 0xff; Status->ShieldDamage_up = 0xff; Status->ALL_up = 0xff; //Bad Status //Status->Stun = 0xff; Status->Poisoned = 0xff; Status->Muted = 0xff; Status->Sleep = 0xff; Status->Flamed = 0xff; Status->Faint = 0xff; //Stats Stats->Attack_Power = GetAttackPower( ); Stats->Defense = GetDefense( ); Stats->Accuracy = GetAccuracy( ); Stats->Magic_Defense = GetMagicDefense( ); Stats->Dodge = GetDodge( ); Stats->Move_Speed = GetMoveSpeed( ); Stats->Attack_Speed = GetAttackSpeed( ); Stats->Critical = GetCritical( ); Stats->MaxHP = GetMaxHP( ); Stats->MaxMP = GetMaxMP( ); //printf("Dispell Done\n"); } break; default: { Log(MSG_WARNING,"Unknow skill status in charfunctions %u.",MagicStatus[i].Status); } } BEGINPACKET( pak,0x7b7 ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, GServer->BuildBuffs( this ) ); GServer->SendToVisible( &pak, this ); MagicStatus[i].Status = 0; MagicStatus[i].Buff = 0; MagicStatus[i].BuffTime = 0; MagicStatus[i].Duration = 0; MagicStatus[i].Value = 0; bflag = true; } else if ( ((MagicStatus[i].Status >= 7 && MagicStatus[i].Status <= 11) || MagicStatus[i].Status == 89) && etime > 1*CLOCKS_PER_SEC) //Do poison dmg every 1.5 seconds { Stats->HP -= MagicStatus[i].Status; //Actually take 7, 8, 9, 10 or 11 from the health. Based on the Status itself, LMA: can be 89 noc too. MagicStatus[i].BuffTime += 1*CLOCKS_PER_SEC; MagicStatus[i].Duration -= 1; //printf("did %i poison dmg to the player, still %i seconds and %i HP remain \n", MagicStatus[i].Status, MagicStatus[i].Duration, Stats->HP); //Log(MSG_WARNING,"did %i poison dmg to the player / monster, still %i seconds and %I64i HP remain", MagicStatus[i].Status, MagicStatus[i].Duration, Stats->HP); //LMA: If dead, let's the client resynch if(IsDead()) { BEGINPACKET( pak, 0x79f ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, 1); GServer->SendToVisible( &pak, this ); Log(MSG_INFO,"death poison for %i, amount: %i",clientid,MagicStatus[i].Status); } //A bunch of messy code to send dmg packet BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, 0 ); ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); ADDDWORD ( pak, MagicStatus[i].Status ); //If Enemy is killed if( IsDead()) { //printf("char died\n"); CDrop* thisdrop = NULL; ADDDWORD ( pak, 16 ); if( !IsSummon( ) && !IsPlayer( )) { //LMA: No drop if already dead and drop done. if(drop_dead) { Log(MSG_WARNING,"Trying to make a monster (CID %u, type %u) drop again but already did.",clientid,char_montype); } else { thisdrop = GetDrop( ); if( thisdrop!=NULL) { CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } } //GServer->SendToVisible( &pak, this, thisdrop ); GServer->SendToVisible( &pak, this); } else { //If enemy is still alive ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, this ); } } else if ( MagicStatus[i].Status == 58 || MagicStatus[i].Status == 61 || MagicStatus[i].Status == 71 || MagicStatus[i].Status >= 77 && MagicStatus[i].Status <= 80 || MagicStatus[i].Status == 88 && etime > 1*CLOCKS_PER_SEC) //Do flame dmg every 1.5 seconds { Stats->HP -= MagicStatus[i].Status; MagicStatus[i].BuffTime += 1*CLOCKS_PER_SEC; MagicStatus[i].Duration -= 1; printf("did %i flame dmg to the player, still %i seconds and %i HP remain \n", MagicStatus[i].Status, MagicStatus[i].Duration, Stats->HP); //LMA: If dead, let's the client resynch if(IsDead()) { BEGINPACKET( pak, 0x79f ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, 1); GServer->SendToVisible( &pak, this ); Log(MSG_INFO,"death flame for %i, amount: %i",clientid,MagicStatus[i].Status); } //A bunch of messy code to send dmg packet BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, 0 ); ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); ADDDWORD ( pak, MagicStatus[i].Status ); //If Enemy is killed if( IsDead()) { //printf("char died\n"); CDrop* thisdrop = NULL; ADDDWORD ( pak, 16 ); if( !IsSummon( ) && !IsPlayer( )) { //LMA: No drop if already dead and drop done. if(drop_dead) { Log(MSG_WARNING,"Trying to make a monster (CID %u, type %u) drop again but already did.",clientid,char_montype); } else { thisdrop = GetDrop( ); if( thisdrop!=NULL) { CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } } //GServer->SendToVisible( &pak, this, thisdrop ); GServer->SendToVisible( &pak, this); } else { //If enemy is still alive ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, this ); } } } for( UINT i=0;i<32;i++) { if(MagicStatus2[i].Buff == 0) continue; clock_t etime = clock() - MagicStatus2[i].BuffTime; if( etime >= MagicStatus2[i].Duration * CLOCKS_PER_SEC ) { CPlayer* thisplayer = GServer->GetClientByID(clientid); Log(MSG_INFO,"Magic Status %i, vanish after: %i", MagicStatus2[i].Status, MagicStatus2[i].Duration); switch(MagicStatus2[i].Status) { case 126: // ALLbuff up { if(i == BUFF_ATTACK_UP_POS) { Status->Attack_up = 0xff; thisplayer->Attr->ALLbuff = 0; } else { Status->Attack_down = 0xff; thisplayer->Attr->ALLbuff = 0; } } default: { Log(MSG_WARNING,"Unknow skill status in charfunctions %u.",MagicStatus[i].Status); } } BEGINPACKET( pak,0x7b7 ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, GServer->BuildBuffs( this ) ); GServer->SendToVisible( &pak, this ); MagicStatus2[i].Status = 0; MagicStatus2[i].Buff = 0; MagicStatus2[i].BuffTime = 0; MagicStatus2[i].Duration = 0; MagicStatus2[i].Value = 0; } } // if(bflag) // { // BEGINPACKET( pak,0x7b7 ); // ADDWORD ( pak, clientid ); // ADDDWORD ( pak, GServer->BuildBuffs( this ) ); // GServer->SendToVisible( &pak, this ); // } }
// use skill attack void CCharacter::UseAtkSkill( CCharacter* Enemy, CSkills* skill, bool deBuff) { // new formula long int skillpower = skill->atkpower + Stats->Attack_Power; Log( MSG_INFO, "Skillpower = %i (%i + %i)",skillpower,skill->atkpower,Stats->Attack_Power); float levelmult = (float) Stats->Level / Enemy->Stats->Level; if(levelmult > 2)levelmult = 2; //cap level multiplier at 2 Log( MSG_INFO, "Level Multiplier = %f",levelmult ); float atkdefmult = 0; float attack = 0; float constant = 2.5; if(skill->skilltype == 6 || skill->skilltype == 7) //magical damage { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Magic_Defense; } else { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Defense; } Log( MSG_INFO, "Attack / Def multiplier = %f",atkdefmult ); attack = (skillpower * levelmult * atkdefmult) / constant; Log( MSG_INFO, "Attack before random mod = %f",attack ); if(attack < 5) attack = 5; float d_attack = attack / 100; float mod = GServer->RandNumber( 0, 10 ) * d_attack; attack += mod; Log( MSG_INFO, "Attack after random mod = %f",attack ); long int hitpower = (long int)floor(attack); skillpower = (int)attack; Log( MSG_INFO, "skillpower = %i",skillpower ); bool bflag = false; Enemy->OnBeAttacked( this ); if(skillpower <= 0) skillpower = 0; if(IsPlayer()) { skillpower += (int)(skillpower * (Stats->ExtraDamage))/100; } if (skill->atkpower == 0) { skillpower = 0; // If the skill has a 0 atk power, it isn't meant to damage Log( MSG_INFO, "This skill does no damage" ); //ClearBattle( Battle ); return; // probably need to add some alternative code here for legitimate skills that have no attack power. } if(skillpower > 2046)skillpower = 2046; //Log(MSG_DEBUG,"Cast a skill. damage is %i",skillpower); if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) { Enemy->AddDamage( this, skillpower ); Enemy->damagecounter += skillpower;// is for AI } Log( MSG_INFO, "modified skillpower = %i",skillpower ); Enemy->Stats->HP -= skillpower; //if(IsPlayer()) // Log(MSG_DEBUG,"Player Spell did damage %i",skillpower); //if(IsMonster()) // Log(MSG_DEBUG,"Monster spell did damage %i",skillpower); BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, Enemy->clientid ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); if (Enemy->Stats->HP < 1) { ADDWORD ( pak, skillpower + 0x8000 ); } else { ADDWORD ( pak, skillpower + 0x2000 ); } if(Enemy->IsDead()) { //Log(MSG_DEBUG,"Enemy died"); CDrop* thisdrop = NULL; ADDDWORD ( pak, 16 ); if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) { thisdrop = Enemy->GetDrop( ); if(thisdrop != NULL) { CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } //GServer->SendToVisible( &pak, Enemy, thisdrop ); GServer->SendToVisible( &pak, Enemy ); //Suppressing drop for now. trying a different trick OnEnemyDie( Enemy ); } else { ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, Enemy ); bflag = GServer->AddBuffs( skill, Enemy, GetInt( ) ); //Send (de)buff information to the whole world if(skill->nbuffs > 0 && bflag) { BEGINPACKET( pak, 0x7b5 ); ADDWORD ( pak, Battle->skilltarget ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Battle->skillid ); ADDWORD ( pak, GetInt( ) ); ADDBYTE ( pak, skill->nbuffs ); GServer->SendToVisible( &pak, Enemy ); } } if (deBuff) return; //Send skill animation to the world RESETPACKET( pak, 0x7b9); ADDWORD ( pak, clientid); ADDWORD ( pak, Battle->skillid); ADDWORD ( pak, 1); GServer->SendToVisible( &pak, this ); Battle->bufftarget = 0; Battle->skilltarget = 0; Battle->skillid = 0; //Battle->atktype = NORMAL_ATTACK; }
// Check For Debuffs void CCharacter::RefreshBuff( ) { bool bflag = false; for( UINT i=0; i<30; i++) { if(MagicStatus[i].Buff == 0) continue; clock_t etime = clock() - MagicStatus[i].BuffTime; if( etime >= MagicStatus[i].Duration * CLOCKS_PER_SEC ) { switch(MagicStatus[i].Status) { case 18: // attack power up case 19: // attack power down case 48: // attack power up if(i<15) Status->Attack_up = 0xff; else Status->Attack_down = 0xff; Stats->Attack_Power = GetAttackPower( ); break; case 20: // def up case 21: // def down case 49: // def up if(i<15) Status->Defense_up= 0xff; else Status->Defense_down = 0xff; Stats->Defense = GetDefense( ); break; case 24: //accuracy up case 25: //accuracy down case 51: //attack accuracy up. if(i<15) Status->Accury_up= 0xff; else Status->Accury_down = 0xff; Stats->Accury = GetAccury( ); break; case 22: // macic resistance up case 23: // magic resistance down case 50: // magic resistance up if(i<15) Status->Magic_Defense_up = 0xff; else Status->Magic_Defense_down = 0xff; Stats->Magic_Defense = GetMagicDefense( ); break; case 28: //dodge up case 29: //dodge down case 53: //dodge rate up if(i<15) Status->Dodge_up = 0xff; else Status->Dodge_down = 0xff; Stats->Dodge = GetDodge( ); break; case 14: //dash case 15: //slow case 46: //movement speed increased if(i<15) Status->Dash_up = 0xff; else Status->Dash_down = 0xff; Stats->Move_Speed = GetMoveSpeed( ); break; case 16: // haste attack case 17: // slow attack case 47: // attack speed up if(i<15) Status->Haste_up = 0xff; else Status->Haste_down = 0xff; Stats->Attack_Speed = GetAttackSpeed( ); break; case 26: // crit up case 27: // crit down case 52: // crit up if(i<15) Status->Critical_up = 0xff; else Status->Critical_down = 0xff; Stats->Critical = GetCritical( ); break; case 12: // max HP up case 44: // max HP up if(i<15) Status->HP_up = 0xff; else Status->HP_down = 0xff; Stats->MaxHP = GetMaxHP( ); break; case 13: // max MP up case 45: // max MP up if(i<15) Status->MP_up = 0xff; else Status->MP_down = 0xff; Stats->MaxMP = GetMaxMP( ); break; case 32: // faint Status->Stuned = 0xff; Status->CanAttack = true; //printf("removing stun\n"); break; case 7: case 8: case 9: case 10: case 11: //poisoned Status->Poisoned = 0xff; //printf("removing poison\n"); break; case 30: // muted Status->Muted = 0xff; Status->CanCastSkill = true; break; case 31: // sleep May need to be fixed later to accomodate multiple status effects. Status->Sleep = 0xff; Status->CanMove = true; Status->CanCastSkill = true; Status->CanAttack = true; break; case 54: //A_GMExtra_Damage: case 36: //A_Extra_Damage: if(i<15) { Status->ExtraDamage_up = 0xff; Stats->ExtraDamage = 0xff; } else { Status->ExtraDamage_down = 0xff; Stats->ExtraDamage = 0xff; } break; case 56: // Taunt Status->Taunt = 0xff; break; } MagicStatus[i].Status = 0; MagicStatus[i].Buff = 0; MagicStatus[i].BuffTime = 0; MagicStatus[i].Duration = 0; MagicStatus[i].Value = 0; bflag = true; } else if (MagicStatus[i].Status >= 7 && MagicStatus[i].Status <= 11 && etime > 1*CLOCKS_PER_SEC) //Do poison dmg every 1.5 seconds { Stats->HP -= MagicStatus[i].Status; //Actually take 7, 8, 9, 10 or 11 from the health. Based on the Status itself MagicStatus[i].BuffTime += 1*CLOCKS_PER_SEC; MagicStatus[i].Duration -= 1; //printf("did %i poison dmg to the player, still %i seconds and %i HP remain \n", MagicStatus[i].Status, MagicStatus[i].Duration, Stats->HP); //A bunch of messy code to send dmg packet BEGINPACKET( pak, 0x7b6 ); ADDWORD ( pak, clientid ); // client taking damage ADDWORD ( pak, 0 ); // client doing damage ADDDWORD ( pak, 0x000007f8 ); ADDBYTE ( pak, 0x00 ); if (Stats->HP < 1) { ADDWORD ( pak, MagicStatus[i].Status + 0x8000 ); } else { ADDWORD ( pak, MagicStatus[i].Status + 0x2000 ); } //ADDDWORD ( pak, MagicStatus[i].Status ); //damage amount //If poisoned entity (player or monster) is killed if( IsDead()) { //printf("char died\n"); CDrop* thisdrop = NULL; ADDDWORD ( pak, 16 ); if( !IsSummon( ) && !IsPlayer( )) { thisdrop = GetDrop( ); if( thisdrop != NULL) { CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } GServer->SendToVisible( &pak, this ); // removed thisdrop from the packet } //If enemy is still alive else { ADDDWORD ( pak, 4 ); GServer->SendToVisible( &pak, this ); } } } if(bflag) { BEGINPACKET( pak,0x7b7 ); ADDWORD ( pak, clientid ); ADDDWORD ( pak, GServer->BuildBuffs( this ) ); GServer->SendToVisible( &pak, this ); } }
// do normal attack void CCharacter::NormalAttack( CCharacter* Enemy ) { Enemy->OnBeAttacked( this ); Position->destiny = Position->current; // new formula float levelmult = (float) Stats->Level / Enemy->Stats->Level; if(levelmult > 2)levelmult = 2; float atkdefmult = 0; float attack = 0; float constant = 4; if(Stats->magicattack == 1) { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Magic_Defense; } else { atkdefmult = (float) Stats->Attack_Power / Enemy->Stats->Defense; } attack = Stats->Attack_Power * levelmult * atkdefmult / constant; if(attack < 5) attack = 5; float d_attack = attack / 100; float mod = GServer->RandNumber( 0, 10 ) * d_attack; attack += mod; long int hitpower = (long int)floor(attack); if(IsPlayer( )) //temp fix to find balance btw monster and player { hitpower = (long int)floor(attack * (GServer->Config.PlayerDmg/100.00)); hitpower+=((hitpower*(Stats->ExtraDamage))/100); } if(IsSummon( )) //temp fix to find balance btw monster and player { hitpower = (long int)floor(attack * (GServer->Config.PlayerDmg/100.00)); Log(MSG_DEBUG,"Summon hitpower = %i",hitpower); } if(IsMonster( )) //temp fix to find balance btw monster and player hitpower = (long int)floor(attack * (GServer->Config.MonsterDmg/100.00)); bool critical = false; if(hitpower <= 5) { hitpower = 5; } else { if(GServer->RandNumber(0,300)<Stats->Critical) { hitpower = (long int)floor(hitpower * 1.5); critical = true; } } // dodge unsigned int hitvalue = (unsigned int)floor((double)(Stats->Accury * 40 / Enemy->Stats->Dodge)); if(hitvalue > 100) hitvalue = 100; if(GServer->RandNumber( 0, 100 ) > hitvalue) hitpower = 0; // dodged if (hitpower > 0x7ff)//2047 packet size limit. { hitpower = 0x7ff; } Battle->atktarget = Battle->target; if(IsMonster()) { //Log(MSG_INFO,"Monster hits player for %i damage. Attack target = %i",hitpower,Battle->atktarget); } //Log( MSG_INFO, "hitpower %i. Attack %f ", hitpower,attack ); if(!Enemy->IsSummon( ) && Enemy->IsMonster( )) { Enemy->AddDamage( this, hitpower ); Enemy->damagecounter += hitpower;// is for AI } Enemy->Stats->HP -= hitpower; BEGINPACKET( pak, 0x799 ); ADDWORD ( pak, clientid ); ADDWORD ( pak, Battle->atktarget ); if(Enemy->IsDead()) { CDrop* thisdrop = NULL; ADDWORD ( pak, (hitpower | ( critical?0xb000:0x8000 ) )); if(!Enemy->IsSummon( ) && !Enemy->IsPlayer( )) { thisdrop = Enemy->GetDrop( ); if(thisdrop != NULL) { //ADDFLOAT ( pak, thisdrop->pos.x*100 ); //ADDFLOAT ( pak, thisdrop->pos.y*100 ); //if(thisdrop->type == 1) //{ // ADDWORD( pak, 0xccdf ); // ADDDWORD( pak, thisdrop->amount ); //} //else //{ // ADDWORD ( pak, GServer->BuildItemHead( thisdrop->item ) ); // ADDDWORD ( pak, GServer->BuildItemData( thisdrop->item ) ); //} //ADDWORD ( pak, thisdrop->clientid ); //ADDWORD ( pak, thisdrop->owner ); CMap* map = GServer->MapList.Index[thisdrop->posMap]; map->AddDrop( thisdrop ); } } GServer->SendToVisible( &pak, Enemy ); //, thisdrop ); OnEnemyDie( Enemy ); } else { ADDWORD ( pak, (hitpower|(hitpower>0?(critical?0x4000:0):0))); GServer->SendToVisible( &pak, Enemy ); } ReduceABC( ); Battle->lastAtkTime = clock( ); }