diff --git a/README.md b/README.md index 269ee8953..111d714b0 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ The core logic and lua script processor of YGOPro. This library can be made external of the project and used to power server technologies. It maintains a state engine that is manipulated by Lua scripts using manipulation functions it exposes. ## Compiling +See [ygopro wiki](https://github.com/Fluorohydride/ygopro/wiki). + ### 1.) Download Fluorohydride/ygopro Start by downloading the most parent of the source code. The team developing this project are the de facto edge and experts in our community. The most up-to-date `ocgcore` is a compiled dll version of the `Fluorohydride/ygopro/ocgcore` folders project. @@ -11,56 +13,83 @@ Start by downloading the most parent of the source code. The team developing thi Download premake5.exe, put it in `c:\windows` or a similar folder that is globally accessible via `cmd` or PowerShell. Install Visual Studio 2022, it is the system used for the guide because other parts of the project use C# and most the development team are Windows users. ### 3.) Download dependencies -Dependencies are absent from the main project. There is information on how to build them but the easiest thing to do is to download the following folders from a [soarqin/ygopro](https://github.com/soarqin/ygopro) fork and simply copy them into the `Fluorohydride/ygopro` folder. - -* event -* freetype -* irrlicht * lua -* sqlite3 ### 4.) Create the project files Run the following commands from the command line in the `Fluorohydride/ygopro` folder. -` premake5 vs2022 ` +`premake5 vs2022` -If you are not using Visual Studio 2022 or higher, make necessary adjustments. In the file system open `Fluorohydride/ygopro/build` folder open the `ygo` project. +If you are not using Visual Studio 2022 or higher, make necessary adjustments. In the file system open `Fluorohydride/ygopro/build` folder open the `ygopro` project. ### 5.) Build the system Make sure the code actually compiles. Compile them in the following order one by one: * lua -* sqlite3 * ocgcore This should provide you with `ocgcore.lib` in the build output folder. `YGOCore` requires a `*.dll`; in `ocgcore` project properties change it to a dynamically linked library. Recompile, it should fail with an error indicating missing dependencies. Right click the project, add an existing file. Add `lua.lib` from the build folder to the project. It should now compile. ## Exposed Functions -These three function need to be provided to the core so it can get card and database information. -- `void set_script_reader(script_reader f);` : Interface provided returns scripts based on number that corresponds to a lua file, send in a string. +The 3 functions need to be provided to the core so it can get card and database information. +- `void set_script_reader(script_reader f);` +Interface provided returns scripts based on number that corresponds to a lua file, send in a string. -- `void set_card_reader(card_reader f);` : Interface provided function that provides database information from the `data` table of `cards.cdb`. +- `void set_card_reader(card_reader f);` +Interface provided function that provides database information from the `data` table of `cards.cdb`. -- `void set_message_handler(message_handler f);` : Interface provided function that handles errors +- `void set_message_handler(message_handler f);` +Interface provided function that handles error messages. These functions create the game itself and then manipulate it. -- `ptr create_duel(uint32 seed);` : Create a the instance of the duel using a random number. -- `void start_duel(ptr pduel, int32 options);` : Starts the duel -- `void end_duel(ptr pduel);` : ends the duel -- `void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);` sets the duel up -- `void get_log_message(ptr pduel, byte* buf);` -- `int32 get_message(ptr pduel, byte* buf);` -- `int32 process(ptr pduel);` : do a game tick -- `void new_card(ptr pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position);` : add a card to the duel state. -- `void new_tag_card(ptr pduel, uint32 code, uint8 owner, uint8 location);` : add a new card to the tag pool. -- `int32 query_card(ptr pduel, uint8 playerid, uint8 location, uint8 sequence, int32 query_flag, byte* buf, int32 use_cache);` : find out about a card in a specific spot. -- `int32 query_field_count(ptr pduel, uint8 playerid, uint8 location);` : Get the number of cards in a specific field/zone. -- `int32 query_field_card(ptr pduel, uint8 playerid, uint8 location, int32 query_flag, byte* buf, int32 use_cache);` -- `int32 query_field_info(ptr pduel, byte* buf);` -- `void set_responsei(ptr pduel, int32 value);` -- `void set_responseb(ptr pduel, byte* buf);` -- `int32 preload_script(ptr pduel, char* script, int32 len);` +- `intptr_t create_duel(uint_fast32_t seed);` +Create a the instance of the duel with a PRNG seed. + +- `void start_duel(intptr_t pduel, int32 options);` +Start the duel. + +- `void end_duel(intptr_t pduel);` +End the duel. + +- `void set_player_info(intptr_t pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);` +Set up the duel information. + +- `void get_log_message(intptr_t pduel, char* buf);` + +- `int32 get_message(intptr_t pduel, byte* buf);` + +- `int32 process(intptr_t pduel);` +Do a game tick. + +- `void new_card(intptr_t pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position);` +Add a card to the duel state. + +- `void new_tag_card(intptr_t pduel, uint32 code, uint8 owner, uint8 location);` +Add a new card to the tag pool. + +- `int32 query_field_card(intptr_t pduel, uint8 playerid, uint8 location, uint32 query_flag, byte* buf, int32 use_cache);` +Get a card in a specific location. + +- `int32 query_field_count(intptr_t pduel, uint8 playerid, uint8 location);` +Get the number of cards in a specific location. + +- `int32 query_field_card(intptr_t pduel, uint8 playerid, uint8 location, uint32 query_flag, byte* buf, int32 use_cache);` +Get all cards in some location. + +- `int32 query_field_info(intptr_t pduel, byte* buf);` + +- `void set_responsei(intptr_t pduel, int32 value);` + +- `void set_responseb(intptr_t pduel, byte* buf);` + +- `int32 preload_script(intptr_t pduel, const char* script, int32 len);` + # Lua functions -`interpreter.cpp` +- `libcard.cpp` +- `libdebug.cpp` +- `libduel.cpp` +- `libeffect.cpp` +- `libgroup.cpp` + diff --git a/card.cpp b/card.cpp index 0d9d283bb..7f4fbc134 100644 --- a/card.cpp +++ b/card.cpp @@ -23,9 +23,7 @@ const std::unordered_map card::second_code = { {CARD_HERMOS, 10000070u} }; -bool card_sort::operator()(void* const & p1, void* const & p2) const { - card* c1 = (card*)p1; - card* c2 = (card*)p2; +bool card_sort::operator()(card* const& c1, card* const& c2) const { return c1->cardid < c2->cardid; } bool card_state::is_location(int32 loc) const { @@ -456,7 +454,7 @@ std::tuple card::get_original_code_rule() const { uint32 card::get_code() { if(assume_type == ASSUME_CODE) return assume_value; - if (temp.code != 0xffffffff) + if(temp.code != UINT32_MAX) // prevent recursion, return the former value return temp.code; effect_set effects; uint32 code = std::get<0>(get_original_code_rule()); @@ -464,7 +462,7 @@ uint32 card::get_code() { filter_effect(EFFECT_CHANGE_CODE, &effects); if (effects.size()) code = effects.get_last()->get_value(this); - temp.code = 0xffffffff; + temp.code = UINT32_MAX; return code; } // return: the current second card name @@ -608,7 +606,7 @@ uint32 card::get_type() { return data.type; if(current.is_location(LOCATION_PZONE)) return TYPE_PENDULUM + TYPE_SPELL; - if (temp.type != 0xffffffff) + if(temp.type != UINT32_MAX) // prevent recursion, return the former value return temp.type; effect_set effects; int32 type = data.type; @@ -625,7 +623,7 @@ uint32 card::get_type() { type = effects[i]->get_value(this); temp.type = type; } - temp.type = 0xffffffff; + temp.type = UINT32_MAX; if (data.type & TYPE_TOKEN) type |= TYPE_TOKEN; return type; @@ -993,7 +991,7 @@ uint32 card::get_level() { return 0; if(assume_type == ASSUME_LEVEL) return assume_value; - if (temp.level != 0xffffffff) + if(temp.level != UINT32_MAX) // prevent recursion, return the former value return temp.level; effect_set effects; int32 level = data.level; @@ -1016,7 +1014,7 @@ uint32 card::get_level() { level += up; if(level < 1 && (get_type() & TYPE_MONSTER)) level = 1; - temp.level = 0xffffffff; + temp.level = UINT32_MAX; return level; } uint32 card::get_rank() { @@ -1026,7 +1024,7 @@ uint32 card::get_rank() { return assume_value; if(!(current.location & LOCATION_MZONE)) return data.level; - if (temp.level != 0xffffffff) + if(temp.level != UINT32_MAX) // prevent recursion, return the former value return temp.level; effect_set effects; int32 rank = data.level; @@ -1049,7 +1047,7 @@ uint32 card::get_rank() { rank += up; if(rank < 1 && (get_type() & TYPE_MONSTER)) rank = 1; - temp.level = 0xffffffff; + temp.level = UINT32_MAX; return rank; } uint32 card::get_link() { @@ -1108,7 +1106,7 @@ uint32 card::get_attribute() { return assume_value; if(!(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER) && !is_affected_by_effect(EFFECT_PRE_MONSTER)) return 0; - if (temp.attribute != 0xffffffff) + if(temp.attribute != UINT32_MAX) // prevent recursion, return the former value return temp.attribute; effect_set effects; int32 attribute = data.attribute; @@ -1128,7 +1126,7 @@ uint32 card::get_attribute() { attribute = effects[i]->get_value(this); temp.attribute = attribute; } - temp.attribute = 0xffffffff; + temp.attribute = UINT32_MAX; return attribute; } uint32 card::get_fusion_attribute(uint8 playerid) { @@ -1178,7 +1176,7 @@ uint32 card::get_race() { return assume_value; if(!(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER) && !is_affected_by_effect(EFFECT_PRE_MONSTER)) return 0; - if (temp.race != 0xffffffff) + if(temp.race != UINT32_MAX) // prevent recursion, return the former value return temp.race; effect_set effects; int32 race = data.race; @@ -1198,7 +1196,7 @@ uint32 card::get_race() { race = effects[i]->get_value(this); temp.race = race; } - temp.race = 0xffffffff; + temp.race = UINT32_MAX; return race; } uint32 card::get_link_race(uint8 playerid) { @@ -1234,7 +1232,7 @@ uint32 card::get_grave_race(uint8 playerid) { uint32 card::get_lscale() { if(!current.is_location(LOCATION_PZONE)) return data.lscale; - if (temp.lscale != 0xffffffff) + if(temp.lscale != UINT32_MAX) // prevent recursion, return the former value return temp.lscale; effect_set effects; int32 lscale = data.lscale; @@ -1257,13 +1255,13 @@ uint32 card::get_lscale() { lscale += up + upc; if(lscale < 0 && current.pzone) lscale = 0; - temp.lscale = 0xffffffff; + temp.lscale = UINT32_MAX; return lscale; } uint32 card::get_rscale() { if(!current.is_location(LOCATION_PZONE)) return data.rscale; - if (temp.rscale != 0xffffffff) + if(temp.rscale != UINT32_MAX) // prevent recursion, return the former value return temp.rscale; effect_set effects; int32 rscale = data.rscale; @@ -1286,7 +1284,7 @@ uint32 card::get_rscale() { rscale += up + upc; if(rscale < 0 && current.pzone) rscale = 0; - temp.rscale = 0xffffffff; + temp.rscale = UINT32_MAX; return rscale; } uint32 card::get_link_marker() { @@ -3284,8 +3282,8 @@ int32 card::is_spsummonable_card() { pduel->lua->add_param(pduel->game_field->core.reason_effect, PARAM_TYPE_EFFECT); pduel->lua->add_param(pduel->game_field->core.reason_player, PARAM_TYPE_INT); pduel->lua->add_param(SUMMON_TYPE_SPECIAL, PARAM_TYPE_INT); - pduel->lua->add_param((void*)0, PARAM_TYPE_INT); - pduel->lua->add_param((void*)0, PARAM_TYPE_INT); + pduel->lua->add_param(0, PARAM_TYPE_INT); + pduel->lua->add_param(0, PARAM_TYPE_INT); if(!eset[i]->check_value_condition(5)) return FALSE; } @@ -3303,8 +3301,8 @@ int32 card::is_fusion_summonable_card(uint32 summon_type) { pduel->lua->add_param(pduel->game_field->core.reason_effect, PARAM_TYPE_EFFECT); pduel->lua->add_param(pduel->game_field->core.reason_player, PARAM_TYPE_INT); pduel->lua->add_param(summon_type, PARAM_TYPE_INT); - pduel->lua->add_param((void*)0, PARAM_TYPE_INT); - pduel->lua->add_param((void*)0, PARAM_TYPE_INT); + pduel->lua->add_param(0, PARAM_TYPE_INT); + pduel->lua->add_param(0, PARAM_TYPE_INT); if(!eset[i]->check_value_condition(5)) return FALSE; } diff --git a/card.h b/card.h index 5fe3c330d..17fb8cbdb 100644 --- a/card.h +++ b/card.h @@ -11,6 +11,7 @@ #include "common.h" #include "effectset.h" #include "card_data.h" +#include "sort.h" #include #include #include diff --git a/common.h b/common.h index e810ebb33..f8f99c6e1 100644 --- a/common.h +++ b/common.h @@ -42,9 +42,6 @@ typedef signed char int8; #ifndef NULL #define NULL 0 #endif -struct card_sort { - bool operator()(void* const & c1, void* const & c2) const; -}; #define CURRENT_RULE 5 @@ -80,6 +77,10 @@ struct card_sort { //Flip effect flags #define NO_FLIP_EFFECT 0x10000 +//Move to field flags +#define RETURN_TEMP_REMOVE_TO_FIELD 1 +#define RETURN_TRAP_MONSTER_TO_SZONE 2 + //Types #define TYPE_MONSTER 0x1 // #define TYPE_SPELL 0x2 // diff --git a/duel.h b/duel.h index 45c6f376a..121986ca6 100644 --- a/duel.h +++ b/duel.h @@ -9,6 +9,7 @@ #define DUEL_H_ #include "common.h" +#include "sort.h" #include "mtrandom.h" #include #include diff --git a/effect.cpp b/effect.cpp index e0293b1a3..d219bb6b9 100644 --- a/effect.cpp +++ b/effect.cpp @@ -18,9 +18,9 @@ bool effect_sort_id(const effect* e1, const effect* e2) { bool is_continuous_event(uint32 code) { if (code & EVENT_CUSTOM) return false; - else if (code & 0xf0000) + else if (code & 0xf0000) // EVENT_ADD_COUNTER, EVENT_REMOVE_COUNTER return false; - else if (code & 0xf000) + else if (code & 0xf000) // EVENT_PHASE_START must be continuous, but other EVENT_PHASE must not be return !!(code & EVENT_PHASE_START); else return continuous_event.find(code) != continuous_event.end(); diff --git a/field.cpp b/field.cpp index 15f0b9cd0..88f598d12 100644 --- a/field.cpp +++ b/field.cpp @@ -2536,9 +2536,9 @@ int32 field::check_must_material(group* mg, uint8 playerid, uint32 limit) { return FALSE; return TRUE; } -void field::get_synchro_material(uint8 playerid, card_set* material, effect* ptuner) { - if(ptuner && ptuner->value) { - int32 location = ptuner->value; +void field::get_synchro_material(uint8 playerid, card_set* material, effect* tuner_limit) { + if(tuner_limit && tuner_limit->value) { + int32 location = tuner_limit->value; if(location & LOCATION_MZONE) { for(auto& pcard : player[playerid].list_mzone) { if(pcard && !pcard->is_treated_as_not_on_field()) @@ -2629,15 +2629,15 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 ++ct; } int32 location = LOCATION_MZONE; - effect* ptuner = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); - if(ptuner) { - if(ptuner->value) - location = ptuner->value; - if(ptuner->is_flag(EFFECT_FLAG_SPSUM_PARAM)) { - if(ptuner->s_range && ptuner->s_range > min) - min = ptuner->s_range; - if(ptuner->o_range && ptuner->o_range < max) - max = ptuner->o_range; + effect* tuner_limit = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); + if(tuner_limit) { + if(tuner_limit->value) + location = tuner_limit->value; + if(tuner_limit->is_flag(EFFECT_FLAG_SPSUM_PARAM)) { + if(tuner_limit->s_range && tuner_limit->s_range > min) + min = tuner_limit->s_range; + if(tuner_limit->o_range && tuner_limit->o_range < max) + max = tuner_limit->o_range; } if(min > max) { pduel->restore_assumes(); @@ -2670,16 +2670,16 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 pduel->restore_assumes(); return FALSE; } - if(ptuner) { - if(ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit) { + if(tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(smat, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) { + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) { pduel->restore_assumes(); return FALSE; } } - if(ptuner->value && !(smat->current.location & location)) { + if(tuner_limit->value && !(smat->current.location & location)) { pduel->restore_assumes(); return FALSE; } @@ -2721,16 +2721,16 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 pduel->restore_assumes(); return FALSE; } - if(ptuner) { - if(ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit) { + if(tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(mcard, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) { + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) { pduel->restore_assumes(); return FALSE; } } - if(ptuner->value && !(mcard->current.location & location)) { + if(tuner_limit->value && !(mcard->current.location & location)) { pduel->restore_assumes(); return FALSE; } @@ -2746,14 +2746,14 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 for(auto& pm : mg->container) { if(pm == tuner || pm == smat || must_list.find(pm) != must_list.end() || !pm->is_can_be_synchro_material(pcard, tuner)) continue; - if(ptuner) { - if(ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit) { + if(tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(pm, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) continue; } - if(ptuner->value && !(pm->current.location & location)) + if(tuner_limit->value && !(pm->current.location & location)) continue; } if(pcheck) @@ -2767,14 +2767,14 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 } } else { card_set cv; - get_synchro_material(playerid, &cv, ptuner); + get_synchro_material(playerid, &cv, tuner_limit); for(auto& pm : cv) { if(!pm || pm == tuner || pm == smat || must_list.find(pm) != must_list.end() || !pm->is_can_be_synchro_material(pcard, tuner)) continue; - if(ptuner && ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit && tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(pm, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) continue; } if(pcheck) diff --git a/field.h b/field.h index 5fc259519..a80c8b323 100644 --- a/field.h +++ b/field.h @@ -474,7 +474,7 @@ class field { void attack_all_target_check(); int32 get_must_material_list(uint8 playerid, uint32 limit, card_set* must_list); int32 check_must_material(group* mg, uint8 playerid, uint32 limit); - void get_synchro_material(uint8 playerid, card_set* material, effect* ptuner = nullptr); + void get_synchro_material(uint8 playerid, card_set* material, effect* tuner_limit = nullptr); int32 check_synchro_material(card* pcard, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg); int32 check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg); int32 check_other_synchro_material(const card_vector& nsyn, int32 lv, int32 min, int32 max, int32 mcount); diff --git a/group.h b/group.h index 39d95bd93..fce727980 100644 --- a/group.h +++ b/group.h @@ -9,6 +9,7 @@ #define GROUP_H_ #include "common.h" +#include "sort.h" #include #include diff --git a/interpreter.cpp b/interpreter.cpp index 7e6e4d607..2f0c75a44 100644 --- a/interpreter.cpp +++ b/interpreter.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "duel.h" #include "group.h" #include "card.h" @@ -180,68 +181,70 @@ int32 interpreter::load_card_script(uint32 code) { } return OPERATION_SUCCESS; } -void interpreter::add_param(void *param, int32 type, bool front) { +void interpreter::add_param(void* param, LuaParamType type, bool front) { + lua_param p; + p.ptr = param; if(front) - params.emplace_front(param, type); + params.emplace_front(p, type); else - params.emplace_back(param, type); + params.emplace_back(p, type); } -void interpreter::add_param(int32 param, int32 type, bool front) { +void interpreter::add_param(int32 param, LuaParamType type, bool front) { + lua_param p; + p.integer = param; if(front) - params.emplace_front((void*)(intptr_t)param, type); + params.emplace_front(p, type); else - params.emplace_back((void*)(intptr_t)param, type); + params.emplace_back(p, type); } void interpreter::push_param(lua_State* L, bool is_coroutine) { int32 pushed = 0; for (const auto& it : params) { luaL_checkstack(L, 1, nullptr); - uint32 type = it.second; + auto type = it.second; switch(type) { case PARAM_TYPE_INT: - lua_pushinteger(L, (lua_Integer)it.first); + lua_pushinteger(L, it.first.integer); break; case PARAM_TYPE_STRING: - lua_pushstring(L, (const char *)it.first); + lua_pushstring(L, (const char*)it.first.ptr); break; case PARAM_TYPE_BOOLEAN: - lua_pushboolean(L, (int32)(intptr_t)it.first); + lua_pushboolean(L, it.first.integer); break; case PARAM_TYPE_CARD: { - if (it.first) - lua_rawgeti(L, LUA_REGISTRYINDEX, ((card*)it.first)->ref_handle); + if (it.first.ptr) + lua_rawgeti(L, LUA_REGISTRYINDEX, ((card*)it.first.ptr)->ref_handle); else lua_pushnil(L); break; } case PARAM_TYPE_EFFECT: { - if (it.first) - lua_rawgeti(L, LUA_REGISTRYINDEX, ((effect*)it.first)->ref_handle); + if (it.first.ptr) + lua_rawgeti(L, LUA_REGISTRYINDEX, ((effect*)it.first.ptr)->ref_handle); else lua_pushnil(L); break; } case PARAM_TYPE_GROUP: { - if (it.first) - lua_rawgeti(L, LUA_REGISTRYINDEX, ((group*)it.first)->ref_handle); + if (it.first.ptr) + lua_rawgeti(L, LUA_REGISTRYINDEX, ((group*)it.first.ptr)->ref_handle); else lua_pushnil(L); break; } case PARAM_TYPE_FUNCTION: { - function2value(L, (int32)(intptr_t)it.first); + function2value(L, it.first.integer); break; } case PARAM_TYPE_INDEX: { - int32 index = (int32)(intptr_t)it.first; + int32 index = it.first.integer; if(index > 0) lua_pushvalue(L, index); else if(is_coroutine) { //copy value from current_state to new stack lua_pushvalue(current_state, index); - int32 ref = luaL_ref(current_state, LUA_REGISTRYINDEX); - lua_rawgeti(L, LUA_REGISTRYINDEX, ref); - luaL_unref(current_state, LUA_REGISTRYINDEX, ref); + lua_xmove(current_state, L, 1); } else { //the calling function is pushed before the params, so the actual index is: index - pushed -1 lua_pushvalue(L, index - pushed - 1); @@ -533,7 +536,7 @@ int32 interpreter::get_function_value(int32 f, uint32 param_count, std::vectorstrbuffer, "\"CallCoroutine\": attempt to call a null function"); @@ -551,18 +554,23 @@ int32 interpreter::call_coroutine(int32 f, uint32 param_count, uint32 * yield_va lua_State* rthread; if (it == coroutines.end()) { rthread = lua_newthread(lua_state); + const auto threadref = luaL_ref(lua_state, LUA_REGISTRYINDEX); function2value(rthread, f); if(!lua_isfunction(rthread, -1)) { + luaL_unref(lua_state, LUA_REGISTRYINDEX, threadref); sprintf(pduel->strbuffer, "\"CallCoroutine\": attempt to call an error function"); handle_message(pduel, 1); params.clear(); return OPERATION_FAIL; } ++call_depth; - coroutines.emplace(f, rthread); + auto ret = coroutines.emplace(f, std::make_pair(rthread, threadref)); + it = ret.first; } else { - rthread = it->second; if(step == 0) { + auto threadref = it->second.second; + coroutines.erase(it); + luaL_unref(lua_state, LUA_REGISTRYINDEX, threadref); sprintf(pduel->strbuffer, "recursive event trigger detected."); handle_message(pduel, 1); params.clear(); @@ -573,49 +581,44 @@ int32 interpreter::call_coroutine(int32 f, uint32 param_count, uint32 * yield_va } return OPERATION_FAIL; } + rthread = it->second.first; } push_param(rthread, true); - lua_State* prev_state = current_state; - current_state = rthread; + int32 result = 0, nresults = 0; + { + auto prev_state = std::exchange(current_state, rthread); #if (LUA_VERSION_NUM >= 504) - int32 nresults; - int32 result = lua_resume(rthread, prev_state, param_count, &nresults); + result = lua_resume(rthread, prev_state, param_count, &nresults); #else - int32 result = lua_resume(rthread, 0, param_count); - int32 nresults = lua_gettop(rthread); + result = lua_resume(rthread, prev_state, param_count); + nresults = lua_gettop(rthread); #endif - if (result == LUA_OK) { - coroutines.erase(f); - if(yield_value) { - if(nresults == 0) - *yield_value = 0; - else if(lua_isboolean(rthread, -1)) - *yield_value = lua_toboolean(rthread, -1); - else - *yield_value = (uint32)lua_tointeger(rthread, -1); - } - current_state = lua_state; - --call_depth; - if(call_depth == 0) { - pduel->release_script_group(); - pduel->restore_assumes(); - } - return COROUTINE_FINISH; - } else if (result == LUA_YIELD) { + current_state = prev_state; + } + if (result == LUA_YIELD) return COROUTINE_YIELD; - } else { - coroutines.erase(f); + if (result != LUA_OK) { sprintf(pduel->strbuffer, "%s", lua_tostring(rthread, -1)); handle_message(pduel, 1); lua_pop(rthread, 1); - current_state = lua_state; - --call_depth; - if(call_depth == 0) { - pduel->release_script_group(); - pduel->restore_assumes(); - } - return COROUTINE_ERROR; } + else if (yield_value) { + if (nresults == 0) + *yield_value = 0; + else if (lua_isboolean(rthread, -1)) + *yield_value = lua_toboolean(rthread, -1); + else + *yield_value = (int32)lua_tointeger(rthread, -1); + } + auto threadref = it->second.second; + coroutines.erase(it); + luaL_unref(lua_state, LUA_REGISTRYINDEX, threadref); + --call_depth; + if (call_depth == 0) { + pduel->release_script_group(); + pduel->restore_assumes(); + } + return (result == LUA_OK) ? COROUTINE_FINISH : COROUTINE_ERROR; } int32 interpreter::clone_function_ref(int32 func_ref) { luaL_checkstack(current_state, 1, nullptr); @@ -632,7 +635,7 @@ void* interpreter::get_ref_object(int32 ref_handler) { lua_pop(current_state, 1); return p; } -//Convert a pointer to a lua value, +1 -0 +//push the object onto the stack, +1 void interpreter::card2value(lua_State* L, card* pcard) { luaL_checkstack(L, 1, nullptr); if (!pcard || pcard->ref_handle == 0) diff --git a/interpreter.h b/interpreter.h index 99b223e42..78ba0d44c 100644 --- a/interpreter.h +++ b/interpreter.h @@ -22,10 +22,25 @@ class effect; class group; class duel; +enum LuaParamType { + PARAM_TYPE_INT = 0x01, + PARAM_TYPE_STRING = 0x02, + PARAM_TYPE_CARD = 0x04, + PARAM_TYPE_GROUP = 0x08, + PARAM_TYPE_EFFECT = 0x10, + PARAM_TYPE_FUNCTION = 0x20, + PARAM_TYPE_BOOLEAN = 0x40, + PARAM_TYPE_INDEX = 0x80, +}; + class interpreter { public: - using coroutine_map = std::unordered_map; - using param_list = std::list>; + union lua_param { + void* ptr; + int32 integer; + }; + using coroutine_map = std::unordered_map>; + using param_list = std::list>; duel* pduel; char msgbuf[64]; @@ -48,8 +63,8 @@ class interpreter { int32 load_script(const char* script_name); int32 load_card_script(uint32 code); - void add_param(void* param, int32 type, bool front = false); - void add_param(int32 param, int32 type, bool front = false); + void add_param(void* param, LuaParamType type, bool front = false); + void add_param(int32 param, LuaParamType type, bool front = false); void push_param(lua_State* L, bool is_coroutine = false); int32 call_function(int32 f, uint32 param_count, int32 ret_count); int32 call_card_function(card* pcard, const char* f, uint32 param_count, int32 ret_count); @@ -59,14 +74,14 @@ class interpreter { int32 get_operation_value(card* pcard, int32 findex, int32 extraargs); int32 get_function_value(int32 f, uint32 param_count); int32 get_function_value(int32 f, uint32 param_count, std::vector* result); - int32 call_coroutine(int32 f, uint32 param_count, uint32* yield_value, uint16 step); + int32 call_coroutine(int32 f, uint32 param_count, int32* yield_value, uint16 step); int32 clone_function_ref(int32 func_ref); void* get_ref_object(int32 ref_handler); static void card2value(lua_State* L, card* pcard); static void group2value(lua_State* L, group* pgroup); static void effect2value(lua_State* L, effect* peffect); - static void function2value(lua_State* L, int32 pointer); + static void function2value(lua_State* L, int32 func_ref); static int32 get_function_handle(lua_State* L, int32 index); static duel* get_duel_info(lua_State* L); @@ -76,15 +91,6 @@ class interpreter { } }; -#define PARAM_TYPE_INT 0x01 -#define PARAM_TYPE_STRING 0x02 -#define PARAM_TYPE_CARD 0x04 -#define PARAM_TYPE_GROUP 0x08 -#define PARAM_TYPE_EFFECT 0x10 -#define PARAM_TYPE_FUNCTION 0x20 -#define PARAM_TYPE_BOOLEAN 0x40 -#define PARAM_TYPE_INDEX 0x80 - #define COROUTINE_FINISH 1 #define COROUTINE_YIELD 2 #define COROUTINE_ERROR 3 diff --git a/libduel.cpp b/libduel.cpp index 694f92241..6e71e9302 100644 --- a/libduel.cpp +++ b/libduel.cpp @@ -897,7 +897,7 @@ int32 scriptlib::duel_return_to_field(lua_State *L) { pcard->enable_field_effect(false); pduel->game_field->adjust_instant(); pduel->game_field->refresh_location_info_instant(); - pduel->game_field->move_to_field(pcard, pcard->previous.controler, pcard->previous.controler, pcard->previous.location, pos, TRUE, 1, pcard->previous.pzone, zone); + pduel->game_field->move_to_field(pcard, pcard->previous.controler, pcard->previous.controler, pcard->previous.location, pos, TRUE, RETURN_TEMP_REMOVE_TO_FIELD, pcard->previous.pzone, zone); return lua_yieldk(L, 0, (lua_KContext)pduel, [](lua_State *L, int32 status, lua_KContext ctx) { duel* pduel = (duel*)ctx; lua_pushboolean(L, pduel->game_field->returns.ivalue[0]); @@ -3227,7 +3227,8 @@ int32 scriptlib::duel_select_synchro_material(lua_State *L) { lua_pushvalue(L, 3); lua_pushvalue(L, 4); lua_pushvalue(L, 2); - return lua_yield(L, 3); + lua_xmove(L, pduel->lua->lua_state, 3); + return lua_yield(L, 0); } int32 scriptlib::duel_check_synchro_material(lua_State *L) { check_param_count(L, 5); @@ -3286,7 +3287,8 @@ int32 scriptlib::duel_select_tuner_material(lua_State *L) { lua_pushvalue(L, 4); lua_pushvalue(L, 5); lua_pushvalue(L, 2); - return lua_yield(L, 3); + lua_xmove(L, pduel->lua->lua_state, 3); + return lua_yield(L, 0); } int32 scriptlib::duel_check_tuner_material(lua_State *L) { check_param_count(L, 6); @@ -4358,7 +4360,7 @@ int32 scriptlib::duel_is_player_can_flipsummon(lua_State * L) { return 1; } int32 scriptlib::duel_is_player_can_spsummon_monster(lua_State * L) { - check_param_count(L, 9); + check_param_count(L, 2); int32 playerid = (int32)lua_tointeger(L, 1); if(playerid != 0 && playerid != 1) { lua_pushboolean(L, 0); @@ -4369,21 +4371,19 @@ int32 scriptlib::duel_is_player_can_spsummon_monster(lua_State * L) { ::read_card(code, &dat); dat.code = code; dat.alias = 0; - if(!lua_isnil(L, 3)) { - uint64 setcode_list = lua_tointeger(L, 3); - dat.set_setcode(setcode_list); - } - if(!lua_isnil(L, 4)) + if(lua_gettop(L) >= 3 && !lua_isnil(L, 3)) + dat.set_setcode((uint64)lua_tointeger(L, 3)); + if(lua_gettop(L) >= 4 && !lua_isnil(L, 4)) dat.type = (uint32)lua_tointeger(L, 4); - if(!lua_isnil(L, 5)) + if(lua_gettop(L) >= 5 && !lua_isnil(L, 5)) dat.attack = (int32)lua_tointeger(L, 5); - if(!lua_isnil(L, 6)) + if(lua_gettop(L) >= 6 && !lua_isnil(L, 6)) dat.defense = (int32)lua_tointeger(L, 6); - if(!lua_isnil(L, 7)) + if(lua_gettop(L) >= 7 && !lua_isnil(L, 7)) dat.level = (uint32)lua_tointeger(L, 7); - if(!lua_isnil(L, 8)) + if(lua_gettop(L) >= 8 && !lua_isnil(L, 8)) dat.race = (uint32)lua_tointeger(L, 8); - if(!lua_isnil(L, 9)) + if(lua_gettop(L) >= 9 && !lua_isnil(L, 9)) dat.attribute = (uint32)lua_tointeger(L, 9); int32 pos = POS_FACEUP; int32 toplayer = playerid; diff --git a/ocgapi.cpp b/ocgapi.cpp index 7295d8368..fc36f2f4d 100644 --- a/ocgapi.cpp +++ b/ocgapi.cpp @@ -120,8 +120,8 @@ extern "C" DECL_DLLEXPORT void set_player_info(intptr_t pduel, int32 playerid, i if(drawcount >= 0) pd->game_field->player[playerid].draw_count = drawcount; } -extern "C" DECL_DLLEXPORT void get_log_message(intptr_t pduel, byte* buf) { - std::strcpy((char*)buf, ((duel*)pduel)->strbuffer); +extern "C" DECL_DLLEXPORT void get_log_message(intptr_t pduel, char* buf) { + std::strcpy(buf, ((duel*)pduel)->strbuffer); } extern "C" DECL_DLLEXPORT int32 get_message(intptr_t pduel, byte* buf) { int32 len = ((duel*)pduel)->read_buffer(buf); diff --git a/ocgapi.h b/ocgapi.h index 7ad5597db..8d9dafd51 100644 --- a/ocgapi.h +++ b/ocgapi.h @@ -42,7 +42,7 @@ extern "C" DECL_DLLEXPORT intptr_t create_duel(uint_fast32_t seed); extern "C" DECL_DLLEXPORT void start_duel(intptr_t pduel, int32 options); extern "C" DECL_DLLEXPORT void end_duel(intptr_t pduel); extern "C" DECL_DLLEXPORT void set_player_info(intptr_t pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount); -extern "C" DECL_DLLEXPORT void get_log_message(intptr_t pduel, byte* buf); +extern "C" DECL_DLLEXPORT void get_log_message(intptr_t pduel, char* buf); extern "C" DECL_DLLEXPORT int32 get_message(intptr_t pduel, byte* buf); extern "C" DECL_DLLEXPORT uint32 process(intptr_t pduel); extern "C" DECL_DLLEXPORT void new_card(intptr_t pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position); diff --git a/operations.cpp b/operations.cpp index c8eef5c47..d28196faf 100644 --- a/operations.cpp +++ b/operations.cpp @@ -1352,7 +1352,7 @@ int32 field::trap_monster_adjust(uint16 step) { pcard->reset(RESET_TURN_SET, RESET_EVENT); if(core.duel_rule <= 4) refresh_location_info_instant(); - move_to_field(pcard, tp, tp, LOCATION_SZONE, pcard->current.position, FALSE, 2); + move_to_field(pcard, tp, tp, LOCATION_SZONE, pcard->current.position, FALSE, RETURN_TRAP_MONSTER_TO_SZONE); } tp = 1 - tp; } @@ -4550,7 +4550,7 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, switch(step) { case 0: { returns.ivalue[0] = FALSE; - if((ret == 1) && (!(target->current.reason & REASON_TEMPORARY) || (target->current.reason_effect->owner != core.reason_effect->owner))) + if((ret == RETURN_TEMP_REMOVE_TO_FIELD) && (!(target->current.reason & REASON_TEMPORARY) || (target->current.reason_effect->owner != core.reason_effect->owner))) return TRUE; if(location == LOCATION_SZONE && zone == 0x1 << 5 && (target->data.type & TYPE_FIELD) && (target->data.type & TYPE_SPELL)) { card* pcard = get_field_card(playerid, LOCATION_SZONE, 5); @@ -4585,7 +4585,7 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, uint32 flag; uint32 lreason = (target->current.location == LOCATION_MZONE) ? LOCATION_REASON_CONTROL : LOCATION_REASON_TOFIELD; int32 ct = get_useable_count(target, playerid, location, move_player, lreason, zone, &flag); - if((ret == 1) && (ct <= 0 || target->is_status(STATUS_FORBIDDEN) || !(positions & POS_FACEDOWN) && check_unique_onfield(target, playerid, location))) { + if((ret == RETURN_TEMP_REMOVE_TO_FIELD) && (ct <= 0 || target->is_status(STATUS_FORBIDDEN) || !(positions & POS_FACEDOWN) && check_unique_onfield(target, playerid, location))) { core.units.begin()->step = 3; send_to(target, core.reason_effect, REASON_RULE, core.reason_player, PLAYER_NONE, LOCATION_GRAVE, 0, 0); return FALSE; @@ -4604,7 +4604,7 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, } } } - if(ret == 2 && core.duel_rule <= 4) { + if(ret == RETURN_TRAP_MONSTER_TO_SZONE && core.duel_rule <= 4) { returns.bvalue[2] = target->previous.sequence; return FALSE; } @@ -4632,7 +4632,7 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, uint32 seq = returns.bvalue[2]; if(location == LOCATION_SZONE && zone == 0x1 << 5 && (target->data.type & TYPE_FIELD) && (target->data.type & TYPE_SPELL)) seq = 5; - if(ret != 1) { + if(ret != RETURN_TEMP_REMOVE_TO_FIELD) { if(location != target->current.location) { uint32 resetflag = 0; if(location & LOCATION_ONFIELD) @@ -4649,10 +4649,10 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, } if(!(target->current.location & LOCATION_ONFIELD)) target->clear_relate_effect(); - if(ret == 1) + if(ret == RETURN_TEMP_REMOVE_TO_FIELD) target->current.reason &= ~REASON_TEMPORARY; if(ret == 0 && location != target->current.location - || ret == 1 && target->turnid != infos.turn_id) { + || ret == RETURN_TEMP_REMOVE_TO_FIELD && target->turnid != infos.turn_id) { target->set_status(STATUS_SUMMON_TURN, FALSE); target->set_status(STATUS_FLIP_SUMMON_TURN, FALSE); target->set_status(STATUS_SPSUMMON_TURN, FALSE); @@ -4770,9 +4770,9 @@ int32 field::move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, } } } - if(enable || ((ret == 1) && target->is_position(POS_FACEUP))) + if(enable || ((ret == RETURN_TEMP_REMOVE_TO_FIELD) && target->is_position(POS_FACEUP))) target->enable_field_effect(true); - if(ret == 1 && target->current.location == LOCATION_MZONE && !(target->data.type & TYPE_MONSTER)) + if(ret == RETURN_TEMP_REMOVE_TO_FIELD && target->current.location == LOCATION_MZONE && !(target->data.type & TYPE_MONSTER)) send_to(target, 0, REASON_RULE, PLAYER_NONE, PLAYER_NONE, LOCATION_GRAVE, 0, 0); else { if(target->previous.location == LOCATION_GRAVE) { @@ -4955,7 +4955,7 @@ int32 field::change_position(uint16 step, group * targets, effect * reason_effec pcard->unequip(); if(trapmonster) { refresh_location_info_instant(); - move_to_field(pcard, pcard->current.controler, pcard->current.controler, LOCATION_SZONE, POS_FACEDOWN, FALSE, 2); + move_to_field(pcard, pcard->current.controler, pcard->current.controler, LOCATION_SZONE, POS_FACEDOWN, FALSE, RETURN_TRAP_MONSTER_TO_SZONE); raise_single_event(pcard, 0, EVENT_SSET, reason_effect, 0, reason_player, 0, 0); ssets.insert(pcard); } @@ -5316,7 +5316,7 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in case 1: { if(returns.ivalue[0] == -1) { lua_pop(pduel->lua->current_state, 3); - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); core.limit_tuner = 0; return TRUE; } @@ -5352,12 +5352,12 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in } case 3: { card* tuner = core.limit_tuner; - effect* ptuner = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); - if(ptuner && ptuner->is_flag(EFFECT_FLAG_SPSUM_PARAM)) { - if(ptuner->s_range && ptuner->s_range > min) - min = ptuner->s_range; - if(ptuner->o_range && ptuner->o_range < max) - max = ptuner->o_range; + effect* tuner_limit = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); + if(tuner_limit && tuner_limit->is_flag(EFFECT_FLAG_SPSUM_PARAM)) { + if(tuner_limit->s_range && tuner_limit->s_range > min) + min = tuner_limit->s_range; + if(tuner_limit->o_range && tuner_limit->o_range < max) + max = tuner_limit->o_range; core.units.begin()->arg2 = min + (max << 16); } int32 mzone_limit = get_mzone_limit(playerid, playerid, LOCATION_REASON_TOFIELD); @@ -5398,10 +5398,10 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in case 4: { card* tuner = core.limit_tuner; int32 location = LOCATION_MZONE; - effect* ptuner = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); - if(ptuner) { - if(ptuner->value) - location = ptuner->value; + effect* tuner_limit = tuner->is_affected_by_effect(EFFECT_TUNER_MATERIAL_LIMIT); + if(tuner_limit) { + if(tuner_limit->value) + location = tuner_limit->value; } effect* pcheck = tuner->is_affected_by_effect(EFFECT_SYNCHRO_CHECK); core.must_select_cards.clear(); @@ -5427,14 +5427,14 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in for(auto& pm : mg->container) { if(pm == tuner || pm == smat || must_list.find(pm) != must_list.end() || !pm->is_can_be_synchro_material(pcard, tuner)) continue; - if(ptuner) { - if(ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit) { + if(tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(pm, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) continue; } - if(ptuner->value && !(pm->current.location & location)) + if(tuner_limit->value && !(pm->current.location & location)) continue; } if(pcheck) @@ -5448,14 +5448,14 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in } } else { card_set cv; - get_synchro_material(playerid, &cv, ptuner); + get_synchro_material(playerid, &cv, tuner_limit); for(auto& pm : cv) { if(!pm || pm == tuner || pm == smat || must_list.find(pm) != must_list.end() || !pm->is_can_be_synchro_material(pcard, tuner)) continue; - if(ptuner && ptuner->target) { - pduel->lua->add_param(ptuner, PARAM_TYPE_EFFECT); + if(tuner_limit && tuner_limit->target) { + pduel->lua->add_param(tuner_limit, PARAM_TYPE_EFFECT); pduel->lua->add_param(pm, PARAM_TYPE_CARD); - if(!pduel->lua->get_function_value(ptuner->target, 2)) + if(!pduel->lua->get_function_value(tuner_limit->target, 2)) continue; } if(pcheck) @@ -5683,7 +5683,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc } case 1: { if(returns.ivalue[0] == -1) { - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); return TRUE; } int32 pv = 0; @@ -5850,7 +5850,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc } case 4: { if(returns.ivalue[0] == -1) { - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); return TRUE; } card* pcard = core.select_cards[returns.bvalue[1]]; @@ -5906,7 +5906,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc } case 6: { if(returns.ivalue[0] == -1) { - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); return TRUE; } group* pgroup = pduel->new_group(core.operated_set); @@ -5930,7 +5930,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc } case 8: { if(returns.ivalue[0] == -1) { - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); return TRUE; } int32 pv = 0; @@ -6036,7 +6036,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc } case 22: { if(returns.ivalue[0] == -1) { - pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP); + pduel->lua->add_param(nullptr, PARAM_TYPE_GROUP); return TRUE; } int32 pv = 0; diff --git a/processor.cpp b/processor.cpp index 22ab8cf7d..a39849062 100644 --- a/processor.cpp +++ b/processor.cpp @@ -758,7 +758,7 @@ int32 field::execute_cost(uint16 step, effect * triggering_effect, uint8 trigger core.reason_effect = triggering_effect; core.reason_player = triggering_player; uint32 count = (uint32)pduel->lua->params.size(); - uint32 yield_value = 0; + int32 yield_value = 0; int32 result = pduel->lua->call_coroutine(triggering_effect->cost, count, &yield_value, step); returns.ivalue[0] = yield_value; if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) { @@ -810,7 +810,7 @@ int32 field::execute_operation(uint16 step, effect * triggering_effect, uint8 tr core.reason_effect = triggering_effect; core.reason_player = triggering_player; uint32 count = (uint32)pduel->lua->params.size(); - uint32 yield_value = 0; + int32 yield_value = 0; int32 result = pduel->lua->call_coroutine(triggering_effect->operation, count, &yield_value, step); returns.ivalue[0] = yield_value; if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) { @@ -867,7 +867,7 @@ int32 field::execute_target(uint16 step, effect * triggering_effect, uint8 trigg core.reason_effect = triggering_effect; core.reason_player = triggering_player; uint32 count = (uint32)pduel->lua->params.size(); - uint32 yield_value = 0; + int32 yield_value = 0; int32 result = pduel->lua->call_coroutine(triggering_effect->target, count, &yield_value, step); returns.ivalue[0] = yield_value; if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) { diff --git a/sort.h b/sort.h new file mode 100644 index 000000000..48ca01dac --- /dev/null +++ b/sort.h @@ -0,0 +1,10 @@ +#ifndef SORT_H_ +#define SORT_H_ + +class card; + +struct card_sort { + bool operator()(card* const& c1, card* const& c2) const; +}; + +#endif /* SORT_H_ */