Commit 60b891ab authored by salix5's avatar salix5

get_attack_target()

check:
1. EFFECT_EXTRA_ATTACK
2. chain attack
3. EFFECT_EXTRA_ATTACK_MONSTER
4. effects with target limit(chain attack with a target,
EFFECT_ATTACK_ALL)

http://www.db.yugioh-card.com/yugiohdb/faq_search.action?ope=5&fid=14710&keyword=&tag=-1
Now the system uses field id instead of real field id.

http://www.db.yugioh-card.com/yugiohdb/faq_search.action?ope=5&fid=15829&keyword=&tag=-1
Now Duel.ChangeAttackTarget() cannot change the attack of monsters with
EFFECT_CANNOT_DIRECT_ATTACK into direct attack.
parent 1f68d428
......@@ -399,6 +399,7 @@ inline effect_flag operator|(effect_flag flag1, effect_flag flag2)
#define EFFECT_ONLY_ATTACK_MONSTER 343
#define EFFECT_MUST_ATTACK_MONSTER 344
#define EFFECT_PATRICIAN_OF_DARKNESS 345
#define EFFECT_EXTRA_ATTACK_MONSTER 346
#define EVENT_STARTUP 1000
#define EVENT_FLIP 1001
......
......@@ -1694,34 +1694,60 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack)
atype = 4;
pv = &player[1 - p].list_mzone;
}
// The system only check the general case (never attacked player), and the script should check specific condition.
if(pcard->announced_cards.size() && (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()) {
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
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() && (int32)it->second.second >= peffect->get_value(atarget)) {
continue;
}
it = pcard->battled_cards.find(atarget->fieldid_r);
if(it != pcard->battled_cards.end() && (int32)it->second.second >= peffect->get_value(atarget)) {
continue;
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(core.attacker == pcard ? pcard->announce_count <= ct1 + 1 : 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)
&& 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 the script should check specific condition.
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()) {
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
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() && (int32)it->second.second >= peffect->get_value(atarget)) {
continue;
}
it = pcard->battled_cards.find(atarget->fieldid_r);
if(it != pcard->battled_cards.end() && (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(atype == 4 && !atarget->is_capable_be_battle_target(pcard))
continue;
v->push_back(atarget);
}
return atype;
} else if(chain_attack && core.chain_attack_target) {
if(std::find(pv->begin(), pv->end(), core.chain_attack_target) != pv->end()
&& (atype != 4 || core.chain_attack_target->is_capable_be_battle_target(pcard))){
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;
......@@ -1745,7 +1771,7 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack)
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))
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK) && dir)
pcard->operation_param = 1;
return atype;
}
......
......@@ -262,6 +262,7 @@ struct processor {
uint8 to_ep;
uint8 skip_m2;
uint8 chain_attack;
uint32 chain_attacker_id;
card* chain_attack_target;
uint8 attack_player;
uint8 selfdes_disabled;
......
......@@ -1200,7 +1200,8 @@ int32 scriptlib::duel_change_attack_target(lua_State *L) {
field::card_vector cv;
pduel->game_field->get_attack_target(attacker, &cv, pduel->game_field->core.chain_attack);
auto turnp=pduel->game_field->infos.turn_player;
if(!target || std::find(cv.begin(), cv.end(), target) != cv.end()) {
if(target && std::find(cv.begin(), cv.end(), target) != cv.end()
|| !target && !attacker->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK)) {
pduel->game_field->core.attack_target = target;
pduel->game_field->core.attack_rollback = FALSE;
for(uint32 i = 0; i < 5; ++i) {
......@@ -1590,6 +1591,7 @@ int32 scriptlib::duel_disable_attack(lua_State *L) {
int32 scriptlib::duel_chain_attack(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
pduel->game_field->core.chain_attack = TRUE;
pduel->game_field->core.chain_attacker_id = pduel->game_field->core.attacker->fieldid;
if(lua_gettop(L) > 0) {
check_param(L, PARAM_TYPE_CARD, 1);
pduel->game_field->core.chain_attack_target = *(card**) lua_touserdata(L, 1);
......
......@@ -2745,8 +2745,10 @@ int32 field::process_battle_command(uint16 step) {
core.select_chains.clear();
chain newchain;
nil_event.event_code = EVENT_FREE_CHAIN;
if(!core.chain_attack)
if(!core.chain_attack) {
core.chain_attacker_id = 0;
core.chain_attack_target = 0;
}
core.attack_player = FALSE;
core.attacker = 0;
core.attack_target = 0;
......@@ -2795,23 +2797,8 @@ int32 field::process_battle_command(uint16 step) {
if(!pcard->is_capable_attack_announce(infos.turn_player))
continue;
uint8 chain_attack = FALSE;
if(core.chain_attack && core.pre_field[0] == pcard->fieldid_r)
if(core.chain_attack && core.chain_attacker_id == pcard->fieldid)
chain_attack = TRUE;
// attack counts
int32 extrac = 0;
int32 tmp = 0;
effect_set exts;
pcard->filter_effect(EFFECT_EXTRA_ATTACK, &exts);
for(int32 i = 0; i < exts.size(); ++i){
tmp = exts[i]->get_value(pcard);
if(tmp > extrac)
extrac = tmp;
}
if(!(pcard->announced_cards.size() && 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())
&& !chain_attack
&& pcard->announce_count >= extrac + 1)
continue;
core.select_cards.clear();
get_attack_target(pcard, &core.select_cards, chain_attack);
if(core.select_cards.size() == 0 && pcard->operation_param == 0)
......@@ -2866,13 +2853,16 @@ int32 field::process_battle_command(uint16 step) {
} else if(ctype == 1) {
core.units.begin()->step = 2;
card* attacker = core.attackable_cards[sel];
if(core.chain_attack && core.pre_field[0] != attacker->fieldid_r) {
if(core.chain_attack && core.chain_attacker_id != attacker->fieldid) {
core.chain_attack = FALSE;
core.chain_attacker_id = 0;
}
core.attacker = attacker;
core.attacker->set_status(STATUS_ATTACK_CANCELED, FALSE);
core.pre_field[0] = core.attacker->fieldid_r;
core.phase_action = TRUE;
core.attack_state_count[infos.turn_player]++;
core.attacker->announce_count++;
effect_set eset;
filter_player_effect(infos.turn_player, EFFECT_ATTACK_COST, &eset, FALSE);
core.attacker->filter_effect(EFFECT_ATTACK_COST, &eset);
......@@ -2944,11 +2934,6 @@ int32 field::process_battle_command(uint16 step) {
}
// no target
if(core.select_cards.size() == 0) {
if(!core.units.begin()->arg1) {
core.attack_state_count[infos.turn_player]++;
core.attacker->announce_count++;
core.attacker->announced_cards.addcard(0);
}
core.chain_attack = FALSE;
core.units.begin()->step = -1;
return FALSE;
......@@ -2997,11 +2982,8 @@ int32 field::process_battle_command(uint16 step) {
core.pre_field[1] = core.attack_target->fieldid_r;
else
core.pre_field[1] = 0;
if(!core.units.begin()->arg1) {
core.attack_state_count[infos.turn_player]++;
core.attacker->announce_count++;
if(!core.units.begin()->arg1)
core.attacker->announced_cards.addcard(core.attack_target);
}
return FALSE;
}
case 7: {
......@@ -3104,7 +3086,7 @@ int32 field::process_battle_command(uint16 step) {
core.chain_attack = FALSE;
if(core.attacker->fieldid_r == afid) {
attack_all_target_check();
if(!core.attacker->is_status(STATUS_ATTACK_CANCELED)) {
if(!atk_disabled) {
core.attacker->attacked_cards.addcard(core.attack_target);
}
}
......@@ -3278,6 +3260,7 @@ int32 field::process_battle_command(uint16 step) {
return FALSE;
}
case 26: {
// Duel.CalculateDamage() goes here
uint32 aa = core.attacker->get_attack(), ad = core.attacker->get_defence();
uint32 da = 0, dd = 0;
uint8 pa = core.attacker->current.controler, pd;
......
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