Commit 3af65bab authored by mercury233's avatar mercury233 Committed by GitHub

update new rule (#261)

* update new rule

* fix EFFECT_MUST_USE_MZONE

* update Duel.GetLocationCountFromEx
parent 9e4732f6
......@@ -629,28 +629,7 @@ int32 field::get_tofield_count(card* pcard, uint8 playerid, uint8 location, uint
return 0;
uint32 flag = player[playerid].disabled_location | player[playerid].used_location;
if(location == LOCATION_MZONE && (reason & LOCATION_REASON_TOFIELD)) {
effect_set eset;
if(uplayer < 2)
filter_player_effect(uplayer, EFFECT_MUST_USE_MZONE, &eset);
if(pcard)
pcard->filter_effect(EFFECT_MUST_USE_MZONE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT) && eset[i]->count_limit == 0)
continue;
uint32 value = 0x1f;
if(eset[i]->is_flag(EFFECT_FLAG_PLAYER_TARGET))
value = eset[i]->get_value();
else {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason, PARAM_TYPE_INT);
value = eset[i]->get_value(pcard, 3);
}
if(eset[i]->get_handler_player() == playerid)
flag |= ~value & 0x1f;
else
flag |= ~(value >> 16) & 0x1f;
}
filter_must_use_mzone(playerid, uplayer, reason, pcard, &flag);
}
if (location == LOCATION_MZONE)
flag = (flag | ~zone) & 0x1f;
......@@ -672,29 +651,7 @@ int32 field::get_useable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 u
}
int32 field::get_spsummonable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
uint32 flag = player[playerid].disabled_location | player[playerid].used_location;
effect_set eset;
if(uplayer < 2)
filter_player_effect(uplayer, EFFECT_MUST_USE_MZONE, &eset);
if(pcard)
pcard->filter_effect(EFFECT_MUST_USE_MZONE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT) && eset[i]->count_limit == 0)
continue;
uint32 value = 0x1f;
if(eset[i]->is_flag(EFFECT_FLAG_PLAYER_TARGET))
value = eset[i]->get_value();
else {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(LOCATION_REASON_TOFIELD, PARAM_TYPE_INT);
value = eset[i]->get_value(pcard, 3);
}
if(eset[i]->get_handler_player() == playerid)
flag |= ~value & 0x7f;
else
flag |= ~(value >> 16) & 0x7f;
}
uint32 linked_zone = get_linked_zone(playerid) | (1u << 5) | (1u << 6);
filter_must_use_mzone(playerid, uplayer, LOCATION_REASON_TOFIELD, pcard, &flag);
if(player[playerid].list_mzone[5] && is_location_useable(playerid, LOCATION_MZONE, 6)
&& check_extra_link(playerid, pcard, 6)) {
flag |= 1u << 5;
......@@ -709,7 +666,8 @@ int32 field::get_spsummonable_count_fromex_rule4(card* pcard, uint8 playerid, ui
if(!is_location_useable(playerid, LOCATION_MZONE, 6))
flag |= 1u << 6;
}
flag = flag | ~zone | ~linked_zone;
uint32 rule_zone = get_rule_zone_fromex(playerid, pcard);
flag = flag | ~zone | ~rule_zone;
if(list)
*list = flag & 0x7f;
int32 count = 5 - field_used_count[flag & 0x1f];
......@@ -773,6 +731,40 @@ uint32 field::get_linked_zone(int32 playerid) {
}
return zones;
}
uint32 field::get_rule_zone_fromex(int32 playerid, card* pcard) {
if(core.duel_rule >= 4) {
if(core.duel_rule >= 5 && pcard && pcard->is_position(POS_FACEDOWN) && (pcard->data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ)))
return 0x7f;
else
return get_linked_zone(playerid) | (1u << 5) | (1u << 6);
} else {
return 0x1f;
}
}
void field::filter_must_use_mzone(uint8 playerid, uint8 uplayer, uint32 reason, card* pcard, uint32* flag) {
effect_set eset;
if(uplayer < 2)
filter_player_effect(uplayer, EFFECT_MUST_USE_MZONE, &eset);
if(pcard)
pcard->filter_effect(EFFECT_MUST_USE_MZONE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT) && eset[i]->count_limit == 0)
continue;
uint32 value = 0x1f;
if(eset[i]->is_flag(EFFECT_FLAG_PLAYER_TARGET))
value = eset[i]->get_value();
else {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason, PARAM_TYPE_INT);
value = eset[i]->get_value(pcard, 3);
}
if(eset[i]->get_handler_player() == playerid)
*flag |= ~value & 0x7f;
else
*flag |= ~(value >> 16) & 0x7f;
}
}
void field::get_linked_cards(uint8 self, uint8 s, uint8 o, card_set* cset) {
cset->clear();
uint8 c = s;
......@@ -2393,11 +2385,13 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
}
int32 playerid = pcard->current.controler;
int32 ct = get_spsummonable_count(pcard, playerid);
card_set linked_cards;
card_set handover_zone_cards;
if(ct <= 0) {
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
if(linked_cards.find(tuner) != linked_cards.end())
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, pcard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, pcard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
if(handover_zone_cards.find(tuner) != handover_zone_cards.end())
ct++;
}
int32 location = LOCATION_MZONE;
......@@ -2454,7 +2448,7 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
smat->sum_param = smat->get_synchro_level(pcard);
mcount++;
if(ct <= 0) {
if(linked_cards.find(smat) != linked_cards.end())
if(handover_zone_cards.find(smat) != handover_zone_cards.end())
ct++;
}
if(min == 0) {
......@@ -2522,7 +2516,7 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
auto start = nsyn.begin() + mcount;
for(auto cit = start; cit != nsyn.end(); ++cit) {
card* pm = *cit;
if(linked_cards.find(pm) == linked_cards.end())
if(handover_zone_cards.find(pm) == handover_zone_cards.end())
continue;
if(start != cit)
std::iter_swap(start, cit);
......@@ -2688,14 +2682,16 @@ int32 field::check_xyz_material(card* scard, int32 findex, int32 lv, int32 min,
get_xyz_material(scard, findex, lv, max, mg);
int32 playerid = scard->current.controler;
int32 ct = get_spsummonable_count(scard, playerid);
card_set linked_cards;
card_set handover_zone_cards;
if(ct <= 0) {
int32 ft = ct;
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, scard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, scard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
for(auto cit = core.xmaterial_lst.begin(); cit != core.xmaterial_lst.end(); ++cit) {
card* pcard = cit->second;
if(linked_cards.find(pcard) != linked_cards.end())
if(handover_zone_cards.find(pcard) != handover_zone_cards.end())
ft++;
}
if(ft <= 0)
......@@ -2709,7 +2705,7 @@ int32 field::check_xyz_material(card* scard, int32 findex, int32 lv, int32 min,
int32 mct = mcset.size();
if(mct > 0) {
if(ct == 0 && std::none_of(mcset.begin(), mcset.end(),
[=](card* pcard) { return linked_cards.find(pcard) != linked_cards.end(); }))
[=](card* pcard) { return handover_zone_cards.find(pcard) != handover_zone_cards.end(); }))
mct++;
if(mct > max)
return FALSE;
......@@ -2764,7 +2760,7 @@ int32 field::check_xyz_material(card* scard, int32 findex, int32 lv, int32 min,
++cit;
}
ct += std::count_if(mcset.begin(), mcset.end(),
[=](card* pcard) { return linked_cards.find(pcard) != linked_cards.end(); });
[=](card* pcard) { return handover_zone_cards.find(pcard) != handover_zone_cards.end(); });
std::multimap<int32, card*, std::greater<int32>> mat;
for(int32 icheck = 1; icheck <= digit; icheck <<= 1) {
mat.clear();
......@@ -2781,7 +2777,7 @@ int32 field::check_xyz_material(card* scard, int32 findex, int32 lv, int32 min,
int32 ft = ct;
for(auto cit = mat.begin(); cit != mat.end(); ++cit) {
card* pcard = cit->second;
if(linked_cards.find(pcard) != linked_cards.end())
if(handover_zone_cards.find(pcard) != handover_zone_cards.end())
ft++;
}
if(ft <= 0)
......
......@@ -378,6 +378,8 @@ public:
int32 get_mzone_limit(uint8 playerid, uint8 uplayer, uint32 reason);
int32 get_szone_limit(uint8 playerid, uint8 uplayer, uint32 reason);
uint32 get_linked_zone(int32 playerid);
uint32 get_rule_zone_fromex(int32 playerid, card* pcard);
void filter_must_use_mzone(uint8 playerid, uint8 uplayer, uint32 reason, card* pcard, uint32* flag);
void get_linked_cards(uint8 self, uint8 s, uint8 o, card_set* cset);
int32 check_extra_link(int32 playerid);
int32 check_extra_link(int32 playerid, card* pcard, int32 sequence);
......
......@@ -1899,10 +1899,22 @@ int32 scriptlib::duel_get_location_count_fromex(lua_State *L) {
}
swapped = true;
}
bool use_temp_card = false;
card* scard = 0;
if(lua_gettop(L) >= 4) {
check_param(L, PARAM_TYPE_CARD, 4);
scard = *(card**)lua_touserdata(L, 4);
if(lua_gettop(L) >= 4 && !lua_isnil(L, 4)) {
if(check_param(L, PARAM_TYPE_CARD, 4, TRUE)) {
scard = *(card**)lua_touserdata(L, 4);
} else {
use_temp_card = true;
uint32 type = lua_tointeger(L, 4);
scard = pduel->game_field->temp_card;
scard->current.location = LOCATION_EXTRA;
scard->data.type = TYPE_MONSTER | type;
if(type & TYPE_PENDULUM)
scard->current.position = POS_FACEUP_DEFENSE;
else
scard->current.position = POS_FACEDOWN_DEFENSE;
}
}
uint32 zone = 0xff;
if(lua_gettop(L) >= 5)
......@@ -1916,6 +1928,11 @@ int32 scriptlib::duel_get_location_count_fromex(lua_State *L) {
pduel->game_field->player[0].list_mzone.swap(list_mzone[0]);
pduel->game_field->player[1].list_mzone.swap(list_mzone[1]);
}
if(use_temp_card) {
scard->current.location = 0;
scard->data.type = 0;
scard->current.position = 0;
}
return 2;
}
int32 scriptlib::duel_get_usable_mzone_count(lua_State *L) {
......
......@@ -5179,12 +5179,14 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in
core.units.begin()->step = 6;
return FALSE;
}
card_set linked_cards;
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
if(linked_cards.find(tuner) != linked_cards.end())
card_set handover_zone_cards;
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, pcard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, pcard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
if(handover_zone_cards.find(tuner) != handover_zone_cards.end())
ct++;
if(smat && linked_cards.find(smat) != linked_cards.end())
if(smat && handover_zone_cards.find(smat) != handover_zone_cards.end())
ct++;
if(ct > 0) {
core.units.begin()->step = 6;
......@@ -5192,7 +5194,7 @@ int32 field::select_synchro_material(int16 step, uint8 playerid, card* pcard, in
}
card_vector* select_cards = new card_vector;
for(auto& pm : core.select_cards) {
if(linked_cards.find(pm) != linked_cards.end())
if(handover_zone_cards.find(pm) != handover_zone_cards.end())
select_cards->push_back(pm);
}
if(select_cards->size() == core.select_cards.size()) {
......@@ -5406,10 +5408,12 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc
if(!(core.global_flag & GLOBALFLAG_TUNE_MAGICIAN))
return FALSE;
int32 ct = get_spsummonable_count(scard, playerid);
card_set linked_cards;
card_set handover_zone_cards;
if(ct <= 0) {
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, scard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, scard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
}
for(auto& pcard : core.operated_set) {
effect* peffect = pcard->is_affected_by_effect(EFFECT_TUNE_MAGICIAN_X);
......@@ -5461,7 +5465,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc
int32 ft = ct;
for(auto cit = mat.begin(); cit != mat.end(); ++cit) {
card* pcard = cit->second;
if(linked_cards.find(pcard) != linked_cards.end())
if(handover_zone_cards.find(pcard) != handover_zone_cards.end())
ft++;
}
if(ft <= 0)
......@@ -5492,11 +5496,13 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc
core.units.begin()->step = 4;
return FALSE;
}
card_set linked_cards;
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
card_set handover_zone_cards;
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, scard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, scard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
int32 ft = ct + std::count_if(core.operated_set.begin(), core.operated_set.end(),
[=](card* pcard) { return linked_cards.find(pcard) != linked_cards.end(); });
[=](card* pcard) { return handover_zone_cards.find(pcard) != handover_zone_cards.end(); });
if(ft > 0) {
returns.ivalue[0] = 1;
core.units.begin()->step = 4;
......@@ -5506,7 +5512,7 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc
core.select_cards.clear();
for(auto iter = core.xmaterial_lst.begin(); iter != core.xmaterial_lst.end(); ++iter) {
card* pcard = iter->second;
if(linked_cards.find(pcard) != linked_cards.end())
if(handover_zone_cards.find(pcard) != handover_zone_cards.end())
core.select_cards.push_back(pcard);
else
mmax++;
......@@ -5675,17 +5681,19 @@ int32 field::select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* sc
int32 ct = get_spsummonable_count(scard, playerid);
if(ct > 0)
return FALSE;
card_set linked_cards;
uint32 linked_zone = core.duel_rule >= 4 ? get_linked_zone(playerid) | (1u << 5) | (1u << 6) : 0x1f;
get_cards_in_zone(&linked_cards, linked_zone, playerid, LOCATION_MZONE);
card_set handover_zone_cards;
uint32 must_use_zone_flag = 0;
filter_must_use_mzone(playerid, playerid, LOCATION_REASON_TOFIELD, scard, &must_use_zone_flag);
uint32 handover_zone = get_rule_zone_fromex(playerid, scard) & ~must_use_zone_flag;
get_cards_in_zone(&handover_zone_cards, handover_zone, playerid, LOCATION_MZONE);
int32 ft = ct + std::count_if(core.operated_set.begin(), core.operated_set.end(),
[=](card* pcard) { return linked_cards.find(pcard) != linked_cards.end(); });
[=](card* pcard) { return handover_zone_cards.find(pcard) != handover_zone_cards.end(); });
if(ft > 0)
return FALSE;
core.select_cards.clear();
for(auto iter = core.xmaterial_lst.begin(); iter != core.xmaterial_lst.end(); ++iter) {
card* pcard = iter->second;
if(linked_cards.find(pcard) != linked_cards.end())
if(handover_zone_cards.find(pcard) != handover_zone_cards.end())
core.select_cards.push_back(pcard);
}
pduel->write_buffer8(MSG_HINT);
......
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