#include "StdAfx.h" #include "TableFrameSink.h" #include "cmath" ////////////////////////////////////////////////////////////////////////// //静态变量 const WORD CTableFrameSink::m_wPlayerCount = GAME_PLAYER; //游戏人数 // 游戏定时器 enum tagServerTimerEnum { IDI_SEND_CARD = 1, //发牌计时器; IDT_SEND_CARD = 5000, //发牌时间; IDI_OUT_CARD = 2, //出牌计时器; IDT_OUT_CARD = 2000, //出牌时间; }; ////////////////////////////////////////////////////////////////////////// //构造函数 CTableFrameSink::CTableFrameSink() { //游戏变量 m_bNobodyCallScore = false; m_wFirstUser = INVALID_CHAIR; m_wBankerUser = INVALID_CHAIR; m_wCurrentUser = INVALID_CHAIR; m_etGameEndType = GAME_END_NULL; ZeroMemory(m_bTrustee, sizeof(m_bTrustee)); //叫分信息; ZeroMemory(m_cbScoreInfo, sizeof(m_cbScoreInfo)); //胜利信息 m_wWinCount = 0; ZeroMemory(m_wWinOrder, sizeof(m_wWinOrder)); ZeroMemory(m_cbGongxian, sizeof(m_cbGongxian)); ZeroMemory(m_lBombScore, sizeof(m_lBombScore)); //出牌信息 m_wTurnWiner = INVALID_CHAIR; ZeroMemory(&m_TurnOutCard, sizeof(m_TurnOutCard)); //扑克信息 ZeroMemory(m_cbHandCardData, sizeof(m_cbHandCardData)); ZeroMemory(m_cbHandCardCount, sizeof(m_cbHandCardCount)); for (WORD i = 0; i < GAME_PLAYER; i++) { m_wFriendChairID[i] = INVALID_CHAIR; } //组件变量 m_pITableFrame = NULL; m_pGameServiceOption = NULL; return; } //析构函数 CTableFrameSink::~CTableFrameSink() { } //接口查询 VOID * CTableFrameSink::QueryInterface(REFGUID Guid, DWORD dwQueryVer) { QUERYINTERFACE(ITableFrameSink, Guid, dwQueryVer); QUERYINTERFACE(ITableUserAction, Guid, dwQueryVer); QUERYINTERFACE_IUNKNOWNEX(ITableFrameSink, Guid, dwQueryVer); return NULL; } //初始化 bool CTableFrameSink::Initialization(IUnknownEx * pIUnknownEx) { //查询接口 ASSERT(pIUnknownEx != NULL); m_pITableFrame = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITableFrame); if (m_pITableFrame == NULL) return false; //获取参数 m_pGameServiceOption = m_pITableFrame->GetGameServiceOption(); ASSERT(m_pGameServiceOption != NULL); //开始模式 m_pITableFrame->SetStartMode(START_MODE_FULL_READY); //BYTE cbCardData[MAX_COUNT] = { // 0x4f, 0x22, 0x02, 0x31, 0x21, 0x01, 0x3d, 0x2d, 0x3c, 0x0c, // 0x3b, 0x2b, 0x0b, 0x39, 0x29, 0x19, 0x38, 0x28, 0x07, 0x16, // 0x06, 0x15, 0x05, 0x05, 0x33, 0x23, 0x03}; //GetBombScore(0, cbCardData, MAX_COUNT); return true; } //复位桌子 VOID CTableFrameSink::RepositionSink() { //游戏变量 m_bNobodyCallScore = false; m_wCurrentUser = INVALID_CHAIR; m_wBankerUser = INVALID_CHAIR; m_etGameEndType = GAME_END_NULL; ZeroMemory(m_bTrustee, sizeof(m_bTrustee)); //叫分信息; ZeroMemory(m_cbScoreInfo, sizeof(m_cbScoreInfo)); //胜利信息 m_wWinCount = 0; ZeroMemory(m_wWinOrder, sizeof(m_wWinOrder)); ZeroMemory(m_cbGongxian, sizeof(m_cbGongxian)); ZeroMemory(m_lBombScore, sizeof(m_lBombScore)); //出牌信息 m_wTurnWiner = INVALID_CHAIR; ZeroMemory(&m_TurnOutCard, sizeof(m_TurnOutCard)); //扑克信息 ZeroMemory(m_cbHandCardData, sizeof(m_cbHandCardData)); ZeroMemory(m_cbHandCardCount, sizeof(m_cbHandCardCount)); for (WORD i = 0; i < GAME_PLAYER; i++) { m_wFriendChairID[i] = INVALID_CHAIR; } return; } //游戏开始 bool CTableFrameSink::OnEventGameStart() { //混乱扑克 srand((unsigned)time(NULL)); //设置状态; m_pITableFrame->SetGameStatus(GAME_SCENE_SEND); BYTE cbRandCard[FULL_COUNT] = {0}; if (IsHasGameRule(eDZRuleEnum_NO_JOKER)) { ////设置状态; //m_pITableFrame->SetGameStatus(GAME_SCENE_CALL_SCORE); m_GameLogic.RandNoJokerCardList(cbRandCard, NO_JOKER_COUNT); //用户扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { m_cbHandCardCount[i] = MAX_NO_JOKER_COUNT; CopyMemory(&m_cbHandCardData[i], &cbRandCard[i*m_cbHandCardCount[i]], sizeof(BYTE)*m_cbHandCardCount[i]); } } else { ////设置状态; //m_pITableFrame->SetGameStatus(GAME_SCENE_PLAY); m_GameLogic.RandCardList(cbRandCard, FULL_COUNT); //用户扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { m_cbHandCardCount[i] = MAX_COUNT; CopyMemory(&m_cbHandCardData[i], &cbRandCard[i*m_cbHandCardCount[i]], sizeof(BYTE)*m_cbHandCardCount[i]); } } if (m_wFirstUser == INVALID_CHAIR) m_wFirstUser = 0; m_wBankerUser = INVALID_CHAIR; m_wTurnWiner = m_wFirstUser; m_wCurrentUser = m_wFirstUser; //构造变量 CMD_S_GameStart GameStart; ZeroMemory(&GameStart, sizeof(GameStart)); //设置变量 GameStart.wCurrentUser = m_wCurrentUser; GameStart.lCellScore = m_pGameServiceOption->lCellScore; GameStart.bHasJoker = !IsHasGameRule(eDZRuleEnum_NO_JOKER); CopyMemory(GameStart.cbCardCount, m_cbHandCardCount, sizeof(BYTE)*GAME_PLAYER); //发送数据 for (WORD i = 0; i < GAME_PLAYER; i++) { //构造扑克 ASSERT(CountArray(GameStart.cbCardData) >= m_cbHandCardCount[i]); CopyMemory(GameStart.cbCardData, m_cbHandCardData[i], sizeof(BYTE)*m_cbHandCardCount[i]); GameStart.bTrustee[i] = m_bTrustee[i]; //发送数据 m_pITableFrame->SendTableData(i, SUB_S_GAME_START, &GameStart, sizeof(GameStart)); m_pITableFrame->SendLookonData(i, SUB_S_GAME_START, &GameStart, sizeof(GameStart)); } // 录像开始; starGameRecord(); // 记录开始消息; CMD_Record_GameStart recordStart; recordStart.wStartUser = m_wFirstUser; recordStart.wCurrentUser = m_wCurrentUser; addGameRecordAction(SUB_S_GAME_START, &recordStart, sizeof(CMD_Record_GameStart)); //排列扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { m_GameLogic.SortCardList(m_cbHandCardData[i], m_cbHandCardCount[i], ST_ORDER); } //// 带王不打独; //if (GameStart.bHasJoker) //{ // m_pITableFrame->SetGameTimer(IDI_SEND_CARD, IDT_SEND_CARD, 1, 0); //} // 发牌结束; m_pITableFrame->SetGameTimer(IDI_SEND_CARD, IDT_SEND_CARD, 1, 0); return true; } //游戏结束 bool CTableFrameSink::OnEventGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason) { switch (cbReason) { case GER_BAOZI: // 懒的重新定义,就用这个了; { //定义变量 CMD_S_GameEnd GameEnd; ZeroMemory(&GameEnd, sizeof(GameEnd)); GameEnd.iGameEndType = m_etGameEndType; //用户扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.wWinOrder[i] = INVALID_CHAIR; GameEnd.wFriendChairID[i] = m_wFriendChairID[i]; GameEnd.cbCardCount[i] = m_cbHandCardCount[i]; CopyMemory(GameEnd.cbCardData[i], m_cbHandCardData[i], m_cbHandCardCount[i] * sizeof(BYTE)); // 计算头子分; if (m_cbHandCardCount[i] > 0) { GetBombScore(i, m_cbHandCardData[i], m_cbHandCardCount[i]); } } //积分变量 tagScoreInfo ScoreInfoArray[GAME_PLAYER]; ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray)); for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.lGameScore[i] = 0; // 游戏得分; GameEnd.lBombScore[i] = m_lBombScore[i]; // 炸弹得分; GameEnd.lAllScore[i] = m_lBombScore[i] + GameEnd.lGameScore[i]; // 总得分; ScoreInfoArray[i].lScore = GameEnd.lAllScore[i]; if (ScoreInfoArray[i].lScore > 0) { ScoreInfoArray[i].cbType = SCORE_TYPE_WIN; } else if (ScoreInfoArray[i].lScore < 0) { ScoreInfoArray[i].cbType = SCORE_TYPE_LOSE; } else { ScoreInfoArray[i].cbType = SCORE_TYPE_DRAW; } } /********************************私人场统计****************************************/ tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord(); BYTE cbFinishCout = pPrivateRecord->cbFinishCout; //统计积分明细 for (WORD i = 0; i < GAME_PLAYER; i++) { if (cbFinishCout < 16) { m_PrivateEndInfo.lDetails[i][cbFinishCout] = GameEnd.lAllScore[i]; } } // 完成局数 m_PrivateEndInfo.cbFinishCout = cbFinishCout + 1; m_pITableFrame->addPrivatePlayCout(1); /********************************私人场统计****************************************/ //牌局结束后,每8局增加一点经验值; if (IsPrivateEnd()) { tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo(); SCORE lGrade = pPrivateFrame->dwPlayCost; for (WORD i = 0; i < GAME_PLAYER; i++) { ScoreInfoArray[i].lGrade = lGrade; } GameEnd.isPrivateEnd = true; } //发送信息 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); // 记录游戏结束消息; addGameRecordAction(SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //写入积分; DataStream kDataStream; m_kGameRecord.StreamValue(kDataStream, true); m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray), kDataStream); //结束游戏 m_pITableFrame->ConcludeGame(GAME_SCENE_FREE); return true; } case GER_DISMISS: //游戏解散 { //构造数据 CMD_S_GameEnd GameEnd; memset(&GameEnd, 0, sizeof(GameEnd)); GameEnd.iGameEndType = GAME_END_DRAW; //用户扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.wFriendChairID[i] = m_wFriendChairID[i]; GameEnd.cbCardCount[i] = m_cbHandCardCount[i]; CopyMemory(GameEnd.cbCardData[i], m_cbHandCardData[i], m_cbHandCardCount[i] * sizeof(BYTE)); // 计算头子分; if (m_cbHandCardCount[i] > 0) { GetBombScore(i, m_cbHandCardData[i], m_cbHandCardCount[i]); } } //积分变量 tagScoreInfo ScoreInfoArray[GAME_PLAYER]; ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray)); for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.lGameScore[i] = 0; // 游戏得分; GameEnd.lBombScore[i] = m_lBombScore[i]; // 炸弹得分; GameEnd.lAllScore[i] = m_lBombScore[i] + GameEnd.lGameScore[i]; // 总得分; ScoreInfoArray[i].lScore = GameEnd.lAllScore[i]; if (ScoreInfoArray[i].lScore > 0) { ScoreInfoArray[i].cbType = SCORE_TYPE_WIN; } else if (ScoreInfoArray[i].lScore < 0) { ScoreInfoArray[i].cbType = SCORE_TYPE_LOSE; } else { ScoreInfoArray[i].cbType = SCORE_TYPE_DRAW; } } /********************************私人场统计****************************************/ tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord(); BYTE cbFinishCout = pPrivateRecord->cbFinishCout; //统计积分明细 for (WORD i = 0; i < GAME_PLAYER; i++) { if (cbFinishCout < 16) { m_PrivateEndInfo.lDetails[i][cbFinishCout] = GameEnd.lAllScore[i]; } } // 完成局数 m_PrivateEndInfo.cbFinishCout = cbFinishCout + 1; m_pITableFrame->addPrivatePlayCout(1); /********************************私人场统计****************************************/ // 私人场游戏结束预判断; if (IsRecordServerType() && IsPrivateEnd()) { GameEnd.isPrivateEnd = true; } //发送信息 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); // 记录游戏结束消息; addGameRecordAction(SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //写入积分; DataStream kDataStream; m_kGameRecord.StreamValue(kDataStream, true); m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray), kDataStream); //结束游戏 m_pITableFrame->ConcludeGame(GAME_SCENE_FREE); return true; } case GER_NORMAL: { // 只打二游; if (IsHasGameRule(eDZRuleEnum_TO_TWO)) { return ToTwoGameConclude(wChairID, pIServerUserItem); } else { return NormalGameConclude(wChairID, pIServerUserItem); } } case GER_USER_LEAVE: //用户强退 case GER_NETWORK_ERROR: //网络中断 { //定义变量 CMD_S_GameEnd GameEnd; memset(&GameEnd, 0, sizeof(GameEnd)); //用户扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.wFriendChairID[i] = m_wFriendChairID[i]; GameEnd.cbCardCount[i] = m_cbHandCardCount[i]; CopyMemory(GameEnd.cbCardData[i], m_cbHandCardData[i], m_cbHandCardCount[i] * sizeof(BYTE)); } //发送信息 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //积分变量 tagScoreInfo ScoreInfoArray[GAME_PLAYER]; ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray)); //逃跑罚分 ScoreInfoArray[wChairID].lScore = GameEnd.lGameScore[wChairID]; ScoreInfoArray[wChairID].cbType = SCORE_TYPE_FLEE; // 记录游戏结束消息; addGameRecordAction(SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //写入积分; DataStream kDataStream; m_kGameRecord.StreamValue(kDataStream, true); m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray), kDataStream); //结束游戏 m_pITableFrame->ConcludeGame(GAME_SCENE_FREE); //切换庄家 m_wBankerUser = (m_wBankerUser + 1) % GAME_PLAYER; return true; } } ASSERT(FALSE); return false; } // 正常结束; bool CTableFrameSink::NormalGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem) { //定义变量 CMD_S_GameEnd GameEnd; ZeroMemory(&GameEnd, sizeof(GameEnd)); tagScoreInfo ScoreInfo[GAME_PLAYER]; ZeroMemory(&ScoreInfo, sizeof(ScoreInfo)); //胜利信息 for (WORD i = 0; i < GAME_PLAYER; i++) { if (m_cbHandCardCount[i] != 0) { m_wWinOrder[m_wWinCount++] = i; } } // 排名; CopyMemory(GameEnd.wWinOrder, m_wWinOrder, sizeof(m_wWinOrder)); //剩余扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.wFriendChairID[i] = m_wFriendChairID[i]; GameEnd.cbCardCount[i] = m_cbHandCardCount[i]; CopyMemory(GameEnd.cbCardData[i], m_cbHandCardData[i], m_cbHandCardCount[i] * sizeof(BYTE)); } // 有玩家打独; if (!m_bNobodyCallScore) { // 赢积分; SCORE lWinCellScore = 2 * m_pGameServiceOption->lCellScore; // 庄家赢; if (wChairID == m_wBankerUser) { ScoreInfo[m_wBankerUser].lScore = 3 * lWinCellScore; ScoreInfo[m_wBankerUser].cbType = SCORE_TYPE_WIN; for (WORD i = 0; i < GAME_PLAYER; i++) { if (i == m_wBankerUser) continue; ScoreInfo[i].lScore = 0 - lWinCellScore; ScoreInfo[i].cbType = SCORE_TYPE_WIN; } } else { ScoreInfo[m_wBankerUser].lScore = 0 - 3 * lWinCellScore; ScoreInfo[m_wBankerUser].cbType = SCORE_TYPE_WIN; for (WORD i = 0; i < GAME_PLAYER; i++) { if (i == m_wBankerUser) continue; ScoreInfo[i].lScore = lWinCellScore; ScoreInfo[i].cbType = SCORE_TYPE_WIN; } } //切换庄家 m_wFirstUser = m_wBankerUser; GameEnd.iGameEndType = GAME_END_DRAW; // 计算头子分; for (WORD i = 0; i < GAME_PLAYER; i++) { if (m_cbHandCardCount[i] <= 0) continue; GetBombScore(i, m_cbHandCardData[i], m_cbHandCardCount[i]); } } else { // 带王积分翻倍; BYTE cbHasJoker = IsHasGameRule(eDZRuleEnum_NO_JOKER) ? 1 : 2; //单扣判断(第一名和第三名是伙伴) //if (m_wWinOrder[0] == (m_wWinOrder[2] + 2) % GAME_PLAYER) if (m_wWinOrder[0] == m_wFriendChairID[m_wWinOrder[2]]) { GameEnd.iGameEndType = GAME_END_ONE_WIN; //游戏积分 ScoreInfo[m_wWinOrder[0]].lScore = 1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[0]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[2]].lScore = 1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[2]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[1]].lScore = -1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[1]].cbType = SCORE_TYPE_LOSE; ScoreInfo[m_wWinOrder[3]].lScore = -1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[3]].cbType = SCORE_TYPE_LOSE; //切换庄家 m_wFirstUser = m_wWinOrder[0]; } //双扣判断(第一名和第二名是伙伴) //else if (m_wWinOrder[0] == (m_wWinOrder[1] + 2) % GAME_PLAYER) else if (m_wWinOrder[0] == m_wFriendChairID[m_wWinOrder[1]]) { GameEnd.iGameEndType = GAME_END_TWO_WIN; //游戏积分 ScoreInfo[m_wWinOrder[0]].lScore = 2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[0]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[1]].lScore = 2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[1]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[2]].lScore = -2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[2]].cbType = SCORE_TYPE_LOSE; ScoreInfo[m_wWinOrder[3]].lScore = -2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[3]].cbType = SCORE_TYPE_LOSE; ////切换庄家 //m_wFirstUser = m_wWinOrder[0]; } else //平扣判断 { GameEnd.iGameEndType = GAME_END_DRAW; //游戏积分 ScoreInfo[m_wWinOrder[0]].lScore = 0; ScoreInfo[m_wWinOrder[0]].cbType = SCORE_TYPE_DRAW; ScoreInfo[m_wWinOrder[2]].lScore = 0; ScoreInfo[m_wWinOrder[2]].cbType = SCORE_TYPE_DRAW; ScoreInfo[m_wWinOrder[1]].lScore = 0; ScoreInfo[m_wWinOrder[1]].cbType = SCORE_TYPE_DRAW; ScoreInfo[m_wWinOrder[3]].lScore = 0; ScoreInfo[m_wWinOrder[3]].cbType = SCORE_TYPE_DRAW; ////切换庄家 //m_wFirstUser = (m_wFirstUser + 1) % 4; } //切换庄家 m_wFirstUser = m_wWinOrder[0]; } //游戏积分 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.lGameScore[i] = ScoreInfo[i].lScore; // 游戏得分; GameEnd.lBombScore[i] = m_lBombScore[i]; // 炸弹得分; GameEnd.lAllScore[i] = GameEnd.lGameScore[i] + m_lBombScore[i]; // 总得分; ScoreInfo[i].lScore = GameEnd.lAllScore[i]; } /********************************私人场统计****************************************/ tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord(); BYTE cbFinishCout = pPrivateRecord->cbFinishCout; //统计积分明细 for (WORD i = 0; i < GAME_PLAYER; i++) { if (cbFinishCout < 16) { m_PrivateEndInfo.lDetails[i][cbFinishCout] = GameEnd.lAllScore[i]; } } // 完成局数 m_PrivateEndInfo.cbFinishCout = cbFinishCout + 1; m_pITableFrame->addPrivatePlayCout(1); /********************************私人场统计****************************************/ //牌局结束后,每8局增加一点经验值; if (IsPrivateEnd()) { tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo(); SCORE lGrade = pPrivateFrame->dwPlayCost; for (WORD i = 0; i < GAME_PLAYER; i++) { ScoreInfo[i].lGrade = lGrade; } GameEnd.isPrivateEnd = true; } //发送信息 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); // 记录游戏结束消息; addGameRecordAction(SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //写入积分; DataStream kDataStream; m_kGameRecord.StreamValue(kDataStream, true); m_pITableFrame->WriteTableScore(ScoreInfo, CountArray(ScoreInfo), kDataStream); //结束游戏 m_pITableFrame->ConcludeGame(GAME_SCENE_FREE); return true; } // 只打二游; bool CTableFrameSink::ToTwoGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem) { //定义变量 CMD_S_GameEnd GameEnd; ZeroMemory(&GameEnd, sizeof(GameEnd)); tagScoreInfo ScoreInfo[GAME_PLAYER]; ZeroMemory(&ScoreInfo, sizeof(ScoreInfo)); //// 排名信息; //for (WORD i = 0; i < GAME_PLAYER; i++) //{ // if (m_cbHandCardCount[i] != 0) // { // m_wWinOrder[m_wWinCount++] = i; // } //} //CopyMemory(GameEnd.wWinOrder, m_wWinOrder, sizeof(m_wWinOrder)); //剩余扑克 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.wFriendChairID[i] = m_wFriendChairID[i]; GameEnd.cbCardCount[i] = m_cbHandCardCount[i]; CopyMemory(GameEnd.cbCardData[i], m_cbHandCardData[i], m_cbHandCardCount[i] * sizeof(BYTE)); } // 有玩家打独; if (!m_bNobodyCallScore) { // 排名信息; for (WORD i = 0; i < GAME_PLAYER; i++) { if (m_cbHandCardCount[i] != 0) { m_wWinOrder[m_wWinCount++] = i; } } CopyMemory(GameEnd.wWinOrder, m_wWinOrder, sizeof(m_wWinOrder)); // 赢积分; SCORE lWinCellScore = 2 * m_pGameServiceOption->lCellScore; // 庄家赢; if (wChairID == m_wBankerUser) { ScoreInfo[m_wBankerUser].lScore = 3 * lWinCellScore; ScoreInfo[m_wBankerUser].cbType = SCORE_TYPE_WIN; for (WORD i = 0; i < GAME_PLAYER; i++) { if (i == m_wBankerUser) continue; ScoreInfo[i].lScore = 0 - lWinCellScore; ScoreInfo[i].cbType = SCORE_TYPE_WIN; } } else { ScoreInfo[m_wBankerUser].lScore = 0 - 3 * lWinCellScore; ScoreInfo[m_wBankerUser].cbType = SCORE_TYPE_WIN; for (WORD i = 0; i < GAME_PLAYER; i++) { if (i == m_wBankerUser) continue; ScoreInfo[i].lScore = lWinCellScore; ScoreInfo[i].cbType = SCORE_TYPE_WIN; } } //切换庄家 m_wFirstUser = m_wBankerUser; GameEnd.iGameEndType = GAME_END_DRAW; // 计算头子分; for (WORD i = 0; i < GAME_PLAYER; i++) { if (m_cbHandCardCount[i] <= 0) continue; GetBombScore(i, m_cbHandCardData[i], m_cbHandCardCount[i]); } } else { // 带王积分翻倍; BYTE cbHasJoker = IsHasGameRule(eDZRuleEnum_NO_JOKER) ? 1 : 2; //双扣判断(第一名和第二名是伙伴); if (m_wWinOrder[0] == m_wFriendChairID[m_wWinOrder[1]]) { GameEnd.iGameEndType = GAME_END_TWO_WIN; // 排名信息; for (WORD i = 0; i < GAME_PLAYER; i++) { if (m_cbHandCardCount[i] != 0) { m_wWinOrder[m_wWinCount++] = i; } } CopyMemory(GameEnd.wWinOrder, m_wWinOrder, sizeof(m_wWinOrder)); //游戏积分 ScoreInfo[m_wWinOrder[0]].lScore = 2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[0]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[1]].lScore = 2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[1]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[2]].lScore = -2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[2]].cbType = SCORE_TYPE_LOSE; ScoreInfo[m_wWinOrder[3]].lScore = -2 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[3]].cbType = SCORE_TYPE_LOSE; } //单扣判断(第一名和第二名不是伙伴); else { GameEnd.iGameEndType = GAME_END_ONE_WIN; //单扣第一名伙伴是第三名; m_wWinOrder[m_wWinCount++] = m_wFriendChairID[m_wWinOrder[0]]; //单扣第二名伙伴是第四名; m_wWinOrder[m_wWinCount++] = m_wFriendChairID[m_wWinOrder[1]]; CopyMemory(GameEnd.wWinOrder, m_wWinOrder, sizeof(m_wWinOrder)); //游戏积分 ScoreInfo[m_wWinOrder[0]].lScore = 1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[0]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[2]].lScore = 1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[2]].cbType = SCORE_TYPE_WIN; ScoreInfo[m_wWinOrder[1]].lScore = -1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[1]].cbType = SCORE_TYPE_LOSE; ScoreInfo[m_wWinOrder[3]].lScore = -1 * m_pGameServiceOption->lCellScore*cbHasJoker; ScoreInfo[m_wWinOrder[3]].cbType = SCORE_TYPE_LOSE; } //切换庄家 m_wFirstUser = m_wWinOrder[0]; } //游戏积分 for (WORD i = 0; i < GAME_PLAYER; i++) { GameEnd.lGameScore[i] = ScoreInfo[i].lScore; // 游戏得分; GameEnd.lBombScore[i] = m_lBombScore[i]; // 炸弹得分; GameEnd.lAllScore[i] = GameEnd.lGameScore[i] + m_lBombScore[i]; // 总得分; ScoreInfo[i].lScore = GameEnd.lAllScore[i]; } /********************************私人场统计****************************************/ tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord(); BYTE cbFinishCout = pPrivateRecord->cbFinishCout; //统计积分明细 for (WORD i = 0; i < GAME_PLAYER; i++) { if (cbFinishCout < 16) { m_PrivateEndInfo.lDetails[i][cbFinishCout] = GameEnd.lAllScore[i]; } } // 完成局数 m_PrivateEndInfo.cbFinishCout = cbFinishCout + 1; m_pITableFrame->addPrivatePlayCout(1); /********************************私人场统计****************************************/ //牌局结束后,每8局增加一点经验值; if (IsPrivateEnd()) { tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo(); SCORE lGrade = pPrivateFrame->dwPlayCost; for (WORD i = 0; i < GAME_PLAYER; i++) { ScoreInfo[i].lGrade = lGrade; } GameEnd.isPrivateEnd = true; } //发送信息 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); // 记录游戏结束消息; addGameRecordAction(SUB_S_GAME_END, &GameEnd, sizeof(GameEnd)); //写入积分; DataStream kDataStream; m_kGameRecord.StreamValue(kDataStream, true); m_pITableFrame->WriteTableScore(ScoreInfo, CountArray(ScoreInfo), kDataStream); //结束游戏 m_pITableFrame->ConcludeGame(GAME_SCENE_FREE); return true; } //发送场景 bool CTableFrameSink::OnEventSendGameScene(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbGameStatus, bool bSendSecret) { switch (cbGameStatus) { case GAME_SCENE_FREE: //空闲状态 { //构造数据 CMD_S_StatusFree StatusFree; memset(&StatusFree, 0, sizeof(StatusFree)); //游戏变量 StatusFree.wBankerUser = m_wBankerUser; StatusFree.lCellScore = m_pGameServiceOption->lCellScore; //发送场景 return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusFree, sizeof(StatusFree)); } case GAME_SCENE_SEND: { //构造数据; CMD_S_StatusSendCard StatusSend; ZeroMemory(&StatusSend, sizeof(StatusSend)); //单元积分; StatusSend.lCellScore = m_pITableFrame->GetCellScore(); //游戏信息; StatusSend.wCurrentUser = m_wCurrentUser; CopyMemory(StatusSend.cbHandCardCount, m_cbHandCardCount, sizeof(m_cbHandCardCount)); CopyMemory(StatusSend.cbHandCardData, m_cbHandCardData[wChairID], m_cbHandCardCount[wChairID] * sizeof(BYTE)); return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusSend, sizeof(StatusSend)); } case GAME_SCENE_CALL_SCORE: { //构造数据; CMD_S_StatusCallScore StatusCall; ZeroMemory(&StatusCall, sizeof(StatusCall)); //单元积分; StatusCall.lCellScore = m_pITableFrame->GetCellScore(); //游戏信息; StatusCall.wCurrentUser = m_wCurrentUser; CopyMemory(StatusCall.cbScoreInfo, m_cbScoreInfo, sizeof(m_cbScoreInfo)); CopyMemory(StatusCall.cbHandCardCount, m_cbHandCardCount, sizeof(m_cbHandCardCount)); CopyMemory(StatusCall.cbHandCardData, m_cbHandCardData[wChairID], m_cbHandCardCount[wChairID] * sizeof(BYTE)); return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusCall, sizeof(StatusCall)); } case GAME_SCENE_PLAY: //游戏状态 { //构造数据 CMD_S_StatusPlay StatusPlay; memset(&StatusPlay, 0, sizeof(StatusPlay)); //游戏变量 StatusPlay.wCurrentUser = m_wCurrentUser; StatusPlay.lCellScore = m_pGameServiceOption->lCellScore; //StatusPlay.wFriendChairID = m_wFriendChairID[wChairID]; StatusPlay.wBankerUser = m_wBankerUser; StatusPlay.bCallCard = m_bNobodyCallScore; if (IsHasGameRule(eDZRuleEnum_MINGBIAN)) { StatusPlay.wFriendChairID = m_wFriendChairID[wChairID]; } else { StatusPlay.wFriendChairID = INVALID_CHAIR; } //胜利信息 StatusPlay.wWinCount = m_wWinCount; CopyMemory(StatusPlay.wWinOrder, m_wWinOrder, sizeof(StatusPlay.wWinOrder)); CopyMemory(StatusPlay.bTrustee, m_bTrustee, sizeof(m_bTrustee)); //出牌信息 StatusPlay.wTurnWiner = m_wTurnWiner; StatusPlay.cbTurnCardType = m_TurnOutCard.cbCardType; StatusPlay.cbTurnCardCount = m_TurnOutCard.cbCardCount; StatusPlay.isLastCard = m_TurnOutCard.isLastCard; CopyMemory(StatusPlay.cbTurnCardData, m_TurnOutCard.cbCardData, m_TurnOutCard.cbCardCount*sizeof(BYTE)); //扑克信息 CopyMemory(StatusPlay.cbHandCardCount, m_cbHandCardCount, sizeof(m_cbHandCardCount)); CopyMemory(StatusPlay.cbHandCardData, m_cbHandCardData[wChairID], sizeof(BYTE)*m_cbHandCardCount[wChairID]); CopyMemory(StatusPlay.cbPartnerCardData, m_cbHandCardData[(wChairID + 2) % GAME_PLAYER], sizeof(BYTE)*m_cbHandCardCount[(wChairID + 2) % GAME_PLAYER]); //发送场景 return m_pITableFrame->SendGameScene(pIServerUserItem, &StatusPlay, sizeof(StatusPlay)); } } return false; } //定时器事件 bool CTableFrameSink::OnTimerMessage(DWORD wTimerID, WPARAM wBindParam) { if (IDI_SEND_CARD == wTimerID) { // 检测是否解散游戏; if (IsHasGameRule(eDZRuleEnum_NO_BOMB)) { for (WORD i = 0; i < GAME_PLAYER; i++) { if (!IsHasBomb(m_cbHandCardData[i], m_cbHandCardCount[i])) { m_etGameEndType = GAME_END_NO_BOMB; return OnEventGameConclude(INVALID_CHAIR, nullptr, GER_BAOZI); } } } if (IsHasGameRule(eDZRuleEnum_EIGHT_BOMB)) { for (WORD i = 0; i < GAME_PLAYER; i++) { if (IsHas8Bomb(m_cbHandCardData[i], m_cbHandCardCount[i])) { m_etGameEndType = GAME_END_8_BOMB; return OnEventGameConclude(INVALID_CHAIR, nullptr, GER_BAOZI); } } } // 有王不打独; if (IsHasGameRule(eDZRuleEnum_NO_JOKER)) { //设置状态; m_pITableFrame->SetGameStatus(GAME_SCENE_CALL_SCORE); //构造变量; CMD_S_CallScore CallScore; CallScore.wCallScoreUser = INVALID_CHAIR; CallScore.wCurrentUser = m_wCurrentUser; CallScore.cbCallScore = 0xff; //发送消息; m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_CALL_SCORE, &CallScore, sizeof(CallScore)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_CALL_SCORE, &CallScore, sizeof(CallScore)); } else { // 场景状态; m_pITableFrame->SetGameStatus(GAME_SCENE_PLAY); //设置用户; m_bNobodyCallScore = true; m_wBankerUser = m_wFirstUser; m_wTurnWiner = m_wBankerUser; m_wCurrentUser = m_wBankerUser; //发送消息; CMD_S_BankerInfo BankerInfo; ZeroMemory(&BankerInfo, sizeof(CMD_S_BankerInfo)); BankerInfo.wBankerUser = m_wBankerUser; BankerInfo.wCurrentUser = m_wCurrentUser; BankerInfo.bCallCard = m_bNobodyCallScore; BankerInfo.cbFirendCardData = SearchFriendChairID(); // 明边; if (IsHasGameRule(eDZRuleEnum_MINGBIAN)) { for (WORD i = 0; i < m_wPlayerCount; i++) { BankerInfo.wFriendChairID[i] = m_wFriendChairID[i]; } } else // 暗边; { for (WORD i = 0; i < m_wPlayerCount; i++) { BankerInfo.wFriendChairID[i] = INVALID_CHAIR; } } //发送数据 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); //增加记录; addGameRecordAction(SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); } } return false; } //数据事件 bool CTableFrameSink::OnDataBaseMessage(WORD wRequestID, VOID * pData, WORD wDataSize) { return false; } //积分事件 bool CTableFrameSink::OnUserScroeNotify(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason) { return false; } //游戏消息处理 bool CTableFrameSink::OnGameMessage(WORD wSubCmdID, VOID * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem) { switch (wSubCmdID) { case SUB_C_CALL_SCORE: //用户叫分; { //效验数据; ASSERT(wDataSize == sizeof(CMD_C_CallScore)); if (wDataSize != sizeof(CMD_C_CallScore)) return false; //状态效验; ASSERT(m_pITableFrame->GetGameStatus()==GAME_SCENE_CALL_SCORE); if (m_pITableFrame->GetGameStatus() != GAME_SCENE_CALL_SCORE) return true; //用户效验; ASSERT(pIServerUserItem->GetUserStatus()==US_PLAYING); if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true; //变量定义; CMD_C_CallScore * pCallScore = (CMD_C_CallScore *)pDataBuffer; //消息处理; WORD wChairID = pIServerUserItem->GetChairID(); return OnUserCallScore(wChairID, pCallScore->cbCallScore); } case SUB_C_OUT_CARD: //用户出牌 { //变量定义 CMD_C_OutCard * pOutCard = (CMD_C_OutCard *)pDataBuffer; WORD wHeadSize = sizeof(CMD_C_OutCard) - sizeof(pOutCard->cbCardData); //效验数据 ASSERT(wDataSize >= wHeadSize); if (wDataSize < wHeadSize) return false; ASSERT(wDataSize == (wHeadSize + pOutCard->cbCardCount*sizeof(pOutCard->cbCardData[0]))); if (wDataSize != (wHeadSize + pOutCard->cbCardCount*sizeof(pOutCard->cbCardData[0]))) return false; //用户效验 ASSERT(pIServerUserItem->GetUserStatus() == US_PLAYING); if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true; //消息处理 WORD wChairID = pIServerUserItem->GetChairID(); //return OnUserOutCard(wChairID, pOutCard->cbCardData, pOutCard->cbCardType, pOutCard->cbCardCount); return OnUserOutCard(wChairID, pOutCard); } case SUB_C_PASS_CARD: { //用户效验 ASSERT(pIServerUserItem->GetUserStatus() == US_PLAYING); if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true; //消息处理 WORD wChairID = pIServerUserItem->GetChairID(); return OnUserPassCard(wChairID); } case SUB_C_TRUSTEE: { CMD_C_Trustee *pTrustee = (CMD_C_Trustee *)pDataBuffer; if (wDataSize != sizeof(CMD_C_Trustee)) return false; //用户效验 WORD wChairID = pIServerUserItem->GetChairID(); m_bTrustee[wChairID] = pTrustee->bTrustee; CMD_S_Trustee Trustee; Trustee.bTrustee = pTrustee->bTrustee; Trustee.wChairID = wChairID; m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee)); return true; } } return false; } //框架消息 bool CTableFrameSink::OnFrameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize, IServerUserItem * pIServerUserItem) { return false; } //重置私人场结束信息 void CTableFrameSink::ResetPrivateEndInfo() { ZeroMemory(&m_PrivateEndInfo, sizeof(CMD_S_Private_End_Info)); } //获得私人场结束信息流 void CTableFrameSink::GetPrivateEndInfo(DataStream &kDataStream, bool bSend) { for (WORD i = 0; i < GAME_PLAYER; i++) { // 总积分 IServerUserItem* pServerUserItem = m_pITableFrame->GetTableUserItem(i); if (pServerUserItem) { m_PrivateEndInfo.lAllScore[i] = pServerUserItem->GetUserScore(); } } m_PrivateEndInfo.StreamValue(kDataStream, bSend); } //判断私人场是否结束 bool CTableFrameSink::IsPrivateEnd() { ASSERT(m_pITableFrame != nullptr); if (m_pITableFrame == nullptr) return false; tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo(); tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord(); if ((pPrivateFrame == nullptr) || (pPrivateRecord == nullptr)) return false; if (pPrivateFrame->cbGameCout <= pPrivateRecord->cbFinishCout) { return true; } return false; } bool CTableFrameSink::IsHasGameRule(eDZRuleEnum eType) { ASSERT(m_pITableFrame != nullptr); if (m_pITableFrame == nullptr) return false; const tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo(); if (nullptr == pPrivateFrame) return false; return (pPrivateFrame->dwGameRule & eType) > 0; //DWORD dwGameRule = (eDZRuleEnum_LOTTERY_7 | eDZRuleEnum_LOTTERY_10 | eDZRuleEnum_LOTTERY_J | eDZRuleEnum_LOTTERY_K); //return (dwGameRule & eType) > 0; } bool CTableFrameSink::IsRecordServerType() { return ((m_pGameServiceOption->wServerType&GAME_GENRE_EDUCATE) == GAME_GENRE_EDUCATE); } //用户坐下 bool CTableFrameSink::OnActionUserSitDown(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser) { //庄家设置 if ((bLookonUser == false) && (m_wFirstUser == INVALID_CHAIR)) { m_wFirstUser = pIServerUserItem->GetChairID(); } return true; } //用户起来 bool CTableFrameSink::OnActionUserStandUp(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser) { //庄家设置 if ((bLookonUser == false) && (m_wBankerUser == pIServerUserItem->GetChairID())) { m_wBankerUser = INVALID_CHAIR; } return true; } //用户叫分; bool CTableFrameSink::OnUserCallScore(WORD wChairID, BYTE cbCallScore) { //效验状态; ASSERT(wChairID == m_wCurrentUser); if (wChairID != m_wCurrentUser) return true; //设置叫分; m_cbScoreInfo[wChairID] = cbCallScore; //设置用户; if (cbCallScore != 0xFF) { m_wBankerUser = wChairID; m_wCurrentUser = INVALID_CHAIR; } else { WORD wNextUser = (wChairID + 1) % GAME_PLAYER; // 四人都不叫; if (m_wFirstUser == wNextUser) { m_bNobodyCallScore = true; m_wBankerUser = m_wFirstUser; m_wCurrentUser = INVALID_CHAIR; } else { m_wCurrentUser = wNextUser; } } //构造变量; CMD_S_CallScore CallScore; CallScore.wCallScoreUser = wChairID; CallScore.wCurrentUser = m_wCurrentUser; CallScore.cbCallScore = cbCallScore; //发送消息; m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_CALL_SCORE, &CallScore, sizeof(CallScore)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_CALL_SCORE, &CallScore, sizeof(CallScore)); //增加记录; addGameRecordAction(SUB_S_CALL_SCORE, &CallScore, sizeof(CallScore)); //开始判断; if (m_wBankerUser != INVALID_CHAIR) { //设置状态; m_pITableFrame->SetGameStatus(GAME_SCENE_PLAY); //设置用户; m_wTurnWiner = m_wBankerUser; m_wCurrentUser = m_wBankerUser; //发送消息; CMD_S_BankerInfo BankerInfo; ZeroMemory(&BankerInfo, sizeof(CMD_S_BankerInfo)); BankerInfo.wBankerUser = m_wBankerUser; BankerInfo.wCurrentUser = m_wCurrentUser; BankerInfo.bCallCard = m_bNobodyCallScore; if (m_bNobodyCallScore) { BankerInfo.cbFirendCardData = SearchFriendChairID(); //CopyMemory(BankerInfo.wFriendChairID, m_wFriendChairID, sizeof(WORD)*GAME_PLAYER); // 明边; if (IsHasGameRule(eDZRuleEnum_MINGBIAN)) { for (WORD i = 0; i < m_wPlayerCount; i++) { BankerInfo.wFriendChairID[i] = m_wFriendChairID[i]; } } else // 暗边; { for (WORD i = 0; i < m_wPlayerCount; i++) { BankerInfo.wFriendChairID[i] = INVALID_CHAIR; } } } //发送消息; m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); //增加记录; addGameRecordAction(SUB_S_BANKER_INFO, &BankerInfo, sizeof(BankerInfo)); } return true; } //用户出牌 bool CTableFrameSink::OnUserOutCard(WORD wChairID, CMD_C_OutCard * pOutCard) { //效验状态 ASSERT(m_pITableFrame->GetGameStatus() == GAME_SCENE_PLAY); if (m_pITableFrame->GetGameStatus() != GAME_SCENE_PLAY) return true; ASSERT(wChairID == m_wCurrentUser); if (wChairID != m_wCurrentUser) return false; ASSERT(pOutCard != nullptr); if (pOutCard == nullptr) return false; // 牌型校验; ASSERT(pOutCard->cbCardType != CT_ERROR); // 是否是最后一手牌; bool isLastCard = (pOutCard->cbCardCount == m_cbHandCardCount[wChairID]); // 排序; m_GameLogic.SortCardList(pOutCard->cbCardData, pOutCard->cbCardCount, ST_ORDER); //类型判断 int bCardType = m_GameLogic.GetCardType(pOutCard->cbCardData, pOutCard->cbCardCount, isLastCard); if ((bCardType&pOutCard->cbCardType) == CT_ERROR) { ASSERT(FALSE); return false; } //更随出牌 if (m_TurnOutCard.cbCardCount > 0 && m_GameLogic.CompareCard(&m_TurnOutCard, pOutCard) == false) { ASSERT(FALSE); return false; } //删除扑克 if (m_GameLogic.RemoveCard(pOutCard->cbCardData, pOutCard->cbCardCount, m_cbHandCardData[wChairID], m_cbHandCardCount[wChairID]) == false) { ASSERT(FALSE); return false; } // 统计炸弹奖分 if ((bCardType >> CT_BOMB_4) > 0) { BYTE cbBombCardData = pOutCard->cbCardData[pOutCard->cbCardCount - 1]; GetBombScore(wChairID, cbBombCardData, bCardType); } //设置变量 m_cbHandCardCount[wChairID] -= pOutCard->cbCardCount; // 保留玩家出牌; m_TurnOutCard.cbCardCount = pOutCard->cbCardCount; m_TurnOutCard.isLastCard = isLastCard; m_TurnOutCard.cbCardType = pOutCard->cbCardType; CopyMemory(m_TurnOutCard.cbCardData, pOutCard->cbCardData, sizeof(BYTE)*pOutCard->cbCardCount); //如呆没有玩家包牌; if (m_bNobodyCallScore) { if (m_cbHandCardCount[wChairID] == 0) { //设置用户 m_wWinOrder[m_wWinCount++] = wChairID; CMD_S_Ranking mRanking; mRanking.wChairID = wChairID; mRanking.cbRanking = (BYTE)m_wWinCount; m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_RANKING, &mRanking, sizeof(mRanking)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_RANKING, &mRanking, sizeof(mRanking)); //增加记录; addGameRecordAction(SUB_S_RANKING, &mRanking, sizeof(mRanking)); //用户统计 WORD wFriendChairID = m_wFriendChairID[wChairID]; if (m_cbHandCardCount[wFriendChairID] == 0) { m_wCurrentUser = INVALID_CHAIR; } // 只打二游; if (IsHasGameRule(eDZRuleEnum_TO_TWO) && (2 == m_wWinCount)) { m_wCurrentUser = INVALID_CHAIR; } } //切换用户 if (m_wCurrentUser != INVALID_CHAIR) { //设置用户 m_wTurnWiner = wChairID; m_wCurrentUser = (wChairID + 1) % GAME_PLAYER; //用户调整 while (m_cbHandCardCount[m_wCurrentUser] == 0) { m_wCurrentUser = (m_wCurrentUser + 1) % GAME_PLAYER; } } } else { //如果有玩家包牌并且出牌玩家剩余牌数为0则结束游戏; if (m_cbHandCardCount[wChairID] != 0) { //设置用户 m_wTurnWiner = wChairID; m_wCurrentUser = (m_wCurrentUser + 1) % GAME_PLAYER; } else { m_wCurrentUser = INVALID_CHAIR; } } //构造数据 CMD_S_OutCard OutCard; ZeroMemory(&OutCard, sizeof(OutCard)); OutCard.isLastCard = isLastCard; OutCard.cbCardType = pOutCard->cbCardType; OutCard.wOutCardUser = wChairID; OutCard.cbCardCount = pOutCard->cbCardCount; OutCard.wCurrentUser = m_wCurrentUser; CopyMemory(OutCard.cbCardData, pOutCard->cbCardData, pOutCard->cbCardCount*sizeof(BYTE)); //发送数据 WORD wHeadSize = sizeof(OutCard) - sizeof(OutCard.cbCardData); WORD wSendSize = wHeadSize + OutCard.cbCardCount*sizeof(BYTE); m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, wSendSize); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, wSendSize); //增加记录; addGameRecordAction(SUB_S_OUT_CARD, &OutCard, wSendSize); //结束判断(出牌玩家不是打独玩家时候结束游戏) if (m_wCurrentUser == INVALID_CHAIR) { OnEventGameConclude(wChairID, NULL, GER_NORMAL); } return true; } //用户放弃 bool CTableFrameSink::OnUserPassCard(WORD wChairID) { //效验状态 if (m_pITableFrame->GetGameStatus() != GAME_SCENE_PLAY) return true; if ((wChairID != m_wCurrentUser) || (m_TurnOutCard.cbCardCount == 0)) return false; //用户切换 do { //设置用户 m_wCurrentUser = (m_wCurrentUser + 1) % GAME_PLAYER; //完成判断 if (m_wCurrentUser == m_wTurnWiner) { //设置变量 m_TurnOutCard.cbCardCount = 0; //接风处理 if (m_cbHandCardCount[m_wTurnWiner] == 0) { //m_wCurrentUser = (m_wTurnWiner + 2) % GAME_PLAYER; m_wCurrentUser = m_wFriendChairID[m_wTurnWiner]; } break; } //继续处理 if (m_cbHandCardCount[m_wCurrentUser] != 0) break; } while (true); //构造消息 CMD_S_PassCard PassCard; PassCard.wPassCardUser = wChairID; PassCard.wCurrentUser = m_wCurrentUser; PassCard.cbTurnOver = (m_TurnOutCard.cbCardCount == 0) ? TRUE : FALSE; //发送数据 m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_PASS_CARD, &PassCard, sizeof(PassCard)); m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_PASS_CARD, &PassCard, sizeof(PassCard)); //增加记录; addGameRecordAction(SUB_S_PASS_CARD, &PassCard, sizeof(CMD_S_PassCard)); return true; } //搜索伙伴; BYTE CTableFrameSink::SearchFriendChairID() { static BYTE cbFriendCard[13] = { 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x21, 0x22 }; // 搜索伙伴; BYTE cbTmpCardData = 0x0; BYTE cbTmpCardCount = 0; WORD wFirstChairID = INVALID_CHAIR; WORD wNextChairID = INVALID_CHAIR; for (BYTE i = 0; i < 13; i++) { cbTmpCardData = cbFriendCard[i]; // 查找指定牌在谁手里; for (BYTE j = 0; j < GAME_PLAYER; j++) { for (BYTE k = 0; k < m_cbHandCardCount[j];k++) { // 找到确定牌; if (cbTmpCardData == m_cbHandCardData[j][k]) { cbTmpCardCount++; // 一张牌最多2张; if (cbTmpCardCount >= 2) break; } } // 两张牌在同一人手里; if ((cbTmpCardCount >= 2) && (wFirstChairID == INVALID_CHAIR)) { cbTmpCardCount = 0; wFirstChairID = INVALID_CHAIR; wNextChairID = INVALID_CHAIR; break; } // 找到第一个人; if ((cbTmpCardCount == 1) && (wFirstChairID == INVALID_CHAIR)) { wFirstChairID = j; } // 找到第二个人; else if ((cbTmpCardCount == 2) && (wFirstChairID != INVALID_CHAIR)) { wNextChairID = j; } // 找到2个人了; if ((cbTmpCardCount == 2) && (wFirstChairID != INVALID_CHAIR) && (wNextChairID != INVALID_CHAIR)) { break; } } // 找到2个人了; if ((cbTmpCardCount == 2) && (wFirstChairID != INVALID_CHAIR) && (wNextChairID != INVALID_CHAIR)) { break; } } // 找到2个人了; if ((cbTmpCardCount == 2) && (wFirstChairID != INVALID_CHAIR) && (wNextChairID != INVALID_CHAIR)) { m_wFriendChairID[wFirstChairID] = wNextChairID; m_wFriendChairID[wNextChairID] = wFirstChairID; for (WORD i = 0; i < GAME_PLAYER; i++) { if ((i == wFirstChairID) || (i == wNextChairID)) continue; for (WORD j = 0; j < GAME_PLAYER; j++) { if ((j == wFirstChairID) || (j == wNextChairID) || (j == i)) continue; m_wFriendChairID[i] = j; } } } else { // 没找到同伴,默认对家同伴; for (WORD i = 0; i < m_wPlayerCount; i++) { m_wFriendChairID[i] = (i + 2) % GAME_PLAYER; } } return cbTmpCardData; } //炸弹升级; int CTableFrameSink::AddBombScore(int nCardType, bool bList /*= true*/) { int nTmpCardType = 0; // 炸弹分级,2炸加一级; if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_4)) { nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_5) : CT_BOMB_5); } else if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_5)) { //nTmpCardType = m_GameLogic.TransListToInt(0, CT_BOMB_6); nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_6) : CT_BOMB_6); } else if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_6)) { //nTmpCardType = m_GameLogic.TransListToInt(0, CT_BOMB_7); nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_7) : CT_BOMB_7); } else if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_7)) { //nTmpCardType = m_GameLogic.TransListToInt(0, CT_BOMB_8); nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_8) : CT_BOMB_8); } else if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_8)) { //nTmpCardType = m_GameLogic.TransListToInt(0, CT_BOMB_9); nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_9) : CT_BOMB_9); } else if (m_GameLogic.IsHasCardType(nCardType, CT_BOMB_9)) { //nTmpCardType = m_GameLogic.TransListToInt(0, CT_BOMB_10); nTmpCardType = (bList ? m_GameLogic.TransListToInt(0, CT_BOMB_10) : CT_BOMB_10); } else { nTmpCardType = nCardType; } return nTmpCardType; } //计算炸弹积分; void CTableFrameSink::GetBombScore(WORD wChairID, BYTE cbCardData, int nCardType) { if ((nCardType >> CT_BOMB_4) > 0) { SCORE lBombScore = 0; // 炸弹分; int nTmpCardType = CT_ERROR; if ((m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x02))) { nTmpCardType = AddBombScore(nCardType); } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_7) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x07))) { nTmpCardType = AddBombScore(nCardType); } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_10) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0A))) { nTmpCardType = AddBombScore(nCardType); } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_J) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0B))) { nTmpCardType = AddBombScore(nCardType); } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_K) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0D))) { nTmpCardType = AddBombScore(nCardType); } else { nTmpCardType = nCardType; } // 炸弹分级,2炸加一级; if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_5)) { lBombScore = 1; } else if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_6)) { lBombScore = 2; } else if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_7)) { lBombScore = 4; } else if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_8)) { lBombScore = 8; } else if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_9)) { lBombScore = 16; } else if (m_GameLogic.IsHasCardType(nTmpCardType, CT_BOMB_10)) { lBombScore = 32; } // 分数统计; if (lBombScore > 0) { // 记录日志; MyLog("wChairID=%d, cbCardData=0x%x, nCardType=%d, lBombScore=%ld", wChairID, cbCardData, nTmpCardType, lBombScore); m_lBombScore[wChairID] += lBombScore * (GAME_PLAYER - 1); for (WORD i = 0; i < GAME_PLAYER; i++) { if (i != wChairID) { m_lBombScore[i] -= lBombScore; } MyLog("m_lBombScore[%d] = %ld", i, m_lBombScore[i]); } } } } void CTableFrameSink::GetBombScore(WORD wChairID, BYTE cbHandCardData[], BYTE cbHandCardCount) { BYTE bCardDataTemp[MAX_COUNT] = { 0 }; BYTE cbJokerCount = 0; BYTE cbCardTempCount = 0; // 拷贝牌列表,不拷贝王; for (BYTE i = 0; i < cbHandCardCount; i++) { if (m_GameLogic.IsLaiZiCard(cbHandCardData[i])) { cbJokerCount++; } else { bCardDataTemp[cbCardTempCount++] = cbHandCardData[i]; } } //分析扑克 tagAnalyseResult AnalyseResult; ZeroMemory(&AnalyseResult, sizeof(AnalyseResult)); m_GameLogic.AnalysebCardData(bCardDataTemp, cbCardTempCount, AnalyseResult); BYTE cbMaxCardType = 0; BYTE cbMaxCardValue = 0; // 找到最大的炸(先找普通最大牌型,再找开奖最大牌型,然后将两个牌型比较); if (cbJokerCount > 0) { // 倒着找; for (int i = BLOCK_EIGHT; i >= 0; i--) { // 找到数量最多的手牌; if (AnalyseResult.cbBlockCount[i] > 0) { BYTE cbCardCount = i + 1; // 牌数量; // 算上癞子数量; BYTE nCardType = CT_BOMB_4 + cbJokerCount + cbCardCount - 4; nCardType = (nCardType > CT_BOMB_10) ? CT_BOMB_10 : nCardType; // 不是炸弹不管; if (nCardType < CT_BOMB_4) break; for (BYTE j = 0; j < AnalyseResult.cbBlockCount[i]; j++) { BYTE nTmpCardType = 0; BYTE cbBombCard = AnalyseResult.cbCardData[i][j*cbCardCount]; // 2也算开奖; if ((m_GameLogic.GetCardValue(cbBombCard) == m_GameLogic.GetCardValue(0x02))) { nTmpCardType = nCardType + 1; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_7) && (m_GameLogic.GetCardValue(cbBombCard) == m_GameLogic.GetCardValue(0x07))) { nTmpCardType = nCardType + 1; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_10) && (m_GameLogic.GetCardValue(cbBombCard) == m_GameLogic.GetCardValue(0x0A))) { nTmpCardType = nCardType + 1; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_J) && (m_GameLogic.GetCardValue(cbBombCard) == m_GameLogic.GetCardValue(0x0B))) { nTmpCardType = nCardType + 1; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_K) && (m_GameLogic.GetCardValue(cbBombCard) == m_GameLogic.GetCardValue(0x0D))) { nTmpCardType = nCardType + 1; } else { nTmpCardType = nCardType; } // 最大10炸; nTmpCardType = (nTmpCardType > CT_BOMB_10) ? CT_BOMB_10 : nTmpCardType; if (nTmpCardType > cbMaxCardType) { cbMaxCardValue = m_GameLogic.GetCardLogicValue(cbBombCard); cbMaxCardType = nTmpCardType; } } break; } } } // 手里有四个王,并且最大炸弹类型小于八炸,就直接用四个王算八炸; if ((4 == cbJokerCount) && (cbMaxCardType < CT_BOMB_8)) { int nCardType = m_GameLogic.TransListToInt(0, CT_BOMB_8); GetBombScore(wChairID, 0x4F, nCardType); cbJokerCount = 0; } // 倒着找; for (int i = BLOCK_EIGHT; i >= 0; i--) { if (AnalyseResult.cbBlockCount[i] <= 0) continue; BYTE cbCardCount = i + 1; // 牌数量; for (BYTE j = 0; j < AnalyseResult.cbBlockCount[i]; j++) { BYTE cbBombCard = AnalyseResult.cbCardData[i][j*cbCardCount]; BYTE cbCardType = CT_BOMB_4 + cbCardCount - 4; // 癞子直接和最大的炸弹组合算头子分; if ((cbJokerCount > 0) && (m_GameLogic.GetCardLogicValue(cbBombCard) == cbMaxCardValue)) { cbCardType += cbJokerCount; cbJokerCount = 0; } cbCardType = (cbCardType > CT_BOMB_10) ? CT_BOMB_10 : cbCardType; if (cbCardType < CT_BOMB_4) continue; // 统计炸弹; int nCardType = m_GameLogic.TransListToInt(0, cbCardType); GetBombScore(wChairID, cbBombCard, nCardType); } } } //是否有炸弹(不算王); bool CTableFrameSink::IsHasBomb(BYTE cbHandCardData[], BYTE cbHandCardCount) { bool bHasBomb = false; BYTE bCardDataTemp[MAX_COUNT] = { 0 }; BYTE cbCardTempCount = 0; // 拷贝牌列表,不拷贝王; for (BYTE i = 0; i < cbHandCardCount; i++) { if (!m_GameLogic.IsLaiZiCard(cbHandCardData[i])) { bCardDataTemp[cbCardTempCount++] = cbHandCardData[i]; } } //分析扑克 tagAnalyseResult AnalyseResult; ZeroMemory(&AnalyseResult, sizeof(AnalyseResult)); m_GameLogic.AnalysebCardData(bCardDataTemp, cbCardTempCount, AnalyseResult); for (int i = BLOCK_FOUR; i <= BLOCK_EIGHT; i++) { if (AnalyseResult.cbBlockCount[i] > 0) { bHasBomb = true; break; } } return bHasBomb; } //是否8炸弹; bool CTableFrameSink::IsHas8Bomb(BYTE cbHandCardData[], BYTE cbHandCardCount) { bool bHas8Bomb = false; BYTE bCardDataTemp[MAX_COUNT] = { 0 }; BYTE cbJokerCount = 0; BYTE cbCardTempCount = 0; // 拷贝牌列表,不拷贝王; for (BYTE i = 0; i < cbHandCardCount; i++) { if (m_GameLogic.IsLaiZiCard(cbHandCardData[i])) { cbJokerCount++; } else { bCardDataTemp[cbCardTempCount++] = cbHandCardData[i]; } } // 四张王就是八炸; if (cbJokerCount >= 4) return true; //分析扑克 tagAnalyseResult AnalyseResult; ZeroMemory(&AnalyseResult, sizeof(AnalyseResult)); m_GameLogic.AnalysebCardData(bCardDataTemp, cbCardTempCount, AnalyseResult); // 最小八炸就是4炸加4王; for (int i = BLOCK_FOUR; i <= BLOCK_EIGHT; i++) { // 有炸弹; if (AnalyseResult.cbBlockCount[i] > 0) { if ((i + cbJokerCount) >= BLOCK_EIGHT) { bHas8Bomb = true; break; } else if ((i + cbJokerCount) == BLOCK_SEVEN) { // 找最大牌值; BYTE cbCardCount = i + 1; // 牌数量; for (BYTE j = 0; j < AnalyseResult.cbBlockCount[i]; j++) { BYTE cbCardData = AnalyseResult.cbCardData[i][j*cbCardCount]; if ((m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x02))) { bHas8Bomb = true; break; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_7) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x07))) { bHas8Bomb = true; break; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_10) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0A))) { bHas8Bomb = true; break; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_J) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0B))) { bHas8Bomb = true; break; } else if (IsHasGameRule(eDZRuleEnum_LOTTERY_K) && (m_GameLogic.GetCardValue(cbCardData) == m_GameLogic.GetCardValue(0x0D))) { bHas8Bomb = true; break; } } } } } return bHas8Bomb; } /////////////////////////////// 游戏录像 /////////////////////////////////////////// void CTableFrameSink::addGameRecordAction(WORD wSubCmdID, void* pSubMessage, int nMessageSize) { tagGameRecordOperateResult kOperateRecord; kOperateRecord.wSubCmdID = wSubCmdID; kOperateRecord.subMessageData.pushValue(pSubMessage, nMessageSize); m_kGameRecord.actionVec.push_back(kOperateRecord); } void CTableFrameSink::starGameRecord() { m_kGameRecord = tagGameRecord(); m_kGameRecord.wBankerUser = m_wBankerUser; m_kGameRecord.wEastUser = 0; for (WORD i = 0; i < GAME_PLAYER; i++) { IServerUserItem* pUserItem = m_pITableFrame->GetTableUserItem(i); tagUserInfo* pUserInfo = pUserItem->GetUserInfo(); if (pUserItem == NULL || NULL == pUserInfo) { continue; } tagGameRecordPlayer kReocrdPlayer; kReocrdPlayer.dwUserID = pUserItem->GetUserID(); kReocrdPlayer.dwGameID = pUserItem->GetGameID(); kReocrdPlayer.wChairID = pUserItem->GetChairID(); kReocrdPlayer.cbSex = pUserItem->GetGender(); kReocrdPlayer.lScore = pUserItem->GetUserScore(); kReocrdPlayer.strHead = pUserInfo->szHeadHttp; kReocrdPlayer.strNickName = pUserItem->GetNickName(); for (BYTE j = 0; j < m_cbHandCardCount[i]; j++) { kReocrdPlayer.cbCardData.push_back(m_cbHandCardData[i][j]); } m_kGameRecord.playersVec.push_back(kReocrdPlayer); } } ////////////////////////////////////////////////////////////////////////// void CTableFrameSink::MyLog(TCHAR *szLog, ...) { CString strLog = ""; va_list ap; va_start(ap, szLog); strLog.FormatV(szLog, ap); va_end(ap); CString strTmpLog = ""; strTmpLog.Format("TableID = %d, %s.\n", m_pITableFrame->GetTableID(), strLog); ::OutputDebugString(strTmpLog.GetBuffer()); }