Commit 1fbf5b26 authored by fallenstardust's avatar fallenstardust

sync ocgcore

parent a88b350e
......@@ -3279,6 +3279,36 @@ int32 card::is_can_be_special_summoned(effect* reason_effect, uint32 sumtype, ui
pduel->game_field->restore_lp_cost();
return TRUE;
}
uint8 card::get_spsummonable_position(effect* reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer) {
uint8 position = 0;
uint8 positions[4] = { POS_FACEUP_ATTACK, POS_FACEDOWN_ATTACK, POS_FACEUP_DEFENSE, POS_FACEDOWN_DEFENSE };
effect_set eset;
for(int32 p = 0; p < 4; ++p) {
bool poscheck = true;
if(!(positions[p] & sumpos))
continue;
if((data.type & (TYPE_TOKEN | TYPE_LINK)) && (positions[p] & POS_FACEDOWN))
continue;
pduel->game_field->filter_player_effect(sumplayer, EFFECT_CANNOT_SPECIAL_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
continue;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(sumplayer, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
pduel->lua->add_param(positions[p], PARAM_TYPE_INT);
pduel->lua->add_param(toplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason_effect, PARAM_TYPE_EFFECT);
if(pduel->lua->check_condition(eset[i]->target, 7))
poscheck = false;
}
eset.clear();
if(poscheck)
position |= positions[p];
}
return position;
}
int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute, uint32 zone) {
if(!is_summonable_card())
return FALSE;
......
......@@ -346,6 +346,7 @@ public:
int32 is_can_be_flip_summoned(uint8 playerid);
int32 is_special_summonable(uint8 playerid, uint32 summon_type, material_info info = null_info);
int32 is_can_be_special_summoned(effect* reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer, uint8 nocheck, uint8 nolimit, uint32 zone);
uint8 get_spsummonable_position(effect* reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer);
int32 is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute, uint32 zone = 0x1f);
int32 is_setable_szone(uint8 playerid, uint8 ignore_fd = 0);
int32 is_affect_by_effect(effect* reason_effect);
......
......@@ -201,7 +201,7 @@ enum effect_flag : uint32 {
EFFECT_FLAG_IMMEDIATELY_APPLY = 0x80000000,
};
enum effect_flag2 : uint32 {
EFFECT_FLAG2_MILLENNIUM_RESTRICT = 0x0001,
// EFFECT_FLAG2_MILLENNIUM_RESTRICT = 0x0001,
EFFECT_FLAG2_COF = 0x0002,
EFFECT_FLAG2_WICKED = 0x0004,
EFFECT_FLAG2_OPTION = 0x0008,
......
......@@ -1824,6 +1824,9 @@ int32 field::get_summon_count_limit(uint8 playerid) {
return count;
}
int32 field::get_draw_count(uint8 playerid) {
if ((core.duel_rule >= 3) && (infos.turn_id == 1) && (infos.turn_player == playerid)) {
return 0;
}
effect_set eset;
filter_player_effect(playerid, EFFECT_DRAW_COUNT, &eset);
int32 count = player[playerid].draw_count;
......@@ -3069,7 +3072,8 @@ int32 field::is_player_can_spsummon(effect* reason_effect, uint32 sumtype, uint8
return FALSE;
if(pcard->data.type & TYPE_LINK)
sumpos &= POS_FACEUP_ATTACK;
if(sumpos == 0)
uint8 position = pcard->get_spsummonable_position(reason_effect, sumtype, sumpos, playerid, toplayer);
if(position == 0)
return FALSE;
sumtype |= SUMMON_TYPE_SPECIAL;
save_lp_cost();
......@@ -3078,8 +3082,8 @@ int32 field::is_player_can_spsummon(effect* reason_effect, uint32 sumtype, uint8
return FALSE;
}
restore_lp_cost();
if(sumpos & POS_FACEDOWN && is_player_affected_by_effect(playerid, EFFECT_DIVINE_LIGHT))
sumpos = (sumpos & POS_FACEUP) | ((sumpos & POS_FACEDOWN) >> 1);
if(position & POS_FACEDOWN && is_player_affected_by_effect(playerid, EFFECT_DIVINE_LIGHT))
position = (position & POS_FACEUP) | ((position & POS_FACEDOWN) >> 1);
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_SPECIAL_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
......@@ -3089,7 +3093,7 @@ int32 field::is_player_can_spsummon(effect* reason_effect, uint32 sumtype, uint8
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
pduel->lua->add_param(sumpos, PARAM_TYPE_INT);
pduel->lua->add_param(position, PARAM_TYPE_INT);
pduel->lua->add_param(toplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason_effect, PARAM_TYPE_EFFECT);
if (pduel->lua->check_condition(eset[i]->target, 7))
......@@ -3377,8 +3381,9 @@ int32 field::get_cteffect(effect* peffect, int32 playerid, int32 store) {
continue;
uint32 code = efit.first;
if(code == EVENT_FREE_CHAIN || code == EVENT_PHASE + infos.phase) {
nil_event.event_code = code;
if(get_cteffect_evt(feffect, playerid, nil_event, store) && !store)
tevent test_event;
test_event.event_code = code;
if(get_cteffect_evt(feffect, playerid, test_event, store) && !store)
return TRUE;
} else {
for(const auto& ev : core.point_event) {
......@@ -3427,8 +3432,9 @@ int32 field::check_cteffect_hint(effect* peffect, uint8 playerid) {
continue;
uint32 code = efit.first;
if(code == EVENT_FREE_CHAIN || code == EVENT_PHASE + infos.phase) {
nil_event.event_code = code;
if(get_cteffect_evt(feffect, playerid, nil_event, FALSE)
tevent test_event;
test_event.event_code = code;
if(get_cteffect_evt(feffect, playerid, test_event, FALSE)
&& (code != EVENT_FREE_CHAIN || check_hint_timing(feffect)))
return TRUE;
} else {
......
......@@ -2747,11 +2747,12 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin
else
targetplayer = 1 - sumplayer;
}
if(positions == 0)
positions = POS_FACEUP_ATTACK;
std::vector<int32> retval;
peffect->get_value(target, 0, &retval);
uint32 summon_info = retval.size() > 0 ? retval[0] : 0;
positions = target->get_spsummonable_position(peffect, ((summon_info & 0xf00ffff) | SUMMON_TYPE_SPECIAL), positions, sumplayer, targetplayer);
if(positions == 0)
positions = POS_FACEUP_ATTACK;
uint32 zone = retval.size() > 1 ? retval[1] : 0xff;
target->summon_info = (summon_info & 0xf00ffff) | SUMMON_TYPE_SPECIAL | ((uint32)target->current.location << 16);
target->enable_field_effect(false);
......@@ -2958,7 +2959,8 @@ int32 field::special_summon_rule(uint16 step, uint8 sumplayer, card* target, uin
if(ct1 == 0)
zone = flag1;
}
move_to_field(pcard, sumplayer, sumplayer, LOCATION_MZONE, POS_FACEUP, FALSE, 0, FALSE, zone);
uint8 positions = pcard->get_spsummonable_position(peffect, ((peffect->get_value(pcard) & 0xff00ffff) | SUMMON_TYPE_SPECIAL), POS_FACEUP, sumplayer, sumplayer);
move_to_field(pcard, sumplayer, sumplayer, LOCATION_MZONE, positions, FALSE, 0, FALSE, zone);
return FALSE;
}
case 24: {
......@@ -3154,7 +3156,8 @@ int32 field::special_summon_step(uint16 step, group* targets, card* target, uint
zone &= flag1;
}
}
move_to_field(target, target->summon_player, playerid, LOCATION_MZONE, positions, FALSE, 0, FALSE, zone);
uint8 sumpositions = target->get_spsummonable_position(core.reason_effect, (target->summon_info & 0xff00ffff), positions, target->summon_player, playerid);
move_to_field(target, target->summon_player, playerid, LOCATION_MZONE, sumpositions, FALSE, 0, FALSE, zone);
return FALSE;
}
case 2: {
......@@ -5089,8 +5092,9 @@ int32 field::activate_effect(uint16 step, effect* peffect) {
case 0: {
card* phandler = peffect->get_handler();
int32 playerid = phandler->current.controler;
nil_event.event_code = EVENT_FREE_CHAIN;
if(!peffect->is_activateable(playerid, nil_event))
tevent test_event;
test_event.event_code = EVENT_FREE_CHAIN;
if(!peffect->is_activateable(playerid, test_event))
return TRUE;
chain newchain;
newchain.flag = 0;
......
......@@ -994,6 +994,9 @@ int32 field::check_hint_timing(effect* peffect) {
}
// core.spe_effect[p]: # of optional trigger effects, activate/quick effect with hints
int32 field::process_phase_event(int16 step, int32 phase) {
tevent test_event;
test_event.event_code = EVENT_PHASE + phase;
test_event.event_player = infos.turn_player;
switch(step) {
case 0: {
if((phase == PHASE_DRAW && is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_DP))
......@@ -1005,8 +1008,6 @@ int32 field::process_phase_event(int16 step, int32 phase) {
return FALSE;
}
int32 phase_event = EVENT_PHASE + phase;
nil_event.event_code = phase_event;
nil_event.event_player = infos.turn_player;
int32 check_player = infos.turn_player;
if(core.units.begin()->arg2 & 0x2)
check_player = 1 - infos.turn_player;
......@@ -1018,7 +1019,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(!peffect->is_activateable(check_player, nil_event))
if(!peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1030,7 +1031,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
effect* peffect = eit->second;
++eit;
//effects.continuous_effect may be changed in is_activateable (e.g. Rescue Cat)
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, nil_event))
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1065,7 +1066,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(!peffect->is_activateable(check_player, nil_event))
if(!peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1088,7 +1089,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, nil_event))
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1102,7 +1103,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, nil_event))
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1115,7 +1116,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, nil_event))
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, test_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
......@@ -1192,7 +1193,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
check_player = 1 - infos.turn_player;
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = nil_event;
newchain.evt = test_event;
newchain.set_triggering_state(phandler);
newchain.triggering_player = check_player;
core.new_chains.push_back(newchain);
......@@ -1205,7 +1206,7 @@ int32 field::process_phase_event(int16 step, int32 phase) {
infos.priorities[1] = 0;
} else {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
solve_continuous(peffect->get_handler_player(), peffect, test_event);
core.units.begin()->step = 3;
}
return FALSE;
......@@ -1497,8 +1498,10 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
return TRUE;
}
case 30: {
// Battle Step, EFFECT_TYPE_CONTINUOUS with EVENT_FREE_CHAIN
int32 check_player = infos.turn_player;
nil_event.event_code = EVENT_FREE_CHAIN;
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
chain newchain;
core.select_chains.clear();
core.spe_effect[check_player] = 0;
......@@ -1507,7 +1510,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
effect* peffect = eit->second;
++eit;
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, nil_event)) {
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, free_event)) {
core.select_chains.push_back(newchain);
core.spe_effect[check_player]++;
}
......@@ -1521,16 +1524,19 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
case 31: {
if(returns.ivalue[0] == -1)
return FALSE;
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
const chain& newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
solve_continuous(peffect->get_handler_player(), peffect, free_event);
core.units.begin()->step = 29;
return FALSE;
}
case 32: {
int32 check_player = 1 - infos.turn_player;
nil_event.event_code = EVENT_FREE_CHAIN;
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
chain newchain;
core.select_chains.clear();
core.spe_effect[check_player] = 0;
......@@ -1539,7 +1545,7 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
effect* peffect = eit->second;
++eit;
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, nil_event)) {
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, free_event)) {
core.select_chains.push_back(newchain);
core.spe_effect[check_player]++;
}
......@@ -1557,8 +1563,10 @@ int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_free
}
const chain& newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
solve_continuous(peffect->get_handler_player(), peffect, free_event);
core.units.begin()->step = 31;
return FALSE;
}
......@@ -1719,17 +1727,18 @@ int32 field::process_quick_effect(int16 step, int32 skip_freechain, uint8 priori
}
core.spe_effect[priority] = (int32)core.select_chains.size();
if(!skip_freechain) {
nil_event.event_code = EVENT_FREE_CHAIN;
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
auto pr = effects.activate_effect.equal_range(EVENT_FREE_CHAIN);
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, nil_event)) {
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, free_event)) {
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = nil_event;
newchain.evt = free_event;
newchain.triggering_effect = peffect;
newchain.set_triggering_state(phandler);
newchain.triggering_player = priority;
......@@ -1743,11 +1752,11 @@ int32 field::process_quick_effect(int16 step, int32 skip_freechain, uint8 priori
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, nil_event)) {
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, free_event)) {
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = nil_event;
newchain.evt = free_event;
newchain.triggering_effect = peffect;
newchain.set_triggering_state(phandler);
newchain.triggering_player = priority;
......@@ -2035,13 +2044,14 @@ int32 field::process_single_event(effect* peffect, const tevent& e, chain_list&
return TRUE;
}
int32 field::process_idle_command(uint16 step) {
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
switch(step) {
case 0: {
effect* peffect;
bool must_attack = false;
core.select_chains.clear();
chain newchain;
nil_event.event_code = EVENT_FREE_CHAIN;
core.to_bp = TRUE;
core.to_ep = TRUE;
if((!(core.duel_options & DUEL_ATTACK_FIRST_TURN) && infos.turn_id == 1) || infos.phase == PHASE_MAIN2 || is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_BP))
......@@ -2088,7 +2098,7 @@ int32 field::process_idle_command(uint16 step) {
++eit;
peffect->set_activate_location();
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
pr = effects.quick_o_effect.equal_range(EVENT_FREE_CHAIN);
......@@ -2097,7 +2107,7 @@ int32 field::process_idle_command(uint16 step) {
++eit;
peffect->set_activate_location();
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
......@@ -2105,7 +2115,7 @@ int32 field::process_idle_command(uint16 step) {
effect* peffect = eit->second;
++eit;
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
for(auto eit = effects.ignition_effect.begin(); eit != effects.ignition_effect.end();) {
......@@ -2113,7 +2123,7 @@ int32 field::process_idle_command(uint16 step) {
++eit;
peffect->set_activate_location();
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
core.summonable_cards.clear();
......@@ -2180,7 +2190,7 @@ int32 field::process_idle_command(uint16 step) {
effect* peffect = newchain.triggering_effect;
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
solve_continuous(peffect->get_handler_player(), peffect, free_event);
core.units.begin()->step = 2;
return FALSE;
}
......@@ -2362,12 +2372,13 @@ int32 field::process_idle_command(uint16 step) {
return TRUE;
}
int32 field::process_battle_command(uint16 step) {
tevent free_event;
free_event.event_code = EVENT_FREE_CHAIN;
switch(step) {
case 0: {
effect* peffect = 0;
core.select_chains.clear();
chain newchain;
nil_event.event_code = EVENT_FREE_CHAIN;
if(!core.chain_attack) {
core.chain_attacker_id = 0;
core.chain_attack_target = 0;
......@@ -2399,7 +2410,7 @@ int32 field::process_battle_command(uint16 step) {
++eit;
peffect->set_activate_location();
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event) && peffect->get_speed() > 1)
if(peffect->is_activateable(infos.turn_player, free_event) && peffect->get_speed() > 1)
core.select_chains.push_back(newchain);
}
pr = effects.quick_o_effect.equal_range(EVENT_FREE_CHAIN);
......@@ -2408,7 +2419,7 @@ int32 field::process_battle_command(uint16 step) {
++eit;
peffect->set_activate_location();
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
......@@ -2416,7 +2427,7 @@ int32 field::process_battle_command(uint16 step) {
effect* peffect = eit->second;
++eit;
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, nil_event))
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, free_event))
core.select_chains.push_back(newchain);
}
core.attackable_cards.clear();
......@@ -2462,7 +2473,7 @@ int32 field::process_battle_command(uint16 step) {
effect* peffect = newchain.triggering_effect;
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
solve_continuous(peffect->get_handler_player(), peffect, free_event);
core.units.begin()->step = 13;
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