Commit f5b3aad9 authored by nanahira's avatar nanahira

Merge branch 'master' of https://github.com/moecube/ygopro-2pick

parents 5850958a ea808d53
os=require("os")
io=require("io")
--globals
local main={[0]={},[1]={}}
local extra={[0]={},[1]={}}
local main_monster={[0]={},[1]={}}
local main_spell={[0]={},[1]={}}
local main_trap={[0]={},[1]={}}
local main_plain={[0]={},[1]={}}
local main_adv={[0]={},[1]={}}
local extra_sp={
[TYPE_FUSION]={[0]={},[1]={}},
[TYPE_SYNCHRO]={[0]={},[1]={}},
[TYPE_XYZ]={[0]={},[1]={}},
[TYPE_LINK]={[0]={},[1]={}},
}
function Auxiliary.SplitData(inputstr)
local t={}
for str in string.gmatch(inputstr,"([^|]+)") do
table.insert(t,tonumber(str))
end
return t
end
function Auxiliary.LoadDB(p,pool)
local file=io.popen("echo \"select * from datas;\" | sqlite3 "..pool)
for line in file:lines() do
local data=Auxiliary.SplitData(line)
local code=data[1]
local cat=data[5]
local lv=data[8] & 0xff
if (cat & TYPE_FUSION+TYPE_SYNCHRO+TYPE_XYZ+TYPE_LINK)>0 then
table.insert(extra[p],code)
for tp,list in pairs(extra_sp) do
if (cat & tp)>0 then
table.insert(list[p],code)
end
end
elseif (cat & TYPE_TOKEN)==0 then
if (cat & TYPE_MONSTER)>0 then
table.insert(main_monster[p],code)
if lv>4 then
table.insert(main_adv[p],code)
else
table.insert(main_plain[p],code)
end
elseif (cat & TYPE_SPELL)>0 then
table.insert(main_spell[p],code)
elseif (cat & TYPE_TRAP)>0 then
table.insert(main_trap[p],code)
end
table.insert(main[p],code)
end
end
file:close()
end
--to do: multi card pools
function Auxiliary.LoadCardPools()
local pool_list={}
local file=io.popen("ls 2pick/*.cdb")
for pool in file:lines() do
table.insert(pool_list,pool)
end
file:close()
for p=0,1 do
Auxiliary.LoadDB(p,pool_list[math.random(#pool_list)])
end
end
function Auxiliary.SaveDeck()
for p=0,1 do
local g=Duel.GetFieldGroup(p,0xff,0)
Duel.SavePickDeck(p,g)
end
end
function Auxiliary.SinglePick(p,list,count,ex_list,ex_count,copy)
if not Duel.IsPlayerNeedToPickDeck(p) then return end
local g1=Group.CreateGroup()
local g2=Group.CreateGroup()
local plist=list[p]
for _,g in ipairs({g1,g2}) do
for i=1,count do
local code=plist[math.random(#plist)]
g:AddCard(Duel.CreateToken(p,code))
end
if ex_list and ex_count then
local ex_plist=ex_list[p]
for i=1,ex_count do
local code=ex_plist[math.random(#ex_plist)]
g:AddCard(Duel.CreateToken(p,code))
end
end
Duel.SendtoDeck(g,nil,0,REASON_RULE)
end
local sg=g1:Clone()
sg:Merge(g2)
Duel.ResetTimeLimit(p,70)
Duel.Hint(HINT_SELECTMSG,p,HINTMSG_TODECK)
local sc=sg:Select(p,1,1,nil):GetFirst()
local tg=g1:IsContains(sc) and g1 or g2
local rg=g1:IsContains(sc) and g2 or g1
Duel.Exile(rg,REASON_RULE)
if copy then
local g3=Group.CreateGroup()
for nc in aux.Next(tg) do
local copy_code=nc:GetOriginalCode()
g3:AddCard(Duel.CreateToken(p,copy_code))
end
Duel.SendtoDeck(g3,nil,0,REASON_RULE)
end
end
function Auxiliary.StartPick(e)
for p=0,1 do
if Duel.IsPlayerNeedToPickDeck(p) then
local g=Duel.GetFieldGroup(p,0xff,0)
Duel.Exile(g,REASON_RULE)
end
end
for i=1,5 do
local list=main_plain
local count=4
local ex_list=nil
local ex_count=nil
if i<3 then
count=3
ex_list=main_adv
ex_count=1
elseif i==4 then
list=main_spell
elseif i==5 then
list=main_trap
end
for p=0,1 do
Auxiliary.SinglePick(p,list,count,ex_list,ex_count,true)
end
end
for p=0,1 do
if Duel.IsPlayerNeedToPickDeck(p) then
Duel.ResetTimeLimit(p,70)
local cg=Duel.GetFieldGroup(p,LOCATION_DECK,0)
Duel.ConfirmCards(p,cg)
end
end
for tp,list in pairs(extra_sp) do
if tp~=TYPE_FUSION then
for p=0,1 do
Auxiliary.SinglePick(p,list,4,nil,nil,false)
end
end
end
for i=1,2 do
for p=0,1 do
Auxiliary.SinglePick(p,extra,4,nil,nil,false)
end
end
Auxiliary.SaveDeck()
for p=0,1 do
if Duel.IsPlayerNeedToPickDeck(p) then
Duel.ShuffleDeck(p)
Duel.ResetTimeLimit(p)
end
end
for p=0,1 do
Duel.Draw(p,Duel.GetStartCount(p),REASON_RULE)
end
e:Reset()
end
function Auxiliary.Load2PickRule()
math.randomseed(os.time())
Auxiliary.LoadCardPools()
local e1=Effect.GlobalEffect()
e1:SetType(EFFECT_TYPE_FIELD | EFFECT_TYPE_CONTINUOUS)
e1:SetCode(EVENT_ADJUST)
e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
e1:SetOperation(Auxiliary.StartPick)
Duel.RegisterEffect(e1,0)
end
## KoishiPro
The server for KoishiPro custom version. Used in 222 Custom Card Server and YGOCC.
## YGOPro 2Pick test
A ygopro server for testing 2pick mode
......@@ -49,9 +49,9 @@ after_build:
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://nodejs.org/dist/v9.1.0/node-v9.1.0-win-x64.zip ; exit 0"
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/MicrosoftArchive/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.zip ; exit 0"
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/archive/master.zip ; exit 0"
- 7z x windbot-master.zip
- cd windbot-master
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/archive/pick.zip ; exit 0"
- 7z x windbot-pick.zip
- cd windbot-pick
- msbuild /property:Configuration=Release /property:OutDir=../ygopro-server/windbot
- cd ../ygopro-server
......
......@@ -199,6 +199,7 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec) {
return errorcode;
}
bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
/*
std::unordered_map<int, int> pcount;
std::unordered_map<int, int> ncount;
for(size_t i = 0; i < deck.main.size(); ++i)
......@@ -221,6 +222,7 @@ bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
if(cdit->second != pcount[cdit->first])
return false;
deck = ndeck;
*/
return true;
}
FILE* DeckManager::OpenDeckFile(const wchar_t* file, const char* mode) {
......
......@@ -19,6 +19,7 @@ SingleDuel::SingleDuel(bool is_match) {
for(int i = 0; i < 2; ++i) {
players[i] = 0;
ready[i] = false;
pick_deck_saved[i] = false;
}
duel_count = 0;
memset(match_result, 0, 3);
......@@ -26,6 +27,10 @@ SingleDuel::SingleDuel(bool is_match) {
cache_recorder = 0;
replay_recorder = 0;
#endif
//2pick
int cardlist[128];
cardlist[0] = 89631139;
deckManager.LoadDeck(default_deck, cardlist, 1, 0);
}
SingleDuel::~SingleDuel() {
}
......@@ -366,7 +371,7 @@ void SingleDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
return;
if(is_ready) {
unsigned int deckerror = 0;
if(!host_info.no_check_deck) {
/*if(!host_info.no_check_deck) {
if(deck_error[dp->type]) {
deckerror = (DECKERROR_UNKNOWNCARD << 28) + deck_error[dp->type];
} else {
......@@ -374,7 +379,7 @@ void SingleDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
bool allow_tcg = host_info.rule == 1 || host_info.rule == 2;
deckerror = deckManager.CheckDeck(pdeck[dp->type], host_info.lflist, allow_ocg, allow_tcg);
}
}
}*/
if(deckerror) {
STOC_HS_PlayerChange scpc;
scpc.status = (dp->type << 4) | PLAYERCHANGE_NOTREADY;
......@@ -458,6 +463,9 @@ void SingleDuel::StartDuel(DuelPlayer* dp) {
hand_result[1] = 0;
players[0]->state = CTOS_HAND_RESULT;
players[1]->state = CTOS_HAND_RESULT;
//reset 2pick deck
pick_deck_saved[0] = false;
pick_deck_saved[1] = false;
}
void SingleDuel::HandResult(DuelPlayer* dp, unsigned char res) {
if(res > 3)
......@@ -516,8 +524,16 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
Deck d = pdeck[0];
pdeck[0] = pdeck[1];
pdeck[1] = d;
SwapPickDeck();
swapped = true;
}
//2pick deck check
for(int i = 0; i < 2; i++) {
if(pick_deck_saved[i])
pdeck[i] = pick_deck[i];
else
pdeck[i] = default_deck;
}
dp->state = CTOS_RESPONSE;
ReplayHeader rh;
rh.id = 0x31707279;
......@@ -547,8 +563,10 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
set_message_handler((message_handler)SingleDuel::MessageHandler);
rnd.reset(seed);
pduel = create_duel(rnd.rand());
set_player_info(pduel, 0, host_info.start_lp, host_info.start_hand, host_info.draw_count);
set_player_info(pduel, 1, host_info.start_lp, host_info.start_hand, host_info.draw_count);
set_player_info(pduel, 0, host_info.start_lp, host_info.start_hand, host_info.draw_count, !pick_deck_saved[0]);
set_player_info(pduel, 1, host_info.start_lp, host_info.start_hand, host_info.draw_count, !pick_deck_saved[1]);
pick_deck_saved[0] = false;
pick_deck_saved[1] = false;
int opt = (int)host_info.duel_rule << 16;
if(host_info.no_shuffle_deck)
opt |= DUEL_PSEUDO_SHUFFLE;
......@@ -659,6 +677,7 @@ void SingleDuel::DuelEndProc() {
Deck d = pdeck[0];
pdeck[0] = pdeck[1];
pdeck[1] = d;
SwapPickDeck();
}
ready[0] = false;
ready[1] = false;
......@@ -710,6 +729,33 @@ int SingleDuel::Analyze(char* msgbuffer, unsigned int len) {
offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf);
switch (engType) {
//2pick
case MSG_SAVE_PICK_DECK: {
player = BufferIO::ReadInt8(pbuf);
count = BufferIO::ReadInt8(pbuf);
int cardlist[128];
int counter = 0;
Deck tdeck;
for(int i = 0; i < count; i++) {
int code = BufferIO::ReadInt32(pbuf);
cardlist[counter++] = code;
}
deckManager.LoadDeck(tdeck, cardlist, count, 0);
pick_deck[player] = tdeck;
pick_deck_saved[player] = true;
break;
}
case MSG_RESET_TIME: {
player = BufferIO::ReadInt8(pbuf);
int time = BufferIO::ReadInt8(pbuf);
if(host_info.time_limit) {
if(time)
time_limit[player] = time;
else
time_limit[player] = host_info.time_limit;
}
break;
}
case MSG_RETRY: {
WaitforResponse(last_response);
NetServer::SendBufferToPlayer(players[last_response], STOC_GAME_MSG, offset, pbuf - offset);
......@@ -1944,5 +1990,13 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) {
event_del(sd->etimer);
}
}
void SingleDuel::SwapPickDeck() {
Deck d = pick_deck[0];
pick_deck[0] = pick_deck[1];
pick_deck[1] = d;
bool pick_deck_saved_temp = pick_deck_saved[0];
pick_deck_saved[0] = pick_deck_saved[1];
pick_deck_saved[1] = pick_deck_saved_temp;
}
}
......@@ -40,8 +40,15 @@ public:
static int MessageHandler(long fduel, int type);
static void SingleTimer(evutil_socket_t fd, short events, void* arg);
//2pick
void SwapPickDeck();
protected:
//2pick
Deck default_deck;
Deck pick_deck[2];
bool pick_deck_saved[2];
DuelPlayer* players[2];
DuelPlayer* pplayer[2];
bool ready[2];
......
......@@ -22,7 +22,7 @@ typedef long ptr;
typedef long long int64;
typedef int int32;
typedef short int16;
typedef signed char int8;
typedef char int8;
typedef int BOOL;
#define MATCH_ALL(x,y) (((x)&(y))==(y))
......
......@@ -71,6 +71,7 @@ struct player_info {
int32 lp;
int32 start_count;
int32 draw_count;
int32 pick_needed;
uint32 used_location;
uint32 disabled_location;
uint32 extra_p_count;
......@@ -912,4 +913,7 @@ public:
#define MSG_CUSTOM_MSG 180
#define MSG_SELECT_UNSELECT_CARD 190
//2pick
#define MSG_SAVE_PICK_DECK 220
#define MSG_RESET_TIME 221
#endif /* FIELD_H_ */
......@@ -370,6 +370,11 @@ static const struct luaL_Reg grouplib[] = {
};
static const struct luaL_Reg duellib[] = {
//2pick
{ "SavePickDeck", scriptlib::duel_save_pick_deck },
{ "IsPlayerNeedToPickDeck", scriptlib::duel_is_player_need_to_pick_deck },
{ "GetStartCount", scriptlib::duel_get_start_count },
{ "ResetTimeLimit", scriptlib::duel_reset_time_limit },
//modded
{ "SelectField", scriptlib::duel_select_field },
{ "GetMasterRule", scriptlib::duel_get_master_rule },
......@@ -664,6 +669,8 @@ interpreter::interpreter(duel* pd): coroutines(256) {
lua_setglobal(lua_state, "HINT_MUSIC_OGG");
//load init.lua by MLD
load_script((char*) "./expansions/script/init.lua");
//2pick rule
load_script((char*) "./2pick/pick.lua");
}
interpreter::~interpreter() {
lua_close(lua_state);
......@@ -951,7 +958,12 @@ int32 interpreter::call_code_function(uint32 code, char* f, uint32 param_count,
params.clear();
return OPERATION_FAIL;
}
//modded
if (code > 0) {
load_card_script(code);
} else {
lua_getglobal(current_state, "Auxiliary");
}
lua_getfield(current_state, -1, f);
if (!lua_isfunction(current_state, -1)) {
sprintf(pduel->strbuffer, "\"CallCodeFunction\": attempt to call an error function");
......
......@@ -13,6 +13,57 @@
#include "group.h"
#include "ocgapi.h"
//2pick
int32 scriptlib::duel_save_pick_deck(lua_State * L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 2);
int32 playerid = lua_tonumberint(L, 1);
if(playerid != 0 && playerid != 1)
luaL_error(L, "Parameter 1 should be 0 or 1.", 2);
group* pgroup = *(group**) lua_touserdata(L, 2);
duel* pduel = pgroup->pduel;
if(pgroup->container.size() == 0)
luaL_error(L, "Deck empty.", 2);
pduel->write_buffer8(MSG_SAVE_PICK_DECK);
pduel->write_buffer8(playerid);
pduel->write_buffer8(pgroup->container.size());
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
pduel->write_buffer32((*cit)->data.code);
}
return 0;
}
int32 scriptlib::duel_is_player_need_to_pick_deck(lua_State * L) {
check_param_count(L, 1);
int32 p = lua_tonumberint(L, 1);
if(p != 0 && p != 1)
luaL_error(L, "Parameter 1 should be 0 or 1.", 2);
duel* pduel = interpreter::get_duel_info(L);
lua_pushboolean(L, pduel->game_field->player[p].pick_needed);
return 1;
}
int32 scriptlib::duel_get_start_count(lua_State * L) {
check_param_count(L, 1);
int32 p = lua_tonumberint(L, 1);
if(p != 0 && p != 1)
luaL_error(L, "Parameter 1 should be 0 or 1.", 2);
duel* pduel = interpreter::get_duel_info(L);
lua_pushinteger(L, pduel->game_field->player[p].start_count);
return 1;
}
int32 scriptlib::duel_reset_time_limit(lua_State * L) {
check_param_count(L, 1);
int32 p = lua_tonumberint(L, 1);
int32 time = 0;
if(p != 0 && p != 1)
luaL_error(L, "Parameter 1 should be 0 or 1.", 2);
if(lua_gettop(L) >= 2)
time = lua_tonumberint(L, 2);
duel* pduel = interpreter::get_duel_info(L);
pduel->write_buffer8(MSG_RESET_TIME);
pduel->write_buffer8(p);
pduel->write_buffer8(time);
return 0;
}
//modded
int32 scriptlib::duel_select_field(lua_State * L) {
check_action_permission(L);
......
......@@ -61,6 +61,7 @@ extern "C" DECL_DLLEXPORT ptr create_duel(uint32 seed) {
duel* pduel = new duel();
duel_set.insert(pduel);
pduel->random.reset(seed);
pduel->lua->call_code_function(0, (char*) "Load2PickRule", 0, 0);
return (ptr)pduel;
}
extern "C" DECL_DLLEXPORT void start_duel(ptr pduel, int options) {
......@@ -77,10 +78,12 @@ extern "C" DECL_DLLEXPORT void start_duel(ptr pduel, int options) {
pd->game_field->core.shuffle_hand_check[1] = FALSE;
pd->game_field->core.shuffle_deck_check[0] = FALSE;
pd->game_field->core.shuffle_deck_check[1] = FALSE;
/*
if(pd->game_field->player[0].start_count > 0)
pd->game_field->draw(0, REASON_RULE, PLAYER_NONE, 0, pd->game_field->player[0].start_count);
if(pd->game_field->player[1].start_count > 0)
pd->game_field->draw(0, REASON_RULE, PLAYER_NONE, 1, pd->game_field->player[1].start_count);
*/
if(options & DUEL_TAG_MODE) {
for(int i = 0; i < pd->game_field->player[0].start_count && pd->game_field->player[0].tag_list_main.size(); ++i) {
card* pcard = pd->game_field->player[0].tag_list_main.back();
......@@ -110,7 +113,7 @@ extern "C" DECL_DLLEXPORT void end_duel(ptr pduel) {
delete pd;
}
}
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount) {
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount, bool pick_needed) {
duel* pd = (duel*)pduel;
if(lp > 0)
pd->game_field->player[playerid].lp = lp;
......@@ -118,6 +121,11 @@ extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32
pd->game_field->player[playerid].start_count = startcount;
if(drawcount >= 0)
pd->game_field->player[playerid].draw_count = drawcount;
//2pick
if(pick_needed)
pd->game_field->player[playerid].pick_needed = TRUE;
else
pd->game_field->player[playerid].pick_needed = FALSE;
}
extern "C" DECL_DLLEXPORT void get_log_message(ptr pduel, byte* buf) {
strcpy((char*)buf, ((duel*)pduel)->strbuffer);
......@@ -185,20 +193,22 @@ extern "C" DECL_DLLEXPORT int32 query_card(ptr pduel, uint8 playerid, uint8 loca
pcard = ptduel->game_field->get_field_card(playerid, location, sequence);
else {
field::card_vector* lst = 0;
if(location == LOCATION_HAND)
if(location == LOCATION_HAND )
lst = &ptduel->game_field->player[playerid].list_hand;
else if(location == LOCATION_GRAVE)
else if(location == LOCATION_GRAVE )
lst = &ptduel->game_field->player[playerid].list_grave;
else if(location == LOCATION_REMOVED)
else if(location == LOCATION_REMOVED )
lst = &ptduel->game_field->player[playerid].list_remove;
else if(location == LOCATION_EXTRA)
else if(location == LOCATION_EXTRA )
lst = &ptduel->game_field->player[playerid].list_extra;
else if(location == LOCATION_DECK)
else if(location == LOCATION_DECK )
lst = &ptduel->game_field->player[playerid].list_main;
if(!lst || sequence >= lst->size())
if(!lst || sequence > lst->size())
pcard = 0;
else {
pcard = (*lst)[sequence];
auto cit = lst->begin();
for(uint32 i = 0; i < sequence; ++i, ++cit);
pcard = *cit;
}
}
if(pcard)
......
......@@ -38,7 +38,7 @@ uint32 handle_message(void* pduel, uint32 message_type);
extern "C" DECL_DLLEXPORT ptr create_duel(uint32 seed);
extern "C" DECL_DLLEXPORT void start_duel(ptr pduel, int32 options);
extern "C" DECL_DLLEXPORT void end_duel(ptr pduel);
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount, bool pick_needed = false);
extern "C" DECL_DLLEXPORT void get_log_message(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT int32 get_message(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT int32 process(ptr pduel);
......
......@@ -16,6 +16,11 @@ public:
static int32 check_param(lua_State* L, int32 param_type, int32 index, BOOL retfalse = FALSE);
static int32 check_param_count(lua_State* L, int32 count);
static int32 check_action_permission(lua_State* L);
//2pick
static int32 duel_save_pick_deck(lua_State *L);
static int32 duel_is_player_need_to_pick_deck(lua_State *L);
static int32 duel_get_start_count(lua_State *L);
static int32 duel_reset_time_limit(lua_State *L);
//millux
static int32 card_is_ritual_type(lua_State *L);
//modded
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment