Beispiel #1
0
DWORD CHARACTER::GetAID() const
{
	char szQuery[1024+1];
	DWORD dwAID = 0;

	snprintf(szQuery, sizeof(szQuery), "SELECT id FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", 
			get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());

	SQLMsg* pMsg = DBManager::instance().DirectQuery(szQuery);

	if (pMsg != NULL)
	{
		if (pMsg->Get()->uiNumRows == 0)
		{
			M2_DELETE(pMsg);
			return 0;
		}

		MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);

		str_to_number(dwAID, row[0]);

		M2_DELETE(pMsg);

		return dwAID;
	}
	else
	{
		return 0;
	}
}
Beispiel #2
0
RenderableObject* Unit::GetClosestEnemy()
{
    std::vector<RenderableObject*> objectInVision = GetPercept();
    std::vector<RenderableObject*> enemyInVision;

    for(std::vector<RenderableObject*>::iterator it = objectInVision.begin(); it != objectInVision.end(); ++it) {
            RenderableObject* currentObject = *it;
            if (currentObject->GetPlayerID() != GetPlayerID() && !currentObject->IsDead()){
                enemyInVision.push_back(currentObject);
            }
    }

    if(!enemyInVision.empty()){

        RenderableObject* closesestUnit = enemyInVision[0];
        for(std::vector<RenderableObject*>::iterator it = enemyInVision.begin(); it != enemyInVision.end(); ++it) {
            RenderableObject* currentObject = *it;
            if (pow(currentObject->getX()- x,2) + pow(currentObject->getY()- y,2) <= pow(closesestUnit->getX()- x,2) + pow(closesestUnit->getY()- y,2)){
                closesestUnit = currentObject;
            }
        }

        return closesestUnit;
    }
    return NULL;
}
Beispiel #3
0
void CHARACTER::SaveAffect()
{
	TPacketGDAddAffect p;

	itertype(m_list_pkAffect) it = m_list_pkAffect.begin();

	while (it != m_list_pkAffect.end())
	{
		CAffect * pkAff = *it++;

		if (IS_NO_SAVE_AFFECT(pkAff->dwType))
			continue;

		sys_log(1, "AFFECT_SAVE: %u %u %d %d", pkAff->dwType, pkAff->bApplyOn, pkAff->lApplyValue, pkAff->lDuration);

		p.dwPID			= GetPlayerID();
		p.elem.dwType		= pkAff->dwType;
		p.elem.bApplyOn		= pkAff->bApplyOn;
		p.elem.lApplyValue	= pkAff->lApplyValue;
		p.elem.dwFlag		= pkAff->dwFlag;
		p.elem.lDuration	= pkAff->lDuration;
		p.elem.lSPCost		= pkAff->lSPCost;
		db_clientdesc->DBPacket(HEADER_GD_ADD_AFFECT, 0, &p, sizeof(p));
	}
}
Beispiel #4
0
// 给该玩家发送某好友下线的信息
VOID USER::SendRelationOfflineMsg(USER* pUser)
{
__ENTER_FUNCTION

    Assert( pUser );

    if( UserStatus() != US_NORMAL )
    {
        return;
    }

    ServerPlayer* pServerPlayer = g_pServerManager->GetServerPlayer( GetServerID() );
    if( pServerPlayer == NULL )
    {
        Assert( pServerPlayer );
        return;
    }

    WGRelation Msg;

    WG_RELATION* pRelation = Msg.GetRelation();

    pRelation->SetPlayerID( GetPlayerID() );
    pRelation->m_Type = RET_RELATIONOFFLINE;
    pRelation->m_RelationGUID.SetTargetGUID( pUser->GetGUID() );

    pServerPlayer->SendPacket( &Msg );

__LEAVE_FUNCTION
}
Beispiel #5
0
void Unit::SendMessageAllAlly(Message message)
{
    for(std::vector<RenderableObject*>::iterator it = objects.begin(); it != objects.end(); ++it) {
            RenderableObject* currentObject = *it;
            if (currentObject->GetPlayerID() == GetPlayerID() && !currentObject->IsDead()){
                currentObject->ReceiveMessage(message);
            }
    }
}
Beispiel #6
0
//
// Prepare to send.
// Update p2p transport groups and rcvrs list in some msgs
// Returns channel.
//
int plNetClientMgr::IPrepMsg(plNetMessage* msg)
{
    // pick channel, prepare msg
    int channel=kNetChanDefault;
    plNetMsgVoice* v=plNetMsgVoice::ConvertNoRef(msg);
    if (v)
    {       // VOICE MSG
        channel=kNetChanVoice;
        
        // compute new transport group (from talkList) if necessary
        GetTalkList()->UpdateTransportGroup(this);  
        
        // update receivers list in voice msg based on talk list
        v->Receivers()->Clear();
        int i;
        for(i=0;i<GetTalkList()->GetNumMembers(); i++)
        {
            v->Receivers()->AddReceiverPlayerID(GetTalkList()->GetMember(i)->GetPlayerID());
        }

        if (msg->IsBitSet(plNetMessage::kEchoBackToSender))
            v->Receivers()->AddReceiverPlayerID(GetPlayerID());
    }
    else if (plNetMsgListenListUpdate::ConvertNoRef(msg))
    {   // LISTEN LIST UPDATE MSG
        channel=kNetChanListenListUpdate;

        // update transport group from rcvrs list, add p2p mbrs to trasnport group
        fTransport.ClearChannelGrp(kNetChanListenListUpdate);
        if (IsPeerToPeer())
        {
            plNetMsgReceiversListHelper* rl = plNetMsgReceiversListHelper::ConvertNoRef(msg);
            hsAssert(rl, "error converting msg to rcvrs list?");
            int i;
            for(i=0;i<rl->GetNumReceivers();i++)
            {
                int idx=fTransport.FindMember(rl->GetReceiverPlayerID(i));
                hsAssert(idx!=-1, "error finding transport mbr");
                plNetTransportMember* tm = fTransport.GetMember(idx);
                if (tm->IsPeerToPeer())
                    fTransport.SubscribeToChannelGrp(tm, kNetChanListenListUpdate);
            }
        }
    }
    else if( plNetMsgGameMessageDirected::ConvertNoRef( msg ) )
    {
        channel = kNetChanDirectedMsg;
    }
    return channel;
}
Beispiel #7
0
int IsPlayerAdded( HWND hDlg, int playerID )
{
	HWND hWndLB1 = GetDlgItem( hDlg, IDC_LIST1 );
	int cnt = ListBox_GetCount( hWndLB1 );
	int i;
	for( i=0; i<cnt; i++ )
	{
		TCHAR buffer[1024];
		ListBox_GetText( hWndLB1, i, buffer );
		int added_playerID = GetPlayerID( buffer );
		if( added_playerID == playerID ) return 1;
	}
	return 0;
}
Beispiel #8
0
void CHARACTER::ClearAffect(bool bSave)
{
	TAffectFlag afOld = m_afAffectFlag;
	WORD	wMovSpd = GetPoint(POINT_MOV_SPEED);
	WORD	wAttSpd = GetPoint(POINT_ATT_SPEED);

	itertype(m_list_pkAffect) it = m_list_pkAffect.begin();

	while (it != m_list_pkAffect.end())
	{
		CAffect * pkAff = *it;

		if (bSave)
		{
			if ( IS_NO_CLEAR_ON_DEATH_AFFECT(pkAff->dwType) || IS_NO_SAVE_AFFECT(pkAff->dwType) )
			{
				++it;
				continue;
			}

			if (IsPC())
			{
				SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
			}
		}

		ComputeAffect(pkAff, false);

		it = m_list_pkAffect.erase(it);
		CAffect::Release(pkAff);
	}

	if (afOld != m_afAffectFlag ||
			wMovSpd != GetPoint(POINT_MOV_SPEED) ||
			wAttSpd != GetPoint(POINT_ATT_SPEED))
		UpdatePacket();

	CheckMaximumPoints();

	if (m_list_pkAffect.empty())
		event_cancel(&m_pkAffectEvent);
}
Beispiel #9
0
bool CHARACTER::RemoveAffect(CAffect * pkAff)
{
	if (!pkAff)
		return false;

	// AFFECT_BUF_FIX
	m_list_pkAffect.remove(pkAff);
	// END_OF_AFFECT_BUF_FIX

	ComputeAffect(pkAff, false);

	// 백기 버그 수정.
	// 백기 버그는 버프 스킬 시전->둔갑->백기 사용(AFFECT_REVIVE_INVISIBLE) 후 바로 공격 할 경우에 발생한다.
	// 원인은 둔갑을 시전하는 시점에, 버프 스킬 효과를 무시하고 둔갑 효과만 적용되게 되어있는데,
	// 백기 사용 후 바로 공격하면 RemoveAffect가 불리게 되고, ComputePoints하면서 둔갑 효과 + 버프 스킬 효과가 된다.
	// ComputePoints에서 둔갑 상태면 버프 스킬 효과 안 먹히도록 하면 되긴 하는데,
	// ComputePoints는 광범위하게 사용되고 있어서 큰 변화를 주는 것이 꺼려진다.(어떤 side effect가 발생할지 알기 힘들다.)
	// 따라서 AFFECT_REVIVE_INVISIBLE가 RemoveAffect로 삭제되는 경우만 수정한다.
	// 시간이 다 되어 백기 효과가 풀리는 경우는 버그가 발생하지 않으므로 그와 똑같이 함.
	//		(ProcessAffect를 보면 시간이 다 되어서 Affect가 삭제되는 경우, ComputePoints를 부르지 않는다.)
	if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType)
	{
		ComputePoints();
	}
	CheckMaximumPoints();

	if (test_server)
		sys_log(0, "AFFECT_REMOVE: %s (flag %u apply: %u)", GetName(), pkAff->dwFlag, pkAff->bApplyOn);

	if (IsPC())
	{
		SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
	}

	CAffect::Release(pkAff);
	return true;
}
Beispiel #10
0
bool CHARACTER::AddAffect(DWORD dwType, BYTE bApplyOn, long lApplyValue, DWORD dwFlag, long lDuration, long lSPCost, bool bOverride, bool IsCube )
{
	// CHAT_BLOCK
	if (dwType == AFFECT_BLOCK_CHAT && lDuration > 1)
	{
		ChatPacket(CHAT_TYPE_INFO, LC_TEXT("운영자 제제로 채팅이 금지 되었습니다."));
	}
	// END_OF_CHAT_BLOCK

	if (lDuration == 0)
	{
		sys_err("Character::AddAffect lDuration == 0 type %d", lDuration, dwType);
		lDuration = 1;
	}

	CAffect * pkAff = NULL;

	if (IsCube)
		pkAff = FindAffect(dwType,bApplyOn);
	else
		pkAff = FindAffect(dwType);

	if (dwFlag == AFF_STUN)
	{
		if (m_posDest.x != GetX() || m_posDest.y != GetY())
		{
			m_posDest.x = m_posStart.x = GetX();
			m_posDest.y = m_posStart.y = GetY();
			battle_end(this);

			SyncPacket();
		}
	}

	// 이미 있는 효과를 덮어 쓰는 처리
	if (pkAff && bOverride)
	{
		ComputeAffect(pkAff, false); // 일단 효과를 삭제하고

		if (GetDesc())
			SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
	}
	else
	{
		//
		// 새 에펙를 추가
		//
		// NOTE: 따라서 같은 type 으로도 여러 에펙트를 붙을 수 있다.
		// 
		pkAff = CAffect::Acquire();
		m_list_pkAffect.push_back(pkAff);

	}

	sys_log(1, "AddAffect %s type %d apply %d %d flag %u duration %d", GetName(), dwType, bApplyOn, lApplyValue, dwFlag, lDuration);
	sys_log(0, "AddAffect %s type %d apply %d %d flag %u duration %d", GetName(), dwType, bApplyOn, lApplyValue, dwFlag, lDuration);

	pkAff->dwType	= dwType;
	pkAff->bApplyOn	= bApplyOn;
	pkAff->lApplyValue	= lApplyValue;
	pkAff->dwFlag	= dwFlag;
	pkAff->lDuration	= lDuration;
	pkAff->lSPCost	= lSPCost;

	WORD wMovSpd = GetPoint(POINT_MOV_SPEED);
	WORD wAttSpd = GetPoint(POINT_ATT_SPEED);

	ComputeAffect(pkAff, true);

	if (pkAff->dwFlag || wMovSpd != GetPoint(POINT_MOV_SPEED) || wAttSpd != GetPoint(POINT_ATT_SPEED))
		UpdatePacket();

	StartAffectEvent();

	if (IsPC())
	{
		SendAffectAddPacket(GetDesc(), pkAff);

		if (IS_NO_SAVE_AFFECT(pkAff->dwType))
			return true;

		TPacketGDAddAffect p;
		p.dwPID			= GetPlayerID();
		p.elem.dwType		= pkAff->dwType;
		p.elem.bApplyOn		= pkAff->bApplyOn;
		p.elem.lApplyValue	= pkAff->lApplyValue;
		p.elem.dwFlag		= pkAff->dwFlag;
		p.elem.lDuration	= pkAff->lDuration;
		p.elem.lSPCost		= pkAff->lSPCost;
		db_clientdesc->DBPacket(HEADER_GD_ADD_AFFECT, 0, &p, sizeof(p));
	}

	return true;
}
Beispiel #11
0
int CHARACTER::ProcessAffect()
{
	bool	bDiff	= false;
	CAffect	*pkAff	= NULL;

	//
	// 프리미엄 처리
	//
	for (int i = 0; i <= PREMIUM_MAX_NUM; ++i)
	{
		int aff_idx = i + AFFECT_PREMIUM_START;

		pkAff = FindAffect(aff_idx);

		if (!pkAff)
			continue;

		int remain = GetPremiumRemainSeconds(i);

		if (remain < 0)
		{
			RemoveAffect(aff_idx);
			bDiff = true;
		}
		else
			pkAff->lDuration = remain + 1;
	}

	////////// HAIR_AFFECT
	pkAff = FindAffect(AFFECT_HAIR);
	if (pkAff)
	{
		// IF HAIR_LIMIT_TIME() < CURRENT_TIME()
		if ( this->GetQuestFlag("hair.limit_time") < get_global_time())
		{
			// SET HAIR NORMAL
			this->SetPart(PART_HAIR, 0);
			// REMOVE HAIR AFFECT
			RemoveAffect(AFFECT_HAIR);
		}
		else
		{
			// INCREASE AFFECT DURATION
			++(pkAff->lDuration);
		}
	}
	////////// HAIR_AFFECT
	//

	CHorseNameManager::instance().Validate(this);

	TAffectFlag afOld = m_afAffectFlag;
	long lMovSpd = GetPoint(POINT_MOV_SPEED);
	long lAttSpd = GetPoint(POINT_ATT_SPEED);

	itertype(m_list_pkAffect) it;

	it = m_list_pkAffect.begin();

	while (it != m_list_pkAffect.end())
	{
		pkAff = *it;

		bool bEnd = false;

		if (pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END)
		{
			if (!GetGuild() || !GetGuild()->UnderAnyWar())
				bEnd = true;
		}

		if (pkAff->lSPCost > 0)
		{
			if (GetSP() < pkAff->lSPCost)
				bEnd = true;
			else
				PointChange(POINT_SP, -pkAff->lSPCost);
		}

		// AFFECT_DURATION_BUG_FIX
		// 무한 효과 아이템도 시간을 줄인다.
		// 시간을 매우 크게 잡기 때문에 상관 없을 것이라 생각됨.
		if ( --pkAff->lDuration <= 0 )
		{
			bEnd = true;
		}
		// END_AFFECT_DURATION_BUG_FIX

		if (bEnd)
		{
			it = m_list_pkAffect.erase(it);
			ComputeAffect(pkAff, false);
			bDiff = true;
			if (IsPC())
			{
				SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
			}

			CAffect::Release(pkAff);

			continue;
		}

		++it;
	}

	if (bDiff)
	{
		if (afOld != m_afAffectFlag ||
				lMovSpd != GetPoint(POINT_MOV_SPEED) ||
				lAttSpd != GetPoint(POINT_ATT_SPEED))
		{
			UpdatePacket();
		}

		CheckMaximumPoints();
	}

	if (m_list_pkAffect.empty())
		return true;

	return false;
}
Beispiel #12
0
INT_PTR CALLBACK DlgProc_Options( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	switch( uMsg )
	{
	case WM_INITDIALOG:
		{
			updateLB1( hDlg );
			updateLB2( hDlg );
			initCBAction( hDlg );
			updateCBAction( hDlg );
			lParam = 0;
		} break;
	case WM_COMMAND:
		{
			int ctrl_id = LOWORD(wParam);
			HWND hWndLB1 = GetDlgItem( hDlg, IDC_LIST1 );
			HWND hWndLB2 = GetDlgItem( hDlg, IDC_LIST2 );
			switch( ctrl_id )
			{
			case IDC_ADD:
				{
					int nSel = ListBox_GetCurSel( hWndLB2 );
					if( nSel >= 0 )
					{
						TCHAR buffer[1024];
						ListBox_GetText( hWndLB2, nSel, buffer );
						ListBox_AddString( hWndLB1, buffer );
						ListBox_DeleteString( hWndLB2, nSel );
					}
				} break;
			case IDC_DEL:
				{
					int nSel = ListBox_GetCurSel( hWndLB1 );
					if( nSel >= 0 )
					{
						TCHAR buffer[1024];
						ListBox_GetText( hWndLB1, nSel, buffer );
						ListBox_AddString( hWndLB2, buffer );
						ListBox_DeleteString( hWndLB1, nSel );
					}
				} break;
			case IDC_MOVEUP:
				{
					int nSel = ListBox_GetCurSel( hWndLB1 );
					if( nSel >= 0 )
					{
						if( nSel >= 1 )
						{
							TCHAR buffer[1024];
							ListBox_GetText( hWndLB1, nSel, buffer );
							ListBox_DeleteString( hWndLB1, nSel );
							ListBox_InsertString( hWndLB1, nSel-1, buffer );
							ListBox_SetCurSel( hWndLB1, nSel-1 );
						}
					}
				} break;
			case IDC_MOVEDOWN:
				{
					int nSel = ListBox_GetCurSel( hWndLB1 );
					if( nSel >= 0 )
					{
						if( nSel < PLAYERS_COUNT-1 )
						{
							TCHAR buffer[1024];
							ListBox_GetText( hWndLB1, nSel, buffer );
							ListBox_DeleteString( hWndLB1, nSel );
							ListBox_InsertString( hWndLB1, nSel+1, buffer );
							ListBox_SetCurSel( hWndLB1, nSel+1 );
						}
					}
				} break;
			case IDC_CBACTION:
				{
					updateCBAction( hDlg );
				} break;
			case IDOK:
				{
					int i;
					int cnt = ListBox_GetCount( hWndLB1 );
					// zero orders in config
					if( g_cfg )
						for( i=0; i<PLAYERS_COUNT; i++ )
							g_cfg->order[i] = 0;
					// save players order
					for( i=0; i<cnt; i++ )
					{
						TCHAR buffer[1024];
						ListBox_GetText( hWndLB1, i, buffer );
						if( g_cfg )
							g_cfg->order[i] = GetPlayerID( buffer );
					}
					// save action & text
					int cur_sel = ComboBox_GetCurSel( GetDlgItem( hDlg, IDC_CBACTION ) );
					if( g_cfg ) g_cfg->action_player_not_found = cur_sel;
					if( g_cfg )
					{
						if( g_cfg->action_player_not_found == ACT_SHOW_USER_TEXT )
							GetDlgItemText( hDlg, IDC_ETEXT, g_cfg->text_PlayerNotFound, sizeof(g_cfg->text_PlayerNotFound)/sizeof(g_cfg->text_PlayerNotFound[0]) );
					}
					EndDialog( hDlg, IDOK );
				} break;
			case IDCANCEL:
				EndDialog( hDlg, IDCANCEL );
				break;
			}
		} break;
	default: return FALSE; break;
	}
	return TRUE;
}
Beispiel #13
0
/*
   Return Value
		0 : 알 수 없는 에러 or 쿼리 에러
		1 : 동일한 제국으로 바꾸려고함
		2 : 길드 가입한 캐릭터가 있음
		3 : 결혼한 캐릭터가 있음

		999 : 제국 이동 성공
*/
int CHARACTER::ChangeEmpire(BYTE empire)
{
	if (GetEmpire() == empire)
		return 1;

	char szQuery[1024+1];
	DWORD dwAID;
	DWORD dwPID[4];
	memset(dwPID, 0, sizeof(dwPID));

	{
		// 1. 내 계정의 모든 pid를 얻어 온다
		snprintf(szQuery, sizeof(szQuery), 
				"SELECT id, pid1, pid2, pid3, pid4 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", 
				get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());

		std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));

		if (msg->Get()->uiNumRows == 0)
		{
			return 0;
		}

		MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);

		str_to_number(dwAID, row[0]);
		str_to_number(dwPID[0], row[1]);
		str_to_number(dwPID[1], row[2]);
		str_to_number(dwPID[2], row[3]);
		str_to_number(dwPID[3], row[4]);
	}

	const int loop = 4;

	{
		// 2. 각 캐릭터의 길드 정보를 얻어온다.
		//   한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다.
		DWORD dwGuildID[4];
		CGuild * pGuild[4];
		SQLMsg * pMsg = NULL;
		
		for (int i = 0; i < loop; ++i)
		{
			snprintf(szQuery, sizeof(szQuery), "SELECT guild_id FROM guild_member%s WHERE pid=%u", get_table_postfix(), dwPID[i]);

			pMsg = DBManager::instance().DirectQuery(szQuery);

			if (pMsg != NULL)
			{
				if (pMsg->Get()->uiNumRows > 0)
				{
					MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);

					str_to_number(dwGuildID[i], row[0]);

					pGuild[i] = CGuildManager::instance().FindGuild(dwGuildID[i]);

					if (pGuild[i] != NULL)
					{
						M2_DELETE(pMsg);
						return 2;
					}
				}
				else
				{
					dwGuildID[i] = 0;
					pGuild[i] = NULL;
				}

				M2_DELETE(pMsg);
			}
		}
	}

	{
		// 3. 각 캐릭터의 결혼 정보를 얻어온다.
		//   한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다.
		for (int i = 0; i < loop; ++i)
		{
			if (marriage::CManager::instance().IsEngagedOrMarried(dwPID[i]) == true)
				return 3;
		}
	}
	
	{
		// 4. db의 제국 정보를 업데이트 한다.
		snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", 
				get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());

		std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));

		if (msg->Get()->uiAffectedRows > 0)
		{
			// 5. 제국 변경 이력을 추가한다.
			SetChangeEmpireCount();

			return 999;
		}
	}

	return 0;
}
//
// show lists of members, listenList, and talkList
//
void plNetClientMgr::IShowLists()
{
    plNetLinkingMgr * lm = plNetLinkingMgr::GetInstance();
    plDebugText     &txt = plDebugText::Instance();

    int y,x,i;
    const int yOff=10, xOff=300, startY=70, startX=10;
    char str[256];

    // My player info
    x=startX;
    y=startY;
    plSceneObject *player = plSceneObject::ConvertNoRef(GetLocalPlayer());
    hsPoint3 pos = (player ? player->GetLocalToWorld() * hsPoint3(0, 0, 0) : hsPoint3(0, 0, 0));
    sprintf(str, "%s%s PlyrName=%s PlyrID=%d AcctID=%d P2P=%d Join#=%d Peers=%d %.1f,%.1f,%.1f",
        GetFlagsBit(kSendingVoice) ? "V" : " ",
        GetFlagsBit(kSendingActions) ? "A" : " ",
        GetPlayerName().c_str(), GetPlayerID(), 0,
        IsPeerToPeer(), GetJoinOrder(), 0,
        pos.fX, pos.fY, pos.fZ);
    txt.DrawString(x,y,str,255,255,255,255);
    SetFlagsBit(kSendingVoice, 0);
    SetFlagsBit(kSendingActions, 0);

    y+=yOff;
    sprintf(str, "   Server=%s ILIAS=%d", "foo",
        IsLoadingInitialAgeState());
    txt.DrawString(x,y,str,255,255,255,255);
    
    // MEMBERS
    y+=yOff;
    int baseY=y;
    txt.DrawString(x,y,"   Members",255,255,255,255,plDebugText::kStyleBold);
    y+=yOff;
    plNetTransportMember** members=nil;
    fTransport.GetMemberListDistSorted(members);
    for(i=0;i<fTransport.GetNumMembers();i++)
    {
        plNetTransportMember* mbr=members[i];
        hsAssert(mbr, "ShowLists: nil member?");
        if (mbr->IsServer())
            continue;
        player = (mbr->GetAvatarKey() ? plSceneObject::ConvertNoRef(mbr->GetAvatarKey()->ObjectIsLoaded()) : nil);
        sprintf(str, "%s%s %s p2p=%d dist=%.1f",
            mbr->GetTransportFlags() & plNetTransportMember::kSendingVoice ? "V" : " ",
            mbr->GetTransportFlags() & plNetTransportMember::kSendingActions ? "A" : " ",
            mbr->AsString().c_str(),
            mbr->IsPeerToPeer(),
            mbr->GetDistSq() != FLT_MAX ? sqrt(mbr->GetDistSq()) :-1.f);
        txt.DrawString(x,y,str);
        y+=yOff;
        mbr->SetTransportFlags(mbr->GetTransportFlags() & 
            ~(plNetTransportMember::kSendingVoice|plNetTransportMember::kSendingActions));
    }

    delete [] members;
    
    // LISTENLIST
    x+=xOff;
    y=baseY;
    txt.DrawString(x,y,"ListenList",255,255,255,255,plDebugText::kStyleBold);
    y+=yOff;
    for(i=0;i<GetListenList()->GetNumMembers();i++)
    {
        sprintf(str, "name=%s", GetListenList()->GetMember(i)->AsString().c_str());
        txt.DrawString(x,y,str);
        y+=yOff;
    }

    // TALKLIST
    x+=xOff;
    y=baseY;
    txt.DrawString(x,y,"TalkList",255,255,255,255,plDebugText::kStyleBold);
    y+=yOff;
    for(i=0;i<GetTalkList()->GetNumMembers();i++)
    {
        sprintf(str, "name=%s", GetTalkList()->GetMember(i)->AsString().c_str());
        txt.DrawString(x,y,str);
        y+=yOff;
    }
}