void CGuildWarManager::SuggestEnd( void* pMsg )
{
	// 편의상 종전을 요청한 측을 아군, 요청받은 측을 적군이라 칭하자

	const MSG_DWORD3*	pmsg			= (MSG_DWORD3*)pMsg;
	CGuild*				friendlyGuild	= GUILDMGR->GetGuildFromMasterIdx( pmsg->dwData1 );
	CGuild*				enemyGuild		= GUILDMGR->GetGuildFromMasterIdx( pmsg->dwData2 );

	if( !	friendlyGuild	||
		!	enemyGuild		||
		!	IsGuildWar( friendlyGuild->GetIdx(), enemyGuild->GetIdx() ) )
	{
		return;
	}

	// 동맹인데 마스터 길드가 아닐 경우 해킹 또는 클라이언트 검사 실패
	{
		CGuildUnion* friendlyAlliance	= GUILDUNIONMGR->GetUnion( friendlyGuild->GetUnionIndex() );
		CGuildUnion* enemyAlliance		= GUILDUNIONMGR->GetUnion( enemyGuild->GetUnionIndex() );

		if( ( friendlyAlliance	&& friendlyAlliance->GetMasterGuild()	!= friendlyGuild	)	||
			( enemyAlliance		&& enemyAlliance->GetMasterGuild()		!= enemyGuild		)	)
		{
			return;
		}
	}

	// 요청 측에 대기하라고 알린다
	{
		CObject* friendlyPlayer	= g_pUserTable->FindUser( pmsg->dwData1 );

		if( friendlyPlayer )
		{
			MSG_BYTE message;
			message.Category	= MP_GUILD_WAR;
			message.Protocol	= MP_GUILD_WAR_WAIT;
			message.bData		= MP_GUILD_WAR_SUGGESTEND;

			friendlyPlayer->SendMsg( &message, sizeof( message ) );
		}
	}
	
	// 제안 받은 측에 메시지 보내자
	{
		CObject* enemyPlayer	= g_pUserTable->FindUser( pmsg->dwData2 );

		if( enemyPlayer )
		{
			MSG_DWORD message;
			message.Category	= MP_GUILD_WAR;
			message.Protocol	= MP_GUILD_WAR_SUGGESTEND;
			message.dwData		= friendlyGuild->GetIdx();

			enemyPlayer->SendMsg( &message, sizeof( message ) );
		}
	}
}
void CGuildWarManager::Surrender( void* pMsg )
{
	const MSG_DWORD* pmsg = (MSG_DWORD*)pMsg;

	CGuild* winnerGuild = GUILDMGR->GetGuild( pmsg->dwData );
	CGuild* loserGuild	= GUILDMGR->GetGuildFromMasterIdx( pmsg->dwObjectID );

	if( !	winnerGuild	||
		!	loserGuild	||
        !	IsGuildWar( winnerGuild->GetIdx(), loserGuild->GetIdx() ) )
	{
		return;
	}

	// 동맹인데 마스터 길드가 아닐 경우 해킹 또는 클라이언트 검사 실패
	{
		CGuildUnion* winnerAlliance	= GUILDUNIONMGR->GetUnion( winnerGuild->GetUnionIndex() );
		CGuildUnion* loseAlliance	= GUILDUNIONMGR->GetUnion( loserGuild->GetUnionIndex() );

		if( ( winnerAlliance	&& winnerAlliance->GetMasterGuild()	!= winnerGuild	)	||
			( loseAlliance		&& loseAlliance->GetMasterGuild()	!= loserGuild	)	)
		{
			return;
		}
	}

	// 선포금 지급
	{
		const CGuildManager::ScoreSetting& setting = GUILDMGR->GetScoreSetting();
		
		const DWORD money = DWORD( setting.mWinMoneyRate * 2.0f * GetWarMoney( winnerGuild->GetIdx(), loserGuild->GetIdx() ) );

		if( money )
		{
			CPlayer* player = ( CPlayer* )g_pUserTable->FindUser( winnerGuild->GetMasterIdx() );

			if( player )
			{
				SendMoneyMsg( player, 0, money, MP_GUILD_WAR_ADDMONEY );
			}
			else
			{
				SendToAgentAddMoneyMsg( winnerGuild->GetMasterIdx(), money );
			}
		}
	}

	// 항복할때 다른 길드의 포인트를 일괄적으로 조정해주어야 한다. 일단 정확한 값을 얻기 위해 
	// DB 쿼리를 요구한 후 결과가 오면 처리해야한다. 처리 후 늦게 업데이트되므로 먼저 보내자
	GuildSelectForRewardByWar( winnerGuild->GetIdx(), winnerGuild->GetUnionIndex(), loserGuild->GetIdx(), loserGuild->GetUnionIndex() );
}
void CGuildWarManager::AddEnemyToFriendly( Alliance& friendlyMap, Alliance& enemyMap )
{
	MSG_GUILD_LIST	messageToClient;
	messageToClient.Category	= MP_GUILD_WAR;
	messageToClient.Protocol	= MP_GUILD_WAR_START;
	messageToClient.mSize		= 0;

	// 길드 1의 적(길드2) 전체 정보를 넣는다
	for( Alliance::iterator it = enemyMap.begin(); enemyMap.end() != it; ++it )
	{
		CGuild*			enemy = it->first;
		const MONEYTYPE	money = it->second;

		if( ! enemy )
		{
			ASSERT( 0 );
			continue;
		}

		MSG_GUILD_LIST::Data&	dest	= messageToClient.mData[ messageToClient.mSize++ ];
		const GUILDINFO&		source	= enemy->GetInfo();
		
		// 제대로 복사되나 꼭 확인하자. 좀 위험한 코드
		memcpy( &dest, &source, sizeof( source ) );

		dest.MarkName = money;

		CGuildUnion* allianace = GUILDUNIONMGR->GetUnion( source.UnionIdx );

		if( allianace )
		{
			SafeStrCpy( dest.mUnionName, allianace->GetName(), sizeof( dest.mUnionName ) );
		}
		else
		{
			dest.mUnionName[ 0 ] = 0;
		}
	}

	MSG_DWORD3 messageToAgent;
	messageToAgent.Category	= MP_GUILD_WAR;
	messageToAgent.Protocol	= MP_GUILD_WAR_START_NOTIFY_TOMAP;

	// 길드 2의 적, 즉 길드 1의 편 전부에게 보낸다.
	for( Alliance::iterator it = friendlyMap.begin(); friendlyMap.end() != it; ++it )
	{
		CGuild*			friendly		= it->first;
		const MONEYTYPE	friendlyMoney	= it->second;
		
		if( ! friendly )
		{
			ASSERT( 0 );
			continue;
		}
		
		friendly->SendMsgToAll( &messageToClient, messageToClient.GetSize() );

		// 아군 길드 각각이 상대 길드들을 적으로 등록하게 한다.
		for( Alliance::iterator inner = enemyMap.begin(); enemyMap.end() != inner; ++inner )
		{
			CGuild*			enemy		= inner->first;
			const MONEYTYPE	enemyMoney	= inner->second;

			if( ! enemy )
			{
				ASSERT( 0 );
				continue;
			}

			// 두 길드 모두 선포금을 지니고 있을때만 돈을 업데이트해야한다. 그렇지 않은 길드는 선포금을 건 당사자가 아니다.
			const MONEYTYPE money = ( friendlyMoney && enemyMoney ? friendlyMoney : 0 ) ;

			InsertGuildWar( friendly->GetIdx(), enemy->GetIdx(), money );
			RegistGuildWar( friendly->GetIdx(), enemy->GetIdx(), money );

			// 다른 맵에도 등록하게 한다.
			{
				messageToAgent.dwData1		= friendly->GetIdx();
				messageToAgent.dwData2		= enemy->GetIdx();
				messageToAgent.dwData3		= money;

				g_Network.Send2AgentServer( (char*)&messageToAgent, sizeof( messageToAgent ) );	
			}
		}
	}
}
void CGuildWarManager::SuggestEndAccept( void* pMsg )
{
	// 편의상 제안한 쪽은 아군, 받아들이는 쪽은 적군이라 하자

	MSG_DWORD*	pmsg				= ( MSG_DWORD* )pMsg;
	CPlayer*	friendlyGuildMaster	= ( CPlayer* )	g_pUserTable->FindUser( pmsg->dwObjectID );

	if( !	friendlyGuildMaster ||
			friendlyGuildMaster->GetGuildMemberRank() != GUILD_MASTER )
	{
		return;	
	}

	const DWORD friendlyGuildIndex	= friendlyGuildMaster->GetGuildIdx();
	const DWORD enemyGuildIndex		= pmsg->dwData;
	CGuild*		friendlyGuild		= GUILDMGR->GetGuild( friendlyGuildIndex );
	CGuild*		enemyGuild			= GUILDMGR->GetGuild( enemyGuildIndex );

	if( !	friendlyGuild	||
		!	enemyGuild		||
		!	IsGuildWar( friendlyGuildIndex, enemyGuildIndex ) )
	{
		return;
	}

	// 동맹인데 마스터 길드가 아닐 경우 해킹 또는 클라이언트 검사 실패
	{
		CGuildUnion* friendlyAlliance	= GUILDUNIONMGR->GetUnion( friendlyGuild->GetUnionIndex() );
		CGuildUnion* enemyAlliance		= GUILDUNIONMGR->GetUnion( enemyGuild->GetUnionIndex() );

		if( ( friendlyAlliance	&& friendlyAlliance->GetMasterGuild()	!= friendlyGuild	)	||
			( enemyAlliance		&& enemyAlliance->GetMasterGuild()		!= enemyGuild		)	)
		{
			return;
		}
	}

	// 편의상 종전을 요청한 측을 아군, 요청받은 측을 적군으로 하자
	Alliance friendlyAlliance;
	Alliance enemyAlliance;

	// 연합인 경우 해당 길드를 모두 자료구조에 담는다. 
	{
		// 아군
		{
			CGuildUnion* alliance = GUILDUNIONMGR->GetUnion( friendlyGuild->GetUnionIndex() );

			if( alliance )
			{
				// 연합이 있는데도 마스터 길드가 아닌 경우 오류
				if( alliance->GetMasterGuild() != friendlyGuild )
				{
					return;
				}

				AddGuildToGroup( alliance, friendlyAlliance );
			}

			friendlyAlliance[ friendlyGuild ] = GetWarMoney( friendlyGuildIndex, enemyGuildIndex );
		}

		// 적군
		{
			CGuildUnion* alliance = GUILDUNIONMGR->GetUnion( enemyGuild->GetUnionIndex() );

			if( alliance )
			{
				// 연합이 있는데도 마스터 길드가 아닌 경우 오류
				if( alliance->GetMasterGuild() != enemyGuild )
				{
					return;
				}

				AddGuildToGroup( alliance, enemyAlliance );
			}

			enemyAlliance[ enemyGuild ] = GetWarMoney( friendlyGuildIndex, enemyGuildIndex );
		}
	}
	
	// 선포금이 있다면 반환해주자
	{
		const DWORD money = GetWarMoney( friendlyGuildIndex, enemyGuildIndex );

		if( money )
		{
			SendMoneyMsg( friendlyGuildMaster, NULL, money, MP_GUILD_WAR_ADDMONEY );

			CPlayer* enemyGuildMaster = ( CPlayer* )g_pUserTable->FindUser( enemyGuild->GetMasterIdx() );

			if( enemyGuildMaster )
			{
				SendMoneyMsg( enemyGuildMaster, NULL, money, MP_GUILD_WAR_ADDMONEY );
			}
			else
			{
				SendToAgentAddMoneyMsg( enemyGuild->GetMasterIdx(), money );
			}
		}
	}
	
	// 자료구조를 순환하며, 각각의 전쟁을 종료시킨다.
	for( Alliance::const_iterator it = friendlyAlliance.begin(); friendlyAlliance.end() != it; ++it )
	{
		// 전쟁 종료
		CGuild* friendly = it->first;

		if( ! friendly )
		{
			ASSERT( 0 );
			continue;
		}

		const DWORD friendlyGuildIndex = friendly->GetIdx();

		for( Alliance::const_iterator inner = enemyAlliance.begin(); enemyAlliance.end() != inner; ++inner )
		{
			CGuild* enemy = inner->first;

			if( ! enemy )
			{
				ASSERT( 0 );
				continue;
			}

			const DWORD enemyGuildIndex = enemy->GetIdx();

			// 길드전 중지를 해당 맵에 알린다
			{
				MSG_DWORD2 message;
				message.Category	= MP_GUILD_WAR;
				message.Protocol	= MP_GUILD_WAR_END;
				message.dwData1		= 2;		// 2 = draw

				message.dwData2		= enemyGuildIndex;
				friendly->SendMsgToAll( &message, sizeof( message ) );

				message.dwData2		= friendlyGuildIndex;
				enemy->SendMsgToAll( &message, sizeof( message ) );
			}

			// 에이전트를 통해 다른 맵에게도 보낸다
			{
				MSG_DWORD2 message;
				message.Category	= MP_GUILD_WAR;
				message.Protocol	= MP_GUILD_WAR_SUGGESTEND_ACCEPT_NOTIFY_TOMAP;
				message.dwData1		= friendlyGuildIndex;
				message.dwData2		= enemyGuildIndex;

				g_Network.Send2AgentServer( (char*)&message, sizeof( message ) );
			}

			DeleteGuildWar( friendlyGuildIndex, enemyGuildIndex );
			UnregistGuildWar( friendlyGuildIndex, enemyGuildIndex );

			UpdateGuildWarRecord( TRUE, 2, friendlyGuildIndex );
			UpdateGuildWarRecord( TRUE, 2, enemyGuildIndex );
		}
	}

	//SendToAllUser( 1, friendlyGuild->GetGuildName(), enemyGuild->GetGuildName() );
}