诸暨麻将添加redis
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

2778 wiersze
101 KiB

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