诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2889 lines
104 KiB

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