Commit 8804e8c6 authored by salix5's avatar salix5

attack target, replay in battle step

removed:
sub_attacker, sub_attack_target: Changing attack target is done by functions
attack_cancelable: It is removed since it will interrupt attack-announce related parts.
Duel.ReplaceAttacker(): No longer used.

EFFECT_RISE_TO_FULL_HEIGHT: It is used by "Rise to Full Height".
EFFECT_ONLY_ATTACK_MONSTER: The opponent monsters can only attack monster X.
EFFECT_ONLY_BE_ATTACKED: The targets of
EFFECT_RISE_TO_FULL_HEIGHT/EFFECT_ONLY_ATTACK_MONSTER.
EFFECT_MUST_ATTACK_MONSTER: If the opponent monsters attack, they can only attack monster X.
EFFECT_MUST_BE_ATTACKED: The targets of EFFECT_MUST_ATTACK_MONSTER.
EFFECT_MUST_ATTACK: The opponent monsters must attack.

Duel.ChangeAttackTarget(): Now it will change the attacker and raise events.
Duel.HintSelection(): Now it will not move cards.

attack_state_count/announce_count:
1. If no target exists, it increases after attack announce.
2. If there are targets, it increases after traget selection.
parent 67d5fc64
......@@ -97,7 +97,7 @@ public:
class attacker_map : public std::unordered_map<uint16, std::pair<card*, uint32> > {
public:
void addcard(card* pcard);
} ;
};
int32 scrtype;
int32 ref_handle;
duel* pduel;
......
......@@ -330,7 +330,7 @@ inline effect_flag operator|(effect_flag flag1, effect_flag flag2)
#define EFFECT_ATTACK_ALL 193
#define EFFECT_EXTRA_ATTACK 194
#define EFFECT_MUST_BE_ATTACKED 195
#define EFFECT_AUTO_BE_ATTACKED 196
#define EFFECT_ONLY_BE_ATTACKED 196
#define EFFECT_ATTACK_DISABLED 197
#define EFFECT_NO_BATTLE_DAMAGE 200
#define EFFECT_AVOID_BATTLE_DAMAGE 201
......@@ -395,6 +395,10 @@ inline effect_flag operator|(effect_flag flag1, effect_flag flag2)
#define EFFECT_HAND_SYNCHRO 339
#define EFFECT_ADD_FUSION_CODE 340
#define EFFECT_ADD_FUSION_SETCODE 341
#define EFFECT_RISE_TO_FULL_HEIGHT 342
#define EFFECT_ONLY_ATTACK_MONSTER 343
#define EFFECT_MUST_ATTACK_MONSTER 344
#define EFFECT_PATRICIAN_OF_DARKNESS 345
#define EVENT_STARTUP 1000
#define EVENT_FLIP 1001
......
......@@ -146,7 +146,7 @@ void field::reload_field_info() {
}
}
// Debug.AddCard() will call this function directly
// check Fusion/S/X monster redirection by the rule
// check Fusion/S/X monster redirection by the rule, set fieldid_r
void field::add_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence) {
if (pcard->current.location != 0)
return;
......@@ -1484,7 +1484,7 @@ int32 field::check_spsummon_once(card* pcard, uint8 playerid) {
auto iter = core.spsummon_once_map[playerid].find(pcard->spsummon_code);
return (iter == core.spsummon_once_map[playerid].end()) || (iter->second == 0);
}
// increase the binary custom counter
void field::check_card_counter(card* pcard, int32 counter_type, int32 playerid) {
auto& counter_map = (counter_type == 1) ? core.summon_counter :
(counter_type == 2) ? core.normalsummon_counter :
......@@ -1649,54 +1649,83 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
uint8 p = pcard->current.controler;
effect* peffect;
card* atarget;
pcard->operation_param = 0;
card_vector* pv = NULL;
int32 atype = 0;
card_vector must_be_attack;
card_vector* pv;
card_vector only_be_attack;
effect_set eset;
pcard->operation_param = 0;
for(uint32 i = 0; i < 5; ++i) {
atarget = player[1 - p].list_mzone[i];
if(atarget && atarget->is_affected_by_effect(EFFECT_MUST_BE_ATTACKED, pcard))
must_be_attack.push_back(atarget);
if(atarget){
if(atarget->is_affected_by_effect(EFFECT_MUST_BE_ATTACKED))
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 atype;
}
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 atype;
}
else if(pcard->is_affected_by_effect(EFFECT_MUST_ATTACK_MONSTER)){
atype = 3;
if(must_be_attack.size())
pv = &must_be_attack;
else
return atype;
}
else{
atype = 4;
pv = &player[1 - p].list_mzone;
}
if(pcard->attack_all_target && (peffect = pcard->is_affected_by_effect(EFFECT_ATTACK_ALL))) {
if(pcard->announced_cards.size()) {
if(must_be_attack.size())
pv = &must_be_attack;
else
pv = &player[1 - p].list_mzone;
if(pcard->battled_cards.size()) {
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
if(!atarget)
continue;
auto it = pcard->announced_cards.find(atarget->fieldid_r);
if(it != pcard->announced_cards.end()) {
pduel->lua->add_param(atarget, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
continue;
auto it = pcard->battled_cards.find(atarget->fieldid_r);
if(it != pcard->battled_cards.end()) {
if(it->second.second >= (uint32)peffect->get_value(atarget))
continue;
}
if(atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
continue;
if(atarget->is_affected_by_effect(EFFECT_CANNOT_BE_BATTLE_TARGET, pcard))
continue;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SELECT_BATTLE_TARGET, atarget))
continue;
pduel->lua->add_param(atarget, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
if(atype == 4 && !atarget->is_capable_be_battle_target(pcard))
continue;
v->push_back(atarget);
}
return must_be_attack.size() ? TRUE : FALSE;
return atype;
}
} else if(!chain_attack) {
uint32 extrac = 0;
if((peffect = pcard->is_affected_by_effect(EFFECT_EXTRA_ATTACK)))
extrac = peffect->get_value(pcard);
if(pcard->announce_count >= extrac + 1)
return FALSE;
} 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))){
v->push_back(core.chain_attack_target);
}
return atype;
}
if(atype <= 3) {
*v = *pv;
return atype;
}
uint32 mcount = 0;
if(must_be_attack.size())
pv = &must_be_attack;
else
pv = &player[1 - p].list_mzone;
for(auto cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
if(!atarget)
......@@ -1708,17 +1737,12 @@ int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack,
continue;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SELECT_BATTLE_TARGET, atarget))
continue;
if(chain_attack && !sub_attack && core.chain_attack_target && atarget != core.chain_attack_target)
continue;
v->push_back(atarget);
}
if(must_be_attack.size())
return TRUE;
if((mcount == 0 || pcard->is_affected_by_effect(EFFECT_DIRECT_ATTACK) || sub_attack)
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK)
&& !(chain_attack && core.chain_attack_target))
if((mcount == 0 || pcard->is_affected_by_effect(EFFECT_DIRECT_ATTACK))
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK))
pcard->operation_param = 1;
return must_be_attack.size() ? TRUE : FALSE;
return atype;
}
void field::attack_all_target_check() {
if(!core.attacker)
......
......@@ -241,15 +241,12 @@ struct processor {
uint8 summon_depth;
uint8 summon_cancelable;
card* attacker;
card* sub_attacker;
card* attack_target;
card* sub_attack_target;
card* limit_tuner;
group* limit_syn;
group* limit_xyz;
int32 limit_xyz_minc;
int32 limit_xyz_maxc;
uint8 attack_cancelable;
uint8 attack_rollback;
uint8 effect_damage_step;
int32 battle_damage[2];
......
......@@ -376,7 +376,6 @@ static const struct luaL_Reg duellib[] = {
{ "ShuffleHand", scriptlib::duel_shuffle_hand },
{ "ShuffleSetCard", scriptlib::duel_shuffle_setcard },
{ "ChangeAttacker", scriptlib::duel_change_attacker },
{ "ReplaceAttacker", scriptlib::duel_replace_attacker },
{ "ChangeAttackTarget", scriptlib::duel_change_attack_target },
{ "ReplaceAttackTarget", scriptlib::duel_replace_attack_target },
{ "CalculateDamage", scriptlib::duel_calculate_damage },
......
......@@ -1166,19 +1166,7 @@ int32 scriptlib::duel_change_attacker(lua_State *L) {
check_param(L, PARAM_TYPE_CARD, 1);
card* target = *(card**) lua_touserdata(L, 1);
duel* pduel = target->pduel;
card* attacker = pduel->game_field->core.attacker;
card* attack_target = pduel->game_field->core.attack_target;
attacker->announce_count++;
attacker->announced_cards.addcard(attack_target);
pduel->game_field->core.sub_attacker = target;
return 0;
}
int32 scriptlib::duel_replace_attacker(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* target = *(card**) lua_touserdata(L, 1);
duel* pduel = target->pduel;
pduel->game_field->core.sub_attacker = target;
pduel->game_field->core.attacker = target;
return 0;
}
int32 scriptlib::duel_change_attack_target(lua_State *L) {
......@@ -1199,10 +1187,23 @@ int32 scriptlib::duel_change_attack_target(lua_State *L) {
return 1;
}
field::card_vector cv;
pduel->game_field->get_attack_target(attacker, &cv, pduel->game_field->core.chain_attack, TRUE);
if(!target && attacker->operation_param
|| target && std::find(cv.begin(), cv.end(), target) != cv.end()) {
pduel->game_field->core.sub_attack_target = target;
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()) {
pduel->game_field->core.attack_target = target;
pduel->game_field->core.attack_rollback = FALSE;
for(uint32 i = 0; i < 5; ++i) {
if(pduel->game_field->player[1 - turnp].list_mzone[i])
pduel->game_field->core.opp_mzone[i] = pduel->game_field->player[1 - turnp].list_mzone[i]->fieldid_r;
else
pduel->game_field->core.opp_mzone[i] = 0;
}
if(target) {
pduel->game_field->raise_single_event(target, 0, EVENT_BE_BATTLE_TARGET, 0, REASON_REPLACE, 0, 1 - turnp, 0);
pduel->game_field->raise_event(target, EVENT_BE_BATTLE_TARGET, 0, REASON_REPLACE, 0, 1 - turnp, 0);
pduel->game_field->process_single_event();
pduel->game_field->process_instant_event();
}
lua_pushboolean(L, 1);
} else
lua_pushboolean(L, 0);
......@@ -2621,8 +2622,6 @@ int32 scriptlib::duel_hint_selection(lua_State *L) {
duel* pduel = pgroup->pduel;
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
card* pcard = *cit;
if(pcard->current.location & 0x30)
pduel->game_field->move_card(pcard->current.controler, pcard, pcard->current.location, 0);
pduel->write_buffer8(MSG_BECOME_TARGET);
pduel->write_buffer8(1);
pduel->write_buffer32(pcard->get_info_location());
......
This diff is collapsed.
......@@ -373,7 +373,6 @@ public:
static int32 duel_shuffle_hand(lua_State *L);
static int32 duel_shuffle_setcard(lua_State *L);
static int32 duel_change_attacker(lua_State *L);
static int32 duel_replace_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);
......
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