void CMagicProcess::ExecuteType3(int magicid, int tid, int data1, int data2, int data3, int moral, int dexpoint, int righthand_damage ) // Applied when a magical attack, healing, and mana restoration is done. { int damage = 0, result = 1, send_index=0, attack_type = 0; char send_buff[256]; _MAGIC_TYPE3* pType = NULL; CNpc* pNpc = NULL ; // Pointer initialization! _MAGIC_TABLE* pMagic = NULL; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) return; if(tid == -1) { // 지역 공격 result = AreaAttack(3, magicid, moral, data1, data2, data3, dexpoint, righthand_damage); //if(result == 0) goto packet_send; //else return; } pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == NULL || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0) { result = 0; goto packet_send; } pType = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType ) return; // if (pType->sFirstDamage < 0) { if ((pType->sFirstDamage < 0) && (pType->bDirectType == 1) && (magicid < 400000)) { damage = GetMagicDamage(tid, pType->sFirstDamage, pType->bAttribute, dexpoint, righthand_damage) ; } else { damage = pType->sFirstDamage ; } //TRACE("magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if (pType->bDuration == 0) { // Non-Durational Spells. if (pType->bDirectType == 1) { // Health Point related ! //damage = pType->sFirstDamage; // Reduce target health point // if(damage >= 0) { if(damage > 0) { result = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP, MAGIC_ATTACK); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP, MAGIC_ATTACK); } } } else if ( pType->bDirectType == 2 || pType->bDirectType == 3 ) // Magic or Skill Point related ! pNpc->MSpChange(pType->bDirectType, pType->sFirstDamage); // Change the SP or the MP of the target. else if( pType->bDirectType == 4 ) // Armor Durability related. pNpc->ItemWoreOut( DEFENCE, pType->sFirstDamage); // Reduce Slot Item Durability } else if (pType->bDuration != 0) { // Durational Spells! Remember, durational spells only involve HPs. if(damage >= 0) { } else { damage = abs(damage); if(pType->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP); } } damage = GetMagicDamage(tid, pType->sTimeDamage, pType->bAttribute, dexpoint, righthand_damage); // The duration magic routine. for(int i=0; i<MAX_MAGIC_TYPE3; i++) { if(pNpc->m_MagicType3[i].sHPAttackUserID == -1 && pNpc->m_MagicType3[i].byHPDuration == 0) { pNpc->m_MagicType3[i].sHPAttackUserID = m_pSrcUser->m_iUserId; pNpc->m_MagicType3[i].fStartTime = TimeGet(); pNpc->m_MagicType3[i].byHPDuration = pType->bDuration; pNpc->m_MagicType3[i].byHPInterval = 2; pNpc->m_MagicType3[i].sHPAmount = damage / (pType->bDuration / 2); break; } } } packet_send: //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcUser->m_iUserId, send_index ); SetShort( send_buff, tid, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, moral, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); g_pMain->Send( send_buff, send_index ); } }
void CMagicProcess::AreaAttackDamage(int magictype, int rx, int rz, int magicid, int moral, int data1, int data2, int data3, int dexpoint, int righthand_damage) { MAP* pMap = m_pSrcUser->GetMap(); if (pMap == NULL) return; // 자신의 region에 있는 UserArray을 먼저 검색하여,, 가까운 거리에 유저가 있는지를 판단.. if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax()) { TRACE("#### CMagicProcess-AreaAttackDamage() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_pSrcUser->m_iUserId, m_pSrcUser->m_strUserID, rx, rz); return; } _MAGIC_TYPE3* pType3 = NULL; _MAGIC_TYPE4* pType4 = NULL; _MAGIC_TABLE* pMagic = NULL; int damage = 0, tid = 0, target_damage = 0, attribute = 0; float fRadius = 0; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic maintable error ,, magicid=%d\n", magicid); return; } if(magictype == 3) { pType3 = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType3 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table3 error ,, magicid=%d\n", magicid); return; } target_damage = pType3->sFirstDamage; attribute = pType3->bAttribute; fRadius = (float)pType3->bRadius; } else if(magictype == 4) { pType4 = g_pMain->m_Magictype4Array.GetData( magicid ); // Get magic skill table type 3. if( !pType4 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table4 error ,, magicid=%d\n", magicid); return; } fRadius = (float)pType4->bRadius; } if( fRadius <= 0 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magicid=%d, radius = %d\n", magicid, fRadius); return; } __Vector3 vStart, vEnd; CNpc* pNpc = NULL ; // Pointer initialization! float fDis = 0.0f; vStart.Set((float)data1, (float)0, (float)data3); char send_buff[256]; int send_index=0, result = 1, count = 0, total_mon = 0, attack_type=0;; int* pNpcIDList = NULL; EnterCriticalSection( &g_region_critical ); CRegion *pRegion = &pMap->m_ppRegion[rx][rz]; total_mon = pRegion->m_RegionNpcArray.GetSize(); pNpcIDList = new int[total_mon]; foreach_stlmap (itr, pRegion->m_RegionNpcArray) pNpcIDList[count++] = *itr->second; LeaveCriticalSection(&g_region_critical); for(int i = 0 ; i < total_mon; i++ ) { int nid = pNpcIDList[i]; if( nid < NPC_BAND ) continue; pNpc = (CNpc*)g_pMain->m_arNpc.GetData(nid - NPC_BAND); if( pNpc != NULL && pNpc->m_NpcState != NPC_DEAD) { if( m_pSrcUser->m_bNation == pNpc->m_byGroup ) continue; vEnd.Set(pNpc->m_fCurX, pNpc->m_fCurY, pNpc->m_fCurZ); fDis = pNpc->GetDistance(vStart, vEnd); if(fDis <= fRadius) { // NPC가 반경안에 있을 경우... if(magictype == 3) { // 타잎 3일 경우... damage = GetMagicDamage(pNpc->m_sNid+NPC_BAND, target_damage, attribute, dexpoint, righthand_damage); TRACE("Area magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if(damage >= 0) { result = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType3->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(pNpc->m_sNid+NPC_BAND, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { m_pSrcUser->SendAttackSuccess(pNpc->m_sNid+NPC_BAND, ATTACK_SUCCESS, damage, pNpc->m_iHP); } } send_index = 0; // 패킷 전송..... //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcUser->m_iUserId, send_index ); SetShort( send_buff, pNpc->m_sNid+NPC_BAND, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, moral, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); g_pMain->Send( send_buff, send_index ); } } else if(magictype == 4) { // 타잎 4일 경우... send_index = 0; result = 1; switch (pType4->bBuffType) { // Depending on which buff-type it is..... case 1 : // HP 올리기.. break; case 2 : // 방어력 올리기.. break; case 4 : // 공격력 올리기.. break; case 5 : // 공격 속도 올리기.. break; case 6 : // 이동 속도 올리기.. //if (pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime > 0) { // result = 0 ; //} //else { pNpc->m_MagicType4[pType4->bBuffType-1].byAmount = pType4->bSpeed; pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime = pType4->sDuration; pNpc->m_MagicType4[pType4->bBuffType-1].fStartTime = TimeGet(); pNpc->m_fSpeed_1 = (float)(pNpc->m_fOldSpeed_1 * ((double)pType4->bSpeed / 100)); pNpc->m_fSpeed_2 = (float)(pNpc->m_fOldSpeed_2 * ((double)pType4->bSpeed / 100)); //} break; case 7 : // 능력치 올리기... break; case 8 : // 저항력 올리기... break; case 9 : // 공격 성공율 및 회피 성공율 올리기.. break; default : result = 0 ; break; } TRACE("Area magictype4 ,, magicid=%d\n", magicid); SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcUser->m_iUserId, send_index ); SetShort( send_buff, pNpc->m_sNid+NPC_BAND, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); g_pMain->Send( send_buff, send_index ); } } } } if(pNpcIDList) { delete [] pNpcIDList; pNpcIDList = NULL; } }
short CUser::GetDamage(int tid, int magicid) { short damage = 0; float Attack = 0; float Avoid = 0; short Hit = 0; short HitB = 0; short Ac = 0; int random = 0; uint8 result; _MAGIC_TABLE* pTable = nullptr; _MAGIC_TYPE1* pType1 = nullptr; _MAGIC_TYPE2* pType2 = nullptr; if (tid < NPC_BAND || tid > INVALID_BAND) return damage; CNpc* pNpc = nullptr; pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == nullptr) return damage; if(pNpc->m_proto->m_tNpcType == NPC_ARTIFACT || pNpc->m_proto->m_tNpcType == NPC_PHOENIX_GATE || pNpc->m_proto->m_tNpcType == NPC_GATE_LEVER || pNpc->m_proto->m_tNpcType == NPC_SPECIAL_GATE ) return damage; Attack = (float)m_fHitrate; // 공격민첩 Avoid = (float)pNpc->m_sEvadeRate; // 방어민첩 Hit = m_sHitDamage; // 공격자 Hit // Ac = (short)(pNpc->m_sDefense) + pNpc->m_sLevel; // 방어자 Ac 2002.07.06 Ac = (short)(pNpc->m_sDefense); // 방어자 Ac HitB = (int)((Hit * 200) / (Ac + 240)) ; // 새로운 공격식의 B if( magicid > 0 ) { // Skill Hit. pTable = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pTable ) return -1; if (pTable->bType[0] == 1) { // SKILL HIT! pType1 = g_pMain->m_Magictype1Array.GetData( magicid ); // Get magic skill table type 1. if( !pType1 ) return -1; if(pType1->bHitType) { // Non-relative hit. random = myrand(0,100) ; if (pType1->sHitRate <= random) result = FAIL; else result = SUCCESS; } else { // Relative hit. result = GetHitRate( (Attack / Avoid) * (pType1->sHitRate / 100.0f) ); } /* if(pType1->bHitType) { // Non-relative hit. Hit = m_sHitDamage * (pType1->sHit / 100.0f); } else { // Hit = (m_sHitDamage - pNpc->m_sDefense) Hit = HitB * (pType1->sHit / 100.0f) ; } */ Hit = (short)(HitB * (pType1->sHit / 100.0f)); } else if (pTable->bType[0] == 2) { // ARROW HIT! pType2 = g_pMain->m_Magictype2Array.GetData( magicid ); // Get magic skill table type 1. if( !pType2 ) return -1; if(pType2->bHitType == 1 || pType2->bHitType == 2 ) { // Non-relative/Penetration hit. random = myrand(0,100) ; if (pType2->sHitRate <= random) result = FAIL; else result = SUCCESS; //result = SUCCESS; } else { // Relative hit/Arc hit. result = GetHitRate( (Attack / Avoid) * (pType2->sHitRate / 100.0f) ); } if(pType2->bHitType == 1 /* || pType2->bHitType == 2 */ ) { Hit = (short)(m_sHitDamage * (pType2->sAddDamage / 100.0f)); } else { // Hit = (m_sHitDamage - pNpc->m_sDefense) * (pType2->sAddDamage / 100.0f); Hit = (short)(HitB * (pType2->sAddDamage / 100.0f)); } } } else { // Normal Hit. result = GetHitRate(Attack/Avoid); // 타격비 구하기 } switch(result) { case GREAT_SUCCESS: case SUCCESS: case NORMAL: if( magicid > 0 ) { // 스킬 공격 damage = (short)Hit; random = myrand(0, damage); // damage = (short)((0.85f * (float)Hit) + 0.3f * (float)random); if (pTable->bType[0] == 1) { damage = (short)((float)Hit + 0.3f * (float)random + 0.99); } else { damage = (short)((float)(Hit*0.6f) + 1.0f * (float)random + 0.99); } } else { //일반 공격 damage = (short)(HitB); random = myrand(0, damage); damage = (short)((0.85f * (float)HitB) + 0.3f * (float)random); } break; case FAIL: // 사장님 요구 damage = 0; break; } if (damage <= 0) return 0; damage = GetMagicDamage(damage,tid); // 2. Magical item damage.... //return 3000; return damage; }
void CNpcMagicProcess::ExecuteType3(int magicid, int tid, int data1, int data2, int data3, int moral ) // Applied when a magical attack, healing, and mana restoration is done. { int damage = 0, result = 1, send_index=0, attack_type = 0; char send_buff[256]; _MAGIC_TYPE3* pType = NULL; CNpc* pNpc = NULL ; // Pointer initialization! int dexpoint = 0; _MAGIC_TABLE* pMagic = NULL; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) return; if(tid == -1) { // 지역 공격,, 몬스터의 지역공격은 게임서버에서 처리한다.. 유저들을 상대로.. goto packet_send; } pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND); if(pNpc == NULL || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0) { result = 0; goto packet_send; } pType = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType ) return; damage = GetMagicDamage(tid, pType->sFirstDamage, pType->bAttribute, dexpoint); // if(damage == 0) damage = -1; //TRACE("magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if (pType->bDuration == 0) { // Non-Durational Spells. if (pType->bDirectType == 1) { // Health Point related ! if(damage > 0) { result = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); /* if(pType->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE) { // Npc가 죽은 경우,, pNpc->SendExpToUserList(); // 경험치 분배!! pNpc->SendDead(); m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP, MAGIC_ATTACK); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP, MAGIC_ATTACK); } */ } } } else if (pType->bDuration != 0) { // Durational Spells! Remember, durational spells only involve HPs. } packet_send: //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { SetByte( send_buff, AG_MAGIC_ATTACK_RESULT, send_index ); SetByte( send_buff, MAGIC_EFFECTING, send_index ); SetDWORD( send_buff, magicid, send_index ); SetShort( send_buff, m_pSrcNpc->m_sNid+NPC_BAND, send_index ); SetShort( send_buff, tid, send_index ); SetShort( send_buff, data1, send_index ); SetShort( send_buff, result, send_index ); SetShort( send_buff, data3, send_index ); SetShort( send_buff, moral, send_index ); SetShort( send_buff, 0, send_index ); SetShort( send_buff, 0, send_index ); m_pSrcNpc->SendAll(send_buff, send_index); } }
void CMagicProcess::AreaAttackDamage(int magictype, int rx, int rz, int magicid, int moral, int data1, int data2, int data3, int dexpoint, int righthand_damage) { MAP* pMap = m_pSrcUser->GetMap(); if (pMap == nullptr) return; // 자신의 region에 있는 UserArray을 먼저 검색하여,, 가까운 거리에 유저가 있는지를 판단.. if(rx < 0 || rz < 0 || rx > pMap->GetXRegionMax() || rz > pMap->GetZRegionMax()) { TRACE("#### CMagicProcess-AreaAttackDamage() Fail : [nid=%d, name=%s], nRX=%d, nRZ=%d #####\n", m_pSrcUser->m_iUserId, m_pSrcUser->m_strUserID, rx, rz); return; } _MAGIC_TYPE3* pType3 = nullptr; _MAGIC_TYPE4* pType4 = nullptr; _MAGIC_TABLE* pMagic = nullptr; int damage = 0, tid = 0, target_damage = 0, attribute = 0; float fRadius = 0; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic maintable error ,, magicid=%d\n", magicid); return; } if(magictype == 3) { pType3 = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType3 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table3 error ,, magicid=%d\n", magicid); return; } target_damage = pType3->sFirstDamage; attribute = pType3->bAttribute; fRadius = (float)pType3->bRadius; } else if(magictype == 4) { pType4 = g_pMain->m_Magictype4Array.GetData( magicid ); // Get magic skill table type 3. if( !pType4 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magic table4 error ,, magicid=%d\n", magicid); return; } fRadius = (float)pType4->bRadius; } if( fRadius <= 0 ) { TRACE("#### CMagicProcess-AreaAttackDamage Fail : magicid=%d, radius = %d\n", magicid, fRadius); return; } __Vector3 vStart, vEnd; CNpc* pNpc = nullptr ; // Pointer initialization! float fDis = 0.0f; vStart.Set((float)data1, (float)0, (float)data3); int count = 0, total_mon = 0, attack_type=0; int* pNpcIDList = nullptr; bool bResult = true; pMap->m_lock.Acquire(); CRegion *pRegion = &pMap->m_ppRegion[rx][rz]; total_mon = pRegion->m_RegionNpcArray.GetSize(); pNpcIDList = new int[total_mon]; foreach_stlmap (itr, pRegion->m_RegionNpcArray) pNpcIDList[count++] = *itr->second; pMap->m_lock.Release(); for(int i = 0; i < total_mon; i++) { int nid = pNpcIDList[i]; if( nid < NPC_BAND ) continue; pNpc = g_pMain->m_arNpc.GetData(nid); if (pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD) continue; if( m_pSrcUser->m_bNation == pNpc->m_byGroup ) continue; vEnd.Set(pNpc->GetX(), pNpc->GetY(), pNpc->GetZ()); fDis = pNpc->GetDistance(vStart, vEnd); if(fDis > fRadius) continue; if (magictype == 3) { damage = GetMagicDamage(pNpc->GetID(), target_damage, attribute, dexpoint, righthand_damage); TRACE("Area magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if(damage >= 0) { bResult = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType3->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_iUserId + USER_BAND) == false) { m_pSrcUser->SendAttackSuccess(pNpc->GetID(), MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { m_pSrcUser->SendAttackSuccess(pNpc->GetID(), ATTACK_SUCCESS, damage, pNpc->m_iHP); } } // 패킷 전송..... //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << pNpc->GetID() << uint16(data1) << uint16(bResult) << uint16(data3) << uint16(moral) << uint16(0) << uint16(0); g_pMain->Send(&result); } } else if(magictype == 4) { // 타잎 4일 경우... bResult = true; switch (pType4->bBuffType) { // Depending on which buff-type it is..... case 1 : // HP 올리기.. break; case 2 : // 방어력 올리기.. break; case 4 : // 공격력 올리기.. break; case 5 : // 공격 속도 올리기.. break; case 6 : // 이동 속도 올리기.. //if (pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime > 0) { // result = 0 ; //} //else { pNpc->m_MagicType4[pType4->bBuffType-1].byAmount = pType4->bSpeed; pNpc->m_MagicType4[pType4->bBuffType-1].sDurationTime = pType4->sDuration; pNpc->m_MagicType4[pType4->bBuffType-1].tStartTime = UNIXTIME; pNpc->m_fSpeed_1 = (float)(pNpc->m_fOldSpeed_1 * ((double)pType4->bSpeed / 100)); pNpc->m_fSpeed_2 = (float)(pNpc->m_fOldSpeed_2 * ((double)pType4->bSpeed / 100)); //} break; case 7 : // 능력치 올리기... break; case 8 : // 저항력 올리기... break; case 9 : // 공격 성공율 및 회피 성공율 올리기.. break; default : bResult = false; break; } TRACE("Area magictype4 ,, magicid=%d\n", magicid); Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << pNpc->GetID() << uint16(data1) << uint16(bResult) << uint16(data3) << uint16(0) << uint16(0) << uint16(0); g_pMain->Send(&result); } } if(pNpcIDList) { delete [] pNpcIDList; pNpcIDList = nullptr; } }
void CMagicProcess::ExecuteType3(int magicid, int tid, int data1, int data2, int data3, int moral, int dexpoint, int righthand_damage ) // Applied when a magical attack, healing, and mana restoration is done. { int damage = 0, attack_type = 0; bool bResult = true; _MAGIC_TYPE3* pType = nullptr; CNpc* pNpc = nullptr ; // Pointer initialization! _MAGIC_TABLE* pMagic = nullptr; pMagic = g_pMain->m_MagictableArray.GetData( magicid ); // Get main magic table. if( !pMagic ) return; if(tid == -1) { // 지역 공격 /*bResult =*/ AreaAttack(3, magicid, moral, data1, data2, data3, dexpoint, righthand_damage); //if(result == 0) goto packet_send; //else return; } pNpc = g_pMain->m_arNpc.GetData(tid); if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0) { bResult = false; goto packet_send; } pType = g_pMain->m_Magictype3Array.GetData( magicid ); // Get magic skill table type 3. if( !pType ) return; // if (pType->sFirstDamage < 0) { if ((pType->sFirstDamage < 0) && (pType->bDirectType == 1) && (magicid < 400000)) { damage = GetMagicDamage(tid, pType->sFirstDamage, pType->bAttribute, dexpoint, righthand_damage) ; } else { damage = pType->sFirstDamage ; } //TRACE("magictype3 ,, magicid=%d, damage=%d\n", magicid, damage); if (pType->bDuration == 0) { // Non-Durational Spells. if (pType->bDirectType == 1) { // Health Point related ! //damage = pType->sFirstDamage; // Reduce target health point // if(damage >= 0) { if(damage > 0) { bResult = pNpc->SetHMagicDamage(damage); } else { damage = abs(damage); if(pType->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if (!pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_iUserId + USER_BAND)) { m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP, MAGIC_ATTACK); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP, MAGIC_ATTACK); } } } else if ( pType->bDirectType == 2 || pType->bDirectType == 3 ) // Magic or Skill Point related ! pNpc->MSpChange(pType->bDirectType, pType->sFirstDamage); // Change the SP or the MP of the target. // else if( pType->bDirectType == 4 ) // Armor Durability related. // pNpc->ItemWoreOut( DEFENCE, pType->sFirstDamage); // Reduce Slot Item Durability } else if (pType->bDuration != 0) { // Durational Spells! Remember, durational spells only involve HPs. if(damage >= 0) { } else { damage = abs(damage); if(pType->bAttribute == 3) attack_type = 3; // 기절시키는 마법이라면..... else attack_type = magicid; if(pNpc->SetDamage(attack_type, damage, m_pSrcUser->m_iUserId + USER_BAND) == false) { m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP); } else { // 공격 결과 전송 m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP); } } damage = GetMagicDamage(tid, pType->sTimeDamage, pType->bAttribute, dexpoint, righthand_damage); // The duration magic routine. for(int i=0; i<MAX_MAGIC_TYPE3; i++) { if(pNpc->m_MagicType3[i].sHPAttackUserID == -1 && pNpc->m_MagicType3[i].byHPDuration == 0) { pNpc->m_MagicType3[i].sHPAttackUserID = m_pSrcUser->m_iUserId; pNpc->m_MagicType3[i].tStartTime = UNIXTIME; pNpc->m_MagicType3[i].byHPDuration = pType->bDuration; pNpc->m_MagicType3[i].byHPInterval = 2; pNpc->m_MagicType3[i].sHPAmount = damage / (pType->bDuration / 2); break; } } } packet_send: //if ( pMagic->bType[1] == 0 || pMagic->bType[1] == 3 ) { Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING)); result << magicid << m_pSrcUser->m_iUserId << uint16(tid) << uint16(data1) << uint16(bResult) << uint16(data3) << uint16(moral) << uint16(0) << uint16(0); g_pMain->Send(&result); } }
short Unit::GetDamage(Unit *pTarget, _MAGIC_TABLE *pSkill) { short damage = 0; int random = 0; short common_damage = 0, temp_hit = 0, temp_ac = 0, temp_hit_B = 0; uint8 result; if (pTarget == nullptr || pTarget->isDead()) return -1; temp_ac = pTarget->m_sTotalAc + pTarget->m_sACAmount; temp_hit_B = (int)((m_sTotalHit * m_bAttackAmount * 200 / 100) / (temp_ac + 240)); // Skill/arrow hit. if (pSkill != nullptr) { // SKILL HIT! YEAH! if (pSkill->bType[0] == 1) { _MAGIC_TYPE1 *pType1 = g_pMain->m_Magictype1Array.GetData(pSkill->iNum); if (pType1 == nullptr) return -1; // Non-relative hit. if (pType1->bHitType) { result = (pType1->sHitRate <= myrand(0, 100) ? FAIL : SUCCESS); } // Relative hit. else { result = GetHitRate((m_sTotalHitrate / pTarget->m_sTotalEvasionrate) * (pType1->sHitRate / 100.0f)); } temp_hit = (short)(temp_hit_B * (pType1->sHit / 100.0f)); } // ARROW HIT! YEAH! else if (pSkill->bType[0] == 2) { _MAGIC_TYPE2 *pType2 = g_pMain->m_Magictype2Array.GetData(pSkill->iNum); if (pType2 == nullptr) return -1; // Non-relative/Penetration hit. if (pType2->bHitType == 1 || pType2->bHitType == 2) { result = (pType2->sHitRate <= myrand(0, 100) ? FAIL : SUCCESS); } // Relative hit/Arc hit. else { result = GetHitRate((m_sTotalHitrate / pTarget->m_sTotalEvasionrate) * (pType2->sHitRate / 100.0f)); } if (pType2->bHitType == 1 /* || pType2->bHitType == 2 */) temp_hit = (short)(m_sTotalHit * m_bAttackAmount * (pType2->sAddDamage / 100.0f) / 100); else temp_hit = (short)(temp_hit_B * (pType2->sAddDamage / 100.0f)); } } // Normal hit (R attack) else { temp_hit = m_sTotalHit * m_bAttackAmount / 100; result = GetHitRate(m_sTotalHitrate / pTarget->m_sTotalEvasionrate); } switch (result) { // 1. Magical item damage.... case GREAT_SUCCESS: case SUCCESS: case NORMAL: if (pSkill != nullptr) { // Skill Hit. damage = (short)temp_hit; random = myrand(0, damage); if (pSkill->bType[0] == 1) damage = (short)((temp_hit + 0.3f * random) + 0.99f); else damage = (short)(((temp_hit * 0.6f) + 1.0f * random) + 0.99f); } else { // Normal Hit. damage = (short)temp_hit_B; random = myrand(0, damage); damage = (short)((0.85f * temp_hit_B) + 0.3f * random); } break; case FAIL: damage = 0; break; } damage = GetMagicDamage(damage, pTarget); // 2. Magical item damage.... // These two only apply to players if (isPlayer() && pTarget->isPlayer()) { damage = GetACDamage(damage, pTarget); // 3. Additional AC calculation.... damage = damage / 3; } return damage; }