Commit 4bb2465e authored by mercury233's avatar mercury233
parents 3fc1ec0d 8e4e8bac
......@@ -76,6 +76,7 @@ card::card(duel* pd) {
spsummon_counter[0] = spsummon_counter[1] = 0;
spsummon_counter_rst[0] = spsummon_counter_rst[1] = 0;
unique_code = 0;
unique_fieldid = 0;
assume_type = 0;
assume_value = 0;
spsummon_code = 0;
......@@ -2289,18 +2290,42 @@ int32 card::check_fusion_substitute(card* fcard) {
return TRUE;
return FALSE;
}
int32 card::is_equipable(card* pcard) {
effect_set eset;
if(this == pcard || pcard->current.location != LOCATION_MZONE)
return FALSE;
filter_effect(EFFECT_EQUIP_LIMIT, &eset);
if(eset.size() == 0)
int32 card::check_unique_code(card* pcard) {
if(!unique_code)
return FALSE;
for(int32 i = 0; i < eset.size(); ++i)
if(eset[i]->get_value(pcard))
return TRUE;
if(unique_code == 1) {
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
return pduel->lua->get_function_value(unique_function, 1);
}
uint32 code1 = pcard->get_code();
uint32 code2 = pcard->get_another_code();
if(code1 == unique_code || (code2 && code2 == unique_code))
return TRUE;
return FALSE;
}
void card::get_unique_target(card_set* cset, int32 controler) {
cset->clear();
for(int32 p = 0; p < 2; ++p) {
if(!unique_pos[p])
continue;
const auto& player = pduel->game_field->player[controler ^ p];
if(unique_location & LOCATION_MZONE) {
for(int32 i = 0; i < 5; ++i) {
card* pcard = player.list_mzone[i];
if(pcard && pcard->is_position(POS_FACEUP) && !pcard->is_status(STATUS_BATTLE_DESTROYED)
&& check_unique_code(pcard))
cset->insert(pcard);
}
}
if(unique_location & LOCATION_SZONE) {
for(int32 i = 0; i < 8; ++i) {
card* pcard = player.list_szone[i];
if(pcard && pcard->is_position(POS_FACEUP) && check_unique_code(pcard))
cset->insert(pcard);
}
}
}
}
// check if this is a normal summonable card
int32 card::is_summonable_card() {
if(!(data.type & TYPE_MONSTER))
......
......@@ -126,15 +126,16 @@ public:
uint16 turnid;
uint16 turn_counter;
uint8 unique_pos[2];
uint16 unique_uid;
uint32 unique_fieldid;
uint32 unique_code;
uint32 unique_location;
int32 unique_function;
effect* unique_effect;
uint32 spsummon_code;
uint16 spsummon_counter[2];
uint16 spsummon_counter_rst[2];
uint8 assume_type;
uint32 assume_value;
effect* unique_effect;
card* equiping_target;
card* pre_equip_target;
card* overlay_target;
......@@ -247,7 +248,8 @@ public:
void fusion_select(uint8 playerid, group* fusion_m, card* cg, uint32 chkf);
int32 check_fusion_substitute(card* fcard);
int32 is_equipable(card* pcard);
int32 check_unique_code(card* pcard);
void get_unique_target(card_set* cset, int32 controler);
int32 is_summonable_card();
int32 is_fusion_summonable_card(uint32 summon_type);
int32 is_spsummonable(effect* peffect);
......
......@@ -1477,15 +1477,55 @@ void field::adjust_disable_check_list() {
}
} while(effects.disable_check_list.size());
}
// adjust check_unique_onfield(), EFFECT_SELF_DESTROY, EFFECT_SELF_TOGRAVE
// adjust SetUniqueOnField(), EFFECT_SELF_DESTROY, EFFECT_SELF_TOGRAVE
void field::adjust_self_destroy_set() {
if(core.selfdes_disabled || !core.self_destroy_set.empty() || !core.self_tograve_set.empty())
if(core.selfdes_disabled || !core.unique_destroy_set.empty() || !core.self_destroy_set.empty() || !core.self_tograve_set.empty())
return;
core.unique_destroy_set.clear();
card_set cset;
int32 p = infos.turn_player;
for(int32 p1 = 0; p1 < 2; ++p1) {
for(auto iter = core.unique_cards[p].begin(); iter != core.unique_cards[p].end(); ++iter) {
card* ucard = *iter;
if(ucard->is_position(POS_FACEUP) && ucard->get_status(STATUS_EFFECT_ENABLED)
&& !ucard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN)) {
ucard->get_unique_target(&cset, p);
if(cset.size() == 0)
ucard->unique_fieldid = 0;
else if(cset.size() == 1) {
auto cit = cset.begin();
ucard->unique_fieldid = (*cit)->fieldid;
} else {
card* mcard = 0;
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
if(ucard->unique_fieldid == pcard->fieldid) {
mcard = pcard;
break;
}
if(!mcard || pcard->fieldid < mcard->fieldid)
mcard = pcard;
}
ucard->unique_fieldid = mcard->fieldid;
cset.erase(mcard);
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
core.unique_destroy_set.insert(pcard);
pcard->temp.reason_effect = pcard->current.reason_effect;
pcard->temp.reason_player = pcard->current.reason_player;
pcard->current.reason_effect = ucard->unique_effect;
pcard->current.reason_player = ucard->current.controler;
}
}
}
}
p = 1 - p;
}
cset.clear();
for(uint8 p = 0; p < 2; ++p) {
for(uint8 i = 0; i < 5; ++i) {
card* pcard = player[p].list_mzone[i];
if(pcard && pcard->is_position(POS_FACEUP))
if(pcard && pcard->is_position(POS_FACEUP) && !pcard->is_status(STATUS_BATTLE_DESTROYED))
cset.insert(pcard);
}
for(uint8 i = 0; i < 8; ++i) {
......@@ -1496,11 +1536,10 @@ void field::adjust_self_destroy_set() {
}
core.self_destroy_set.clear();
core.self_tograve_set.clear();
effect* peffect;
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
if((peffect = check_unique_onfield(pcard, pcard->current.controler, pcard->current.location))
|| (peffect = pcard->is_affected_by_effect(EFFECT_SELF_DESTROY)) && !pcard->is_status(STATUS_BATTLE_DESTROYED)) {
effect* peffect = pcard->is_affected_by_effect(EFFECT_SELF_DESTROY);
if(peffect) {
core.self_destroy_set.insert(pcard);
pcard->temp.reason_effect = pcard->current.reason_effect;
pcard->temp.reason_player = pcard->current.reason_player;
......@@ -1511,7 +1550,8 @@ void field::adjust_self_destroy_set() {
if(core.global_flag & GLOBALFLAG_SELF_TOGRAVE) {
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
if(peffect = pcard->is_affected_by_effect(EFFECT_SELF_TOGRAVE)) {
effect* peffect = pcard->is_affected_by_effect(EFFECT_SELF_TOGRAVE);
if(peffect) {
core.self_tograve_set.insert(pcard);
pcard->temp.reason_effect = pcard->current.reason_effect;
pcard->temp.reason_player = pcard->current.reason_player;
......@@ -1520,7 +1560,7 @@ void field::adjust_self_destroy_set() {
}
}
}
if(!core.self_destroy_set.empty() || !core.self_tograve_set.empty())
if(!core.unique_destroy_set.empty() || !core.self_destroy_set.empty() || !core.self_tograve_set.empty())
add_process(PROCESSOR_SELF_DESTROY, 0, 0, 0, 0, 0);
}
void field::add_unique_card(card* pcard) {
......@@ -1529,7 +1569,7 @@ void field::add_unique_card(card* pcard) {
core.unique_cards[con].insert(pcard);
if(pcard->unique_pos[1])
core.unique_cards[1 - con].insert(pcard);
pcard->unique_uid = infos.copy_id++;
pcard->unique_fieldid = 0;
}
void field::remove_unique_card(card* pcard) {
......@@ -1543,16 +1583,21 @@ void field::remove_unique_card(card* pcard) {
}
// return: pcard->unique_effect or 0
effect* field::check_unique_onfield(card* pcard, uint8 controler, uint8 location) {
if(!pcard->unique_code)
return 0;
for(auto iter = core.unique_cards[controler].begin(); iter != core.unique_cards[controler].end(); ++iter) {
card* ucard = *iter;
if((ucard != pcard) && ucard->is_position(POS_FACEUP) && ucard->get_status(STATUS_EFFECT_ENABLED)
&& (ucard->unique_code == pcard->unique_code) && (ucard->unique_location & location)
&& (!(pcard->current.location & ucard->unique_location) || pcard->is_position(POS_FACEDOWN)
|| ((!pcard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN) || !ucard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN)) && ucard->unique_uid < pcard->unique_uid)))
return pcard->unique_effect;
&& !ucard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN)
&& ucard->unique_fieldid && ucard->check_unique_code(pcard) && (ucard->unique_location & location))
return ucard->unique_effect;
}
if(!pcard->unique_code || !(pcard->unique_location & location) || pcard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN))
return 0;
card_set cset;
pcard->get_unique_target(&cset, controler);
if(pcard->check_unique_code(pcard))
cset.insert(pcard);
if(cset.size() >= 2)
return pcard->unique_effect;
return 0;
}
......
......@@ -199,6 +199,7 @@ struct processor {
card_set special_summoning;
card_set equiping_cards;
card_set control_adjust_set[2];
card_set unique_destroy_set;
card_set self_destroy_set;
card_set self_tograve_set;
card_set release_cards;
......
......@@ -2346,7 +2346,11 @@ int32 scriptlib::card_set_unique_onfield(lua_State *L) {
card* pcard = *(card**) lua_touserdata(L, 1);
pcard->unique_pos[0] = lua_tointeger(L, 2);
pcard->unique_pos[1] = lua_tointeger(L, 3);
pcard->unique_code = lua_tointeger(L, 4);
if(lua_isfunction(L, 4)) {
pcard->unique_code = 1;
pcard->unique_function = interpreter::get_function_handle(L, 4);
} else
pcard->unique_code = lua_tointeger(L, 4);
uint32 location = LOCATION_ONFIELD;
if(lua_gettop(L) > 4)
location = lua_tointeger(L, 5) & LOCATION_ONFIELD;
......
......@@ -1182,24 +1182,12 @@ int32 field::control_adjust(uint16 step) {
int32 field::self_destroy(uint16 step) {
switch(step) {
case 0: {
if(core.self_destroy_set.empty()) {
core.units.begin()->step = 1;
return FALSE;
}
card_set cset;
for (auto cit = core.self_destroy_set.begin(); cit != core.self_destroy_set.end();) {
auto rm = cit++;
card* pcard = *rm;
if(pcard->current.reason_effect->code == EFFECT_UNIQUE_CHECK) {
cset.insert(pcard);
core.self_destroy_set.erase(rm);
}
}
if(!cset.empty())
destroy(&cset, 0, REASON_RULE, 5);
if(!core.unique_destroy_set.empty())
destroy(&core.unique_destroy_set, 0, REASON_RULE, 5);
return FALSE;
}
case 1: {
core.unique_destroy_set.clear();
core.operated_set.clear();
if(!core.self_destroy_set.empty())
destroy(&core.self_destroy_set, 0, REASON_EFFECT, 5);
......@@ -1235,6 +1223,7 @@ int32 field::equip(uint16 step, uint8 equip_player, card * equip_card, card * ta
if(equip_card == target || target->current.location != LOCATION_MZONE)
return TRUE;
if(equip_card->equiping_target) {
equip_card->cancel_card_target(equip_card->equiping_target);
equip_card->unequip();
equip_card->enable_field_effect(false);
return FALSE;
......
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