예제 #1
0
void CNpc::NpcInOut(BYTE Type, float fx, float fz, float fy)
{
	int send_index = 0;
	char buff[1024];
	memset( buff, 0x00, 1024 );

	C3DMap *pMap = m_pMain->GetZoneByID(getZoneID());
	if (pMap == NULL)
		return;

	m_pMap = pMap;

	if( Type == NPC_OUT )
	{
		pMap->RegionNpcRemove( m_sRegion_X, m_sRegion_Z, m_sNid );
	}
	else	
	{
		pMap->RegionNpcAdd( m_sRegion_X, m_sRegion_Z, m_sNid );
		m_fCurX = fx;	m_fCurZ = fz;	m_fCurY = fy;
	}

	SetByte( buff, WIZ_NPC_INOUT, send_index );
	SetByte( buff, Type, send_index );
	SetShort( buff, m_sNid, send_index );
	if( Type == NPC_OUT ) {
		m_pMain->Send_Region(buff, send_index, GetMap(), m_sRegion_X, m_sRegion_Z);
		return;
	}

	GetNpcInfo(buff, send_index);
	m_pMain->Send_Region(buff, send_index, GetMap(), m_sRegion_X, m_sRegion_Z);
}
예제 #2
0
void CAISocket::RecvNpcDead(Packet & pkt)
{
	uint16 nid = pkt.read<uint16>();
	CNpc* pNpc = g_pMain->m_arNpcArray.GetData(nid);
	if (pNpc == NULL)
		return;

	C3DMap* pMap = pNpc->GetMap();
	if (pMap == NULL)
		return;

	if (pNpc->m_byObjectType == SPECIAL_OBJECT)
	{
		_OBJECT_EVENT *pEvent = pMap->GetObjectEvent(pNpc->m_sSid);
		if (pEvent)
			pEvent->byLife = 0;
	}

	pMap->RegionNpcRemove(pNpc->m_sRegion_X, pNpc->m_sRegion_Z, nid);

	Packet result(WIZ_DEAD);
	result << nid;
	g_pMain->Send_Region(&result, pNpc->GetMap(), pNpc->m_sRegion_X, pNpc->m_sRegion_Z);

	pNpc->m_sRegion_X = pNpc->m_sRegion_Z = 0;
}
예제 #3
0
void CAISocket::RecvNpcGiveItem(Packet & pkt)
{
	Packet result(WIZ_ITEM_DROP);
	short sUid, sNid, regionx, regionz;
	float fX, fZ, fY;
	BYTE byCount, bZone;
	int nItemNumber[NPC_HAVE_ITEM_LIST];
	short sCount[NPC_HAVE_ITEM_LIST];
	CUser* pUser = NULL;
	pkt >> sUid >> sNid >> bZone >> regionx >> regionz >> fX >> fZ >> fY >> byCount;

	for (int i = 0; i < byCount; i++)
		pkt >> nItemNumber[i] >> sCount[i];

	if (sUid < 0 || sUid >= MAX_USER)
		return;

	C3DMap *pMap = g_pMain->GetZoneByID(bZone);
	if (pMap == NULL)
		return;

	_ZONE_ITEM *pItem = new _ZONE_ITEM;
	for(int i=0; i<6; i++) {
		pItem->itemid[i] = 0;
		pItem->count[i] = 0;
	}

	pItem->time = TimeGet();
	pItem->x = fX;
	pItem->z = fZ;
	pItem->y = fY;
	for(int i=0; i<byCount; i++) {
		if( g_pMain->GetItemPtr(nItemNumber[i]) ) {
			pItem->itemid[i] = nItemNumber[i];
			pItem->count[i] = sCount[i];
		}
	}

	if (!pMap->RegionItemAdd(regionx, regionz, pItem ))
	{
		delete pItem;
		return;
	}

	pUser = g_pMain->GetUserPtr(sUid);
	if (pUser == NULL) 
		return;

	result << sNid << uint32(pItem->bundle_index);
	if (!pUser->isInParty())
		pUser->Send(&result);
	else
		g_pMain->Send_PartyMember(pUser->m_sPartyIndex, &result);
}
예제 #4
0
void CNpc::RegisterRegion()
{
	int iRegX = 0, iRegZ = 0, old_region_x = 0, old_region_z = 0;
	iRegX = (int)(m_fCurX / VIEW_DISTANCE);
	iRegZ = (int)(m_fCurZ / VIEW_DISTANCE);

	if (m_sRegion_X != iRegX || m_sRegion_Z != iRegZ)
	{
		C3DMap* pMap = GetMap();
		if (pMap == NULL)
			return;
		
		old_region_x = m_sRegion_X;	old_region_z = m_sRegion_Z;
		pMap->RegionNpcRemove(m_sRegion_X, m_sRegion_Z, m_sNid);
		m_sRegion_X = iRegX;		m_sRegion_Z = iRegZ;
		pMap->RegionNpcAdd(m_sRegion_X, m_sRegion_Z, m_sNid);

		RemoveRegion( old_region_x - m_sRegion_X, old_region_z - m_sRegion_Z );	// delete npc 는 계산 방향이 진행방향의 반대...
		InsertRegion( m_sRegion_X - old_region_x, m_sRegion_Z - old_region_z );	// add npc 는 계산 방향이 진행방향...
	}
}
예제 #5
0
int CNpc::GetRegionNpcList(int region_x, int region_z, char *buff, int &t_count)
{
	if( m_pMain->m_bPointCheckFlag == FALSE)	return 0;	// 포인터 참조하면 안됨

	int buff_index = 0, i=0, j=0;
	int user_count = 0, nid = -1;
	C3DMap* pMap = GetMap();
	CNpc* pNpc = NULL;

	if (pMap == NULL
		|| region_x < 0 || region_z < 0 
		|| region_x > pMap->GetXRegionMax() 
		|| region_z > pMap->GetZRegionMax() )
		return 0;

	EnterCriticalSection( &g_region_critical );

	map < int, int* >::iterator		Iter1;
	map < int, int* >::iterator		Iter2;
	
	Iter1 = pMap->m_ppRegion[region_x][region_z].m_RegionNpcArray.m_UserTypeMap.begin();
	Iter2 = pMap->m_ppRegion[region_x][region_z].m_RegionNpcArray.m_UserTypeMap.end();

	for( ; Iter1 != Iter2; Iter1++ ) {
		nid = *( (*Iter1).second );
		if( nid < 0 )
			continue;
		pNpc = (CNpc*)m_pMain->m_arNpcArray.GetData(nid);
		if( pNpc) {
			SetShort( buff, pNpc->m_sNid, buff_index );
			t_count++;
		}
	}

	LeaveCriticalSection( &g_region_critical );

	return buff_index;
}
예제 #6
0
void CAISocket::RecvNpcDead(char* pBuf)
{
	int index = 0, send_index = 0;
	int nid = 0;
	char send_buff[256];
	_OBJECT_EVENT* pEvent = NULL;

	nid = GetShort(pBuf,index);


	if(nid >= NPC_BAND)		{
		CNpc* pNpc = m_pMain->m_arNpcArray.GetData(nid);
		if(!pNpc)	return;

		C3DMap* pMap = pNpc->GetMap();
		if (pMap == NULL)
			return;

		if( pNpc->m_byObjectType == SPECIAL_OBJECT )	{
			pEvent = pMap->GetObjectEvent( pNpc->m_sSid );
			if( pEvent )	pEvent->byLife = 0;
		}

		//pNpc->NpcInOut( NPC_OUT );
		//TRACE("RecvNpcDead - (%d,%s)\n", pNpc->m_sNid, pNpc->m_strName);

		pMap->RegionNpcRemove(pNpc->m_sRegion_X, pNpc->m_sRegion_Z, nid);
		//TRACE("--- RecvNpcDead : Npc를 Region에서 삭제처리.. ,, zone=%d, region_x=%d, y=%d\n", pNpc->m_sZoneIndex, pNpc->m_sRegion_X, pNpc->m_sRegion_Z);

		SetByte( send_buff, WIZ_DEAD, send_index );
		SetShort( send_buff, nid, send_index );
		m_pMain->Send_Region(send_buff, send_index, pNpc->GetMap(), pNpc->m_sRegion_X, pNpc->m_sRegion_Z, NULL, false);

		pNpc->m_sRegion_X = 0;		pNpc->m_sRegion_Z = 0;
	}
}
예제 #7
0
파일: AISocket.cpp 프로젝트: Damra/koserver
void CAISocket::RecvNpcGiveItem(Packet & pkt)
{
	Packet result(WIZ_ITEM_DROP);
	short sUid, sNid, regionx, regionz;
	float fX, fZ, fY;
	uint8 byCount, bZone;
	int nItemNumber[NPC_HAVE_ITEM_LIST];
	short sCount[NPC_HAVE_ITEM_LIST];
	CUser* pUser = nullptr;
	pkt >> sUid >> sNid >> bZone >> regionx >> regionz >> fX >> fZ >> fY >> byCount;

	for (int i = 0; i < byCount; i++)
		pkt >> nItemNumber[i] >> sCount[i];

	if (sUid < 0 || sUid >= MAX_USER)
		return;

	C3DMap *pMap = g_pMain->GetZoneByID(bZone);
	if (pMap == nullptr)
		return;

	_LOOT_BUNDLE * pBundle = new _LOOT_BUNDLE;

	pBundle->tDropTime = UNIXTIME;
	pBundle->x = fX;
	pBundle->z = fZ;
	pBundle->y = fY;

	for (int i = 0; i < byCount; i++)
	{
		if (g_pMain->GetItemPtr(nItemNumber[i]))
		{
			_LOOT_ITEM pItem(nItemNumber[i], sCount[i]);
			if (nItemNumber[i] == ITEM_GOLD)
			{
				// Add on any additional coins earned because of a global coin event.
				// NOTE: Officially it caps at SHRT_MAX, but that's really only for technical reasons.
				// Using the unsigned range gives us a little bit of wiggle room.
				uint32 coinAmount = sCount[i] * (100 + g_pMain->m_byCoinEventAmount) / 100;
				if (sCount[i] + coinAmount > USHRT_MAX)
					coinAmount = USHRT_MAX;

				pUser = g_pMain->GetUserPtr(sUid);

				if (pUser != nullptr) 
					if (pUser->m_bPremiumType != 0)
						coinAmount = coinAmount * (100 + g_pMain->m_PremiumItemArray.GetData(pUser->m_bPremiumType)->NoahPercent) / 100;

				pItem.sCount = coinAmount;
			}

			pBundle->Items.push_back(pItem); // emplace_back() would be so much more useful here, but requires C++11.
		}
	}

	if (!pMap->RegionItemAdd(regionx, regionz, pBundle))
	{
		delete pBundle;
		return;
	}

	if (pUser == nullptr) 
		return;

	result << sNid << pBundle->nBundleID;
	if (!pUser->isInParty())
		pUser->Send(&result);
	else
		g_pMain->Send_PartyMember(pUser->GetPartyID(), &result);
}
예제 #8
0
void CAISocket::RecvNpcGiveItem(char* pBuf)
{
	int index = 0, send_index = 0;
	char send_buff[1024];
	short sUid, sNid, sZone, regionx, regionz;
	float fX, fZ, fY;
	BYTE byCount;
	int nItemNumber[NPC_HAVE_ITEM_LIST];
	short sCount[NPC_HAVE_ITEM_LIST];
	_ZONE_ITEM* pItem = NULL;
	C3DMap* pMap = NULL;
	CUser* pUser = NULL;

	sUid = GetShort(pBuf,index);	// Item을 가져갈 사람의 아이디... (이것을 참조해서 작업하셈~)
	sNid = GetShort(pBuf,index);
	sZone = GetShort(pBuf, index);
	regionx = GetShort( pBuf, index );
	regionz = GetShort( pBuf, index );
	fX = Getfloat(pBuf,index);
	fZ = Getfloat(pBuf,index);
	fY = Getfloat(pBuf,index);
	byCount = GetByte(pBuf,index);
	for(int i=0; i<byCount; i++)
	{
		nItemNumber[i] = GetDWORD(pBuf, index);
		sCount[i] = GetShort(pBuf,index);
	}

	if( sUid < 0 || sUid >= MAX_USER ) return;
	pMap = m_pMain->GetZoneByID(sZone);
	if (pMap == NULL)
		return;

	pItem = new _ZONE_ITEM;
	for(int i=0; i<6; i++) {
		pItem->itemid[i] = 0;
		pItem->count[i] = 0;
	}
	pItem->bundle_index = pMap->m_wBundle;
	pItem->time = TimeGet();
	pItem->x = fX;
	pItem->z = fZ;
	pItem->y = fY;
	for(int i=0; i<byCount; i++) {
		if( m_pMain->m_ItemtableArray.GetData(nItemNumber[i]) ) {
			pItem->itemid[i] = nItemNumber[i];
			pItem->count[i] = sCount[i];
		}
	}

	if (!pMap->RegionItemAdd(regionx, regionz, pItem ))
	{
		delete pItem;
		return;
	}

	pUser = m_pMain->GetUserPtr(sUid);
	if (pUser == NULL) 
		return;
	
	send_index = 0;

	SetByte( send_buff, WIZ_ITEM_DROP, send_index );
	SetShort( send_buff, sNid, send_index );
	SetDWORD( send_buff, pItem->bundle_index, send_index );
	if( pUser->m_sPartyIndex == -1 )
		pUser->Send( send_buff, send_index );
	else
		m_pMain->Send_PartyMember( pUser->m_sPartyIndex, send_buff, send_index );
}
void CUser::ZoneChange(uint16 sNewZone, float x, float z)
{
	C3DMap * pMap = g_pMain->GetZoneByID(sNewZone);
	if (pMap == nullptr) 
		return;

	ZoneChangeError errorReason;
	if (!CanChangeZone(pMap, errorReason))
	{
		Packet result;

		switch (errorReason)
		{
		case ZoneChangeErrorWrongLevel:
			/* this will depend on the zone */
			break;

		case ZoneChangeErrorWarActive:
			result.Initialize(WIZ_WARP_LIST);
			result << uint8(2) << uint8(4);
			Send(&result);
			break;

		case ZoneChangeErrorNeedLoyalty:
			/* does this have an error? */
			break;
		}

		return;
	}

	m_bWarp = true;
	m_bZoneChangeFlag = true;

	UserInOut(INOUT_OUT);

	if (sNewZone == ZONE_SNOW_BATTLE)
		SetMaxHp(1);

	if (GetZoneID() != sNewZone)
	{
		SetZoneAbilityChange();

		// Reset the user's anger gauge when leaving the zone
		// Unknown if this is official behaviour, but it's logical.
		if (GetAngerGauge() > 0)
			UpdateAngerGauge(0);

		/* 
			Here we also send a clan packet with subopcode 0x16 (with a byte flag of 2) if war zone/Moradon
			or subopcode 0x17 (with nWarEnemyID) for all else
		*/
#if 0
		if (isInClan())
		{
			CKnights * pKnights = g_pMain->GetClanPtr(GetClanID());
			if (pKnights != nullptr
					&& pKnights->bKnightsWarStarted)
			{
				Packet clanPacket(WIZ_KNIGHTS_PROCESS);
				if (pMap->isWarZone() || byNewZone == ZONE_MORADON)
					clanPacket << uint8(0x17) << uint8(2);
				else 
					clanPacket << uint16(0x16) << uint16(0 /*nWarEnemyID*/);

				Send(&clanPacket);
			}
		}
#endif


		if (sNewZone == ZONE_SNOW_BATTLE)
			SetMaxHp();

		if (isInParty())
			PartyRemove(GetSocketID());

		ResetWindows();
	}

	m_bZone = (uint8) sNewZone; // this is 2 bytes to support the warp data loaded from SMDs. It should not go above a byte, however.
	SetPosition(x, 0.0f, z);
	m_pMap = pMap;

	if (g_pMain->m_nServerNo != pMap->m_nServerNo)
	{
		_ZONE_SERVERINFO *pInfo = g_pMain->m_ServerArray.GetData(pMap->m_nServerNo);
		if (pInfo == nullptr) 
			return;

		UserDataSaveToAgent();

		m_bLogout = 2;	// server change flag
		SendServerChange(pInfo->strServerIP, 2);
		return;
	}
	
	SetRegion(GetNewRegionX(), GetNewRegionZ());

	Packet result(WIZ_ZONE_CHANGE, uint8(ZoneChangeTeleport));
	result << uint16(GetZoneID()) << GetSPosX() << GetSPosZ() << GetSPosY() << g_pMain->m_byOldVictory;
	Send(&result);

	if (!m_bZoneChangeSameZone)
	{
		m_sWhoKilledMe = -1;
		m_iLostExp = 0;
		m_bRegeneType = 0;
		m_tLastRegeneTime = 0;
		m_sBind = -1;
		InitType3();
		InitType4();
		CMagicProcess::CheckExpiredType9Skills(this, true);
		SetUserAbility();
	}	

	result.Initialize(AG_ZONE_CHANGE);
	result << GetSocketID() << GetZoneID();
	Send_AIServer(&result);

	m_bZoneChangeSameZone = false;
	m_bZoneChangeFlag = false;
}