Files
ygopro/gframe/duelclient.cpp

4158 lines
149 KiB
C++

#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 <thread>
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<float> DuelClient::real_dist;
bool DuelClient::is_refreshing = false;
int DuelClient::match_kill = 0;
std::vector<HostPacket> DuelClient::hosts;
std::set<std::pair<unsigned int, unsigned short>> 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;
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::ReadUInt8(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::ReadInt16(pdata);
int extrac = BufferIO::ReadInt16(pdata);
int sidec = BufferIO::ReadInt16(pdata);
mainGame->dField.Initial(0, deckc, extrac, sidec);
deckc = BufferIO::ReadInt16(pdata);
extrac = BufferIO::ReadInt16(pdata);
sidec = BufferIO::ReadInt16(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 = buffer_read<uint16_t>(pdata);
uint16_t chat_msg[LEN_CHAT_MSG];
buffer_read_block(pdata, chat_msg, 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::ReadUInt8(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::ReadUInt8(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::ReadUInt8(pbuf);
int player = BufferIO::ReadUInt8(pbuf);
int data = BufferIO::ReadInt32(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::ReadUInt8(pbuf);
int type = BufferIO::ReadUInt8(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::ReadUInt8(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::ReadUInt8(pbuf);
mainGame->dInfo.lp[mainGame->LocalPlayer(0)] = BufferIO::ReadInt32(pbuf);
mainGame->dInfo.lp[mainGame->LocalPlayer(1)] = BufferIO::ReadInt32(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::ReadInt16(pbuf);
int extrac = BufferIO::ReadInt16(pbuf);
mainGame->dField.Initial(mainGame->LocalPlayer(0), deckc, extrac);
deckc = BufferIO::ReadInt16(pbuf);
extrac = BufferIO::ReadInt16(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::ReadUInt8(pbuf));
int location = BufferIO::ReadUInt8(pbuf);
mainGame->gMutex.lock();
mainGame->dField.UpdateFieldCard(player, location, pbuf);
mainGame->gMutex.unlock();
return true;
}
case MSG_UPDATE_CARD: {
int player = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int loc = BufferIO::ReadUInt8(pbuf);
int seq = BufferIO::ReadUInt8(pbuf);
mainGame->gMutex.lock();
mainGame->dField.UpdateCard(player, loc, seq, pbuf);
mainGame->gMutex.unlock();
break;
}
case MSG_SELECT_BATTLECMD: {
/*int selecting_player = */BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(pbuf);
desc = BufferIO::ReadInt32(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
/*code = */BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(pbuf);
/*diratt = */BufferIO::ReadUInt8(pbuf);
pcard = mainGame->dField.GetCard(con, loc, seq);
mainGame->dField.attackable_cards.push_back(pcard);
pcard->cmdFlag |= COMMAND_ATTACK;
}
mainGame->gMutex.lock();
if(BufferIO::ReadUInt8(pbuf)) {
mainGame->btnM2->setVisible(true);
mainGame->btnM2->setEnabled(true);
mainGame->btnM2->setPressed(false);
}
if(BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
int desc, count, con, seq;
unsigned int code, loc;
ClientCard* pcard;
mainGame->dField.summonable_cards.clear();
count = BufferIO::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(pbuf);
con = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
loc = BufferIO::ReadUInt8(pbuf);
seq = BufferIO::ReadUInt8(pbuf);
desc = BufferIO::ReadInt32(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::ReadUInt8(pbuf)) {
mainGame->btnBP->setVisible(true);
mainGame->btnBP->setEnabled(true);
mainGame->btnBP->setPressed(false);
}
if(BufferIO::ReadUInt8(pbuf)) {
mainGame->btnEP->setVisible(true);
mainGame->btnEP->setEnabled(true);
mainGame->btnEP->setPressed(false);
}
if (BufferIO::ReadUInt8(pbuf)) {
mainGame->btnShuffle->setVisible(true);
} else {
mainGame->btnShuffle->setVisible(false);
}
return false;
}
case MSG_SELECT_EFFECTYN: {
/*int selecting_player = */BufferIO::ReadUInt8(pbuf);
unsigned int code = BufferIO::ReadInt32(pbuf);
int c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
ClientCard* pcard = mainGame->dField.GetCard(c, l, s);
if (pcard->code != code)
pcard->SetCode(code);
BufferIO::ReadUInt8(pbuf);
if(l != LOCATION_DECK) {
pcard->is_highlighting = true;
mainGame->dField.highlighting_card = pcard;
}
int desc = BufferIO::ReadInt32(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::ReadUInt8(pbuf);
int desc = BufferIO::ReadInt32(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::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_options.clear();
for (int i = 0; i < count; ++i)
mainGame->dField.select_options.push_back(BufferIO::ReadInt32(pbuf));
mainGame->dField.ShowSelectOption(select_hint);
select_hint = 0;
return false;
}
case MSG_SELECT_CARD: {
/*int selecting_player = */BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_cancelable = BufferIO::ReadUInt8(pbuf) != 0;
mainGame->dField.select_min = BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_max = BufferIO::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
ss = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
bool finishable = BufferIO::ReadUInt8(pbuf) != 0;
bool cancelable = BufferIO::ReadUInt8(pbuf) != 0;
mainGame->dField.select_cancelable = finishable || cancelable;
mainGame->dField.select_min = BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_max = BufferIO::ReadUInt8(pbuf);
int count1 = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
ss = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
for (int i = count1; i < count1 + count2; ++i) {
code = (unsigned int)BufferIO::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
ss = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(pbuf);
int specount = BufferIO::ReadUInt8(pbuf);
int forced = BufferIO::ReadUInt8(pbuf);
/*int hint0 = */BufferIO::ReadInt32(pbuf);
/*int hint1 = */BufferIO::ReadInt32(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 = (forced != 0);
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::ReadUInt8(pbuf);
code = BufferIO::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
ss = BufferIO::ReadUInt8(pbuf);
desc = BufferIO::ReadInt32(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(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 && !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() && forced && !(mainGame->always_chain || mainGame->chain_when_avail)) {
SetResponseI(0);
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(!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::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadInt32(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::ReadUInt8(pbuf);
unsigned int code = (unsigned int)BufferIO::ReadInt32(pbuf);
unsigned int positions = BufferIO::ReadUInt8(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<irr::s32>(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<irr::s32>(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<irr::s32>(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<irr::s32>(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::ReadUInt8(pbuf);
mainGame->dField.select_cancelable = BufferIO::ReadUInt8(pbuf) != 0;
mainGame->dField.select_min = BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_max = BufferIO::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
t = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
mainGame->dField.select_counter_type = BufferIO::ReadInt16(pbuf);
mainGame->dField.select_counter_count = BufferIO::ReadInt16(pbuf);
int count = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
t = BufferIO::ReadInt16(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::ReadUInt8(pbuf);
/*int selecting_player = */BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_sumval = BufferIO::ReadInt32(pbuf);
mainGame->dField.select_min = BufferIO::ReadUInt8(pbuf);
mainGame->dField.select_max = BufferIO::ReadUInt8(pbuf);
mainGame->dField.must_select_count = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
int c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
ClientCard* pcard = mainGame->dField.GetCard(c, l, s);
if (code != 0 && pcard->code != code)
pcard->SetCode(code);
pcard->opParam = BufferIO::ReadInt32(pbuf);
pcard->select_seq = 0;
mainGame->dField.selected_cards.push_back(pcard);
}
int count = BufferIO::ReadUInt8(pbuf);
for (int i = 0; i < count; ++i) {
unsigned int code = (unsigned int)BufferIO::ReadInt32(pbuf);
int c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
ClientCard* pcard = mainGame->dField.GetCard(c, l, s);
if (code != 0 && pcard->code != code)
pcard->SetCode(code);
pcard->opParam = BufferIO::ReadInt32(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::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
unsigned int code;
ClientCard* pcard;
mainGame->dField.selectable_cards.clear();
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
unsigned int code;
ClientCard* pcard;
mainGame->dField.selectable_cards.clear();
for (int i = 0; i < count; ++i) {
code = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
int c, s;
unsigned int code, l;
std::vector<ClientCard*> field_confirm;
std::vector<ClientCard*> 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::ReadInt32(pbuf);
c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(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 (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::ReadUInt8(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(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::ReadInt32(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(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::ReadInt32(pbuf));
return true;
}
case MSG_REFRESH_DECK: {
/*int player = */mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
return true;
}
case MSG_SWAP_GRAVE_DECK: {
int player = mainGame->LocalPlayer(BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int seq = BufferIO::ReadUInt8(pbuf);
unsigned int code = BufferIO::ReadInt32(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<ClientCard*>* lst = 0;
unsigned int loc = BufferIO::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
l = BufferIO::ReadUInt8(pbuf);
s = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(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::ReadInt16(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::ReadInt32(pbuf);
int pc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int pl = BufferIO::ReadUInt8(pbuf);
int ps = BufferIO::ReadUInt8(pbuf);
unsigned int pp = BufferIO::ReadUInt8(pbuf);
int cc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int cl = BufferIO::ReadUInt8(pbuf);
int cs = BufferIO::ReadUInt8(pbuf);
unsigned int cp = BufferIO::ReadUInt8(pbuf);
int reason = BufferIO::ReadInt32(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::ReadInt32(pbuf);
int cc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int cl = BufferIO::ReadUInt8(pbuf);
int cs = BufferIO::ReadUInt8(pbuf);
unsigned int pp = BufferIO::ReadUInt8(pbuf);
unsigned int cp = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
/*int cc = mainGame->LocalPlayer*/(BufferIO::ReadUInt8(pbuf));
/*int cl = */BufferIO::ReadUInt8(pbuf);
/*int cs = */BufferIO::ReadUInt8(pbuf);
/*int cp = */BufferIO::ReadUInt8(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::ReadInt32(pbuf);
int c1 = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l1 = BufferIO::ReadUInt8(pbuf);
int s1 = BufferIO::ReadUInt8(pbuf);
/*int p1 = */BufferIO::ReadUInt8(pbuf);
/*int code2 = */BufferIO::ReadInt32(pbuf);
int c2 = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l2 = BufferIO::ReadUInt8(pbuf);
int s2 = BufferIO::ReadUInt8(pbuf);
/*int p2 = */BufferIO::ReadUInt8(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::ReadInt32(pbuf);
if (!mainGame->dInfo.isFirst)
disabled = (disabled >> 16) | (disabled << 16);
mainGame->dField.disabled_field = disabled;
return true;
}
case MSG_SUMMONING: {
unsigned int code = BufferIO::ReadInt32(pbuf);
/*int cc = */mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
/*int cl = */BufferIO::ReadUInt8(pbuf);
/*int cs = */BufferIO::ReadUInt8(pbuf);
/*int cp = */BufferIO::ReadUInt8(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::ReadInt32(pbuf);
/*int cc = */mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
/*int cl = */BufferIO::ReadUInt8(pbuf);
/*int cs = */BufferIO::ReadUInt8(pbuf);
/*int cp = */BufferIO::ReadUInt8(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));
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::ReadInt32(pbuf);
int cc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int cl = BufferIO::ReadUInt8(pbuf);
int cs = BufferIO::ReadUInt8(pbuf);
unsigned int cp = BufferIO::ReadUInt8(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::ReadInt32(pbuf);
int pcc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int pcl = BufferIO::ReadUInt8(pbuf);
int pcs = BufferIO::ReadUInt8(pbuf);
int subs = BufferIO::ReadUInt8(pbuf);
int cc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int cl = BufferIO::ReadUInt8(pbuf);
int cs = BufferIO::ReadUInt8(pbuf);
int desc = BufferIO::ReadInt32(pbuf);
/*int ct = */BufferIO::ReadUInt8(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::ReadUInt8(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::ReadUInt8(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::ReadUInt8(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::ReadUInt8(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::ReadUInt8(pbuf);
int count = BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
int ss = BufferIO::ReadUInt8(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::ReadUInt8(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::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
/*int ss = */BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
ClientCard* pcard;
for (int i = 0; i < count; ++i) {
unsigned int code = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int val = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int val = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
unsigned int l1 = BufferIO::ReadUInt8(pbuf);
int s1 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int c2 = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l2 = BufferIO::ReadUInt8(pbuf);
int s2 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int val = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
unsigned int l1 = BufferIO::ReadUInt8(pbuf);
int s1 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
unsigned int l1 = BufferIO::ReadUInt8(pbuf);
int s1 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int c2 = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l2 = BufferIO::ReadUInt8(pbuf);
int s2 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
unsigned int l1 = BufferIO::ReadUInt8(pbuf);
int s1 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int c2 = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l2 = BufferIO::ReadUInt8(pbuf);
int s2 = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int cost = BufferIO::ReadInt32(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::ReadInt16(pbuf);
int c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
int count = BufferIO::ReadInt16(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::ReadInt16(pbuf);
int c = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
int count = BufferIO::ReadInt16(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::ReadUInt8(pbuf));
unsigned int la = BufferIO::ReadUInt8(pbuf);
int sa = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
mainGame->dField.attacker = mainGame->dField.GetCard(ca, la, sa);
int cd = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int ld = BufferIO::ReadUInt8(pbuf);
int sd = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
unsigned int la = BufferIO::ReadUInt8(pbuf);
int sa = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int aatk = BufferIO::ReadInt32(pbuf);
int adef = BufferIO::ReadInt32(pbuf);
/*int da = */BufferIO::ReadUInt8(pbuf);
int cd = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int ld = BufferIO::ReadUInt8(pbuf);
int sd = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int datk = BufferIO::ReadInt32(pbuf);
int ddef = BufferIO::ReadInt32(pbuf);
/*int dd = */BufferIO::ReadUInt8(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::ReadInt32(pbuf);
unsigned int code = BufferIO::ReadInt32(pbuf);
myswprintf(textBuffer, dataManager.GetSysString(1622), dataManager.GetName(code));
mainGame->AddLog(textBuffer, code);
return true;
}
case MSG_TOSS_COIN: {
/*int player = */mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
wchar_t* pwbuf = textBuffer;
BufferIO::CopyWStrRef(dataManager.GetSysString(1623), pwbuf, 256);
for (int i = 0; i < count; ++i) {
int res = BufferIO::ReadUInt8(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
wchar_t* pwbuf = textBuffer;
BufferIO::CopyWStrRef(dataManager.GetSysString(1624), pwbuf, 256);
for (int i = 0; i < count; ++i) {
int res = BufferIO::ReadUInt8(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::ReadUInt8(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::ReadUInt8(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::ReadUInt8(pbuf));
mainGame->dField.announce_count = BufferIO::ReadUInt8(pbuf);
int available = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
mainGame->dField.announce_count = BufferIO::ReadUInt8(pbuf);
int available = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(pbuf);
mainGame->dField.declare_opcodes.clear();
for (int i = 0; i < count; ++i)
mainGame->dField.declare_opcodes.push_back(buffer_read<uint32_t>(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::ReadUInt8(pbuf));
int count = BufferIO::ReadUInt8(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::ReadInt32(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<irr::s32>(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<irr::s32>(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::ReadUInt8(pbuf));
unsigned int l = BufferIO::ReadUInt8(pbuf);
int s = BufferIO::ReadUInt8(pbuf);
BufferIO::ReadUInt8(pbuf);
int chtype = BufferIO::ReadUInt8(pbuf);
int value = BufferIO::ReadInt32(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::ReadUInt8(pbuf));
int chtype = BufferIO::ReadUInt8(pbuf);
int value = BufferIO::ReadInt32(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::ReadInt32(pbuf);
return true;
}
case MSG_TAG_SWAP: {
int player = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
size_t mcount = (size_t)BufferIO::ReadUInt8(pbuf);
size_t ecount = (size_t)BufferIO::ReadUInt8(pbuf);
size_t pcount = (size_t)BufferIO::ReadUInt8(pbuf);
size_t hcount = (size_t)BufferIO::ReadUInt8(pbuf);
int topcode = BufferIO::ReadInt32(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::ReadInt32(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::ReadInt32(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::ReadUInt8(pbuf);
int val = 0;
for(int i = 0; i < 2; ++i) {
int p = mainGame->LocalPlayer(i);
mainGame->dInfo.lp[p] = BufferIO::ReadInt32(pbuf);
myswprintf(mainGame->dInfo.strLP[p], L"%d", mainGame->dInfo.lp[p]);
for(int seq = 0; seq < 7; ++seq) {
val = BufferIO::ReadUInt8(pbuf);
if(val) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_MZONE, seq);
ccard->position = BufferIO::ReadUInt8(pbuf);
val = BufferIO::ReadUInt8(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::ReadUInt8(pbuf);
if(val) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_SZONE, seq);
ccard->position = BufferIO::ReadUInt8(pbuf);
}
}
val = BufferIO::ReadUInt8(pbuf);
for(int seq = 0; seq < val; ++seq) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_DECK, seq);
}
val = BufferIO::ReadUInt8(pbuf);
for(int seq = 0; seq < val; ++seq) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_HAND, seq);
}
val = BufferIO::ReadUInt8(pbuf);
for(int seq = 0; seq < val; ++seq) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_GRAVE, seq);
}
val = BufferIO::ReadUInt8(pbuf);
for(int seq = 0; seq < val; ++seq) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_REMOVED, seq);
}
val = BufferIO::ReadUInt8(pbuf);
for(int seq = 0; seq < val; ++seq) {
ClientCard* ccard = new ClientCard;
mainGame->dField.AddCard(ccard, p, LOCATION_EXTRA, seq);
}
val = BufferIO::ReadUInt8(pbuf);
mainGame->dField.extra_p_count[p] = val;
}
mainGame->dField.RefreshAllCards();
val = BufferIO::ReadUInt8(pbuf); //chains
for(int i = 0; i < val; ++i) {
unsigned int code = BufferIO::ReadInt32(pbuf);
int pcc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int pcl = BufferIO::ReadUInt8(pbuf);
int pcs = BufferIO::ReadUInt8(pbuf);
int subs = BufferIO::ReadUInt8(pbuf);
int cc = mainGame->LocalPlayer(BufferIO::ReadUInt8(pbuf));
unsigned int cl = BufferIO::ReadUInt8(pbuf);
int cs = BufferIO::ReadUInt8(pbuf);
int desc = BufferIO::ReadInt32(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();
}
}
}
}