#include "config.h" #include "duelclient.h" #include "client_card.h" #include "materials.h" #include "image_manager.h" #include "sound_manager.h" #include "single_mode.h" #include "game.h" #include "deck_manager.h" #include "replay.h" #include namespace ygo { unsigned DuelClient::connect_state = 0; unsigned char DuelClient::response_buf[SIZE_RETURN_VALUE]; size_t DuelClient::response_len = 0; unsigned int DuelClient::watching = 0; unsigned char DuelClient::selftype = 0; bool DuelClient::is_host = false; event_base* DuelClient::client_base = 0; bufferevent* DuelClient::client_bev = 0; unsigned char DuelClient::duel_client_write[SIZE_NETWORK_BUFFER]; bool DuelClient::is_closing = false; bool DuelClient::is_swapping = false; int DuelClient::select_hint = 0; int DuelClient::select_unselect_hint = 0; int DuelClient::last_select_hint = 0; unsigned char DuelClient::last_successful_msg[SIZE_NETWORK_BUFFER]; size_t DuelClient::last_successful_msg_length = 0; wchar_t DuelClient::event_string[256]; std::mt19937 DuelClient::rnd; std::uniform_real_distribution DuelClient::real_dist; bool DuelClient::is_refreshing = false; int DuelClient::match_kill = 0; std::vector DuelClient::hosts; std::set> DuelClient::remotes; event* DuelClient::resp_event = 0; bool DuelClient::StartClient(unsigned int ip, unsigned short port, bool create_game) { if(connect_state) return false; sockaddr_in sin; client_base = event_base_new(); if(!client_base) return false; std::memset(&sin, 0, sizeof sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(ip); sin.sin_port = htons(port); client_bev = bufferevent_socket_new(client_base, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(client_bev, ClientRead, nullptr, ClientEvent, (void*)create_game); if (bufferevent_socket_connect(client_bev, (sockaddr*)&sin, sizeof(sin)) < 0) { bufferevent_free(client_bev); event_base_free(client_base); client_bev = 0; client_base = 0; return false; } connect_state = 0x1; rnd.seed(std::random_device()()); if(!create_game) { timeval timeout = {5, 0}; event* timeout_event = event_new(client_base, 0, EV_TIMEOUT, ConnectTimeout, 0); event_add(timeout_event, &timeout); } std::thread(ClientThread).detach(); return true; } void DuelClient::ConnectTimeout(evutil_socket_t fd, short events, void* arg) { if(connect_state == 0x7) return; if(!is_closing) { mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->gMutex.lock(); if(bot_mode && !mainGame->wSinglePlay->isVisible()) mainGame->ShowElement(mainGame->wSinglePlay); else if(!bot_mode && !mainGame->wLanWindow->isVisible()) mainGame->ShowElement(mainGame->wLanWindow); soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", dataManager.GetSysString(1400)); mainGame->gMutex.unlock(); } event_base_loopbreak(client_base); } void DuelClient::StopClient(bool is_exiting) { if(connect_state != 0x7) return; is_closing = is_exiting; if(!is_closing) { } event_base_loopbreak(client_base); } void DuelClient::ClientRead(bufferevent* bev, void* ctx) { evbuffer* input = bufferevent_get_input(bev); int len = evbuffer_get_length(input); if (len < 2) return; unsigned char* duel_client_read = new unsigned char[SIZE_NETWORK_BUFFER]; uint16_t packet_len = 0; while (len >= 2) { evbuffer_copyout(input, &packet_len, sizeof packet_len); if (len < packet_len + 2) break; int read_len = evbuffer_remove(input, duel_client_read, packet_len + 2); if (read_len > 2) HandleSTOCPacketLan(&duel_client_read[2], read_len - 2); len -= packet_len + 2; } delete[] duel_client_read; } void DuelClient::ClientEvent(bufferevent* bev, short events, void* ctx) { if (events & BEV_EVENT_CONNECTED) { bool create_game = (intptr_t)ctx; if(!create_game) { uint16_t hostname_buf[LEN_HOSTNAME]; auto hostname_len = BufferIO::CopyCharArray(mainGame->ebJoinHost->getText(), hostname_buf); auto hostname_msglen = (hostname_len + 1) * sizeof(uint16_t); char buf[LEN_HOSTNAME * sizeof(uint16_t) + sizeof(uint32_t)]; memset(buf, 0, sizeof(uint32_t)); // real_ip memcpy(buf + sizeof(uint32_t), hostname_buf, hostname_msglen); SendBufferToServer(CTOS_EXTERNAL_ADDRESS, buf, hostname_msglen + sizeof(uint32_t)); } CTOS_PlayerInfo cspi; BufferIO::CopyCharArray(mainGame->ebNickName->getText(), cspi.name); SendPacketToServer(CTOS_PLAYER_INFO, cspi); if(create_game) { CTOS_CreateGame cscg; if(bot_mode) { BufferIO::CopyCharArray(L"Bot Game", cscg.name); BufferIO::CopyCharArray(L"", cscg.pass); cscg.info.rule = 5; cscg.info.mode = 0; cscg.info.start_hand = 5; cscg.info.start_lp = 8000; cscg.info.draw_count = 1; cscg.info.time_limit = 0; cscg.info.lflist = 0; cscg.info.duel_rule = mainGame->cbBotRule->getSelected() + 3; cscg.info.no_check_deck = mainGame->chkBotNoCheckDeck->isChecked(); cscg.info.no_shuffle_deck = mainGame->chkBotNoShuffleDeck->isChecked(); } else { BufferIO::CopyCharArray(mainGame->ebServerName->getText(), cscg.name); BufferIO::CopyCharArray(mainGame->ebServerPass->getText(), cscg.pass); cscg.info.rule = mainGame->cbRule->getSelected(); cscg.info.mode = mainGame->cbMatchMode->getSelected(); cscg.info.start_hand = std::wcstol(mainGame->ebStartHand->getText(),nullptr,10); cscg.info.start_lp = std::wcstol(mainGame->ebStartLP->getText(),nullptr,10); cscg.info.draw_count = std::wcstol(mainGame->ebDrawCount->getText(),nullptr,10); cscg.info.time_limit = std::wcstol(mainGame->ebTimeLimit->getText(),nullptr,10); cscg.info.lflist = mainGame->cbHostLFlist->getItemData(mainGame->cbHostLFlist->getSelected()); cscg.info.duel_rule = mainGame->cbDuelRule->getSelected() + 1; cscg.info.no_check_deck = mainGame->chkNoCheckDeck->isChecked(); cscg.info.no_shuffle_deck = mainGame->chkNoShuffleDeck->isChecked(); } SendPacketToServer(CTOS_CREATE_GAME, cscg); } else { CTOS_JoinGame csjg; csjg.version = PRO_VERSION; csjg.gameid = 0; BufferIO::CopyCharArray(mainGame->ebJoinPass->getText(), csjg.pass); SendPacketToServer(CTOS_JOIN_GAME, csjg); } bufferevent_enable(bev, EV_READ); connect_state |= 0x2; } else if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { bufferevent_disable(bev, EV_READ); if(!is_closing) { if(connect_state == 0x1) { mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->gMutex.lock(); if(bot_mode && !mainGame->wSinglePlay->isVisible()) mainGame->ShowElement(mainGame->wSinglePlay); else if(!bot_mode && !mainGame->wLanWindow->isVisible()) mainGame->ShowElement(mainGame->wLanWindow); soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", dataManager.GetSysString(1400)); mainGame->gMutex.unlock(); } else if(connect_state == 0x7) { if(!mainGame->dInfo.isStarted && !mainGame->is_building) { mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->gMutex.lock(); mainGame->HideElement(mainGame->wHostPrepare); if(bot_mode) mainGame->ShowElement(mainGame->wSinglePlay); else mainGame->ShowElement(mainGame->wLanWindow); mainGame->wChat->setVisible(false); soundManager.PlaySoundEffect(SOUND_INFO); if(events & BEV_EVENT_EOF) mainGame->env->addMessageBox(L"", dataManager.GetSysString(1401)); else mainGame->env->addMessageBox(L"", dataManager.GetSysString(1402)); mainGame->gMutex.unlock(); } else { mainGame->gMutex.lock(); soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", dataManager.GetSysString(1502)); mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->stTip->setVisible(false); mainGame->gMutex.unlock(); mainGame->closeDoneSignal.Reset(); mainGame->closeSignal.Set(); mainGame->closeDoneSignal.Wait(); mainGame->gMutex.lock(); mainGame->dInfo.isStarted = false; mainGame->dInfo.isInDuel = false; mainGame->dInfo.isFinished = false; mainGame->is_building = false; mainGame->ResizeChatInputWindow(); mainGame->device->setEventReceiver(&mainGame->menuHandler); if(bot_mode) mainGame->ShowElement(mainGame->wSinglePlay); else mainGame->ShowElement(mainGame->wLanWindow); mainGame->gMutex.unlock(); } } } event_base_loopexit(client_base, 0); } } int DuelClient::ClientThread() { event_base_dispatch(client_base); bufferevent_free(client_bev); event_base_free(client_base); client_bev = 0; client_base = 0; connect_state = 0; return 0; } void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { unsigned char* pdata = data; unsigned char pktType = BufferIO::Read(pdata); switch(pktType) { case STOC_GAME_MSG: { if (len < 1 + (int)sizeof(unsigned char)) return; ClientAnalyze(pdata, len - 1); break; } case STOC_ERROR_MSG: { if (len < 1 + (int)sizeof(STOC_ErrorMsg)) return; STOC_ErrorMsg packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; switch(pkt->msg) { case ERRMSG_JOINERROR: { mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->gMutex.lock(); soundManager.PlaySoundEffect(SOUND_INFO); if(pkt->code == 0) mainGame->env->addMessageBox(L"", dataManager.GetSysString(1403)); else if(pkt->code == 1) mainGame->env->addMessageBox(L"", dataManager.GetSysString(1404)); else if(pkt->code == 2) mainGame->env->addMessageBox(L"", dataManager.GetSysString(1405)); mainGame->gMutex.unlock(); event_base_loopbreak(client_base); break; } case ERRMSG_DECKERROR: { mainGame->gMutex.lock(); unsigned int code = pkt->code & MAX_CARD_ID; unsigned int flag = pkt->code >> 28; wchar_t msgbuf[256]; switch(flag) { case DECKERROR_LFLIST: { myswprintf(msgbuf, dataManager.GetSysString(1407), dataManager.GetName(code)); break; } case DECKERROR_OCGONLY: { myswprintf(msgbuf, dataManager.GetSysString(1413), dataManager.GetName(code)); break; } case DECKERROR_TCGONLY: { myswprintf(msgbuf, dataManager.GetSysString(1414), dataManager.GetName(code)); break; } case DECKERROR_UNKNOWNCARD: { myswprintf(msgbuf, dataManager.GetSysString(1415), dataManager.GetName(code), code); break; } case DECKERROR_CARDCOUNT: { myswprintf(msgbuf, dataManager.GetSysString(1416), dataManager.GetName(code)); break; } case DECKERROR_MAINCOUNT: { myswprintf(msgbuf, dataManager.GetSysString(1417), code); break; } case DECKERROR_EXTRACOUNT: { if(code>0) myswprintf(msgbuf, dataManager.GetSysString(1418), code); else myswprintf(msgbuf, dataManager.GetSysString(1420)); break; } case DECKERROR_SIDECOUNT: { myswprintf(msgbuf, dataManager.GetSysString(1419), code); break; } case DECKERROR_NOTAVAIL: { myswprintf(msgbuf, dataManager.GetSysString(1432), dataManager.GetName(code)); break; } default: { myswprintf(msgbuf, dataManager.GetSysString(1406)); break; } } soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", msgbuf); mainGame->cbCategorySelect->setEnabled(true); mainGame->cbDeckSelect->setEnabled(true); mainGame->gMutex.unlock(); break; } case ERRMSG_SIDEERROR: { mainGame->gMutex.lock(); soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", dataManager.GetSysString(1408)); mainGame->gMutex.unlock(); break; } case ERRMSG_VERERROR: { mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->gMutex.lock(); wchar_t msgbuf[256]; myswprintf(msgbuf, dataManager.GetSysString(1411), pkt->code >> 12, (pkt->code >> 4) & 0xff, pkt->code & 0xf); soundManager.PlaySoundEffect(SOUND_INFO); mainGame->env->addMessageBox(L"", msgbuf); mainGame->gMutex.unlock(); event_base_loopbreak(client_base); break; } } break; } case STOC_SELECT_HAND: { mainGame->wHand->setVisible(true); break; } case STOC_SELECT_TP: { mainGame->gMutex.lock(); mainGame->PopupElement(mainGame->wFTSelect); mainGame->gMutex.unlock(); break; } case STOC_HAND_RESULT: { if (len < 1 + (int)sizeof(STOC_HandResult)) return; STOC_HandResult packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; mainGame->stHintMsg->setVisible(false); mainGame->showcardcode = (pkt->res1 - 1) + ((pkt->res2 - 1) << 16); mainGame->showcarddif = 50; mainGame->showcardp = 0; mainGame->showcard = 100; mainGame->WaitFrameSignal(60); break; } case STOC_TP_RESULT: { break; } case STOC_CHANGE_SIDE: { mainGame->gMutex.lock(); mainGame->dInfo.isStarted = false; mainGame->dInfo.isInDuel = false; mainGame->dField.Clear(); mainGame->is_building = true; mainGame->is_siding = true; mainGame->CloseGameWindow(); mainGame->ResizeChatInputWindow(); mainGame->wDeckEdit->setVisible(false); mainGame->wFilter->setVisible(false); mainGame->wSort->setVisible(false); if(mainGame->dInfo.player_type < 7) mainGame->btnLeaveGame->setVisible(false); mainGame->btnSideOK->setVisible(true); mainGame->btnSideShuffle->setVisible(true); mainGame->btnSideSort->setVisible(true); mainGame->btnSideReload->setVisible(true); mainGame->deckBuilder.result_string[0] = L'0'; mainGame->deckBuilder.result_string[1] = 0; mainGame->deckBuilder.results.clear(); mainGame->deckBuilder.hovered_code = 0; mainGame->deckBuilder.is_draging = false; mainGame->deckBuilder.is_starting_dragging = false; mainGame->deckBuilder.readonly = false; mainGame->deckBuilder.showing_pack = false; mainGame->deckBuilder.pre_mainc = deckManager.current_deck.main.size(); mainGame->deckBuilder.pre_extrac = deckManager.current_deck.extra.size(); mainGame->deckBuilder.pre_sidec = deckManager.current_deck.side.size(); mainGame->device->setEventReceiver(&mainGame->deckBuilder); mainGame->gMutex.unlock(); break; } case STOC_WAITING_SIDE: { mainGame->dInfo.isInDuel = false; mainGame->gMutex.lock(); mainGame->dField.Clear(); mainGame->stHintMsg->setText(dataManager.GetSysString(1409)); mainGame->stHintMsg->setVisible(true); mainGame->gMutex.unlock(); break; } case STOC_DECK_COUNT: { if (len < 1 + (int)sizeof(int16_t) * 6) return; mainGame->gMutex.lock(); int deckc = BufferIO::Read(pdata); int extrac = BufferIO::Read(pdata); int sidec = BufferIO::Read(pdata); mainGame->dField.Initial(0, deckc, extrac, sidec); deckc = BufferIO::Read(pdata); extrac = BufferIO::Read(pdata); sidec = BufferIO::Read(pdata); mainGame->dField.Initial(1, deckc, extrac, sidec); mainGame->gMutex.unlock(); break; } case STOC_JOIN_GAME: { if (len < 1 + (int)sizeof(STOC_JoinGame)) return; STOC_JoinGame packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; std::wstring str; wchar_t msgbuf[256]; myswprintf(msgbuf, L"%ls%ls\n", dataManager.GetSysString(1226), deckManager.GetLFListName(pkt->info.lflist)); str.append(msgbuf); myswprintf(msgbuf, L"%ls%ls\n", dataManager.GetSysString(1225), dataManager.GetSysString(1481 + pkt->info.rule)); str.append(msgbuf); myswprintf(msgbuf, L"%ls%ls\n", dataManager.GetSysString(1227), dataManager.GetSysString(1244 + pkt->info.mode)); str.append(msgbuf); if(pkt->info.time_limit) { myswprintf(msgbuf, L"%ls%d\n", dataManager.GetSysString(1237), pkt->info.time_limit); str.append(msgbuf); } str.append(L"==========\n"); myswprintf(msgbuf, L"%ls%d\n", dataManager.GetSysString(1231), pkt->info.start_lp); str.append(msgbuf); myswprintf(msgbuf, L"%ls%d\n", dataManager.GetSysString(1232), pkt->info.start_hand); str.append(msgbuf); myswprintf(msgbuf, L"%ls%d\n", dataManager.GetSysString(1233), pkt->info.draw_count); str.append(msgbuf); if(pkt->info.duel_rule != DEFAULT_DUEL_RULE) { myswprintf(msgbuf, L"*%ls\n", dataManager.GetSysString(1260 + pkt->info.duel_rule - 1)); str.append(msgbuf); } if(pkt->info.no_check_deck) { myswprintf(msgbuf, L"*%ls\n", dataManager.GetSysString(1229)); str.append(msgbuf); } if(pkt->info.no_shuffle_deck) { myswprintf(msgbuf, L"*%ls\n", dataManager.GetSysString(1230)); str.append(msgbuf); } mainGame->gMutex.lock(); if(pkt->info.mode == 2) { mainGame->dInfo.isTag = true; mainGame->chkHostPrepReady[2]->setVisible(true); mainGame->chkHostPrepReady[3]->setVisible(true); mainGame->stHostPrepDuelist[2]->setVisible(true); mainGame->stHostPrepDuelist[3]->setVisible(true); } else { mainGame->dInfo.isTag = false; mainGame->chkHostPrepReady[2]->setVisible(false); mainGame->chkHostPrepReady[3]->setVisible(false); mainGame->stHostPrepDuelist[2]->setVisible(false); mainGame->stHostPrepDuelist[3]->setVisible(false); } for(int i = 0; i < 4; ++i) { mainGame->chkHostPrepReady[i]->setChecked(false); mainGame->stHostPrepDuelist[i]->setText(L""); mainGame->stHostPrepDuelist[i]->setToolTipText(L""); } mainGame->btnHostPrepReady->setVisible(true); mainGame->btnHostPrepNotReady->setVisible(false); mainGame->dInfo.time_limit = pkt->info.time_limit; mainGame->dInfo.time_left[0] = 0; mainGame->dInfo.time_left[1] = 0; mainGame->deckBuilder.filterList = deckManager.GetLFList(pkt->info.lflist); if(mainGame->deckBuilder.filterList == nullptr) mainGame->deckBuilder.filterList = &deckManager._lfList[0]; mainGame->stHostPrepOB->setText(L""); mainGame->SetStaticText(mainGame->stHostPrepRule, 180, mainGame->guiFont, str.c_str()); mainGame->RefreshCategoryDeck(mainGame->cbCategorySelect, mainGame->cbDeckSelect); mainGame->cbCategorySelect->setEnabled(true); mainGame->cbDeckSelect->setEnabled(true); mainGame->HideElement(mainGame->wCreateHost); mainGame->HideElement(mainGame->wLanWindow); mainGame->HideElement(mainGame->wSinglePlay); mainGame->ShowElement(mainGame->wHostPrepare); mainGame->ResizeChatInputWindow(); if(!mainGame->chkIgnore1->isChecked()) mainGame->wChat->setVisible(true); mainGame->gMutex.unlock(); mainGame->dInfo.duel_rule = pkt->info.duel_rule; mainGame->dInfo.start_lp = pkt->info.start_lp; watching = 0; connect_state |= 0x4; break; } case STOC_TYPE_CHANGE: { if (len < 1 + (int)sizeof(STOC_TypeChange)) return; STOC_TypeChange packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; if(!mainGame->dInfo.isTag) { selftype = pkt->type & 0xf; is_host = ((pkt->type >> 4) & 0xf) != 0; mainGame->btnHostPrepKick[2]->setVisible(false); mainGame->btnHostPrepKick[3]->setVisible(false); if(is_host) { mainGame->btnHostPrepStart->setVisible(true); mainGame->btnHostPrepKick[0]->setVisible(true); mainGame->btnHostPrepKick[1]->setVisible(true); } else { mainGame->btnHostPrepStart->setVisible(false); mainGame->btnHostPrepKick[0]->setVisible(false); mainGame->btnHostPrepKick[1]->setVisible(false); } mainGame->chkHostPrepReady[0]->setEnabled(false); mainGame->chkHostPrepReady[1]->setEnabled(false); if(selftype < 2) { mainGame->chkHostPrepReady[selftype]->setEnabled(true); mainGame->chkHostPrepReady[selftype]->setChecked(false); mainGame->btnHostPrepDuelist->setEnabled(false); mainGame->btnHostPrepOB->setEnabled(true); mainGame->btnHostPrepReady->setVisible(true); mainGame->btnHostPrepNotReady->setVisible(false); } else { mainGame->btnHostPrepDuelist->setEnabled(true); mainGame->btnHostPrepOB->setEnabled(false); mainGame->btnHostPrepReady->setVisible(false); mainGame->btnHostPrepNotReady->setVisible(false); } if(mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked()) { mainGame->btnHostPrepStart->setEnabled(true); } else { mainGame->btnHostPrepStart->setEnabled(false); } } else { if(selftype < 4) { mainGame->chkHostPrepReady[selftype]->setEnabled(false); mainGame->chkHostPrepReady[selftype]->setChecked(false); } selftype = pkt->type & 0xf; is_host = ((pkt->type >> 4) & 0xf) != 0; mainGame->btnHostPrepDuelist->setEnabled(true); if(is_host) { mainGame->btnHostPrepStart->setVisible(true); for(int i = 0; i < 4; ++i) mainGame->btnHostPrepKick[i]->setVisible(true); } else { mainGame->btnHostPrepStart->setVisible(false); for(int i = 0; i < 4; ++i) mainGame->btnHostPrepKick[i]->setVisible(false); } if(selftype < 4) { mainGame->chkHostPrepReady[selftype]->setEnabled(true); mainGame->btnHostPrepOB->setEnabled(true); mainGame->btnHostPrepReady->setVisible(true); mainGame->btnHostPrepNotReady->setVisible(false); } else { mainGame->btnHostPrepOB->setEnabled(false); mainGame->btnHostPrepReady->setVisible(false); mainGame->btnHostPrepNotReady->setVisible(false); } if(mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked() && mainGame->chkHostPrepReady[2]->isChecked() && mainGame->chkHostPrepReady[3]->isChecked()) { mainGame->btnHostPrepStart->setEnabled(true); } else { mainGame->btnHostPrepStart->setEnabled(false); } } mainGame->dInfo.player_type = selftype; break; } case STOC_DUEL_START: { mainGame->HideElement(mainGame->wHostPrepare); mainGame->WaitFrameSignal(11); mainGame->gMutex.lock(); mainGame->dField.Clear(); mainGame->dInfo.isStarted = true; mainGame->dInfo.isFinished = false; mainGame->dInfo.lp[0] = 0; mainGame->dInfo.lp[1] = 0; mainGame->dInfo.strLP[0][0] = 0; mainGame->dInfo.strLP[1][0] = 0; mainGame->dInfo.turn = 0; mainGame->dInfo.time_left[0] = 0; mainGame->dInfo.time_left[1] = 0; mainGame->dInfo.time_player = 2; mainGame->dInfo.isReplaySwapped = false; mainGame->is_building = false; mainGame->wCardImg->setVisible(true); mainGame->wInfos->setVisible(true); mainGame->wPhase->setVisible(true); mainGame->btnSideOK->setVisible(false); mainGame->btnSideShuffle->setVisible(false); mainGame->btnSideSort->setVisible(false); mainGame->btnSideReload->setVisible(false); mainGame->btnPhaseStatus->setVisible(false); mainGame->btnBP->setVisible(false); mainGame->btnM2->setVisible(false); mainGame->btnEP->setVisible(false); mainGame->btnShuffle->setVisible(false); mainGame->ResizeChatInputWindow(); if(!mainGame->chkIgnore1->isChecked()) mainGame->wChat->setVisible(true); if(mainGame->chkDefaultShowChain->isChecked()) { mainGame->always_chain = true; mainGame->ignore_chain = false; mainGame->chain_when_avail = false; } mainGame->device->setEventReceiver(&mainGame->dField); if(!mainGame->dInfo.isTag) { if(selftype > 1) { mainGame->dInfo.player_type = NETPLAYER_TYPE_OBSERVER; mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350)); mainGame->btnLeaveGame->setVisible(true); mainGame->btnSpectatorSwap->setVisible(true); } if(selftype != 1) { BufferIO::CopyWideString(mainGame->stHostPrepDuelist[0]->getToolTipText().c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[1]->getToolTipText().c_str(), mainGame->dInfo.clientname); } else { BufferIO::CopyWideString(mainGame->stHostPrepDuelist[1]->getToolTipText().c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[0]->getToolTipText().c_str(), mainGame->dInfo.clientname); } } else { if(selftype > 3) { mainGame->dInfo.player_type = NETPLAYER_TYPE_OBSERVER; mainGame->btnLeaveGame->setText(dataManager.GetSysString(1350)); mainGame->btnLeaveGame->setVisible(true); mainGame->btnSpectatorSwap->setVisible(true); } if(selftype > 1 && selftype < 4) { BufferIO::CopyWideString(mainGame->stHostPrepDuelist[2]->getToolTipText().c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[3]->getToolTipText().c_str(), mainGame->dInfo.hostname_tag); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[0]->getToolTipText().c_str(), mainGame->dInfo.clientname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[1]->getToolTipText().c_str(), mainGame->dInfo.clientname_tag); } else { BufferIO::CopyWideString(mainGame->stHostPrepDuelist[0]->getToolTipText().c_str(), mainGame->dInfo.hostname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[1]->getToolTipText().c_str(), mainGame->dInfo.hostname_tag); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[2]->getToolTipText().c_str(), mainGame->dInfo.clientname); BufferIO::CopyWideString(mainGame->stHostPrepDuelist[3]->getToolTipText().c_str(), mainGame->dInfo.clientname_tag); } mainGame->dInfo.tag_player[0] = false; mainGame->dInfo.tag_player[1] = false; } mainGame->gMutex.unlock(); match_kill = 0; break; } case STOC_DUEL_END: { mainGame->gMutex.lock(); if(mainGame->dInfo.player_type < 7) mainGame->btnLeaveGame->setVisible(false); mainGame->CloseGameButtons(); mainGame->stMessage->setText(dataManager.GetSysString(1500)); mainGame->PopupElement(mainGame->wMessage); mainGame->gMutex.unlock(); mainGame->actionSignal.Reset(); mainGame->actionSignal.Wait(); mainGame->closeDoneSignal.Reset(); mainGame->closeSignal.Set(); mainGame->closeDoneSignal.Wait(); mainGame->gMutex.lock(); mainGame->dInfo.isStarted = false; mainGame->dInfo.isInDuel = false; mainGame->dInfo.isFinished = true; mainGame->is_building = false; mainGame->wDeckEdit->setVisible(false); mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->stTip->setVisible(false); mainGame->ResizeChatInputWindow(); mainGame->device->setEventReceiver(&mainGame->menuHandler); if(bot_mode) mainGame->ShowElement(mainGame->wSinglePlay); else mainGame->ShowElement(mainGame->wLanWindow); mainGame->gMutex.unlock(); event_base_loopbreak(client_base); if(exit_on_return) mainGame->device->closeDevice(); break; } case STOC_REPLAY: { if (len < 1 + (int)sizeof(ExtendedReplayHeader)) return; mainGame->gMutex.lock(); mainGame->wPhase->setVisible(false); if(mainGame->dInfo.player_type < 7) mainGame->btnLeaveGame->setVisible(false); mainGame->CloseGameButtons(); auto prep = pdata; Replay new_replay; std::memcpy(&new_replay.pheader, prep, sizeof(new_replay.pheader)); time_t starttime; if (new_replay.pheader.base.flag & REPLAY_UNIFORM) starttime = new_replay.pheader.base.start_time; else starttime = new_replay.pheader.base.seed; wchar_t timetext[40]; std::wcsftime(timetext, sizeof timetext / sizeof timetext[0], L"%Y-%m-%d %H-%M-%S", std::localtime(&starttime)); mainGame->ebRSName->setText(timetext); if(!mainGame->chkAutoSaveReplay->isChecked()) { mainGame->wReplaySave->setText(dataManager.GetSysString(1340)); mainGame->PopupElement(mainGame->wReplaySave); mainGame->gMutex.unlock(); mainGame->replaySignal.Reset(); mainGame->replaySignal.Wait(); } else { mainGame->actionParam = 1; wchar_t msgbuf[256]; myswprintf(msgbuf, dataManager.GetSysString(1367), timetext); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, msgbuf); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(30); } if(mainGame->actionParam || !is_host) { prep += sizeof new_replay.pheader; std::memcpy(new_replay.comp_data, prep, len - sizeof new_replay.pheader - 1); new_replay.comp_size = len - sizeof new_replay.pheader - 1; if(mainGame->actionParam) new_replay.SaveReplay(mainGame->ebRSName->getText()); else new_replay.SaveReplay(L"_LastReplay"); } break; } case STOC_TIME_LIMIT: { if (len < 1 + (int)sizeof(STOC_TimeLimit)) return; STOC_TimeLimit packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; int lplayer = mainGame->LocalPlayer(pkt->player); if(lplayer == 0) DuelClient::SendPacketToServer(CTOS_TIME_CONFIRM); mainGame->dInfo.time_player = lplayer; mainGame->dInfo.time_left[lplayer] = pkt->left_time; break; } case STOC_CHAT: { if (len < 1 + sizeof(uint16_t) + sizeof(uint16_t) * 1) return; if (len > 1 + sizeof(uint16_t) + sizeof(uint16_t) * LEN_CHAT_MSG) return; const int chat_msg_size = len - 1 - sizeof(uint16_t); if (chat_msg_size % sizeof(uint16_t)) return; uint16_t chat_player_type = BufferIO::Read(pdata); uint16_t chat_msg[LEN_CHAT_MSG]; std::memcpy(chat_msg, pdata, chat_msg_size); pdata += chat_msg_size; const int chat_msg_len = chat_msg_size / sizeof(uint16_t); if (chat_msg[chat_msg_len - 1] != 0) return; int player = chat_player_type; auto play_sound = false; if(player < 4) { if(mainGame->chkIgnore1->isChecked()) break; auto localplayer = mainGame->ChatLocalPlayer(player); player = localplayer & 0xf; if(!(localplayer & 0x10)) play_sound = true; } else { if(player == 8) { //system custom message. play_sound = true; if(mainGame->chkIgnore1->isChecked()) break; } else if(player < 11 || player > 19) { if(mainGame->chkIgnore2->isChecked()) break; player = 10; } } // UTF-16 to wchar_t wchar_t msg[LEN_CHAT_MSG]; BufferIO::CopyCharArray(chat_msg, msg); mainGame->gMutex.lock(); mainGame->AddChatMsg(msg, player, play_sound); mainGame->gMutex.unlock(); break; } case STOC_HS_PLAYER_ENTER: { if (len < 1 + STOC_HS_PlayerEnter_size) return; soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER); STOC_HS_PlayerEnter packet; std::memcpy(&packet, pdata, STOC_HS_PlayerEnter_size); auto pkt = &packet; if(pkt->pos > 3) break; wchar_t name[20]; BufferIO::NullTerminate(pkt->name); BufferIO::CopyCharArray(pkt->name, name); if(mainGame->dInfo.isTag) { if(pkt->pos == 0) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.hostname); else if(pkt->pos == 1) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.hostname_tag); else if(pkt->pos == 2) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.clientname); else if(pkt->pos == 3) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.clientname_tag); } else { if(pkt->pos == 0) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.hostname); else if(pkt->pos == 1) BufferIO::CopyCharArray(pkt->name, mainGame->dInfo.clientname); } mainGame->gMutex.lock(); if(mainGame->gameConf.hide_player_name) mainGame->stHostPrepDuelist[pkt->pos]->setText(L"[********]"); else mainGame->stHostPrepDuelist[pkt->pos]->setText(name); mainGame->stHostPrepDuelist[pkt->pos]->setToolTipText(name); mainGame->gMutex.unlock(); mainGame->FlashWindow(); break; } case STOC_HS_PLAYER_CHANGE: { if (len < 1 + (int)sizeof(STOC_HS_PlayerChange)) return; STOC_HS_PlayerChange packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; unsigned char pos = (pkt->status >> 4) & 0xf; unsigned char state = pkt->status & 0xf; if(pos > 3) break; mainGame->gMutex.lock(); if(state < 8) { soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER); const wchar_t* prename = mainGame->stHostPrepDuelist[pos]->getToolTipText().c_str(); if(mainGame->gameConf.hide_player_name) mainGame->stHostPrepDuelist[state]->setText(L"[********]"); else mainGame->stHostPrepDuelist[state]->setText(prename); mainGame->stHostPrepDuelist[state]->setToolTipText(prename); mainGame->stHostPrepDuelist[pos]->setText(L""); mainGame->stHostPrepDuelist[pos]->setToolTipText(L""); mainGame->chkHostPrepReady[pos]->setChecked(false); if(pos == 0) BufferIO::CopyCharArray(prename, mainGame->dInfo.hostname); else if(pos == 1) BufferIO::CopyCharArray(prename, mainGame->dInfo.hostname_tag); else if(pos == 2) BufferIO::CopyCharArray(prename, mainGame->dInfo.clientname); else if(pos == 3) BufferIO::CopyCharArray(prename, mainGame->dInfo.clientname_tag); } else if(state == PLAYERCHANGE_READY) { mainGame->chkHostPrepReady[pos]->setChecked(true); if(pos == selftype) { mainGame->btnHostPrepReady->setVisible(false); mainGame->btnHostPrepNotReady->setVisible(true); } } else if(state == PLAYERCHANGE_NOTREADY) { mainGame->chkHostPrepReady[pos]->setChecked(false); if(pos == selftype) { mainGame->btnHostPrepReady->setVisible(true); mainGame->btnHostPrepNotReady->setVisible(false); } } else if(state == PLAYERCHANGE_LEAVE) { mainGame->stHostPrepDuelist[pos]->setText(L""); mainGame->stHostPrepDuelist[pos]->setToolTipText(L""); mainGame->chkHostPrepReady[pos]->setChecked(false); } else if(state == PLAYERCHANGE_OBSERVE) { watching++; wchar_t watchbuf[32]; myswprintf(watchbuf, L"%ls%d", dataManager.GetSysString(1253), watching); mainGame->stHostPrepDuelist[pos]->setText(L""); mainGame->stHostPrepDuelist[pos]->setToolTipText(L""); mainGame->chkHostPrepReady[pos]->setChecked(false); mainGame->stHostPrepOB->setText(watchbuf); } if(mainGame->chkHostPrepReady[0]->isChecked() && mainGame->chkHostPrepReady[1]->isChecked() && (!mainGame->dInfo.isTag || (mainGame->chkHostPrepReady[2]->isChecked() && mainGame->chkHostPrepReady[3]->isChecked()))) { mainGame->btnHostPrepStart->setEnabled(true); } else { mainGame->btnHostPrepStart->setEnabled(false); } mainGame->gMutex.unlock(); break; } case STOC_HS_WATCH_CHANGE: { if (len < 1 + (int)sizeof(STOC_HS_WatchChange)) return; STOC_HS_WatchChange packet; std::memcpy(&packet, pdata, sizeof packet); const auto* pkt = &packet; watching = pkt->watch_count; wchar_t watchbuf[32]; myswprintf(watchbuf, L"%ls%d", dataManager.GetSysString(1253), watching); mainGame->gMutex.lock(); mainGame->stHostPrepOB->setText(watchbuf); mainGame->gMutex.unlock(); break; } case STOC_TEAMMATE_SURRENDER: { if(!mainGame->dField.tag_surrender) mainGame->dField.tag_teammate_surrender = true; mainGame->btnLeaveGame->setText(dataManager.GetSysString(1355)); break; } } } // Analyze STOC_GAME_MSG packet bool DuelClient::ClientAnalyze(unsigned char* msg, int len) { unsigned char* pbuf = msg; wchar_t textBuffer[256]; mainGame->dInfo.curMsg = BufferIO::Read(pbuf); if(mainGame->dInfo.curMsg != MSG_RETRY) { std::memcpy(last_successful_msg, msg, len); last_successful_msg_length = len; } mainGame->dField.HideMenu(); if(!mainGame->dInfo.isReplay && mainGame->dInfo.curMsg != MSG_WAITING && mainGame->dInfo.curMsg != MSG_CARD_SELECTED) { mainGame->waitFrame = -1; mainGame->stHintMsg->setVisible(false); if(mainGame->wCardSelect->isVisible()) { mainGame->gMutex.lock(); mainGame->HideElement(mainGame->wCardSelect); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(11); } if(mainGame->wOptions->isVisible()) { mainGame->gMutex.lock(); mainGame->HideElement(mainGame->wOptions); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(11); } } if(mainGame->dInfo.time_player == 1) mainGame->dInfo.time_player = 2; if(is_swapping) { mainGame->gMutex.lock(); mainGame->dField.ReplaySwap(); mainGame->gMutex.unlock(); is_swapping = false; } switch(mainGame->dInfo.curMsg) { case MSG_RETRY: { if(last_successful_msg_length) { auto p = last_successful_msg; auto last_msg = BufferIO::Read(p); int err_desc = 1421; switch(last_msg) { case MSG_ANNOUNCE_CARD: err_desc = 1422; break; case MSG_ANNOUNCE_ATTRIB: err_desc = 1423; break; case MSG_ANNOUNCE_RACE: err_desc = 1424; break; case MSG_ANNOUNCE_NUMBER: err_desc = 1425; break; case MSG_SELECT_EFFECTYN: case MSG_SELECT_YESNO: case MSG_SELECT_OPTION: err_desc = 1426; break; case MSG_SELECT_CARD: case MSG_SELECT_UNSELECT_CARD: case MSG_SELECT_TRIBUTE: case MSG_SELECT_SUM: case MSG_SORT_CARD: err_desc = 1427; break; case MSG_SELECT_CHAIN: err_desc = 1428; break; case MSG_SELECT_PLACE: case MSG_SELECT_DISFIELD: err_desc = 1429; break; case MSG_SELECT_POSITION: err_desc = 1430; break; case MSG_SELECT_COUNTER: err_desc = 1431; break; default: break; } mainGame->gMutex.lock(); mainGame->stMessage->setText(dataManager.GetDesc(err_desc)); mainGame->PopupElement(mainGame->wMessage); mainGame->gMutex.unlock(); mainGame->actionSignal.Reset(); mainGame->actionSignal.Wait(); select_hint = last_select_hint; return ClientAnalyze(last_successful_msg, last_successful_msg_length); } mainGame->gMutex.lock(); mainGame->stMessage->setText(L"Error occurs."); mainGame->PopupElement(mainGame->wMessage); mainGame->gMutex.unlock(); mainGame->actionSignal.Reset(); mainGame->actionSignal.Wait(); if(!mainGame->dInfo.isSingleMode) { mainGame->closeDoneSignal.Reset(); mainGame->closeSignal.Set(); mainGame->closeDoneSignal.Wait(); mainGame->gMutex.lock(); mainGame->dInfo.isStarted = false; mainGame->dInfo.isInDuel = false; mainGame->dInfo.isFinished = false; mainGame->btnCreateHost->setEnabled(true); mainGame->btnJoinHost->setEnabled(true); mainGame->btnJoinCancel->setEnabled(true); mainGame->btnStartBot->setEnabled(true); mainGame->btnBotCancel->setEnabled(true); mainGame->stTip->setVisible(false); mainGame->device->setEventReceiver(&mainGame->menuHandler); if(bot_mode) mainGame->ShowElement(mainGame->wSinglePlay); else mainGame->ShowElement(mainGame->wLanWindow); mainGame->gMutex.unlock(); event_base_loopbreak(client_base); if(exit_on_return) mainGame->device->closeDevice(); } return false; } case MSG_HINT: { int type = BufferIO::Read(pbuf); int player = BufferIO::Read(pbuf); int data = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; switch (type) { case HINT_EVENT: { myswprintf(event_string, L"%ls", dataManager.GetDesc(data)); break; } case HINT_MESSAGE: { mainGame->gMutex.lock(); mainGame->stMessage->setText(dataManager.GetDesc(data)); mainGame->PopupElement(mainGame->wMessage); mainGame->gMutex.unlock(); mainGame->actionSignal.Reset(); mainGame->actionSignal.Wait(); break; } case HINT_SELECTMSG: { select_hint = data; last_select_hint = data; break; } case HINT_OPSELECTED: { myswprintf(textBuffer, dataManager.GetSysString(1510), dataManager.GetDesc(data)); mainGame->AddLog(textBuffer); mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); break; } case HINT_EFFECT: { mainGame->showcardcode = data; mainGame->showcarddif = 0; mainGame->showcard = 1; mainGame->WaitFrameSignal(30); break; } case HINT_RACE: { myswprintf(textBuffer, dataManager.GetSysString(1511), dataManager.FormatRace(data).c_str()); mainGame->AddLog(textBuffer); mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); break; } case HINT_ATTRIB: { myswprintf(textBuffer, dataManager.GetSysString(1511), dataManager.FormatAttribute(data).c_str()); mainGame->AddLog(textBuffer); mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); break; } case HINT_CODE: { myswprintf(textBuffer, dataManager.GetSysString(1511), dataManager.GetName(data)); mainGame->AddLog(textBuffer, data); mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); break; } case HINT_NUMBER: { myswprintf(textBuffer, dataManager.GetSysString(1512), data); mainGame->AddLog(textBuffer); mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stACMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); break; } case HINT_CARD: { mainGame->showcardcode = data; mainGame->showcarddif = 0; mainGame->showcard = 1; mainGame->WaitFrameSignal(30); break; } case HINT_ZONE: { if(mainGame->LocalPlayer(player) == 1) data = (data >> 16) | (data << 16); for(unsigned filter = 0x1; filter != 0; filter <<= 1) { std::wstring str; if(unsigned s = filter & data) { if(s & 0x60) { str += dataManager.GetSysString(1081); data &= ~0x600000; } else if(s & 0xffff) str += dataManager.GetSysString(102); else if(s & 0xffff0000) { str += dataManager.GetSysString(103); s >>= 16; } if(s & 0x1f) str += dataManager.GetSysString(1002); else if(s & 0xff00) { s >>= 8; if(s & 0x1f) str += dataManager.GetSysString(1003); else if(s & 0x20) str += dataManager.GetSysString(1008); else if(s & 0xc0) str += dataManager.GetSysString(1009); } int seq = 1; for(int i = 0x1; i < 0x100; i <<= 1) { if(s & i) break; ++seq; } str += L"(" + std::to_wstring(seq) + L")"; myswprintf(textBuffer, dataManager.GetSysString(1510), str.c_str()); mainGame->AddLog(textBuffer); } } mainGame->dField.selectable_field = data; mainGame->WaitFrameSignal(40); mainGame->dField.selectable_field = 0; break; } } break; } case MSG_WIN: { mainGame->dInfo.isFinished = true; int player = BufferIO::Read(pbuf); int type = BufferIO::Read(pbuf); mainGame->showcarddif = 110; mainGame->showcardp = 0; mainGame->dInfo.vic_string = L""; wchar_t vic_buf[256]; if(player == 2) mainGame->showcardcode = 3; else { wchar_t vic_name[20]; if(mainGame->LocalPlayer(player) == 0) { mainGame->showcardcode = 1; myswprintf(vic_name, L"%ls", mainGame->dInfo.clientname); } else { mainGame->showcardcode = 2; myswprintf(vic_name, L"%ls", mainGame->dInfo.hostname); } if(mainGame->gameConf.hide_player_name) myswprintf(vic_name, L"********"); if(match_kill) myswprintf(vic_buf, dataManager.GetVictoryString(0xffff), dataManager.GetName(match_kill)); else if(type < 0x10) myswprintf(vic_buf, L"[%ls] %ls", vic_name, dataManager.GetVictoryString(type)); else myswprintf(vic_buf, L"%ls", dataManager.GetVictoryString(type)); mainGame->dInfo.vic_string = vic_buf; } mainGame->showcard = 101; mainGame->WaitFrameSignal(120); mainGame->dInfo.vic_string = L""; mainGame->showcard = 0; break; } case MSG_WAITING: { mainGame->waitFrame = 0; mainGame->gMutex.lock(); mainGame->stHintMsg->setText(dataManager.GetSysString(1390)); mainGame->stHintMsg->setVisible(true); mainGame->gMutex.unlock(); return true; } case MSG_START: { mainGame->showcardcode = 11; mainGame->showcarddif = 30; mainGame->showcardp = 0; mainGame->showcard = 101; mainGame->WaitFrameSignal(40); mainGame->showcard = 0; mainGame->gMutex.lock(); mainGame->dField.Clear(); mainGame->dInfo.isInDuel = true; int playertype = BufferIO::Read(pbuf); mainGame->dInfo.isFirst = (playertype & 0xf) ? false : true; if(playertype & 0xf0) mainGame->dInfo.player_type = 7; if(mainGame->dInfo.isTag) { if(mainGame->dInfo.isFirst) mainGame->dInfo.tag_player[1] = true; else mainGame->dInfo.tag_player[0] = true; } mainGame->dInfo.duel_rule = BufferIO::Read(pbuf); mainGame->dInfo.lp[mainGame->LocalPlayer(0)] = BufferIO::Read(pbuf); mainGame->dInfo.lp[mainGame->LocalPlayer(1)] = BufferIO::Read(pbuf); myswprintf(mainGame->dInfo.strLP[0], L"%d", mainGame->dInfo.lp[0]); myswprintf(mainGame->dInfo.strLP[1], L"%d", mainGame->dInfo.lp[1]); int deckc = BufferIO::Read(pbuf); int extrac = BufferIO::Read(pbuf); mainGame->dField.Initial(mainGame->LocalPlayer(0), deckc, extrac); deckc = BufferIO::Read(pbuf); extrac = BufferIO::Read(pbuf); mainGame->dField.Initial(mainGame->LocalPlayer(1), deckc, extrac); mainGame->dInfo.turn = 0; mainGame->dInfo.is_shuffling = false; select_hint = 0; select_unselect_hint = 0; last_select_hint = 0; last_successful_msg_length = 0; if(mainGame->dInfo.isReplaySwapped) { std::swap(mainGame->dInfo.hostname, mainGame->dInfo.clientname); std::swap(mainGame->dInfo.hostname_tag, mainGame->dInfo.clientname_tag); mainGame->dInfo.isReplaySwapped = false; mainGame->dField.ReplaySwap(); } mainGame->gMutex.unlock(); return true; } case MSG_UPDATE_DATA: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int location = BufferIO::Read(pbuf); mainGame->gMutex.lock(); mainGame->dField.UpdateFieldCard(player, location, pbuf); mainGame->gMutex.unlock(); return true; } case MSG_UPDATE_CARD: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int loc = BufferIO::Read(pbuf); int seq = BufferIO::Read(pbuf); mainGame->gMutex.lock(); mainGame->dField.UpdateCard(player, loc, seq, pbuf); mainGame->gMutex.unlock(); break; } case MSG_SELECT_BATTLECMD: { /*int selecting_player = */BufferIO::Read(pbuf); int desc, count, con, seq/*, diratt*/; unsigned int code, loc; ClientCard* pcard; mainGame->dField.activatable_cards.clear(); mainGame->dField.activatable_descs.clear(); mainGame->dField.conti_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); desc = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); int flag = 0; if(code & 0x80000000) { flag = EDESC_OPERATION; code &= 0x7fffffff; } mainGame->dField.activatable_cards.push_back(pcard); mainGame->dField.activatable_descs.push_back(std::make_pair(desc, flag)); if(flag & EDESC_OPERATION) { pcard->chain_code = code; mainGame->dField.conti_cards.push_back(pcard); mainGame->dField.conti_act = true; } else { pcard->cmdFlag |= COMMAND_ACTIVATE; if(pcard->location == LOCATION_GRAVE) mainGame->dField.grave_act[con] = true; else if(pcard->location == LOCATION_REMOVED) mainGame->dField.remove_act[con] = true; else if(pcard->location == LOCATION_EXTRA) mainGame->dField.extra_act[con] = true; } } mainGame->dField.attackable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { /*code = */BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); /*diratt = */BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.attackable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_ATTACK; } mainGame->gMutex.lock(); if(BufferIO::Read(pbuf)) { mainGame->btnM2->setVisible(true); mainGame->btnM2->setEnabled(true); mainGame->btnM2->setPressed(false); } if(BufferIO::Read(pbuf)) { mainGame->btnEP->setVisible(true); mainGame->btnEP->setEnabled(true); mainGame->btnEP->setPressed(false); } mainGame->gMutex.unlock(); return false; } case MSG_SELECT_IDLECMD: { /*int selecting_player = */BufferIO::Read(pbuf); int desc, count, con, seq; unsigned int code, loc; ClientCard* pcard; mainGame->dField.summonable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.summonable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_SUMMON; } mainGame->dField.spsummonable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.spsummonable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_SPSUMMON; if (pcard->location == LOCATION_DECK) { pcard->SetCode(code); mainGame->dField.deck_act[con] = true; } else if (pcard->location == LOCATION_GRAVE) mainGame->dField.grave_act[con] = true; else if (pcard->location == LOCATION_REMOVED) mainGame->dField.remove_act[con] = true; else if (pcard->location == LOCATION_EXTRA) mainGame->dField.extra_act[con] = true; else { int left_seq = mainGame->dInfo.duel_rule >= 4 ? 0 : 6; if (pcard->location == LOCATION_SZONE && pcard->sequence == left_seq && (pcard->type & TYPE_PENDULUM) && !pcard->equipTarget) mainGame->dField.pzone_act[con] = true; } } mainGame->dField.reposable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.reposable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_REPOS; } mainGame->dField.msetable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.msetable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_MSET; } mainGame->dField.ssetable_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); mainGame->dField.ssetable_cards.push_back(pcard); pcard->cmdFlag |= COMMAND_SSET; } mainGame->dField.activatable_cards.clear(); mainGame->dField.activatable_descs.clear(); mainGame->dField.conti_cards.clear(); count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); con = mainGame->LocalPlayer(BufferIO::Read(pbuf)); loc = BufferIO::Read(pbuf); seq = BufferIO::Read(pbuf); desc = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(con, loc, seq); int flag = 0; if(code & 0x80000000) { flag = EDESC_OPERATION; code &= 0x7fffffff; } mainGame->dField.activatable_cards.push_back(pcard); mainGame->dField.activatable_descs.push_back(std::make_pair(desc, flag)); if(flag & EDESC_OPERATION) { pcard->chain_code = code; mainGame->dField.conti_cards.push_back(pcard); mainGame->dField.conti_act = true; } else { pcard->cmdFlag |= COMMAND_ACTIVATE; if(pcard->location == LOCATION_GRAVE) mainGame->dField.grave_act[con] = true; else if(pcard->location == LOCATION_REMOVED) mainGame->dField.remove_act[con] = true; else if(pcard->location == LOCATION_EXTRA) mainGame->dField.extra_act[con] = true; } } if(BufferIO::Read(pbuf)) { mainGame->btnBP->setVisible(true); mainGame->btnBP->setEnabled(true); mainGame->btnBP->setPressed(false); } if(BufferIO::Read(pbuf)) { mainGame->btnEP->setVisible(true); mainGame->btnEP->setEnabled(true); mainGame->btnEP->setPressed(false); } if (BufferIO::Read(pbuf)) { mainGame->btnShuffle->setVisible(true); } else { mainGame->btnShuffle->setVisible(false); } return false; } case MSG_SELECT_EFFECTYN: { /*int selecting_player = */BufferIO::Read(pbuf); unsigned int code = BufferIO::Read(pbuf); int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(c, l, s); if (pcard->code != code) pcard->SetCode(code); BufferIO::Read(pbuf); if(l != LOCATION_DECK) { pcard->is_highlighting = true; mainGame->dField.highlighting_card = pcard; } int desc = BufferIO::Read(pbuf); if(desc == 0) { wchar_t ynbuf[256]; myswprintf(ynbuf, dataManager.GetSysString(200), dataManager.FormatLocation(l, s), dataManager.GetName(code)); myswprintf(textBuffer, L"%ls\n%ls", event_string, ynbuf); } else if(desc == 221) { wchar_t ynbuf[256]; myswprintf(ynbuf, dataManager.GetSysString(221), dataManager.FormatLocation(l, s), dataManager.GetName(code)); myswprintf(textBuffer, L"%ls\n%ls\n%ls", event_string, ynbuf, dataManager.GetSysString(223)); } else if(desc <= MAX_STRING_ID) { myswprintf(textBuffer, dataManager.GetSysString(desc), dataManager.GetName(code)); } else { myswprintf(textBuffer, dataManager.GetDesc(desc), dataManager.GetName(code)); } mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wQuery); mainGame->gMutex.unlock(); return false; } case MSG_SELECT_YESNO: { /*int selecting_player = */BufferIO::Read(pbuf); int desc = BufferIO::Read(pbuf); mainGame->dField.highlighting_card = 0; mainGame->gMutex.lock(); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, dataManager.GetDesc(desc)); mainGame->PopupElement(mainGame->wQuery); mainGame->gMutex.unlock(); return false; } case MSG_SELECT_OPTION: { /*int selecting_player = */BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.select_options.clear(); for (int i = 0; i < count; ++i) mainGame->dField.select_options.push_back(BufferIO::Read(pbuf)); mainGame->dField.ShowSelectOption(select_hint); select_hint = 0; return false; } case MSG_SELECT_CARD: { /*int selecting_player = */BufferIO::Read(pbuf); mainGame->dField.select_cancelable = BufferIO::Read(pbuf) != 0; mainGame->dField.select_min = BufferIO::Read(pbuf); mainGame->dField.select_max = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.selectable_cards.clear(); mainGame->dField.selected_cards.clear(); int c, s, ss; unsigned int l; unsigned int code; bool panelmode = false; size_t hand_count[2] = { mainGame->dField.hand[0].size(), mainGame->dField.hand[1].size() }; int select_count_in_hand[2] = { 0, 0 }; bool select_ready = mainGame->dField.select_min == 0; mainGame->dField.select_ready = select_ready; ClientCard* pcard; for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); ss = BufferIO::Read(pbuf); if (l & LOCATION_OVERLAY) pcard = mainGame->dField.GetCard(c, l & 0x7f, s)->overlayed[ss]; else pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->select_seq = i; mainGame->dField.selectable_cards.push_back(pcard); pcard->is_selectable = true; pcard->is_selected = false; if (l & 0xf1) panelmode = true; if((l & LOCATION_HAND) && hand_count[c] >= 10) { if(++select_count_in_hand[c] > 1) panelmode = true; } } std::sort(mainGame->dField.selectable_cards.begin(), mainGame->dField.selectable_cards.end(), ClientCard::client_card_sort); if(select_hint) myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetDesc(select_hint), mainGame->dField.select_min, mainGame->dField.select_max); else myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetSysString(560), mainGame->dField.select_min, mainGame->dField.select_max); select_hint = 0; if (panelmode) { mainGame->gMutex.lock(); mainGame->wCardSelect->setText(textBuffer); mainGame->dField.ShowSelectCard(select_ready); mainGame->gMutex.unlock(); } else { mainGame->stHintMsg->setText(textBuffer); mainGame->stHintMsg->setVisible(true); } if (mainGame->dField.select_cancelable) { mainGame->dField.ShowCancelOrFinishButton(1); } else if (select_ready) { mainGame->dField.ShowCancelOrFinishButton(2); } else { mainGame->dField.ShowCancelOrFinishButton(0); } return false; } case MSG_SELECT_UNSELECT_CARD: { /*int selecting_player = */BufferIO::Read(pbuf); bool finishable = BufferIO::Read(pbuf) != 0; bool cancelable = BufferIO::Read(pbuf) != 0; mainGame->dField.select_cancelable = finishable || cancelable; mainGame->dField.select_min = BufferIO::Read(pbuf); mainGame->dField.select_max = BufferIO::Read(pbuf); int count1 = BufferIO::Read(pbuf); mainGame->dField.selectable_cards.clear(); mainGame->dField.selected_cards.clear(); int c, s, ss; unsigned int l; unsigned int code; bool panelmode = false; size_t hand_count[2] = { mainGame->dField.hand[0].size(), mainGame->dField.hand[1].size() }; int select_count_in_hand[2] = { 0, 0 }; mainGame->dField.select_ready = false; ClientCard* pcard; for (int i = 0; i < count1; ++i) { code = (unsigned int)BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); ss = BufferIO::Read(pbuf); if (l & LOCATION_OVERLAY) pcard = mainGame->dField.GetCard(c, l & 0x7f, s)->overlayed[ss]; else pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->select_seq = i; mainGame->dField.selectable_cards.push_back(pcard); pcard->is_selectable = true; pcard->is_selected = false; if (l & 0xf1) panelmode = true; if((l & LOCATION_HAND) && hand_count[c] >= 10) { if(++select_count_in_hand[c] > 1) panelmode = true; } } int count2 = BufferIO::Read(pbuf); for (int i = count1; i < count1 + count2; ++i) { code = (unsigned int)BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); ss = BufferIO::Read(pbuf); if (l & LOCATION_OVERLAY) pcard = mainGame->dField.GetCard(c, l & 0x7f, s)->overlayed[ss]; else pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->select_seq = i; mainGame->dField.selectable_cards.push_back(pcard); pcard->is_selectable = true; pcard->is_selected = true; if (l & 0xf1) panelmode = true; if((l & LOCATION_HAND) && hand_count[c] >= 10) { if(++select_count_in_hand[c] > 1) panelmode = true; } } std::sort(mainGame->dField.selectable_cards.begin(), mainGame->dField.selectable_cards.end(), ClientCard::client_card_sort); if(select_hint) select_unselect_hint = select_hint; if(select_unselect_hint) myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetDesc(select_unselect_hint), mainGame->dField.select_min, mainGame->dField.select_max); else myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetSysString(560), mainGame->dField.select_min, mainGame->dField.select_max); select_hint = 0; if (panelmode) { mainGame->gMutex.lock(); mainGame->wCardSelect->setText(textBuffer); mainGame->dField.ShowSelectCard(mainGame->dField.select_cancelable); mainGame->gMutex.unlock(); } else { mainGame->stHintMsg->setText(textBuffer); mainGame->stHintMsg->setVisible(true); } if (mainGame->dField.select_cancelable) { if(finishable) { mainGame->dField.select_ready = true; mainGame->dField.ShowCancelOrFinishButton(2); } else { mainGame->dField.ShowCancelOrFinishButton(1); } } else mainGame->dField.ShowCancelOrFinishButton(0); return false; } case MSG_SELECT_CHAIN: { /*int selecting_player = */BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); int specount = BufferIO::Read(pbuf); /*int hint0 = */BufferIO::Read(pbuf); /*int hint1 = */BufferIO::Read(pbuf); int c, s, ss, desc; unsigned int code,l; ClientCard* pcard; bool panelmode = false; bool conti_exist = false; bool select_trigger = (specount == 0x7f); mainGame->dField.chain_forced = false; mainGame->dField.activatable_cards.clear(); mainGame->dField.activatable_descs.clear(); mainGame->dField.conti_cards.clear(); for (int i = 0; i < count; ++i) { int flag = BufferIO::Read(pbuf); int forced = BufferIO::Read(pbuf); flag |= forced << 8; code = BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); ss = BufferIO::Read(pbuf); desc = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(c, l, s, ss); mainGame->dField.activatable_cards.push_back(pcard); mainGame->dField.activatable_descs.push_back(std::make_pair(desc, flag)); pcard->is_selected = false; if(forced) { mainGame->dField.chain_forced = true; } if(flag & EDESC_OPERATION) { pcard->chain_code = code; mainGame->dField.conti_cards.push_back(pcard); mainGame->dField.conti_act = true; conti_exist = true; } else { pcard->is_selectable = true; if(flag & EDESC_RESET) pcard->cmdFlag |= COMMAND_RESET; else pcard->cmdFlag |= COMMAND_ACTIVATE; if(pcard->location == LOCATION_DECK) { pcard->SetCode(code); mainGame->dField.deck_act[c] = true; } else if(l == LOCATION_GRAVE) mainGame->dField.grave_act[c] = true; else if(l == LOCATION_REMOVED) mainGame->dField.remove_act[c] = true; else if(l == LOCATION_EXTRA) mainGame->dField.extra_act[c] = true; else if(l == LOCATION_OVERLAY) panelmode = true; } } if(!select_trigger && !mainGame->dField.chain_forced && (mainGame->ignore_chain || ((count == 0 || specount == 0) && !mainGame->always_chain)) && (count == 0 || !mainGame->chain_when_avail)) { SetResponseI(-1); mainGame->dField.ClearChainSelect(); if(mainGame->chkWaitChain->isChecked() && !mainGame->ignore_chain) { mainGame->WaitFrameSignal(std::uniform_int_distribution<>(20, 40)(rnd)); } DuelClient::SendResponse(); return true; } if(mainGame->chkAutoChain->isChecked() && mainGame->dField.chain_forced && !(mainGame->always_chain || mainGame->chain_when_avail)) { for(size_t i = 0; i < mainGame->dField.activatable_descs.size();++i) { auto it = mainGame->dField.activatable_descs[i]; if(it.second >> 8) { SetResponseI((int)i); break; } } mainGame->dField.ClearChainSelect(); DuelClient::SendResponse(); return true; } mainGame->gMutex.lock(); if(!conti_exist) mainGame->stHintMsg->setText(dataManager.GetSysString(550)); else mainGame->stHintMsg->setText(dataManager.GetSysString(556)); mainGame->stHintMsg->setVisible(true); if(panelmode) { mainGame->dField.list_command = COMMAND_ACTIVATE; mainGame->dField.selectable_cards = mainGame->dField.activatable_cards; std::sort(mainGame->dField.selectable_cards.begin(), mainGame->dField.selectable_cards.end()); auto eit = std::unique(mainGame->dField.selectable_cards.begin(), mainGame->dField.selectable_cards.end()); mainGame->dField.selectable_cards.erase(eit, mainGame->dField.selectable_cards.end()); mainGame->dField.ShowChainCard(); } else { if(!mainGame->dField.chain_forced) { if(count == 0) myswprintf(textBuffer, L"%ls\n%ls", dataManager.GetSysString(201), dataManager.GetSysString(202)); else if(select_trigger) myswprintf(textBuffer, L"%ls\n%ls\n%ls", event_string, dataManager.GetSysString(222), dataManager.GetSysString(223)); else myswprintf(textBuffer, L"%ls\n%ls", event_string, dataManager.GetSysString(203)); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, textBuffer); mainGame->PopupElement(mainGame->wQuery); } } mainGame->gMutex.unlock(); return false; } case MSG_SELECT_PLACE: case MSG_SELECT_DISFIELD: { int selecting_player = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.select_min = count > 0 ? count : 1; mainGame->dField.select_ready = false; mainGame->dField.select_cancelable = count == 0; mainGame->dField.selectable_field = ~BufferIO::Read(pbuf); if(selecting_player == mainGame->LocalPlayer(1)) mainGame->dField.selectable_field = (mainGame->dField.selectable_field >> 16) | (mainGame->dField.selectable_field << 16); mainGame->dField.selected_field = 0; unsigned char respbuf[SIZE_RETURN_VALUE]; int pzone = 0; if (mainGame->dInfo.curMsg == MSG_SELECT_PLACE) { if (select_hint) { myswprintf(textBuffer, dataManager.GetSysString(569), dataManager.GetName(select_hint)); } else myswprintf(textBuffer, dataManager.GetSysString(560)); } else { if (select_hint) { myswprintf(textBuffer, dataManager.GetDesc(select_hint)); } else myswprintf(textBuffer, dataManager.GetSysString(570)); } select_hint = 0; mainGame->stHintMsg->setText(textBuffer); mainGame->stHintMsg->setVisible(true); if (mainGame->dInfo.curMsg == MSG_SELECT_PLACE && ( (mainGame->chkMAutoPos->isChecked() && mainGame->dField.selectable_field & 0x7f007f) || (mainGame->chkSTAutoPos->isChecked() && !(mainGame->dField.selectable_field & 0x7f007f)))) { unsigned int filter; if (mainGame->dField.selectable_field & 0x7f) { respbuf[0] = mainGame->LocalPlayer(0); respbuf[1] = LOCATION_MZONE; filter = mainGame->dField.selectable_field & 0x7f; } else if (mainGame->dField.selectable_field & 0x3f00) { respbuf[0] = mainGame->LocalPlayer(0); respbuf[1] = LOCATION_SZONE; filter = (mainGame->dField.selectable_field >> 8) & 0x3f; } else if (mainGame->dField.selectable_field & 0xc000) { respbuf[0] = mainGame->LocalPlayer(0); respbuf[1] = LOCATION_SZONE; filter = (mainGame->dField.selectable_field >> 14) & 0x3; pzone = 1; } else if (mainGame->dField.selectable_field & 0x7f0000) { respbuf[0] = mainGame->LocalPlayer(1); respbuf[1] = LOCATION_MZONE; filter = (mainGame->dField.selectable_field >> 16) & 0x7f; } else if (mainGame->dField.selectable_field & 0x3f000000) { respbuf[0] = mainGame->LocalPlayer(1); respbuf[1] = LOCATION_SZONE; filter = (mainGame->dField.selectable_field >> 24) & 0x3f; } else { respbuf[0] = mainGame->LocalPlayer(1); respbuf[1] = LOCATION_SZONE; filter = (mainGame->dField.selectable_field >> 30) & 0x3; pzone = 1; } if(!pzone) { if(mainGame->chkRandomPos->isChecked()) { std::uniform_int_distribution<> dist(0, 6); do { respbuf[2] = dist(rnd); } while(!(filter & (0x1U << respbuf[2]))); } else { if (filter & 0x40) respbuf[2] = 6; else if (filter & 0x20) respbuf[2] = 5; else if (filter & 0x4) respbuf[2] = 2; else if (filter & 0x2) respbuf[2] = 1; else if (filter & 0x8) respbuf[2] = 3; else if (filter & 0x1) respbuf[2] = 0; else if (filter & 0x10) respbuf[2] = 4; } } else { if (filter & 0x1) respbuf[2] = 6; else if (filter & 0x2) respbuf[2] = 7; } mainGame->dField.selectable_field = 0; SetResponseB(respbuf, 3); DuelClient::SendResponse(); return true; } if(mainGame->dField.select_cancelable) { mainGame->dField.ShowCancelOrFinishButton(1); } return false; } case MSG_SELECT_POSITION: { /*int selecting_player = */BufferIO::Read(pbuf); unsigned int code = (unsigned int)BufferIO::Read(pbuf); unsigned int positions = BufferIO::Read(pbuf); if (positions == 0x1 || positions == 0x2 || positions == 0x4 || positions == 0x8) { SetResponseI(positions); return true; } int count = 0, filter = 0x1, startpos; while(filter != 0x10) { if(positions & filter) count++; filter <<= 1; } if(count == 4) startpos = 10; else if(count == 3) startpos = 82; else startpos = 155; if(positions & 0x1) { mainGame->imageLoading.insert(std::make_pair(mainGame->btnPSAU, code)); mainGame->btnPSAU->setRelativePosition(irr::core::rect(startpos, 45, startpos + 140, 185)); mainGame->btnPSAU->setVisible(true); startpos += 145; } else mainGame->btnPSAU->setVisible(false); if(positions & 0x2) { mainGame->btnPSAD->setRelativePosition(irr::core::rect(startpos, 45, startpos + 140, 185)); mainGame->btnPSAD->setVisible(true); startpos += 145; } else mainGame->btnPSAD->setVisible(false); if(positions & 0x4) { mainGame->imageLoading.insert(std::make_pair(mainGame->btnPSDU, code)); mainGame->btnPSDU->setRelativePosition(irr::core::rect(startpos, 45, startpos + 140, 185)); mainGame->btnPSDU->setVisible(true); startpos += 145; } else mainGame->btnPSDU->setVisible(false); if(positions & 0x8) { mainGame->btnPSDD->setRelativePosition(irr::core::rect(startpos, 45, startpos + 140, 185)); mainGame->btnPSDD->setVisible(true); startpos += 145; } else mainGame->btnPSDD->setVisible(false); mainGame->gMutex.lock(); mainGame->PopupElement(mainGame->wPosSelect); mainGame->gMutex.unlock(); return false; } case MSG_SELECT_TRIBUTE: { /*int selecting_player = */BufferIO::Read(pbuf); mainGame->dField.select_cancelable = BufferIO::Read(pbuf) != 0; mainGame->dField.select_min = BufferIO::Read(pbuf); mainGame->dField.select_max = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.selectable_cards.clear(); mainGame->dField.selected_cards.clear(); mainGame->dField.selectsum_all.clear(); mainGame->dField.selectsum_cards.clear(); mainGame->dField.select_panalmode = false; int c, s, t; unsigned int code, l; ClientCard* pcard; mainGame->dField.select_ready = false; for (int i = 0; i < count; ++i) { code = (unsigned int)BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); t = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(c, l, s); if (code && pcard->code != code) pcard->SetCode(code); mainGame->dField.selectable_cards.push_back(pcard); mainGame->dField.selectsum_all.push_back(pcard); pcard->opParam = t << 16 | 1; pcard->select_seq = i; pcard->is_selectable = true; } mainGame->dField.CheckSelectTribute(); if(select_hint) myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetDesc(select_hint), mainGame->dField.select_min, mainGame->dField.select_max); else myswprintf(textBuffer, L"%ls(%d-%d)", dataManager.GetSysString(531), mainGame->dField.select_min, mainGame->dField.select_max); select_hint = 0; mainGame->gMutex.lock(); mainGame->stHintMsg->setText(textBuffer); mainGame->stHintMsg->setVisible(true); if (mainGame->dField.select_cancelable) { mainGame->dField.ShowCancelOrFinishButton(1); } mainGame->gMutex.unlock(); return false; } case MSG_SELECT_COUNTER: { /*int selecting_player = */BufferIO::Read(pbuf); mainGame->dField.select_counter_type = BufferIO::Read(pbuf); mainGame->dField.select_counter_count = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.selectable_cards.clear(); int c, s, t/*, code*/; unsigned int l; ClientCard* pcard; for (int i = 0; i < count; ++i) { /*code = */BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); t = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(c, l, s); mainGame->dField.selectable_cards.push_back(pcard); pcard->opParam = (t << 16) | t; pcard->is_selectable = true; } myswprintf(textBuffer, dataManager.GetSysString(204), mainGame->dField.select_counter_count, dataManager.GetCounterName(mainGame->dField.select_counter_type)); mainGame->gMutex.lock(); mainGame->stHintMsg->setText(textBuffer); mainGame->stHintMsg->setVisible(true); mainGame->gMutex.unlock(); return false; } case MSG_SELECT_SUM: { mainGame->dField.select_mode = BufferIO::Read(pbuf); /*int selecting_player = */BufferIO::Read(pbuf); mainGame->dField.select_sumval = BufferIO::Read(pbuf); mainGame->dField.select_min = BufferIO::Read(pbuf); mainGame->dField.select_max = BufferIO::Read(pbuf); mainGame->dField.must_select_count = BufferIO::Read(pbuf); mainGame->dField.selectsum_all.clear(); mainGame->dField.selected_cards.clear(); mainGame->dField.selectsum_cards.clear(); mainGame->dField.select_panalmode = false; for (int i = 0; i < mainGame->dField.must_select_count; ++i) { unsigned int code = (unsigned int)BufferIO::Read(pbuf); int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->opParam = BufferIO::Read(pbuf); pcard->select_seq = 0; mainGame->dField.selected_cards.push_back(pcard); } int count = BufferIO::Read(pbuf); for (int i = 0; i < count; ++i) { unsigned int code = (unsigned int)BufferIO::Read(pbuf); int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->opParam = BufferIO::Read(pbuf); pcard->select_seq = i; mainGame->dField.selectsum_all.push_back(pcard); if ((l & 0xe) == 0) mainGame->dField.select_panalmode = true; } std::sort(mainGame->dField.selectsum_all.begin(), mainGame->dField.selectsum_all.end(), ClientCard::client_card_sort); mainGame->dField.select_hint = select_hint; select_hint = 0; return mainGame->dField.ShowSelectSum(mainGame->dField.select_panalmode); } case MSG_SORT_CARD: { /*int player = */BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); mainGame->dField.selectable_cards.clear(); mainGame->dField.selected_cards.clear(); mainGame->dField.sort_list.clear(); int c, s; unsigned int code, l; ClientCard* pcard; for (int i = 0; i < count; ++i) { code = (unsigned int)BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(c, l, s); if (code != 0 && pcard->code != code) pcard->SetCode(code); mainGame->dField.selectable_cards.push_back(pcard); mainGame->dField.sort_list.push_back(0); } mainGame->wCardSelect->setText(dataManager.GetSysString(205)); mainGame->dField.select_min = 0; mainGame->dField.select_max = count; mainGame->dField.ShowSelectCard(); return false; } case MSG_CONFIRM_DECKTOP: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); unsigned int code; ClientCard* pcard; mainGame->dField.selectable_cards.clear(); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); pbuf += 3; pcard = *(mainGame->dField.deck[player].rbegin() + i); if (code != 0) pcard->SetCode(code); } if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_REVEAL); myswprintf(textBuffer, dataManager.GetSysString(207), count); mainGame->AddLog(textBuffer); for (int i = 0; i < count; ++i) { pcard = *(mainGame->dField.deck[player].rbegin() + i); mainGame->gMutex.lock(); myswprintf(textBuffer, L"*[%ls]", dataManager.GetName(pcard->code)); mainGame->AddLog(textBuffer, pcard->code); mainGame->gMutex.unlock(); float shift = -0.15f; if (player == 1) shift = 0.15f; pcard->dPos = irr::core::vector3df(shift, 0, 0); if(!mainGame->dField.deck_reversed) pcard->dRot = irr::core::vector3df(0, 3.14159f / 5.0f, 0); else pcard->dRot = irr::core::vector3df(0, 0, 0); pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(count > 5 ? 12 : 45); mainGame->dField.MoveCard(pcard, 5); mainGame->WaitFrameSignal(5); } return true; } case MSG_CONFIRM_EXTRATOP: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); unsigned int code; ClientCard* pcard; mainGame->dField.selectable_cards.clear(); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); pbuf += 3; pcard = *(mainGame->dField.extra[player].rbegin() + i + mainGame->dField.extra_p_count[player]); if (code != 0) pcard->SetCode(code); } if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_REVEAL); myswprintf(textBuffer, dataManager.GetSysString(207), count); mainGame->AddLog(textBuffer); for (int i = 0; i < count; ++i) { pcard = *(mainGame->dField.extra[player].rbegin() + i + mainGame->dField.extra_p_count[player]); mainGame->gMutex.lock(); myswprintf(textBuffer, L"*[%ls]", dataManager.GetName(pcard->code)); mainGame->AddLog(textBuffer, pcard->code); mainGame->gMutex.unlock(); if (player == 0) pcard->dPos = irr::core::vector3df(0, -0.20f, 0); else pcard->dPos = irr::core::vector3df(0.15f, 0, 0); pcard->dRot = irr::core::vector3df(0, 3.14159f / 5.0f, 0); pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(45); mainGame->dField.MoveCard(pcard, 5); mainGame->WaitFrameSignal(5); } return true; } case MSG_CONFIRM_CARDS: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); int skip_panel = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); int c, s; unsigned int code, l; std::vector field_confirm; std::vector panel_confirm; ClientCard* pcard; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pbuf += count * 7; return true; } soundManager.PlaySoundEffect(SOUND_REVEAL); myswprintf(textBuffer, dataManager.GetSysString(208), count); mainGame->AddLog(textBuffer); for (int i = 0; i < count; ++i) { code = BufferIO::Read(pbuf); c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(c, l, s); if (code != 0) pcard->SetCode(code); mainGame->gMutex.lock(); myswprintf(textBuffer, L"*[%ls]", dataManager.GetName(code)); mainGame->AddLog(textBuffer, code); mainGame->gMutex.unlock(); if (l & 0x41) { if(count == 1) { float shift = -0.15f; if (c == 0 && l == 0x40) shift = 0.15f; pcard->dPos = irr::core::vector3df(shift, 0, 0); if((l == LOCATION_DECK) && mainGame->dField.deck_reversed) pcard->dRot = irr::core::vector3df(0, 0, 0); else pcard->dRot = irr::core::vector3df(0, 3.14159f / 5.0f, 0); pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(45); mainGame->dField.MoveCard(pcard, 5); mainGame->WaitFrameSignal(5); } else { if(!mainGame->dInfo.isReplay) panel_confirm.push_back(pcard); } } else { if(!mainGame->dInfo.isReplay || (l & LOCATION_ONFIELD)) field_confirm.push_back(pcard); } } if (field_confirm.size() > 0) { mainGame->WaitFrameSignal(5); for(int i = 0; i < (int)field_confirm.size(); ++i) { pcard = field_confirm[i]; c = pcard->controler; l = pcard->location; if (l == LOCATION_HAND) { mainGame->dField.MoveCard(pcard, 5); pcard->is_highlighting = true; } else if (l == LOCATION_MZONE) { if (pcard->position & POS_FACEUP) continue; pcard->dPos = irr::core::vector3df(0, 0, 0); if (pcard->position == POS_FACEDOWN_ATTACK) pcard->dRot = irr::core::vector3df(0, 3.14159f / 5.0f, 0); else pcard->dRot = irr::core::vector3df(3.14159f / 5.0f, 0, 0); pcard->is_moving = true; pcard->aniFrame = 5; } else if (l == LOCATION_SZONE) { if (pcard->position & POS_FACEUP) continue; pcard->dPos = irr::core::vector3df(0, 0, 0); pcard->dRot = irr::core::vector3df(0, 3.14159f / 5.0f, 0); pcard->is_moving = true; pcard->aniFrame = 5; } } if (mainGame->dInfo.isReplay) mainGame->WaitFrameSignal(30); else mainGame->WaitFrameSignal(90); for(int i = 0; i < (int)field_confirm.size(); ++i) { pcard = field_confirm[i]; mainGame->dField.MoveCard(pcard, 5); pcard->is_highlighting = false; } mainGame->WaitFrameSignal(5); } if (!skip_panel && panel_confirm.size() && mainGame->dInfo.player_type != 7) { std::sort(panel_confirm.begin(), panel_confirm.end(), ClientCard::client_card_sort); mainGame->gMutex.lock(); mainGame->dField.selectable_cards = panel_confirm; myswprintf(textBuffer, dataManager.GetSysString(208), panel_confirm.size()); mainGame->wCardSelect->setText(textBuffer); mainGame->dField.ShowSelectCard(true); mainGame->gMutex.unlock(); mainGame->actionSignal.Reset(); mainGame->actionSignal.Wait(); } return true; } case MSG_SHUFFLE_DECK: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); if(mainGame->dField.deck[player].size() < 2) return true; bool rev = mainGame->dField.deck_reversed; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->dField.deck_reversed = false; if(rev) { for (size_t i = 0; i < mainGame->dField.deck[player].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.deck[player][i], 10); mainGame->WaitFrameSignal(10); } } for (size_t i = 0; i < mainGame->dField.deck[player].size(); ++i) { mainGame->dField.deck[player][i]->code = 0; mainGame->dField.deck[player][i]->is_reversed = false; } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_SHUFFLE); for (int i = 0; i < 5; ++i) { for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ++cit) { (*cit)->dPos = irr::core::vector3df(real_dist(rnd) * 0.4f - 0.2f, 0, 0); (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->aniFrame = 3; } mainGame->WaitFrameSignal(3); for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ++cit) mainGame->dField.MoveCard(*cit, 3); mainGame->WaitFrameSignal(3); } mainGame->dField.deck_reversed = rev; if(rev) { for (size_t i = 0; i < mainGame->dField.deck[player].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.deck[player][i], 10); } } return true; } case MSG_SHUFFLE_HAND: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { if(count > 1) soundManager.PlaySoundEffect(SOUND_SHUFFLE); mainGame->WaitFrameSignal(5); if(player == 1 && !mainGame->dInfo.isReplay && !mainGame->dInfo.isSingleMode) { bool flip = false; for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) if((*cit)->code) { (*cit)->dPos = irr::core::vector3df(0, 0, 0); (*cit)->dRot = irr::core::vector3df(1.322f / 5, 3.1415926f / 5, 0); (*cit)->is_moving = true; (*cit)->is_hovered = false; (*cit)->aniFrame = 5; flip = true; } if(flip) mainGame->WaitFrameSignal(5); } for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) { (*cit)->dPos = irr::core::vector3df((3.9f - (*cit)->curPos.X) / 5, 0, 0); (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->is_hovered = false; (*cit)->aniFrame = 5; } mainGame->WaitFrameSignal(11); } for(auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) { (*cit)->SetCode(BufferIO::Read(pbuf)); (*cit)->desc_hints.clear(); } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) { (*cit)->is_hovered = false; mainGame->dField.MoveCard(*cit, 5); } mainGame->WaitFrameSignal(5); } return true; } case MSG_SHUFFLE_EXTRA: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); if((mainGame->dField.extra[player].size() - mainGame->dField.extra_p_count[player]) < 2) return true; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { if(count > 1) soundManager.PlaySoundEffect(SOUND_SHUFFLE); for (int i = 0; i < 5; ++i) { for (auto cit = mainGame->dField.extra[player].begin(); cit != mainGame->dField.extra[player].end(); ++cit) { if(!((*cit)->position & POS_FACEUP)) { (*cit)->dPos = irr::core::vector3df(real_dist(rnd) * 0.4f - 0.2f, 0, 0); (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->aniFrame = 3; } } mainGame->WaitFrameSignal(3); for (auto cit = mainGame->dField.extra[player].begin(); cit != mainGame->dField.extra[player].end(); ++cit) if(!((*cit)->position & POS_FACEUP)) mainGame->dField.MoveCard(*cit, 3); mainGame->WaitFrameSignal(3); } } for (auto cit = mainGame->dField.extra[player].begin(); cit != mainGame->dField.extra[player].end(); ++cit) if(!((*cit)->position & POS_FACEUP)) (*cit)->SetCode(BufferIO::Read(pbuf)); return true; } case MSG_REFRESH_DECK: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); return true; } case MSG_SWAP_GRAVE_DECK: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dField.grave[player].swap(mainGame->dField.deck[player]); for (auto cit = mainGame->dField.grave[player].begin(); cit != mainGame->dField.grave[player].end(); ++cit) (*cit)->location = LOCATION_GRAVE; int m = 0; for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ) { if ((*cit)->type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_LINK)) { (*cit)->position = POS_FACEDOWN; mainGame->dField.AddCard(*cit, player, LOCATION_EXTRA, 0); cit = mainGame->dField.deck[player].erase(cit); } else { (*cit)->location = LOCATION_DECK; (*cit)->sequence = m++; ++cit; } } } else { mainGame->gMutex.lock(); mainGame->dField.grave[player].swap(mainGame->dField.deck[player]); for (auto cit = mainGame->dField.grave[player].begin(); cit != mainGame->dField.grave[player].end(); ++cit) { (*cit)->location = LOCATION_GRAVE; mainGame->dField.MoveCard(*cit, 10); } int m = 0; for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ) { ClientCard* pcard = *cit; if (pcard->type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_LINK)) { pcard->position = POS_FACEDOWN; mainGame->dField.AddCard(pcard, player, LOCATION_EXTRA, 0); cit = mainGame->dField.deck[player].erase(cit); } else { pcard->location = LOCATION_DECK; pcard->sequence = m++; ++cit; } mainGame->dField.MoveCard(pcard, 10); } mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(11); } return true; } case MSG_REVERSE_DECK: { mainGame->dField.deck_reversed = !mainGame->dField.deck_reversed; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { for(size_t i = 0; i < mainGame->dField.deck[0].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.deck[0][i], 10); for(size_t i = 0; i < mainGame->dField.deck[1].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.deck[1][i], 10); } return true; } case MSG_DECK_TOP: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int seq = BufferIO::Read(pbuf); unsigned int code = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(player, LOCATION_DECK, mainGame->dField.deck[player].size() - 1 - seq); pcard->SetCode(code & 0x7fffffff); bool rev = (code & 0x80000000) != 0; if(pcard->is_reversed != rev) { pcard->is_reversed = rev; mainGame->dField.MoveCard(pcard, 5); } return true; } case MSG_SHUFFLE_SET_CARD: { std::vector* lst = 0; unsigned int loc = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); if(loc == LOCATION_MZONE) lst = mainGame->dField.mzone; else lst = mainGame->dField.szone; ClientCard* mc[5]{ nullptr }; ClientCard* swp; int c, s, ps; unsigned int l; for (int i = 0; i < count; ++i) { c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); BufferIO::Read(pbuf); mc[i] = lst[c][s]; mc[i]->SetCode(0); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mc[i]->dPos = irr::core::vector3df((3.95f - mc[i]->curPos.X) / 10, 0, 0.05f); mc[i]->dRot = irr::core::vector3df(0, 0, 0); mc[i]->is_moving = true; mc[i]->aniFrame = 10; } } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) mainGame->WaitFrameSignal(20); for (int i = 0; i < count; ++i) { c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); l = BufferIO::Read(pbuf); s = BufferIO::Read(pbuf); BufferIO::Read(pbuf); ps = mc[i]->sequence; if (l > 0) { swp = lst[c][s]; lst[c][ps] = swp; lst[c][s] = mc[i]; mc[i]->sequence = s; swp->sequence = ps; } } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_SHUFFLE); for (int i = 0; i < count; ++i) { mainGame->dField.MoveCard(mc[i], 10); for (auto cit = mc[i]->overlayed.begin(); cit != mc[i]->overlayed.end(); ++cit) mainGame->dField.MoveCard(*cit, 10); } mainGame->WaitFrameSignal(11); } return true; } case MSG_NEW_TURN: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); mainGame->dInfo.turn++; if(!mainGame->dInfo.isReplay && mainGame->dInfo.player_type < 7) { mainGame->dField.tag_surrender = false; mainGame->dField.tag_teammate_surrender = false; mainGame->btnLeaveGame->setText(dataManager.GetSysString(1351)); mainGame->btnLeaveGame->setVisible(true); } mainGame->HideElement(mainGame->wSurrender); if(!mainGame->dInfo.isReplay && mainGame->dInfo.player_type < 7) { if(mainGame->gameConf.control_mode == 0) { mainGame->btnChainIgnore->setVisible(true); mainGame->btnChainAlways->setVisible(true); mainGame->btnChainWhenAvail->setVisible(true); mainGame->dField.UpdateChainButtons(); } else { mainGame->btnChainIgnore->setVisible(false); mainGame->btnChainAlways->setVisible(false); mainGame->btnChainWhenAvail->setVisible(false); mainGame->btnCancelOrFinish->setVisible(false); } } if(mainGame->dInfo.isTag && mainGame->dInfo.turn != 1) { if(player == 0) mainGame->dInfo.tag_player[0] = !mainGame->dInfo.tag_player[0]; else mainGame->dInfo.tag_player[1] = !mainGame->dInfo.tag_player[1]; } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_NEXT_TURN); mainGame->showcardcode = 10; mainGame->showcarddif = 30; mainGame->showcardp = 0; mainGame->showcard = 101; mainGame->WaitFrameSignal(40); mainGame->showcard = 0; } return true; } case MSG_NEW_PHASE: { unsigned short phase = BufferIO::Read(pbuf); mainGame->btnPhaseStatus->setVisible(false); mainGame->btnBP->setVisible(false); mainGame->btnM2->setVisible(false); mainGame->btnEP->setVisible(false); mainGame->btnShuffle->setVisible(false); mainGame->showcarddif = 30; mainGame->showcardp = 0; switch (phase) { case PHASE_DRAW: mainGame->btnPhaseStatus->setText(L"\xff24\xff30"); mainGame->showcardcode = 4; break; case PHASE_STANDBY: mainGame->btnPhaseStatus->setText(L"\xff33\xff30"); mainGame->showcardcode = 5; break; case PHASE_MAIN1: mainGame->btnPhaseStatus->setText(L"\xff2d\xff11"); mainGame->showcardcode = 6; break; case PHASE_BATTLE_START: mainGame->btnPhaseStatus->setText(L"\xff22\xff30"); mainGame->showcardcode = 7; break; case PHASE_MAIN2: mainGame->btnPhaseStatus->setText(L"\xff2d\xff12"); mainGame->showcardcode = 8; break; case PHASE_END: mainGame->btnPhaseStatus->setText(L"\xff25\xff30"); mainGame->showcardcode = 9; break; } mainGame->btnPhaseStatus->setPressed(true); mainGame->btnPhaseStatus->setVisible(true); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_PHASE); mainGame->showcard = 101; mainGame->WaitFrameSignal(40); mainGame->showcard = 0; } return true; } case MSG_MOVE: { unsigned int code = BufferIO::Read(pbuf); int pc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int pl = BufferIO::Read(pbuf); int ps = BufferIO::Read(pbuf); unsigned int pp = BufferIO::Read(pbuf); int cc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int cl = BufferIO::Read(pbuf); int cs = BufferIO::Read(pbuf); unsigned int cp = BufferIO::Read(pbuf); int reason = BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { if(cl & LOCATION_REMOVED && pl != cl) soundManager.PlaySoundEffect(SOUND_BANISHED); else if(reason & REASON_DESTROY && pl != cl) soundManager.PlaySoundEffect(SOUND_DESTROYED); } int appear = mainGame->gameConf.quick_animation ? 12 : 20; if (pl == 0) { ClientCard* pcard = new ClientCard; pcard->position = cp; pcard->SetCode(code); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->gMutex.lock(); mainGame->dField.AddCard(pcard, cc, cl, cs); mainGame->gMutex.unlock(); mainGame->dField.GetCardLocation(pcard, &pcard->curPos, &pcard->curRot, true); pcard->curAlpha = 5; mainGame->dField.FadeCard(pcard, 255, appear); mainGame->WaitFrameSignal(appear); } else mainGame->dField.AddCard(pcard, cc, cl, cs); } else if (cl == 0) { ClientCard* pcard = mainGame->dField.GetCard(pc, pl, ps); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->ClearTarget(); for(auto eqit = pcard->equipped.begin(); eqit != pcard->equipped.end(); ++eqit) (*eqit)->equipTarget = 0; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->dField.FadeCard(pcard, 5, appear); mainGame->WaitFrameSignal(appear); mainGame->gMutex.lock(); mainGame->dField.RemoveCard(pc, pl, ps); mainGame->gMutex.unlock(); if(pcard == mainGame->dField.hovered_card) mainGame->dField.hovered_card = 0; } else mainGame->dField.RemoveCard(pc, pl, ps); delete pcard; } else { if (!(pl & LOCATION_OVERLAY) && !(cl & LOCATION_OVERLAY)) { ClientCard* pcard = mainGame->dField.GetCard(pc, pl, ps); if (pcard->code != code && (code != 0 || cl == 0x40)) pcard->SetCode(code); pcard->cHint = 0; pcard->chValue = 0; if((pl & LOCATION_ONFIELD) && (cl != pl)) pcard->counters.clear(); if(cl != pl) { pcard->ClearTarget(); if(pcard->equipTarget) { pcard->equipTarget->is_showequip = false; pcard->equipTarget->equipped.erase(pcard); pcard->equipTarget = 0; } } pcard->is_hovered = false; pcard->is_showequip = false; pcard->is_showtarget = false; pcard->is_showchaintarget = false; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dField.RemoveCard(pc, pl, ps); pcard->position = cp; mainGame->dField.AddCard(pcard, cc, cl, cs); } else { mainGame->gMutex.lock(); mainGame->dField.RemoveCard(pc, pl, ps); pcard->position = cp; mainGame->dField.AddCard(pcard, cc, cl, cs); mainGame->gMutex.unlock(); if (pl == cl && pc == cc && (cl & 0x71)) { pcard->dPos = irr::core::vector3df(-0.3f, 0, 0); pcard->dRot = irr::core::vector3df(0, 0, 0); if (pc == 1) pcard->dPos.X = 0.3f; pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(5); mainGame->dField.MoveCard(pcard, 5); mainGame->WaitFrameSignal(5); } else { if (cl == 0x4 && pcard->overlayed.size() > 0) { mainGame->gMutex.lock(); for (size_t i = 0; i < pcard->overlayed.size(); ++i) mainGame->dField.MoveCard(pcard->overlayed[i], 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(10); } if (cl == 0x2) { mainGame->gMutex.lock(); for (size_t i = 0; i < mainGame->dField.hand[cc].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.hand[cc][i], 10); mainGame->gMutex.unlock(); } else { mainGame->gMutex.lock(); mainGame->dField.MoveCard(pcard, 10); if (pl == 0x2) for (size_t i = 0; i < mainGame->dField.hand[pc].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.hand[pc][i], 10); mainGame->gMutex.unlock(); } mainGame->WaitFrameSignal(5); } } } else if (!(pl & LOCATION_OVERLAY)) { ClientCard* pcard = mainGame->dField.GetCard(pc, pl, ps); if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->counters.clear(); pcard->ClearTarget(); if(pcard->equipTarget) { pcard->equipTarget->is_showequip = false; pcard->equipTarget->equipped.erase(pcard); pcard->equipTarget = 0; } pcard->is_showequip = false; pcard->is_showtarget = false; pcard->is_showchaintarget = false; ClientCard* olcard = mainGame->dField.GetCard(cc, cl & 0x7f, cs); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dField.RemoveCard(pc, pl, ps); olcard->overlayed.push_back(pcard); mainGame->dField.overlay_cards.insert(pcard); pcard->overlayTarget = olcard; pcard->location = LOCATION_OVERLAY; pcard->sequence = (unsigned char)(olcard->overlayed.size() - 1); } else { mainGame->gMutex.lock(); mainGame->dField.RemoveCard(pc, pl, ps); olcard->overlayed.push_back(pcard); mainGame->dField.overlay_cards.insert(pcard); mainGame->gMutex.unlock(); pcard->overlayTarget = olcard; pcard->location = LOCATION_OVERLAY; pcard->sequence = (unsigned char)(olcard->overlayed.size() - 1); if (olcard->location == LOCATION_MZONE) { mainGame->gMutex.lock(); mainGame->dField.MoveCard(pcard, 10); if (pl == 0x2) for (size_t i = 0; i < mainGame->dField.hand[pc].size(); ++i) mainGame->dField.MoveCard(mainGame->dField.hand[pc][i], 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(5); } } } else if (!(cl & LOCATION_OVERLAY)) { ClientCard* olcard = mainGame->dField.GetCard(pc, pl & 0x7f, ps); ClientCard* pcard = olcard->overlayed[pp]; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { olcard->overlayed.erase(olcard->overlayed.begin() + pcard->sequence); pcard->overlayTarget = 0; pcard->position = cp; mainGame->dField.AddCard(pcard, cc, cl, cs); mainGame->dField.overlay_cards.erase(pcard); for (size_t i = 0; i < olcard->overlayed.size(); ++i) olcard->overlayed[i]->sequence = (unsigned char)i; } else { mainGame->gMutex.lock(); olcard->overlayed.erase(olcard->overlayed.begin() + pcard->sequence); pcard->overlayTarget = 0; pcard->position = cp; mainGame->dField.AddCard(pcard, cc, cl, cs); mainGame->dField.overlay_cards.erase(pcard); for (size_t i = 0; i < olcard->overlayed.size(); ++i) { olcard->overlayed[i]->sequence = (unsigned char)i; mainGame->dField.MoveCard(olcard->overlayed[i], 2); } mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(5); mainGame->gMutex.lock(); mainGame->dField.MoveCard(pcard, 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(5); } } else { ClientCard* olcard1 = mainGame->dField.GetCard(pc, pl & 0x7f, ps); ClientCard* pcard = olcard1->overlayed[pp]; ClientCard* olcard2 = mainGame->dField.GetCard(cc, cl & 0x7f, cs); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { olcard1->overlayed.erase(olcard1->overlayed.begin() + pcard->sequence); olcard2->overlayed.push_back(pcard); pcard->sequence = (unsigned char)(olcard2->overlayed.size() - 1); pcard->location = LOCATION_OVERLAY; pcard->overlayTarget = olcard2; for (size_t i = 0; i < olcard1->overlayed.size(); ++i) { olcard1->overlayed[i]->sequence = (unsigned char)i; } } else { mainGame->gMutex.lock(); olcard1->overlayed.erase(olcard1->overlayed.begin() + pcard->sequence); olcard2->overlayed.push_back(pcard); pcard->sequence = (unsigned char)(olcard2->overlayed.size() - 1); pcard->location = LOCATION_OVERLAY; pcard->overlayTarget = olcard2; for (size_t i = 0; i < olcard1->overlayed.size(); ++i) { olcard1->overlayed[i]->sequence = (unsigned char)i; mainGame->dField.MoveCard(olcard1->overlayed[i], 2); } mainGame->dField.MoveCard(pcard, 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(5); } } } return true; } case MSG_POS_CHANGE: { unsigned int code = BufferIO::Read(pbuf); int cc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int cl = BufferIO::Read(pbuf); int cs = BufferIO::Read(pbuf); unsigned int pp = BufferIO::Read(pbuf); unsigned int cp = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(cc, cl, cs); if((pp & POS_FACEUP) && (cp & POS_FACEDOWN)) { pcard->counters.clear(); pcard->ClearTarget(); } if (code != 0 && pcard->code != code) pcard->SetCode(code); pcard->position = cp; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { myswprintf(event_string, dataManager.GetSysString(1600)); mainGame->dField.MoveCard(pcard, 10); mainGame->WaitFrameSignal(11); } return true; } case MSG_SET: { /*int code = */BufferIO::Read(pbuf); /*int cc = mainGame->LocalPlayer*/(BufferIO::Read(pbuf)); /*int cl = */BufferIO::Read(pbuf); /*int cs = */BufferIO::Read(pbuf); /*int cp = */BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) soundManager.PlaySoundEffect(SOUND_SET); myswprintf(event_string, dataManager.GetSysString(1601)); return true; } case MSG_SWAP: { /*int code1 = */BufferIO::Read(pbuf); int c1 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l1 = BufferIO::Read(pbuf); int s1 = BufferIO::Read(pbuf); /*int p1 = */BufferIO::Read(pbuf); /*int code2 = */BufferIO::Read(pbuf); int c2 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l2 = BufferIO::Read(pbuf); int s2 = BufferIO::Read(pbuf); /*int p2 = */BufferIO::Read(pbuf); myswprintf(event_string, dataManager.GetSysString(1602)); ClientCard* pc1 = mainGame->dField.GetCard(c1, l1, s1); ClientCard* pc2 = mainGame->dField.GetCard(c2, l2, s2); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->gMutex.lock(); mainGame->dField.RemoveCard(c1, l1, s1); mainGame->dField.RemoveCard(c2, l2, s2); mainGame->dField.AddCard(pc1, c2, l2, s2); mainGame->dField.AddCard(pc2, c1, l1, s1); mainGame->dField.MoveCard(pc1, 10); mainGame->dField.MoveCard(pc2, 10); for (size_t i = 0; i < pc1->overlayed.size(); ++i) mainGame->dField.MoveCard(pc1->overlayed[i], 10); for (size_t i = 0; i < pc2->overlayed.size(); ++i) mainGame->dField.MoveCard(pc2->overlayed[i], 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(11); } else { mainGame->dField.RemoveCard(c1, l1, s1); mainGame->dField.RemoveCard(c2, l2, s2); mainGame->dField.AddCard(pc1, c2, l2, s2); mainGame->dField.AddCard(pc2, c1, l1, s1); } return true; } case MSG_FIELD_DISABLED: { unsigned int disabled = BufferIO::Read(pbuf); if (!mainGame->dInfo.isFirst) disabled = (disabled >> 16) | (disabled << 16); mainGame->dField.disabled_field = disabled; return true; } case MSG_SUMMONING: { unsigned int code = BufferIO::Read(pbuf); /*int cc = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); /*int cl = */BufferIO::Read(pbuf); /*int cs = */BufferIO::Read(pbuf); /*int cp = */BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_SUMMON); myswprintf(event_string, dataManager.GetSysString(1603), dataManager.GetName(code)); mainGame->showcardcode = code; mainGame->showcarddif = 0; mainGame->showcardp = 0; mainGame->showcard = 7; mainGame->WaitFrameSignal(30); mainGame->showcard = 0; mainGame->WaitFrameSignal(11); } return true; } case MSG_SUMMONED: { myswprintf(event_string, dataManager.GetSysString(1604)); return true; } case MSG_SPSUMMONING: { unsigned int code = BufferIO::Read(pbuf); /*int cc = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); /*int cl = */BufferIO::Read(pbuf); /*int cs = */BufferIO::Read(pbuf); /*int cp = */BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { CardData cd; if(dataManager.GetData(code, &cd) && (cd.type & TYPE_TOKEN)) soundManager.PlaySoundEffect(SOUND_TOKEN); else soundManager.PlaySoundEffect(SOUND_SPECIAL_SUMMON); myswprintf(event_string, dataManager.GetSysString(1605), dataManager.GetName(code)); if(code) { mainGame->showcardcode = code; mainGame->showcarddif = 1; mainGame->showcard = 5; mainGame->WaitFrameSignal(30); mainGame->showcard = 0; mainGame->WaitFrameSignal(11); } } return true; } case MSG_SPSUMMONED: { myswprintf(event_string, dataManager.GetSysString(1606)); return true; } case MSG_FLIPSUMMONING: { unsigned int code = BufferIO::Read(pbuf); int cc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int cl = BufferIO::Read(pbuf); int cs = BufferIO::Read(pbuf); unsigned int cp = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(cc, cl, cs); pcard->SetCode(code); pcard->position = cp; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_FILP); myswprintf(event_string, dataManager.GetSysString(1607), dataManager.GetName(code)); mainGame->dField.MoveCard(pcard, 10); mainGame->WaitFrameSignal(11); mainGame->showcardcode = code; mainGame->showcarddif = 0; mainGame->showcardp = 0; mainGame->showcard = 7; mainGame->WaitFrameSignal(30); mainGame->showcard = 0; mainGame->WaitFrameSignal(11); } return true; } case MSG_FLIPSUMMONED: { myswprintf(event_string, dataManager.GetSysString(1608)); return true; } case MSG_CHAINING: { unsigned int code = BufferIO::Read(pbuf); int pcc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int pcl = BufferIO::Read(pbuf); int pcs = BufferIO::Read(pbuf); int subs = BufferIO::Read(pbuf); int cc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int cl = BufferIO::Read(pbuf); int cs = BufferIO::Read(pbuf); int desc = BufferIO::Read(pbuf); /*int ct = */BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_ACTIVATE); ClientCard* pcard = mainGame->dField.GetCard(pcc, pcl, pcs, subs); if(pcard->code != code) { pcard->code = code; mainGame->dField.MoveCard(pcard, 10); } mainGame->showcardcode = code; mainGame->showcarddif = 0; mainGame->showcard = 1; pcard->is_highlighting = true; if(pcard->location & 0x30) { float shift = -0.15f; if(cc == 1) shift = 0.15f; pcard->dPos = irr::core::vector3df(shift, 0, 0); pcard->dRot = irr::core::vector3df(0, 0, 0); pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(30); mainGame->dField.MoveCard(pcard, 5); } else mainGame->WaitFrameSignal(30); pcard->is_highlighting = false; mainGame->dField.current_chain.chain_card = pcard; mainGame->dField.current_chain.code = code; mainGame->dField.current_chain.desc = desc; mainGame->dField.current_chain.controler = cc; mainGame->dField.current_chain.location = cl; mainGame->dField.current_chain.sequence = cs; mainGame->dField.GetChainLocation(cc, cl, cs, &mainGame->dField.current_chain.chain_pos); mainGame->dField.current_chain.solved = false; mainGame->dField.current_chain.target.clear(); int chc = 0; for(auto chit = mainGame->dField.chains.begin(); chit != mainGame->dField.chains.end(); ++chit) { if (cl == 0x10 || cl == 0x20) { if (chit->controler == cc && chit->location == cl) chc++; } else { if (chit->controler == cc && chit->location == cl && chit->sequence == cs) chc++; } } if(cl == LOCATION_HAND) mainGame->dField.current_chain.chain_pos.X += 0.35f; else mainGame->dField.current_chain.chain_pos.Y += chc * 0.25f; return true; } case MSG_CHAINED: { int ct = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; myswprintf(event_string, dataManager.GetSysString(1609), dataManager.GetName(mainGame->dField.current_chain.code)); mainGame->gMutex.lock(); mainGame->dField.chains.push_back(mainGame->dField.current_chain); mainGame->gMutex.unlock(); if (ct > 1) mainGame->WaitFrameSignal(20); mainGame->dField.last_chain = true; return true; } case MSG_CHAIN_SOLVING: { int ct = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; if(mainGame->dField.chains.size() > 1 || mainGame->gameConf.draw_single_chain) { if (mainGame->dField.last_chain) mainGame->WaitFrameSignal(11); for(int i = 0; i < 5; ++i) { mainGame->dField.chains[ct - 1].solved = false; mainGame->WaitFrameSignal(3); mainGame->dField.chains[ct - 1].solved = true; mainGame->WaitFrameSignal(3); } } mainGame->dField.last_chain = false; return true; } case MSG_CHAIN_SOLVED: { /*int ct = */BufferIO::Read(pbuf); return true; } case MSG_CHAIN_END: { for(auto chit = mainGame->dField.chains.begin(); chit != mainGame->dField.chains.end(); ++chit) { for(auto tgit = chit->target.begin(); tgit != chit->target.end(); ++tgit) (*tgit)->is_showchaintarget = false; chit->chain_card->is_showchaintarget = false; } mainGame->dField.chains.clear(); return true; } case MSG_CHAIN_NEGATED: case MSG_CHAIN_DISABLED: { int ct = BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { soundManager.PlaySoundEffect(SOUND_NEGATE); mainGame->showcardcode = mainGame->dField.chains[ct - 1].code; mainGame->showcarddif = 0; mainGame->showcard = 3; mainGame->WaitFrameSignal(30); mainGame->showcard = 0; } return true; } case MSG_CARD_SELECTED: { return true; } case MSG_RANDOM_SELECTED: { /*int player = */BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pbuf += count * 4; return true; } soundManager.PlaySoundEffect(SOUND_DICE); ClientCard* pcards[10]; for (int i = 0; i < count; ++i) { int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); int ss = BufferIO::Read(pbuf); if (l & LOCATION_OVERLAY) pcards[i] = mainGame->dField.GetCard(c, l & 0x7f, s)->overlayed[ss]; else pcards[i] = mainGame->dField.GetCard(c, l, s); pcards[i]->is_highlighting = true; } mainGame->WaitFrameSignal(30); for(int i = 0; i < count; ++i) pcards[i]->is_highlighting = false; return true; } case MSG_BECOME_TARGET: { //soundManager.PlaySoundEffect(SOUND_TARGET); int count = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pbuf += count * 4; return true; } for (int i = 0; i < count; ++i) { int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); /*int ss = */BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(c, l, s); pcard->is_highlighting = true; mainGame->dField.current_chain.target.insert(pcard); if(pcard->location & LOCATION_ONFIELD) { for (int j = 0; j < 3; ++j) { mainGame->dField.FadeCard(pcard, 5, 5); mainGame->WaitFrameSignal(5); mainGame->dField.FadeCard(pcard, 255, 5); mainGame->WaitFrameSignal(5); } } else if(pcard->location & 0x30) { float shift = -0.15f; if(c == 1) shift = 0.15f; pcard->dPos = irr::core::vector3df(shift, 0, 0); pcard->dRot = irr::core::vector3df(0, 0, 0); pcard->is_moving = true; pcard->aniFrame = 5; mainGame->WaitFrameSignal(30); mainGame->dField.MoveCard(pcard, 5); } else mainGame->WaitFrameSignal(30); myswprintf(textBuffer, dataManager.GetSysString(1610), dataManager.GetName(pcard->code), dataManager.FormatLocation(l, s), s + 1); mainGame->AddLog(textBuffer, pcard->code); pcard->is_highlighting = false; } return true; } case MSG_DRAW: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); ClientCard* pcard; for (int i = 0; i < count; ++i) { unsigned int code = BufferIO::Read(pbuf); pcard = mainGame->dField.GetCard(player, LOCATION_DECK, mainGame->dField.deck[player].size() - 1 - i); if(!mainGame->dField.deck_reversed || code) pcard->SetCode(code & 0x7fffffff); } if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { for (int i = 0; i < count; ++i) { pcard = mainGame->dField.GetCard(player, LOCATION_DECK, mainGame->dField.deck[player].size() - 1); mainGame->dField.deck[player].erase(mainGame->dField.deck[player].end() - 1); mainGame->dField.AddCard(pcard, player, LOCATION_HAND, 0); } } else { for (int i = 0; i < count; ++i) { soundManager.PlaySoundEffect(SOUND_DRAW); mainGame->gMutex.lock(); pcard = mainGame->dField.GetCard(player, LOCATION_DECK, mainGame->dField.deck[player].size() - 1); mainGame->dField.deck[player].erase(mainGame->dField.deck[player].end() - 1); mainGame->dField.AddCard(pcard, player, LOCATION_HAND, 0); for(int j = 0; j < (int)mainGame->dField.hand[player].size(); ++j) mainGame->dField.MoveCard(mainGame->dField.hand[player][j], 10); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(5); } } if (player == 0) myswprintf(event_string, dataManager.GetSysString(1611), count); else myswprintf(event_string, dataManager.GetSysString(1612), count); return true; } case MSG_DAMAGE: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int val = BufferIO::Read(pbuf); int final = mainGame->dInfo.lp[player] - val; if (final < 0) final = 0; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dInfo.lp[player] = final; myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); return true; } soundManager.PlaySoundEffect(SOUND_DAMAGE); mainGame->lpd = (mainGame->dInfo.lp[player] - final) / 10; if (player == 0) myswprintf(event_string, dataManager.GetSysString(1613), val); else myswprintf(event_string, dataManager.GetSysString(1614), val); mainGame->lpccolor = 0xffff0000; mainGame->lpplayer = player; myswprintf(textBuffer, L"-%d", val); mainGame->lpcstring = textBuffer; mainGame->WaitFrameSignal(30); mainGame->lpframe = 10; mainGame->WaitFrameSignal(11); mainGame->lpcstring = L""; mainGame->dInfo.lp[player] = final; mainGame->gMutex.lock(); myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); mainGame->gMutex.unlock(); return true; } case MSG_RECOVER: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int val = BufferIO::Read(pbuf); int final = mainGame->dInfo.lp[player] + val; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dInfo.lp[player] = final; myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); return true; } soundManager.PlaySoundEffect(SOUND_RECOVER); mainGame->lpd = (mainGame->dInfo.lp[player] - final) / 10; if (player == 0) myswprintf(event_string, dataManager.GetSysString(1615), val); else myswprintf(event_string, dataManager.GetSysString(1616), val); mainGame->lpccolor = 0xff00ff00; mainGame->lpplayer = player; myswprintf(textBuffer, L"+%d", val); mainGame->lpcstring = textBuffer; mainGame->WaitFrameSignal(30); mainGame->lpframe = 10; mainGame->WaitFrameSignal(11); mainGame->lpcstring = L""; mainGame->dInfo.lp[player] = final; mainGame->gMutex.lock(); myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); mainGame->gMutex.unlock(); return true; } case MSG_EQUIP: { int c1 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l1 = BufferIO::Read(pbuf); int s1 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int c2 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l2 = BufferIO::Read(pbuf); int s2 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); ClientCard* pc1 = mainGame->dField.GetCard(c1, l1, s1); ClientCard* pc2 = mainGame->dField.GetCard(c2, l2, s2); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { if(pc1->equipTarget) pc1->equipTarget->equipped.erase(pc1); pc1->equipTarget = pc2; pc2->equipped.insert(pc1); } else { soundManager.PlaySoundEffect(SOUND_EQUIP); mainGame->gMutex.lock(); if(pc1->equipTarget) { pc1->is_showequip = false; pc1->equipTarget->is_showequip = false; pc1->equipTarget->equipped.erase(pc1); } pc1->equipTarget = pc2; pc2->equipped.insert(pc1); if (mainGame->dField.hovered_card == pc1) pc2->is_showequip = true; else if (mainGame->dField.hovered_card == pc2) pc1->is_showequip = true; mainGame->gMutex.unlock(); } return true; } case MSG_LPUPDATE: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int val = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dInfo.lp[player] = val; myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); return true; } mainGame->lpd = (mainGame->dInfo.lp[player] - val) / 10; mainGame->lpplayer = player; mainGame->lpframe = 10; mainGame->WaitFrameSignal(11); mainGame->dInfo.lp[player] = val; mainGame->gMutex.lock(); myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); mainGame->gMutex.unlock(); return true; } case MSG_UNEQUIP: { int c1 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l1 = BufferIO::Read(pbuf); int s1 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); ClientCard* pc = mainGame->dField.GetCard(c1, l1, s1); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pc->equipTarget->equipped.erase(pc); pc->equipTarget = 0; } else { mainGame->gMutex.lock(); if (mainGame->dField.hovered_card == pc) pc->equipTarget->is_showequip = false; else if (mainGame->dField.hovered_card == pc->equipTarget) pc->is_showequip = false; pc->equipTarget->equipped.erase(pc); pc->equipTarget = 0; mainGame->gMutex.unlock(); } return true; } case MSG_CARD_TARGET: { int c1 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l1 = BufferIO::Read(pbuf); int s1 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int c2 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l2 = BufferIO::Read(pbuf); int s2 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); ClientCard* pc1 = mainGame->dField.GetCard(c1, l1, s1); ClientCard* pc2 = mainGame->dField.GetCard(c2, l2, s2); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pc1->cardTarget.insert(pc2); pc2->ownerTarget.insert(pc1); } else { mainGame->gMutex.lock(); pc1->cardTarget.insert(pc2); pc2->ownerTarget.insert(pc1); if (mainGame->dField.hovered_card == pc1) pc2->is_showtarget = true; else if (mainGame->dField.hovered_card == pc2) pc1->is_showtarget = true; mainGame->gMutex.unlock(); } break; } case MSG_CANCEL_TARGET: { int c1 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l1 = BufferIO::Read(pbuf); int s1 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int c2 = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l2 = BufferIO::Read(pbuf); int s2 = BufferIO::Read(pbuf); BufferIO::Read(pbuf); ClientCard* pc1 = mainGame->dField.GetCard(c1, l1, s1); ClientCard* pc2 = mainGame->dField.GetCard(c2, l2, s2); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { pc1->cardTarget.erase(pc2); pc2->ownerTarget.erase(pc1); } else { mainGame->gMutex.lock(); pc1->cardTarget.erase(pc2); pc2->ownerTarget.erase(pc1); if (mainGame->dField.hovered_card == pc1) pc2->is_showtarget = false; else if (mainGame->dField.hovered_card == pc2) pc1->is_showtarget = false; mainGame->gMutex.unlock(); } break; } case MSG_PAY_LPCOST: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int cost = BufferIO::Read(pbuf); int final = mainGame->dInfo.lp[player] - cost; if (final < 0) final = 0; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) { mainGame->dInfo.lp[player] = final; myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); return true; } soundManager.PlaySoundEffect(SOUND_DAMAGE); mainGame->lpd = (mainGame->dInfo.lp[player] - final) / 10; mainGame->lpccolor = 0xff0000ff; mainGame->lpplayer = player; myswprintf(textBuffer, L"-%d", cost); mainGame->lpcstring = textBuffer; mainGame->WaitFrameSignal(30); mainGame->lpframe = 10; mainGame->WaitFrameSignal(11); mainGame->lpcstring = L""; mainGame->dInfo.lp[player] = final; mainGame->gMutex.lock(); myswprintf(mainGame->dInfo.strLP[player], L"%d", mainGame->dInfo.lp[player]); mainGame->gMutex.unlock(); return true; } case MSG_ADD_COUNTER: { int type = BufferIO::Read(pbuf); int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); ClientCard* pc = mainGame->dField.GetCard(c, l, s); if (pc->counters.count(type)) pc->counters[type] += count; else pc->counters[type] = count; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_COUNTER_ADD); myswprintf(textBuffer, dataManager.GetSysString(1617), dataManager.GetName(pc->code), count, dataManager.GetCounterName(type)); pc->is_highlighting = true; mainGame->gMutex.lock(); mainGame->stACMessage->setText(textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); pc->is_highlighting = false; return true; } case MSG_REMOVE_COUNTER: { int type = BufferIO::Read(pbuf); int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); int count = BufferIO::Read(pbuf); ClientCard* pc = mainGame->dField.GetCard(c, l, s); pc->counters[type] -= count; if (pc->counters[type] <= 0) pc->counters.erase(type); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_COUNTER_REMOVE); myswprintf(textBuffer, dataManager.GetSysString(1618), dataManager.GetName(pc->code), count, dataManager.GetCounterName(type)); pc->is_highlighting = true; mainGame->gMutex.lock(); mainGame->stACMessage->setText(textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); pc->is_highlighting = false; return true; } case MSG_ATTACK: { int ca = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int la = BufferIO::Read(pbuf); int sa = BufferIO::Read(pbuf); BufferIO::Read(pbuf); mainGame->dField.attacker = mainGame->dField.GetCard(ca, la, sa); int cd = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int ld = BufferIO::Read(pbuf); int sd = BufferIO::Read(pbuf); BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; float sy; if (ld != 0) { soundManager.PlaySoundEffect(SOUND_ATTACK); mainGame->dField.attack_target = mainGame->dField.GetCard(cd, ld, sd); myswprintf(event_string, dataManager.GetSysString(1619), dataManager.GetName(mainGame->dField.attacker->code), dataManager.GetName(mainGame->dField.attack_target->code)); float xa = mainGame->dField.attacker->curPos.X; float ya = mainGame->dField.attacker->curPos.Y; float xd = mainGame->dField.attack_target->curPos.X; float yd = mainGame->dField.attack_target->curPos.Y; sy = (float)sqrt((xa - xd) * (xa - xd) + (ya - yd) * (ya - yd)) / 2; mainGame->atk_t = irr::core::vector3df((xa + xd) / 2, (ya + yd) / 2, 0); if (ca == 0) mainGame->atk_r = irr::core::vector3df(0, 0, -atan((xd - xa) / (yd - ya))); else mainGame->atk_r = irr::core::vector3df(0, 0, 3.1415926 - atan((xd - xa) / (yd - ya))); } else { soundManager.PlaySoundEffect(SOUND_DIRECT_ATTACK); myswprintf(event_string, dataManager.GetSysString(1620), dataManager.GetName(mainGame->dField.attacker->code)); float xa = mainGame->dField.attacker->curPos.X; float ya = mainGame->dField.attacker->curPos.Y; float xd = 3.95f; float yd = 3.5f; if (ca == 0) yd = -3.5f; sy = (float)sqrt((xa - xd) * (xa - xd) + (ya - yd) * (ya - yd)) / 2; mainGame->atk_t = irr::core::vector3df((xa + xd) / 2, (ya + yd) / 2, 0); if (ca == 0) mainGame->atk_r = irr::core::vector3df(0, 0, -atan((xd - xa) / (yd - ya))); else mainGame->atk_r = irr::core::vector3df(0, 0, 3.1415926 - atan((xd - xa) / (yd - ya))); } matManager.GenArrow(sy); mainGame->attack_sv = 0; mainGame->is_attacking = true; mainGame->WaitFrameSignal(40); mainGame->is_attacking = false; return true; } case MSG_BATTLE: { int ca = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int la = BufferIO::Read(pbuf); int sa = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int aatk = BufferIO::Read(pbuf); int adef = BufferIO::Read(pbuf); /*int da = */BufferIO::Read(pbuf); int cd = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int ld = BufferIO::Read(pbuf); int sd = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int datk = BufferIO::Read(pbuf); int ddef = BufferIO::Read(pbuf); /*int dd = */BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; mainGame->gMutex.lock(); ClientCard* pcard = mainGame->dField.GetCard(ca, la, sa); if(aatk != pcard->attack) { pcard->attack = aatk; myswprintf(pcard->atkstring, L"%d", aatk); } if(adef != pcard->defense) { pcard->defense = adef; myswprintf(pcard->defstring, L"%d", adef); } if(ld) { pcard = mainGame->dField.GetCard(cd, ld, sd); if(datk != pcard->attack) { pcard->attack = datk; myswprintf(pcard->atkstring, L"%d", datk); } if(ddef != pcard->defense) { pcard->defense = ddef; myswprintf(pcard->defstring, L"%d", ddef); } } mainGame->gMutex.unlock(); return true; } case MSG_ATTACK_DISABLED: { myswprintf(event_string, dataManager.GetSysString(1621), dataManager.GetName(mainGame->dField.attacker->code)); return true; } case MSG_DAMAGE_STEP_START: { return true; } case MSG_DAMAGE_STEP_END: { return true; } case MSG_MISSED_EFFECT: { BufferIO::Read(pbuf); unsigned int code = BufferIO::Read(pbuf); myswprintf(textBuffer, dataManager.GetSysString(1622), dataManager.GetName(code)); mainGame->AddLog(textBuffer, code); return true; } case MSG_TOSS_COIN: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); wchar_t* pwbuf = textBuffer; BufferIO::CopyWStrRef(dataManager.GetSysString(1623), pwbuf, 256); for (int i = 0; i < count; ++i) { int res = BufferIO::Read(pbuf); *pwbuf++ = L'['; BufferIO::CopyWStrRef(dataManager.GetSysString(res ? 60 : 61), pwbuf, 256); *pwbuf++ = L']'; } *pwbuf = 0; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_COIN); mainGame->gMutex.lock(); mainGame->AddLog(textBuffer); mainGame->stACMessage->setText(textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); return true; } case MSG_TOSS_DICE: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); wchar_t* pwbuf = textBuffer; BufferIO::CopyWStrRef(dataManager.GetSysString(1624), pwbuf, 256); for (int i = 0; i < count; ++i) { int res = BufferIO::Read(pbuf); *pwbuf++ = L'['; *pwbuf++ = L'0' + res; *pwbuf++ = L']'; } *pwbuf = 0; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; soundManager.PlaySoundEffect(SOUND_DICE); mainGame->gMutex.lock(); mainGame->AddLog(textBuffer); mainGame->stACMessage->setText(textBuffer); mainGame->PopupElement(mainGame->wACMessage, 20); mainGame->gMutex.unlock(); mainGame->WaitFrameSignal(40); return true; } case MSG_ROCK_PAPER_SCISSORS: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; mainGame->gMutex.lock(); mainGame->PopupElement(mainGame->wHand); mainGame->gMutex.unlock(); return false; } case MSG_HAND_RES: { int res = BufferIO::Read(pbuf); if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; mainGame->stHintMsg->setVisible(false); int res1 = (res & 0x3) - 1; int res2 = ((res >> 2) & 0x3) - 1; if(mainGame->dInfo.isFirst) mainGame->showcardcode = res1 + (res2 << 16); else mainGame->showcardcode = res2 + (res1 << 16); mainGame->showcarddif = 50; mainGame->showcardp = 0; mainGame->showcard = 100; mainGame->WaitFrameSignal(60); return false; } case MSG_ANNOUNCE_RACE: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); mainGame->dField.announce_count = BufferIO::Read(pbuf); int available = BufferIO::Read(pbuf); for(int i = 0, filter = 0x1; i < RACES_COUNT; ++i, filter <<= 1) { mainGame->chkRace[i]->setChecked(false); if(filter & available) mainGame->chkRace[i]->setVisible(true); else mainGame->chkRace[i]->setVisible(false); } if(select_hint) myswprintf(textBuffer, L"%ls", dataManager.GetDesc(select_hint)); else myswprintf(textBuffer, dataManager.GetSysString(563)); select_hint = 0; mainGame->gMutex.lock(); mainGame->wANRace->setText(textBuffer); mainGame->PopupElement(mainGame->wANRace); mainGame->gMutex.unlock(); return false; } case MSG_ANNOUNCE_ATTRIB: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); mainGame->dField.announce_count = BufferIO::Read(pbuf); int available = BufferIO::Read(pbuf); for(int i = 0, filter = 0x1; i < 7; ++i, filter <<= 1) { mainGame->chkAttribute[i]->setChecked(false); if(filter & available) mainGame->chkAttribute[i]->setVisible(true); else mainGame->chkAttribute[i]->setVisible(false); } if(select_hint) myswprintf(textBuffer, L"%ls", dataManager.GetDesc(select_hint)); else myswprintf(textBuffer, dataManager.GetSysString(562)); select_hint = 0; mainGame->gMutex.lock(); mainGame->wANAttribute->setText(textBuffer); mainGame->PopupElement(mainGame->wANAttribute); mainGame->gMutex.unlock(); return false; } case MSG_ANNOUNCE_CARD: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); mainGame->dField.declare_opcodes.clear(); for (int i = 0; i < count; ++i) mainGame->dField.declare_opcodes.push_back(BufferIO::Read(pbuf)); if(select_hint) myswprintf(textBuffer, L"%ls", dataManager.GetDesc(select_hint)); else myswprintf(textBuffer, dataManager.GetSysString(564)); select_hint = 0; mainGame->gMutex.lock(); mainGame->ebANCard->setText(L""); mainGame->wANCard->setText(textBuffer); mainGame->dField.UpdateDeclarableList(); mainGame->PopupElement(mainGame->wANCard); mainGame->gMutex.unlock(); return false; } case MSG_ANNOUNCE_NUMBER: { /*int player = */mainGame->LocalPlayer(BufferIO::Read(pbuf)); int count = BufferIO::Read(pbuf); mainGame->gMutex.lock(); mainGame->cbANNumber->clear(); bool quickmode = count <= 12; if(quickmode) { for(int i = 0; i < 12; ++i) { mainGame->btnANNumber[i]->setEnabled(false); mainGame->btnANNumber[i]->setPressed(false); mainGame->btnANNumber[i]->setVisible(true); } } for (int i = 0; i < count; ++i) { int value = BufferIO::Read(pbuf); myswprintf(textBuffer, L" % d", value); mainGame->cbANNumber->addItem(textBuffer, value); if(quickmode) { if((value > 12 || value <= 0)) { quickmode = false; } else { mainGame->btnANNumber[value - 1]->setEnabled(true); } } } mainGame->cbANNumber->setSelected(0); if(quickmode) { mainGame->cbANNumber->setVisible(false); mainGame->btnANNumberOK->setRelativePosition(irr::core::rect(20, 195, 210, 230)); mainGame->btnANNumberOK->setEnabled(false); irr::core::recti pos = mainGame->wANNumber->getRelativePosition(); pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + 250; mainGame->wANNumber->setRelativePosition(pos); } else { for(int i = 0; i < 12; ++i) { mainGame->btnANNumber[i]->setVisible(false); } mainGame->cbANNumber->setVisible(true); mainGame->btnANNumberOK->setRelativePosition(irr::core::rect(80, 60, 150, 85)); irr::core::recti pos = mainGame->wANNumber->getRelativePosition(); pos.LowerRightCorner.Y = pos.UpperLeftCorner.Y + 95; mainGame->wANNumber->setRelativePosition(pos); } if(select_hint) myswprintf(textBuffer, L"%ls", dataManager.GetDesc(select_hint)); else myswprintf(textBuffer, dataManager.GetSysString(565)); select_hint = 0; mainGame->wANNumber->setText(textBuffer); mainGame->PopupElement(mainGame->wANNumber); mainGame->gMutex.unlock(); return false; } case MSG_CARD_HINT: { int c = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int l = BufferIO::Read(pbuf); int s = BufferIO::Read(pbuf); BufferIO::Read(pbuf); int chtype = BufferIO::Read(pbuf); int value = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(c, l, s); if(!pcard) return true; if(chtype == CHINT_DESC_ADD) { pcard->desc_hints[value]++; } else if(chtype == CHINT_DESC_REMOVE) { pcard->desc_hints[value]--; if(pcard->desc_hints[value] == 0) pcard->desc_hints.erase(value); } else { pcard->cHint = chtype; pcard->chValue = value; if(chtype == CHINT_TURN) { if(value == 0) return true; if(mainGame->dInfo.isReplay && mainGame->dInfo.isReplaySkiping) return true; if(pcard->location & LOCATION_ONFIELD) pcard->is_highlighting = true; mainGame->showcardcode = pcard->code; mainGame->showcarddif = 0; mainGame->showcardp = value - 1; mainGame->showcard = 6; mainGame->WaitFrameSignal(30); pcard->is_highlighting = false; mainGame->showcard = 0; } } return true; } case MSG_PLAYER_HINT: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); int chtype = BufferIO::Read(pbuf); int value = BufferIO::Read(pbuf); auto& player_desc_hints = mainGame->dField.player_desc_hints[player]; if(value == CARD_QUESTION && player == 0) { if(chtype == PHINT_DESC_ADD) { mainGame->dField.cant_check_grave = true; } else if(chtype == PHINT_DESC_REMOVE) { mainGame->dField.cant_check_grave = false; } } else if(chtype == PHINT_DESC_ADD) { player_desc_hints[value]++; } else if(chtype == PHINT_DESC_REMOVE) { player_desc_hints[value]--; if(player_desc_hints[value] == 0) player_desc_hints.erase(value); } return true; } case MSG_MATCH_KILL: { match_kill = BufferIO::Read(pbuf); return true; } case MSG_TAG_SWAP: { int player = mainGame->LocalPlayer(BufferIO::Read(pbuf)); size_t mcount = (size_t)BufferIO::Read(pbuf); size_t ecount = (size_t)BufferIO::Read(pbuf); size_t pcount = (size_t)BufferIO::Read(pbuf); size_t hcount = (size_t)BufferIO::Read(pbuf); int topcode = BufferIO::Read(pbuf); if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ++cit) { if(player == 0) (*cit)->dPos.Y = 0.4f; else (*cit)->dPos.Y = -0.6f; (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->aniFrame = 5; } for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) { if(player == 0) (*cit)->dPos.Y = 0.4f; else (*cit)->dPos.Y = -0.6f; (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->aniFrame = 5; } for (auto cit = mainGame->dField.extra[player].begin(); cit != mainGame->dField.extra[player].end(); ++cit) { if(player == 0) (*cit)->dPos.Y = 0.4f; else (*cit)->dPos.Y = -0.6f; (*cit)->dRot = irr::core::vector3df(0, 0, 0); (*cit)->is_moving = true; (*cit)->aniFrame = 5; } mainGame->WaitFrameSignal(5); } // if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) mainGame->gMutex.lock(); if(mainGame->dField.deck[player].size() > mcount) { while(mainGame->dField.deck[player].size() > mcount) { ClientCard* ccard = *mainGame->dField.deck[player].rbegin(); mainGame->dField.deck[player].pop_back(); delete ccard; } } else { while(mainGame->dField.deck[player].size() < mcount) { ClientCard* ccard = new ClientCard; ccard->controler = player; ccard->location = LOCATION_DECK; ccard->sequence = (unsigned char)mainGame->dField.deck[player].size(); mainGame->dField.deck[player].push_back(ccard); } } if(mainGame->dField.hand[player].size() > hcount) { while(mainGame->dField.hand[player].size() > hcount) { ClientCard* ccard = *mainGame->dField.hand[player].rbegin(); mainGame->dField.hand[player].pop_back(); delete ccard; } } else { while(mainGame->dField.hand[player].size() < hcount) { ClientCard* ccard = new ClientCard; ccard->controler = player; ccard->location = LOCATION_HAND; ccard->sequence = (unsigned char)mainGame->dField.hand[player].size(); mainGame->dField.hand[player].push_back(ccard); } } if(mainGame->dField.extra[player].size() > ecount) { while(mainGame->dField.extra[player].size() > ecount) { ClientCard* ccard = *mainGame->dField.extra[player].rbegin(); mainGame->dField.extra[player].pop_back(); delete ccard; } } else { while(mainGame->dField.extra[player].size() < ecount) { ClientCard* ccard = new ClientCard; ccard->controler = player; ccard->location = LOCATION_EXTRA; ccard->sequence = (unsigned char)mainGame->dField.extra[player].size(); mainGame->dField.extra[player].push_back(ccard); } } mainGame->dField.extra_p_count[player] = pcount; if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) mainGame->gMutex.unlock(); // if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { for (auto cit = mainGame->dField.deck[player].begin(); cit != mainGame->dField.deck[player].end(); ++cit) { ClientCard* pcard = *cit; mainGame->dField.GetCardLocation(pcard, &pcard->curPos, &pcard->curRot); if(player == 0) pcard->curPos.Y += 2.0f; else pcard->curPos.Y -= 3.0f; mainGame->dField.MoveCard(*cit, 5); } if(mainGame->dField.deck[player].size()) (*mainGame->dField.deck[player].rbegin())->code = topcode; for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) { ClientCard* pcard = *cit; pcard->code = BufferIO::Read(pbuf); mainGame->dField.GetCardLocation(pcard, &pcard->curPos, &pcard->curRot); if(player == 0) pcard->curPos.Y += 2.0f; else pcard->curPos.Y -= 3.0f; mainGame->dField.MoveCard(*cit, 5); } for (auto cit = mainGame->dField.extra[player].begin(); cit != mainGame->dField.extra[player].end(); ++cit) { ClientCard* pcard = *cit; pcard->code = BufferIO::Read(pbuf) & 0x7fffffff; mainGame->dField.GetCardLocation(pcard, &pcard->curPos, &pcard->curRot); if(player == 0) pcard->curPos.Y += 2.0f; else pcard->curPos.Y -= 3.0f; mainGame->dField.MoveCard(*cit, 5); } mainGame->WaitFrameSignal(5); } break; } case MSG_RELOAD_FIELD: { if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->gMutex.lock(); } mainGame->dField.Clear(); mainGame->dInfo.duel_rule = BufferIO::Read(pbuf); int val = 0; for(int i = 0; i < 2; ++i) { int p = mainGame->LocalPlayer(i); mainGame->dInfo.lp[p] = BufferIO::Read(pbuf); myswprintf(mainGame->dInfo.strLP[p], L"%d", mainGame->dInfo.lp[p]); for(int seq = 0; seq < 7; ++seq) { val = BufferIO::Read(pbuf); if(val) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_MZONE, seq); ccard->position = BufferIO::Read(pbuf); val = BufferIO::Read(pbuf); if(val) { for(int xyz = 0; xyz < val; ++xyz) { ClientCard* xcard = new ClientCard; ccard->overlayed.push_back(xcard); mainGame->dField.overlay_cards.insert(xcard); xcard->overlayTarget = ccard; xcard->location = LOCATION_OVERLAY; xcard->sequence = (unsigned char)(ccard->overlayed.size() - 1); xcard->owner = p; xcard->controler = p; } } } } for(int seq = 0; seq < 8; ++seq) { val = BufferIO::Read(pbuf); if(val) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_SZONE, seq); ccard->position = BufferIO::Read(pbuf); } } val = BufferIO::Read(pbuf); for(int seq = 0; seq < val; ++seq) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_DECK, seq); } val = BufferIO::Read(pbuf); for(int seq = 0; seq < val; ++seq) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_HAND, seq); } val = BufferIO::Read(pbuf); for(int seq = 0; seq < val; ++seq) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_GRAVE, seq); } val = BufferIO::Read(pbuf); for(int seq = 0; seq < val; ++seq) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_REMOVED, seq); } val = BufferIO::Read(pbuf); for(int seq = 0; seq < val; ++seq) { ClientCard* ccard = new ClientCard; mainGame->dField.AddCard(ccard, p, LOCATION_EXTRA, seq); } val = BufferIO::Read(pbuf); mainGame->dField.extra_p_count[p] = val; } mainGame->dField.RefreshAllCards(); val = BufferIO::Read(pbuf); //chains for(int i = 0; i < val; ++i) { unsigned int code = BufferIO::Read(pbuf); int pcc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int pcl = BufferIO::Read(pbuf); int pcs = BufferIO::Read(pbuf); int subs = BufferIO::Read(pbuf); int cc = mainGame->LocalPlayer(BufferIO::Read(pbuf)); unsigned int cl = BufferIO::Read(pbuf); int cs = BufferIO::Read(pbuf); int desc = BufferIO::Read(pbuf); ClientCard* pcard = mainGame->dField.GetCard(pcc, pcl, pcs, subs); mainGame->dField.current_chain.chain_card = pcard; mainGame->dField.current_chain.code = code; mainGame->dField.current_chain.desc = desc; mainGame->dField.current_chain.controler = cc; mainGame->dField.current_chain.location = cl; mainGame->dField.current_chain.sequence = cs; mainGame->dField.GetChainLocation(cc, cl, cs, &mainGame->dField.current_chain.chain_pos); mainGame->dField.current_chain.solved = false; int chc = 0; for(auto chit = mainGame->dField.chains.begin(); chit != mainGame->dField.chains.end(); ++chit) { if(cl == 0x10 || cl == 0x20) { if(chit->controler == cc && chit->location == cl) chc++; } else { if(chit->controler == cc && chit->location == cl && chit->sequence == cs) chc++; } } if(cl == LOCATION_HAND) mainGame->dField.current_chain.chain_pos.X += 0.35f; else mainGame->dField.current_chain.chain_pos.Y += chc * 0.25f; mainGame->dField.chains.push_back(mainGame->dField.current_chain); } if(val) { myswprintf(event_string, dataManager.GetSysString(1609), dataManager.GetName(mainGame->dField.current_chain.code)); mainGame->dField.last_chain = true; } if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping) { mainGame->gMutex.unlock(); } break; } } return true; } void DuelClient::SwapField() { is_swapping = true; } void DuelClient::SetResponseI(int32_t respI) { std::memcpy(response_buf, &respI, sizeof respI); response_len = sizeof respI; } void DuelClient::SetResponseB(void* respB, size_t len) { if (len > SIZE_RETURN_VALUE) len = SIZE_RETURN_VALUE; std::memcpy(response_buf, respB, len); response_len = len; } void DuelClient::SendResponse() { switch(mainGame->dInfo.curMsg) { case MSG_SELECT_BATTLECMD: { mainGame->dField.ClearCommandFlag(); mainGame->btnM2->setVisible(false); mainGame->btnEP->setVisible(false); break; } case MSG_SELECT_IDLECMD: { mainGame->dField.ClearCommandFlag(); mainGame->btnBP->setVisible(false); mainGame->btnEP->setVisible(false); mainGame->btnShuffle->setVisible(false); break; } case MSG_SELECT_CARD: case MSG_SELECT_UNSELECT_CARD: case MSG_SELECT_TRIBUTE: case MSG_SELECT_SUM: case MSG_SELECT_COUNTER: { mainGame->dField.ClearSelect(); break; } case MSG_SELECT_CHAIN: { mainGame->dField.ClearChainSelect(); break; } } if(mainGame->dInfo.isSingleMode) { SingleMode::SetResponse(response_buf, response_len); mainGame->singleSignal.Set(); } else { mainGame->dInfo.time_player = 2; SendBufferToServer(CTOS_RESPONSE, response_buf, response_len); } } void DuelClient::BeginRefreshHost() { if(is_refreshing) return; is_refreshing = true; mainGame->btnLanRefresh->setEnabled(false); mainGame->lstHostList->clear(); remotes.clear(); hosts.clear(); event_base* broadev = event_base_new(); char hname[256]; gethostname(hname, 256); hostent* host = gethostbyname(hname); if(!host) return; SOCKET reply = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); sockaddr_in reply_addr; std::memset(&reply_addr, 0, sizeof reply_addr); reply_addr.sin_family = AF_INET; reply_addr.sin_port = htons(7921); reply_addr.sin_addr.s_addr = 0; if(bind(reply, (sockaddr*)&reply_addr, sizeof(reply_addr)) == SOCKET_ERROR) { closesocket(reply); return; } timeval timeout = {3, 0}; resp_event = event_new(broadev, reply, EV_TIMEOUT | EV_READ | EV_PERSIST, BroadcastReply, broadev); event_add(resp_event, &timeout); std::thread(RefreshThread, broadev).detach(); //send request SOCKADDR_IN local; local.sin_family = AF_INET; local.sin_port = htons(7922); SOCKADDR_IN sockTo; sockTo.sin_addr.s_addr = htonl(INADDR_BROADCAST); sockTo.sin_family = AF_INET; sockTo.sin_port = htons(7920); HostRequest hReq; hReq.identifier = NETWORK_CLIENT_ID; for(int i = 0; i < 8; ++i) { if(host->h_addr_list[i] == 0) break; unsigned int local_addr = 0; std::memcpy(&local_addr, host->h_addr_list[i], sizeof local_addr); local.sin_addr.s_addr = local_addr; SOCKET sSend = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sSend == INVALID_SOCKET) break; int opt = TRUE; setsockopt(sSend, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof opt); if(bind(sSend, (sockaddr*)&local, sizeof(sockaddr)) == SOCKET_ERROR) { closesocket(sSend); break; } sendto(sSend, (const char*)&hReq, sizeof(HostRequest), 0, (sockaddr*)&sockTo, sizeof(sockaddr)); closesocket(sSend); } } int DuelClient::RefreshThread(event_base* broadev) { event_base_dispatch(broadev); evutil_socket_t fd; event_get_assignment(resp_event, 0, &fd, 0, 0, 0); evutil_closesocket(fd); event_free(resp_event); event_base_free(broadev); is_refreshing = false; return 0; } void DuelClient::BroadcastReply(evutil_socket_t fd, short events, void * arg) { if(events & EV_TIMEOUT) { evutil_closesocket(fd); event_base_loopbreak((event_base*)arg); if(!is_closing) mainGame->btnLanRefresh->setEnabled(true); } else if(events & EV_READ) { sockaddr_in bc_addr; socklen_t sz = sizeof(sockaddr_in); char buf[256]; /*int ret = */recvfrom(fd, buf, 256, 0, (sockaddr*)&bc_addr, &sz); HostPacket packet; std::memcpy(&packet, buf, sizeof packet); HostPacket* pHP = &packet; if(is_closing || pHP->identifier != NETWORK_SERVER_ID) return; if(pHP->version != PRO_VERSION) return; unsigned int ipaddr = bc_addr.sin_addr.s_addr; const auto remote = std::make_pair(ipaddr, pHP->port); if(remotes.find(remote) == remotes.end()) { mainGame->gMutex.lock(); remotes.insert(remote); pHP->ipaddr = ipaddr; hosts.push_back(*pHP); std::wstring hoststr; hoststr.append(L"["); hoststr.append(deckManager.GetLFListName(pHP->host.lflist)); hoststr.append(L"]["); hoststr.append(dataManager.GetSysString(pHP->host.rule + 1481)); hoststr.append(L"]["); hoststr.append(dataManager.GetSysString(pHP->host.mode + 1244)); hoststr.append(L"]["); if(pHP->host.draw_count == 1 && pHP->host.start_hand == 5 && pHP->host.start_lp == 8000 && !pHP->host.no_check_deck && !pHP->host.no_shuffle_deck && pHP->host.duel_rule == DEFAULT_DUEL_RULE) hoststr.append(dataManager.GetSysString(1247)); else hoststr.append(dataManager.GetSysString(1248)); hoststr.append(L"]"); wchar_t gamename[20]; BufferIO::CopyCharArray(pHP->name, gamename); hoststr.append(gamename); mainGame->lstHostList->addItem(hoststr.c_str()); mainGame->gMutex.unlock(); } } } }