Commit 0c163d40 authored by salix5's avatar salix5

Duel.CheckTribute()

TODO:
Add
e1:SetValue(SUMMON_TYPE_ADVANCE+k)
Duel.CheckTribute(c,k)
in EFFECT_SUMMON_PROC, EFFECT_LIMIT_SUMMON_PROC, EFFECT_SET_PROC, EFFECT_LIMIT_SET_PROC scripts
parent ab403b97
......@@ -1993,7 +1993,7 @@ void card::filter_disable_related_cards() {
}
}
}
// put all summon procedures in peset (see is_can_be_summoned())
// put all summon procedures except ordinay summon in peset (see is_can_be_summoned())
// return value:
// -2 = this has EFFECT_LIMIT_SUMMON_PROC, 0 available
// -1 = this has EFFECT_LIMIT_SUMMON_PROC, at least 1 available
......@@ -2034,17 +2034,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
// uniqueness
if(pduel->game_field->check_unique_onfield(this, toplayer, LOCATION_MZONE))
continue;
int32 m = 0;
if(toplayer == playerid) {
m = pduel->game_field->get_summon_release_list(this, NULL, NULL, NULL, NULL, 0);
}
else {
m = pduel->game_field->get_summon_release_list(this, NULL, NULL, NULL, NULL, 1);
}
// check if the # of tributes is enough
if(m < rcount)
continue;
// the script will check the usable count according to the card effect
// the script will check the usable count, the # of tributes
if(is_summonable(eset[i], min_tribute))
peset->add_item(eset[i]);
}
......@@ -2061,6 +2051,7 @@ int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ign
return 0;
}
}
// put all set procedures except ordinay set in peset (see is_can_be_summoned())
int32 card::filter_set_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute) {
effect_set eset;
bool lim = true;
......@@ -2093,17 +2084,7 @@ int32 card::filter_set_procedure(uint8 playerid, effect_set* peset, uint8 ignore
}
else
toplayer = playerid;
int32 m = 0;
if(toplayer == playerid) {
m = pduel->game_field->get_summon_release_list(this, NULL, NULL, NULL, NULL, 0);
}
else {
m = pduel->game_field->get_summon_release_list(this, NULL, NULL, NULL, NULL, 1);
}
// check if the # of tributes is enough
if(m < rcount)
continue;
// the script will check the usable count according to the card effect
// the script will check the usable count, the # of tributes
if(is_summonable(eset[i], min_tribute))
peset->add_item(eset[i]);
}
......@@ -2374,6 +2355,44 @@ int32 card::is_summonable(effect* peffect, uint8 min_tribute) {
pduel->game_field->core.reason_player = op;
return result;
}
// check if the ordinary summon/set of this is available
int32 card::check_ordinary_procedure(uint8 playerid, uint8 min_tribute, bool is_summon) {
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this))
return FALSE;
// uniqueness
if(is_summon && pduel->game_field->check_unique_onfield(this, playerid, LOCATION_MZONE))
return FALSE;
card_set test, exset;
int32 rcount = get_summon_tribute_count();
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
int32 m1 = pduel->game_field->get_summon_release_slist(this, &test, NULL);
int32 m2 = pduel->game_field->get_summon_release_olist(this, NULL, NULL, NULL);
// min_tribute is the real lower bound
if(min < (int32)min_tribute)
min = min_tribute;
// sum of release count is the real upper bound
if(max > m1 + m2)
max = m1 + m2;
if(min > max)
return FALSE;
int32 fcount = pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, current.controler, LOCATION_REASON_TOFIELD);
pduel->game_field->get_summon_release_exlist(this, &exset);
int32 res = pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this);
for(int32 i = min; i <= max; ++i) {
if(i > 0 && !res)
continue;
// check if the usable count is enough
int32 self_max = i - (int32)exset.size();
if(self_max < 0)
self_max = 0;
if(self_max > (int32)test.size())
self_max = (int32)test.size();
if(fcount + self_max - 1 >= 0)
return TRUE;
}
return FALSE;
}
// if this does not have a summon procedure, it will check ordinary summon
// ignore_count: ignore the summon count in this turn or not
// peffect: effects that changes the ordinary summon procedure (c80921533)
// min_tribute: the limit of min tribute number by EFFECT_EXTRA_SUMMON_COUNT
......@@ -2432,51 +2451,7 @@ int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffe
}
else {
// ordinary summon
if(!proc.size()) {
// uniqueness
if(pduel->game_field->check_unique_onfield(this, playerid, LOCATION_MZONE)){
pduel->game_field->restore_lp_cost();
return FALSE;
}
card_set test, exset;
int32 rcount = get_summon_tribute_count();
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
int32 m1 = pduel->game_field->get_summon_release_slist(this, &test, NULL);
int32 m2 = pduel->game_field->get_summon_release_olist(this, NULL, NULL, NULL);
// min_tribute is the real lower bound
if(min < (int32)min_tribute)
min = min_tribute;
// sum of release count is the real upper bound
if(max > m1 + m2)
max = m1 + m2;
if(min > max) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
int32 fcount = pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, current.controler, LOCATION_REASON_TOFIELD);
pduel->game_field->get_summon_release_exlist(this, &exset);
for(int32 i = min; i <= max; ++i) {
if(i == 0){
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this))
continue;
}
else {
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this))
continue;
}
// check if the usable count is enough
int32 self_max = 0;
if(i < (int32)exset.size())
self_max = 0;
else
self_max = i - exset.size();
if(self_max > (int32)test.size())
self_max = test.size();
if(fcount + self_max - 1 >= 0) {
pduel->game_field->restore_lp_cost();
return TRUE;
}
}
if(!proc.size() && !check_ordinary_procedure(playerid, min_tribute, true)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
......@@ -2665,7 +2640,7 @@ int32 card::is_can_be_special_summoned(effect * reason_effect, uint32 sumtype, u
pduel->game_field->restore_lp_cost();
return TRUE;
}
// see is_can_be_summoned()
// if this does not have a set set procedure, it will check ordinary set (see is_can_be_summoned())
int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) {
if(!is_summonable_card())
return FALSE;
......@@ -2708,46 +2683,7 @@ int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect
}
}
else {
if(!proc.size()) {
card_set test, exset;
int32 rcount = get_summon_tribute_count();
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
int32 m1 = pduel->game_field->get_summon_release_slist(this, &test, NULL);
int32 m2 = pduel->game_field->get_summon_release_olist(this, NULL, NULL, NULL);
// min_tribute is the real lower bound
if(min < (int32)min_tribute)
min = min_tribute;
// sum of release count is the real upper bound
if(max > m1 + m2)
max = m1 + m2;
if(min > max) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
int32 fcount = pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, current.controler, LOCATION_REASON_TOFIELD);
pduel->game_field->get_summon_release_exlist(this, &exset);
for(int32 i = min; i <= max; ++i) {
if(i == 0){
if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_NORMAL, playerid, this))
continue;
}
else {
if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_ADVANCE, playerid, this))
continue;
}
// check if the usable count is enough
int32 self_max = 0;
if(i < (int32)exset.size())
self_max = 0;
else
self_max = i - exset.size();
if(self_max > (int32)test.size())
self_max = test.size();
if(fcount + self_max - 1 >= 0) {
pduel->game_field->restore_lp_cost();
return TRUE;
}
}
if(!proc.size() && !check_ordinary_procedure(playerid, min_tribute, false)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
......
......@@ -235,6 +235,7 @@ public:
void filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort = TRUE);
void filter_immune_effect();
void filter_disable_related_cards();
int32 check_ordinary_procedure(uint8 playerid, uint8 min_tribute, bool summon);
int32 filter_summon_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute);
int32 filter_set_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute);
void filter_spsummon_procedure(uint8 playerid, effect_set* eset, uint32 summon_type);
......
......@@ -1291,7 +1291,7 @@ int32 field::get_summon_release_olist(card* target, card_set* ex_list, card_set*
uint32 ex_sum_max = 0;
for(int i = 0; i < 5; ++i) {
pcard = player[1 - p].list_mzone[i];
if(!pcard || pcard->is_releasable_by_summon(p, target))
if(!(pcard && pcard->is_releasable_by_summon(p, target)))
continue;
if(mg && !mg->has_card(pcard))
continue;
......@@ -1320,13 +1320,15 @@ int32 field::get_summon_release_olist(card* target, card_set* ex_list, card_set*
return rcount + ex_sum_max;
}
// put the monsters of 1-p affected by EFFECT_EXTRA_RELEASE
void field::get_summon_release_exlist(card* target, card_set* ex_list) {
void field::get_summon_release_exlist(card* target, card_set* ex_list, group* mg) {
uint8 p = target->current.controler;
card* pcard;
uint32 rcount = 0;
for(int i = 0; i < 5; ++i) {
pcard = player[1 - p].list_mzone[i];
if(!pcard || pcard->is_releasable_by_summon(p, target))
if(!(pcard && pcard->is_releasable_by_summon(p, target)))
continue;
if(mg && !mg->has_card(pcard))
continue;
if(pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)) {
ex_list->insert(pcard);
......@@ -2217,24 +2219,33 @@ int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32
pduel->restore_assumes();
return FALSE;
}
int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 toplayer) {
int32 fcount = get_useable_count(toplayer, LOCATION_MZONE, toplayer, LOCATION_REASON_TOFIELD);
if(max <= -fcount)
// check if the # of tributes and the usable count are enough when releasing rcount tributes
int32 field::check_tribute(card* pcard, int32 rcount, group* mg, uint8 toplayer) {
card_set test, exset;
int32 m1 = 0, m2 = 0, self_max = 0;
if(toplayer == pcard->current.controler) {
m1 = get_summon_release_slist(pcard, &test, mg);
m2 = get_summon_release_olist(pcard, NULL, NULL, mg, 0);
get_summon_release_exlist(pcard, &exset, mg);
self_max = rcount - (int32)exset.size();
if(self_max < 0)
self_max = 0;
}
else {
m1 = get_summon_release_olist(pcard, &test, NULL, mg, 1);
m2 = get_summon_release_slist(pcard, NULL, mg);
self_max = rcount;
}
// check if the # of tributes is enough
if(m1 + m2 < rcount)
return FALSE;
if(min < -fcount + 1)
min = -fcount + 1;
if(min == 0)
return TRUE;
card_set release_list;
uint32 ex = FALSE;
if(pcard->current.controler != toplayer)
ex = TRUE;
int32 m = get_summon_release_list(pcard, &release_list, 0, 0, mg, ex);
if((int32)release_list.size() < -fcount + 1)
// check if the usable count is enough
int32 fcount = pduel->game_field->get_useable_count(toplayer, LOCATION_MZONE, pcard->current.controler, LOCATION_REASON_TOFIELD);
if(self_max > (int32)test.size())
self_max = (int32)test.size();
if(fcount + self_max - 1 < 0)
return FALSE;
if(m >= min)
return TRUE;
return FALSE;
}
int32 field::check_with_sum_limit(const card_vector& mats, int32 acc, int32 index, int32 count, int32 min, int32 max) {
if(count > max)
......
......@@ -366,7 +366,7 @@ public:
int32 get_summon_release_list(card* target, card_set* release_list, card_set* ex_list, card_set* ex_list_sum, group* mg = NULL, uint32 ex = 0);
int32 get_summon_release_slist(card* target, card_set* release_list, group* mg = NULL);
int32 get_summon_release_olist(card* target, card_set* ex_list, card_set* ex_list_sum, group* mg = NULL, uint32 ex = 0);
void get_summon_release_exlist(card* target, card_set* ex_list);
void get_summon_release_exlist(card* target, card_set* ex_list, group* mg = NULL);
int32 get_summon_count_limit(uint8 playerid);
int32 get_draw_count(uint8 playerid);
void get_ritual_material(uint8 playerid, effect* peffect, card_set* material);
......@@ -400,7 +400,7 @@ public:
void attack_all_target_check();
int32 check_synchro_material(card* pcard, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg);
int32 check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg);
int32 check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 toplayer);
int32 check_tribute(card* pcard, int32 rcount, group* mg, uint8 toplayer);
static int32 check_with_sum_limit(const card_vector& mats, int32 acc, int32 index, int32 count, int32 min, int32 max);
static int32 check_with_sum_limit_m(const card_vector& mats, int32 acc, int32 index, int32 min, int32 max, int32 must_count);
static int32 check_with_sum_greater_limit(const card_vector& mats, int32 acc, int32 index, int32 opmin);
......
......@@ -2018,20 +2018,17 @@ int32 scriptlib::duel_check_tribute(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* target = *(card**) lua_touserdata(L, 1);
uint32 min = lua_tointeger(L, 2);
uint32 max = min;
if(lua_gettop(L) >= 3 && !lua_isnil(L, 3))
max = lua_tointeger(L, 3);
group* mg = 0;
if(lua_gettop(L) >= 4 && !lua_isnil(L, 4)) {
check_param(L, PARAM_TYPE_GROUP, 4);
mg = *(group**) lua_touserdata(L, 4);
uint32 rcount = lua_tointeger(L, 2);
group* mg = NULL;
if(lua_gettop(L) >= 3 && !lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_GROUP, 3);
mg = *(group**) lua_touserdata(L, 3);
}
uint8 toplayer = target->current.controler;
if(lua_gettop(L) >= 5 && !lua_isnil(L, 5))
toplayer = lua_tointeger(L, 5);
if(lua_gettop(L) >= 4 && !lua_isnil(L, 4))
toplayer = lua_tointeger(L, 4);
duel* pduel = target->pduel;
lua_pushboolean(L, pduel->game_field->check_tribute(target, min, max, mg, toplayer));
lua_pushboolean(L, pduel->game_field->check_tribute(target, rcount, mg, toplayer));
return 1;
}
int32 scriptlib::duel_select_tribute(lua_State *L) {
......
......@@ -1350,10 +1350,10 @@ int32 field::summon(uint16 step, uint8 sumplayer, card * target, effect * proc,
return FALSE;
}
effect_set eset;
int32 res = target->filter_summon_procedure(sumplayer, &eset, ignore_count, min_tribute);
target->filter_summon_procedure(sumplayer, &eset, ignore_count, min_tribute);
core.select_effects.clear();
core.select_options.clear();
if(res >= 0) {
if(target->check_ordinary_procedure(sumplayer, min_tribute, true)) {
core.select_effects.push_back(0);
core.select_options.push_back(1);
}
......@@ -1848,10 +1848,10 @@ int32 field::mset(uint16 step, uint8 setplayer, card * target, effect * proc, ui
return FALSE;
}
effect_set eset;
int32 res = target->filter_set_procedure(setplayer, &eset, ignore_count, min_tribute);
target->filter_set_procedure(setplayer, &eset, ignore_count, min_tribute);
core.select_effects.clear();
core.select_options.clear();
if(res >= 0) {
if(target->check_ordinary_procedure(setplayer, min_tribute, false)) {
core.select_effects.push_back(0);
core.select_options.push_back(1);
}
......
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