诸暨麻将添加redis
您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 
 
 
 

2826 行
103 KiB

  1. #include "StdAfx.h"
  2. #include "TableFrameSinkCxz.h"
  3. TableFrameSinkCxz::~TableFrameSinkCxz(void)
  4. {
  5. }
  6. //构造函数
  7. TableFrameSinkCxz::TableFrameSinkCxz(void) :m_GameLogic(this)
  8. {
  9. //游戏变量
  10. bGameType = 0;
  11. m_lSiceCount=0;
  12. m_wBankerUser=INVALID_CHAIR;
  13. ZeroMemory(m_cbCardIndex,sizeof(m_cbCardIndex));
  14. ZeroMemory(m_bTrustee,sizeof(m_bTrustee));
  15. // ZeroMemory( m_GangScore,sizeof(m_GangScore) );
  16. ZeroMemory( m_cbGenCount,sizeof(m_cbGenCount) );
  17. ZeroMemory( m_bPlayStatus,sizeof(m_bPlayStatus) );
  18. ZeroMemory(m_lGameScore, sizeof(m_lGameScore));
  19. ZeroMemory(m_lGameTatolScore, sizeof(m_lGameTatolScore));
  20. ZeroMemory(m_HuPai, sizeof(m_HuPai));
  21. // ZeroMemory( m_lFangPao, sizeof(m_lFangPao));
  22. // ZeroMemory( m_lDianPao, sizeof(m_lDianPao));
  23. // ZeroMemory( m_lMingGang, sizeof(m_lMingGang));
  24. // ZeroMemory( m_lAnGang, sizeof(m_lAnGang));
  25. // ZeroMemory( m_lChaDaJiao, sizeof(m_lChaDaJiao));
  26. ZeroMemory(m_TabbOutCardCout, sizeof(m_TabbOutCardCout)); //可以打出的牌就听牌的个数
  27. ZeroMemory(m_TabbOutCardData, sizeof(m_TabbOutCardData)); //具体打哪几张牌
  28. ZeroMemory(m_TabbTingCardCount, sizeof(m_TabbTingCardCount)); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  29. ZeroMemory(m_TabbTingCardData, sizeof(m_TabbTingCardData)); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  30. m_cbWinCount = 0;
  31. memset( m_wWinOrder,INVALID_CHAIR,sizeof(m_wWinOrder) );
  32. ZeroMemory( m_lGameTax,sizeof(m_lGameTax) );
  33. //ZeroMemory( m_wLostFanShu,sizeof(m_wLostFanShu) );
  34. //出牌信息
  35. m_cbOutCardData=0;
  36. m_cbOutCardCount=0;
  37. m_wOutCardUser=INVALID_CHAIR;
  38. ZeroMemory(m_cbDiscardCard,sizeof(m_cbDiscardCard));
  39. ZeroMemory(m_cbDiscardCount,sizeof(m_cbDiscardCount));
  40. ZeroMemory(m_cbLastDisCardData, sizeof(m_cbLastDisCardData));
  41. ZeroMemory(m_cbLastDisCount, sizeof(m_cbLastDisCount));
  42. ZeroMemory(m_OutLaiZi, sizeof(m_OutLaiZi));
  43. //堆立信息
  44. m_wHeapHand = INVALID_CHAIR;
  45. m_wHeapTail = INVALID_CHAIR;
  46. ZeroMemory(m_cbHeapCardInfo,sizeof(m_cbHeapCardInfo));
  47. //发牌信息
  48. m_cbSendCardData=0;
  49. m_cbSendCardCount=0;
  50. m_cbLeftCardCount=0;
  51. ZeroMemory(m_cbRepertoryCard,sizeof(m_cbRepertoryCard));
  52. //运行变量
  53. m_cbProvideCard=0;
  54. m_wResumeUser=INVALID_CHAIR;
  55. m_wCurrentUser=INVALID_CHAIR;
  56. m_wProvideUser=INVALID_CHAIR;
  57. //状态变量
  58. m_bSendStatus=false;
  59. m_bGangStatus = false;
  60. m_bGangOutStatus = false;
  61. ZeroMemory(m_bEnjoinChiHu,sizeof(m_bEnjoinChiHu));
  62. ZeroMemory(m_bEnjoinChiPeng,sizeof(m_bEnjoinChiPeng));
  63. //用户状态
  64. ZeroMemory(m_bResponse,sizeof(m_bResponse));
  65. ZeroMemory(m_cbUserAction,sizeof(m_cbUserAction));
  66. ZeroMemory(m_cbOperateCard,sizeof(m_cbOperateCard));
  67. ZeroMemory(m_cbPerformAction,sizeof(m_cbPerformAction));
  68. //组合扑克
  69. ZeroMemory(m_WeaveItemArray,sizeof(m_WeaveItemArray));
  70. ZeroMemory(m_cbWeaveItemCount,sizeof(m_cbWeaveItemCount));
  71. //结束信息
  72. m_cbChiHuCard=0;
  73. ZeroMemory( m_dwChiHuKind,sizeof(m_dwChiHuKind) );
  74. memset( m_wProvider,INVALID_CHAIR,sizeof(m_wProvider) );
  75. ZeroMemory(m_HuPai, sizeof(m_HuPai));
  76. ZeroMemory(m_HuPaiLiuShui, sizeof(m_HuPaiLiuShui));
  77. //组件变量
  78. m_pITableFrame=NULL;
  79. m_pGameServiceOption=NULL;
  80. //m_bReduceBean = false;
  81. for (int i = 0; i < GAME_PLAY; ++i)
  82. {
  83. //m_cbDingQue[i] = INVALID_BYTE;
  84. m_lUserTmpScore[i] = TEMP_MAX_SCORE; //用户临时积分
  85. }
  86. bIsHuang = false;
  87. return;
  88. }
  89. //接口查询
  90. void * TableFrameSinkCxz::QueryInterface(const IID & Guid, DWORD dwQueryVer)
  91. {
  92. if ((Guid == IID_ITableFrameSink) && (InterfaceVersionCompare(dwQueryVer, VER_ITableFrameSinkCxz)))
  93. return static_cast<ITableFrameSink *>(this);
  94. QUERYINTERFACE(ITableUserAction, Guid, dwQueryVer);
  95. if ((Guid == IID_IUnknownEx) && (InterfaceVersionCompare(dwQueryVer, VER_IUnknownEx)))
  96. return static_cast<IUnknownEx *>(static_cast<ITableFrameSink *>(this));
  97. return NULL;
  98. }
  99. //初始化
  100. bool TableFrameSinkCxz::Initialization(IUnknownEx * pIUnknownEx)
  101. {
  102. //查询接口
  103. ASSERT(pIUnknownEx!=NULL);
  104. m_pITableFrame=QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx,ITableFrame);
  105. if (m_pITableFrame==NULL)
  106. return false;
  107. //获取参数
  108. m_pGameServiceOption=m_pITableFrame->GetGameServiceOption();
  109. ASSERT(m_pGameServiceOption!=NULL);
  110. //开始模式
  111. m_pITableFrame->SetStartMode(START_MODE_FULL_READY);
  112. return true;
  113. }
  114. //复位桌子
  115. VOID TableFrameSinkCxz::RepositionSink()
  116. {
  117. //游戏变量
  118. m_lSiceCount=0;
  119. ZeroMemory(m_cbCardIndex,sizeof(m_cbCardIndex));
  120. ZeroMemory(m_bTrustee,sizeof(m_bTrustee));
  121. // ZeroMemory( m_GangScore,sizeof(m_GangScore) );
  122. ZeroMemory( m_cbGenCount,sizeof(m_cbGenCount) );
  123. ZeroMemory( m_lGameScore,sizeof(m_lGameScore) );
  124. ZeroMemory( m_bPlayStatus,sizeof(m_bPlayStatus) );
  125. m_cbWinCount = 0;
  126. memset( m_wWinOrder,INVALID_CHAIR,sizeof(m_wWinOrder) );
  127. ZeroMemory( m_lGameTax,sizeof(m_lGameTax) );
  128. //ZeroMemory( m_wLostFanShu,sizeof(m_wLostFanShu) );
  129. ZeroMemory(m_TabbOutCardCout, sizeof(m_TabbOutCardCout)); //可以打出的牌就听牌的个数
  130. ZeroMemory(m_TabbOutCardData, sizeof(m_TabbOutCardData)); //具体打哪几张牌
  131. ZeroMemory(m_TabbTingCardCount, sizeof(m_TabbTingCardCount)); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  132. ZeroMemory(m_TabbTingCardData, sizeof(m_TabbTingCardData)); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  133. //出牌信息
  134. m_cbOutCardData=0;
  135. m_cbOutCardCount=0;
  136. m_wOutCardUser=INVALID_CHAIR;
  137. ZeroMemory(m_cbDiscardCard,sizeof(m_cbDiscardCard));
  138. ZeroMemory(m_cbDiscardCount,sizeof(m_cbDiscardCount));
  139. ZeroMemory(m_cbLastDisCardData, sizeof(m_cbLastDisCardData));
  140. ZeroMemory(m_cbLastDisCount, sizeof(m_cbLastDisCount));
  141. //ZeroMemory(m_cbDiscardWuYongCard, sizeof(m_cbDiscardWuYongCard));
  142. //ZeroMemory(m_cbDiscardWuYongCount, sizeof(m_cbDiscardWuYongCount));
  143. ZeroMemory(m_OutLaiZi, sizeof(m_OutLaiZi));
  144. //堆立信息
  145. m_wHeapHand = INVALID_CHAIR;
  146. m_wHeapTail = INVALID_CHAIR;
  147. ZeroMemory(m_cbHeapCardInfo,sizeof(m_cbHeapCardInfo));
  148. //发牌信息
  149. m_cbSendCardData=0;
  150. m_cbSendCardCount=0;
  151. m_cbLeftCardCount=0;
  152. ZeroMemory(m_cbRepertoryCard,sizeof(m_cbRepertoryCard));
  153. //运行变量
  154. m_cbProvideCard=0;
  155. m_wResumeUser=INVALID_CHAIR;
  156. m_wCurrentUser=INVALID_CHAIR;
  157. m_wProvideUser=INVALID_CHAIR;
  158. m_wBankerUser = INVALID_CHAIR;
  159. //状态变量
  160. m_bSendStatus=false;
  161. m_bGangStatus = false;
  162. m_bGangOutStatus = false;
  163. ZeroMemory(m_bEnjoinChiHu,sizeof(m_bEnjoinChiHu));
  164. ZeroMemory(m_bEnjoinChiPeng,sizeof(m_bEnjoinChiPeng));
  165. //用户状态
  166. ZeroMemory(m_bResponse,sizeof(m_bResponse));
  167. ZeroMemory(m_cbUserAction,sizeof(m_cbUserAction));
  168. ZeroMemory(m_cbOperateCard,sizeof(m_cbOperateCard));
  169. ZeroMemory(m_cbPerformAction,sizeof(m_cbPerformAction));
  170. //组合扑克
  171. ZeroMemory(m_WeaveItemArray,sizeof(m_WeaveItemArray));
  172. ZeroMemory(m_cbWeaveItemCount,sizeof(m_cbWeaveItemCount));
  173. //结束信息
  174. m_cbChiHuCard=0;
  175. ZeroMemory(m_dwChiHuKind,sizeof(m_dwChiHuKind));
  176. m_cbLaiZiPiData = 0;
  177. m_cbLaiZiData = 0;
  178. bIsHuang = false;
  179. //for( WORD i = 0; i < GAME_PLAY; i++ )
  180. // m_ChiHuRight[i].clear();
  181. return;
  182. }
  183. bool TableFrameSinkCxz::RepayRecordStart()
  184. {
  185. m_bReplayRecordStart = true;
  186. for (GameRecordPacket grp : m_UserReplayRecord)
  187. {
  188. delete[] grp.pData;
  189. grp.pData = nullptr;
  190. }
  191. m_UserReplayRecord.clear();//不会释放内存
  192. m_UserReplayRecord.shrink_to_fit();//释放内存
  193. return true;
  194. }
  195. bool TableFrameSinkCxz::RepayRecordEnd()
  196. {
  197. if (!m_bReplayRecordStart)
  198. return false;
  199. m_bReplayRecordStart = false;
  200. CMD_GR_ReplayRecordResp urr;
  201. ZeroMemory(&urr, sizeof(CMD_GR_ReplayRecordResp));
  202. urr.m_UUID = 0;
  203. urr.m_UserId = 0;
  204. urr.m_startTime = time(0);
  205. urr.m_endTime = time(0);
  206. urr.m_gameconfig = m_gameConfig;
  207. //urr.m_UserId = pIServerUserItem->GetUserID();
  208. for (int j = 0; j < GAME_PLAY; ++j)
  209. {
  210. IServerUserItem * pIServerUserItem = m_pITableFrame->GetTableUserItem(j);
  211. if ((pIServerUserItem == NULL) /*|| (pIServerUserItem->IsClientReady() == false)*/)
  212. continue;
  213. auto& chairInfo = urr.m_chairList[j];
  214. chairInfo.dwUserId = pIServerUserItem->GetUserID();
  215. chairInfo.wChairId = pIServerUserItem->GetChairID();
  216. lstrcpy(chairInfo.userName, pIServerUserItem->GetNickName());
  217. lstrcpy(chairInfo.headUrl, pIServerUserItem->GetUserInfo ()->szHeadUrl);
  218. }
  219. urr.m_recordCount = m_UserReplayRecord.size();
  220. int GameRecordPacketSize = sizeof(GameRecordPacket) - sizeof(void*);//每条记录头长度
  221. int totalSize = sizeof(CMD_GR_ReplayRecordResp);//总记录头长度
  222. for (GameRecordPacket grp : m_UserReplayRecord)
  223. totalSize += (GameRecordPacketSize + grp.wSize);
  224. char* replyRecordData = new char[totalSize];
  225. ZeroMemory(replyRecordData, totalSize);
  226. CopyMemory(replyRecordData, &urr, sizeof(CMD_GR_ReplayRecordResp));
  227. int nOffset = sizeof(CMD_GR_ReplayRecordResp);
  228. for (GameRecordPacket grp : m_UserReplayRecord)
  229. {
  230. CopyMemory(replyRecordData + nOffset, &grp, GameRecordPacketSize);
  231. nOffset += GameRecordPacketSize;
  232. CopyMemory(replyRecordData + nOffset, grp.pData, grp.wSize);
  233. nOffset += grp.wSize;
  234. }
  235. m_pITableFrame->SaveReplayRecord(replyRecordData, totalSize);
  236. //delete replyRecordData;不能删除,已托管给SaveReplayRecord函数
  237. return true;
  238. }
  239. bool TableFrameSinkCxz::RepayRecord(WORD wChairID, WORD wSubCmdId, void* pData, WORD wSize)
  240. {
  241. //获取用户
  242. //char* pNewData = new char[wSize + sizeof(GameRecordPacket)];
  243. //memcpy(pNewData, pData, wSize); //修改BYJN 疑似内存溢出
  244. GameRecordPacket record;
  245. record.wSize = wSize;
  246. record.wChairID = wChairID;
  247. record.wSubCmdID = wSubCmdId;
  248. record.wMainCmdID = MDM_GF_GAME;
  249. record.pData = new char[wSize];
  250. CopyMemory(record.pData, pData, wSize);
  251. m_UserReplayRecord.push_back(record);
  252. return true;
  253. }
  254. //游戏开始
  255. bool TableFrameSinkCxz::OnEventGameStart()
  256. {
  257. //椅子数量
  258. WORD wChairCount = m_pITableFrame->GetChairCount();
  259. //开始记录回放数据
  260. RepayRecordStart();
  261. //重置发牌状态
  262. m_isCanOutCard = false;
  263. //重置掉线玩家列表
  264. m_offlineUsers.clear();
  265. //设置状态
  266. m_pITableFrame->SetGameStatus(GS_MJ_PLAY);
  267. m_gameConfig.wHadPlayCount++;
  268. //混乱扑克
  269. m_lSiceCount = MAKELONG(MAKEWORD(rand()%6+1,rand()%6+1),MAKEWORD(rand()%6+1,rand()%6+1));
  270. m_cbLeftCardCount = m_GameLogic.RandCardData(m_cbRepertoryCard);
  271. if (1 == m_gameConfig.wHadPlayCount || m_wNextBankerUser == INVALID_CHAIR)
  272. {
  273. m_wBankerUser = 0;//((BYTE)(m_lSiceCount >> 24) + (BYTE)(m_lSiceCount >> 16) - 1) % wChairCount;
  274. }
  275. else
  276. {
  277. m_wBankerUser = m_wNextBankerUser;
  278. }
  279. m_wNextBankerUser = INVALID_CHAIR;
  280. /*#ifdef DEBUGA
  281. BYTE byTest[] = {
  282. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, //万子
  283. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, //万子
  284. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, //万子
  285. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, //万子
  286. 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x18, 0x19, 0x21, //索子
  287. 0x26, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, //同子
  288. 0x11, 0x12, //索子
  289. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x13, //索子
  290. 0x11, 0x12, 0x13, 0x14, 0x15, 0x17, 0x17, 0x19, 0x19, 0x21, 0x16, 0x18, 0x18, //索子 //同子
  291. 0x21, 0x22, 0x23, 0x24, 0x25, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x27, 0x29, //同子
  292. 0x14, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x21, //同子
  293. };
  294. if (m_GameLogic.PeiPai(byTest))
  295. CopyMemory(m_cbRepertoryCard, byTest, sizeof(byTest));
  296. #endif*/
  297. BYTE cbTakeCount = 0;
  298. //分发扑克
  299. for (WORD i=0;i<GAME_PLAY;i++)
  300. {
  301. //if( m_pITableFrame->GetTableUserItem(i) != NULL )
  302. //{
  303. m_bPlayStatus[i] = true;
  304. m_cbLeftCardCount-=(MAX_COUNT-1);//每一个玩家都发出去13张牌,还剩多少
  305. cbTakeCount += (MAX_COUNT - 1);//每个玩家加13张牌
  306. m_GameLogic.SwitchToCardIndex(&m_cbRepertoryCard[m_cbLeftCardCount],MAX_COUNT-1,m_cbCardIndex[i]);
  307. //}
  308. //else
  309. //{
  310. // m_bPlayStatus[i] = false;
  311. //}
  312. }
  313. //癞子皮
  314. m_cbSendCardCount++;
  315. m_cbSendCardData = m_cbRepertoryCard[--m_cbLeftCardCount];
  316. m_cbLaiZiPiData = m_cbSendCardData;
  317. //m_cbDiscardCard[m_wBankerUser][m_cbDiscardCount[m_wBankerUser]++] = m_cbLaiZiPiData;//翻出来得皮子不放在任何玩家得得丢弃牌里面
  318. //癞子
  319. if ((m_cbLaiZiPiData&0x0f) == 0x09)
  320. {
  321. BYTE m_cbCole = m_cbLaiZiPiData & 0xf0;
  322. m_cbLaiZiData = m_cbCole | 0x01;
  323. }
  324. else
  325. {
  326. m_cbLaiZiData = m_cbLaiZiPiData + 1;
  327. }
  328. //需要把癞子皮,癞子数据返回给前端
  329. //发送扑克,庄家摸牌
  330. m_cbSendCardCount++;
  331. m_cbSendCardData=m_cbRepertoryCard[--m_cbLeftCardCount];
  332. m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]++;
  333. //设置变量
  334. m_cbProvideCard=0;
  335. m_wProvideUser = m_wBankerUser;
  336. m_wCurrentUser=m_wBankerUser;
  337. //杠牌判断
  338. tagGangCardResult GangCardResult;
  339. m_cbUserAction[m_wBankerUser] |= m_GameLogic.AnalyseGangCard(m_cbCardIndex[m_wBankerUser],m_cbLaiZiData,m_cbLaiZiPiData, NULL, 0, GangCardResult);
  340. //胡牌判断
  341. CChiHuRight chr;
  342. m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]--;
  343. m_cbUserAction[m_wBankerUser] |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[m_wBankerUser], NULL, 0, m_cbSendCardData, chr, m_cbLaiZiData, bGameType);
  344. m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]++;
  345. BYTE ActionCard[3] = { 0 };//杠哪个牌
  346. BYTE AntActionCount = 0;//暗杠操作动作次数
  347. if (m_cbUserAction[m_wBankerUser] != WIK_NULL)
  348. {
  349. if (m_cbUserAction[m_wBankerUser] & WIK_GANG)
  350. {
  351. if ( m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbLaiZiPiData)]==3)
  352. {
  353. m_cbUserAction[m_wBankerUser] |= WIK_AN_PIGANG;
  354. ActionCard[AntActionCount++] = m_cbLaiZiPiData;
  355. }
  356. else
  357. {
  358. m_cbUserAction[m_wBankerUser] |= WIK_AN_GANG;
  359. for (BYTE i = 0; i < MAX_INDEX; i++)
  360. {
  361. if (m_cbCardIndex[m_wBankerUser][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  362. {
  363. ActionCard[AntActionCount++] = m_GameLogic.SwitchToCardData(i);
  364. }
  365. }
  366. }
  367. }
  368. if (m_cbUserAction[m_wBankerUser] & WIK_ZI_MO)
  369. {
  370. if (m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] == 1 && (!(m_cbUserAction[m_wBankerUser] & WIK_YING_ZIMO)))
  371. {
  372. m_cbUserAction[m_wBankerUser] |= WIK_RUAN_ZIMO;//软自摸
  373. }
  374. else
  375. {
  376. m_cbUserAction[m_wBankerUser] |= WIK_YING_ZIMO;//硬自摸
  377. }
  378. }
  379. }
  380. if (bGameType == CXZBanLai && (m_cbUserAction[m_wBankerUser] & WIK_RUAN_ZIMO))
  381. {
  382. m_cbUserAction[m_wBankerUser] = m_cbUserAction[m_wBankerUser] & 0xff0ff;
  383. }
  384. m_cbProvideCard = m_cbSendCardData;
  385. m_wResumeUser = m_wCurrentUser;
  386. //if (m_cbUserAction[m_wBankerUser] != WIK_NULL)
  387. // SendOperateNotify();
  388. //构造数据
  389. CMD_S_GameStart GameStart;
  390. GameStart.wBankerUser = m_wBankerUser;
  391. GameStart.cbLeftCardCount = m_cbLeftCardCount;
  392. WORD wSice = WORD(m_lSiceCount & 0xffff);
  393. GameStart.cbSiceLaiZi[0] = HIBYTE(wSice);
  394. GameStart.cbSiceLaiZi[1] = LOBYTE(wSice);
  395. GameStart.cbSiceLaiZi[2] = m_cbLaiZiPiData;
  396. GameStart.cbSiceLaiZi[3] = m_cbLaiZiData;
  397. GameStart.cbTotalCardCount = MAX_REPERTORY_SRLF;
  398. GameStart.cbCurrPlay = m_gameConfig.wHadPlayCount;
  399. GameStart.cbOptTime = GAME_TIMEOUT;
  400. //CopyMemory(GameStart.cbHeapCardInfo,m_cbHeapCardInfo,_countof(m_cbHeapCardInfo));
  401. //发送数据
  402. for (WORD i=0;i<wChairCount;i++)
  403. {
  404. if( !m_bPlayStatus[i] ) continue;
  405. //设置变量
  406. GameStart.wCurrentUser = i;
  407. GameStart.cbUserAction=m_cbUserAction[i];
  408. ZeroMemory(GameStart.ActionCard, sizeof(GameStart.ActionCard));
  409. if (i == m_wCurrentUser)
  410. {
  411. if (m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)] > 0 && m_wBankerUser == i)
  412. {
  413. m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]--;//从手上去掉抓的牌
  414. }
  415. else
  416. {
  417. return false;
  418. }
  419. }
  420. ZeroMemory(GameStart.cbCardData, sizeof(GameStart.cbCardData));
  421. m_GameLogic.SwitchToCardData(m_cbCardIndex[i], &GameStart.cbCardData[MAX_COUNT*i]);
  422. if (i == m_wCurrentUser)
  423. {
  424. CopyMemory(GameStart.ActionCard, ActionCard, sizeof(ActionCard));
  425. GameStart.cbCardData[i * 14 + 13] = m_cbSendCardData;//把去掉的牌加到数组末尾,
  426. m_cbCardIndex[m_wBankerUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]++;//把去掉的加进来
  427. }
  428. //if( m_pITableFrame->GetTableUserItem(i)->IsAndroidUser() )
  429. //{
  430. // BYTE bIndex = 1;
  431. // for( WORD j=0; j<wChairCount; j++ )
  432. // {
  433. // if( j == i ) continue;
  434. // m_GameLogic.SwitchToCardData(m_cbCardIndex[j],&GameStart.cbCardData[MAX_COUNT*bIndex++]);
  435. // }
  436. //}
  437. //发送数据
  438. m_pITableFrame->SendTableData(i, SUB_S_GAME_START, &GameStart, sizeof(GameStart));
  439. }
  440. //用户回放
  441. ZeroMemory(GameStart.cbCardData, sizeof(GameStart.cbCardData));
  442. //清手牌 旁观只能发一次
  443. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_START, &GameStart, sizeof(GameStart));
  444. for (WORD i = 0; i < wChairCount; i++)
  445. m_GameLogic.SwitchToCardData(m_cbCardIndex[i], &GameStart.cbCardData[MAX_COUNT*i]);
  446. RepayRecord(INVALID_CHAIR, SUB_S_GAME_START, &GameStart, sizeof(GameStart));
  447. return true;
  448. }
  449. void TableFrameSinkCxz::DeletePrivateTable(bool bSendState)
  450. {
  451. tagScoreInfo ScoreInfoArray[GAME_PLAY];
  452. ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray));
  453. WORD wChairCount = m_pITableFrame->GetChairCount();
  454. for (int i = 0; i < wChairCount; ++i)
  455. {
  456. IServerUserItem *pIUserItem = m_pITableFrame->GetTableUserItem(i);
  457. if (pIUserItem == NULL)
  458. continue;
  459. ScoreInfoArray[i].cbType = SCORE_TYPE_END;
  460. ScoreInfoArray[i].lScore = m_lUserTmpScore[i] - TEMP_MAX_SCORE; //记录临时分
  461. }
  462. m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
  463. ConcludeGame(GAME_STATUS_DELETE, bSendState);
  464. m_pITableFrame->DeletePrivateTableNow();
  465. }
  466. //游戏结束
  467. bool TableFrameSinkCxz::OnEventGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason, bool bSendState)
  468. {
  469. bool bFinish = (m_gameConfig.wHadPlayCount >= m_gameConfig.wPlayCountRule) ? 1 : 0;
  470. bool bDelete = false;
  471. switch (cbReason)
  472. {
  473. case GER_DELETE_PRIVATE:
  474. bFinish = 1;
  475. bDelete = true;
  476. if (!m_pITableFrame->IsGameStarted())
  477. {
  478. DeletePrivateTable(bSendState);
  479. return true;
  480. }
  481. //return true;
  482. //下坠
  483. case GER_NORMAL: //常规结束
  484. {
  485. if (bSendState && cbReason == GER_NORMAL)
  486. {
  487. bSendState = true;
  488. }
  489. //变量定义
  490. CMD_S_GameEnd GameEnd;
  491. ZeroMemory(&GameEnd, sizeof(GameEnd));
  492. GameEnd.bFinish = bFinish;//1……
  493. if (m_cbLeftCardCount <= 0 || bDelete)//荒庄了
  494. {
  495. if (!bDelete) GameEnd.bOptType = (bIsHuang == true ? 2 : 1);//庄荒了,需要返回信息
  496. else GameEnd.bOptType = 3;
  497. if (GameEnd.bOptType == 1)
  498. {//海底捞月
  499. GameEnd.bOptType = 1;
  500. BYTE TempWanJiaCardCount = 0;
  501. m_wNextBankerUser = wChairID;
  502. //统计积分,胡牌得分,玩家牌值
  503. for (WORD i = 0; i < GAME_PLAY; i++)
  504. {
  505. //m_lGameTatolScore[i] += m_lGameScore[i];
  506. GameEnd.cbWanJiaScore[i] = m_lGameTatolScore[i];//各玩家积分3…………
  507. if (i == wChairID)continue;
  508. m_GameLogic.SwitchToCardData(m_cbCardIndex[i], GameEnd.cbCardData[i]);
  509. }
  510. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--)
  511. {
  512. m_GameLogic.SwitchToCardData(m_cbCardIndex[wChairID], GameEnd.cbCardData[wChairID]);
  513. TempWanJiaCardCount = m_GameLogic.GetCardCount(m_cbCardIndex[wChairID]);
  514. GameEnd.cbCardData[wChairID][TempWanJiaCardCount] = m_cbProvideCard;//手牌数据4……
  515. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  516. }
  517. }
  518. else
  519. {
  520. m_wNextBankerUser = (m_wBankerUser + 1) % GAME_PLAY;
  521. //黄庄了
  522. //统计玩家积分,牌值
  523. for (WORD i = 0; i < GAME_PLAY; i++)
  524. {
  525. GameEnd.cbWanJiaScore[i] = m_lGameTatolScore[i];//各玩家积分4…………
  526. m_GameLogic.SwitchToCardData(m_cbCardIndex[i], GameEnd.cbCardData[i]);
  527. }
  528. }
  529. }
  530. else
  531. {
  532. GameEnd.bOptType = 1;
  533. BYTE TempWanJiaCardCount = 0;
  534. m_wNextBankerUser = wChairID;
  535. //统计积分,胡牌得分,玩家牌值
  536. for (WORD i = 0; i < GAME_PLAY; i++)
  537. {
  538. //m_lGameTatolScore[i] += m_lGameScore[i];
  539. GameEnd.cbWanJiaScore[i] = m_lGameTatolScore[i];//各玩家积分3…………
  540. if (i == wChairID)continue;
  541. m_GameLogic.SwitchToCardData(m_cbCardIndex[i], GameEnd.cbCardData[i]);
  542. }
  543. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--)
  544. {
  545. m_GameLogic.SwitchToCardData(m_cbCardIndex[wChairID], GameEnd.cbCardData[wChairID]);
  546. TempWanJiaCardCount = m_GameLogic.GetCardCount(m_cbCardIndex[wChairID]);
  547. GameEnd.cbCardData[wChairID][TempWanJiaCardCount] = m_cbProvideCard;//手牌数据4……
  548. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  549. }
  550. }
  551. GameEnd.bWanJiaId = wChairID;//玩家座位号 5……
  552. GameEnd.bLeftCardCount = m_cbLeftCardCount;//剩余牌输量6…………
  553. CopyMemory(GameEnd.bLeftCardDada, m_cbRepertoryCard, m_cbLeftCardCount);//剩余牌值7………………
  554. CopyMemory(GameEnd.bZimo, m_HuPai, sizeof(m_HuPai));//玩家胡牌次数8…………
  555. GameEnd.dwOwnerID = m_pITableFrame->GetPrivateTableOwnerID();//获取房间ID,9……
  556. GameEnd.playGameNum = m_gameConfig.wHadPlayCount;//得到第几局了,10…………
  557. for (BYTE i = 0; i < GAME_PLAY;i++)
  558. {
  559. m_HuPaiLiuShui[(m_gameConfig.wHadPlayCount-1)*4+i] = m_lGameScore[i];
  560. }
  561. CopyMemory(GameEnd.lGameScoreDetail, m_HuPaiLiuShui, sizeof(m_HuPaiLiuShui));//游戏流水,10…………
  562. //数据处理
  563. int iSendLen = 0;
  564. CMD_S_GameEnd GameEndBuffer;
  565. BYTE *pOutData = (BYTE *)&GameEndBuffer;
  566. BYTE *pInData = (BYTE *)&GameEnd;
  567. ZeroMemory(&GameEndBuffer, sizeof(GameEndBuffer));
  568. CopyMemory(pOutData, &GameEnd, 85);
  569. iSendLen = iSendLen + 85;
  570. pInData = pInData + 85;
  571. pOutData = pOutData + 85;
  572. BYTE *pData = (BYTE *)&GameEnd;
  573. BYTE bNum = GameEnd.bLeftCardCount;
  574. CopyMemory(pOutData, pInData, bNum);
  575. iSendLen = iSendLen + bNum;
  576. pOutData = pOutData + bNum;
  577. pInData = pInData + CountArray(GameEnd.bLeftCardDada);
  578. //pInData = pInData + 54;
  579. bNum = GameEnd.playGameNum;
  580. pOutData[0] = bNum;
  581. pInData++;
  582. pOutData++;
  583. iSendLen = iSendLen + bNum * 4 * GAME_PLAYER + 1;
  584. CopyMemory(pOutData, pInData, bNum * 4 * GAME_PLAYER);
  585. //iSendLen = iSendLen + bNum;
  586. //回放数据
  587. RepayRecord(INVALID_CHAIR, SUB_S_GAME_END, &GameEndBuffer, iSendLen);
  588. //发送结束信息
  589. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEndBuffer, iSendLen);
  590. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEndBuffer, iSendLen);
  591. tagScoreInfo ScoreInfoArray[GAME_PLAY];
  592. ZeroMemory(&ScoreInfoArray, sizeof(ScoreInfoArray));
  593. for (WORD i = 0; i < GAME_PLAY; i++)
  594. {
  595. IServerUserItem *pUserItem = m_pITableFrame->GetTableUserItem(i);
  596. if (NULL == pUserItem) continue;
  597. BYTE ScoreKind;
  598. if (m_lGameScore[i] > 0L) ScoreKind = SCORE_TYPE_WIN;
  599. else if (m_lGameScore[i] < 0L) ScoreKind = SCORE_TYPE_LOSE;
  600. else ScoreKind = SCORE_TYPE_DRAW;
  601. ScoreInfoArray[i].lScore = m_lGameScore[i];
  602. ScoreInfoArray[i].cbType = ScoreKind;
  603. //if (i == wChairID)continue;
  604. //m_GameLogic.SwitchToCardData(m_cbCardIndex[i], GameEnd.cbCardData[i]);
  605. }
  606. m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
  607. ConcludeGame(GS_MJ_FREE);
  608. if (!bDelete)
  609. {
  610. if (bFinish)
  611. {
  612. DeletePrivateTable(true);
  613. }
  614. }
  615. else
  616. {
  617. if (bFinish)
  618. {
  619. DeletePrivateTable(bSendState);
  620. }
  621. }
  622. return true;
  623. }
  624. case GER_DISMISS: //游戏解散
  625. {
  626. //变量定义
  627. CMD_S_GameEnd GameEnd;
  628. ZeroMemory(&GameEnd, sizeof(GameEnd));
  629. GameEnd.bFinish = 1;
  630. GameEnd.bOptType = 3;
  631. CopyMemory(GameEnd.bZimo, m_HuPai, sizeof(m_HuPai));
  632. CopyMemory(GameEnd.cbWanJiaScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  633. GameEnd.dwOwnerID = m_pITableFrame->GetPrivateTableOwnerID();
  634. GameEnd.playGameNum = m_gameConfig.wHadPlayCount;
  635. CopyMemory(GameEnd.lGameScoreDetail, m_HuPaiLiuShui, sizeof(m_HuPaiLiuShui));
  636. //设置变量
  637. //memset(GameEnd.wProvideUser, INVALID_CHAIR, sizeof(GameEnd.wProvideUser));
  638. //拷贝扑克
  639. /*for (WORD i = 0;i < GAME_PLAY;i++)
  640. {
  641. GameEnd.cbCardCount[i] = m_GameLogic.SwitchToCardData(m_cbCardIndex[i], GameEnd.cbCardData[i]);
  642. }*/
  643. //CopyMemory(GameEnd.lUserTmpScore, m_lUserTmpScore, sizeof(m_lUserTmpScore));
  644. RepayRecord(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd));
  645. //发送信息
  646. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd));
  647. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd));
  648. ConcludeGame(GS_MJ_FREE);
  649. return true;
  650. }
  651. case GER_NETWORK_ERROR: //网络错误
  652. case GER_USER_LEAVE: //用户强退
  653. {
  654. DWORD dwUserID = pIServerUserItem->GetUserID();
  655. m_offlineUsers.push_back(dwUserID);
  656. return true;
  657. ////变量定义
  658. //CMD_S_GameEnd GameEnd;
  659. //ZeroMemory(&GameEnd,sizeof(GameEnd));
  660. //GameEnd.wLeftUser = wChairID;
  661. ////结束信息
  662. //for (WORD i=0;i<GAME_PLAY;i++)
  663. //{
  664. // GameEnd.cbCardCount[i]=m_GameLogic.SwitchToCardData(m_cbCardIndex[i],GameEnd.cbCardData[i]);
  665. //
  666. // auto ChiHuRightList = m_ChiHuRight[i];
  667. // tagChihuList& chihuList = GameEnd.ChiHuRight[i];
  668. // chihuList.chihuCount = ChiHuRightList.size();
  669. // if (chihuList.chihuCount > 10)
  670. // chihuList.chihuCount = 10;
  671. // for (int j = 0; j < chihuList.chihuCount;j++)
  672. // {
  673. // ChiHuRightList[j].chr.GetRightData(&chihuList.chihuRightData[j], MAX_RIGHT_COUNT);
  674. // chihuList.chihuCardData[j] = ChiHuRightList[j].cbChihuCard;
  675. // chihuList.wProvideUser[j] = ChiHuRightList[j].wProvideUser;
  676. // }
  677. // //m_ChiHuRight[i].GetRightData( &GameEnd.dwChiHuRight[i],MAX_RIGHT_COUNT );
  678. //}
  679. //LONGLONG lGangScore[GAME_PLAY];
  680. //ZeroMemory( lGangScore,sizeof(lGangScore) );
  681. //////扣分,逃跑者垫付所有刮风下雨的钱,并扣16倍点数*未胡牌玩家.
  682. //for( WORD i = 0; i < GAME_PLAY; i++ )
  683. //{
  684. // for( BYTE j = 0; j < m_GangScore[i].cbGangCount; j++ )
  685. // {
  686. // for( WORD k = 0; k < GAME_PLAY; k++ )
  687. // {
  688. // if( m_GangScore[i].lScore[j][k] < 0 )
  689. // lGangScore[wChairID] += m_GangScore[i].lScore[j][k];
  690. // else if( k != wChairID )
  691. // lGangScore[k] += m_GangScore[i].lScore[j][k];
  692. // }
  693. // }
  694. //}
  695. //m_bPlayStatus[wChairID] = false;
  696. //for( WORD i = 0; i < GAME_PLAY; i++ )
  697. //{
  698. // if( m_bPlayStatus[i] )
  699. // {
  700. // m_lGameScore[i] += 16L*m_pGameServiceOption->lCellScore;
  701. // m_lGameScore[wChairID] -= 16L*m_pGameServiceOption->lCellScore;
  702. // }
  703. // m_lGameScore[i] += lGangScore[i];
  704. //}
  705. //tagScoreInfo ScoreInfoArray[GAME_PLAY];
  706. //ZeroMemory(&ScoreInfoArray,sizeof(ScoreInfoArray));
  707. ////统计积分
  708. //for (WORD i=0;i<GAME_PLAY;i++)
  709. //{
  710. // if( NULL == m_pITableFrame->GetTableUserItem(i) ) continue;
  711. // //设置积分
  712. // LONG lGameTax = 0L;
  713. // if( GAME_GENRE_SCORE != m_pGameServiceOption->wServerType )
  714. // {
  715. // if (m_lGameScore[i]>0L)
  716. // {
  717. // lGameTax = m_pITableFrame->CalculateRevenue(i,m_lGameScore[i]);
  718. // m_lGameScore[i] -= lGameTax;
  719. // }
  720. // else
  721. // {
  722. // //防止负分
  723. // IServerUserItem *pUserItem = m_pITableFrame->GetTableUserItem(i);
  724. // if( GAME_GENRE_SCORE!=m_pGameServiceOption->wServerType && -m_lGameScore[i] > pUserItem->GetUserScore() )
  725. // m_lGameScore[i] = -pUserItem->GetUserScore();
  726. // }
  727. // }
  728. // BYTE ScoreKind;
  729. // if( i == wChairID ) ScoreKind = SCORE_TYPE_FLEE;
  730. // else if( m_lGameScore[i] > 0L ) ScoreKind = SCORE_TYPE_WIN;
  731. // else if( m_lGameScore[i] < 0L ) ScoreKind = SCORE_TYPE_LOSE;
  732. // else ScoreKind = SCORE_TYPE_DRAW;
  733. // ScoreInfoArray[i].lScore = GameEnd.lGameScore[i];
  734. // ScoreInfoArray[i].lRevenue = m_lGameTax[i];
  735. // ScoreInfoArray[i].cbType = ScoreKind;
  736. //}
  737. ////写入积分
  738. //m_pITableFrame->WriteTableScore(ScoreInfoArray,CountArray(ScoreInfoArray));
  739. //CopyMemory( GameEnd.lGameScore,m_lGameScore,sizeof(m_lGameScore) );
  740. //CopyMemory( GameEnd.lGangScore,lGangScore,sizeof(lGangScore) );
  741. //CopyMemory( GameEnd.wWinOrder,m_wWinOrder,sizeof(m_wWinOrder) );
  742. //CopyMemory( GameEnd.wProvideUser,m_wProvider,sizeof(m_wProvider) );
  743. //CopyMemory( GameEnd.wLostFanShu,m_wLostFanShu,sizeof(m_wLostFanShu) );
  744. //RepayRecord(INVALID_CHAIR, SUB_S_GAME_END, &GameEnd, sizeof(GameEnd));
  745. ////发送结束信息
  746. //m_pITableFrame->SendTableData( INVALID_CHAIR,SUB_S_GAME_END,&GameEnd,sizeof(GameEnd) );
  747. //m_pITableFrame->SendLookonData( INVALID_CHAIR,SUB_S_GAME_END,&GameEnd,sizeof(GameEnd) );
  748. ////结束游戏
  749. //ConcludeGame(GS_MJ_FREE);
  750. //return true;
  751. }
  752. }
  753. //错误断言
  754. ASSERT(FALSE);
  755. return false;
  756. }
  757. //发送场景 断线重连
  758. bool TableFrameSinkCxz::OnEventSendGameScene(WORD wChiarID, IServerUserItem * pIServerUserItem, BYTE cbGameStatus, bool bSendSecret)
  759. {
  760. switch (cbGameStatus)
  761. {
  762. case GS_MJ_FREE: //空闲状态
  763. {
  764. //变量定义
  765. CMD_S_StatusFree StatusFree;
  766. memset(&StatusFree,0,sizeof(StatusFree));
  767. //游戏房主基础配置
  768. CopyMemory(&StatusFree.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig));
  769. for (int i = 0; i < GAME_PLAY; i++)
  770. {
  771. StatusFree.lUserTmpScore[i] = (INT)m_lGameTatolScore[i];
  772. }
  773. StatusFree.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  774. //构造数据
  775. StatusFree.UserStat = pIServerUserItem->GetUserInfo()->cbUserStatus;
  776. //发送场景
  777. return m_pITableFrame->SendGameScene(pIServerUserItem,&StatusFree,sizeof(StatusFree));
  778. }
  779. case GS_MJ_PLAY: //游戏状态
  780. {
  781. //变量定义
  782. CMD_S_StatusPlay StatusPlay;
  783. memset(&StatusPlay,0,sizeof(StatusPlay));
  784. //游戏房主基础配置
  785. CopyMemory(&StatusPlay.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig));
  786. CopyMemory(StatusPlay.lUserTmpScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  787. StatusPlay.cbTotalCardCount = MAX_REPERTORY_SRLF;
  788. StatusPlay.cbLeftCardCount = m_cbLeftCardCount;
  789. StatusPlay.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  790. //游戏变量
  791. StatusPlay.wBankerUser=m_wBankerUser;
  792. WORD wSice = WORD(m_lSiceCount & 0xffff);
  793. StatusPlay.lSiZi[0] = HIBYTE(wSice);
  794. StatusPlay.lSiZi[1] = LOBYTE(wSice);
  795. StatusPlay.lSiZi[2] = m_cbLaiZiPiData;
  796. StatusPlay.lSiZi[3] = m_cbLaiZiData;
  797. StatusPlay.dwOwnerID = m_pITableFrame->GetPrivateTableOwnerID();
  798. CopyMemory(StatusPlay.bWanLaiZi, m_OutLaiZi, sizeof(m_OutLaiZi));
  799. CopyMemory(StatusPlay.cbDiscardCard, m_cbDiscardCard, sizeof(m_cbDiscardCard));
  800. CopyMemory(StatusPlay.cbDiscardCount, m_cbDiscardCount, sizeof(m_cbDiscardCount));
  801. StatusPlay.totalOptTime = 10;
  802. StatusPlay.leftOptTime = 0;
  803. //当前到谁家
  804. StatusPlay.wCurrentUser = (m_wCurrentUser == INVALID_CHAIR ? m_wProvideUser : m_wCurrentUser);
  805. BYTE OldUser = 0;//定义一个最后出牌用户
  806. if (m_wProvideUser == m_wCurrentUser&&m_wOutCardUser == INVALID_CHAIR)//牌权是摸牌得且没出牌
  807. {
  808. if (m_wProvideUser == 0)
  809. {
  810. OldUser = 2;
  811. }
  812. else
  813. OldUser = m_wProvideUser - 1;
  814. BYTE TempIndex;
  815. for (BYTE i = 0; i < 55; i++)
  816. {
  817. if (m_cbDiscardCard[OldUser][i] == 0)
  818. {
  819. TempIndex = i - 1;
  820. break;
  821. }
  822. }
  823. if (OldUser>3 || TempIndex == 255)
  824. {
  825. OldUser = 0;
  826. TempIndex = 0;
  827. }
  828. StatusPlay.bPutCardData[OldUser] = m_cbDiscardCard[OldUser][TempIndex];
  829. }
  830. //if (m_wProvideUser != m_wCurrentUser&&m_wOutCardUser == INVALID_CHAIR)//牌权是碰来得且没出牌
  831. //{
  832. //OldUser = m_wProvideUser;
  833. //StatusPlay.bPutCardData[OldUser] = m_cbProvideCard;
  834. //}
  835. if (m_wProvideUser == m_wOutCardUser&& m_wCurrentUser == INVALID_CHAIR)//当有人可以碰且没有碰时候
  836. {
  837. OldUser = m_wProvideUser;
  838. StatusPlay.bPutCardData[OldUser] = m_cbProvideCard;
  839. StatusPlay.cbDiscardCard[OldUser][StatusPlay.cbDiscardCount[OldUser]++] = m_cbProvideCard;
  840. }
  841. for (BYTE i = 0; i < GAME_PLAY; i++)
  842. {
  843. StatusPlay.cbCardCount[i] = m_GameLogic.GetCardCount(m_cbCardIndex[i]);
  844. }
  845. //CopyMemory(StatusPlay.cbCardData, m_cbCardIndex[wChiarID], sizeof(StatusPlay.cbCardData));
  846. m_GameLogic.SwitchToCardData(m_cbCardIndex[wChiarID], StatusPlay.cbCardData);
  847. StatusPlay.bOutCardCout = m_TabbOutCardCout[wChiarID]; //可以打出的牌就听牌的个数
  848. CopyMemory(StatusPlay.bOutCardData, m_TabbOutCardData[wChiarID], sizeof(m_TabbOutCardData[wChiarID])); //具体打哪几张牌
  849. CopyMemory(StatusPlay.bTingCardCount, m_TabbTingCardCount[wChiarID], sizeof(m_TabbTingCardCount[wChiarID]));//相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  850. CopyMemory(StatusPlay.bTingCardData, m_TabbTingCardData[wChiarID], sizeof(m_TabbTingCardData[wChiarID])); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  851. if (wChiarID != StatusPlay.wCurrentUser&&m_wCurrentUser == INVALID_CHAIR) //表示当前牌权就在断线玩家手里,且是轮到他碰或者杠
  852. {
  853. StatusPlay.cbActionMask = m_cbUserAction[wChiarID]; //需要用到操作码
  854. }
  855. /*if (wChiarID == StatusPlay.wCurrentUser&&m_wCurrentUser == INVALID_CHAIR)
  856. {
  857. }*/
  858. if (wChiarID == StatusPlay.wCurrentUser&&m_wCurrentUser != INVALID_CHAIR&&m_wCurrentUser != m_wProvideUser)////表示当前牌权就在断线玩家手里,且是轮到他出牌(牌权碰来得)
  859. {
  860. ZeroMemory(StatusPlay.cbCardData, sizeof(StatusPlay.cbCardData));
  861. StatusPlay.cbActionMask = m_cbUserAction[wChiarID]; //需要用到操作码
  862. BYTE TempIndex = 0;
  863. if (m_cbUserAction[wChiarID] & WIK_AN_PIGANG)//|| m_cbUserAction[wChiarID] & WIK_MING_PIGANG)
  864. {
  865. StatusPlay.gangCards[TempIndex++] = m_cbLaiZiPiData;
  866. }
  867. if (m_cbUserAction[wChiarID] & WIK_AN_GANG)
  868. {
  869. for (BYTE i = 0; i < MAX_INDEX;i++)
  870. {
  871. if (m_cbCardIndex[wChiarID][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  872. {
  873. StatusPlay.gangCards[TempIndex++] = m_GameLogic.SwitchToCardData(i);
  874. if (TempIndex == 3)
  875. break;
  876. }
  877. }
  878. }
  879. BYTE TempCardData[MAX_INDEX];
  880. CopyMemory(TempCardData, m_cbCardIndex[wChiarID], sizeof(TempCardData));
  881. BYTE TempCardIndex = 0;
  882. for (int i = MAX_INDEX - 1; i >= 0; i--)//手牌里面获取最后一张牌,
  883. {
  884. if (TempCardData[i] > 0 && m_GameLogic.SwitchToCardData(i) != m_cbLaiZiData)
  885. {
  886. TempCardIndex = i;
  887. break;
  888. }
  889. }
  890. if (TempCardData[TempCardIndex] == 0)ASSERT(false);
  891. TempCardData[TempCardIndex]--;
  892. m_GameLogic.SwitchToCardData(TempCardData, StatusPlay.cbCardData);
  893. BYTE cardNum = m_GameLogic.GetCardCount(TempCardData);
  894. StatusPlay.cbCardData[cardNum] = m_GameLogic.SwitchToCardData(TempCardIndex);//处理得到最后一张牌数据放最后
  895. }
  896. if (wChiarID == StatusPlay.wCurrentUser&&m_wCurrentUser != INVALID_CHAIR&&m_wCurrentUser == m_wProvideUser)//牌权是轮到他抓牌,未打出
  897. {
  898. ZeroMemory(StatusPlay.cbCardData, sizeof(StatusPlay.cbCardData));
  899. StatusPlay.cbActionMask = m_cbUserAction[wChiarID]; //需要用到操作码
  900. BYTE TempIndex = 0;
  901. if (m_cbUserAction[wChiarID] & WIK_AN_PIGANG)//|| m_cbUserAction[wChiarID] & WIK_MING_PIGANG)
  902. {
  903. StatusPlay.gangCards[TempIndex++] = m_cbLaiZiPiData;
  904. }
  905. if (m_cbUserAction[wChiarID] & WIK_AN_GANG)
  906. {
  907. for (BYTE i = 0; i < MAX_INDEX; i++)
  908. {
  909. if (m_cbCardIndex[wChiarID][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  910. {
  911. StatusPlay.gangCards[TempIndex++] = m_GameLogic.SwitchToCardData(i);
  912. if (TempIndex == 3)
  913. break;
  914. }
  915. }
  916. }
  917. /*if (m_cbUserAction[wChiarID] & WIK_MING_GANG)
  918. {
  919. for (BYTE i = 0; i < MAX_INDEX; i++)
  920. {
  921. if (m_cbCardIndex[wChiarID][i] == 3 && m_cbProvideCard == m_GameLogic.SwitchToCardData(i))
  922. {
  923. StatusPlay.gangCards[TempIndex++] = m_GameLogic.SwitchToCardData(i);
  924. break;
  925. }
  926. }
  927. }
  928. if (m_cbUserAction[wChiarID] & WIK_BU_GANG)
  929. {
  930. for (BYTE i = 0; i < m_cbWeaveItemCount[wChiarID]; i++)
  931. {
  932. if (m_WeaveItemArray[wChiarID][i].cbCenterCard == m_cbProvideCard&&m_WeaveItemArray[wChiarID][i].cbWeaveKind == WIK_PENG)
  933. {
  934. StatusPlay.gangCards[TempIndex++] = m_cbProvideCard;
  935. break;
  936. }
  937. }
  938. }*/
  939. BYTE TempCardData[MAX_INDEX];
  940. CopyMemory(TempCardData, m_cbCardIndex[wChiarID], sizeof(TempCardData));
  941. BYTE TempCardIndex = m_GameLogic.SwitchToCardIndex(m_cbProvideCard);
  942. if (m_cbCardIndex[wChiarID][TempCardIndex] == 0)ASSERT(false);
  943. TempCardData[TempCardIndex]--;
  944. m_GameLogic.SwitchToCardData(TempCardData, StatusPlay.cbCardData);
  945. BYTE cardNum = m_GameLogic.GetCardCount(TempCardData);
  946. StatusPlay.cbCardData[cardNum] = m_GameLogic.SwitchToCardData(TempCardIndex);//处理得到最后一张牌数据放最后
  947. }
  948. //组合扑克
  949. CopyMemory(StatusPlay.WeaveItemArray,m_WeaveItemArray,sizeof(m_WeaveItemArray));
  950. CopyMemory(StatusPlay.cbWeaveCount,m_cbWeaveItemCount,sizeof(m_cbWeaveItemCount));
  951. //扑克数据
  952. //StatusPlay.cbSendCardData=((m_cbSendCardData!=0)&&(m_wProvideUser==wChiarID))?m_cbSendCardData:0x00;
  953. //发送场景
  954. return m_pITableFrame->SendGameScene(pIServerUserItem,&StatusPlay,sizeof(StatusPlay));
  955. }
  956. }
  957. return false;
  958. }
  959. //定时器事件
  960. bool TableFrameSinkCxz::OnTimerMessage(DWORD wTimerID, WPARAM wBindParam)
  961. {
  962. return false;
  963. }
  964. //游戏消息处理
  965. void TableFrameSinkCxz::SetGameConfig(VOID * pDataBuffer, WORD wDataSize, std::wstring sPrivateRoomId)
  966. {
  967. tagGameConfig* ppConfig = (tagGameConfig*)pDataBuffer;
  968. m_gameConfig.wSubGameID = ppConfig->wSubGameID;
  969. m_gameConfig.wDiScore = ppConfig->wPlayRule;
  970. m_gameConfig.wFanFei = ppConfig->wMaxFanRule;
  971. m_gameConfig.wIpLimit = ppConfig->wMaxScore;
  972. m_gameConfig.wPlayCountRule = ppConfig->wPlayCountRule;
  973. m_gameConfig.RoomId = ppConfig->wHadPlayCount;
  974. m_gameConfig.wHadPlayCount = 0;
  975. lstrcpy(m_gameConfig.sPrivateTableID, sPrivateRoomId.c_str());
  976. bGameType = m_gameConfig.wSubGameID;
  977. m_pITableFrame->SetChairCount(GAME_PLAY);
  978. ASSERT(m_gameConfig.wSubGameID >= 0 && m_gameConfig.wSubGameID < MahJongType::count);
  979. }
  980. //游戏消息处理
  981. bool TableFrameSinkCxz::OnGameMessage(WORD wSubCmdID, VOID* pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem)
  982. {
  983. switch (wSubCmdID)
  984. {
  985. case SUB_C_OUT_CARD: //出牌消息
  986. {
  987. //效验消息
  988. ASSERT(wDataSize == sizeof(CMD_C_OutCard));
  989. if (wDataSize != sizeof(CMD_C_OutCard)) return false;
  990. //用户效验
  991. if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true;
  992. //消息处理
  993. CMD_C_OutCard * pOutCard = (CMD_C_OutCard *)pDataBuffer;
  994. return OnUserOutCard(pIServerUserItem->GetChairID(), pOutCard->cbCardData);
  995. }
  996. case SUB_C_OPERATE_CARD: //操作消息
  997. {
  998. //效验消息
  999. ASSERT(wDataSize == sizeof(CMD_C_OperateCard));
  1000. if (wDataSize != sizeof(CMD_C_OperateCard)) return false;
  1001. //用户效验
  1002. if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true;
  1003. //消息处理
  1004. CMD_C_OperateCard * pOperateCard = (CMD_C_OperateCard *)pDataBuffer;
  1005. return OnUserOperateCard(pIServerUserItem->GetChairID(), pOperateCard->cbOperateCode, pOperateCard->cbOperateCard);
  1006. }
  1007. case SUB_C_TRUSTEE:
  1008. {
  1009. CMD_C_Trustee *pTrustee = (CMD_C_Trustee *)pDataBuffer;
  1010. if (wDataSize != sizeof(CMD_C_Trustee)) return false;
  1011. m_bTrustee[pIServerUserItem->GetChairID()] = pTrustee->bTrustee;
  1012. CMD_S_Trustee Trustee;
  1013. Trustee.bTrustee = pTrustee->bTrustee;
  1014. Trustee.wChairID = pIServerUserItem->GetChairID();
  1015. RepayRecord(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee));
  1016. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee));
  1017. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee));
  1018. return true;
  1019. }
  1020. return false;
  1021. }
  1022. return false;
  1023. }
  1024. //框架消息处理
  1025. bool TableFrameSinkCxz::OnFrameMessage(WORD wSubCmdID, VOID * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem)
  1026. {
  1027. return false;
  1028. }
  1029. //用户断线重连
  1030. bool TableFrameSinkCxz::OnActionUserConnect(WORD wChairID, IServerUserItem * pIServerUserItem)
  1031. {
  1032. auto dwUserID = pIServerUserItem->GetUserID();
  1033. auto iter = std::find(m_offlineUsers.begin(), m_offlineUsers.end(), dwUserID);
  1034. if (iter != end(m_offlineUsers))
  1035. {
  1036. m_offlineUsers.erase(iter); //玩家重新上线
  1037. return true;
  1038. }
  1039. return true;
  1040. }
  1041. //用户坐下
  1042. bool TableFrameSinkCxz::OnActionUserSitDown(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  1043. {
  1044. return true;
  1045. }
  1046. //游戏中途旁观进入
  1047. bool TableFrameSinkCxz::PerformLookonLogin(IServerUserItem * pIServerUserItem)
  1048. {
  1049. CMD_S_PangGuan StatusPlay;
  1050. memset(&StatusPlay, 0, sizeof(StatusPlay));
  1051. //游戏房主基础配置
  1052. CopyMemory(&StatusPlay.gameConfig, &m_gameConfig, sizeof(CMD_S_GameConfig));
  1053. CopyMemory(StatusPlay.lUserTmpScore, m_lGameTatolScore, sizeof(m_lGameTatolScore));
  1054. StatusPlay.cbTotalCardCount = MAX_REPERTORY_SRLF;
  1055. StatusPlay.cbLeftCardCount = m_cbLeftCardCount;
  1056. StatusPlay.gameConfig.IsOwner = m_pITableFrame->GetPrivateTableOwnerID() == pIServerUserItem->GetUserID() ? 1 : 0;
  1057. StatusPlay.GameStatus = m_pITableFrame->IsDrawStarted();
  1058. if (StatusPlay.GameStatus)
  1059. {
  1060. //游戏变量
  1061. StatusPlay.wBankerUser = m_wBankerUser;
  1062. WORD wSice = WORD(m_lSiceCount & 0xffff);
  1063. StatusPlay.lSiZi[0] = HIBYTE(wSice);
  1064. StatusPlay.lSiZi[1] = LOBYTE(wSice);
  1065. StatusPlay.lSiZi[2] = m_cbLaiZiPiData;
  1066. StatusPlay.lSiZi[3] = m_cbLaiZiData;
  1067. StatusPlay.dwOwnerID = m_pITableFrame->GetPrivateTableOwnerID();
  1068. CopyMemory(StatusPlay.bWanLaiZi, m_OutLaiZi, sizeof(m_OutLaiZi));
  1069. CopyMemory(StatusPlay.cbDiscardCard, m_cbDiscardCard, sizeof(m_cbDiscardCard));
  1070. CopyMemory(StatusPlay.cbDiscardCount, m_cbDiscardCount, sizeof(m_cbDiscardCount));
  1071. StatusPlay.totalOptTime = 10;
  1072. StatusPlay.leftOptTime = 0;
  1073. //当前到谁家
  1074. StatusPlay.wCurrentUser = (m_wCurrentUser == INVALID_CHAIR ? m_wProvideUser : m_wCurrentUser);
  1075. WORD OldUser = 0;//定义一个最后出牌用户
  1076. if (m_wProvideUser == m_wCurrentUser&&m_wOutCardUser == INVALID_CHAIR)//牌权是摸牌得且没出牌
  1077. {
  1078. if (m_wProvideUser == 0)
  1079. {
  1080. OldUser = 2;
  1081. }
  1082. else
  1083. OldUser = m_wProvideUser - 1;
  1084. BYTE TempIndex;
  1085. for (BYTE i = 0; i < 55; i++)
  1086. {
  1087. if (m_cbDiscardCard[OldUser][i] == 0)
  1088. {
  1089. TempIndex = i - 1;
  1090. break;
  1091. }
  1092. }
  1093. if (OldUser>3 || TempIndex == 255)
  1094. {
  1095. OldUser = 0;
  1096. TempIndex = 0;
  1097. }
  1098. StatusPlay.bPutCardData[OldUser] = m_cbDiscardCard[OldUser][TempIndex];
  1099. }
  1100. if (m_wProvideUser == m_wOutCardUser&& m_wCurrentUser == INVALID_CHAIR)//当有人可以碰且没有碰时候
  1101. {
  1102. OldUser = m_wProvideUser;
  1103. StatusPlay.bPutCardData[OldUser] = m_cbProvideCard;
  1104. StatusPlay.cbDiscardCard[OldUser][StatusPlay.cbDiscardCount[OldUser]++] = m_cbProvideCard;
  1105. }
  1106. for (BYTE i = 0; i < GAME_PLAY; i++)
  1107. {
  1108. StatusPlay.cbCardCount[i] = m_GameLogic.GetCardCount(m_cbCardIndex[i]);
  1109. }
  1110. //组合扑克
  1111. CopyMemory(StatusPlay.WeaveItemArray, m_WeaveItemArray, sizeof(m_WeaveItemArray));
  1112. CopyMemory(StatusPlay.cbWeaveCount, m_cbWeaveItemCount, sizeof(m_cbWeaveItemCount));
  1113. }
  1114. return m_pITableFrame->SendUserItemData(pIServerUserItem, SUB_S_PANGGUAN, &StatusPlay, sizeof(StatusPlay));
  1115. }
  1116. //用户起来
  1117. bool TableFrameSinkCxz::OnActionUserStandUp(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
  1118. {
  1119. //庄家设置
  1120. if (bLookonUser == false && !QueryUseTemporaryScore())
  1121. {
  1122. m_bTrustee[wChairID]=false;
  1123. CMD_S_Trustee Trustee;
  1124. Trustee.bTrustee=false;
  1125. Trustee.wChairID = wChairID;
  1126. RepayRecord(INVALID_CHAIR, SUB_S_TRUSTEE, &Trustee, sizeof(Trustee));
  1127. m_pITableFrame->SendTableData(INVALID_CHAIR,SUB_S_TRUSTEE,&Trustee,sizeof(Trustee));
  1128. m_pITableFrame->SendLookonData(INVALID_CHAIR,SUB_S_TRUSTEE,&Trustee,sizeof(Trustee));
  1129. }
  1130. return true;
  1131. }
  1132. //用户出牌
  1133. bool TableFrameSinkCxz::OnUserOutCard(WORD wChairID, BYTE cbCardData)
  1134. {
  1135. //检查是否可以出牌
  1136. //if (!IsCanOutCard())
  1137. // return true;
  1138. //效验状态
  1139. ASSERT(m_pITableFrame->GetGameStatus()==GS_MJ_PLAY);
  1140. if (m_pITableFrame->GetGameStatus()!=GS_MJ_PLAY) return true;
  1141. //错误断言
  1142. ASSERT(wChairID==m_wCurrentUser);
  1143. ASSERT(m_GameLogic.IsValidCard(cbCardData)==true);
  1144. //效验参数
  1145. if (wChairID!=m_wCurrentUser) return true;
  1146. if (m_GameLogic.IsValidCard(cbCardData)==false) return false;
  1147. if ((m_GameLogic.GetCardCount(m_cbCardIndex[wChairID]) - 2) % 3 != 0)
  1148. {
  1149. return false;
  1150. }
  1151. //删除扑克
  1152. if (m_GameLogic.RemoveCard(m_cbCardIndex[wChairID],cbCardData)==false)
  1153. {
  1154. ASSERT(FALSE);
  1155. return false;
  1156. }
  1157. ZeroMemory(&m_cbLastDisCardData[wChairID], sizeof(m_cbLastDisCardData[wChairID]));
  1158. m_cbLastDisCount[wChairID] = 0;
  1159. for (BYTE i = 0; i < GAME_PLAY; i++)
  1160. {
  1161. if (i == wChairID)continue;
  1162. m_cbLastDisCardData[i][m_cbLastDisCount[i]++] = cbCardData;//打出得牌,放到其他玩家得记忆库里面
  1163. }
  1164. if (cbCardData == m_cbLaiZiData)
  1165. {
  1166. //设置变量
  1167. m_bSendStatus = true;
  1168. if (!m_bGangStatus)
  1169. {
  1170. m_bGangStatus = true;
  1171. m_bGangOutStatus = true;
  1172. }
  1173. m_cbUserAction[wChairID] = WIK_NULL;
  1174. m_cbPerformAction[wChairID] = WIK_NULL;
  1175. //出牌记录
  1176. m_cbOutCardCount++;
  1177. //m_cbDiscardCard[wChairID][m_cbDiscardCount[wChairID]++] = cbCardData;
  1178. //m_cbDiscardWuYongCard[wChairID][m_cbDiscardWuYongCount[wChairID]++] = cbCardData;
  1179. m_wOutCardUser = INVALID_CHAIR; //记录出牌人
  1180. m_cbOutCardData = 0; //记录出牌数据
  1181. //构造数据
  1182. CMD_S_OutCard OutCard;
  1183. OutCard.wOutCardUser = wChairID;
  1184. OutCard.cbOutCardData = cbCardData;
  1185. OutCard.bOptType = 1;//打出的是癞子
  1186. RepayRecord(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1187. //发送消息
  1188. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1189. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1190. m_wProvideUser = wChairID;
  1191. m_cbProvideCard = cbCardData;
  1192. //筹码翻倍,该用户打出的癞子加一
  1193. m_OutLaiZi[wChairID]++;
  1194. //相当于杠牌,摸一张重新出牌
  1195. return DispatchCardData(m_wCurrentUser, true, true);
  1196. }
  1197. else
  1198. {
  1199. //设置变量
  1200. m_bSendStatus = true;
  1201. if (m_bGangStatus)
  1202. {
  1203. m_bGangStatus = false;
  1204. m_bGangOutStatus = true;
  1205. }
  1206. m_cbUserAction[wChairID] = WIK_NULL;
  1207. m_cbPerformAction[wChairID] = WIK_NULL;
  1208. //出牌记录
  1209. m_cbOutCardCount++;
  1210. //m_cbDiscardCard[wChairID][m_cbDiscardCount[wChairID]++] = cbCardData;
  1211. //m_cbDiscardWuYongCard[wChairID][m_cbDiscardWuYongCount[wChairID]++] = cbCardData;
  1212. m_wOutCardUser = wChairID; //记录出牌人
  1213. m_cbOutCardData = cbCardData; //记录出牌数据
  1214. //构造数据
  1215. CMD_S_OutCard OutCard;
  1216. OutCard.wOutCardUser = wChairID;
  1217. OutCard.cbOutCardData = cbCardData;
  1218. OutCard.bOptType = 0;
  1219. m_TabbOutCardCout[wChairID] = 255; //可以打出的牌就听牌的个数
  1220. ZeroMemory(m_TabbOutCardData[wChairID], sizeof(m_TabbOutCardData[wChairID])); //具体打哪几张牌
  1221. ZeroMemory(m_TabbTingCardCount[wChairID], sizeof(m_TabbTingCardCount[wChairID])); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  1222. ZeroMemory(m_TabbTingCardData[wChairID], sizeof(m_TabbTingCardData[wChairID])); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  1223. BYTE TingParCount = 0;
  1224. BYTE TingParData[MAX_INDEX];
  1225. BYTE m_cbTingPai[MAX_INDEX];
  1226. ZeroMemory(TingParData, sizeof(TingParData));
  1227. ZeroMemory(m_cbTingPai, sizeof(m_cbTingPai));
  1228. if (m_GameLogic.IsTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbLaiZiData, bGameType, m_OutLaiZi[wChairID]))//是否听牌状态
  1229. {
  1230. //OutCard.bIsTingPai = m_isTingPai[wChairID];
  1231. if (m_GameLogic.AnalyseTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbTingPai, m_cbLaiZiData, bGameType, m_OutLaiZi[wChairID]))
  1232. {
  1233. for (BYTE i = 0; i < MAX_INDEX; i++)
  1234. {
  1235. if (m_cbTingPai[i] == 1)
  1236. {
  1237. TingParData[TingParCount++] = m_GameLogic.SwitchToCardData(i);
  1238. BYTE num = RemainNum(wChairID, TingParData[TingParCount - 1], m_GameLogic.SwitchToCardIndex(cbCardData));
  1239. TingParData[TingParCount - 1] = m_GameLogic.GetValue(num, TingParData[TingParCount - 1]);
  1240. }
  1241. }
  1242. //OutCard.cbTingCardCount = m_cbTingParCount;
  1243. }
  1244. m_TabbTingCardCount[wChairID][0] = TingParCount;
  1245. CopyMemory(m_TabbTingCardData[wChairID][0], TingParData, sizeof(TingParData));
  1246. }
  1247. RepayRecord(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1248. //发送消息
  1249. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1250. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OUT_CARD, &OutCard, sizeof(OutCard));
  1251. m_wProvideUser = wChairID;
  1252. m_cbProvideCard = cbCardData;
  1253. //用户切换
  1254. m_wCurrentUser = (wChairID + 1) % GAME_PLAY;
  1255. while (!m_bPlayStatus[m_wCurrentUser])
  1256. m_wCurrentUser = (m_wCurrentUser + 1) % GAME_PLAY;
  1257. //响应判断
  1258. bool bAroseAction = EstimateUserRespond(wChairID, cbCardData, EstimatKind_OutCard);
  1259. //派发扑克
  1260. if (bAroseAction == false)
  1261. DispatchCardData(m_wCurrentUser);
  1262. return true;
  1263. }
  1264. }
  1265. //用户操作
  1266. bool TableFrameSinkCxz::OnUserOperateCard(WORD wChairID, int cbOperateCode, BYTE cbOperateCard)
  1267. {
  1268. //效验状态
  1269. ASSERT(m_pITableFrame->GetGameStatus()==GS_MJ_PLAY);
  1270. if (m_pITableFrame->GetGameStatus()!=GS_MJ_PLAY)
  1271. return true;
  1272. if (cbOperateCode == WIK_NULL)
  1273. {
  1274. //用户状态
  1275. ZeroMemory(m_bResponse, sizeof(m_bResponse));
  1276. ZeroMemory(m_cbUserAction, sizeof(m_cbUserAction));
  1277. ZeroMemory(m_cbOperateCard, sizeof(m_cbOperateCard));
  1278. ZeroMemory(m_cbPerformAction, sizeof(m_cbPerformAction));
  1279. //发送扑克
  1280. if (m_wCurrentUser == INVALID_CHAIR)
  1281. DispatchCardData(m_wResumeUser);
  1282. return true;
  1283. }
  1284. //效验用户 注意:机器人有可能发生此断言
  1285. //ASSERT((wChairID==m_wCurrentUser)||(m_wCurrentUser==INVALID_CHAIR));
  1286. if ((wChairID!=m_wCurrentUser)&&(m_wCurrentUser!=INVALID_CHAIR))
  1287. return true;
  1288. int FanKuiAction = WIK_NULL;
  1289. //被动动作
  1290. if (m_wCurrentUser == INVALID_CHAIR&&wChairID != m_wProvideUser)//表示有人出牌后,下一个人还未摸牌这段时间内,有人对上一张出牌有吃胡、杠、碰等操作
  1291. {
  1292. //效验状态
  1293. if (m_bResponse[wChairID] == true)
  1294. return true;
  1295. if ((cbOperateCode != WIK_NULL) && ((m_cbUserAction[wChairID] & cbOperateCode) == 0))
  1296. return true;
  1297. if (cbOperateCard != m_cbProvideCard)
  1298. {
  1299. ASSERT(false);
  1300. return true;
  1301. }
  1302. //变量定义
  1303. WORD wTargetUser = wChairID;
  1304. int cbTargetAction = cbOperateCode;
  1305. //设置变量
  1306. m_bResponse[wChairID] = true;
  1307. m_cbPerformAction[wChairID] = cbOperateCode;
  1308. m_cbOperateCard[wChairID] = m_cbProvideCard;
  1309. //在自己未摸下一张牌的一圈内,不能弃上一家而胡下一家,癞油不可以胡打出来的牌的。
  1310. if (cbTargetAction == WIK_NULL && (WIK_CHI_HU&m_cbUserAction[wTargetUser]) && m_wProvideUser != wTargetUser)
  1311. m_bEnjoinChiHu[wTargetUser] = true;
  1312. //执行动作的优先级判断, WIK_CHI_HU 大于 WIK_GANG 大于 WIK_PENG 大于 [WIK_RIGHT or WIK_CENTER or WIK_LEFT]
  1313. //for (WORD i = 0; i < GAME_PLAY; i++)
  1314. //{
  1315. // //获取动作
  1316. // BYTE cbUserAction = (m_bResponse[i] == false) ? m_cbUserAction[i] : m_cbPerformAction[i];
  1317. // //优先级别
  1318. // BYTE cbUserActionRank = m_GameLogic.GetUserActionRank(cbUserAction);
  1319. // BYTE cbTargetActionRank = m_GameLogic.GetUserActionRank(cbTargetAction);
  1320. // //动作判断
  1321. // if (cbUserActionRank > cbTargetActionRank)
  1322. // {
  1323. // wTargetUser = i;
  1324. // cbTargetAction = cbUserAction;
  1325. // }
  1326. //}
  1327. //if (m_bResponse[wTargetUser] == false)
  1328. // return true;
  1329. //放弃操作
  1330. //变量定义
  1331. BYTE cbTargetCard = cbOperateCard;
  1332. m_cbOperateCard[wTargetUser] = cbTargetCard;
  1333. //出牌变量
  1334. m_cbOutCardData = 0;
  1335. m_bSendStatus = true;
  1336. m_wOutCardUser = INVALID_CHAIR;
  1337. m_bEnjoinChiHu[wTargetUser] = true;
  1338. //用户状态
  1339. ZeroMemory(m_bResponse, sizeof(m_bResponse));
  1340. ZeroMemory(m_cbUserAction, sizeof(m_cbUserAction));
  1341. ZeroMemory(m_cbOperateCard, sizeof(m_cbOperateCard));
  1342. ZeroMemory(m_cbPerformAction, sizeof(m_cbPerformAction));
  1343. //组合扑克
  1344. ASSERT(m_cbWeaveItemCount[wTargetUser] < 4);
  1345. WORD wIndex = m_cbWeaveItemCount[wTargetUser]++;
  1346. m_WeaveItemArray[wTargetUser][wIndex].cbPublicCard = TRUE;
  1347. m_WeaveItemArray[wTargetUser][wIndex].cbCenterCard = cbTargetCard;
  1348. m_WeaveItemArray[wTargetUser][wIndex].cbWeaveKind = cbTargetAction;
  1349. m_WeaveItemArray[wTargetUser][wIndex].wProvideUser = (m_wProvideUser == INVALID_CHAIR) ? wTargetUser : m_wProvideUser;
  1350. //BYTE TempGangType = 0;
  1351. //删除扑克
  1352. switch (cbTargetAction)
  1353. {
  1354. case WIK_PENG: //碰牌操作
  1355. {
  1356. //删除扑克
  1357. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)] < 2)
  1358. {
  1359. return false;
  1360. }
  1361. BYTE cbRemoveCard[] = { cbTargetCard, cbTargetCard };
  1362. VERIFY(m_GameLogic.RemoveCard(m_cbCardIndex[wTargetUser], cbRemoveCard, 2));
  1363. tagGangCardResult GangCardResult;
  1364. FanKuiAction |= m_GameLogic.AnalyseGangCard(m_cbCardIndex[wChairID], m_cbLaiZiData, m_cbLaiZiPiData, m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], GangCardResult);
  1365. break;
  1366. }
  1367. case WIK_MING_GANG: //明杠牌操作
  1368. {
  1369. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)] != 3)
  1370. {
  1371. return false;
  1372. }
  1373. BYTE cbRemoveCard[] = { cbTargetCard, cbTargetCard, cbTargetCard };
  1374. VERIFY(m_GameLogic.RemoveCard(m_cbCardIndex[wTargetUser], cbRemoveCard, CountArray(cbRemoveCard)));
  1375. break;
  1376. }
  1377. case WIK_MING_PIGANG: //明朝天杠牌操作
  1378. {
  1379. //删除扑克,被动动作只存在放杠
  1380. if (cbTargetCard == m_cbLaiZiPiData)
  1381. {
  1382. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)] != 2)
  1383. {
  1384. ASSERT(false);
  1385. return false;
  1386. }
  1387. //删除扑克
  1388. BYTE cbRemoveCard[] = { cbTargetCard, cbTargetCard };
  1389. VERIFY(m_GameLogic.RemoveCard(m_cbCardIndex[wTargetUser], cbRemoveCard, 2));
  1390. tagGangCardResult GangCardResult;
  1391. FanKuiAction |= m_GameLogic.AnalyseGangCard(m_cbCardIndex[wChairID], m_cbLaiZiData, m_cbLaiZiPiData, m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], GangCardResult);
  1392. }
  1393. else false;
  1394. break;
  1395. }
  1396. default:
  1397. ASSERT(FALSE);
  1398. return false;
  1399. }
  1400. //构造结果
  1401. CMD_S_OperateResult OperateResult;
  1402. OperateResult.wOperateUser = wTargetUser;
  1403. OperateResult.cbOperateCard = cbTargetCard;
  1404. OperateResult.cbOperateCode = cbTargetAction;
  1405. OperateResult.wProvideUser = (m_wProvideUser == INVALID_CHAIR) ? wTargetUser : m_wProvideUser;
  1406. OperateResult.bOutCardCout = 0;//能出牌个数
  1407. OperateResult.cbActionMask = WIK_NULL;
  1408. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1409. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  1410. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  1411. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  1412. if (OperateResult.cbOperateCode == WIK_PENG || OperateResult.cbOperateCode == WIK_MING_PIGANG)
  1413. {
  1414. BYTE tempData[MAX_INDEX] = { 0 };
  1415. for (BYTE i = 0; i < MAX_INDEX; i++)
  1416. {
  1417. if (m_cbCardIndex[wChairID][i] == 0)continue;
  1418. BYTE TempLaiZiCount = m_OutLaiZi[wChairID];
  1419. if (m_GameLogic.SwitchToCardData(i) == m_cbLaiZiData)TempLaiZiCount++;
  1420. m_cbCardIndex[wChairID][i]--;
  1421. if (m_GameLogic.IsTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbLaiZiData, bGameType, TempLaiZiCount))
  1422. {
  1423. OperateResult.bOutCardData[OperateResult.bOutCardCout] = m_GameLogic.SwitchToCardData(i);
  1424. BYTE m_cbTingPai[MAX_INDEX] = { 0 };//听牌数组,听哪个牌就把哪个牌设置为1
  1425. BYTE m_cbTingParCount = 0;//听牌数据
  1426. bool BbanlaiTemp = true;
  1427. if (m_GameLogic.AnalyseTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbTingPai, m_cbLaiZiData, bGameType,TempLaiZiCount))
  1428. {
  1429. for (BYTE j = 0; j < MAX_INDEX; j++)
  1430. {
  1431. if (m_cbTingPai[j] == 1)
  1432. {
  1433. BbanlaiTemp = false;
  1434. OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount++] = m_GameLogic.SwitchToCardData(j);
  1435. BYTE num = RemainNum(wChairID, OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1], i);
  1436. OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1] = m_GameLogic.GetValue(num, OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1]);
  1437. }
  1438. }
  1439. OperateResult.bTingCardCount[OperateResult.bOutCardCout] = m_cbTingParCount;
  1440. }
  1441. if ((bGameType == CXZBanLai) && BbanlaiTemp)
  1442. {
  1443. OperateResult.bOutCardData[OperateResult.bOutCardCout] = 0;
  1444. OperateResult.bOutCardCout--;
  1445. }
  1446. OperateResult.bOutCardCout++;
  1447. }
  1448. m_cbCardIndex[wChairID][i]++;
  1449. }
  1450. }
  1451. BYTE TempCount = 0;
  1452. if (FanKuiAction != WIK_NULL)
  1453. {
  1454. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiPiData)]==3)
  1455. {
  1456. OperateResult.cbActionMask |= WIK_AN_PIGANG;
  1457. m_cbUserAction[wChairID] |= WIK_AN_PIGANG;
  1458. OperateResult.cbActionCard[TempCount++] = m_cbLaiZiPiData;
  1459. }
  1460. for (BYTE i = 0; i < MAX_INDEX;i++)
  1461. {
  1462. if (m_cbCardIndex[wChairID][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  1463. {
  1464. OperateResult.cbActionMask |= WIK_AN_GANG;
  1465. m_cbUserAction[wChairID] |= WIK_AN_GANG;
  1466. OperateResult.cbActionCard[TempCount++] = m_GameLogic.SwitchToCardData(i);
  1467. }
  1468. }
  1469. }
  1470. if (OperateResult.bOutCardCout != 0)
  1471. {
  1472. m_TabbOutCardCout[wTargetUser] = 0; //可以打出的牌就听牌的个数
  1473. ZeroMemory(m_TabbOutCardData[wTargetUser], sizeof(m_TabbOutCardData[wTargetUser])); //具体打哪几张牌
  1474. ZeroMemory(m_TabbTingCardCount[wTargetUser], sizeof(m_TabbTingCardCount[wTargetUser])); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  1475. ZeroMemory(m_TabbTingCardData[wTargetUser], sizeof(m_TabbTingCardData[wTargetUser])); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  1476. m_TabbOutCardCout[wTargetUser] = OperateResult.bOutCardCout; //可以打出的牌就听牌的个数
  1477. CopyMemory(m_TabbOutCardData[wTargetUser], OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData)); //具体打哪几张牌
  1478. CopyMemory(m_TabbTingCardCount[wTargetUser], OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount)); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  1479. CopyMemory(m_TabbTingCardData[wTargetUser], OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData)); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  1480. }
  1481. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1482. //发送消息
  1483. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1484. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1485. //设置用户
  1486. m_wCurrentUser = wTargetUser;
  1487. //杠牌处理
  1488. if (cbTargetAction == WIK_MING_GANG || cbTargetAction == WIK_MING_PIGANG)
  1489. {
  1490. //发送信息
  1491. CMD_S_GangScore gs;
  1492. ZeroMemory(&gs, sizeof(gs));
  1493. gs.wChairId = wTargetUser;
  1494. gs.lGangScore[wTargetUser] += m_gameConfig.wDiScore * 2;
  1495. gs.lGangScore[m_wProvideUser] -= m_gameConfig.wDiScore * 2;
  1496. gs.cbOperateCode = cbTargetAction;
  1497. m_lGameScore[wTargetUser] += gs.lGangScore[wTargetUser];
  1498. m_lGameScore[m_wProvideUser] += gs.lGangScore[m_wProvideUser];
  1499. m_lGameTatolScore[wTargetUser] += gs.lGangScore[wTargetUser];
  1500. m_lGameTatolScore[m_wProvideUser] += gs.lGangScore[m_wProvideUser];
  1501. gs.cbWanJiaScore[wTargetUser] = m_lGameTatolScore[wTargetUser];
  1502. gs.cbWanJiaScore[m_wProvideUser] = m_lGameTatolScore[m_wProvideUser];
  1503. for (BYTE i = 0; i < GAME_PLAY;i++)
  1504. {
  1505. if (i == m_wProvideUser || i == wTargetUser)continue;
  1506. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  1507. }
  1508. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1509. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1510. for (BYTE i = 0; i < GAME_PLAY; i++)
  1511. {
  1512. gs.cbWanJiaScore[i] = m_lGameScore[i];
  1513. }
  1514. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1515. //杠得分 //送杠者扣2倍积分
  1516. //BYTE cbIndex = m_GangScore[wTargetUser].cbGangCount++;
  1517. ////这里需要及时算分
  1518. //m_GangScore[wTargetUser].lScore[cbIndex][wTargetUser] += m_pGameServiceOption->lCellScore * 3;
  1519. //m_GangScore[wTargetUser].lScore[cbIndex][m_wProvideUser] += -m_pGameServiceOption->lCellScore * 3;
  1520. m_bGangStatus = false;
  1521. m_wDianGangUser = m_wProvideUser;
  1522. if ((cbTargetCard != m_cbLaiZiPiData) && cbTargetAction == WIK_MING_GANG)
  1523. {
  1524. DispatchCardData(wTargetUser, true);
  1525. }
  1526. }
  1527. return true;
  1528. }
  1529. //主动动作
  1530. if (m_wCurrentUser==wChairID) //如果是摸牌用户的操作,比如自摸或者自杠
  1531. {
  1532. //效验操作
  1533. if ((cbOperateCode==WIK_NULL)||((m_cbUserAction[wChairID]&cbOperateCode)==0))
  1534. return true;
  1535. //设置变量
  1536. m_bSendStatus=true;
  1537. m_bEnjoinChiHu[m_wCurrentUser]=true;
  1538. m_cbUserAction[m_wCurrentUser]=WIK_NULL;
  1539. m_cbPerformAction[m_wCurrentUser]=WIK_NULL;
  1540. bool bPublic=false;
  1541. //执行动作
  1542. switch (cbOperateCode)
  1543. {
  1544. case WIK_AN_GANG: //暗杠牌操作
  1545. {
  1546. //扑克效验
  1547. ASSERT((cbOperateCode == WIK_NULL) || (cbOperateCode == WIK_ZI_MO) || (m_GameLogic.IsValidCard(cbOperateCard) == true));
  1548. if ((cbOperateCode != WIK_NULL) && (cbOperateCode != WIK_CHI_HU) && (m_GameLogic.IsValidCard(cbOperateCard) == false))
  1549. return false;
  1550. //变量定义
  1551. BYTE cbWeaveIndex = 0xFF;
  1552. BYTE cbCardIndex = m_GameLogic.SwitchToCardIndex(cbOperateCard);
  1553. //杠牌处理
  1554. if (m_cbCardIndex[wChairID][cbCardIndex] == 4 && m_GameLogic.SwitchToCardData(cbCardIndex) != m_cbLaiZiPiData)
  1555. {
  1556. //扑克效验
  1557. ASSERT(m_cbCardIndex[wChairID][cbCardIndex] == 4);
  1558. if (m_cbCardIndex[wChairID][cbCardIndex] != 4)
  1559. return false;
  1560. //设置变量
  1561. bPublic = false;
  1562. cbWeaveIndex = m_cbWeaveItemCount[wChairID]++;
  1563. m_WeaveItemArray[wChairID][cbWeaveIndex].cbPublicCard = FALSE;
  1564. m_WeaveItemArray[wChairID][cbWeaveIndex].wProvideUser = wChairID;
  1565. m_WeaveItemArray[wChairID][cbWeaveIndex].cbWeaveKind = cbOperateCode;
  1566. m_WeaveItemArray[wChairID][cbWeaveIndex].cbCenterCard = cbOperateCard;
  1567. }
  1568. else return false;
  1569. //删除扑克
  1570. m_cbCardIndex[wChairID][cbCardIndex] = 0;
  1571. m_wDianGangUser = wChairID;
  1572. //构造结果
  1573. CMD_S_OperateResult OperateResult;
  1574. OperateResult.wOperateUser = wChairID;
  1575. OperateResult.wProvideUser = wChairID;
  1576. OperateResult.cbOperateCode = cbOperateCode;
  1577. OperateResult.cbOperateCard = cbOperateCard;
  1578. OperateResult.bOutCardCout = 0;//能出牌个数
  1579. OperateResult.cbActionMask = WIK_NULL;
  1580. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1581. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  1582. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  1583. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  1584. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1585. //发送消息
  1586. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1587. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1588. //发送信息
  1589. CMD_S_GangScore gs;
  1590. ZeroMemory(&gs, sizeof(gs));
  1591. //杠牌得分
  1592. int lScore = 0;
  1593. gs.wChairId = wChairID;
  1594. gs.cbOperateCode = WIK_AN_GANG;
  1595. for (WORD i = 0; i < GAME_PLAY; i++)
  1596. {
  1597. if (!m_bPlayStatus[i] || i == wChairID) continue;
  1598. gs.lGangScore[i] -= m_gameConfig.wDiScore * 2;
  1599. m_lGameScore[i] += gs.lGangScore[i];
  1600. m_lGameTatolScore[i] += gs.lGangScore[i];
  1601. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  1602. lScore -= gs.lGangScore[i];
  1603. }
  1604. gs.lGangScore[wChairID] = lScore;
  1605. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  1606. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  1607. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  1608. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1609. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1610. for (BYTE i = 0; i < GAME_PLAY; i++)
  1611. {
  1612. gs.cbWanJiaScore[i] = m_lGameScore[i];
  1613. }
  1614. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1615. DispatchCardData(wChairID, true);
  1616. return true;
  1617. }
  1618. case WIK_BU_GANG:
  1619. {
  1620. //扑克效验
  1621. ASSERT((cbOperateCode == WIK_NULL) || (cbOperateCode == WIK_ZI_MO) || (m_GameLogic.IsValidCard(cbOperateCard) == true));
  1622. if ((cbOperateCode != WIK_NULL) && (cbOperateCode != WIK_CHI_HU) && (m_GameLogic.IsValidCard(cbOperateCard) == false))
  1623. return false;
  1624. BYTE cbWeaveIndex = 0xFF;
  1625. BYTE cbCardIndex = m_GameLogic.SwitchToCardIndex(m_cbProvideCard);
  1626. //杠牌处理
  1627. if (m_cbCardIndex[wChairID][cbCardIndex] == 1)//表示续杠类型
  1628. {
  1629. //寻找组合
  1630. for (BYTE i = 0; i < m_cbWeaveItemCount[wChairID]; i++)
  1631. {
  1632. BYTE cbWeaveKind = m_WeaveItemArray[wChairID][i].cbWeaveKind;
  1633. BYTE cbCenterCard = m_WeaveItemArray[wChairID][i].cbCenterCard;
  1634. if ((cbCenterCard == m_cbProvideCard) && (cbWeaveKind == WIK_PENG))
  1635. {
  1636. bPublic = true;
  1637. cbWeaveIndex = i;
  1638. break;
  1639. }
  1640. }
  1641. //效验动作
  1642. ASSERT(cbWeaveIndex != 0xFF);
  1643. if (cbWeaveIndex == 0xFF) return false;
  1644. //组合扑克
  1645. m_WeaveItemArray[wChairID][cbWeaveIndex].cbPublicCard = TRUE;
  1646. m_WeaveItemArray[wChairID][cbWeaveIndex].wProvideUser = wChairID;
  1647. m_WeaveItemArray[wChairID][cbWeaveIndex].cbWeaveKind = cbOperateCode;
  1648. m_WeaveItemArray[wChairID][cbWeaveIndex].cbCenterCard = m_cbProvideCard;
  1649. }
  1650. else return false;
  1651. //删除扑克
  1652. m_cbCardIndex[wChairID][cbCardIndex] = 0;
  1653. m_wDianGangUser = wChairID;
  1654. //构造结果
  1655. CMD_S_OperateResult OperateResult;
  1656. OperateResult.wOperateUser = wChairID;
  1657. OperateResult.wProvideUser = wChairID;
  1658. OperateResult.cbOperateCode = cbOperateCode;
  1659. OperateResult.cbOperateCard = m_cbProvideCard;
  1660. OperateResult.bOutCardCout = 0;//能出牌个数
  1661. OperateResult.cbActionMask = WIK_NULL;
  1662. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1663. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  1664. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  1665. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  1666. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1667. //发送消息
  1668. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1669. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1670. //发送信息
  1671. CMD_S_GangScore gs;
  1672. ZeroMemory(&gs, sizeof(gs));
  1673. gs.wChairId = wChairID;
  1674. //杠牌得分
  1675. int lScore = 0;
  1676. gs.cbOperateCode = WIK_BU_GANG;
  1677. for (WORD i = 0; i < GAME_PLAY; i++)
  1678. {
  1679. if (!m_bPlayStatus[i] || i == wChairID) continue;
  1680. gs.lGangScore[i] -= m_gameConfig.wDiScore;
  1681. m_lGameScore[i] += gs.lGangScore[i];
  1682. m_lGameTatolScore[i] += gs.lGangScore[i];
  1683. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  1684. lScore -= gs.lGangScore[i];
  1685. }
  1686. gs.lGangScore[wChairID] = lScore;
  1687. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  1688. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  1689. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  1690. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1691. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1692. for (BYTE i = 0; i < GAME_PLAY; i++)
  1693. {
  1694. gs.cbWanJiaScore[i] = m_lGameScore[i];
  1695. }
  1696. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1697. DispatchCardData(wChairID, true);
  1698. return true;
  1699. }
  1700. case WIK_AN_PIGANG:
  1701. {
  1702. //扑克效验
  1703. ASSERT((cbOperateCode == WIK_NULL) || (cbOperateCode == WIK_ZI_MO) || (m_GameLogic.IsValidCard(cbOperateCard) == true));
  1704. if ((cbOperateCode != WIK_NULL) && (cbOperateCode != WIK_CHI_HU) && (m_GameLogic.IsValidCard(cbOperateCard) == false))
  1705. return false;
  1706. BYTE cbWeaveIndex = 0xFF;
  1707. BYTE cbCardIndex = m_GameLogic.SwitchToCardIndex(cbOperateCard);
  1708. if (m_cbCardIndex[wChairID][cbCardIndex] == 3 && m_GameLogic.SwitchToCardData(cbCardIndex) == m_cbLaiZiPiData)
  1709. {
  1710. bPublic = false;
  1711. cbWeaveIndex = m_cbWeaveItemCount[wChairID]++;
  1712. m_WeaveItemArray[wChairID][cbWeaveIndex].cbPublicCard = FALSE;
  1713. m_WeaveItemArray[wChairID][cbWeaveIndex].wProvideUser = wChairID;
  1714. m_WeaveItemArray[wChairID][cbWeaveIndex].cbWeaveKind = cbOperateCode;
  1715. m_WeaveItemArray[wChairID][cbWeaveIndex].cbCenterCard = cbOperateCard;
  1716. }
  1717. else return false;
  1718. //删除扑克
  1719. m_cbCardIndex[wChairID][cbCardIndex] = 0;
  1720. m_wDianGangUser = wChairID;
  1721. //构造结果
  1722. CMD_S_OperateResult OperateResult;
  1723. OperateResult.wOperateUser = wChairID;
  1724. OperateResult.wProvideUser = wChairID;
  1725. OperateResult.cbOperateCode = cbOperateCode;
  1726. OperateResult.cbOperateCard = cbOperateCard;
  1727. OperateResult.bOutCardCout = 0;//能出牌个数
  1728. OperateResult.cbActionMask = 0;
  1729. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1730. if (m_wProvideUser == m_wCurrentUser&&wChairID == m_wCurrentUser)
  1731. {
  1732. CChiHuRight chr;
  1733. BYTE LastTempDate = 0;
  1734. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] == 1)
  1735. {
  1736. LastTempDate = m_cbLaiZiData;
  1737. }
  1738. else
  1739. {
  1740. LastTempDate = m_cbProvideCard == m_cbLaiZiPiData ? (m_GameLogic.GetEndCard(m_cbCardIndex[wChairID], m_cbLaiZiData)) : m_cbProvideCard;
  1741. }
  1742. BYTE m_cbTempData[MAX_INDEX];
  1743. ZeroMemory(m_cbTempData, sizeof(m_cbTempData));
  1744. CopyMemory(m_cbTempData, m_cbCardIndex[wChairID], sizeof(m_cbTempData));
  1745. m_cbTempData[m_GameLogic.SwitchToCardIndex(LastTempDate)]--;
  1746. OperateResult.cbActionMask |= m_GameLogic.AnalyseChiHuCard(m_cbTempData, m_WeaveItemArray[wChairID],
  1747. m_cbWeaveItemCount[wChairID], LastTempDate, chr, m_cbLaiZiData, bGameType);
  1748. if (OperateResult.cbActionMask&WIK_ZI_MO)
  1749. {
  1750. if (OperateResult.cbActionMask&WIK_YING_ZIMO)
  1751. {
  1752. if (m_bGangStatus)
  1753. {
  1754. OperateResult.cbActionMask |= WIK_YING_LAIYOU;
  1755. m_cbUserAction[wChairID] |= WIK_YING_LAIYOU;
  1756. }
  1757. else
  1758. m_cbUserAction[wChairID] |= WIK_YING_ZIMO;
  1759. }
  1760. else
  1761. {
  1762. if (m_bGangStatus)
  1763. {
  1764. OperateResult.cbActionMask |= WIK_RUAN_LAIYOU;
  1765. m_cbUserAction[wChairID] |= WIK_RUAN_LAIYOU;
  1766. }
  1767. else
  1768. {
  1769. OperateResult.cbActionMask |= WIK_RUAN_ZIMO;
  1770. m_cbUserAction[wChairID] |= WIK_RUAN_ZIMO;
  1771. }
  1772. }
  1773. m_cbProvideCard = LastTempDate;
  1774. }
  1775. if (bGameType == CXZBanLai && (m_cbUserAction[wChairID] & WIK_RUAN_ZIMO) && m_OutLaiZi[wChairID] == 0)
  1776. {
  1777. OperateResult.cbActionMask = OperateResult.cbActionMask & 0xff0ff;
  1778. m_cbUserAction[wChairID] = m_cbUserAction[wChairID] & 0xff0ff;
  1779. }
  1780. }
  1781. tagGangCardResult GangCardResult;
  1782. OperateResult.cbActionMask |= m_GameLogic.AnalyseGangCard(m_cbCardIndex[wChairID], m_cbLaiZiData, m_cbLaiZiPiData, m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], GangCardResult);
  1783. if (OperateResult.cbActionMask & WIK_GANG)
  1784. {
  1785. BYTE TempCount = 0;
  1786. for (BYTE i = 0; i < MAX_INDEX; i++)
  1787. {
  1788. if (m_cbCardIndex[wChairID][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  1789. {
  1790. OperateResult.cbActionMask |= WIK_AN_GANG;
  1791. m_cbUserAction[wChairID] |= WIK_GANG;
  1792. m_cbUserAction[wChairID] |= WIK_AN_GANG;
  1793. OperateResult.cbActionCard[TempCount++] = m_GameLogic.SwitchToCardData(i);
  1794. }
  1795. }
  1796. }
  1797. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  1798. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  1799. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  1800. for (BYTE i = 0; i < MAX_INDEX; i++)
  1801. {
  1802. if (m_cbCardIndex[wChairID][i] == 0)continue;
  1803. BYTE TempLaiZiCount = m_OutLaiZi[wChairID];
  1804. if (m_GameLogic.SwitchToCardData(i) == m_cbLaiZiData)TempLaiZiCount++;
  1805. m_cbCardIndex[wChairID][i]--;
  1806. if (m_GameLogic.IsTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbLaiZiData, bGameType, TempLaiZiCount))
  1807. {
  1808. OperateResult.bOutCardData[OperateResult.bOutCardCout] = m_GameLogic.SwitchToCardData(i);
  1809. BYTE m_cbTingPai[MAX_INDEX] = { 0 };//听牌数组,听哪个牌就把哪个牌设置为1
  1810. BYTE m_cbTingParCount = 0;//听牌数据
  1811. bool BbanlaiTemp = true;
  1812. if (m_GameLogic.AnalyseTingCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID], m_cbWeaveItemCount[wChairID], m_cbTingPai, m_cbLaiZiData, bGameType,TempLaiZiCount))
  1813. {
  1814. for (BYTE j = 0; j < MAX_INDEX; j++)
  1815. {
  1816. if (m_cbTingPai[j] == 1)
  1817. {
  1818. BbanlaiTemp = false;
  1819. OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount++] = m_GameLogic.SwitchToCardData(j);
  1820. BYTE num = RemainNum(wChairID, OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1], i);
  1821. OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1] = m_GameLogic.GetValue(num, OperateResult.bTingCardData[OperateResult.bOutCardCout][m_cbTingParCount - 1]);
  1822. }
  1823. }
  1824. OperateResult.bTingCardCount[OperateResult.bOutCardCout] = m_cbTingParCount;
  1825. }
  1826. if ((bGameType == CXZBanLai) && BbanlaiTemp)
  1827. {
  1828. OperateResult.bOutCardData[OperateResult.bOutCardCout] = 0;
  1829. OperateResult.bOutCardCout--;
  1830. }
  1831. OperateResult.bOutCardCout++;
  1832. }
  1833. m_cbCardIndex[wChairID][i]++;
  1834. }
  1835. if (OperateResult.bOutCardCout != 0)
  1836. {
  1837. m_TabbOutCardCout[wChairID] = 0; //可以打出的牌就听牌的个数
  1838. ZeroMemory(m_TabbOutCardData[wChairID], sizeof(m_TabbOutCardData[wChairID])); //具体打哪几张牌
  1839. ZeroMemory(m_TabbTingCardCount[wChairID], sizeof(m_TabbTingCardCount[wChairID])); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  1840. ZeroMemory(m_TabbTingCardData[wChairID], sizeof(m_TabbTingCardData[wChairID])); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  1841. m_TabbOutCardCout[wChairID] = OperateResult.bOutCardCout; //可以打出的牌就听牌的个数
  1842. CopyMemory(m_TabbOutCardData[wChairID], OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData)); //具体打哪几张牌
  1843. CopyMemory(m_TabbTingCardCount[wChairID], OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount)); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  1844. CopyMemory(m_TabbTingCardData[wChairID], OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData)); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  1845. }
  1846. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1847. //发送消息
  1848. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1849. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1850. //发送信息
  1851. CMD_S_GangScore gs;
  1852. ZeroMemory(&gs, sizeof(gs));
  1853. gs.wChairId = wChairID;
  1854. gs.cbOperateCode = WIK_AN_PIGANG;
  1855. //杠牌得分
  1856. int lScore = 0;
  1857. for (WORD i = 0; i < GAME_PLAY; i++)
  1858. {
  1859. if (!m_bPlayStatus[i] || i == wChairID) continue;
  1860. gs.lGangScore[i] -= m_gameConfig.wDiScore * 2;
  1861. m_lGameScore[i] += gs.lGangScore[i];
  1862. m_lGameTatolScore[i] += gs.lGangScore[i];
  1863. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  1864. lScore -= gs.lGangScore[i];
  1865. }
  1866. gs.lGangScore[wChairID] = lScore;
  1867. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  1868. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  1869. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  1870. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1871. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1872. for (BYTE i = 0; i < GAME_PLAY; i++)
  1873. {
  1874. gs.cbWanJiaScore[i] = m_lGameScore[i];
  1875. }
  1876. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1877. if (m_cbProvideCard == m_cbLaiZiPiData || m_wProvideUser != wChairID)
  1878. m_cbProvideCard = m_GameLogic.GetEndCard(m_cbCardIndex[wChairID], m_cbLaiZiData);
  1879. m_cbSendCardData = m_cbProvideCard;
  1880. m_wProvideUser = wChairID;
  1881. m_wCurrentUser = wChairID;
  1882. return true;
  1883. }
  1884. case WIK_RUAN_ZIMO: //自摸和牌
  1885. {
  1886. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] != 1)
  1887. {
  1888. ASSERT(false);
  1889. return false;
  1890. }
  1891. BYTE TempCardData=m_cbProvideCard;
  1892. if (m_cbProvideCard!=m_cbSendCardData)
  1893. {
  1894. ASSERT(false);
  1895. return false;
  1896. }
  1897. int TempAction;
  1898. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--;
  1899. CChiHuRight chr;
  1900. TempAction |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID],
  1901. m_cbWeaveItemCount[wChairID], m_cbSendCardData, chr, m_cbLaiZiData,bGameType);
  1902. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  1903. if (TempAction == WIK_NULL)
  1904. {
  1905. ASSERT(false);
  1906. return false;
  1907. }
  1908. m_HuPai[wChairID]++;
  1909. CMD_S_OperateResult OperateResult;
  1910. OperateResult.wOperateUser = wChairID;
  1911. OperateResult.wProvideUser = wChairID;
  1912. OperateResult.cbOperateCode = cbOperateCode;
  1913. OperateResult.cbOperateCard = cbOperateCard;
  1914. OperateResult.bOutCardCout = 0;//能出牌个数
  1915. OperateResult.cbActionMask = WIK_NULL;
  1916. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1917. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  1918. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  1919. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  1920. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1921. //发送消息
  1922. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1923. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  1924. BYTE tempLaiZi = 0;//癞子个数超过四个就特殊处理
  1925. for (BYTE i = 0; i < GAME_PLAY; i++)
  1926. {
  1927. tempLaiZi += m_OutLaiZi[i];
  1928. }
  1929. if (tempLaiZi > 4)
  1930. {
  1931. ASSERT(false);
  1932. return false;
  1933. }
  1934. //积分变动
  1935. CMD_S_GangScore gs;
  1936. ZeroMemory(&gs, sizeof(gs));
  1937. gs.wChairId = wChairID;
  1938. gs.cbOperateCode = WIK_RUAN_ZIMO;
  1939. int TempInfoScore = 0;
  1940. BYTE FanShu = 1;
  1941. for (BYTE i = 0; i < GAME_PLAY; i++)//各个玩家游戏积分变动
  1942. {
  1943. if (i == wChairID)continue;
  1944. FanShu = (FanShu << (m_OutLaiZi[i] + m_OutLaiZi[wChairID]));
  1945. gs.lGangScore[i] -= m_gameConfig.wDiScore*FanShu;
  1946. m_lGameScore[i] += gs.lGangScore[i];
  1947. m_lGameTatolScore[i] += gs.lGangScore[i];
  1948. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  1949. TempInfoScore -= gs.lGangScore[i];
  1950. FanShu = 1;
  1951. }
  1952. gs.lGangScore[wChairID] = TempInfoScore;
  1953. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  1954. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  1955. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  1956. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1957. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1958. for (BYTE i = 0; i < GAME_PLAY; i++)
  1959. {
  1960. gs.cbWanJiaScore[i] = m_lGameScore[i];
  1961. }
  1962. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  1963. OnEventGameConclude(wChairID, NULL, GER_NORMAL);
  1964. return true;
  1965. }
  1966. case WIK_YING_ZIMO:
  1967. {
  1968. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] > 1)
  1969. {
  1970. ASSERT(false);
  1971. return false;
  1972. }
  1973. if (m_cbProvideCard != m_cbSendCardData)
  1974. {
  1975. ASSERT(false);
  1976. return false;
  1977. }
  1978. BYTE TempCardData = m_cbProvideCard;
  1979. int TempAction;
  1980. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--;
  1981. CChiHuRight chr;
  1982. TempAction |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID],
  1983. m_cbWeaveItemCount[wChairID], m_cbSendCardData, chr, m_cbLaiZiData, bGameType);
  1984. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  1985. if (TempAction == WIK_NULL)
  1986. {
  1987. ASSERT(false);
  1988. return false;
  1989. }
  1990. m_HuPai[wChairID]++;
  1991. CMD_S_OperateResult OperateResult;
  1992. OperateResult.wOperateUser = wChairID;
  1993. OperateResult.wProvideUser = wChairID;
  1994. OperateResult.cbOperateCode = cbOperateCode;
  1995. OperateResult.cbOperateCard = cbOperateCard;
  1996. OperateResult.bOutCardCout = 0;//能出牌个数
  1997. OperateResult.cbActionMask = WIK_NULL;
  1998. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  1999. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  2000. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  2001. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  2002. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2003. //发送消息
  2004. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2005. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2006. BYTE tempLaiZi = 0;//癞子个数超过四个就特殊处理
  2007. for (BYTE i = 0; i < GAME_PLAY; i++)
  2008. {
  2009. tempLaiZi += m_OutLaiZi[i];
  2010. }
  2011. if (tempLaiZi > 4)
  2012. {
  2013. ASSERT(false);
  2014. return false;
  2015. }
  2016. //积分变动
  2017. CMD_S_GangScore gs;
  2018. ZeroMemory(&gs, sizeof(gs));
  2019. gs.wChairId = wChairID;
  2020. gs.cbOperateCode = WIK_YING_ZIMO;
  2021. int TempInfoScore = 0;
  2022. BYTE FanShu = 1;
  2023. for (BYTE i = 0; i < GAME_PLAY; i++)//各个玩家游戏积分变动
  2024. {
  2025. if (i == wChairID)continue;
  2026. FanShu = (FanShu << (m_OutLaiZi[i] + m_OutLaiZi[wChairID]));
  2027. gs.lGangScore[i] -= m_gameConfig.wDiScore*FanShu * 2;
  2028. m_lGameScore[i] += gs.lGangScore[i];
  2029. m_lGameTatolScore[i] += gs.lGangScore[i];
  2030. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  2031. TempInfoScore -= gs.lGangScore[i];
  2032. FanShu = 1;
  2033. }
  2034. gs.lGangScore[wChairID] = TempInfoScore;
  2035. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  2036. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  2037. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  2038. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2039. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2040. for (BYTE i = 0; i < GAME_PLAY; i++)
  2041. {
  2042. gs.cbWanJiaScore[i] = m_lGameScore[i];
  2043. }
  2044. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2045. OnEventGameConclude(wChairID, NULL, GER_NORMAL);
  2046. return true;
  2047. }
  2048. case WIK_RUAN_LAIYOU:
  2049. {
  2050. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] != 1)
  2051. {
  2052. ASSERT(false);
  2053. return false;
  2054. }
  2055. if (!m_bGangStatus)
  2056. {
  2057. m_bGangStatus = false;
  2058. ASSERT(false);
  2059. return false;
  2060. }
  2061. BYTE TempCardData = m_cbProvideCard;
  2062. if (m_cbProvideCard != m_cbSendCardData)
  2063. {
  2064. ASSERT(false);
  2065. return false;
  2066. }
  2067. int TempAction;
  2068. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--;
  2069. CChiHuRight chr;
  2070. TempAction |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID],
  2071. m_cbWeaveItemCount[wChairID], m_cbSendCardData, chr, m_cbLaiZiData, bGameType);
  2072. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  2073. if (TempAction == WIK_NULL)
  2074. {
  2075. ASSERT(false);
  2076. return false;
  2077. }
  2078. m_HuPai[wChairID]++;
  2079. CMD_S_OperateResult OperateResult;
  2080. OperateResult.wOperateUser = wChairID;
  2081. OperateResult.wProvideUser = wChairID;
  2082. OperateResult.cbOperateCode = cbOperateCode;
  2083. OperateResult.cbOperateCard = cbOperateCard;
  2084. OperateResult.bOutCardCout = 0;//能出牌个数
  2085. OperateResult.cbActionMask = WIK_NULL;
  2086. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  2087. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  2088. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  2089. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  2090. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2091. //发送消息
  2092. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2093. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2094. BYTE tempLaiZi = 0;//癞子个数超过四个就特殊处理
  2095. for (BYTE i = 0; i < GAME_PLAY; i++)
  2096. {
  2097. tempLaiZi += m_OutLaiZi[i];
  2098. }
  2099. if (tempLaiZi > 4)return false;
  2100. //积分变动
  2101. CMD_S_GangScore gs;
  2102. ZeroMemory(&gs, sizeof(gs));
  2103. gs.wChairId = wChairID;
  2104. gs.cbOperateCode = WIK_RUAN_LAIYOU;
  2105. int TempInfoScore = 0;
  2106. BYTE FanShu = 1;
  2107. for (BYTE i = 0; i < GAME_PLAY; i++)//各个玩家游戏积分变动
  2108. {
  2109. if (i == wChairID)continue;
  2110. FanShu = (FanShu << (m_OutLaiZi[i] + m_OutLaiZi[wChairID]));
  2111. gs.lGangScore[i] -= m_gameConfig.wDiScore*FanShu * 2;
  2112. m_lGameScore[i] += gs.lGangScore[i];
  2113. m_lGameTatolScore[i] += gs.lGangScore[i];
  2114. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  2115. TempInfoScore -= gs.lGangScore[i];
  2116. FanShu = 1;
  2117. }
  2118. gs.lGangScore[wChairID] = TempInfoScore;
  2119. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  2120. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  2121. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  2122. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2123. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2124. for (BYTE i = 0; i < GAME_PLAY; i++)
  2125. {
  2126. gs.cbWanJiaScore[i] = m_lGameScore[i];
  2127. }
  2128. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2129. OnEventGameConclude(wChairID, NULL, GER_NORMAL);
  2130. return true;
  2131. }
  2132. case WIK_YING_LAIYOU:
  2133. {
  2134. if (m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] > 1)
  2135. {
  2136. ASSERT(false);
  2137. return false;
  2138. }
  2139. if (!m_bGangStatus)
  2140. {
  2141. m_bGangStatus = false;
  2142. ASSERT(false);
  2143. return false;
  2144. }
  2145. BYTE TempCardData = m_cbProvideCard;
  2146. int TempAction;
  2147. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]--;
  2148. CChiHuRight chr;
  2149. TempAction |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[wChairID], m_WeaveItemArray[wChairID],
  2150. m_cbWeaveItemCount[wChairID], m_cbSendCardData, chr, m_cbLaiZiData, bGameType);
  2151. m_cbCardIndex[wChairID][m_GameLogic.SwitchToCardIndex(m_cbProvideCard)]++;
  2152. if (TempAction == WIK_NULL)
  2153. {
  2154. ASSERT(false);
  2155. return false;
  2156. }
  2157. m_HuPai[wChairID]++;
  2158. CMD_S_OperateResult OperateResult;
  2159. OperateResult.wOperateUser = wChairID;
  2160. OperateResult.wProvideUser = wChairID;
  2161. OperateResult.cbOperateCode = cbOperateCode;
  2162. OperateResult.cbOperateCard = cbOperateCard;
  2163. OperateResult.bOutCardCout = 0;//能出牌个数
  2164. OperateResult.cbActionMask = WIK_NULL;
  2165. ZeroMemory(OperateResult.cbActionCard, sizeof(OperateResult.cbActionCard));
  2166. ZeroMemory(OperateResult.bOutCardData, sizeof(OperateResult.bOutCardData));//能出牌具体数据
  2167. ZeroMemory(OperateResult.bTingCardCount, sizeof(OperateResult.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  2168. ZeroMemory(OperateResult.bTingCardData, sizeof(OperateResult.bTingCardData));
  2169. RepayRecord(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2170. //发送消息
  2171. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2172. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_OPERATE_RESULT, &OperateResult, sizeof(OperateResult));
  2173. BYTE tempLaiZi = 0;//癞子个数超过四个就特殊处理
  2174. for (BYTE i = 0; i < GAME_PLAY; i++)
  2175. {
  2176. tempLaiZi += m_OutLaiZi[i];
  2177. }
  2178. if (tempLaiZi > 4)return false;
  2179. //积分变动
  2180. CMD_S_GangScore gs;
  2181. ZeroMemory(&gs, sizeof(gs));
  2182. gs.wChairId = wChairID;
  2183. gs.cbOperateCode = WIK_YING_LAIYOU;
  2184. int TempInfoScore = 0;
  2185. BYTE FanShu = 1;
  2186. for (BYTE i = 0; i < GAME_PLAY; i++)//各个玩家游戏积分变动
  2187. {
  2188. if (i == wChairID)continue;
  2189. FanShu = (FanShu << (m_OutLaiZi[i] + m_OutLaiZi[wChairID]));
  2190. gs.lGangScore[i] -= m_gameConfig.wDiScore*FanShu * 4;
  2191. m_lGameScore[i] += gs.lGangScore[i];
  2192. m_lGameTatolScore[i] += gs.lGangScore[i];
  2193. gs.cbWanJiaScore[i] = m_lGameTatolScore[i];
  2194. TempInfoScore -= gs.lGangScore[i];
  2195. FanShu = 1;
  2196. }
  2197. gs.lGangScore[wChairID] = TempInfoScore;
  2198. m_lGameScore[wChairID] += gs.lGangScore[wChairID];
  2199. m_lGameTatolScore[wChairID] += gs.lGangScore[wChairID];
  2200. gs.cbWanJiaScore[wChairID] = m_lGameTatolScore[wChairID];
  2201. m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2202. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2203. for (BYTE i = 0; i < GAME_PLAY; i++)
  2204. {
  2205. gs.cbWanJiaScore[i] = m_lGameScore[i];
  2206. }
  2207. RepayRecord(INVALID_CHAIR, SUB_S_GANG_SCORE, &gs, sizeof(gs));
  2208. OnEventGameConclude(wChairID, NULL, GER_NORMAL);
  2209. return true;
  2210. }
  2211. }
  2212. return true;
  2213. }
  2214. return false;
  2215. }
  2216. //发送操作
  2217. bool TableFrameSinkCxz::SendOperateNotify()
  2218. {
  2219. //发送提示
  2220. for (WORD i=0;i<GAME_PLAY;i++)
  2221. {
  2222. if (m_cbUserAction[i]!=WIK_NULL)
  2223. {
  2224. //构造数据
  2225. CMD_S_OperateNotify OperateNotify;
  2226. OperateNotify.wResumeUser=m_wResumeUser;
  2227. OperateNotify.cbActionCard=m_cbProvideCard;
  2228. OperateNotify.cbActionMask=m_cbUserAction[i];
  2229. //RepayRecord(i, SUB_S_OPERATE_NOTIFY, &OperateNotify, sizeof(OperateNotify));
  2230. //发送数据
  2231. m_pITableFrame->SendTableData(i,SUB_S_OPERATE_NOTIFY,&OperateNotify,sizeof(OperateNotify));
  2232. }
  2233. }
  2234. //m_pITableFrame->SendLookonData(i, SUB_S_OPERATE_NOTIFY, &OperateNotify, sizeof(OperateNotify));
  2235. return true;
  2236. }
  2237. //派发扑克,wCurrentUser表示给哪个用户,bTail表示是末尾拿牌还是不是,true表示末尾,bLaiZiGang默认false不是癞子杠,true才是
  2238. bool TableFrameSinkCxz::DispatchCardData(WORD wCurrentUser, bool bTail, bool bLaiZiGang)
  2239. {
  2240. //状态效验
  2241. ASSERT(wCurrentUser!=INVALID_CHAIR);
  2242. if (wCurrentUser==INVALID_CHAIR)
  2243. return false;
  2244. //丢弃扑克
  2245. if ((m_wOutCardUser != INVALID_CHAIR) && (m_cbOutCardData != 0))
  2246. {
  2247. m_cbDiscardCount[m_wOutCardUser]++;
  2248. m_cbDiscardCard[m_wOutCardUser][m_cbDiscardCount[m_wOutCardUser] - 1] = m_cbOutCardData;
  2249. }
  2250. //荒庄结束
  2251. if (m_cbLeftCardCount == 0)
  2252. {
  2253. m_cbChiHuCard = 0;
  2254. m_wProvideUser = INVALID_CHAIR;
  2255. bIsHuang = true;
  2256. OnEventGameConclude(m_wProvideUser, NULL, GER_NORMAL);
  2257. return true;
  2258. }
  2259. m_TabbOutCardCout[wCurrentUser] = 0; //可以打出的牌就听牌的个数
  2260. ZeroMemory(m_TabbOutCardData[wCurrentUser], sizeof(m_TabbOutCardData[wCurrentUser])); //具体打哪几张牌
  2261. ZeroMemory(m_TabbTingCardCount[wCurrentUser], sizeof(m_TabbTingCardCount[wCurrentUser])); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  2262. ZeroMemory(m_TabbTingCardData[wCurrentUser], sizeof(m_TabbTingCardData[wCurrentUser])); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  2263. //设置变量
  2264. m_cbOutCardData = 0;
  2265. m_wCurrentUser = wCurrentUser; //记录拿牌人的索引。
  2266. m_wOutCardUser = INVALID_CHAIR; //置空上次出牌用户的索引
  2267. m_bEnjoinChiHu[wCurrentUser] = false;
  2268. BYTE ActionCard[3] = { 0 };//操作牌值
  2269. BYTE AnActionCount = 0;
  2270. //发牌处理
  2271. if (m_bSendStatus == true)
  2272. {
  2273. //发送扑克
  2274. m_cbSendCardCount++;
  2275. m_cbSendCardData = m_cbRepertoryCard[--m_cbLeftCardCount];
  2276. CChiHuRight chr;
  2277. m_cbUserAction[wCurrentUser] |= m_GameLogic.AnalyseChiHuCard(m_cbCardIndex[wCurrentUser], m_WeaveItemArray[wCurrentUser],
  2278. m_cbWeaveItemCount[wCurrentUser], m_cbSendCardData, chr, m_cbLaiZiData, bGameType);
  2279. //加牌
  2280. m_cbCardIndex[wCurrentUser][m_GameLogic.SwitchToCardIndex(m_cbSendCardData)]++;
  2281. //设置变量
  2282. m_wProvideUser = wCurrentUser;
  2283. m_cbProvideCard = m_cbSendCardData;
  2284. //杠牌判断
  2285. if (m_cbLeftCardCount > 0 )
  2286. {
  2287. bool bCanAnGang = true;//此true表示自己抓牌,false表示表人打得去检验杠,
  2288. tagGangCardResult GangCardResult;
  2289. m_cbUserAction[wCurrentUser] |= m_GameLogic.AnalyseGangCard(m_cbCardIndex[wCurrentUser], m_cbLaiZiData, m_cbLaiZiPiData,
  2290. m_WeaveItemArray[wCurrentUser], m_cbWeaveItemCount[wCurrentUser], GangCardResult, m_cbSendCardData);
  2291. }
  2292. }
  2293. if (m_cbUserAction[wCurrentUser]!=WIK_NULL)
  2294. {
  2295. if (m_cbUserAction[wCurrentUser] & WIK_ZI_MO)
  2296. {
  2297. if (bLaiZiGang)
  2298. {
  2299. if (m_cbUserAction[wCurrentUser]&WIK_YING_ZIMO)
  2300. {
  2301. m_cbUserAction[wCurrentUser] = m_cbUserAction[wCurrentUser] & 0xff0ff;
  2302. m_cbUserAction[wCurrentUser] |= WIK_YING_LAIYOU;
  2303. }
  2304. if (m_cbCardIndex[wCurrentUser][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] == 1 && !(m_cbUserAction[wCurrentUser] & WIK_YING_LAIYOU))
  2305. {
  2306. m_cbUserAction[wCurrentUser] |= WIK_RUAN_LAIYOU;
  2307. }
  2308. else
  2309. {
  2310. m_cbUserAction[wCurrentUser] |= WIK_YING_LAIYOU;
  2311. }
  2312. }
  2313. else
  2314. {
  2315. if (m_cbCardIndex[wCurrentUser][m_GameLogic.SwitchToCardIndex(m_cbLaiZiData)] == 1 && !(m_cbUserAction[wCurrentUser]&WIK_YING_ZIMO))
  2316. {
  2317. m_cbUserAction[wCurrentUser] |= WIK_RUAN_ZIMO;
  2318. }
  2319. else
  2320. {
  2321. m_cbUserAction[wCurrentUser] |= WIK_YING_ZIMO;
  2322. }
  2323. }
  2324. }
  2325. if (m_cbUserAction[wCurrentUser] & WIK_GANG)
  2326. {
  2327. if (m_cbCardIndex[wCurrentUser][m_GameLogic.SwitchToCardIndex(m_cbLaiZiPiData)] == 3)
  2328. {
  2329. m_cbUserAction[wCurrentUser] |= WIK_AN_PIGANG;
  2330. ActionCard[AnActionCount++] = m_cbLaiZiPiData;
  2331. }
  2332. else
  2333. {
  2334. m_cbUserAction[wCurrentUser] |= WIK_AN_GANG;
  2335. for (BYTE i = 0; i < MAX_INDEX; i++)
  2336. {
  2337. if (m_cbCardIndex[wCurrentUser][i] == 4 && i != m_GameLogic.SwitchToCardIndex(m_cbLaiZiData))
  2338. {
  2339. ActionCard[AnActionCount++] = m_GameLogic.SwitchToCardData(i);
  2340. }
  2341. }
  2342. }
  2343. }
  2344. }
  2345. if (bGameType == CXZBanLai && (m_cbUserAction[wCurrentUser]&WIK_RUAN_ZIMO) && m_OutLaiZi[wCurrentUser] == 0)
  2346. {
  2347. m_cbUserAction[wCurrentUser] = m_cbUserAction[wCurrentUser] & 0xff0ff;
  2348. }
  2349. //构造数据
  2350. CMD_S_SendCard SendCard;
  2351. ZeroMemory(&SendCard, sizeof(SendCard));
  2352. SendCard.wCurrentUser = wCurrentUser;
  2353. SendCard.bTail = 0;
  2354. SendCard.bLeftCardCount = m_cbLeftCardCount;
  2355. SendCard.cbActionMask = m_cbUserAction[wCurrentUser];
  2356. SendCard.cbCardData = (m_bSendStatus == true) ? m_cbSendCardData : 0x00;
  2357. BYTE bOutCardCount = 0;//听牌个数
  2358. BYTE bTempCardData[14] = { 0 };
  2359. BYTE bTingCount[14] = { 0 };
  2360. BYTE bTingCardData[14][27] = { 0 };
  2361. SendCard.bOutCardCout = 0;//能出牌个数(由个数决定是否听牌,0表示不可以听牌)
  2362. ZeroMemory(SendCard.bOutCardData, sizeof(SendCard.bOutCardData));//能出牌具体数据
  2363. ZeroMemory(SendCard.bTingCardCount, sizeof(SendCard.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  2364. ZeroMemory(SendCard.bTingCardData, sizeof(SendCard.bTingCardData));
  2365. BYTE tempData[MAX_INDEX] = { 0 };
  2366. for (BYTE i = 0; i < MAX_INDEX; i++)
  2367. {
  2368. if (m_cbCardIndex[m_wCurrentUser][i] == 0)continue;
  2369. BYTE TempLaiZiCount = m_OutLaiZi[wCurrentUser];
  2370. if (m_GameLogic.SwitchToCardData(i) == m_cbLaiZiData)TempLaiZiCount++;
  2371. m_cbCardIndex[m_wCurrentUser][i]--;
  2372. if (m_GameLogic.IsTingCard(m_cbCardIndex[m_wCurrentUser], m_WeaveItemArray[m_wCurrentUser], m_cbWeaveItemCount[m_wCurrentUser], m_cbLaiZiData, bGameType, TempLaiZiCount))
  2373. {
  2374. bTempCardData[bOutCardCount] = m_GameLogic.SwitchToCardData(i);
  2375. BYTE m_cbTingPai[MAX_INDEX] = { 0 };//听牌数组,听哪个牌就把哪个牌设置为1
  2376. BYTE m_cbTingParCount = 0;//听牌数据
  2377. bool BbanlaiTemp = true;
  2378. if (m_GameLogic.AnalyseTingCard(m_cbCardIndex[m_wCurrentUser], m_WeaveItemArray[m_wCurrentUser], m_cbWeaveItemCount[m_wCurrentUser], m_cbTingPai, m_cbLaiZiData, bGameType,TempLaiZiCount))
  2379. {
  2380. for (BYTE j = 0; j < MAX_INDEX; j++)
  2381. {
  2382. if (m_cbTingPai[j] == 1)
  2383. {
  2384. BbanlaiTemp = false;
  2385. bTingCardData[bOutCardCount][m_cbTingParCount++] = m_GameLogic.SwitchToCardData(j);
  2386. BYTE num = RemainNum(wCurrentUser, bTingCardData[bOutCardCount][m_cbTingParCount - 1], i);
  2387. bTingCardData[bOutCardCount][m_cbTingParCount - 1] = m_GameLogic.GetValue(num, bTingCardData[bOutCardCount][m_cbTingParCount - 1]);
  2388. }
  2389. }
  2390. bTingCount[bOutCardCount] = m_cbTingParCount;
  2391. }
  2392. if ((bGameType == CXZBanLai) && BbanlaiTemp)
  2393. {
  2394. bTempCardData[bOutCardCount] = 0;
  2395. bOutCardCount--;
  2396. }
  2397. //if (bTingCount[bOutCardCount] > 0)
  2398. bOutCardCount++;
  2399. //else
  2400. // bTempCardData[bOutCardCount] = 0;
  2401. }
  2402. m_cbCardIndex[m_wCurrentUser][i]++;
  2403. }
  2404. RepayRecord(INVALID_CHAIR, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard) - 378);
  2405. //m_wResumeUser = m_wCurrentUser;//当前为抓牌用户,就算是过,也是还回到自己牌权
  2406. //发送数据
  2407. for (int i = 0; i < GAME_PLAY; i++)
  2408. {
  2409. if (i == m_wCurrentUser)
  2410. {//发送给摸牌玩家的数据,附带麻将牌面数据
  2411. SendCard.cbCardData = (m_bSendStatus == true) ? m_cbSendCardData : 0x00;
  2412. SendCard.cbActionMask = m_cbUserAction[wCurrentUser];
  2413. SendCard.bOutCardCout = bOutCardCount;
  2414. CopyMemory(SendCard.cbActionCard, ActionCard, sizeof(ActionCard));
  2415. CopyMemory(SendCard.bTingCardCount, bTingCount, sizeof(bTingCount));
  2416. CopyMemory(SendCard.bOutCardData, bTempCardData, sizeof(bTempCardData));
  2417. CopyMemory(SendCard.bTingCardData, bTingCardData, sizeof(bTingCardData));
  2418. m_pITableFrame->SendTableData(i, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard));
  2419. //m_pITableFrame->SendLookonData(i, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard));
  2420. m_TabbOutCardCout[m_wCurrentUser] = bOutCardCount; //可以打出的牌就听牌的个数
  2421. CopyMemory(m_TabbOutCardData[m_wCurrentUser], bTempCardData, sizeof(bTempCardData)); //具体打哪几张牌
  2422. CopyMemory(m_TabbTingCardCount[m_wCurrentUser], bTingCount, sizeof(bTingCount)); //相对应打出牌可听牌个数,索引表示第几张,值是对应对应的听牌个数
  2423. CopyMemory(m_TabbTingCardData[m_wCurrentUser], bTingCardData, sizeof(bTingCardData)); //具体听牌数据,一维索引表示打出牌的第几个,二维索引表示听牌的第几个,值表示牌数据
  2424. }
  2425. else
  2426. {//发送给其他玩家的数据,没有麻将牌面数据(防止客户端作弊)
  2427. SendCard.cbCardData = 0x00;
  2428. SendCard.cbActionMask = 0x0000;
  2429. SendCard.bOutCardCout = 0;//能出牌个数这幅牌出个牌是否可以听牌
  2430. ZeroMemory(SendCard.cbActionCard, sizeof(SendCard.cbActionCard));//对哪个牌操作
  2431. ZeroMemory(SendCard.bOutCardData, sizeof(SendCard.bOutCardData));//能出牌具体数据
  2432. ZeroMemory(SendCard.bTingCardCount, sizeof(SendCard.bTingCardCount));//在出相应牌后能听牌的个数,所以是个二维的
  2433. ZeroMemory(SendCard.bTingCardData, sizeof(SendCard.bTingCardData));
  2434. m_pITableFrame->SendTableData(i, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard));
  2435. //m_pITableFrame->SendLookonData(i, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard));
  2436. }
  2437. }
  2438. SendCard.cbActionMask = 0;
  2439. SendCard.cbCardData = 0;
  2440. SendCard.bOutCardCout = 0;
  2441. ZeroMemory(SendCard.bOutCardData, sizeof(SendCard.bOutCardData));
  2442. ZeroMemory(SendCard.bTingCardCount, sizeof(SendCard.cbCardData));
  2443. ZeroMemory(SendCard.bTingCardData, sizeof(SendCard.cbCardData));
  2444. ZeroMemory(SendCard.cbActionCard, sizeof(SendCard.cbCardData));
  2445. //给旁观者的抓牌动作
  2446. m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_SEND_CARD, &SendCard, sizeof(SendCard));
  2447. return true;
  2448. }
  2449. bool TableFrameSinkCxz::IsWin(WORD wChairID)
  2450. {
  2451. for (auto chairID : m_wWinOrder)
  2452. {
  2453. if (chairID == wChairID)//表示玩家已经开始听牌,则出牌必须是所摸牌
  2454. return true;
  2455. }
  2456. return false;
  2457. }
  2458. //响应判断
  2459. bool TableFrameSinkCxz::EstimateUserRespond(WORD wCenterUser, BYTE cbCenterCard, enEstimatKind EstimatKind)
  2460. {
  2461. //变量定义
  2462. bool bAroseAction=false;
  2463. //用户状态
  2464. ZeroMemory(m_bResponse,sizeof(m_bResponse));
  2465. ZeroMemory(m_cbUserAction,sizeof(m_cbUserAction));
  2466. ZeroMemory(m_cbPerformAction,sizeof(m_cbPerformAction));
  2467. //动作判断
  2468. for (WORD i=0;i<GAME_PLAY;i++)
  2469. {
  2470. //用户过滤
  2471. if (wCenterUser==i||!m_bPlayStatus[i]) continue;
  2472. //出牌类型
  2473. if (EstimatKind==EstimatKind_OutCard)
  2474. {
  2475. //吃碰判断
  2476. //if (m_bEnjoinChiPeng[i]==false)
  2477. //{
  2478. ////碰牌判断
  2479. m_cbUserAction[i] |= m_GameLogic.EstimatePengCard(m_cbCardIndex[i], cbCenterCard, m_cbLaiZiPiData);
  2480. //杠牌判断
  2481. if (m_cbLeftCardCount>0 && cbCenterCard != m_cbLaiZiPiData)
  2482. {
  2483. m_cbUserAction[i] |= m_GameLogic.EstimateGangCard(m_cbCardIndex[i], cbCenterCard);
  2484. }
  2485. //}
  2486. }
  2487. //结果判断
  2488. if (m_cbUserAction[i] != WIK_NULL)
  2489. {
  2490. bAroseAction = true;
  2491. if (m_cbUserAction[i]&WIK_PENG)
  2492. {
  2493. BYTE bTemp = 0;
  2494. for (BYTE j = 0; j < m_cbLastDisCount[i]; j++)
  2495. {
  2496. if (m_cbLastDisCardData[i][j] == cbCenterCard)
  2497. {
  2498. bTemp++;
  2499. if (bTemp==2)
  2500. {
  2501. m_cbUserAction[i] = m_cbUserAction[i] & 0xffff7;
  2502. bAroseAction = false;
  2503. break;
  2504. }
  2505. }
  2506. }
  2507. }
  2508. break;
  2509. }
  2510. }
  2511. //结果处理
  2512. if (bAroseAction==true)
  2513. {
  2514. //设置变量
  2515. m_wProvideUser=wCenterUser;
  2516. m_cbProvideCard=cbCenterCard;
  2517. m_wResumeUser=m_wCurrentUser;
  2518. m_wCurrentUser=INVALID_CHAIR;
  2519. //发送提示
  2520. SendOperateNotify();
  2521. return true;
  2522. }
  2523. return false;
  2524. }
  2525. int TableFrameSinkCxz::GetGenCount(WORD wChairId, CChiHuRight& chr)
  2526. {
  2527. int cbGenCount = 0;
  2528. //根,青龙七对和龙七对不算根
  2529. //if ((chr&CHR_QING_LONG_QI_DUI).IsEmpty() && (chr&CHR_LONG_QI_DUI).IsEmpty())
  2530. //{
  2531. BYTE cbCardIndexTemp[MAX_INDEX];
  2532. CopyMemory(cbCardIndexTemp, m_cbCardIndex[wChairId], sizeof(cbCardIndexTemp));
  2533. for (BYTE i = 0; i < m_cbWeaveItemCount[wChairId]; i++)
  2534. {
  2535. // 抢杠过滤
  2536. bool bQiangGang = false;
  2537. if (m_WeaveItemArray[wChairId][i].cbWeaveKind == WIK_GANG)
  2538. {
  2539. for (BYTE k = 0; k < GAME_PLAY; k++)
  2540. {
  2541. if (m_cbQiangGangCardData[k] == m_WeaveItemArray[wChairId][i].cbCenterCard) bQiangGang = true;
  2542. }
  2543. }
  2544. if (bQiangGang) continue;
  2545. BYTE cbCardBuffer[4];
  2546. BYTE cbCardCount = m_GameLogic.GetWeaveCard(m_WeaveItemArray[wChairId][i].cbWeaveKind,
  2547. m_WeaveItemArray[wChairId][i].cbCenterCard, cbCardBuffer);
  2548. for (BYTE j = 0; j < cbCardCount; j++)
  2549. {
  2550. BYTE cbIndex = m_GameLogic.SwitchToCardIndex(cbCardBuffer[j]);
  2551. cbCardIndexTemp[cbIndex]++;
  2552. }
  2553. }
  2554. for (BYTE i = 0; i < MAX_INDEX; i++)
  2555. {
  2556. if (cbCardIndexTemp[i] == 4) cbGenCount++;
  2557. }
  2558. return cbGenCount;
  2559. }
  2560. BYTE TableFrameSinkCxz::RemainNum(WORD wChairId, const BYTE m_cbCard, BYTE bIndex)
  2561. {
  2562. BYTE m_cbNum = 0;
  2563. BYTE mCard[MAX_INDEX] = { 0 };
  2564. BYTE TempIndex = m_GameLogic.SwitchToCardIndex(m_cbCard);
  2565. BYTE LaiZiIndex = m_GameLogic.SwitchToCardIndex(m_cbLaiZiData);
  2566. BYTE LaiZiPiIndex = m_GameLogic.SwitchToCardIndex(m_cbLaiZiPiData);
  2567. for (BYTE i = 0; i < GAME_PLAY; i++)
  2568. {
  2569. mCard[LaiZiIndex] += m_OutLaiZi[i];//癞子数
  2570. for (BYTE j = 0; j < m_cbDiscardCount[i]; j++)//丢弃数
  2571. {
  2572. mCard[m_GameLogic.SwitchToCardIndex(m_cbDiscardCard[i][j])]++;
  2573. }
  2574. for (BYTE k = 0; k < m_cbWeaveItemCount[i]; k++)//摆出来的牌
  2575. {
  2576. if (m_WeaveItemArray[i][k].cbWeaveKind == WIK_PENG || m_WeaveItemArray[i][k].cbWeaveKind == WIK_AN_PIGANG || m_WeaveItemArray[i][k].cbWeaveKind == WIK_MING_PIGANG)
  2577. {
  2578. mCard[m_GameLogic.SwitchToCardIndex(m_WeaveItemArray[i][k].cbCenterCard)] += 3;
  2579. }
  2580. else
  2581. {
  2582. mCard[m_GameLogic.SwitchToCardIndex(m_WeaveItemArray[i][k].cbCenterCard)] += 4;
  2583. }
  2584. }
  2585. }
  2586. mCard[LaiZiPiIndex]++;
  2587. mCard[bIndex]++;
  2588. for (BYTE i = 0; i < MAX_INDEX; i++)
  2589. {
  2590. mCard[i] += m_cbCardIndex[wChairId][i];
  2591. }
  2592. m_cbNum = 4 - mCard[TempIndex];
  2593. ASSERT(m_cbNum >= 0 && m_cbNum <= 4);
  2594. if (m_cbNum < 0 || m_cbNum>4)m_cbNum = 0;
  2595. return m_cbNum;
  2596. }