void CUser::ExchangeReq(Packet & pkt)
{
	Packet result(WIZ_EXCHANGE);
	if (isDead())
		goto fail_return;
	else if (isTrading())
	{
		ExchangeCancel();
		return;
	}

	uint16 destid = pkt.read<uint16>();
	CUser* pUser = g_pMain->GetUserPtr(destid);
	if (pUser == NULL
		|| pUser->isTrading()
		|| (pUser->GetNation() != GetNation() && pUser->GetZoneID() != 21 && GetZoneID() != 21)
		|| pUser->GetZoneID() != GetZoneID())
		goto fail_return;

	m_sExchangeUser = destid;
	pUser->m_sExchangeUser = GetSocketID();

	result << uint8(EXCHANGE_REQ) << GetSocketID();
	pUser->Send(&result);
	return;

fail_return:
	result << uint8(EXCHANGE_CANCEL);
	Send(&result);
}
void CUser::Attack(Packet & pkt)
{
	Packet result;
	int16 sid = -1, tid = -1, damage, delaytime, distance;	
	uint8 bType, bResult;	
	
	CUser* pTUser = NULL;

	pkt >> bType >> bResult >> tid >> delaytime >> distance;

//	delaytime = delaytime / 100.0f;
//	distance = distance / 10.0f;

	if (isBlinking()
		|| isDead())
		return;

	_ITEM_TABLE *pTable = GetItemPrototype(RIGHTHAND);
	if (pTable == NULL) 
		return;
	
	// If you're holding a weapon, do a client-based (ugh, do not trust!) delay check.
	if (pTable 
		&& (delaytime < pTable->m_sDelay
			|| distance > pTable->m_sRange))
		return;	
	// Empty handed.
	else if (delaytime < 100)
		return;			

	// We're attacking a player...
	if (tid < NPC_BAND)
	{
		pTUser = g_pMain->GetUserPtr(tid);
 
		if (pTUser == NULL || pTUser->isDead() || pTUser->isBlinking()
				|| (pTUser->GetNation() == GetNation() && GetZoneID() != 48 /* TO-DO: implement better checks */)
				|| !isAttackZone()) 
			bResult = 0;
		else 
		{
			damage = GetDamage(pTUser, NULL);
			if (GetZoneID() == ZONE_SNOW_BATTLE && g_pMain->m_byBattleOpen == SNOW_BATTLE)
				damage = 0;		

			if (damage <= 0)
				bResult = 0;
			else 
			{
				// TO-DO: Move all this redundant code into appropriate event-based methods so that all the other cases don't have to copypasta (and forget stuff).
				pTUser->HpChange(-damage, this);
				if (pTUser->isDead())
					bResult = 2;

				ItemWoreOut(ATTACK, damage);
				pTUser->ItemWoreOut(DEFENCE, damage);
				SendTargetHP(0, tid, -damage);
			}
		}
	}
	// We're attacking an NPC...
	else if (tid >= NPC_BAND)
	{
		// AI hasn't loaded yet
		if (g_pMain->m_bPointCheckFlag == FALSE)	
			return;	

		CNpc *pNpc = g_pMain->m_arNpcArray.GetData(tid);		
		if (pNpc != NULL && pNpc->isAlive() 
			&& (pNpc->GetNation() == 0 || pNpc->GetNation() == GetNation()))
		{
			result.SetOpcode(AG_ATTACK_REQ);
			result	<< bType << bResult
					<< GetSocketID() << tid
					<< uint16(m_sTotalHit * m_bAttackAmount / 100)
					<< uint16(m_sTotalAc + m_sACAmount)
					<< m_sTotalHitrate /* this is actually a float. screwed up naming... */
					<< m_sTotalEvasionrate /* also a float */
					<< m_sItemAc
					<< m_bMagicTypeLeftHand << m_bMagicTypeRightHand
					<< m_sMagicAmountLeftHand << m_sMagicAmountRightHand;
			g_pMain->Send_AIServer(&result);	
			return;
		}
	}

	result.SetOpcode(WIZ_ATTACK);
	result << bType << bResult << GetSocketID() << tid;
	SendToRegion(&result);

	if (tid < NPC_BAND
		&& bResult == 2 // 2 means a player died.
		&& pTUser) 
	{
		pTUser->Send(&result);
		TRACE("*** User Attack Dead, id=%s, result=%d, type=%d, HP=%d\n", pTUser->m_pUserData->m_id, bResult, pTUser->m_bResHpType, pTUser->m_pUserData->m_sHp);
	}
}
Example #3
0
void CAISocket::RecvBattleEvent(Packet & pkt)
{
    string chatstr, strMaxUserName, strKnightsName;
    CUser* pUser = nullptr;
    CKnights* pKnights = nullptr;

    uint8 bType, bResult;
    pkt >> bType >> bResult;

    if (bType == BATTLE_EVENT_OPEN)
    {
    }
    else if (bType == BATTLE_MAP_EVENT_RESULT)
    {
        if (g_pMain->m_byBattleOpen == NO_BATTLE)
        {
            TRACE("#### RecvBattleEvent Fail : battleopen = %d, type = %d\n", g_pMain->m_byBattleOpen, bType);
            return;
        }

        if (bResult == KARUS)
            g_pMain->m_byKarusOpenFlag = true;
        else if (bResult == ELMORAD)
            g_pMain->m_byElmoradOpenFlag = true;
    }
    else if (bType == BATTLE_EVENT_RESULT)
    {
        if (g_pMain->m_byBattleOpen == NO_BATTLE)
        {
            TRACE("#### RecvBattleEvent Fail : battleopen = %d, type=%d\n", g_pMain->m_byBattleOpen, bType);
            return;
        }

        pkt.SByte();
        pkt >> strMaxUserName;

        if (!strMaxUserName.empty()
                && !g_pMain->m_byBattleSave)
        {
            Packet result(WIZ_BATTLE_EVENT, bType);
            result.SByte();
            result << bResult << strMaxUserName;

            g_pMain->AddDatabaseRequest(result);
            g_pMain->m_byBattleSave = true;
        }

        pUser = g_pMain->GetUserPtr(strMaxUserName, TYPE_CHARACTER);
        if (pUser != nullptr)
        {
            g_pMain->m_bVictory = pUser->GetNation();
            g_pMain->m_byOldVictory = pUser->GetNation();
        }
        else
        {
            g_pMain->m_bVictory = bResult;
            g_pMain->m_byOldVictory = bResult;
        }

        g_pMain->m_byKarusOpenFlag = false;
        g_pMain->m_byElmoradOpenFlag = false;
        g_pMain->m_byBanishFlag = true;
    }
    else if (bType == BATTLE_EVENT_MAX_USER)