Commit ff51e934 authored by mercury233's avatar mercury233
parents ce89e6b1 2044525c
......@@ -3112,6 +3112,8 @@ int32 card::is_special_summonable(uint8 playerid, uint32 summon_type) {
return eset.size();
}
int32 card::is_can_be_special_summoned(effect* reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer, uint8 nocheck, uint8 nolimit, uint32 zone) {
if(reason_effect->get_handler() == this)
reason_effect->status |= EFFECT_STATUS_SPSELF;
if(current.location == LOCATION_MZONE)
return FALSE;
if(current.location == LOCATION_REMOVED && (current.position & POS_FACEDOWN))
......@@ -3361,17 +3363,6 @@ int32 card::is_releasable_by_nonsummon(uint8 playerid) {
int32 card::is_releasable_by_effect(uint8 playerid, effect* peffect) {
if(!peffect)
return TRUE;
if(current.controler != playerid && !is_affected_by_effect(EFFECT_EXTRA_RELEASE)) {
effect_set eset;
filter_effect(EFFECT_EXTRA_RELEASE_NONSUM, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(REASON_EFFECT, PARAM_TYPE_INT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!eset[i]->check_value_condition(3))
return FALSE;
}
}
effect_set eset;
filter_effect(EFFECT_UNRELEASABLE_EFFECT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
......
......@@ -111,6 +111,7 @@ public:
//status
#define EFFECT_STATUS_AVAILABLE 0x0001
//#define EFFECT_STATUS_ACTIVATED 0x0002
#define EFFECT_STATUS_SPSELF 0x0004
#define EFFECT_COUNT_CODE_OATH 0x10000000
#define EFFECT_COUNT_CODE_DUEL 0x20000000
......
......@@ -227,7 +227,7 @@ struct processor {
card_set discarded_set;
card_set destroy_canceled;
card_set delayed_enable_set;
card_set temp_set;
card_set set_group_set;
effect_set_v disfield_effects;
effect_set_v extram_effects;
effect_set_v extras_effects;
......@@ -278,6 +278,8 @@ struct processor {
uint32 copy_reset;
uint8 copy_reset_count;
uint32 last_control_changed_id;
uint32 set_group_used_zones;
uint8 set_group_seq[7];
uint8 dice_result[5];
uint8 coin_result[5];
uint8 to_bp;
......@@ -554,7 +556,7 @@ public:
int32 flip_summon(uint16 step, uint8 sumplayer, card* target);
int32 mset(uint16 step, uint8 setplayer, card* ptarget, effect* proc, uint8 ignore_count, uint8 min_tribute, uint32 zone);
int32 sset(uint16 step, uint8 setplayer, uint8 toplayer, card* ptarget);
int32 sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget);
int32 sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget, uint8 confirm);
int32 special_summon_rule(uint16 step, uint8 sumplayer, card* target, uint32 summon_type);
int32 special_summon_step(uint16 step, group* targets, card* target, uint32 zone);
int32 special_summon(uint16 step, effect* reason_effect, uint8 reason_player, group* targets, uint32 zone);
......
......@@ -377,6 +377,9 @@ int32 scriptlib::duel_sets(lua_State *L) {
toplayer = lua_tointeger(L, 3);
if(toplayer != 0 && toplayer != 1)
toplayer = playerid;
uint32 confirm = TRUE;
if(lua_gettop(L) > 3)
confirm = lua_toboolean(L, 4);
card* pcard = 0;
group* pgroup = 0;
duel* pduel = 0;
......@@ -385,13 +388,20 @@ int32 scriptlib::duel_sets(lua_State *L) {
pduel = pcard->pduel;
} else if(check_param(L, PARAM_TYPE_GROUP, 2, TRUE)) {
pgroup = *(group**) lua_touserdata(L, 2);
pduel = pgroup->pduel;
if(pgroup->container.empty()) {
return 0;
} else if(pgroup->container.size() == 1) {
pcard = *pgroup->container.begin();
pduel = pcard->pduel;
} else {
pduel = pgroup->pduel;
}
} else
luaL_error(L, "Parameter %d should be \"Card\" or \"Group\".", 2);
if(pcard)
pduel->game_field->add_process(PROCESSOR_SSET, 0, 0, (group*)pcard, playerid, toplayer);
else
pduel->game_field->add_process(PROCESSOR_SSET_G, 0, 0, pgroup, playerid, toplayer);
pduel->game_field->add_process(PROCESSOR_SSET_G, 0, 0, pgroup, playerid, toplayer, confirm);
return lua_yield(L, 0);
}
int32 scriptlib::duel_create_token(lua_State *L) {
......@@ -435,9 +445,9 @@ int32 scriptlib::duel_special_summon(lua_State *L) {
if(lua_gettop(L) >= 8)
zone = lua_tointeger(L, 8);
if(pcard) {
pduel->game_field->core.temp_set.clear();
pduel->game_field->core.temp_set.insert(pcard);
pduel->game_field->special_summon(&pduel->game_field->core.temp_set, sumtype, sumplayer, playerid, nocheck, nolimit, positions, zone);
field::card_set cset;
cset.insert(pcard);
pduel->game_field->special_summon(&cset, sumtype, sumplayer, playerid, nocheck, nolimit, positions, zone);
} else
pduel->game_field->special_summon(&(pgroup->container), sumtype, sumplayer, playerid, nocheck, nolimit, positions, zone);
pduel->game_field->core.subunits.back().type = PROCESSOR_SPSUMMON_S;
......@@ -629,9 +639,9 @@ int32 scriptlib::duel_change_form(lua_State *L) {
if(top > 5 && lua_toboolean(L, 6)) flag |= NO_FLIP_EFFECT;
if(top > 6 && lua_toboolean(L, 7)) flag |= FLIP_SET_AVAILABLE;
if(pcard) {
pduel->game_field->core.temp_set.clear();
pduel->game_field->core.temp_set.insert(pcard);
pduel->game_field->change_position(&pduel->game_field->core.temp_set, pduel->game_field->core.reason_effect, pduel->game_field->core.reason_player, au, ad, du, dd, flag, TRUE);
field::card_set cset;
cset.insert(pcard);
pduel->game_field->change_position(&cset, pduel->game_field->core.reason_effect, pduel->game_field->core.reason_player, au, ad, du, dd, flag, TRUE);
} else
pduel->game_field->change_position(&(pgroup->container), pduel->game_field->core.reason_effect, pduel->game_field->core.reason_player, au, ad, du, dd, flag, TRUE);
pduel->game_field->core.subunits.back().type = PROCESSOR_CHANGEPOS_S;
......
......@@ -1425,7 +1425,7 @@ int32 field::equip(uint16 step, uint8 equip_player, card * equip_card, card * ta
cset.insert(equip_card);
raise_single_event(target, &cset, EVENT_EQUIP, core.reason_effect, 0, core.reason_player, PLAYER_NONE, 0);
raise_event(&cset, EVENT_EQUIP, core.reason_effect, 0, core.reason_player, PLAYER_NONE, 0);
core.hint_timing[target->overlay_target ? target->overlay_target->current.controler : target->current.controler] |= TIMING_EQUIP;
core.hint_timing[target->current.controler] |= TIMING_EQUIP;
process_single_event();
process_instant_event();
return FALSE;
......@@ -2358,7 +2358,7 @@ int32 field::sset(uint16 step, uint8 setplayer, uint8 toplayer, card * target) {
}
return TRUE;
}
int32 field::sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget) {
int32 field::sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget, uint8 confirm) {
switch(step) {
case 0: {
card_set* set_cards = new card_set;
......@@ -2379,6 +2379,8 @@ int32 field::sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget
returns.ivalue[0] = 0;
return TRUE;
}
core.set_group_set.clear();
core.set_group_used_zones = 0;
core.phase_action = TRUE;
core.units.begin()->ptarget = (group*)set_cards;
return FALSE;
......@@ -2386,13 +2388,66 @@ int32 field::sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget
case 1: {
card_set* set_cards = (card_set*)ptarget;
card* target = *set_cards->begin();
target->enable_field_effect(false);
move_to_field(target, setplayer, toplayer, LOCATION_SZONE, POS_FACEDOWN, FALSE);
uint32 flag;
int32 ct = get_useable_count(target, toplayer, LOCATION_SZONE, setplayer, LOCATION_REASON_TOFIELD, 0xff, &flag);
if(ct <= 0) {
core.units.begin()->step = 2;
return FALSE;
}
if(target->data.type & TYPE_FIELD) {
returns.bvalue[2] = 5;
return FALSE;
}
flag |= core.set_group_used_zones;
if(setplayer == toplayer) {
flag = ((flag & 0xff) << 8) | 0xffff00ff;
} else {
flag = ((flag & 0xff) << 24) | 0xffffff;
}
flag |= 0xe080e080;
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(setplayer);
pduel->write_buffer32(target->data.code);
add_process(PROCESSOR_SELECT_PLACE, 0, 0, 0, setplayer, flag, 1);
return FALSE;
}
case 2: {
card_set* set_cards = (card_set*)ptarget;
card* target = *set_cards->begin();
uint32 seq = returns.bvalue[2];
core.set_group_seq[core.set_group_set.size()] = seq;
core.set_group_set.insert(target);
core.set_group_used_zones |= (1 << seq);
set_cards->erase(target);
if(!set_cards->empty())
core.units.begin()->step = 0;
else
delete set_cards;
return FALSE;
}
case 3: {
card_set* set_cards = &core.set_group_set;
card* target = *set_cards->begin();
target->enable_field_effect(false);
uint32 zone;
if(target->data.type & TYPE_FIELD) {
zone = 1 << 5;
} else {
for(uint32 i = 0; i < 7; i++) {
zone = 1 << i;
if(core.set_group_used_zones & zone) {
core.set_group_used_zones &= ~zone;
break;
}
}
}
move_to_field(target, setplayer, toplayer, LOCATION_SZONE, POS_FACEDOWN, FALSE, 0, FALSE, zone);
return FALSE;
}
case 4: {
card_set* set_cards = &core.set_group_set;
card* target = *set_cards->begin();
target->set_status(STATUS_SET_TURN, TRUE);
if(target->data.type & TYPE_MONSTER) {
effect* peffect = target->is_affected_by_effect(EFFECT_MONSTER_SSET);
......@@ -2411,12 +2466,47 @@ int32 field::sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget
core.operated_set.insert(target);
set_cards->erase(target);
if(!set_cards->empty())
core.units.begin()->step = 0;
else
delete set_cards;
core.units.begin()->step = 2;
return FALSE;
}
case 3: {
case 5: {
if(confirm) {
pduel->write_buffer8(MSG_CONFIRM_CARDS);
pduel->write_buffer8(toplayer);
pduel->write_buffer8(core.operated_set.size());
for(auto cit = core.operated_set.begin(); cit != core.operated_set.end(); ++cit) {
pduel->write_buffer32((*cit)->data.code);
pduel->write_buffer8((*cit)->current.controler);
pduel->write_buffer8((*cit)->current.location);
pduel->write_buffer8((*cit)->current.sequence);
}
}
return FALSE;
}
case 6: {
uint8 ct = core.operated_set.size();
if(core.set_group_used_zones & (1 << 5))
ct--;
pduel->write_buffer8(MSG_SHUFFLE_SET_CARD);
pduel->write_buffer8(LOCATION_SZONE);
pduel->write_buffer8(ct);
uint8 i = 0;
for(auto cit = core.operated_set.begin(); cit != core.operated_set.end(); ++cit) {
card* pcard = *cit;
uint8 seq = core.set_group_seq[i];
i++;
if(pcard->data.type & TYPE_FIELD)
continue;
pduel->write_buffer32(pcard->get_info_location());
pduel->game_field->player[toplayer].list_szone[seq] = pcard;
pcard->current.sequence = seq;
}
for(uint32 i = 0; i < ct; ++i) {
pduel->write_buffer32(0);
}
return FALSE;
}
case 7: {
returns.ivalue[0] = core.operated_set.size();
adjust_instant();
raise_event(&core.operated_set, EVENT_SSET, 0, 0, setplayer, setplayer, 0);
......@@ -3081,9 +3171,13 @@ int32 field::destroy(uint16 step, group * targets, effect * reason_effect, uint3
for (auto cit = targets->container.begin(); cit != targets->container.end();) {
auto rm = cit++;
card* pcard = *rm;
if(!pcard->is_destructable()) {
indestructable_set.insert(pcard);
continue;
}
if (!(pcard->current.reason & (REASON_RULE | REASON_COST))) {
int32 is_destructable = true;
if (pcard->is_destructable() && pcard->is_affect_by_effect(pcard->current.reason_effect)) {
bool is_destructable = true;
if (pcard->is_affect_by_effect(pcard->current.reason_effect)) {
effect* indestructable_effect = pcard->check_indestructable_by_effect(pcard->current.reason_effect, pcard->current.reason_player);
if (indestructable_effect) {
if(reason_player != 5)
......@@ -3235,7 +3329,7 @@ int32 field::destroy(uint16 step, group * targets, effect * reason_effect, uint3
continue;
}
pcard->current.reason |= REASON_DESTROY;
core.hint_timing[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] |= TIMING_DESTROY;
core.hint_timing[pcard->current.controler] |= TIMING_DESTROY;
raise_single_event(pcard, 0, EVENT_DESTROY, pcard->current.reason_effect, pcard->current.reason, pcard->current.reason_player, 0, 0);
}
adjust_instant();
......@@ -3280,15 +3374,13 @@ int32 field::destroy(uint16 step, group * targets, effect * reason_effect, uint3
for (auto cit = targets->container.begin(); cit != targets->container.end();) {
auto rm = cit++;
card* pcard = *rm;
if (!(pcard->current.reason & REASON_RULE)) {
if (!pcard->is_destructable()) {
pcard->current.reason = pcard->temp.reason;
pcard->current.reason_effect = pcard->temp.reason_effect;
pcard->current.reason_player = pcard->temp.reason_player;
pcard->set_status(STATUS_DESTROY_CONFIRMED, FALSE);
targets->container.erase(pcard);
continue;
}
if (!pcard->is_destructable()) {
pcard->current.reason = pcard->temp.reason;
pcard->current.reason_effect = pcard->temp.reason_effect;
pcard->current.reason_player = pcard->temp.reason_player;
pcard->set_status(STATUS_DESTROY_CONFIRMED, FALSE);
targets->container.erase(pcard);
continue;
}
eset.clear();
pcard->filter_effect(EFFECT_INDESTRUCTABLE, &eset);
......@@ -3774,16 +3866,17 @@ int32 field::send_to(uint16 step, group * targets, effect * reason_effect, uint3
uint8 playerid = pcard->sendto_param.playerid & 0x7;
uint8 dest = pcard->sendto_param.location;
uint8 seq = pcard->sendto_param.sequence;
uint8 control_player = pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler;
if(dest == LOCATION_GRAVE) {
core.hint_timing[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] |= TIMING_TOGRAVE;
core.hint_timing[control_player] |= TIMING_TOGRAVE;
} else if(dest == LOCATION_HAND) {
pcard->set_status(STATUS_PROC_COMPLETE, FALSE);
core.hint_timing[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] |= TIMING_TOHAND;
core.hint_timing[control_player] |= TIMING_TOHAND;
} else if(dest == LOCATION_DECK) {
pcard->set_status(STATUS_PROC_COMPLETE, FALSE);
core.hint_timing[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] |= TIMING_TODECK;
core.hint_timing[control_player] |= TIMING_TODECK;
} else if(dest == LOCATION_REMOVED) {
core.hint_timing[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] |= TIMING_REMOVE;
core.hint_timing[control_player] |= TIMING_REMOVE;
}
//call move_card()
if(pcard->current.controler != playerid || pcard->current.location != dest) {
......@@ -3800,7 +3893,7 @@ int32 field::send_to(uint16 step, group * targets, effect * reason_effect, uint3
pduel->write_buffer32(pcard->current.reason);
}
if((core.deck_reversed && pcard->current.location == LOCATION_DECK) || (pcard->current.position == POS_FACEUP_DEFENSE))
param->show_decktop[pcard->overlay_target ? pcard->overlay_target->current.controler : pcard->current.controler] = true;
param->show_decktop[pcard->current.controler] = true;
pcard->set_status(STATUS_LEAVE_CONFIRMED, FALSE);
if(pcard->status & (STATUS_SUMMON_DISABLED | STATUS_ACTIVATE_DISABLED)) {
pcard->set_status(STATUS_SUMMON_DISABLED | STATUS_ACTIVATE_DISABLED, FALSE);
......@@ -3894,8 +3987,6 @@ int32 field::send_to(uint16 step, group * targets, effect * reason_effect, uint3
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
}
for(auto iter = param->leave.begin(); iter != param->leave.end(); ++iter)
raise_single_event(*iter, 0, EVENT_LEAVE_FIELD, (*iter)->current.reason_effect, (*iter)->current.reason, (*iter)->current.reason_player, 0, 0);
for(auto iter = param->discard.begin(); iter != param->discard.end(); ++iter)
raise_single_event(*iter, 0, EVENT_DISCARD, (*iter)->current.reason_effect, (*iter)->current.reason, (*iter)->current.reason_player, 0, 0);
if((core.global_flag & GLOBALFLAG_DETACH_EVENT) && param->detach.size()) {
......@@ -3905,8 +3996,6 @@ int32 field::send_to(uint16 step, group * targets, effect * reason_effect, uint3
}
}
process_single_event();
if(param->leave.size())
raise_event(&param->leave, EVENT_LEAVE_FIELD, reason_effect, reason, reason_player, 0, 0);
if(param->discard.size())
raise_event(&param->discard, EVENT_DISCARD, reason_effect, reason, reason_player, 0, 0);
if((core.global_flag & GLOBALFLAG_DETACH_EVENT) && param->detach.size())
......@@ -3919,6 +4008,10 @@ int32 field::send_to(uint16 step, group * targets, effect * reason_effect, uint3
exargs* param = (exargs*)targets;
core.units.begin()->ptarget = param->targets;
targets = param->targets;
for(auto iter = param->leave.begin(); iter != param->leave.end(); ++iter)
raise_single_event(*iter, 0, EVENT_LEAVE_FIELD, (*iter)->current.reason_effect, (*iter)->current.reason, (*iter)->current.reason_player, 0, 0);
if(param->leave.size())
raise_event(&param->leave, EVENT_LEAVE_FIELD, reason_effect, reason, reason_player, 0, 0);
delete param;
uint8 nloc;
card_set tohand, todeck, tograve, remove, released, destroyed, retgrave;
......
......@@ -417,7 +417,7 @@ int32 field::process() {
return pduel->bufferlen;
}
case PROCESSOR_SSET_G: {
if (sset_g(it->step, it->arg1, it->arg2, it->ptarget)) {
if (sset_g(it->step, it->arg1, it->arg2, it->ptarget, it->arg3)) {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else
......@@ -2106,7 +2106,8 @@ int32 field::process_quick_effect(int16 step, int32 skip_freechain, uint8 priori
&& peffect->is_chainable(priority) && peffect->is_activateable(priority, clit->evt, TRUE)) {
for(auto cait = core.current_chain.begin(); cait != core.current_chain.end(); ++cait) {
if(cait->triggering_player == priority) {
if(std::any_of(core.new_ochain_h.begin(), core.new_ochain_h.end(), [=](chain ch) { return ch.chain_id == cait->chain_id; })) {
if((peffect->status & EFFECT_STATUS_SPSELF) && (cait->triggering_effect->status & EFFECT_STATUS_SPSELF)
&& std::any_of(core.new_ochain_h.begin(), core.new_ochain_h.end(), [=](chain ch) { return ch.chain_id == cait->chain_id; })) {
act = false;
break;
}
......
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