From b579cda9adc48f42f279372ecb11e8bfac02d0cc Mon Sep 17 00:00:00 2001 From: salix5 Date: Fri, 25 Oct 2024 00:27:56 +0800 Subject: [PATCH 1/2] fix card::xyz_remove (#645) --- card.cpp | 11 ++++++----- field.cpp | 10 +++++++--- libduel.cpp | 4 ++-- operations.cpp | 8 +++----- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/card.cpp b/card.cpp index d5ba136a5..d678b0635 100644 --- a/card.cpp +++ b/card.cpp @@ -1570,12 +1570,11 @@ int32 card::get_old_union_count() { return count; } void card::xyz_overlay(card_set* materials) { - if(materials->size() == 0) + if(materials->empty()) return; card_set des, leave_grave, leave_deck; card_vector cv; - for(auto& pcard : *materials) - cv.push_back(pcard); + cv.assign(materials->begin(), materials->end()); std::sort(cv.begin(), cv.end(), card::card_operation_sort); if(pduel->game_field->core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) { int32 d0 = (int32)pduel->game_field->player[0].list_main.size() - 1, s0 = d0; @@ -1622,9 +1621,9 @@ void card::xyz_overlay(card_set* materials) { pduel->game_field->remove_unique_card(pcard); if(pcard->equiping_target) pcard->unequip(); + des.insert(pcard->equiping_cards.begin(), pcard->equiping_cards.end()); for(auto cit = pcard->equiping_cards.begin(); cit != pcard->equiping_cards.end();) { card* equipc = *cit++; - des.insert(equipc); equipc->unequip(); } pcard->clear_card_target(); @@ -1681,7 +1680,9 @@ void card::xyz_add(card* mat) { void card::xyz_remove(card* mat) { if(mat->overlay_target != this) return; - xyz_materials.erase(xyz_materials.begin() + mat->current.sequence); + if (std::find(xyz_materials.begin(), xyz_materials.end(), mat) == xyz_materials.end()) + return; + xyz_materials.erase(std::remove(xyz_materials.begin(), xyz_materials.end(), mat), xyz_materials.end()); mat->previous.controler = mat->current.controler; mat->previous.location = mat->current.location; mat->previous.sequence = mat->current.sequence; diff --git a/field.cpp b/field.cpp index a62b367b2..e60db1b39 100644 --- a/field.cpp +++ b/field.cpp @@ -1963,11 +1963,13 @@ void field::get_xyz_material(lua_State* L, card* scard, int32 findex, uint32 lv, } } void field::get_overlay_group(uint8 self, uint8 s, uint8 o, card_set* pset) { + if (!check_playerid(self)) + return; uint8 c = s; for(int32 p = 0; p < 2; ++p) { if(c) { for(auto& pcard : player[self].list_mzone) { - if(pcard && !pcard->get_status(STATUS_SUMMONING | STATUS_SPSUMMON_STEP) && pcard->xyz_materials.size()) + if(pcard && !pcard->is_treated_as_not_on_field() && pcard->xyz_materials.size()) pset->insert(pcard->xyz_materials.begin(), pcard->xyz_materials.end()); } } @@ -1976,12 +1978,14 @@ void field::get_overlay_group(uint8 self, uint8 s, uint8 o, card_set* pset) { } } int32 field::get_overlay_count(uint8 self, uint8 s, uint8 o) { + if (!check_playerid(self)) + return 0; uint8 c = s; int32 count = 0; for(int32 p = 0; p < 2; ++p) { if(c) { for(auto& pcard : player[self].list_mzone) { - if(pcard && !pcard->get_status(STATUS_SUMMONING | STATUS_SPSUMMON_STEP)) + if(pcard && !pcard->is_treated_as_not_on_field()) count += (int32)pcard->xyz_materials.size(); } } @@ -3283,7 +3287,7 @@ int32 field::is_player_can_remove_counter(uint8 playerid, card * pcard, uint8 s, return FALSE; } int32 field::is_player_can_remove_overlay_card(uint8 playerid, card * pcard, uint8 s, uint8 o, uint16 min, uint32 reason) { - if((pcard && pcard->xyz_materials.size() >= min) || (!pcard && get_overlay_count(playerid, s, o) >= min)) + if((pcard && (int32)pcard->xyz_materials.size() >= min) || (!pcard && get_overlay_count(playerid, s, o) >= min)) return TRUE; auto pr = effects.continuous_effect.equal_range(EFFECT_OVERLAY_REMOVE_REPLACE); tevent e; diff --git a/libduel.cpp b/libduel.cpp index 0212595e0..70552964c 100644 --- a/libduel.cpp +++ b/libduel.cpp @@ -1610,7 +1610,7 @@ int32 scriptlib::duel_shuffle_setcard(lua_State *L) { pduel->write_buffer8(MSG_SHUFFLE_SET_CARD); pduel->write_buffer8(loc); pduel->write_buffer8(ct); - for(uint32 i = 0; i < ct; ++i) { + for(int32 i = 0; i < ct; ++i) { card* pcard = ms[i]; pduel->write_buffer32(pcard->get_info_location()); if(loc == LOCATION_MZONE) @@ -1623,7 +1623,7 @@ int32 scriptlib::duel_shuffle_setcard(lua_State *L) { pduel->game_field->raise_event(&pgroup->container, EVENT_MOVE, pduel->game_field->core.reason_effect, 0, pduel->game_field->core.reason_player, tp, 0); pduel->game_field->process_single_event(); pduel->game_field->process_instant_event(); - for(uint32 i = 0; i < ct; ++i) { + for(int32 i = 0; i < ct; ++i) { if(ms[i]->xyz_materials.size()) pduel->write_buffer32(ms[i]->get_info_location()); else diff --git a/operations.cpp b/operations.cpp index 327b64c81..d1399a21f 100644 --- a/operations.cpp +++ b/operations.cpp @@ -784,7 +784,7 @@ int32 field::remove_overlay_card(uint16 step, uint32 reason, card* pcard, uint8 case 0: { core.select_options.clear(); core.select_effects.clear(); - if((pcard && pcard->xyz_materials.size() >= min) || (!pcard && get_overlay_count(rplayer, s, o) >= min)) { + if((pcard && (int32)pcard->xyz_materials.size() >= min) || (!pcard && get_overlay_count(rplayer, s, o) >= min)) { core.select_options.push_back(12); core.select_effects.push_back(0); } @@ -845,13 +845,11 @@ int32 field::remove_overlay_card(uint16 step, uint32 reason, card* pcard, uint8 } core.select_cards.clear(); if(pcard) { - for(auto& mcard : pcard->xyz_materials) - core.select_cards.push_back(mcard); + core.select_cards.assign(pcard->xyz_materials.begin(), pcard->xyz_materials.end()); } else { card_set cset; get_overlay_group(rplayer, s, o, &cset); - for(auto& xcard : cset) - core.select_cards.push_back(xcard); + core.select_cards.assign(cset.begin(), cset.end()); } pduel->write_buffer8(MSG_HINT); pduel->write_buffer8(HINT_SELECTMSG); From 7a9fd22de062b5c1f61e9d08bca7fdd2dfcb0046 Mon Sep 17 00:00:00 2001 From: salix5 Date: Fri, 25 Oct 2024 08:36:16 +0800 Subject: [PATCH 2/2] delete card target on RESET_COPY & remove EFFECT_FLAG_COPY_INHERIT (#644) * remove EFFECT_FLAG_COPY_INHERIT * delete card target on RESET_COPY * add effect_indexer::iterator remove_effect(effect* peffect) * minor fix * fix field::add_effect avoid duplicate entries like card::add_effect * reload script after removing all effects * update signature * always call field::remove_effect * fix field::adjust_grant_effect * avoid nested EFFECT_TYPE_GRANT --- card.cpp | 118 ++++++++++++++++++++++++++------------------------ card.h | 7 +-- effect.h | 3 +- field.cpp | 53 ++++++++++++++--------- field.h | 3 +- libcard.cpp | 1 - libeffect.cpp | 4 ++ processor.cpp | 2 +- 8 files changed, 106 insertions(+), 85 deletions(-) diff --git a/card.cpp b/card.cpp index d678b0635..da0afccc7 100644 --- a/card.cpp +++ b/card.cpp @@ -414,7 +414,7 @@ int32 card::get_infos(byte* buf, uint32 query_flag, int32 use_cache) { buffer_write(finalize, query_flag); return (int32)(p - buf); } -uint32 card::get_info_location() { +uint32 card::get_info_location() const { if(overlay_target) { uint32 c = overlay_target->current.controler; uint32 l = overlay_target->current.location | LOCATION_OVERLAY; @@ -1715,9 +1715,7 @@ void card::cancel_field_effect() { if (current.controler == PLAYER_NONE) return; for (auto& it : field_effect) { - if (it.second->in_range(this) || it.second->is_hand_trigger()) { - pduel->game_field->remove_effect(it.second); - } + pduel->game_field->remove_effect(it.second); } if(unique_code && (current.location & unique_location)) pduel->game_field->remove_unique_card(this); @@ -1882,12 +1880,6 @@ int32 card::add_effect(effect* peffect) { peffect->reset_count = pduel->game_field->core.copy_reset_count; } effect* reason_effect = pduel->game_field->core.reason_effect; - if(peffect->is_flag(EFFECT_FLAG_COPY_INHERIT) && reason_effect && reason_effect->copy_id) { - peffect->copy_id = reason_effect->copy_id; - peffect->reset_flag |= reason_effect->reset_flag; - if(peffect->reset_count > reason_effect->reset_count) - peffect->reset_count = reason_effect->reset_count; - } indexer.emplace(peffect, eit); peffect->handler = this; if((peffect->type & EFFECT_TYPE_FIELD)) { @@ -1927,13 +1919,11 @@ int32 card::add_effect(effect* peffect) { } return peffect->id; } -void card::remove_effect(effect* peffect) { - auto it = indexer.find(peffect); - if (it == indexer.end()) - return; - remove_effect(peffect, it->second); -} -void card::remove_effect(effect* peffect, effect_container::iterator it) { +effect_indexer::iterator card::remove_effect(effect* peffect) { + auto index = indexer.find(peffect); + if (index == indexer.end()) + return index; + auto& it = index->second; card_set check_target = { this }; if (peffect->type & EFFECT_TYPE_SINGLE) { single_effect.erase(it); @@ -1961,8 +1951,6 @@ void card::remove_effect(effect* peffect, effect_container::iterator it) { pduel->game_field->update_disable_check_list(peffect); } field_effect.erase(it); - if(peffect->in_range(this) || current.controler != PLAYER_NONE && peffect->is_hand_trigger()) - pduel->game_field->remove_effect(peffect); } if ((current.controler != PLAYER_NONE) && !get_status(STATUS_DISABLED | STATUS_FORBIDDEN) && !check_target.empty()) { if (peffect->is_disable_related()) { @@ -1970,16 +1958,7 @@ void card::remove_effect(effect* peffect, effect_container::iterator it) { pduel->game_field->add_to_disable_check_list(target); } } - if (peffect->is_flag(EFFECT_FLAG_INITIAL) && peffect->copy_id && is_status(STATUS_EFFECT_REPLACED)) { - set_status(STATUS_EFFECT_REPLACED, FALSE); - if (interpreter::is_load_script(data)) { - set_status(STATUS_INITIALIZING, TRUE); - pduel->lua->add_param(this, PARAM_TYPE_CARD); - pduel->lua->call_card_function(this, "initial_effect", 1, 0); - set_status(STATUS_INITIALIZING, FALSE); - } - } - indexer.erase(peffect); + auto ret = indexer.erase(index); if(peffect->is_flag(EFFECT_FLAG_OATH)) pduel->game_field->effects.oath.erase(peffect); if(peffect->reset_flag & RESET_PHASE) @@ -2011,7 +1990,9 @@ void card::remove_effect(effect* peffect, effect_container::iterator it) { unique_pos[0] = unique_pos[1] = 0; unique_code = 0; } + pduel->game_field->remove_effect(peffect); pduel->game_field->core.reseted_effects.insert(peffect); + return ret; } int32 card::copy_effect(uint32 code, uint32 reset, int32 count) { card_data cdata; @@ -2056,12 +2037,12 @@ int32 card::replace_effect(uint32 code, uint32 reset, int32 count) { return -1; if(is_status(STATUS_EFFECT_REPLACED)) set_status(STATUS_EFFECT_REPLACED, FALSE); - for(auto i = indexer.begin(); i != indexer.end();) { - auto rm = i++; - effect* peffect = rm->first; - auto& it = rm->second; - if (peffect->is_flag(EFFECT_FLAG_INITIAL | EFFECT_FLAG_COPY_INHERIT)) - remove_effect(peffect, it); + for(auto it = indexer.begin(); it != indexer.end();) { + effect* const& peffect = it->first; + if (peffect->is_flag(EFFECT_FLAG_INITIAL)) + it = remove_effect(peffect); + else + ++it; } auto cr = pduel->game_field->core.copy_reset; auto crc = pduel->game_field->core.copy_reset_count; @@ -2160,17 +2141,34 @@ 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; - if (peffect->reset(id, reset_type)) - remove_effect(peffect, it); + else if (reset_type == RESET_COPY) { + delete_card_target(TRUE); + effect_target_cards.clear(); + } + bool reload = false; + for (auto it = indexer.begin(); it != indexer.end();) { + effect* const& peffect = it->first; + if (peffect->reset(id, reset_type)) { + if (is_status(STATUS_EFFECT_REPLACED) && peffect->is_flag(EFFECT_FLAG_INITIAL) && peffect->copy_id) + reload = true; + it = remove_effect(peffect); + } + else + ++it; + } + if (reload) { + set_status(STATUS_EFFECT_REPLACED, FALSE); + if (interpreter::is_load_script(data)) { + set_status(STATUS_INITIALIZING, TRUE); + pduel->lua->add_param(this, PARAM_TYPE_CARD); + pduel->lua->call_card_function(this, "initial_effect", 1, 0); + set_status(STATUS_INITIALIZING, FALSE); + } } } void card::reset_effect_count() { for (auto& i : indexer) { - effect* peffect = i.first; + effect* const& peffect = i.first; if (peffect->is_flag(EFFECT_FLAG_COUNT_LIMIT)) peffect->recharge(); } @@ -2478,6 +2476,26 @@ void card::cancel_card_target(card* pcard) { pduel->write_buffer32(pcard->get_info_location()); } } +void card::delete_card_target(uint32 send_msg) { + for (auto& pcard : effect_target_cards) { + pcard->effect_target_owner.erase(this); + for (auto& it : target_effect) { + if (it.second->is_disable_related()) + pduel->game_field->add_to_disable_check_list(pcard); + } + for (auto it = pcard->single_effect.begin(); it != pcard->single_effect.end();) { + auto rm = it++; + effect* const& peffect = rm->second; + if ((peffect->owner == this) && peffect->is_flag(EFFECT_FLAG_OWNER_RELATE)) + pcard->remove_effect(peffect); + } + if (send_msg) { + pduel->write_buffer8(MSG_CANCEL_TARGET); + pduel->write_buffer32(get_info_location()); + pduel->write_buffer32(pcard->get_info_location()); + } + } +} void card::clear_card_target() { for(auto& pcard : effect_target_owner) { pcard->effect_target_cards.erase(this); @@ -2486,19 +2504,7 @@ void card::clear_card_target() { pduel->game_field->add_to_disable_check_list(this); } } - for(auto& pcard : effect_target_cards) { - pcard->effect_target_owner.erase(this); - for(auto& it : target_effect) { - if(it.second->is_disable_related()) - pduel->game_field->add_to_disable_check_list(pcard); - } - for(auto it = pcard->single_effect.begin(); it != pcard->single_effect.end();) { - auto rm = it++; - effect* peffect = rm->second; - if((peffect->owner == this) && peffect->is_flag(EFFECT_FLAG_OWNER_RELATE)) - pcard->remove_effect(peffect, rm); - } - } + delete_card_target(FALSE); effect_target_owner.clear(); effect_target_cards.clear(); } @@ -2703,7 +2709,7 @@ void card::filter_immune_effect() { // 4. Insert continuous target of this into it. void card::filter_disable_related_cards() { for (auto& it : indexer) { - effect* peffect = it.first; + effect* const& peffect = it.first; if (peffect->is_disable_related()) { if (peffect->type & EFFECT_TYPE_FIELD) pduel->game_field->update_disable_check_list(peffect); diff --git a/card.h b/card.h index 4954bb7ae..fbf3cde1d 100644 --- a/card.h +++ b/card.h @@ -28,6 +28,7 @@ using card_set = std::set; using card_vector = std::vector; using effect_container = std::multimap; using effect_indexer = std::unordered_map; +using effect_collection = std::unordered_set; struct card_state { uint32 code{ 0 }; @@ -216,7 +217,7 @@ class card { bool is_extra_deck_monster() const { return !!(data.type & TYPES_EXTRA_DECK); } int32 get_infos(byte* buf, uint32 query_flag, int32 use_cache = TRUE); - uint32 get_info_location(); + uint32 get_info_location() const; uint32 get_original_code() const; std::tuple get_original_code_rule() const; uint32 get_code(); @@ -286,8 +287,7 @@ class card { void cancel_field_effect(); void enable_field_effect(bool enabled); int32 add_effect(effect* peffect); - void remove_effect(effect* peffect); - void remove_effect(effect* peffect, effect_container::iterator it); + effect_indexer::iterator remove_effect(effect* peffect); int32 copy_effect(uint32 code, uint32 reset, int32 count); int32 replace_effect(uint32 code, uint32 reset, int32 count); void reset(uint32 id, uint32 reset_type); @@ -316,6 +316,7 @@ class card { void set_material(card_set* materials); void add_card_target(card* pcard); void cancel_card_target(card* pcard); + void delete_card_target(uint32 send_msg); void clear_card_target(); void set_special_summon_status(effect* peffect); diff --git a/effect.h b/effect.h index fed91e100..dc5074207 100644 --- a/effect.h +++ b/effect.h @@ -63,6 +63,7 @@ class effect { int32 operation{ 0 }; uint8 cost_checked{ FALSE }; effect_set required_handorset_effects; + LuaParamType object_type{ PARAM_TYPE_INT }; explicit effect(duel* pd); ~effect() = default; @@ -190,7 +191,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_INHERIT = 0x2000, EFFECT_FLAG_DAMAGE_STEP = 0x4000, EFFECT_FLAG_DAMAGE_CAL = 0x8000, EFFECT_FLAG_DELAY = 0x10000, diff --git a/field.cpp b/field.cpp index e60db1b39..9d191658c 100644 --- a/field.cpp +++ b/field.cpp @@ -1161,13 +1161,8 @@ void field::tag_swap(uint8 playerid) { pduel->write_buffer32(pcard->data.code | (pcard->is_position(POS_FACEUP) ? 0x80000000 : 0)); } void field::add_effect(effect* peffect, uint8 owner_player) { - if (!peffect->handler) { - peffect->flag[0] |= EFFECT_FLAG_FIELD_ONLY; - peffect->handler = peffect->owner; - peffect->effect_owner = owner_player; - peffect->id = infos.field_id++; - } - peffect->card_type = peffect->owner->data.type; + if (effects.indexer.find(peffect) != effects.indexer.end()) + return; effect_container::iterator it; if (!(peffect->type & EFFECT_TYPE_ACTIONS)) { it = effects.aura_effect.emplace(peffect->code, peffect); @@ -1178,9 +1173,9 @@ void field::add_effect(effect* peffect, uint8 owner_player) { } else { if (peffect->type & EFFECT_TYPE_IGNITION) it = effects.ignition_effect.emplace(peffect->code, peffect); - else if (peffect->type & EFFECT_TYPE_TRIGGER_O && peffect->type & EFFECT_TYPE_FIELD) + else if (peffect->type & EFFECT_TYPE_TRIGGER_O) it = effects.trigger_o_effect.emplace(peffect->code, peffect); - else if (peffect->type & EFFECT_TYPE_TRIGGER_F && peffect->type & EFFECT_TYPE_FIELD) + else if (peffect->type & EFFECT_TYPE_TRIGGER_F) it = effects.trigger_f_effect.emplace(peffect->code, peffect); else if (peffect->type & EFFECT_TYPE_QUICK_O) it = effects.quick_o_effect.emplace(peffect->code, peffect); @@ -1190,7 +1185,16 @@ void field::add_effect(effect* peffect, uint8 owner_player) { it = effects.activate_effect.emplace(peffect->code, peffect); else if (peffect->type & EFFECT_TYPE_CONTINUOUS) it = effects.continuous_effect.emplace(peffect->code, peffect); + else + return; } + if (!peffect->handler) { + peffect->flag[0] |= EFFECT_FLAG_FIELD_ONLY; + peffect->handler = peffect->owner; + peffect->effect_owner = owner_player; + peffect->id = infos.field_id++; + } + peffect->card_type = peffect->owner->data.type; effects.indexer.emplace(peffect, it); if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)) { if(peffect->is_disable_related()) @@ -1228,7 +1232,7 @@ void field::remove_effect(effect* peffect) { auto eit = effects.indexer.find(peffect); if (eit == effects.indexer.end()) return; - auto it = eit->second; + auto& it = eit->second; if (!(peffect->type & EFFECT_TYPE_ACTIONS)) { effects.aura_effect.erase(it); if(peffect->code == EFFECT_SPSUMMON_COUNT_LIMIT) @@ -1287,16 +1291,14 @@ void field::remove_effect(effect* peffect) { } void field::remove_oath_effect(effect* reason_effect) { for(auto oeit = effects.oath.begin(); oeit != effects.oath.end();) { - if(oeit->second == reason_effect) { - effect* peffect = oeit->first; - oeit = effects.oath.erase(oeit); + auto rm = oeit++; + if(rm->second == reason_effect) { + effect* peffect = rm->first; if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)) remove_effect(peffect); else peffect->handler->remove_effect(peffect); } - else - ++oeit; } } void field::release_oath_relation(effect* reason_effect) { @@ -1309,7 +1311,7 @@ void field::reset_phase(uint32 phase) { auto rm = eit++; if((*rm)->reset(phase, RESET_PHASE)) { if((*rm)->is_flag(EFFECT_FLAG_FIELD_ONLY)) - remove_effect((*rm)); + remove_effect(*rm); else (*rm)->handler->remove_effect((*rm)); } @@ -1319,7 +1321,7 @@ void field::reset_chain() { for(auto eit = effects.cheff.begin(); eit != effects.cheff.end();) { auto rm = eit++; if((*rm)->is_flag(EFFECT_FLAG_FIELD_ONLY)) - remove_effect((*rm)); + remove_effect(*rm); else (*rm)->handler->remove_effect((*rm)); } @@ -1366,9 +1368,11 @@ void field::filter_field_effect(uint32 code, effect_set* eset, uint8 sort) { if(sort) eset->sort(); } +//Get all cards in the target range of a EFFECT_TYPE_FIELD effect void field::filter_affected_cards(effect* peffect, card_set* cset) { - if((peffect->type & EFFECT_TYPE_ACTIONS) || !(peffect->type & EFFECT_TYPE_FIELD) - || peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET | EFFECT_FLAG_SPSUM_PARAM)) + if ((peffect->type & EFFECT_TYPE_ACTIONS) || !(peffect->type & EFFECT_TYPE_FIELD)) + return; + if (peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET | EFFECT_FLAG_SPSUM_PARAM)) return; uint8 self = peffect->get_handler_player(); if (!check_playerid(self)) @@ -2097,6 +2101,8 @@ void field::adjust_self_destroy_set() { } void field::erase_grant_effect(effect* peffect) { auto eit = effects.grant_effect.find(peffect); + if (eit == effects.grant_effect.end()) + return; for(auto& it : eit->second) it.first->remove_effect(it.second); effects.grant_effect.erase(eit); @@ -2105,7 +2111,10 @@ int32 field::adjust_grant_effect() { int32 adjusted = FALSE; for(auto& eit : effects.grant_effect) { effect* peffect = eit.first; - if(!peffect->label_object) + if (peffect->object_type != PARAM_TYPE_EFFECT) + continue; + effect* geffect = (effect*)peffect->get_label_object(); + if (geffect->type & EFFECT_TYPE_GRANT) continue; card_set cset; if(peffect->is_available()) @@ -2121,8 +2130,10 @@ int32 field::adjust_grant_effect() { if(!pcard->is_affect_by_effect(peffect) || !cset.count(pcard)) remove_set.insert(pcard); } + //X gains an effect from itself will break card::remove_effect + if (!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)) + add_set.erase(peffect->handler); for(auto& pcard : add_set) { - effect* geffect = (effect*)peffect->get_label_object(); effect* ceffect = geffect->clone(); ceffect->owner = pcard; pcard->add_effect(ceffect); diff --git a/field.h b/field.h index 242396325..ea8b424d8 100644 --- a/field.h +++ b/field.h @@ -103,7 +103,6 @@ struct player_info { }; struct field_effect { using oath_effects = std::unordered_map; - using effect_collection = std::unordered_set; using gain_effects = std::unordered_map; using grant_effect_container = std::unordered_map; @@ -417,7 +416,7 @@ class field { void refresh_player_info(uint8 playerid); void tag_swap(uint8 playerid); - void add_effect(effect* peffect, uint8 owner_player = 2); + void add_effect(effect* peffect, uint8 owner_player = PLAYER_NONE); void remove_effect(effect* peffect); void remove_oath_effect(effect* reason_effect); void release_oath_relation(effect* reason_effect); diff --git a/libcard.cpp b/libcard.cpp index fc319d4cc..39a383258 100644 --- a/libcard.cpp +++ b/libcard.cpp @@ -3342,7 +3342,6 @@ int32 scriptlib::card_set_unique_onfield(lua_State *L) { peffect->owner = pcard; peffect->type = EFFECT_TYPE_SINGLE; peffect->code = EFFECT_UNIQUE_CHECK; - peffect->flag[0] = EFFECT_FLAG_COPY_INHERIT; pcard->add_effect(peffect); pcard->unique_effect = peffect; if(pcard->current.location & location) diff --git a/libeffect.cpp b/libeffect.cpp index f723d690b..78bc3eea9 100644 --- a/libeffect.cpp +++ b/libeffect.cpp @@ -190,17 +190,21 @@ int32 scriptlib::effect_set_label_object(lua_State *L) { effect* peffect = *(effect**) lua_touserdata(L, 1); if(lua_isnil(L, 2)) { peffect->label_object = 0; + peffect->object_type = PARAM_TYPE_INT; return 0; } if(check_param(L, PARAM_TYPE_CARD, 2, TRUE)) { card* p = *(card**)lua_touserdata(L, 2); peffect->label_object = p->ref_handle; + peffect->object_type = PARAM_TYPE_CARD; } else if(check_param(L, PARAM_TYPE_EFFECT, 2, TRUE)) { effect* p = *(effect**)lua_touserdata(L, 2); peffect->label_object = p->ref_handle; + peffect->object_type = PARAM_TYPE_EFFECT; } else if(check_param(L, PARAM_TYPE_GROUP, 2, TRUE)) { group* p = *(group**)lua_touserdata(L, 2); peffect->label_object = p->ref_handle; + peffect->object_type = PARAM_TYPE_GROUP; } else return luaL_error(L, "Parameter 2 should be \"Card\" or \"Effect\" or \"Group\"."); return 0; diff --git a/processor.cpp b/processor.cpp index ac8a40407..6005903ac 100644 --- a/processor.cpp +++ b/processor.cpp @@ -1039,7 +1039,7 @@ int32 field::process_phase_event(int16 step, int32 phase) { ++cn_count; } //all effects taking control non-permanently are only until End Phase, not until Turn end - for(auto* peffect : effects.pheff) { + for(auto& peffect : effects.pheff) { if(peffect->code != EFFECT_SET_CONTROL) continue; if(!(peffect->reset_flag & phase))