Commit 101ed0bf authored by salix5's avatar salix5 Committed by GitHub

add Card.IsEffectProperty (#648)

* add EFFECT_FLAG_COPY

* card: add filter_effect_container()

avoid unnecessary copy

* card: add find_effect_container()

* card: add find_effect_with_target()

* use template

* update effect_set

* remove unused include

* add Card.IsEffectCode, IsEffectCategory

* rename to Card.IsEffectProperty

* card: update is_effect_property

* effect: add is_monster_effect

* fix exclude condition
parent 59593ffc
...@@ -1770,8 +1770,8 @@ int32 card::add_effect(effect* peffect) { ...@@ -1770,8 +1770,8 @@ int32 card::add_effect(effect* peffect) {
if (peffect->type & EFFECT_TYPES_TRIGGER_LIKE && is_continuous_event(peffect->code)) if (peffect->type & EFFECT_TYPES_TRIGGER_LIKE && is_continuous_event(peffect->code))
return 0; return 0;
// the trigger effect in phase is "once per turn" by default // 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) if (peffect->get_code_type() == CODE_PHASE && peffect->code & (PHASE_DRAW | PHASE_STANDBY | PHASE_END)
&& !peffect->is_flag(EFFECT_FLAG_COUNT_LIMIT)) { && 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->flag[0] |= EFFECT_FLAG_COUNT_LIMIT;
peffect->count_limit = 1; peffect->count_limit = 1;
peffect->count_limit_max = 1; peffect->count_limit_max = 1;
...@@ -1874,8 +1874,10 @@ int32 card::add_effect(effect* peffect) { ...@@ -1874,8 +1874,10 @@ int32 card::add_effect(effect* peffect) {
return 0; return 0;
peffect->id = pduel->game_field->infos.field_id++; peffect->id = pduel->game_field->infos.field_id++;
peffect->card_type = data.type; peffect->card_type = data.type;
if(get_status(STATUS_INITIALIZING)) if (get_status(STATUS_INITIALIZING))
peffect->flag[0] |= EFFECT_FLAG_INITIAL; 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)) { if (get_status(STATUS_COPYING_EFFECT)) {
peffect->copy_id = pduel->game_field->infos.copy_id; peffect->copy_id = pduel->game_field->infos.copy_id;
peffect->reset_flag |= pduel->game_field->core.copy_reset; peffect->reset_flag |= pduel->game_field->core.copy_reset;
...@@ -1884,6 +1886,10 @@ int32 card::add_effect(effect* peffect) { ...@@ -1884,6 +1886,10 @@ int32 card::add_effect(effect* peffect) {
effect* reason_effect = pduel->game_field->core.reason_effect; effect* reason_effect = pduel->game_field->core.reason_effect;
indexer.emplace(peffect, eit); indexer.emplace(peffect, eit);
peffect->handler = this; 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->type & EFFECT_TYPE_FIELD)) {
if(peffect->in_range(this) || current.controler != PLAYER_NONE && peffect->is_hand_trigger()) if(peffect->in_range(this) || current.controler != PLAYER_NONE && peffect->is_hand_trigger())
pduel->game_field->add_effect(peffect); pduel->game_field->add_effect(peffect);
...@@ -1961,6 +1967,10 @@ effect_indexer::iterator card::remove_effect(effect* peffect) { ...@@ -1961,6 +1967,10 @@ effect_indexer::iterator card::remove_effect(effect* peffect) {
} }
} }
auto ret = indexer.erase(index); 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)) if(peffect->is_flag(EFFECT_FLAG_OATH))
pduel->game_field->effects.oath.erase(peffect); pduel->game_field->effects.oath.erase(peffect);
if(peffect->reset_flag & RESET_PHASE) if(peffect->reset_flag & RESET_PHASE)
...@@ -2001,6 +2011,8 @@ int32 card::copy_effect(uint32 code, uint32 reset, int32 count) { ...@@ -2001,6 +2011,8 @@ int32 card::copy_effect(uint32 code, uint32 reset, int32 count) {
::read_card(code, &cdata); ::read_card(code, &cdata);
if(cdata.type & TYPE_NORMAL) if(cdata.type & TYPE_NORMAL)
return -1; return -1;
if (!reset)
reset = RESETS_STANDARD;
set_status(STATUS_COPYING_EFFECT, TRUE); set_status(STATUS_COPYING_EFFECT, TRUE);
auto cr = pduel->game_field->core.copy_reset; auto cr = pduel->game_field->core.copy_reset;
auto crc = pduel->game_field->core.copy_reset_count; auto crc = pduel->game_field->core.copy_reset_count;
...@@ -2037,6 +2049,8 @@ int32 card::replace_effect(uint32 code, uint32 reset, int32 count) { ...@@ -2037,6 +2049,8 @@ int32 card::replace_effect(uint32 code, uint32 reset, int32 count) {
::read_card(code, &cdata); ::read_card(code, &cdata);
if(cdata.type & TYPE_NORMAL) if(cdata.type & TYPE_NORMAL)
return -1; return -1;
if (!reset)
reset = RESETS_STANDARD;
if(is_status(STATUS_EFFECT_REPLACED)) if(is_status(STATUS_EFFECT_REPLACED))
set_status(STATUS_EFFECT_REPLACED, FALSE); set_status(STATUS_EFFECT_REPLACED, FALSE);
for(auto it = indexer.begin(); it != indexer.end();) { for(auto it = indexer.begin(); it != indexer.end();) {
...@@ -2572,136 +2586,91 @@ void card::set_special_summon_status(effect* peffect) { ...@@ -2572,136 +2586,91 @@ void card::set_special_summon_status(effect* peffect) {
spsummon.reason_player = cait->triggering_player; spsummon.reason_player = cait->triggering_player;
} }
} }
void card::filter_effect(int32 code, effect_set* eset, uint8 sort) { auto default_single_filter = [](card* c, effect* peffect) -> bool {
effect* peffect; return peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || c->is_affect_by_effect(peffect));
auto rg = single_effect.equal_range(code); };
for (; rg.first != rg.second; ++rg.first) { auto default_equip_filter = [](card* c, effect* peffect) -> bool {
peffect = rg.first->second; return peffect->is_available() && c->is_affect_by_effect(peffect);
if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect))) };
eset->add_item(peffect); auto default_target_filter = [](card* c, effect* peffect) -> bool {
} return peffect->is_available() && peffect->is_target(c) && c->is_affect_by_effect(peffect);
for (auto& pcard : equiping_cards) { };
rg = pcard->equip_effect.equal_range(code); auto default_xmaterial_filter = [](card* c, effect* peffect) -> bool {
for (; rg.first != rg.second; ++rg.first) { return !(peffect->type & EFFECT_TYPE_FIELD) && peffect->is_available() && c->is_affect_by_effect(peffect);
peffect = rg.first->second; };
if (peffect->is_available() && is_affect_by_effect(peffect)) auto default_aura_filter = [](card* c, effect* peffect) -> bool {
eset->add_item(peffect); 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 {
for(auto& pcard : effect_target_owner) { return true;
rg = pcard->target_effect.equal_range(code); };
for(; rg.first != rg.second; ++rg.first) { template<typename T>
peffect = rg.first->second; void card::filter_effect_container(const effect_container& container, uint32 code, effect_filter f, T& eset) {
if(peffect->is_available() && peffect->is_target(this) && is_affect_by_effect(peffect)) auto rg = container.equal_range(code);
eset->add_item(peffect); for (auto it = rg.first; it != rg.second; ++it) {
} if (f(this, it->second))
} eset.add_item(it->second);
for (auto& pcard : xyz_materials) { }
rg = pcard->xmaterial_effect.equal_range(code); }
for (; rg.first != rg.second; ++rg.first) { void card::filter_effect(uint32 code, effect_set* eset, uint8 sort) {
peffect = rg.first->second; filter_effect_container(single_effect, code, default_single_filter, *eset);
if (peffect->type & EFFECT_TYPE_FIELD) for (const auto& pcard : equiping_cards)
continue; filter_effect_container(pcard->equip_effect, code, default_equip_filter, *eset);
if (peffect->is_available() && is_affect_by_effect(peffect)) for (const auto& pcard : effect_target_owner)
eset->add_item(peffect); 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);
rg = pduel->game_field->effects.aura_effect.equal_range(code); filter_effect_container(pduel->game_field->effects.aura_effect, code, default_aura_filter, *eset);
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);
}
if(sort) if(sort)
eset->sort(); eset->sort();
} }
void card::filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort) { void card::filter_single_continuous_effect(uint32 code, effect_set* eset, uint8 sort) {
auto rg = single_effect.equal_range(code); filter_effect_container(single_effect, code, accept_filter, *eset);
for (; rg.first != rg.second; ++rg.first) for (const auto& pcard : equiping_cards)
eset->add_item(rg.first->second); filter_effect_container(pcard->equip_effect, code, accept_filter, *eset);
for (auto& pcard : equiping_cards) { auto target_filter = [](card* c, effect* peffect) -> bool {
rg = pcard->equip_effect.equal_range(code); return peffect->is_target(c);
for (; rg.first != rg.second; ++rg.first) };
eset->add_item(rg.first->second); for (const auto& pcard : effect_target_owner)
} filter_effect_container(pcard->target_effect, code, target_filter, *eset);
for(auto& pcard : effect_target_owner) { auto xmaterial_filter = [](card* c, effect* peffect) -> bool {
rg = pcard->target_effect.equal_range(code); return !(peffect->type & EFFECT_TYPE_FIELD);
for(; rg.first != rg.second; ++rg.first) { };
effect* peffect = rg.first->second; for (const auto& pcard : xyz_materials)
if(peffect->is_target(pcard)) filter_effect_container(pcard->xmaterial_effect, code, xmaterial_filter, *eset);
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);
}
}
if(sort) if(sort)
eset->sort(); eset->sort();
} }
void card::filter_self_effect(int32 code, effect_set* eset, uint8 sort) { void card::filter_self_effect(uint32 code, effect_set* eset, uint8 sort) {
auto rg = single_effect.equal_range(code); auto single_filter = [](card* c, effect* peffect) -> bool {
for (; rg.first != rg.second; ++rg.first) { return peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE);
effect* peffect = rg.first->second; };
if(peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)) filter_effect_container(single_effect, code, single_filter, *eset);
eset->add_item(rg.first->second); auto xmaterial_filter = [](card* c, effect* peffect) -> bool {
} return !(peffect->type & EFFECT_TYPE_FIELD);
for (auto& pcard : xyz_materials) { };
rg = pcard->xmaterial_effect.equal_range(code); for (const auto& pcard : xyz_materials)
for (; rg.first != rg.second; ++rg.first) { filter_effect_container(pcard->xmaterial_effect, code, xmaterial_filter, *eset);
effect* peffect = rg.first->second;
if (peffect->type & EFFECT_TYPE_FIELD)
continue;
eset->add_item(peffect);
}
}
if (sort) if (sort)
eset->sort(); eset->sort();
} }
// refresh this->immune_effect // refresh this->immune_effect
void card::filter_immune_effect() { void card::filter_immune_effect() {
immune_effect.clear(); immune_effect.clear();
auto rg = single_effect.equal_range(EFFECT_IMMUNE_EFFECT); filter_effect_container(single_effect, EFFECT_IMMUNE_EFFECT, accept_filter, immune_effect);
for (; rg.first != rg.second; ++rg.first) { for (const auto& pcard : equiping_cards)
effect* peffect = rg.first->second; filter_effect_container(pcard->equip_effect, EFFECT_IMMUNE_EFFECT, accept_filter, immune_effect);
immune_effect.add_item(peffect); auto target_filter = [](card* c, effect* peffect) -> bool {
} return peffect->is_target(c);
for (auto& pcard : equiping_cards) { };
rg = pcard->equip_effect.equal_range(EFFECT_IMMUNE_EFFECT); for (const auto& pcard : effect_target_owner)
for (; rg.first != rg.second; ++rg.first) { filter_effect_container(pcard->target_effect, EFFECT_IMMUNE_EFFECT, target_filter, immune_effect);
effect* peffect = rg.first->second; auto xmaterial_filter = [](card* c, effect* peffect) -> bool {
immune_effect.add_item(peffect); return !(peffect->type & EFFECT_TYPE_FIELD);
} };
} for (const auto& pcard : xyz_materials)
for (auto& pcard : effect_target_owner) { filter_effect_container(pcard->xmaterial_effect, EFFECT_IMMUNE_EFFECT, xmaterial_filter, immune_effect);
rg = pcard->target_effect.equal_range(EFFECT_IMMUNE_EFFECT); filter_effect_container(pduel->game_field->effects.aura_effect, EFFECT_IMMUNE_EFFECT, target_filter, 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);
}
immune_effect.sort(); immune_effect.sort();
} }
// for all disable-related peffect of this, // for all disable-related peffect of this,
...@@ -2948,90 +2917,84 @@ void card::filter_spsummon_procedure_g(uint8 playerid, effect_set* peset) { ...@@ -2948,90 +2917,84 @@ void card::filter_spsummon_procedure_g(uint8 playerid, effect_set* peset) {
pduel->game_field->core.reason_player = op; pduel->game_field->core.reason_player = op;
} }
} }
// find an effect with code which affects this effect* card::find_effect(const effect_container& container, uint32 code, effect_filter f) {
effect* card::is_affected_by_effect(int32 code) { auto rg = container.equal_range(code);
auto rg = single_effect.equal_range(code);
for (auto it = rg.first; it != rg.second; ++it) { for (auto it = rg.first; it != rg.second; ++it) {
effect* const& peffect = it->second; if (f(this, it->second))
if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect))) return it->second;
return peffect;
} }
for (auto& pcard : equiping_cards) { return nullptr;
rg = pcard->equip_effect.equal_range(code); }
for (auto it = rg.first; it != rg.second; ++it) { effect* card::find_effect_with_target(const effect_container& container, uint32 code, effect_filter_target f, card* target) {
effect* const& peffect = it->second; auto rg = container.equal_range(code);
if (peffect->is_available() && is_affect_by_effect(peffect)) for (auto it = rg.first; it != rg.second; ++it) {
return peffect; if (f(this, it->second, target))
} return it->second;
} }
for (auto& pcard : effect_target_owner) { return nullptr;
rg = pcard->target_effect.equal_range(code); }
for (auto it = rg.first; it != rg.second; ++it) { // find an effect with code which affects this
effect* const& peffect = it->second; effect* card::is_affected_by_effect(uint32 code) {
if (peffect->is_available() && peffect->is_target(this) && is_affect_by_effect(peffect)) effect* peffect = find_effect(single_effect, code, default_single_filter);
return peffect; 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) { for (const auto& pcard : effect_target_owner) {
rg = pcard->xmaterial_effect.equal_range(code); peffect = find_effect(pcard->target_effect, code, default_target_filter);
for (auto it = rg.first; it != rg.second; ++it) { if (peffect)
effect* const& peffect = it->second; return peffect;
if (peffect->type & EFFECT_TYPE_FIELD)
continue;
if (peffect->is_available() && is_affect_by_effect(peffect))
return peffect;
}
} }
rg = pduel->game_field->effects.aura_effect.equal_range(code); for (const auto& pcard : xyz_materials) {
for (auto it = rg.first; it != rg.second; ++it) { peffect = find_effect(pcard->xmaterial_effect, code, default_xmaterial_filter);
effect* const& peffect = it->second; if (peffect)
if (!peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_target(this)
&& peffect->is_available() && is_affect_by_effect(peffect))
return peffect; return peffect;
} }
peffect = find_effect(pduel->game_field->effects.aura_effect, code, default_aura_filter);
if (peffect)
return peffect;
return nullptr; return nullptr;
} }
effect* card::is_affected_by_effect(int32 code, card* target) { effect* card::is_affected_by_effect(int32 code, card* target) {
auto rg = single_effect.equal_range(code); auto single_filter = [](card* c, effect* peffect, card* target) -> bool {
for (auto it = rg.first; it != rg.second; ++it) { return default_single_filter(c, peffect) && peffect->get_value(target);
effect* const& peffect = it->second; };
if (peffect->is_available() && (!peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect)) effect* peffect = find_effect_with_target(single_effect, code, single_filter, target);
&& peffect->get_value(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; return peffect;
} }
for (auto& pcard : equiping_cards) { auto target_filter = [](card* c, effect* peffect, card* target) -> bool {
rg = pcard->equip_effect.equal_range(code); return default_target_filter(c, peffect) && peffect->get_value(target);
for (auto it = rg.first; it != rg.second; ++it) { };
effect* const& peffect = it->second; for (const auto& pcard : effect_target_owner) {
if (peffect->is_available() && is_affect_by_effect(peffect) && peffect->get_value(target)) peffect = find_effect_with_target(pcard->target_effect, code, target_filter, target);
return peffect; if (peffect)
} 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;
}
} }
rg = pduel->game_field->effects.aura_effect.equal_range(code); auto xmaterial_filter = [](card* c, effect* peffect, card* target) -> bool {
for (auto it = rg.first; it != rg.second; ++it) { return default_xmaterial_filter(c, peffect) && peffect->get_value(target);
effect* const& peffect = it->second; };
if (!peffect->is_flag(EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available() for (const auto& pcard : xyz_materials) {
&& peffect->is_target(this) && is_affect_by_effect(peffect) && peffect->get_value(target)) peffect = find_effect_with_target(pcard->xmaterial_effect, code, xmaterial_filter, target);
if (peffect)
return 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; return nullptr;
} }
int32 card::fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material) { int32 card::fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material) {
...@@ -4196,3 +4159,38 @@ int32 card::is_can_be_link_material(card* scard) { ...@@ -4196,3 +4159,38 @@ int32 card::is_can_be_link_material(card* scard) {
return FALSE; return FALSE;
return TRUE; 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);
if (pduel->lua->check_condition(filter, 1))
return TRUE;
}
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_MZONE) && !peffect->is_monster_effect())
continue;
if (current.is_location(LOCATION_SZONE) && !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_MZONE) && !peffect->is_monster_effect())
continue;
if (current.is_location(LOCATION_SZONE) && !peffect->in_range(this))
continue;
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
if (pduel->lua->check_condition(filter, 1))
return TRUE;
}
return FALSE;
}
...@@ -30,6 +30,9 @@ using effect_container = std::multimap<uint32, effect*>; ...@@ -30,6 +30,9 @@ using effect_container = std::multimap<uint32, effect*>;
using effect_indexer = std::unordered_map<effect*, effect_container::iterator>; using effect_indexer = std::unordered_map<effect*, effect_container::iterator>;
using effect_collection = std::unordered_set<effect*>; using effect_collection = std::unordered_set<effect*>;
using effect_filter = bool(*)(card* self, effect* peffect);
using effect_filter_target = bool(*)(card* self, effect* peffect, card* target);
struct card_state { struct card_state {
uint32 code{ 0 }; uint32 code{ 0 };
uint32 code2{ 0 }; uint32 code2{ 0 };
...@@ -210,6 +213,8 @@ public: ...@@ -210,6 +213,8 @@ public:
effect_indexer indexer; effect_indexer indexer;
effect_relation relate_effect; effect_relation relate_effect;
effect_set_v immune_effect; effect_set_v immune_effect;
effect_collection initial_effect;
effect_collection owning_effect;
explicit card(duel* pd); explicit card(duel* pd);
~card() = default; ~card() = default;
...@@ -320,9 +325,11 @@ public: ...@@ -320,9 +325,11 @@ public:
void clear_card_target(); void clear_card_target();
void set_special_summon_status(effect* peffect); void set_special_summon_status(effect* peffect);
void filter_effect(int32 code, effect_set* eset, uint8 sort = TRUE); template<typename T>
void filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort = TRUE); void filter_effect_container(const effect_container& container, uint32 code, effect_filter f, T& eset);
void filter_self_effect(int32 code, effect_set* eset, uint8 sort = TRUE); 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_immune_effect();
void filter_disable_related_cards(); void filter_disable_related_cards();
int32 filter_summon_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute, uint32 zone); int32 filter_summon_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute, uint32 zone);
...@@ -331,7 +338,9 @@ public: ...@@ -331,7 +338,9 @@ public:
int32 check_set_procedure(effect* proc, uint8 playerid, uint8 ignore_count, uint8 min_tribute, uint32 zone); 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(uint8 playerid, effect_set* eset, uint32 summon_type, material_info info = null_info);
void filter_spsummon_procedure_g(uint8 playerid, effect_set* eset); 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* 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); effect* is_affected_by_effect(int32 code, card* target);
int32 fusion_check(group* fusion_m, card* cg, uint32 chkf, uint8 not_material); 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); void fusion_select(uint8 playerid, group* fusion_m, card* cg, uint32 chkf, uint8 not_material);
...@@ -392,6 +401,8 @@ public: ...@@ -392,6 +401,8 @@ public:
int32 is_can_be_ritual_material(card* scard); int32 is_can_be_ritual_material(card* scard);
int32 is_can_be_xyz_material(card* scard); int32 is_can_be_xyz_material(card* scard);
int32 is_can_be_link_material(card* scard); int32 is_can_be_link_material(card* scard);
int32 is_original_effect_property(int32 filter);
int32 is_effect_property(int32 filter);
}; };
//Summon Type in summon_info //Summon Type in summon_info
......
...@@ -622,6 +622,11 @@ int32 effect::is_hand_trigger() const { ...@@ -622,6 +622,11 @@ int32 effect::is_hand_trigger() const {
int32 effect::is_initial_single() const { int32 effect::is_initial_single() const {
return (type & EFFECT_TYPE_SINGLE) && is_flag(EFFECT_FLAG_SINGLE_RANGE) && is_flag(EFFECT_FLAG_INITIAL); return (type & EFFECT_TYPE_SINGLE) && is_flag(EFFECT_FLAG_SINGLE_RANGE) && is_flag(EFFECT_FLAG_INITIAL);
} }
int32 effect::is_monster_effect() const {
if (range & (LOCATION_SZONE | LOCATION_FZONE | LOCATION_PZONE))
return FALSE;
return TRUE;
}
//return: this can be reset by reset_level or not //return: this can be reset by reset_level or not
//RESET_DISABLE is valid only when owner == handler //RESET_DISABLE is valid only when owner == handler
int32 effect::reset(uint32 reset_level, uint32 reset_type) { int32 effect::reset(uint32 reset_level, uint32 reset_type) {
......
...@@ -11,9 +11,7 @@ ...@@ -11,9 +11,7 @@
#include "common.h" #include "common.h"
#include "field.h" #include "field.h"
#include "effectset.h" #include "effectset.h"
#include <stdlib.h>
#include <vector> #include <vector>
#include <map>
class card; class card;
class duel; class duel;
...@@ -90,6 +88,7 @@ public: ...@@ -90,6 +88,7 @@ public:
int32 is_chainable(uint8 tp); int32 is_chainable(uint8 tp);
int32 is_hand_trigger() const; int32 is_hand_trigger() const;
int32 is_initial_single() const; int32 is_initial_single() const;
int32 is_monster_effect() const;
int32 reset(uint32 reset_level, uint32 reset_type); int32 reset(uint32 reset_level, uint32 reset_type);
void dec_count(uint8 playerid = PLAYER_NONE); void dec_count(uint8 playerid = PLAYER_NONE);
void recharge(); void recharge();
...@@ -156,6 +155,8 @@ public: ...@@ -156,6 +155,8 @@ public:
#define RESET_OVERLAY 0x04000000 #define RESET_OVERLAY 0x04000000
#define RESET_MSCHANGE 0x08000000 #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 ========== //========== Types ==========
#define EFFECT_TYPE_SINGLE 0x0001 // #define EFFECT_TYPE_SINGLE 0x0001 //
#define EFFECT_TYPE_FIELD 0x0002 // #define EFFECT_TYPE_FIELD 0x0002 //
...@@ -191,7 +192,7 @@ enum effect_flag : uint32 { ...@@ -191,7 +192,7 @@ enum effect_flag : uint32 {
EFFECT_FLAG_CANNOT_DISABLE = 0x0400, EFFECT_FLAG_CANNOT_DISABLE = 0x0400,
EFFECT_FLAG_PLAYER_TARGET = 0x0800, EFFECT_FLAG_PLAYER_TARGET = 0x0800,
EFFECT_FLAG_BOTH_SIDE = 0x1000, EFFECT_FLAG_BOTH_SIDE = 0x1000,
// EFFECT_FLAG_COPY_INHERIT = 0x2000, EFFECT_FLAG_COPY = 0x2000,
EFFECT_FLAG_DAMAGE_STEP = 0x4000, EFFECT_FLAG_DAMAGE_STEP = 0x4000,
EFFECT_FLAG_DAMAGE_CAL = 0x8000, EFFECT_FLAG_DAMAGE_CAL = 0x8000,
EFFECT_FLAG_DELAY = 0x10000, EFFECT_FLAG_DELAY = 0x10000,
...@@ -220,7 +221,7 @@ enum effect_flag2 : uint32 { ...@@ -220,7 +221,7 @@ enum effect_flag2 : uint32 {
constexpr effect_flag operator|(effect_flag flag1, effect_flag flag2) { constexpr effect_flag operator|(effect_flag flag1, effect_flag flag2) {
return static_cast<effect_flag>(static_cast<uint32>(flag1) | static_cast<uint32>(flag2)); return static_cast<effect_flag>(static_cast<uint32>(flag1) | static_cast<uint32>(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 ========== //========== Codes ==========
#define EFFECT_IMMUNE_EFFECT 1 // #define EFFECT_IMMUNE_EFFECT 1 //
#define EFFECT_DISABLE 2 // #define EFFECT_DISABLE 2 //
......
...@@ -26,10 +26,6 @@ struct effect_set { ...@@ -26,10 +26,6 @@ struct effect_set {
void remove_item(int index) { void remove_item(int index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return; return;
if(index == count - 1) {
--count;
return;
}
for(int i = index; i < count - 1; ++i) for(int i = index; i < count - 1; ++i)
container[i] = container[i + 1]; container[i] = container[i + 1];
--count; --count;
...@@ -86,10 +82,7 @@ struct effect_set_v { ...@@ -86,10 +82,7 @@ struct effect_set_v {
return (int)container.size(); return (int)container.size();
} }
void sort() { void sort() {
int count = (int)container.size(); std::sort(container.begin(), container.end(), effect_sort_id);
if(count < 2)
return;
std::sort(container.begin(), container.begin() + count, effect_sort_id);
} }
effect* const& get_last() const { effect* const& get_last() const {
assert(container.size()); assert(container.size());
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#include <set> #include <set>
#include <map> #include <map>
#include <list> #include <list>
#include <array>
#include <functional>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
......
...@@ -1345,6 +1345,24 @@ int32 scriptlib::card_is_tuner(lua_State* L) { ...@@ -1345,6 +1345,24 @@ int32 scriptlib::card_is_tuner(lua_State* L) {
lua_pushboolean(L, pcard->is_tuner(scard)); lua_pushboolean(L, pcard->is_tuner(scard));
return 1; return 1;
} }
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);
int32 filter = interpreter::get_function_handle(L, 2);
lua_pushboolean(L, pcard->is_original_effect_property(filter));
return 1;
}
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);
int32 filter = interpreter::get_function_handle(L, 2);
lua_pushboolean(L, pcard->is_effect_property(filter));
return 1;
}
int32 scriptlib::card_set_status(lua_State *L) { int32 scriptlib::card_set_status(lua_State *L) {
check_param_count(L, 3); check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1); check_param(L, PARAM_TYPE_CARD, 1);
...@@ -3515,6 +3533,8 @@ static const struct luaL_Reg cardlib[] = { ...@@ -3515,6 +3533,8 @@ static const struct luaL_Reg cardlib[] = {
{ "IsStatus", scriptlib::card_is_status }, { "IsStatus", scriptlib::card_is_status },
{ "IsNotTuner", scriptlib::card_is_not_tuner }, { "IsNotTuner", scriptlib::card_is_not_tuner },
{ "IsTuner", scriptlib::card_is_tuner }, { "IsTuner", scriptlib::card_is_tuner },
{ "IsOriginalEffectProperty", scriptlib::card_is_original_effect_property },
{ "IsEffectProperty", scriptlib::card_is_effect_property },
{ "SetStatus", scriptlib::card_set_status }, { "SetStatus", scriptlib::card_set_status },
{ "IsDualState", scriptlib::card_is_dual_state }, { "IsDualState", scriptlib::card_is_dual_state },
{ "EnableDualState", scriptlib::card_enable_dual_state }, { "EnableDualState", scriptlib::card_enable_dual_state },
......
...@@ -4792,7 +4792,7 @@ int32 scriptlib::duel_majestic_copy(lua_State *L) { ...@@ -4792,7 +4792,7 @@ int32 scriptlib::duel_majestic_copy(lua_State *L) {
ceffect->flag[0] &= ~EFFECT_FLAG_INITIAL; ceffect->flag[0] &= ~EFFECT_FLAG_INITIAL;
ceffect->effect_owner = PLAYER_NONE; ceffect->effect_owner = PLAYER_NONE;
ceffect->reset_flag = RESET_EVENT + 0x1fe0000 + RESET_PHASE + PHASE_END + RESET_SELF_TURN + RESET_OPPO_TURN; 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(); ceffect->recharge();
if(ceffect->type & EFFECT_TYPE_TRIGGER_F) { if(ceffect->type & EFFECT_TYPE_TRIGGER_F) {
ceffect->type &= ~EFFECT_TYPE_TRIGGER_F; ceffect->type &= ~EFFECT_TYPE_TRIGGER_F;
......
...@@ -151,6 +151,8 @@ public: ...@@ -151,6 +151,8 @@ public:
static int32 card_is_status(lua_State *L); static int32 card_is_status(lua_State *L);
static int32 card_is_not_tuner(lua_State *L); static int32 card_is_not_tuner(lua_State *L);
static int32 card_is_tuner(lua_State* L); static int32 card_is_tuner(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_set_status(lua_State *L);
static int32 card_is_dual_state(lua_State *L); static int32 card_is_dual_state(lua_State *L);
static int32 card_enable_dual_state(lua_State *L); static int32 card_enable_dual_state(lua_State *L);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment