Beispiel #1
0
void CUser::Attack(int sid, int tid)
{
	CNpc* pNpc = m_pMain->m_arNpc.GetData(tid-NPC_BAND);
	if(pNpc == NULL)	return;
	if(pNpc->m_NpcState == NPC_DEAD) return;
	if(pNpc->m_iHP == 0) return;

/*	if(pNpc->m_tNpcType == NPCTYPE_GUARD)					// 경비병이면 타겟을 해당 유저로
	{
		pNpc->m_Target.id = m_iUserId + USER_BAND;
		pNpc->m_Target.x = m_curx;
		pNpc->m_Target.y = m_cury;
		pNpc->m_Target.failCount = 0;
		pNpc->Attack(m_pIocport);
	//	return;
	}	*/

	int nDefence = 0, nFinalDamage = 0;
	// NPC 방어값 
	nDefence = pNpc->GetDefense();

	// 명중이면 //Damage 처리 ----------------------------------------------------------------//
	nFinalDamage = GetDamage(tid);
	if( m_pMain->m_byTestMode )		nFinalDamage = 3000;	// sungyong test
		
	// Calculate Target HP	 -------------------------------------------------------//
	short sOldNpcHP = pNpc->m_iHP;

	if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND, m_pIocport) == FALSE)
	{
		// Npc가 죽은 경우,,
		pNpc->SendExpToUserList(); // 경험치 분배!!
		pNpc->SendDead(m_pIocport);
		SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP);

	//	CheckMaxValue(m_dwXP, 1);		// 몹이 죽을때만 1 증가!	
	//	SendXP();
	}
	else
	{
		// 공격 결과 전송
		SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP);
	}
	//	m_dwLastAttackTime = GetTickCount();
}
uint8 CMagicProcess::ExecuteType1(int magicid, int tid, int data1, int data2, int data3, uint8 sequence)   // Applied to an attack skill using a weapon.
{	
	int damage = 0;
	uint8 bResult = 1;     // Variable initialization. result == 1 : success, 0 : fail
	_MAGIC_TABLE* pMagic = g_pMain->m_MagictableArray.GetData( magicid );   // Get main magic table.
	if( !pMagic ) return 0; 

	damage = m_pSrcUser->GetDamage(tid, magicid);  // Get damage points of enemy.	
// 	if(damage <= 0)	damage = 1;
	//TRACE("magictype1 ,, magicid=%d, damage=%d\n", magicid, damage);

//	if (damage > 0) {
		CNpc* pNpc = nullptr ;      // Pointer initialization!
		pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
		if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0)	{
			bResult = 0;
			goto packet_send;
		}

		if(pNpc->SetDamage(magicid, 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, 0, pNpc->m_iHP);
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);
		}
		else	{
			// 공격 결과 전송
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP);
		}

packet_send:
	if (pMagic->bType[1] == 0 || pMagic->bType[1] == 1)
	{
		Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING));
		result	<< magicid
				<< m_pSrcUser->m_iUserId << int16(tid) 
				<< int16(data1) << uint8(bResult) << int16(data3)
				<< int16(0) << int16(0) << int16(0)
				<< int16(damage == 0 ? -104 : 0);
		g_pMain->Send(&result);	
	}

	return bResult;
}
uint8 CMagicProcess::ExecuteType2(int magicid, int tid, int data1, int data2, int data3)
{
	Packet result(AG_MAGIC_ATTACK_RESULT, uint8(MAGIC_EFFECTING));
	int damage = m_pSrcUser->GetDamage(tid, magicid);;
	uint8 bResult = 1;
	
	result << magicid << m_pSrcUser->m_iUserId << tid << data1;

	if (damage > 0){
		CNpc* pNpc = nullptr ;      // Pointer initialization!
		pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
		if(pNpc == nullptr || pNpc->m_NpcState == NPC_DEAD || pNpc->m_iHP == 0)	{
			bResult = 0;
			goto packet_send;
		}

		if (!pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND))
		{
			result	<< int16(bResult) << data3 << int16(0) << int16(0) << int16(0)
					<< int16(damage == 0 ? -104 : 0);
			g_pMain->Send(&result);

			pNpc->SendExpToUserList(); // 경험치 분배!!
			pNpc->SendDead();
			m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);
			//m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);

			return bResult;
		}
		else	{
			// 공격 결과 전송
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP);
		}
	}
//	else
//		result = 0;

packet_send:
	// this is a little redundant but leaving it in just in case order is intended
	// this should all be removed eventually anyway...
	result	<< int16(bResult) << data3 << int16(0) << int16(0) << int16(0)
			<< int16(damage == 0 ? -104 : 0);
	g_pMain->Send(&result);
	return bResult;
}
void CGameSocket::RecvNpcHpChange(Packet & pkt)
{
	int16 nid, sAttackerID;
	int32 nHP, nAmount;
	pkt >> nid >> sAttackerID >> nHP >> nAmount;
	CNpc * pNpc = g_pMain->m_arNpc.GetData(nid);
	if (pNpc == nullptr)
		return;

	if (nAmount < 0)
	{
		pNpc->SetDamage(0, -nAmount, sAttackerID, 1);
	}
	else
	{		
		pNpc->m_iHP += nAmount;
		if (pNpc->m_iHP > pNpc->m_iMaxHP)
			pNpc->m_iHP = pNpc->m_iMaxHP;
	}
}
Beispiel #5
0
void CUser::Attack(int sid, int tid)
{
    CNpc* pNpc = g_pMain->m_arNpc.GetData(tid-NPC_BAND);
    if(pNpc == nullptr)	return;
    if(pNpc->m_NpcState == NPC_DEAD) return;
    if(pNpc->m_iHP == 0) return;

    /*	if(pNpc->m_proto->m_tNpcType == NPCTYPE_GUARD)					// 경비병이면 타겟을 해당 유저로
    	{
    		pNpc->m_Target.id = m_iUserId + USER_BAND;
    		pNpc->m_Target.x = m_curx;
    		pNpc->m_Target.y = m_cury;
    		pNpc->m_Target.failCount = 0;
    		pNpc->Attack();
    	//	return;
    	}	*/

    int nDefence = 0, nFinalDamage = 0;
    // NPC 방어값
    nDefence = pNpc->GetDefense();

    // 명중이면 //Damage 처리 ----------------------------------------------------------------//
    nFinalDamage = GetDamage(tid);

    // Calculate Target HP	 -------------------------------------------------------//
    short sOldNpcHP = pNpc->m_iHP;

    if(pNpc->SetDamage(0, nFinalDamage, m_strUserID, m_iUserId + USER_BAND) == false)
    {
        // Npc가 죽은 경우,,
        pNpc->SendExpToUserList(); // 경험치 분배!!
        pNpc->SendDead();
        SendAttackSuccess(tid, ATTACK_TARGET_DEAD, nFinalDamage, pNpc->m_iHP);
    }
    else
    {
        // 공격 결과 전송
        SendAttackSuccess(tid, ATTACK_SUCCESS, nFinalDamage, pNpc->m_iHP);
    }
}
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;
	}
}
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 );
	}
	
}
BYTE CMagicProcess::ExecuteType2(int magicid, int tid, int data1, int data2, int data3)
{
	int damage = 0, send_index = 0, result = 1 ; // Variable initialization. result == 1 : success, 0 : fail
	char send_buff[128]; 
	
	damage = m_pSrcUser->GetDamage(tid, magicid);  // Get damage points of enemy.	
//	if(damage <= 0)	damage = 1;
	//TRACE("magictype2 ,, magicid=%d, damage=%d\n", magicid, damage);
	
	if (damage > 0){
		CNpc* pNpc = NULL ;      // Pointer initialization!
		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;
		}

		if(pNpc->SetDamage(magicid, damage, m_pSrcUser->m_strUserID, m_pSrcUser->m_iUserId + USER_BAND) == FALSE)	{
			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, 0, send_index );
			SetShort( send_buff, 0, send_index );
			SetShort( send_buff, 0, send_index );

			if (damage == 0) {
				SetShort( send_buff, -104, send_index );
			}
			else {
				SetShort( send_buff, 0, send_index );
			}

			g_pMain->Send( send_buff, send_index );
			// Npc가 죽은 경우,,
			pNpc->SendExpToUserList(); // 경험치 분배!!
			pNpc->SendDead();
			m_pSrcUser->SendAttackSuccess(tid, MAGIC_ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);
			//m_pSrcUser->SendAttackSuccess(tid, ATTACK_TARGET_DEAD, damage, pNpc->m_iHP);

			return result;
		}
		else	{
			// 공격 결과 전송
			m_pSrcUser->SendAttackSuccess(tid, ATTACK_SUCCESS, damage, pNpc->m_iHP);
		}
	}
//	else
//		result = 0;

packet_send:
	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, 0, send_index );
	SetShort( send_buff, 0, send_index );
	SetShort( send_buff, 0, send_index );

	if (damage == 0) {
		SetShort( send_buff, -104, send_index );
	}
	else {
		SetShort( send_buff, 0, send_index );
	}

	g_pMain->Send( send_buff, send_index );

	return result;
}
Beispiel #9
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;
	}
}
Beispiel #10
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);
	}
	
}