Пример #1
0
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 );
	}
	
}
Пример #2
0
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;
	}
}
Пример #3
0
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);
	}
}
Пример #5
0
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;
	}
}
Пример #6
0
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);
	}
	
}
Пример #7
0
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;	  
}