diff --git a/README.md b/README.md index 59dced0f5..0afcf745f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ These functions create the game itself and then manipulate it. - `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);` +- `void start_duel(intptr_t pduel, uint32 options);` Start the duel. - `void end_duel(intptr_t pduel);` @@ -60,7 +60,7 @@ Get all cards in some location. - `void set_responseb(intptr_t pduel, byte* buf);` -- `int32 preload_script(intptr_t pduel, const char* script, int32 len);` +- `int32 preload_script(intptr_t pduel, const char* script_name);` # Lua functions diff --git a/card.cpp b/card.cpp index 52ebd32cd..d5ba136a5 100644 --- a/card.cpp +++ b/card.cpp @@ -1104,21 +1104,18 @@ uint32 card::get_attribute() { if(temp.attribute != UINT32_MAX) // prevent recursion, return the former value return temp.attribute; effect_set effects; - int32 attribute = data.attribute; + auto attribute = data.attribute; temp.attribute = data.attribute; filter_effect(EFFECT_ADD_ATTRIBUTE, &effects, FALSE); - filter_effect(EFFECT_REMOVE_ATTRIBUTE, &effects); + filter_effect(EFFECT_REMOVE_ATTRIBUTE, &effects, FALSE); + filter_effect(EFFECT_CHANGE_ATTRIBUTE, &effects); for (int32 i = 0; i < effects.size(); ++i) { if (effects[i]->code == EFFECT_ADD_ATTRIBUTE) attribute |= effects[i]->get_value(this); - else + else if (effects[i]->code == EFFECT_REMOVE_ATTRIBUTE) attribute &= ~(effects[i]->get_value(this)); - temp.attribute = attribute; - } - effects.clear(); - filter_effect(EFFECT_CHANGE_ATTRIBUTE, &effects); - for (int32 i = 0; i < effects.size(); ++i) { - attribute = effects[i]->get_value(this); + else if (effects[i]->code == EFFECT_CHANGE_ATTRIBUTE) + attribute = effects[i]->get_value(this); temp.attribute = attribute; } temp.attribute = UINT32_MAX; @@ -1174,21 +1171,18 @@ uint32 card::get_race() { if(temp.race != UINT32_MAX) // prevent recursion, return the former value return temp.race; effect_set effects; - int32 race = data.race; + auto race = data.race; temp.race = data.race; filter_effect(EFFECT_ADD_RACE, &effects, FALSE); - filter_effect(EFFECT_REMOVE_RACE, &effects); + filter_effect(EFFECT_REMOVE_RACE, &effects, FALSE); + filter_effect(EFFECT_CHANGE_RACE, &effects); for (int32 i = 0; i < effects.size(); ++i) { if (effects[i]->code == EFFECT_ADD_RACE) race |= effects[i]->get_value(this); - else + else if (effects[i]->code == EFFECT_REMOVE_RACE) race &= ~(effects[i]->get_value(this)); - temp.race = race; - } - effects.clear(); - filter_effect(EFFECT_CHANGE_RACE, &effects); - for (int32 i = 0; i < effects.size(); ++i) { - race = effects[i]->get_value(this); + else if (effects[i]->code == EFFECT_CHANGE_RACE) + race = effects[i]->get_value(this); temp.race = race; } temp.race = UINT32_MAX; @@ -2064,7 +2058,7 @@ int32 card::replace_effect(uint32 code, uint32 reset, int32 count) { for(auto i = indexer.begin(); i != indexer.end();) { auto rm = i++; effect* peffect = rm->first; - auto it = rm->second; + auto& it = rm->second; if (peffect->is_flag(EFFECT_FLAG_INITIAL | EFFECT_FLAG_COPY_INHERIT)) remove_effect(peffect, it); } @@ -2168,7 +2162,7 @@ void card::reset(uint32 id, uint32 reset_type) { for (auto i = indexer.begin(); i != indexer.end();) { auto rm = i++; effect* peffect = rm->first; - auto it = rm->second; + auto& it = rm->second; if (peffect->reset(id, reset_type)) remove_effect(peffect, it); } @@ -2526,7 +2520,7 @@ void card::set_special_summon_status(effect* peffect) { } card* pcard = peffect->get_handler(); auto cait = pduel->game_field->core.current_chain.rbegin(); - if(!(peffect->type & 0x7f0) || (pcard->is_has_relation(*cait) && !(pcard->get_type() & TYPE_TRAPMONSTER))) { + if(!(peffect->type & EFFECT_TYPES_CHAIN_LINK) || (pcard->is_has_relation(*cait) && !(pcard->get_type() & TYPE_TRAPMONSTER))) { spsummon.code = pcard->get_code(); spsummon.code2 = pcard->get_another_code(); spsummon.type = pcard->get_type(); @@ -2726,8 +2720,8 @@ void card::filter_disable_related_cards() { // return value: // -2 = this has a EFFECT_LIMIT_SUMMON_PROC, 0 available // -1 = this has a EFFECT_LIMIT_SUMMON_PROC, at least 1 available -// 0 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon ia not available -// 1 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon ia available +// 0 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon is not available +// 1 = no EFFECT_LIMIT_SUMMON_PROC, and ordinary summon is available int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute, uint32 zone) { effect_set eset; filter_effect(EFFECT_LIMIT_SUMMON_PROC, &eset); @@ -2947,33 +2941,32 @@ void card::filter_spsummon_procedure_g(uint8 playerid, effect_set* peset) { } // find an effect with code which affects this effect* card::is_affected_by_effect(int32 code) { - effect* peffect = nullptr; auto rg = single_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect))) return peffect; } for (auto& pcard : equiping_cards) { rg = pcard->equip_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && is_affect_by_effect(peffect)) return peffect; } } for (auto& pcard : effect_target_owner) { rg = pcard->target_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && peffect->is_target(this) && is_affect_by_effect(peffect)) return peffect; } } for (auto& pcard : xyz_materials) { rg = pcard->xmaterial_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->type & EFFECT_TYPE_FIELD) continue; if (peffect->is_available() && is_affect_by_effect(peffect)) @@ -2981,8 +2974,8 @@ effect* card::is_affected_by_effect(int32 code) { } } rg = pduel->game_field->effects.aura_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (!peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_target(this) && peffect->is_available() && is_affect_by_effect(peffect)) return peffect; @@ -2990,34 +2983,33 @@ effect* card::is_affected_by_effect(int32 code) { return nullptr; } effect* card::is_affected_by_effect(int32 code, card* target) { - effect* peffect = nullptr; auto rg = single_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect)) - && peffect->get_value(target)) + && peffect->get_value(target)) return peffect; } for (auto& pcard : equiping_cards) { rg = pcard->equip_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && is_affect_by_effect(peffect) && peffect->get_value(target)) return peffect; } } for (auto& pcard : effect_target_owner) { rg = pcard->target_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->is_available() && peffect->is_target(this) && is_affect_by_effect(peffect) && peffect->get_value(target)) return peffect; } } for (auto& pcard : xyz_materials) { rg = pcard->xmaterial_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (peffect->type & EFFECT_TYPE_FIELD) continue; if (peffect->is_available() && is_affect_by_effect(peffect) && peffect->get_value(target)) @@ -3025,10 +3017,10 @@ effect* card::is_affected_by_effect(int32 code, card* target) { } } rg = pduel->game_field->effects.aura_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; + for (auto it = rg.first; it != rg.second; ++it) { + effect* const& peffect = it->second; if (!peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available() - && peffect->is_target(this) && is_affect_by_effect(peffect) && peffect->get_value(target)) + && peffect->is_target(this) && is_affect_by_effect(peffect) && peffect->get_value(target)) return peffect; } return nullptr; @@ -3671,8 +3663,8 @@ int32 card::is_setable_szone(uint8 playerid, uint8 ignore_fd) { return TRUE; } int32 card::is_affect_by_effect(effect* reason_effect) { - if(is_status(STATUS_SUMMONING) && reason_effect->code != EFFECT_CANNOT_DISABLE_SUMMON && reason_effect->code != EFFECT_CANNOT_DISABLE_SPSUMMON) - return FALSE; + if (is_status(STATUS_SUMMONING)) + return reason_effect && (reason_effect->code == EFFECT_CANNOT_DISABLE_SUMMON || reason_effect->code == EFFECT_CANNOT_DISABLE_SPSUMMON); if(!reason_effect || reason_effect->is_flag(EFFECT_FLAG_IGNORE_IMMUNE)) return TRUE; if(reason_effect->is_immuned(this)) diff --git a/card.h b/card.h index 1aff307c7..4954bb7ae 100644 --- a/card.h +++ b/card.h @@ -26,6 +26,8 @@ struct chain; using card_set = std::set; using card_vector = std::vector; +using effect_container = std::multimap; +using effect_indexer = std::unordered_map; struct card_state { uint32 code{ 0 }; @@ -116,8 +118,6 @@ class card { return std::hash()(v.second); } }; - using effect_container = std::multimap; - using effect_indexer = std::unordered_map; using effect_relation = std::unordered_set, effect_relation_hash>; using relation_map = std::unordered_map; using counter_map = std::map; diff --git a/common.h b/common.h index 5b67630b1..58fd7ea8f 100644 --- a/common.h +++ b/common.h @@ -114,6 +114,7 @@ typedef signed char int8; #define TYPES_EXTRA_DECK (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_LINK) //Attributes +#define ATTRIBUTES_COUNT 7 #define ATTRIBUTE_ALL 0x7f // #define ATTRIBUTE_EARTH 0x01 // #define ATTRIBUTE_WATER 0x02 // diff --git a/duel.cpp b/duel.cpp index 2b967d072..8687f30fd 100644 --- a/duel.cpp +++ b/duel.cpp @@ -104,7 +104,7 @@ int32 duel::read_buffer(byte* buf) { } void duel::release_script_group() { for(auto& pgroup : sgroups) { - if(pgroup->is_readonly == 0) { + if(pgroup->is_readonly == GTYPE_DEFAULT) { lua->unregister_group(pgroup); groups.erase(pgroup); delete pgroup; diff --git a/effect.cpp b/effect.cpp index 7552381a1..616a10d91 100644 --- a/effect.cpp +++ b/effect.cpp @@ -12,6 +12,10 @@ #include "interpreter.h" bool effect_sort_id(const effect* e1, const effect* e2) { + int32 is_single1 = e1->is_initial_single(); + int32 is_single2 = e2->is_initial_single(); + if (is_single1 != is_single2) + return is_single1 > is_single2; return e1->id < e2->id; } // return: code is an event reserved for EFFECT_TYPE_CONTINUOUS or not @@ -30,17 +34,17 @@ effect::effect(duel* pd) { pduel = pd; label.reserve(4); } -int32 effect::is_disable_related() { +int32 effect::is_disable_related() const { if (code == EFFECT_IMMUNE_EFFECT || code == EFFECT_DISABLE || code == EFFECT_CANNOT_DISABLE || code == EFFECT_FORBIDDEN) return TRUE; return FALSE; } -int32 effect::is_self_destroy_related() { +int32 effect::is_self_destroy_related() const { if(code == EFFECT_UNIQUE_CHECK || code == EFFECT_SELF_DESTROY || code == EFFECT_SELF_TOGRAVE) return TRUE; return FALSE; } -int32 effect::is_can_be_forbidden() { +int32 effect::is_can_be_forbidden() const { if (is_flag(EFFECT_FLAG_CANNOT_DISABLE) && !is_flag(EFFECT_FLAG_CANNOT_NEGATE)) return FALSE; return TRUE; @@ -612,9 +616,12 @@ int32 effect::is_chainable(uint8 tp) { } return TRUE; } -int32 effect::is_hand_trigger() { +int32 effect::is_hand_trigger() const { return (range & LOCATION_HAND) && (type & EFFECT_TYPE_TRIGGER_O) && get_code_type() != CODE_PHASE; } +int32 effect::is_initial_single() const { + return (type & EFFECT_TYPE_SINGLE) && is_flag(EFFECT_FLAG_SINGLE_RANGE) && is_flag(EFFECT_FLAG_INITIAL); +} //return: this can be reset by reset_level or not //RESET_DISABLE is valid only when owner == handler int32 effect::reset(uint32 reset_level, uint32 reset_type) { @@ -802,7 +809,7 @@ card* effect::get_owner() const { return handler->overlay_target; return owner; } -uint8 effect::get_owner_player() { +uint8 effect::get_owner_player() const { if(effect_owner != PLAYER_NONE) return effect_owner; return get_owner()->current.controler; @@ -814,17 +821,17 @@ card* effect::get_handler() const { return handler->overlay_target; return handler; } -uint8 effect::get_handler_player() { +uint8 effect::get_handler_player() const { if(is_flag(EFFECT_FLAG_FIELD_ONLY)) return effect_owner; return get_handler()->current.controler; } -int32 effect::in_range(card* pcard) { +int32 effect::in_range(card* pcard) const { if(type & EFFECT_TYPE_XMATERIAL) return handler->overlay_target ? TRUE : FALSE; return pcard->current.is_location(range); } -int32 effect::in_range(const chain& ch) { +int32 effect::in_range(const chain& ch) const { if(type & EFFECT_TYPE_XMATERIAL) return handler->overlay_target ? TRUE : FALSE; return range & ch.triggering_location; @@ -841,7 +848,7 @@ void effect::set_active_type() { active_type &= ~TYPE_TRAP; } uint32 effect::get_active_type(uint8 uselast) { - if(type & 0x7f0) { + if(type & EFFECT_TYPES_CHAIN_LINK) { if(active_type && uselast) return active_type; else if((type & EFFECT_TYPE_ACTIVATE) && (get_handler()->data.type & TYPE_PENDULUM)) diff --git a/effect.h b/effect.h index d6129e408..fed91e100 100644 --- a/effect.h +++ b/effect.h @@ -36,7 +36,7 @@ class effect { uint32 code{ 0 }; uint32 flag[2]{}; uint32 id{ 0 }; - uint16 type{ 0 }; + uint32 type{ 0 }; uint16 copy_id{ 0 }; uint16 range{ 0 }; uint16 s_range{ 0 }; @@ -67,9 +67,9 @@ class effect { explicit effect(duel* pd); ~effect() = default; - int32 is_disable_related(); - int32 is_self_destroy_related(); - int32 is_can_be_forbidden(); + int32 is_disable_related() const; + int32 is_self_destroy_related() const; + int32 is_can_be_forbidden() const; int32 is_available(int32 neglect_disabled = FALSE); int32 limit_counter_is_available(); int32 is_single_ready(); @@ -87,7 +87,8 @@ class effect { int32 is_player_effect_target(card* pcard); int32 is_immuned(card* pcard); int32 is_chainable(uint8 tp); - int32 is_hand_trigger(); + int32 is_hand_trigger() const; + int32 is_initial_single() const; int32 reset(uint32 reset_level, uint32 reset_type); void dec_count(uint8 playerid = PLAYER_NONE); void recharge(); @@ -103,11 +104,11 @@ class effect { int32 get_speed(); effect* clone(); card* get_owner() const; - uint8 get_owner_player(); + uint8 get_owner_player() const; card* get_handler() const; - uint8 get_handler_player(); - int32 in_range(card* pcard); - int32 in_range(const chain& ch); + uint8 get_handler_player() const; + int32 in_range(card* pcard) const; + int32 in_range(const chain& ch) const; void set_activate_location(); void set_active_type(); uint32 get_active_type(uint8 uselast = TRUE); @@ -171,7 +172,8 @@ class effect { #define EFFECT_TYPE_GRANT 0x2000 // #define EFFECT_TYPE_TARGET 0x4000 // -#define EFFECT_TYPES_TRIGGER_LIKE (EFFECT_TYPE_ACTIVATE | EFFECT_TYPE_TRIGGER_O | EFFECT_TYPE_TRIGGER_F | EFFECT_TYPE_QUICK_O | EFFECT_TYPE_QUICK_F) +constexpr uint32 EFFECT_TYPES_TRIGGER_LIKE = EFFECT_TYPE_ACTIVATE | EFFECT_TYPE_TRIGGER_O | EFFECT_TYPE_TRIGGER_F | EFFECT_TYPE_QUICK_O | EFFECT_TYPE_QUICK_F; +constexpr uint32 EFFECT_TYPES_CHAIN_LINK = EFFECT_TYPES_TRIGGER_LIKE | EFFECT_TYPE_FLIP | EFFECT_TYPE_IGNITION; //========== Flags ========== enum effect_flag : uint32 { diff --git a/effectset.h b/effectset.h index 5dd2a72da..3ef15a74f 100644 --- a/effectset.h +++ b/effectset.h @@ -16,6 +16,7 @@ class effect; bool effect_sort_id(const effect* e1, const effect* e2); +// std::array struct effect_set { void add_item(effect* peffect) { if (count >= 64) diff --git a/field.cpp b/field.cpp index 0ac36c89f..a62b367b2 100644 --- a/field.cpp +++ b/field.cpp @@ -192,7 +192,7 @@ void field::add_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence refresh_player_info(playerid); } void field::remove_card(card* pcard) { - if (pcard->current.controler == PLAYER_NONE || pcard->current.location == 0) + if (!check_playerid(pcard->current.controler) || pcard->current.location == 0) return; uint8 playerid = pcard->current.controler; switch (pcard->current.location) { @@ -1371,7 +1371,7 @@ void field::filter_affected_cards(effect* peffect, card_set* cset) { || peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET | EFFECT_FLAG_SPSUM_PARAM)) return; uint8 self = peffect->get_handler_player(); - if(self == PLAYER_NONE) + if (!check_playerid(self)) return; std::vector cvec; uint16 range = peffect->s_range; @@ -1404,11 +1404,11 @@ void field::filter_inrange_cards(effect* peffect, card_set* cset) { if(peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET | EFFECT_FLAG_SPSUM_PARAM)) return; uint8 self = peffect->get_handler_player(); - if(self == PLAYER_NONE) + if (!check_playerid(self)) return; uint16 range = peffect->s_range; std::vector cvec; - for(uint32 p = 0; p < 2; ++p) { + for(int32 p = 0; p < 2; ++p) { if(range & LOCATION_MZONE) cvec.push_back(&player[self].list_mzone); if(range & LOCATION_SZONE) @@ -1428,7 +1428,7 @@ void field::filter_inrange_cards(effect* peffect, card_set* cset) { } for(auto& cvit : cvec) { for(auto& pcard : *cvit) { - if(pcard && peffect->is_fit_target_function(pcard)) + if (pcard && (!(pcard->current.location & LOCATION_ONFIELD) || !pcard->is_treated_as_not_on_field()) && peffect->is_fit_target_function(pcard)) cset->insert(pcard); } } @@ -2144,7 +2144,7 @@ void field::add_unique_card(card* pcard) { } void field::remove_unique_card(card* pcard) { uint8 con = pcard->current.controler; - if(con == PLAYER_NONE) + if (!check_playerid(con)) return; if(pcard->unique_pos[0]) core.unique_cards[con].erase(pcard); diff --git a/field.h b/field.h index 2a849f881..242396325 100644 --- a/field.h +++ b/field.h @@ -33,6 +33,8 @@ class duel; class group; class effect; +using effect_vector = std::vector; + bool check_playerid(int32 playerid); struct tevent { @@ -100,8 +102,6 @@ struct player_info { card_vector tag_list_extra; }; struct field_effect { - using effect_container = std::multimap; - using effect_indexer = std::unordered_map; using oath_effects = std::unordered_map; using effect_collection = std::unordered_set; using gain_effects = std::unordered_map; @@ -171,7 +171,6 @@ union return_value { int64 lvalue[SIZE_LVALUE]; }; struct processor { - using effect_vector = std::vector; using option_vector = std::vector; using card_list = std::list; using event_list = std::list; @@ -364,8 +363,6 @@ struct processor { }; class field { public: - using effect_container = std::multimap; - using effect_vector = std::vector; using card_list = std::list; using event_list = std::list; using chain_list = std::list; diff --git a/group.h b/group.h index 7fbf794b8..4e3356a2f 100644 --- a/group.h +++ b/group.h @@ -18,13 +18,17 @@ class duel; using card_set = std::set; +constexpr int GTYPE_DEFAULT = 0; +constexpr int GTYPE_READ_ONLY = 1; +constexpr int GTYPE_KEEP_ALIVE = 2; + class group { public: duel* pduel; card_set container; card_set::iterator it; int32 ref_handle{ 0 }; - uint32 is_readonly{ 0 }; + uint32 is_readonly{ GTYPE_DEFAULT }; bool is_iterator_dirty{ true }; bool has_card(card* c) { diff --git a/interpreter.cpp b/interpreter.cpp index 1caee1129..19b5eaf67 100644 --- a/interpreter.cpp +++ b/interpreter.cpp @@ -125,7 +125,7 @@ void interpreter::unregister_group(group *pgroup) { pgroup->ref_handle = 0; } int32 interpreter::load_script(const char* script_name) { - int32 len = 0; + int len = 0; byte* buffer = ::read_script(script_name, &len); if (!buffer) return OPERATION_FAIL; diff --git a/libduel.cpp b/libduel.cpp index 33e2fb0a4..0212595e0 100644 --- a/libduel.cpp +++ b/libduel.cpp @@ -358,7 +358,7 @@ int32 scriptlib::duel_synchro_summon(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 4); group* pgroup = *(group**) lua_touserdata(L, 4); mg = pduel->new_group(pgroup->container); - mg->is_readonly = 1; + mg->is_readonly = GTYPE_READ_ONLY; } } int32 minc = 0; @@ -399,7 +399,7 @@ int32 scriptlib::duel_xyz_summon(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 3); group* pgroup = *(group**)lua_touserdata(L, 3); materials = pduel->new_group(pgroup->container); - materials->is_readonly = 1; + materials->is_readonly = GTYPE_READ_ONLY; } int32 minc = 0; if(lua_gettop(L) >= 4) @@ -439,7 +439,7 @@ int32 scriptlib::duel_link_summon(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 3); group* pgroup = *(group**)lua_touserdata(L, 3); materials = pduel->new_group(pgroup->container); - materials->is_readonly = 1; + materials->is_readonly = GTYPE_READ_ONLY; } if(lua_gettop(L) >= 4) { if(!lua_isnil(L, 4)) { @@ -3058,7 +3058,7 @@ int32 scriptlib::duel_select_target(lua_State *L) { return 0; if(!ch->target_cards) { ch->target_cards = pduel->new_group(); - ch->target_cards->is_readonly = 1; + ch->target_cards->is_readonly = GTYPE_READ_ONLY; } group* tg = ch->target_cards; effect* peffect = ch->triggering_effect; @@ -3115,10 +3115,10 @@ int32 scriptlib::duel_check_must_material(lua_State *L) { pduel = interpreter::get_duel_info(L); if(mgroup) { pgroup = pduel->new_group(mgroup->container); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; } else if(mcard) { pgroup = pduel->new_group(mcard); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; } else pgroup = 0; uint32 limit = (uint32)lua_tointeger(L, 3); @@ -3413,7 +3413,7 @@ int32 scriptlib::duel_set_target_card(lua_State *L) { return 0; if(!ch->target_cards) { ch->target_cards = pduel->new_group(); - ch->target_cards->is_readonly = 1; + ch->target_cards->is_readonly = GTYPE_READ_ONLY; } group* targets = ch->target_cards; effect* peffect = ch->triggering_effect; @@ -3504,10 +3504,10 @@ int32 scriptlib::duel_set_operation_info(lua_State *L) { return 0; if(pgroup) { pg = pduel->new_group(pgroup->container); - pg->is_readonly = 1; + pg->is_readonly = GTYPE_READ_ONLY; } else if(pcard) { pg = pduel->new_group(pcard); - pg->is_readonly = 1; + pg->is_readonly = GTYPE_READ_ONLY; } else pg = nullptr; optarget opt; diff --git a/libeffect.cpp b/libeffect.cpp index a59398f76..f723d690b 100644 --- a/libeffect.cpp +++ b/libeffect.cpp @@ -147,7 +147,7 @@ int32 scriptlib::effect_set_type(lua_State *L) { check_param(L, PARAM_TYPE_EFFECT, 1); effect* peffect = *(effect**) lua_touserdata(L, 1); uint32 v = (uint32)lua_tointeger(L, 2); - if (v & 0x0ff0) + if (v & (EFFECT_TYPES_CHAIN_LINK | EFFECT_TYPE_CONTINUOUS)) v |= EFFECT_TYPE_ACTIONS; else v &= ~EFFECT_TYPE_ACTIONS; @@ -518,7 +518,7 @@ int32 scriptlib::effect_is_activated(lua_State *L) { check_param_count(L, 1); check_param(L, PARAM_TYPE_EFFECT, 1); effect* peffect = *(effect**) lua_touserdata(L, 1); - lua_pushboolean(L, (peffect->type & 0x7f0)); + lua_pushboolean(L, (peffect->type & EFFECT_TYPES_CHAIN_LINK)); return 1; } int32 scriptlib::effect_is_cost_checked(lua_State *L) { diff --git a/libgroup.cpp b/libgroup.cpp index 453ebea69..6f4d31153 100644 --- a/libgroup.cpp +++ b/libgroup.cpp @@ -44,10 +44,10 @@ int32 scriptlib::group_delete(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 1); duel* pduel = interpreter::get_duel_info(L); group* pgroup = *(group**) lua_touserdata(L, 1); - if(pgroup->is_readonly != 2) + if(pgroup->is_readonly != GTYPE_KEEP_ALIVE) return 0; pgroup->is_iterator_dirty = true; - pgroup->is_readonly = 0; + pgroup->is_readonly = GTYPE_DEFAULT; pduel->sgroups.insert(pgroup); return 0; } @@ -56,9 +56,9 @@ int32 scriptlib::group_keep_alive(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 1); duel* pduel = interpreter::get_duel_info(L); group* pgroup = *(group**) lua_touserdata(L, 1); - if(pgroup->is_readonly == 1) + if(pgroup->is_readonly == GTYPE_READ_ONLY) return 0; - pgroup->is_readonly = 2; + pgroup->is_readonly = GTYPE_KEEP_ALIVE; pduel->sgroups.erase(pgroup); return 0; } @@ -66,7 +66,7 @@ int32 scriptlib::group_clear(lua_State *L) { check_param_count(L, 1); check_param(L, PARAM_TYPE_GROUP, 1); group* pgroup = *(group**) lua_touserdata(L, 1); - if (pgroup->is_readonly != 1) { + if (pgroup->is_readonly != GTYPE_READ_ONLY) { pgroup->is_iterator_dirty = true; pgroup->container.clear(); } @@ -78,7 +78,7 @@ int32 scriptlib::group_add_card(lua_State *L) { check_param(L, PARAM_TYPE_CARD, 2); group* pgroup = *(group**) lua_touserdata(L, 1); card* pcard = *(card**) lua_touserdata(L, 2); - if (pgroup->is_readonly != 1) { + if (pgroup->is_readonly != GTYPE_READ_ONLY) { pgroup->is_iterator_dirty = true; pgroup->container.insert(pcard); } @@ -90,7 +90,7 @@ int32 scriptlib::group_remove_card(lua_State *L) { check_param(L, PARAM_TYPE_CARD, 2); group* pgroup = *(group**) lua_touserdata(L, 1); card* pcard = *(card**) lua_touserdata(L, 2); - if (pgroup->is_readonly != 1) { + if (pgroup->is_readonly != GTYPE_READ_ONLY) { pgroup->is_iterator_dirty = true; pgroup->container.erase(pcard); } @@ -672,7 +672,7 @@ int32 scriptlib::group_remove(lua_State *L) { group* pgroup = *(group**) lua_touserdata(L, 1); duel* pduel = pgroup->pduel; uint32 extraargs = lua_gettop(L) - 3; - if(pgroup->is_readonly == 1) + if(pgroup->is_readonly == GTYPE_READ_ONLY) return 0; pgroup->is_iterator_dirty = true; for (auto cit = pgroup->container.begin(); cit != pgroup->container.end();) { @@ -690,7 +690,7 @@ int32 scriptlib::group_merge(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 2); group* pgroup = *(group**) lua_touserdata(L, 1); group* mgroup = *(group**) lua_touserdata(L, 2); - if(pgroup->is_readonly == 1) + if(pgroup->is_readonly == GTYPE_READ_ONLY) return 0; pgroup->is_iterator_dirty = true; pgroup->container.insert(mgroup->container.begin(), mgroup->container.end()); @@ -702,7 +702,7 @@ int32 scriptlib::group_sub(lua_State *L) { check_param(L, PARAM_TYPE_GROUP, 2); group* pgroup = *(group**) lua_touserdata(L, 1); group* sgroup = *(group**) lua_touserdata(L, 2); - if(pgroup->is_readonly == 1) + if(pgroup->is_readonly == GTYPE_READ_ONLY) return 0; pgroup->is_iterator_dirty = true; for (auto& pcard : sgroup->container) { diff --git a/ocgapi.cpp b/ocgapi.cpp index 834f98366..e079fe2f6 100644 --- a/ocgapi.cpp +++ b/ocgapi.cpp @@ -44,12 +44,12 @@ byte* default_script_reader(const char* script_name, int* slen) { FILE *fp; fp = std::fopen(script_name, "rb"); if (!fp) - return 0; - int len = (int)fread(buffer, 1, sizeof(buffer), fp); + return nullptr; + size_t len = std::fread(buffer, 1, sizeof buffer, fp); std::fclose(fp); - if(len >= sizeof(buffer)) - return 0; - *slen = len; + if (len >= sizeof buffer) + return nullptr; + *slen = (int)len; return buffer; } uint32 default_card_reader(uint32 code, card_data* data) { @@ -347,6 +347,6 @@ extern "C" DECL_DLLEXPORT void set_responsei(intptr_t pduel, int32 value) { extern "C" DECL_DLLEXPORT void set_responseb(intptr_t pduel, byte* buf) { ((duel*)pduel)->set_responseb(buf); } -extern "C" DECL_DLLEXPORT int32 preload_script(intptr_t pduel, const char* script, int32 len) { - return ((duel*)pduel)->lua->load_script(script); +extern "C" DECL_DLLEXPORT int32 preload_script(intptr_t pduel, const char* script_name) { + return ((duel*)pduel)->lua->load_script(script_name); } diff --git a/ocgapi.h b/ocgapi.h index db2302890..6d58eafd3 100644 --- a/ocgapi.h +++ b/ocgapi.h @@ -53,7 +53,7 @@ extern "C" DECL_DLLEXPORT int32 query_field_card(intptr_t pduel, uint8 playerid, extern "C" DECL_DLLEXPORT int32 query_field_info(intptr_t pduel, byte* buf); extern "C" DECL_DLLEXPORT void set_responsei(intptr_t pduel, int32 value); extern "C" DECL_DLLEXPORT void set_responseb(intptr_t pduel, byte* buf); -extern "C" DECL_DLLEXPORT int32 preload_script(intptr_t pduel, const char* script, int32 len); +extern "C" DECL_DLLEXPORT int32 preload_script(intptr_t pduel, const char* script_name); byte* default_script_reader(const char* script_name, int* len); uint32 default_card_reader(uint32 code, card_data* data); uint32 default_message_handler(intptr_t pduel, uint32 msg_type); diff --git a/operations.cpp b/operations.cpp index b3a06b192..327b64c81 100644 --- a/operations.cpp +++ b/operations.cpp @@ -114,7 +114,7 @@ void field::remove_overlay_card(uint32 reason, card* pcard, uint32 rplayer, uint } void field::get_control(card_set* targets, effect* reason_effect, uint32 reason_player, uint32 playerid, uint32 reset_phase, uint32 reset_count, uint32 zone) { group* ng = pduel->new_group(*targets); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_GET_CONTROL, 0, reason_effect, ng, 0, (reason_player << 28) + (playerid << 24) + (reset_phase << 8) + reset_count, zone); } void field::get_control(card* target, effect* reason_effect, uint32 reason_player, uint32 playerid, uint32 reset_phase, uint32 reset_count, uint32 zone) { @@ -124,9 +124,9 @@ void field::get_control(card* target, effect* reason_effect, uint32 reason_playe } void field::swap_control(effect* reason_effect, uint32 reason_player, card_set* targets1, card_set* targets2, uint32 reset_phase, uint32 reset_count) { group* ng1 = pduel->new_group(*targets1); - ng1->is_readonly = 1; + ng1->is_readonly = GTYPE_READ_ONLY; group* ng2 = pduel->new_group(*targets2); - ng2->is_readonly = 1; + ng2->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_SWAP_CONTROL, 0, reason_effect, ng1, reason_player, reset_phase, reset_count, 0, ng2); } void field::swap_control(effect* reason_effect, uint32 reason_player, card* pcard1, card* pcard2, uint32 reset_phase, uint32 reset_count) { @@ -176,7 +176,7 @@ void field::special_summon(card_set* target, uint32 sumtype, uint32 sumplayer, u pcard->spsummon_param = (playerid << 24) + (nocheck << 16) + (nolimit << 8) + positions; } group* pgroup = pduel->new_group(*target); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_SPSUMMON, 0, core.reason_effect, pgroup, core.reason_player, zone); } void field::special_summon_step(card* target, uint32 sumtype, uint32 sumplayer, uint32 playerid, uint32 nocheck, uint32 nolimit, uint32 positions, uint32 zone) { @@ -196,7 +196,7 @@ void field::special_summon_step(card* target, uint32 sumtype, uint32 sumplayer, void field::special_summon_complete(effect* reason_effect, uint8 reason_player) { group* ng = pduel->new_group(); ng->container.swap(core.special_summoning); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; core.hint_timing[reason_player] |= TIMING_SPSUMMON; add_process(PROCESSOR_SPSUMMON, 1, reason_effect, ng, reason_player, 0); } @@ -228,7 +228,7 @@ void field::destroy(card_set* targets, effect* reason_effect, uint32 reason, uin ++cit; } group* ng = pduel->new_group(*targets); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_DESTROY, 0, reason_effect, ng, reason, reason_player); } void field::destroy(card* target, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 destination, uint32 sequence) { @@ -247,7 +247,7 @@ void field::release(card_set* targets, effect* reason_effect, uint32 reason, uin pcard->sendto_param.set(pcard->owner, POS_FACEUP, LOCATION_GRAVE); } group* ng = pduel->new_group(*targets); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_RELEASE, 0, reason_effect, ng, reason, reason_player); } void field::release(card* target, effect* reason_effect, uint32 reason, uint32 reason_player) { @@ -283,7 +283,7 @@ void field::send_to(card_set* targets, effect* reason_effect, uint32 reason, uin pcard->sendto_param.set(p, pos, destination, sequence); } group* ng = pduel->new_group(*targets); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_SENDTO, 0, reason_effect, ng, reason, reason_player, send_activating); } void field::send_to(card* target, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 destination, uint32 sequence, uint32 position, uint8 send_activating) { @@ -301,7 +301,7 @@ void field::move_to_field(card* target, uint32 move_player, uint32 playerid, uin } void field::change_position(card_set* targets, effect* reason_effect, uint32 reason_player, uint32 au, uint32 ad, uint32 du, uint32 dd, uint32 flag, uint32 enable) { group* ng = pduel->new_group(*targets); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; for(auto& pcard : *targets) { if(pcard->current.position == POS_FACEUP_ATTACK) pcard->position_param = au; @@ -317,7 +317,7 @@ void field::change_position(card_set* targets, effect* reason_effect, uint32 rea } void field::change_position(card* target, effect* reason_effect, uint32 reason_player, uint32 npos, uint32 flag, uint32 enable) { group* ng = pduel->new_group(target); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; target->position_param = npos; target->position_param |= flag; add_process(PROCESSOR_CHANGEPOS, 0, reason_effect, ng, reason_player, enable); @@ -1489,13 +1489,15 @@ int32 field::summon(uint16 step, uint8 sumplayer, card* target, effect* proc, ui core.select_effects.clear(); core.select_options.clear(); if(res > 0) { - core.select_effects.push_back(0); + core.select_effects.push_back(nullptr); core.select_options.push_back(1); } for(int32 i = 0; i < eset.size(); ++i) { core.select_effects.push_back(eset[i]); core.select_options.push_back(eset[i]->description); } + if (core.select_options.empty()) + return TRUE; if(core.select_options.size() == 1) returns.ivalue[0] = 0; else @@ -1865,6 +1867,16 @@ int32 field::summon(uint16 step, uint8 sumplayer, card* target, effect* proc, ui core.phase_action = TRUE; target->current.reason = REASON_SUMMON; target->summon_player = sumplayer; + if (core.current_chain.size() == 0) { + if (core.is_gemini_summoning) { + target->set_status(STATUS_SUMMONING, FALSE); + target->set_status(STATUS_FLIP_SUMMONING, TRUE); + } + else { + target->set_status(STATUS_SUMMONING, TRUE); + target->set_status(STATUS_FLIP_SUMMONING, FALSE); + } + } pduel->write_buffer8(MSG_SUMMONING); pduel->write_buffer32(target->data.code); pduel->write_buffer32(target->get_info_location()); @@ -1889,14 +1901,6 @@ int32 field::summon(uint16 step, uint8 sumplayer, card* target, effect* proc, ui return FALSE; } case 13: { - if (core.is_gemini_summoning) { - target->set_status(STATUS_SUMMONING, FALSE); - target->set_status(STATUS_FLIP_SUMMONING, TRUE); - } - else { - target->set_status(STATUS_SUMMONING, TRUE); - target->set_status(STATUS_FLIP_SUMMONING, FALSE); - } target->set_status(STATUS_SUMMON_DISABLED, FALSE); target->set_status(STATUS_FLIP_SUMMON_DISABLED, FALSE); raise_event(target, EVENT_SUMMON, proc, 0, sumplayer, sumplayer, 0); @@ -2860,6 +2864,7 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin set_control(target, target->current.controler, 0, 0); core.phase_action = TRUE; target->current.reason_effect = core.units.begin()->peffect; + target->set_status(STATUS_SUMMONING, TRUE); pduel->write_buffer8(MSG_SPSUMMONING); pduel->write_buffer32(target->data.code); pduel->write_buffer32(target->get_info_location()); @@ -2897,7 +2902,6 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin return FALSE; } case 10: { - target->set_status(STATUS_SUMMONING, TRUE); target->set_status(STATUS_SUMMON_DISABLED, FALSE); raise_event(target, EVENT_SPSUMMON, core.units.begin()->peffect, 0, sumplayer, sumplayer, 0); process_instant_event(); @@ -3070,13 +3074,14 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin } card* pcard = *pgroup->it; ++pgroup->it; + set_control(pcard, pcard->current.controler, 0, 0); + pcard->set_status(STATUS_SUMMONING, TRUE); pduel->write_buffer8(MSG_SPSUMMONING); pduel->write_buffer32(pcard->data.code); pduel->write_buffer8(pcard->current.controler); pduel->write_buffer8(pcard->current.location); pduel->write_buffer8(pcard->current.sequence); pduel->write_buffer8(pcard->current.position); - set_control(pcard, pcard->current.controler, 0, 0); if(pgroup->it != pgroup->container.end()) core.units.begin()->step = 22; return FALSE; @@ -3085,7 +3090,6 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin group* pgroup = core.units.begin()->ptarget; card_set cset; for(auto& pcard : pgroup->container) { - pcard->set_status(STATUS_SUMMONING, TRUE); if(!pcard->is_affected_by_effect(EFFECT_CANNOT_DISABLE_SPSUMMON)) { cset.insert(pcard); } @@ -3623,7 +3627,7 @@ int32 field::destroy(uint16 step, group * targets, effect * reason_effect, uint3 } case 4: { group* sendtargets = pduel->new_group(targets->container); - sendtargets->is_readonly = 1; + sendtargets->is_readonly = GTYPE_READ_ONLY; for(auto& pcard : sendtargets->container) { pcard->set_status(STATUS_DESTROY_CONFIRMED, FALSE); uint32 dest = pcard->sendto_param.location; @@ -3851,7 +3855,7 @@ int32 field::release(uint16 step, group * targets, effect * reason_effect, uint3 } case 3: { group* sendtargets = pduel->new_group(targets->container); - sendtargets->is_readonly = 1; + sendtargets->is_readonly = GTYPE_READ_ONLY; operation_replace(EFFECT_SEND_REPLACE, 5, sendtargets); add_process(PROCESSOR_SENDTO, 1, reason_effect, sendtargets, reason | REASON_RELEASE, reason_player); return FALSE; @@ -4915,7 +4919,7 @@ int32 field::change_position(uint16 step, group * targets, effect * reason_effec flips.insert(pcard); } if(enable) { - if(!reason_effect || !(reason_effect->type & 0x7f0) || pcard->current.location != LOCATION_MZONE) + if(!reason_effect || !(reason_effect->type & EFFECT_TYPES_CHAIN_LINK) || pcard->current.location != LOCATION_MZONE) pcard->enable_field_effect(true); else core.delayed_enable_set.insert(pcard); diff --git a/premake/lua.lua b/premake/lua.lua index d64c5370e..c6de89ae8 100644 --- a/premake/lua.lua +++ b/premake/lua.lua @@ -10,6 +10,9 @@ project "lua" filter "not action:vs*" buildoptions { "-x c++" } + filter "configurations:Debug" + defines { "LUA_USE_APICHECK" } + filter "system:bsd" defines { "LUA_USE_POSIX" } diff --git a/processor.cpp b/processor.cpp index 2ff811f94..ac8a40407 100644 --- a/processor.cpp +++ b/processor.cpp @@ -894,7 +894,7 @@ void field::raise_event(card* event_card, uint32 event_code, effect* reason_effe new_event.trigger_card = 0; if (event_card) { group* pgroup = pduel->new_group(event_card); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; new_event.event_cards = pgroup; } else new_event.event_cards = 0; @@ -911,7 +911,7 @@ void field::raise_event(card_set* event_cards, uint32 event_code, effect* reason new_event.trigger_card = 0; if (event_cards) { group* pgroup = pduel->new_group(*event_cards); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; new_event.event_cards = pgroup; } else new_event.event_cards = 0; @@ -928,7 +928,7 @@ void field::raise_single_event(card* trigger_card, card_set* event_cards, uint32 new_event.trigger_card = trigger_card; if (event_cards) { group* pgroup = pduel->new_group(*event_cards); - pgroup->is_readonly = 1; + pgroup->is_readonly = GTYPE_READ_ONLY; new_event.event_cards = pgroup; } else new_event.event_cards = 0; @@ -3086,7 +3086,7 @@ int32 field::process_battle_command(uint16 step) { if(des.size()) { group* ng = pduel->new_group(); ng->container.swap(des); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_DESTROY, 10, 0, ng, REASON_BATTLE, PLAYER_NONE); core.units.begin()->ptarget = ng; } @@ -5009,7 +5009,7 @@ int32 field::adjust_step(uint16 step) { core.re_adjust = TRUE; group* ng = pduel->new_group(); ng->container.swap(pos_adjust); - ng->is_readonly = 1; + ng->is_readonly = GTYPE_READ_ONLY; add_process(PROCESSOR_CHANGEPOS, 0, 0, ng, PLAYER_NONE, TRUE); } return FALSE;