Commit 86a64f83 authored by nanahira's avatar nanahira

Merge branch 'patch-rule' of github.com:Fluorohydride/ygopro-core

parents 502908cb 89d5e316
......@@ -586,20 +586,10 @@ int32 field::get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer
pcard->current.location = LOCATION_EXTRA;
}
int32 useable_count = 0;
if(core.duel_rule >= 4 && !is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) && !pcard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
if(core.duel_rule >= 4)
useable_count = get_useable_count_fromex_rule4(pcard, playerid, uplayer, zone, list);
else
{
useable_count = get_useable_count_other(pcard, playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone, list);
if(core.duel_rule >= 4) {
uint32 temp_list = 0;
get_useable_count_fromex_rule4(pcard, playerid, uplayer, zone, &temp_list);
if(~temp_list & ((1u << 5) | (1u << 6)))
useable_count++;
if(list)
*list &= temp_list;
}
}
if(use_temp_card)
pcard->current.location = 0;
return useable_count;
......@@ -652,28 +642,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;
......@@ -695,29 +664,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;
......@@ -732,7 +679,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];
......@@ -804,6 +752,42 @@ 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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || pcard && pcard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
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;
......@@ -2431,13 +2415,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || pcard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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;
......@@ -2494,7 +2478,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) {
......@@ -2562,7 +2546,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);
......@@ -2728,16 +2712,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || scard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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)
......@@ -2751,7 +2735,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;
......@@ -2806,7 +2790,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();
......@@ -2823,7 +2807,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)
......
......@@ -380,6 +380,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);
......
......@@ -2112,10 +2112,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)
......@@ -2137,6 +2149,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) {
......
......@@ -5237,14 +5237,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || pcard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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;
......@@ -5252,7 +5252,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()) {
......@@ -5466,12 +5466,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || scard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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);
......@@ -5523,7 +5523,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)
......@@ -5554,13 +5554,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || scard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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;
......@@ -5570,7 +5570,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++;
......@@ -5739,19 +5739,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;
if(is_player_affected_by_effect(playerid, EFFECT_EXTRA_TOMAIN_KOISHI) || scard->is_affected_by_effect(EFFECT_EXTRA_TOMAIN_KOISHI))
linked_zone = 0x7f;
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