Commit 3eac2212 authored by salix5's avatar salix5

fix get_attack_target(), remove ReplaceAttackTarget()

get_attack_target()
classified into 2 categories:
1.attacker=pcard
2.otherwise
The main differences are attack counts and EFFECT_ATTACK_ALL counts.

confirm_attack_target()
Now battle step replay rule will use this function instead.
parent 7058e371
......@@ -1659,19 +1659,18 @@ int32 field::effect_replace_check(uint32 code, const tevent& e) {
}
return FALSE;
}
int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack, bool choose_target) {
int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack) {
uint8 p = pcard->current.controler;
effect* peffect;
card* atarget;
card_vector* pv = NULL;
int32 atype = 0;
card_vector must_be_attack;
card_vector only_be_attack;
effect_set eset;
// find the universal set pv
pcard->operation_param = 0;
for(uint32 i = 0; i < 5; ++i) {
atarget = player[1 - p].list_mzone[i];
card* atarget = player[1 - p].list_mzone[i];
if(atarget){
if(atarget->is_affected_by_effect(EFFECT_MUST_BE_ATTACKED, pcard))
must_be_attack.push_back(atarget);
......@@ -1708,7 +1707,7 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
atype = 4;
pv = &player[1 - p].list_mzone;
}
// extra count
int32 ct1 = 0, ct2 = 0;
int32 tmp = 0;
effect_set exts1, exts2;
......@@ -1725,21 +1724,21 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
if(tmp > ct2)
ct2 = tmp;
}
if(core.attacker == pcard ? pcard->announce_count <= ct1 + 1 : pcard->announce_count < ct1 + 1)
if(pcard != core.attacker){
if(pcard->announce_count < ct1 + 1)
dir = true;
else if(chain_attack && !core.chain_attack_target)
dir = true;
else if(ct2 && (core.attacker == pcard ? pcard->announce_count <= ct2 + 1 : pcard->announce_count < ct2 + 1)
else if(ct2 && pcard->announce_count < ct2 + 1
&& pcard->announced_cards.find(0) == pcard->announced_cards.end() && pcard->battled_cards.find(0) == pcard->battled_cards.end())
dir = false;
else{
// effects with target limit
// The system only check the general case (never attacked player) and approximate solution
if((peffect = pcard->is_affected_by_effect(EFFECT_ATTACK_ALL))
&& pcard->announced_cards.find(0) == pcard->announced_cards.end() && pcard->battled_cards.find(0) == pcard->battled_cards.end()
&& pcard->attack_all_target) {
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
card* atarget = *cit;
if(!atarget)
continue;
// valid target
......@@ -1767,16 +1766,60 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
}
return atype;
}
}
else {
if(pcard->announce_count <= ct1 + 1)
dir = true;
else if(chain_attack && !core.chain_attack_target)
dir = true;
else if(ct2 && pcard->announce_count <= ct2 + 1
&& pcard->announced_cards.find(0) == pcard->announced_cards.end() && pcard->battled_cards.find(0) == pcard->battled_cards.end())
dir = false;
else{
// effects with target limit
if((peffect = pcard->is_affected_by_effect(EFFECT_ATTACK_ALL)) && pcard->attack_all_target) {
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
card* atarget = *cit;
if(!atarget)
continue;
// valid target
pduel->lua->add_param(atarget, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
continue;
// enough effect count
auto it = pcard->announced_cards.find(atarget->fieldid_r);
if(it != pcard->announced_cards.end()
&& (atarget == core.attack_target ? (int32)it->second.second > peffect->get_value(atarget) : (int32)it->second.second >= peffect->get_value(atarget))) {
continue;
}
it = pcard->battled_cards.find(atarget->fieldid_r);
if(it != pcard->battled_cards.end()
&& (atarget == core.attack_target ? (int32)it->second.second > peffect->get_value(atarget) : (int32)it->second.second >= peffect->get_value(atarget))) {
continue;
}
if(atype == 4 && !atarget->is_capable_be_battle_target(pcard))
continue;
v->push_back(atarget);
}
}
if(chain_attack && core.chain_attack_target
&& std::find(pv->begin(), pv->end(), core.chain_attack_target) != pv->end()
&& (atype != 4 || core.chain_attack_target->is_capable_be_battle_target(pcard))) {
v->push_back(core.chain_attack_target);
}
return atype;
}
}
if(atype <= 3) {
*v = *pv;
return atype;
}
// For atype=4(normal), check all cards in pv.
uint32 mcount = 0;
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
card* atarget = *cit;
if(!atarget)
continue;
if(choose_target){
if(atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
continue;
mcount++;
......@@ -1786,17 +1829,124 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
continue;
v->push_back(atarget);
}
else {
if(!atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
mcount++;
v->push_back(atarget);
}
}
if((mcount == 0 || pcard->is_affected_by_effect(EFFECT_DIRECT_ATTACK) || core.attack_player)
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK) && dir)
pcard->operation_param = 1;
return atype;
}
// return: core.attack_target is valid or not
bool field::confirm_attack_target() {
card* pcard = core.attacker;
uint8 p = pcard->current.controler;
effect* peffect;
card_vector* pv = NULL;
int32 atype = 0;
card_vector must_be_attack;
card_vector only_be_attack;
effect_set eset;
// find the universal set
for(uint32 i = 0; i < 5; ++i) {
card* atarget = player[1 - p].list_mzone[i];
if(atarget){
if(atarget->is_affected_by_effect(EFFECT_MUST_BE_ATTACKED, pcard))
must_be_attack.push_back(atarget);
if(atarget->is_affected_by_effect(EFFECT_ONLY_BE_ATTACKED))
only_be_attack.push_back(atarget);
}
}
pcard->filter_effect(EFFECT_RISE_TO_FULL_HEIGHT, &eset);
if(eset.size()){
atype = 1;
std::set<uint32> idset;
for(int32 i = 0; i < eset.size(); ++i)
idset.insert(eset[i]->label);
if(idset.size()==1 && only_be_attack.size() == 1 && only_be_attack.front()->fieldid_r == *idset.begin())
pv = &only_be_attack;
else
return false;
}
else if(pcard->is_affected_by_effect(EFFECT_ONLY_ATTACK_MONSTER)){
atype = 2;
if(only_be_attack.size() == 1)
pv = &only_be_attack;
else
return false;
}
else if(pcard->is_affected_by_effect(EFFECT_MUST_ATTACK_MONSTER)){
atype = 3;
if(must_be_attack.size())
pv = &must_be_attack;
else
return false;
}
else{
atype = 4;
pv = &player[1 - p].list_mzone;
}
// extra count
int32 ct1 = 0, ct2 = 0;
int32 tmp = 0;
effect_set exts1, exts2;
bool dir = true;
pcard->filter_effect(EFFECT_EXTRA_ATTACK, &exts1);
for(int32 i = 0; i < exts1.size(); ++i){
tmp = exts1[i]->get_value(pcard);
if(tmp > ct1)
ct1 = tmp;
}
pcard->filter_effect(EFFECT_EXTRA_ATTACK_MONSTER, &exts2);
for(int32 i = 0; i < exts2.size(); ++i){
tmp = exts2[i]->get_value(pcard);
if(tmp > ct2)
ct2 = tmp;
}
if(pcard->announce_count <= ct1 + 1)
dir = true;
else if(core.chain_attack && !core.chain_attack_target)
dir = true;
else if(ct2 && pcard->announce_count <= ct2 + 1
&& pcard->announced_cards.find(0) == pcard->announced_cards.end() && pcard->battled_cards.find(0) == pcard->battled_cards.end())
dir = false;
else{
// effects with target limit
if((peffect = pcard->is_affected_by_effect(EFFECT_ATTACK_ALL)) && pcard->attack_all_target && core.attack_target) {
// valid target
pduel->lua->add_param(core.attack_target, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
return false;
// enough effect count
auto it = pcard->announced_cards.find(core.attack_target->fieldid_r);
if(it != pcard->announced_cards.end() && (int32)it->second.second > peffect->get_value(core.attack_target)) {
return false;
}
it = pcard->battled_cards.find(core.attack_target->fieldid_r);
if(it != pcard->battled_cards.end() && (int32)it->second.second > peffect->get_value(core.attack_target)) {
return false;
}
return true;
}
if(core.chain_attack && core.chain_attack_target && core.chain_attack_target == core.attack_target) {
return true;
}
return false;
}
uint32 mcount = 0;
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
card* atarget = *cit;
if(!atarget)
continue;
if(atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
continue;
mcount++;
}
if(core.attack_target)
return std::find(pv->begin(), pv->end(), core.attack_target) != pv->end();
else
return (mcount == 0 || pcard->is_affected_by_effect(EFFECT_DIRECT_ATTACK) || core.attack_player)
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK) && dir;
}
// update the validity for EFFECT_ATTACK_ALL (approximate solution)
void field::attack_all_target_check() {
if(!core.attacker)
return;
......
......@@ -385,7 +385,8 @@ public:
uint32 get_field_counter(uint8 self, uint8 s, uint8 o, uint16 countertype);
int32 effect_replace_check(uint32 code, const tevent& e);
int32 get_attack_target(card* pcard, card_vector* v, uint8 chain_attack = FALSE, bool choose_target = true);
int32 get_attack_target(card* pcard, card_vector* v, uint8 chain_attack = FALSE);
bool confirm_attack_target();
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);
......
......@@ -380,7 +380,6 @@ static const struct luaL_Reg duellib[] = {
{ "ShuffleSetCard", scriptlib::duel_shuffle_setcard },
{ "ChangeAttacker", scriptlib::duel_change_attacker },
{ "ChangeAttackTarget", scriptlib::duel_change_attack_target },
{ "ReplaceAttackTarget", scriptlib::duel_replace_attack_target },
{ "CalculateDamage", scriptlib::duel_calculate_damage },
{ "GetBattleDamage", scriptlib::duel_get_battle_damage },
{ "ChangeBattleDamage", scriptlib::duel_change_battle_damage },
......
......@@ -2222,7 +2222,10 @@ int32 scriptlib::card_get_attackable_target(lua_State *L) {
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
field::card_vector targets;
pduel->game_field->get_attack_target(pcard, &targets);
uint8 chain_attack = FALSE;
if(pduel->game_field->core.chain_attacker_id == pcard->fieldid)
chain_attack = TRUE;
pduel->game_field->get_attack_target(pcard, &targets, chain_attack);
group* newgroup = pduel->new_group();
newgroup->container.insert(targets.begin(), targets.end());
interpreter::group2value(L, newgroup);
......
......@@ -1239,9 +1239,6 @@ int32 scriptlib::duel_change_attack_target(lua_State *L) {
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::duel_replace_attack_target(lua_State *L) {
return 0;
}
int32 scriptlib::duel_calculate_damage(lua_State *L) {
check_action_permission(L);
check_param_count(L, 2);
......
......@@ -2912,7 +2912,6 @@ int32 field::process_battle_command(uint16 step) {
return FALSE;
}
case 3: {
//Filter Targers
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->fieldid_r != core.pre_field[0]) {
core.chain_attack = FALSE;
core.units.begin()->step = -1;
......@@ -3103,11 +3102,7 @@ int32 field::process_battle_command(uint16 step) {
adjust_all();
return FALSE;
}
core.select_cards.clear();
auto atype = get_attack_target(core.attacker, &core.select_cards, core.chain_attack, false);
if(!core.attack_target && !core.attacker->operation_param
|| core.attack_target && atype <= 3
&& std::find(core.select_cards.begin(), core.select_cards.end(), core.attack_target) == core.select_cards.end())
if(!confirm_attack_target())
rollback = true;
// go to damage step
if(!rollback) {
......
......@@ -377,7 +377,6 @@ public:
static int32 duel_shuffle_setcard(lua_State *L);
static int32 duel_change_attacker(lua_State *L);
static int32 duel_change_attack_target(lua_State *L);
static int32 duel_replace_attack_target(lua_State *L);
static int32 duel_calculate_damage(lua_State *L);
static int32 duel_get_battle_damage(lua_State *L);
static int32 duel_change_battle_damage(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