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; } }
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; }
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)); } }
// 给该玩家发送某好友下线的信息 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 }
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); } } }
// // 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; }
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; }
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); }
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; }
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; }
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; }
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; }
/* 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; } }