From 53568604f766446b7fb3cef9c749ca1464a49f3c Mon Sep 17 00:00:00 2001 From: salix5 Date: Sat, 26 Oct 2024 19:19:06 +0800 Subject: [PATCH 01/10] add EFFECT_FLAG_COPY --- card.cpp | 20 +++++++++++++++++--- card.h | 2 ++ effect.h | 6 ++++-- libduel.cpp | 2 +- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/card.cpp b/card.cpp index da0afccc7..8d1f6057b 100644 --- a/card.cpp +++ b/card.cpp @@ -1768,8 +1768,8 @@ int32 card::add_effect(effect* peffect) { if (peffect->type & EFFECT_TYPES_TRIGGER_LIKE && is_continuous_event(peffect->code)) return 0; // the trigger effect in phase is "once per turn" by default - if (peffect->get_code_type() == CODE_PHASE && peffect->code & (PHASE_DRAW | PHASE_STANDBY | PHASE_END) && peffect->type & (EFFECT_TYPE_TRIGGER_O | EFFECT_TYPE_TRIGGER_F) - && !peffect->is_flag(EFFECT_FLAG_COUNT_LIMIT)) { + if (peffect->get_code_type() == CODE_PHASE && peffect->code & (PHASE_DRAW | PHASE_STANDBY | PHASE_END) + && peffect->type & (EFFECT_TYPE_TRIGGER_O | EFFECT_TYPE_TRIGGER_F) && !peffect->is_flag(EFFECT_FLAG_COUNT_LIMIT)) { peffect->flag[0] |= EFFECT_FLAG_COUNT_LIMIT; peffect->count_limit = 1; peffect->count_limit_max = 1; @@ -1872,8 +1872,10 @@ int32 card::add_effect(effect* peffect) { return 0; peffect->id = pduel->game_field->infos.field_id++; peffect->card_type = data.type; - if(get_status(STATUS_INITIALIZING)) + if (get_status(STATUS_INITIALIZING)) peffect->flag[0] |= EFFECT_FLAG_INITIAL; + else if (get_status(STATUS_COPYING_EFFECT)) + peffect->flag[0] |= EFFECT_FLAG_COPY; if (get_status(STATUS_COPYING_EFFECT)) { peffect->copy_id = pduel->game_field->infos.copy_id; peffect->reset_flag |= pduel->game_field->core.copy_reset; @@ -1882,6 +1884,10 @@ int32 card::add_effect(effect* peffect) { effect* reason_effect = pduel->game_field->core.reason_effect; indexer.emplace(peffect, eit); peffect->handler = this; + if (peffect->is_flag(EFFECT_FLAG_INITIAL)) + initial_effect.insert(peffect); + else if (peffect->is_flag(EFFECT_FLAG_COPY)) + owning_effect.insert(peffect); if((peffect->type & EFFECT_TYPE_FIELD)) { if(peffect->in_range(this) || current.controler != PLAYER_NONE && peffect->is_hand_trigger()) pduel->game_field->add_effect(peffect); @@ -1959,6 +1965,10 @@ effect_indexer::iterator card::remove_effect(effect* peffect) { } } auto ret = indexer.erase(index); + if (peffect->is_flag(EFFECT_FLAG_INITIAL)) + initial_effect.erase(peffect); + else if (peffect->is_flag(EFFECT_FLAG_COPY)) + owning_effect.erase(peffect); if(peffect->is_flag(EFFECT_FLAG_OATH)) pduel->game_field->effects.oath.erase(peffect); if(peffect->reset_flag & RESET_PHASE) @@ -1999,6 +2009,8 @@ int32 card::copy_effect(uint32 code, uint32 reset, int32 count) { ::read_card(code, &cdata); if(cdata.type & TYPE_NORMAL) return -1; + if (!reset) + reset = RESETS_STANDARD; set_status(STATUS_COPYING_EFFECT, TRUE); auto cr = pduel->game_field->core.copy_reset; auto crc = pduel->game_field->core.copy_reset_count; @@ -2035,6 +2047,8 @@ int32 card::replace_effect(uint32 code, uint32 reset, int32 count) { ::read_card(code, &cdata); if(cdata.type & TYPE_NORMAL) return -1; + if (!reset) + reset = RESETS_STANDARD; if(is_status(STATUS_EFFECT_REPLACED)) set_status(STATUS_EFFECT_REPLACED, FALSE); for(auto it = indexer.begin(); it != indexer.end();) { diff --git a/card.h b/card.h index fbf3cde1d..c785395e7 100644 --- a/card.h +++ b/card.h @@ -210,6 +210,8 @@ class card { effect_indexer indexer; effect_relation relate_effect; effect_set_v immune_effect; + effect_collection initial_effect; + effect_collection owning_effect; explicit card(duel* pd); ~card() = default; diff --git a/effect.h b/effect.h index dc5074207..c845b5985 100644 --- a/effect.h +++ b/effect.h @@ -156,6 +156,8 @@ class effect { #define RESET_OVERLAY 0x04000000 #define RESET_MSCHANGE 0x08000000 +constexpr uint32 RESETS_STANDARD = RESET_TOFIELD | RESET_LEAVE | RESET_TODECK | RESET_TOHAND | RESET_TEMP_REMOVE | RESET_REMOVE | RESET_TOGRAVE | RESET_TURN_SET; + //========== Types ========== #define EFFECT_TYPE_SINGLE 0x0001 // #define EFFECT_TYPE_FIELD 0x0002 // @@ -191,7 +193,7 @@ enum effect_flag : uint32 { EFFECT_FLAG_CANNOT_DISABLE = 0x0400, EFFECT_FLAG_PLAYER_TARGET = 0x0800, EFFECT_FLAG_BOTH_SIDE = 0x1000, -// EFFECT_FLAG_COPY_INHERIT = 0x2000, + EFFECT_FLAG_COPY = 0x2000, EFFECT_FLAG_DAMAGE_STEP = 0x4000, EFFECT_FLAG_DAMAGE_CAL = 0x8000, EFFECT_FLAG_DELAY = 0x10000, @@ -220,7 +222,7 @@ enum effect_flag2 : uint32 { constexpr effect_flag operator|(effect_flag flag1, effect_flag flag2) { return static_cast(static_cast(flag1) | static_cast(flag2)); } -constexpr uint32 INTERNAL_FLAGS = EFFECT_FLAG_INITIAL | EFFECT_FLAG_FUNC_VALUE | EFFECT_FLAG_COUNT_LIMIT | EFFECT_FLAG_FIELD_ONLY | EFFECT_FLAG_ABSOLUTE_TARGET; +constexpr uint32 INTERNAL_FLAGS = EFFECT_FLAG_INITIAL | EFFECT_FLAG_COPY | EFFECT_FLAG_FUNC_VALUE | EFFECT_FLAG_COUNT_LIMIT | EFFECT_FLAG_FIELD_ONLY | EFFECT_FLAG_ABSOLUTE_TARGET; //========== Codes ========== #define EFFECT_IMMUNE_EFFECT 1 // #define EFFECT_DISABLE 2 // diff --git a/libduel.cpp b/libduel.cpp index 70552964c..538c8aebe 100644 --- a/libduel.cpp +++ b/libduel.cpp @@ -4792,7 +4792,7 @@ int32 scriptlib::duel_majestic_copy(lua_State *L) { ceffect->flag[0] &= ~EFFECT_FLAG_INITIAL; ceffect->effect_owner = PLAYER_NONE; ceffect->reset_flag = RESET_EVENT + 0x1fe0000 + RESET_PHASE + PHASE_END + RESET_SELF_TURN + RESET_OPPO_TURN; - ceffect->reset_count = 0x1; + ceffect->reset_count = 1; ceffect->recharge(); if(ceffect->type & EFFECT_TYPE_TRIGGER_F) { ceffect->type &= ~EFFECT_TYPE_TRIGGER_F; From aeffc3950bfcac9fa04e955d2885312f369b2bc1 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 00:04:34 +0800 Subject: [PATCH 02/10] card: add filter_effect_container() avoid unnecessary copy --- card.cpp | 141 +++++++++++++++++++++++-------------------------------- card.h | 9 ++-- 2 files changed, 64 insertions(+), 86 deletions(-) diff --git a/card.cpp b/card.cpp index 8d1f6057b..d893eab10 100644 --- a/card.cpp +++ b/card.cpp @@ -2584,95 +2584,70 @@ void card::set_special_summon_status(effect* peffect) { spsummon.reason_player = cait->triggering_player; } } -void card::filter_effect(int32 code, effect_set* eset, uint8 sort) { - effect* peffect; - auto rg = single_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; - if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect))) - eset->add_item(peffect); - } - for (auto& pcard : equiping_cards) { - rg = pcard->equip_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; - if (peffect->is_available() && is_affect_by_effect(peffect)) - eset->add_item(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; - if(peffect->is_available() && peffect->is_target(this) && is_affect_by_effect(peffect)) - eset->add_item(peffect); - } - } - for (auto& pcard : xyz_materials) { - rg = pcard->xmaterial_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; - if (peffect->type & EFFECT_TYPE_FIELD) - continue; - if (peffect->is_available() && is_affect_by_effect(peffect)) - eset->add_item(peffect); - } - } - rg = pduel->game_field->effects.aura_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - peffect = rg.first->second; - if (!peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available() - && peffect->is_target(this) && is_affect_by_effect(peffect)) - eset->add_item(peffect); - } +auto default_single_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || c->is_affect_by_effect(peffect)); +}; +auto default_equip_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_available() && c->is_affect_by_effect(peffect); +}; +auto default_target_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_available() && peffect->is_target(c) && c->is_affect_by_effect(peffect); +}; +auto default_xmaterial_filter = [](card* c, effect* peffect) -> bool { + return !(peffect->type & EFFECT_TYPE_FIELD) && peffect->is_available() && c->is_affect_by_effect(peffect); +}; +auto default_aura_filter = [](card* c, effect* peffect) -> bool { + return !peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available() && peffect->is_target(c) && c->is_affect_by_effect(peffect); +}; +auto accept_filter = [](card* c, effect* peffect) -> bool { + return true; +}; +void card::filter_effect_container(const effect_container& container, uint32 code, effect_filter f, effect_set& eset) { + auto rg = container.equal_range(code); + for (auto it = rg.first; it != rg.second; ++it) { + if (f(this, it->second)) + eset.add_item(it->second); + } +} +void card::filter_effect(uint32 code, effect_set* eset, uint8 sort) { + filter_effect_container(single_effect, code, default_single_filter, *eset); + for (const auto& pcard : equiping_cards) + filter_effect_container(pcard->equip_effect, code, default_equip_filter, *eset); + for (const auto& pcard : effect_target_owner) + filter_effect_container(pcard->target_effect, code, default_target_filter, *eset); + for (const auto& pcard : xyz_materials) + filter_effect_container(pcard->xmaterial_effect, code, default_xmaterial_filter, *eset); + filter_effect_container(pduel->game_field->effects.aura_effect, code, default_aura_filter, *eset); if(sort) eset->sort(); } -void card::filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort) { - auto rg = single_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) - eset->add_item(rg.first->second); - for (auto& pcard : equiping_cards) { - rg = pcard->equip_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) - eset->add_item(rg.first->second); - } - for(auto& pcard : effect_target_owner) { - rg = pcard->target_effect.equal_range(code); - for(; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if(peffect->is_target(pcard)) - eset->add_item(peffect); - } - } - for (auto& pcard : xyz_materials) { - rg = pcard->xmaterial_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if (peffect->type & EFFECT_TYPE_FIELD) - continue; - eset->add_item(peffect); - } - } +void card::filter_single_continuous_effect(uint32 code, effect_set* eset, uint8 sort) { + filter_effect_container(single_effect, code, accept_filter, *eset); + for (const auto& pcard : equiping_cards) + filter_effect_container(pcard->equip_effect, code, accept_filter, *eset); + auto target_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_target(c); + }; + for (const auto& pcard : effect_target_owner) + filter_effect_container(pcard->target_effect, code, target_filter, *eset); + auto xmaterial_filter = [](card* c, effect* peffect) -> bool { + return !(peffect->type & EFFECT_TYPE_FIELD); + }; + for (const auto& pcard : xyz_materials) + filter_effect_container(pcard->xmaterial_effect, code, xmaterial_filter, *eset); if(sort) eset->sort(); } -void card::filter_self_effect(int32 code, effect_set* eset, uint8 sort) { - auto rg = single_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if(peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)) - eset->add_item(rg.first->second); - } - for (auto& pcard : xyz_materials) { - rg = pcard->xmaterial_effect.equal_range(code); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if (peffect->type & EFFECT_TYPE_FIELD) - continue; - eset->add_item(peffect); - } - } +void card::filter_self_effect(uint32 code, effect_set* eset, uint8 sort) { + auto single_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE); + }; + filter_effect_container(single_effect, code, single_filter, *eset); + auto xmaterial_filter = [](card* c, effect* peffect) -> bool { + return !(peffect->type & EFFECT_TYPE_FIELD); + }; + for (const auto& pcard : xyz_materials) + filter_effect_container(pcard->xmaterial_effect, code, xmaterial_filter, *eset); if (sort) eset->sort(); } diff --git a/card.h b/card.h index c785395e7..fe779e4ca 100644 --- a/card.h +++ b/card.h @@ -30,6 +30,8 @@ using effect_container = std::multimap; using effect_indexer = std::unordered_map; using effect_collection = std::unordered_set; +using effect_filter = bool(*)(card* self, effect* peffect); + struct card_state { uint32 code{ 0 }; uint32 code2{ 0 }; @@ -322,9 +324,10 @@ class card { void clear_card_target(); void set_special_summon_status(effect* peffect); - void filter_effect(int32 code, effect_set* eset, uint8 sort = TRUE); - void filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort = TRUE); - void filter_self_effect(int32 code, effect_set* eset, uint8 sort = TRUE); + void filter_effect_container(const effect_container& container, uint32 code, effect_filter f, effect_set& eset); + void filter_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); + void filter_single_continuous_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); + void filter_self_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); void filter_immune_effect(); void filter_disable_related_cards(); int32 filter_summon_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute, uint32 zone); From 690391b0bffa2438107100cd69b8ab7919d702bf Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 08:49:46 +0800 Subject: [PATCH 03/10] card: add find_effect_container() --- card.cpp | 60 +++++++++++++++++++++++--------------------------------- card.h | 4 +++- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/card.cpp b/card.cpp index d893eab10..b228f19ef 100644 --- a/card.cpp +++ b/card.cpp @@ -2935,47 +2935,37 @@ void card::filter_spsummon_procedure_g(uint8 playerid, effect_set* peset) { pduel->game_field->core.reason_player = op; } } -// find an effect with code which affects this -effect* card::is_affected_by_effect(int32 code) { - auto rg = single_effect.equal_range(code); +effect* card::find_effect(const effect_container& container, uint32 code, effect_filter f) { + auto rg = container.equal_range(code); 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 (auto it = rg.first; it != rg.second; ++it) { - effect* const& peffect = it->second; - if (peffect->is_available() && is_affect_by_effect(peffect)) - return peffect; - } + if (f(this, it->second)) + return it->second; } - for (auto& pcard : effect_target_owner) { - rg = pcard->target_effect.equal_range(code); - 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; - } + return nullptr; +} +// find an effect with code which affects this +effect* card::is_affected_by_effect(uint32 code) { + effect* peffect = find_effect(single_effect, code, default_single_filter); + if (peffect) + return peffect; + for (const auto& pcard : equiping_cards) { + peffect = find_effect(pcard->equip_effect, code, default_equip_filter); + if (peffect) + return peffect; } - for (auto& pcard : xyz_materials) { - rg = pcard->xmaterial_effect.equal_range(code); - 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)) - return peffect; - } + for (const auto& pcard : effect_target_owner) { + peffect = find_effect(pcard->target_effect, code, default_target_filter); + if (peffect) + return peffect; } - rg = pduel->game_field->effects.aura_effect.equal_range(code); - 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)) + for (const auto& pcard : xyz_materials) { + peffect = find_effect(pcard->xmaterial_effect, code, default_xmaterial_filter); + if (peffect) return peffect; } + peffect = find_effect(pduel->game_field->effects.aura_effect, code, default_aura_filter); + if (peffect) + return peffect; return nullptr; } effect* card::is_affected_by_effect(int32 code, card* target) { diff --git a/card.h b/card.h index fe779e4ca..e23b5043e 100644 --- a/card.h +++ b/card.h @@ -31,6 +31,7 @@ using effect_indexer = std::unordered_map; using effect_collection = std::unordered_set; using effect_filter = bool(*)(card* self, effect* peffect); +using effect_filter_target = bool(*)(card* self, effect* peffect, card* target); struct card_state { uint32 code{ 0 }; @@ -336,7 +337,8 @@ class card { int32 check_set_procedure(effect* proc, uint8 playerid, uint8 ignore_count, uint8 min_tribute, uint32 zone); void filter_spsummon_procedure(uint8 playerid, effect_set* eset, uint32 summon_type, material_info info = null_info); void filter_spsummon_procedure_g(uint8 playerid, effect_set* eset); - effect* is_affected_by_effect(int32 code); + effect* find_effect(const effect_container& container, uint32 code, effect_filter f); + effect* is_affected_by_effect(uint32 code); effect* is_affected_by_effect(int32 code, card* target); int32 fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material); void fusion_select(uint8 playerid, group* fusion_m, card* cg, uint32 chkf, uint8 not_material); From f26eab013078ab31e0720b9f3b2fa9eae006e107 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 10:31:38 +0800 Subject: [PATCH 04/10] card: add find_effect_with_target() --- card.cpp | 74 +++++++++++++++++++++++++++++--------------------------- card.h | 1 + 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/card.cpp b/card.cpp index b228f19ef..4f23cf6e0 100644 --- a/card.cpp +++ b/card.cpp @@ -2943,6 +2943,14 @@ effect* card::find_effect(const effect_container& container, uint32 code, effect } return nullptr; } +effect* card::find_effect_with_target(const effect_container& container, uint32 code, effect_filter_target f, card* target) { + auto rg = container.equal_range(code); + for (auto it = rg.first; it != rg.second; ++it) { + if (f(this, it->second, target)) + return it->second; + } + return nullptr; +} // find an effect with code which affects this effect* card::is_affected_by_effect(uint32 code) { effect* peffect = find_effect(single_effect, code, default_single_filter); @@ -2969,46 +2977,42 @@ effect* card::is_affected_by_effect(uint32 code) { return nullptr; } effect* card::is_affected_by_effect(int32 code, card* target) { - auto rg = single_effect.equal_range(code); - 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)) + auto single_filter = [](card* c, effect* peffect, card* target) -> bool { + return default_single_filter(c, peffect) && peffect->get_value(target); + }; + effect* peffect = find_effect_with_target(single_effect, code, single_filter, target); + if (peffect) + return peffect; + auto equip_filter = [](card* c, effect* peffect, card* target) -> bool { + return default_equip_filter(c, peffect) && peffect->get_value(target); + }; + for (const auto& pcard : equiping_cards) { + peffect = find_effect_with_target(pcard->equip_effect, code, equip_filter, target); + if (peffect) return peffect; } - for (auto& pcard : equiping_cards) { - rg = pcard->equip_effect.equal_range(code); - 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 (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 (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)) - return peffect; - } + auto target_filter = [](card* c, effect* peffect, card* target) -> bool { + return default_target_filter(c, peffect) && peffect->get_value(target); + }; + for (const auto& pcard : effect_target_owner) { + peffect = find_effect_with_target(pcard->target_effect, code, target_filter, target); + if (peffect) + return peffect; } - rg = pduel->game_field->effects.aura_effect.equal_range(code); - 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)) + auto xmaterial_filter = [](card* c, effect* peffect, card* target) -> bool { + return default_xmaterial_filter(c, peffect) && peffect->get_value(target); + }; + for (const auto& pcard : xyz_materials) { + peffect = find_effect_with_target(pcard->xmaterial_effect, code, xmaterial_filter, target); + if (peffect) return peffect; } + auto aura_filter = [](card* c, effect* peffect, card* target) -> bool { + return default_aura_filter(c, peffect) && peffect->get_value(target); + }; + peffect = find_effect_with_target(pduel->game_field->effects.aura_effect, code, aura_filter, target); + if (peffect) + return peffect; return nullptr; } int32 card::fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material) { diff --git a/card.h b/card.h index e23b5043e..ec12e85fb 100644 --- a/card.h +++ b/card.h @@ -338,6 +338,7 @@ class card { void filter_spsummon_procedure(uint8 playerid, effect_set* eset, uint32 summon_type, material_info info = null_info); void filter_spsummon_procedure_g(uint8 playerid, effect_set* eset); effect* find_effect(const effect_container& container, uint32 code, effect_filter f); + effect* find_effect_with_target(const effect_container& container, uint32 code, effect_filter_target f, card* target); effect* is_affected_by_effect(uint32 code); effect* is_affected_by_effect(int32 code, card* target); int32 fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material); From 80938363b64d676730000944f2487dda74b14aa8 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 11:41:36 +0800 Subject: [PATCH 05/10] use template --- card.cpp | 52 ++++++++++++++++------------------------------------ card.h | 3 ++- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/card.cpp b/card.cpp index 4f23cf6e0..90238bd31 100644 --- a/card.cpp +++ b/card.cpp @@ -2602,7 +2602,8 @@ auto default_aura_filter = [](card* c, effect* peffect) -> bool { auto accept_filter = [](card* c, effect* peffect) -> bool { return true; }; -void card::filter_effect_container(const effect_container& container, uint32 code, effect_filter f, effect_set& eset) { +template +void card::filter_effect_container(const effect_container& container, uint32 code, effect_filter f, T& eset) { auto rg = container.equal_range(code); for (auto it = rg.first; it != rg.second; ++it) { if (f(this, it->second)) @@ -2654,41 +2655,20 @@ void card::filter_self_effect(uint32 code, effect_set* eset, uint8 sort) { // refresh this->immune_effect void card::filter_immune_effect() { immune_effect.clear(); - auto rg = single_effect.equal_range(EFFECT_IMMUNE_EFFECT); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - immune_effect.add_item(peffect); - } - for (auto& pcard : equiping_cards) { - rg = pcard->equip_effect.equal_range(EFFECT_IMMUNE_EFFECT); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - immune_effect.add_item(peffect); - } - } - for (auto& pcard : effect_target_owner) { - rg = pcard->target_effect.equal_range(EFFECT_IMMUNE_EFFECT); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if(peffect->is_target(this)) - immune_effect.add_item(peffect); - } - } - for (auto& pcard : xyz_materials) { - rg = pcard->xmaterial_effect.equal_range(EFFECT_IMMUNE_EFFECT); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if (peffect->type & EFFECT_TYPE_FIELD) - continue; - immune_effect.add_item(peffect); - } - } - rg = pduel->game_field->effects.aura_effect.equal_range(EFFECT_IMMUNE_EFFECT); - for (; rg.first != rg.second; ++rg.first) { - effect* peffect = rg.first->second; - if (peffect->is_target(this)) - immune_effect.add_item(peffect); - } + filter_effect_container(single_effect, EFFECT_IMMUNE_EFFECT, accept_filter, immune_effect); + for (const auto& pcard : equiping_cards) + filter_effect_container(pcard->equip_effect, EFFECT_IMMUNE_EFFECT, accept_filter, immune_effect); + auto target_filter = [](card* c, effect* peffect) -> bool { + return peffect->is_target(c); + }; + for (const auto& pcard : effect_target_owner) + filter_effect_container(pcard->target_effect, EFFECT_IMMUNE_EFFECT, target_filter, immune_effect); + auto xmaterial_filter = [](card* c, effect* peffect) -> bool { + return !(peffect->type & EFFECT_TYPE_FIELD); + }; + for (const auto& pcard : xyz_materials) + filter_effect_container(pcard->xmaterial_effect, EFFECT_IMMUNE_EFFECT, xmaterial_filter, immune_effect); + filter_effect_container(pduel->game_field->effects.aura_effect, EFFECT_IMMUNE_EFFECT, target_filter, immune_effect); immune_effect.sort(); } // for all disable-related peffect of this, diff --git a/card.h b/card.h index ec12e85fb..297ab432b 100644 --- a/card.h +++ b/card.h @@ -325,7 +325,8 @@ class card { void clear_card_target(); void set_special_summon_status(effect* peffect); - void filter_effect_container(const effect_container& container, uint32 code, effect_filter f, effect_set& eset); + template + void filter_effect_container(const effect_container& container, uint32 code, effect_filter f, T& eset); void filter_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); void filter_single_continuous_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); void filter_self_effect(uint32 code, effect_set* eset, uint8 sort = TRUE); From b4ad918ff470df86d1beb89c52f1762238c89764 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 11:42:10 +0800 Subject: [PATCH 06/10] update effect_set --- effectset.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/effectset.h b/effectset.h index 3ef15a74f..90168db54 100644 --- a/effectset.h +++ b/effectset.h @@ -26,10 +26,6 @@ struct effect_set { void remove_item(int index) { if (index < 0 || index >= count) return; - if(index == count - 1) { - --count; - return; - } for(int i = index; i < count - 1; ++i) container[i] = container[i + 1]; --count; @@ -86,10 +82,7 @@ struct effect_set_v { return (int)container.size(); } void sort() { - int count = (int)container.size(); - if(count < 2) - return; - std::sort(container.begin(), container.begin() + count, effect_sort_id); + std::sort(container.begin(), container.end(), effect_sort_id); } effect* const& get_last() const { assert(container.size()); From ab3766ec780d6c3243d73707fcf2a65fd273e7e8 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 08:57:41 +0800 Subject: [PATCH 07/10] remove unused include --- effect.h | 2 -- field.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/effect.h b/effect.h index c845b5985..ad05c48a5 100644 --- a/effect.h +++ b/effect.h @@ -11,9 +11,7 @@ #include "common.h" #include "field.h" #include "effectset.h" -#include #include -#include class card; class duel; diff --git a/field.h b/field.h index ea8b424d8..0b80d6c1b 100644 --- a/field.h +++ b/field.h @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include From f1ea4aaed0992b568fdcfd8e11aed72cb16659b4 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 19:10:05 +0800 Subject: [PATCH 08/10] add Card.IsEffectCode, IsEffectCategory --- card.cpp | 11 +++++++++++ card.h | 2 ++ libcard.cpp | 24 ++++++++++++++++++++++++ scriptlib.h | 2 ++ 4 files changed, 39 insertions(+) diff --git a/card.cpp b/card.cpp index 90238bd31..607ec9f65 100644 --- a/card.cpp +++ b/card.cpp @@ -4157,3 +4157,14 @@ int32 card::is_can_be_link_material(card* scard) { return FALSE; return TRUE; } +int32 card::is_effect_property(const std::function& filter) { + for (const auto& peffect : initial_effect) { + if (filter(peffect)) + return TRUE; + } + for (const auto& peffect : owning_effect) { + if (filter(peffect)) + return TRUE; + } + return FALSE; +} diff --git a/card.h b/card.h index 297ab432b..9f0fbb3c4 100644 --- a/card.h +++ b/card.h @@ -17,6 +17,7 @@ #include #include #include +#include class card; class duel; @@ -401,6 +402,7 @@ class card { int32 is_can_be_ritual_material(card* scard); int32 is_can_be_xyz_material(card* scard); int32 is_can_be_link_material(card* scard); + int32 is_effect_property(const std::function& filter); }; //Summon Type in summon_info diff --git a/libcard.cpp b/libcard.cpp index 39a383258..4c0a45b45 100644 --- a/libcard.cpp +++ b/libcard.cpp @@ -1345,6 +1345,28 @@ int32 scriptlib::card_is_tuner(lua_State* L) { lua_pushboolean(L, pcard->is_tuner(scard)); return 1; } +int32 scriptlib::card_is_effect_code(lua_State* L) { + check_param_count(L, 2); + check_param(L, PARAM_TYPE_CARD, 1); + card* pcard = *(card**)lua_touserdata(L, 1); + uint32 code = (uint32)lua_tointeger(L, 2); + auto filter = [code](effect* peffect) -> bool { + return peffect->code == code; + }; + lua_pushboolean(L, pcard->is_effect_property(filter)); + return 1; +} +int32 scriptlib::card_is_effect_category(lua_State* L) { + check_param_count(L, 2); + check_param(L, PARAM_TYPE_CARD, 1); + card* pcard = *(card**)lua_touserdata(L, 1); + uint32 category = (uint32)lua_tointeger(L, 2); + auto filter = [category](effect* peffect) -> bool { + return peffect->category & category; + }; + lua_pushboolean(L, pcard->is_effect_property(filter)); + return 1; +} int32 scriptlib::card_set_status(lua_State *L) { check_param_count(L, 3); check_param(L, PARAM_TYPE_CARD, 1); @@ -3515,6 +3537,8 @@ static const struct luaL_Reg cardlib[] = { { "IsStatus", scriptlib::card_is_status }, { "IsNotTuner", scriptlib::card_is_not_tuner }, { "IsTuner", scriptlib::card_is_tuner }, + { "IsEffectCode", scriptlib::card_is_effect_code }, + { "IsEffectCategory", scriptlib::card_is_effect_category }, { "SetStatus", scriptlib::card_set_status }, { "IsDualState", scriptlib::card_is_dual_state }, { "EnableDualState", scriptlib::card_enable_dual_state }, diff --git a/scriptlib.h b/scriptlib.h index 9cfb2218c..cf0ba0018 100644 --- a/scriptlib.h +++ b/scriptlib.h @@ -143,6 +143,8 @@ class scriptlib { static int32 card_is_status(lua_State *L); static int32 card_is_not_tuner(lua_State *L); static int32 card_is_tuner(lua_State* L); + static int32 card_is_effect_code(lua_State* L); + static int32 card_is_effect_category(lua_State* L); static int32 card_set_status(lua_State *L); static int32 card_is_dual_state(lua_State *L); static int32 card_enable_dual_state(lua_State *L); From 870b781620d916093de96e192d82820d6871db62 Mon Sep 17 00:00:00 2001 From: salix5 Date: Sun, 27 Oct 2024 20:57:51 +0800 Subject: [PATCH 09/10] rename to Card.IsEffectProperty --- card.cpp | 16 +++++++++++++--- card.h | 4 ++-- libcard.cpp | 22 +++++++++------------- scriptlib.h | 4 ++-- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/card.cpp b/card.cpp index 607ec9f65..003fdf024 100644 --- a/card.cpp +++ b/card.cpp @@ -4157,13 +4157,23 @@ int32 card::is_can_be_link_material(card* scard) { return FALSE; return TRUE; } -int32 card::is_effect_property(const std::function& filter) { +int32 card::is_original_effect_property(int32 filter) { for (const auto& peffect : initial_effect) { - if (filter(peffect)) + pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); + if (pduel->lua->check_condition(filter, 1)) + return TRUE; + } + return FALSE; +} +int32 card::is_effect_property(int32 filter) { + for (const auto& peffect : initial_effect) { + pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); + if(pduel->lua->check_condition(filter, 1)) return TRUE; } for (const auto& peffect : owning_effect) { - if (filter(peffect)) + pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); + if (pduel->lua->check_condition(filter, 1)) return TRUE; } return FALSE; diff --git a/card.h b/card.h index 9f0fbb3c4..027ad2241 100644 --- a/card.h +++ b/card.h @@ -17,7 +17,6 @@ #include #include #include -#include class card; class duel; @@ -402,7 +401,8 @@ class card { int32 is_can_be_ritual_material(card* scard); int32 is_can_be_xyz_material(card* scard); int32 is_can_be_link_material(card* scard); - int32 is_effect_property(const std::function& filter); + int32 is_original_effect_property(int32 filter); + int32 is_effect_property(int32 filter); }; //Summon Type in summon_info diff --git a/libcard.cpp b/libcard.cpp index 4c0a45b45..59462375b 100644 --- a/libcard.cpp +++ b/libcard.cpp @@ -1345,25 +1345,21 @@ int32 scriptlib::card_is_tuner(lua_State* L) { lua_pushboolean(L, pcard->is_tuner(scard)); return 1; } -int32 scriptlib::card_is_effect_code(lua_State* L) { +int32 scriptlib::card_is_original_effect_property(lua_State* L) { check_param_count(L, 2); check_param(L, PARAM_TYPE_CARD, 1); + check_param(L, PARAM_TYPE_FUNCTION, 2); card* pcard = *(card**)lua_touserdata(L, 1); - uint32 code = (uint32)lua_tointeger(L, 2); - auto filter = [code](effect* peffect) -> bool { - return peffect->code == code; - }; - lua_pushboolean(L, pcard->is_effect_property(filter)); + int32 filter = interpreter::get_function_handle(L, 2); + lua_pushboolean(L, pcard->is_original_effect_property(filter)); return 1; } -int32 scriptlib::card_is_effect_category(lua_State* L) { +int32 scriptlib::card_is_effect_property(lua_State* L) { check_param_count(L, 2); check_param(L, PARAM_TYPE_CARD, 1); + check_param(L, PARAM_TYPE_FUNCTION, 2); card* pcard = *(card**)lua_touserdata(L, 1); - uint32 category = (uint32)lua_tointeger(L, 2); - auto filter = [category](effect* peffect) -> bool { - return peffect->category & category; - }; + int32 filter = interpreter::get_function_handle(L, 2); lua_pushboolean(L, pcard->is_effect_property(filter)); return 1; } @@ -3537,8 +3533,8 @@ static const struct luaL_Reg cardlib[] = { { "IsStatus", scriptlib::card_is_status }, { "IsNotTuner", scriptlib::card_is_not_tuner }, { "IsTuner", scriptlib::card_is_tuner }, - { "IsEffectCode", scriptlib::card_is_effect_code }, - { "IsEffectCategory", scriptlib::card_is_effect_category }, + { "IsOriginalEffectProperty", scriptlib::card_is_original_effect_property }, + { "IsEffectProperty", scriptlib::card_is_effect_property }, { "SetStatus", scriptlib::card_set_status }, { "IsDualState", scriptlib::card_is_dual_state }, { "EnableDualState", scriptlib::card_enable_dual_state }, diff --git a/scriptlib.h b/scriptlib.h index cf0ba0018..82db2e1a8 100644 --- a/scriptlib.h +++ b/scriptlib.h @@ -143,8 +143,8 @@ class scriptlib { static int32 card_is_status(lua_State *L); static int32 card_is_not_tuner(lua_State *L); static int32 card_is_tuner(lua_State* L); - static int32 card_is_effect_code(lua_State* L); - static int32 card_is_effect_category(lua_State* L); + static int32 card_is_original_effect_property(lua_State* L); + static int32 card_is_effect_property(lua_State* L); static int32 card_set_status(lua_State *L); static int32 card_is_dual_state(lua_State *L); static int32 card_enable_dual_state(lua_State *L); From a06a3f6774f2eafa24a472a78121bf0a8a685b4f Mon Sep 17 00:00:00 2001 From: salix5 Date: Sat, 2 Nov 2024 21:27:32 +0800 Subject: [PATCH 10/10] card: update is_effect_property --- card.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/card.cpp b/card.cpp index 003fdf024..294c62abc 100644 --- a/card.cpp +++ b/card.cpp @@ -4157,6 +4157,9 @@ int32 card::is_can_be_link_material(card* scard) { return FALSE; return TRUE; } +/** +* @param filter Lua function filter(e) +*/ int32 card::is_original_effect_property(int32 filter) { for (const auto& peffect : initial_effect) { pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); @@ -4165,13 +4168,20 @@ int32 card::is_original_effect_property(int32 filter) { } return FALSE; } +/** +* @param filter Lua function filter(e) +*/ int32 card::is_effect_property(int32 filter) { for (const auto& peffect : initial_effect) { + if (current.is_location(LOCATION_ONFIELD) && !peffect->in_range(this)) + continue; pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); if(pduel->lua->check_condition(filter, 1)) return TRUE; } for (const auto& peffect : owning_effect) { + if (current.is_location(LOCATION_ONFIELD) && !peffect->in_range(this)) + continue; pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT); if (pduel->lua->check_condition(filter, 1)) return TRUE;