dep-ygopro-core/processor.cpp

5472 lines
187 KiB
C++
Raw Permalink Normal View History

2015-09-25 21:07:16 +08:00
/*
* processor.cpp
*
* Created on: 2010-8-3
* Author: Argon
*/
#include "field.h"
#include "duel.h"
#include "card.h"
#include "group.h"
#include "effect.h"
#include "interpreter.h"
#include "ocgapi.h"
#include <iterator>
void field::add_process(uint16 type, uint16 step, effect* peffect, group* target, ptr arg1, ptr arg2, ptr arg3, ptr arg4, void* ptr1, void* ptr2) {
2015-09-25 21:07:16 +08:00
processor_unit new_unit;
new_unit.type = type;
new_unit.step = step;
new_unit.peffect = peffect;
new_unit.ptarget = target;
new_unit.arg1 = arg1;
new_unit.arg2 = arg2;
2016-08-25 21:51:04 +08:00
new_unit.arg3 = arg3;
new_unit.arg4 = arg4;
new_unit.ptr1 = ptr1;
new_unit.ptr2 = ptr2;
2015-09-25 21:07:16 +08:00
core.subunits.push_back(new_unit);
}
int32 field::process() {
if (core.subunits.size())
core.units.splice(core.units.begin(), core.subunits);
if (core.units.size() == 0)
return PROCESSOR_END + pduel->bufferlen;
2016-05-07 06:13:42 +09:00
auto it = core.units.begin();
2015-09-25 21:07:16 +08:00
switch (it->type) {
case PROCESSOR_ADJUST: {
if (adjust_step(it->step))
core.units.pop_front();
else {
it->step++;
}
return pduel->bufferlen;
}
case PROCESSOR_TURN: {
if (process_turn(it->step, it->arg1))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_WAIT: {
core.units.pop_front();
return PROCESSOR_WAITING + pduel->bufferlen;
}
case PROCESSOR_REFRESH_LOC: {
if (refresh_location_info(it->step))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SELECT_BATTLECMD: {
if (select_battle_command(it->step, it->arg1)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_IDLECMD: {
if (select_idle_command(it->step, it->arg1)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_EFFECTYN: {
2017-07-24 03:25:04 +08:00
if (select_effect_yes_no(it->step, it->arg1, it->arg2, (card*)it->ptarget)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_YESNO: {
if (select_yes_no(it->step, it->arg1, it->arg2)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_OPTION: {
if (select_option(it->step, it->arg1)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_CARD: {
if (select_card(it->step, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
2017-02-06 23:16:54 +01:00
case PROCESSOR_SELECT_UNSELECT_CARD: {
if (select_unselect_card(it->step, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff, (it->arg3) & 0xff)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
2015-09-25 21:07:16 +08:00
case PROCESSOR_SELECT_CHAIN: {
if (select_chain(it->step, it->arg1, (it->arg2 & 0xffff), it->arg2 >> 16)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_DISFIELD:
case PROCESSOR_SELECT_PLACE: {
2016-08-25 21:51:04 +08:00
if (select_place(it->step, it->arg1, it->arg2, it->arg3)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_POSITION: {
if (select_position(it->step, it->arg1 & 0xffff, it->arg2, (it->arg1 >> 16) & 0xffff)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_TRIBUTE_P: {
if (select_tribute(it->step, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SORT_CHAIN: {
if (sort_chain(it->step, it->arg1)) {
core.units.pop_front();
} else {
it->step++;
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_COUNTER: {
if (select_counter(it->step, it->arg1, it->arg2, it->arg3, it->arg4 >> 8, it->arg4 & 0xff)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_SUM: {
if (select_with_sum_limit(it->step, it->arg2 & 0xffff, it->arg1, (it->arg2 >> 16) & 0xff, (it->arg2 >> 24) & 0xff)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SORT_CARD: {
if (sort_card(it->step, it->arg1, it->arg2)) {
core.units.pop_front();
return pduel->bufferlen;
} else {
it->step = 1;
return PROCESSOR_WAITING + pduel->bufferlen;
}
}
case PROCESSOR_SELECT_RELEASE: {
2018-03-11 17:51:46 +09:00
if (select_release_cards(it->step, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SELECT_TRIBUTE: {
2018-03-14 22:21:06 +09:00
if (select_tribute_cards(it->step, (card*)it->ptarget, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff, it->arg3, it->arg4))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_POINT_EVENT: {
if(process_point_event(it->step, it->arg1 & 0xff, (it->arg1 >> 8) & 0xff, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_QUICK_EFFECT: {
if(process_quick_effect(it->step, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_IDLE_COMMAND: {
if(process_idle_command(it->step))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_PHASE_EVENT: {
if(process_phase_event(it->step, it->arg1))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_BATTLE_COMMAND: {
if(process_battle_command(it->step))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_DAMAGE_STEP: {
if(process_damage_step(it->step, it->arg2))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_ADD_CHAIN: {
if (add_chain(it->step))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SOLVE_CHAIN: {
if (solve_chain(it->step, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SOLVE_CONTINUOUS: {
if (solve_continuous(it->step))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_EXECUTE_COST: {
if (execute_cost(it->step, it->peffect, it->arg1)) {
core.units.pop_front();
core.solving_event.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_EXECUTE_OPERATION: {
if (execute_operation(it->step, it->peffect, it->arg1)) {
core.units.pop_front();
core.solving_event.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_EXECUTE_TARGET: {
if (execute_target(it->step, it->peffect, it->arg1)) {
core.units.pop_front();
core.solving_event.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_DESTROY: {
if (destroy(it->step, it->ptarget, it->peffect, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_RELEASE: {
if (release(it->step, it->ptarget, it->peffect, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SENDTO: {
if (send_to(it->step, it->ptarget, it->peffect, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
2018-10-14 21:16:02 +08:00
case PROCESSOR_DESTROY_REPLACE: {
if(destroy_replace(it->step, it->ptarget, (card*)it->ptr1, it->arg2))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
2018-10-14 21:16:02 +08:00
case PROCESSOR_RELEASE_REPLACE: {
if (release_replace(it->step, it->ptarget, (card*)it->ptr1))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
2018-10-14 21:16:02 +08:00
case PROCESSOR_SENDTO_REPLACE: {
if (send_replace(it->step, it->ptarget, (card*)it->ptr1))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_MOVETOFIELD: {
2018-09-04 19:36:20 +02:00
if (move_to_field(it->step, (card*)it->ptarget, it->arg1, it->arg2 & 0xff, (it->arg2 >> 8) & 0xff, it->arg3 & 0xff, (it->arg3 >> 8) & 0xff, (it->arg3 >> 16) & 0xff, it->arg4))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_CHANGEPOS: {
if (change_position(it->step, it->ptarget, it->peffect, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_OPERATION_REPLACE: {
2017-07-27 20:59:32 +09:00
if (operation_replace(it->step, it->peffect, it->ptarget, (card*)it->ptr1, it->arg1))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
2017-07-01 23:51:49 +09:00
case PROCESSOR_ACTIVATE_EFFECT: {
if (activate_effect(it->step, it->peffect))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
2015-09-25 21:07:16 +08:00
case PROCESSOR_SUMMON_RULE: {
2017-06-08 19:57:49 +09:00
if (summon(it->step, it->arg1 & 0xff, (card*)it->ptarget, it->peffect, (it->arg1 >> 8) & 0xff, (it->arg1 >> 16) & 0xff, (it->arg1 >> 24) & 0xff))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON_RULE: {
if (special_summon_rule(it->step, it->arg1, (card*)it->ptarget, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON: {
2017-04-06 19:46:46 +09:00
if (special_summon(it->step, it->peffect, it->arg1, it->ptarget, it->arg2))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_FLIP_SUMMON: {
if (flip_summon(it->step, it->arg1, (card*)(it->ptarget)))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_MSET: {
2017-06-09 09:44:04 +09:00
if (mset(it->step, it->arg1 & 0xff, (card*)it->ptarget, it->peffect, (it->arg1 >> 8) & 0xff, (it->arg1 >> 16) & 0xff, (it->arg1 >> 24) & 0xff))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SSET: {
if (sset(it->step, it->arg1, it->arg2, (card*)(it->ptarget)))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON_STEP: {
2017-03-26 19:50:07 +09:00
if (special_summon_step(it->step, it->ptarget, (card*)(it->ptr1), it->arg1))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SSET_G: {
2018-06-29 15:19:29 +08:00
if (sset_g(it->step, it->arg1, it->arg2, it->ptarget, it->arg3)) {
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_DRAW : {
if (draw(it->step, it->peffect, it->arg1, (it->arg2 >> 28) & 0xf, (it->arg2 >> 24) & 0xf, it->arg2 & 0xffffff))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_DAMAGE: {
int32 reason = it->arg1;
2016-05-17 19:00:41 +09:00
effect* reason_effect = 0;
card* reason_card = 0;
2015-09-25 21:07:16 +08:00
if(reason & REASON_BATTLE)
2016-05-17 19:00:41 +09:00
reason_card = (card*)it->peffect;
else
reason_effect = it->peffect;
if (damage(it->step, reason_effect, reason, (it->arg2 >> 26) & 0x3, reason_card, (it->arg2 >> 24) & 0x3, it->arg2 & 0xffffff, (it->arg2 >> 28) & 0x1)) {
if(it->step == 9) {
it->step = 1;
core.recover_damage_reserve.splice(core.recover_damage_reserve.end(), core.units, it);
} else
core.units.pop_front();
} else
2015-09-25 21:07:16 +08:00
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_RECOVER: {
2016-05-17 19:00:41 +09:00
if (recover(it->step, it->peffect, it->arg1, (it->arg2 >> 26) & 0x3, (it->arg2 >> 24) & 0x3, it->arg2 & 0xffffff, (it->arg2 >> 28) & 0x1)) {
if(it->step == 9) {
it->step = 1;
core.recover_damage_reserve.splice(core.recover_damage_reserve.end(), core.units, it);
} else
core.units.pop_front();
} else
2015-09-25 21:07:16 +08:00
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_EQUIP: {
if (equip(it->step, it->arg2 & 0xffff, (card*)it->ptr1, (card*)it->ptarget, (it->arg2 >> 16) & 0xff, (it->arg2 >> 24) & 0xff))
2015-09-25 21:07:16 +08:00
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_GET_CONTROL: {
2017-05-22 16:55:48 +09:00
if (get_control(it->step, it->peffect, (it->arg2 >> 28) & 0xf, it->ptarget, (it->arg2 >> 24) & 0xf, (it->arg2 >> 8) & 0x3ff, it->arg2 & 0xff, it->arg3)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SWAP_CONTROL: {
2016-10-09 19:22:30 +09:00
if (swap_control(it->step, it->peffect, it->arg1, it->ptarget, (group*)it->ptr1, it->arg2, it->arg3)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_CONTROL_ADJUST: {
if (control_adjust(it->step)) {
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_SELF_DESTROY: {
2017-09-23 20:18:10 +09:00
if (self_destroy(it->step, (card*)it->ptr1, it->arg1)) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_PAY_LPCOST: {
if (pay_lp_cost(it->step, it->arg1, it->arg2))
core.units.pop_front();
else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_REMOVE_COUNTER: {
if (remove_counter(it->step, it->arg4, (card*)it->ptarget, (it->arg1 >> 16) & 0xff, (it->arg1 >> 8) & 0xff, it->arg1 & 0xff, it->arg2, it->arg3)) {
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_ATTACK_DISABLE: {
if(it->step == 0) {
card* attacker = core.attacker;
if(!attacker
|| (attacker->fieldid_r != core.pre_field[0])
|| (attacker->current.location != LOCATION_MZONE)
|| !attacker->is_capable_attack()
|| !attacker->is_affect_by_effect(core.reason_effect)
2017-01-31 19:53:39 +01:00
|| attacker->is_affected_by_effect(EFFECT_UNSTOPPABLE_ATTACK)) {
2015-09-25 21:07:16 +08:00
returns.ivalue[0] = 0;
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
} else {
effect* peffect = pduel->new_effect();
peffect->code = EFFECT_ATTACK_DISABLED;
peffect->type = EFFECT_TYPE_SINGLE;
attacker->add_effect(peffect);
attacker->set_status(STATUS_ATTACK_CANCELED, TRUE);
raise_event(attacker, EVENT_ATTACK_DISABLED, core.reason_effect, 0, core.reason_player, PLAYER_NONE, 0);
process_instant_event();
it->step++;
}
} else {
returns.ivalue[0] = 1;
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_DESTROY_S: {
if(it->step == 0) {
add_process(PROCESSOR_DESTROY, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_RELEASE_S: {
if(it->step == 0) {
add_process(PROCESSOR_RELEASE, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SENDTO_S: {
if(it->step == 0) {
add_process(PROCESSOR_SENDTO, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_CHANGEPOS_S: {
if(it->step == 0) {
add_process(PROCESSOR_CHANGEPOS, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_ANNOUNCE_RACE: {
if(announce_race(it->step, it->arg1 & 0xffff, it->arg1 >> 16, it->arg2)) {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else {
it->step++;
}
return PROCESSOR_WAITING + pduel->bufferlen;
}
case PROCESSOR_ANNOUNCE_ATTRIB: {
if(announce_attribute(it->step, it->arg1 & 0xffff, it->arg1 >> 16, it->arg2)) {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else {
it->step++;
}
return PROCESSOR_WAITING + pduel->bufferlen;
}
case PROCESSOR_ANNOUNCE_CARD: {
2015-12-19 11:30:33 +09:00
if(announce_card(it->step, it->arg1, it->arg2)) {
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else {
2018-05-15 18:26:41 +08:00
if(it->step == 0)
it->step++;
2015-09-25 21:07:16 +08:00
}
return PROCESSOR_WAITING + pduel->bufferlen;
}
case PROCESSOR_ANNOUNCE_NUMBER: {
if(announce_number(it->step, it->arg1)) {
pduel->lua->add_param(core.select_options[returns.ivalue[0]], PARAM_TYPE_INT);
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else {
it->step++;
}
return PROCESSOR_WAITING + pduel->bufferlen;
}
case PROCESSOR_TOSS_DICE: {
if(toss_dice(it->step, it->peffect, it->arg1 >> 16, it->arg1 & 0xff, it->arg2 & 0xff, it->arg2 >> 16)) {
for(int32 i = 0; i < (it->arg2 & 0xff) + (it->arg2 >> 16); ++i)
pduel->lua->add_param(core.dice_result[i], PARAM_TYPE_INT);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
case PROCESSOR_TOSS_COIN: {
if (toss_coin(it->step, it->peffect, (it->arg1 >> 16), it->arg1 & 0xff, it->arg2)) {
for(int32 i = 0; i < it->arg2; ++i)
pduel->lua->add_param(core.coin_result[i], PARAM_TYPE_INT);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
2017-04-13 22:57:49 +02:00
case PROCESSOR_ROCK_PAPER_SCISSORS: {
2017-04-14 15:49:51 +02:00
if (rock_paper_scissors(it->step, it->arg1)) {
2017-04-13 22:57:49 +02:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
2015-09-25 21:07:16 +08:00
case PROCESSOR_SELECT_EFFECTYN_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_EFFECTYN, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_YESNO_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_YESNO, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_OPTION_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_OPTION, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_OPSELECTED);
pduel->write_buffer8(it->arg1);
pduel->write_buffer64(core.select_options[returns.ivalue[0]]);
2015-09-25 21:07:16 +08:00
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_CARD_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_CARD, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
if (returns.bvalue[0] == -1)
pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP);
else {
group* pgroup = pduel->new_group();
for (int32 i = 0; i < returns.bvalue[0]; ++i) {
card* pcard = core.select_cards[returns.bvalue[i + 1]];
pgroup->container.insert(pcard);
}
pduel->lua->add_param(pgroup, PARAM_TYPE_GROUP);
2015-09-25 21:07:16 +08:00
}
core.units.pop_front();
}
return pduel->bufferlen;
}
2017-02-06 23:16:54 +01:00
case PROCESSOR_SELECT_UNSELECT_CARD_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_UNSELECT_CARD, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3);
it->step++;
} else {
if (returns.bvalue[0] == -1)
pduel->lua->add_param((void*)0, PARAM_TYPE_GROUP);
else {
//group* pgroup = pduel->new_group(); // UNUSED VARIABLE
2017-02-06 23:16:54 +01:00
card* pcard;
if ((size_t)returns.bvalue[1] < core.select_cards.size())
2018-04-05 14:41:14 +02:00
pcard = core.select_cards[returns.bvalue[1]];
else
pcard = core.unselect_cards[returns.bvalue[1] - core.select_cards.size()];
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
}
core.units.pop_front();
}
return pduel->bufferlen;
}
2015-09-25 21:07:16 +08:00
case PROCESSOR_SELECT_POSITION_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_POSITION, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_RELEASE_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_RELEASE, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
group* pgroup = pduel->new_group();
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
2018-08-30 19:50:21 +08:00
card* pcard = core.select_cards[returns.bvalue[i + 1]];
2015-09-25 21:07:16 +08:00
pgroup->container.insert(pcard);
}
pduel->lua->add_param(pgroup, PARAM_TYPE_GROUP);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_TRIBUTE_S: {
if(it->step == 0) {
2017-10-14 17:21:47 +08:00
add_process(PROCESSOR_SELECT_TRIBUTE, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3, it->arg4);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
group* pgroup = pduel->new_group();
if(returns.ivalue[0] != -1)
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
card* pcard = core.select_cards[returns.bvalue[i + 1]];
pgroup->container.insert(pcard);
}
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(pgroup, PARAM_TYPE_GROUP);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SORT_CARDS_S:
core.units.pop_front();
break;
case PROCESSOR_SELECT_TARGET: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_CARD, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
2017-07-01 23:51:49 +09:00
chain* ch = get_chain(0);
if(ch) {
if(!ch->target_cards) {
ch->target_cards = pduel->new_group();
ch->target_cards->is_readonly = TRUE;
2015-09-25 21:07:16 +08:00
}
2017-07-01 23:51:49 +09:00
group* tg = ch->target_cards;
effect* peffect = ch->triggering_effect;
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
for(int32 i = 0; i < returns.bvalue[0]; ++i)
tg->container.insert(core.select_cards[returns.bvalue[i + 1]]);
pduel->lua->add_param(tg, PARAM_TYPE_GROUP);
} else {
group* pret = pduel->new_group();
2015-09-25 21:07:16 +08:00
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
2017-07-01 23:51:49 +09:00
tg->container.insert(core.select_cards[returns.bvalue[i + 1]]);
pret->container.insert(core.select_cards[returns.bvalue[i + 1]]);
}
if((returns.bvalue[0] > 0) && peffect->is_flag(EFFECT_FLAG_CARD_TARGET)) {
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
card* pcard = core.select_cards[returns.bvalue[i + 1]];
pduel->write_buffer8(MSG_BECOME_TARGET);
pduel->write_buffer8(1);
pduel->write_buffer32(pcard->get_info_location());
}
2015-09-25 21:07:16 +08:00
}
2018-09-03 16:36:45 +08:00
for(auto& pcard : pret->container)
pcard->create_relation(*ch);
2017-07-01 23:51:49 +09:00
pduel->lua->add_param(pret, PARAM_TYPE_GROUP);
2015-09-25 21:07:16 +08:00
}
}
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_FUSION: {
if(it->step == 0) {
2017-06-07 19:55:21 +02:00
effect_set eset;
card* pcard = (card*)it->ptr2;
2017-10-15 14:56:58 +02:00
pcard->fusion_filter_valid(it->ptarget, (group*)it->ptr1, it->arg1>>16, &eset);
2017-06-07 19:55:21 +02:00
core.select_effects.clear();
core.select_options.clear();
2017-06-10 23:30:38 +02:00
if(eset.size() < 1) {
core.units.pop_front();
return pduel->bufferlen;
}
2017-06-07 19:55:21 +02:00
for (int32 i = 0; i < eset.size(); ++i) {
core.select_effects.push_back(eset[i]);
core.select_options.push_back(eset[i]->description);
}
if (core.select_options.size() == 1)
returns.ivalue[0] = 0;
else
add_process(PROCESSOR_SELECT_OPTION, 0, 0, 0, it->arg1, 0);
it->step++;
} else if(it->step==1){
2015-09-25 21:07:16 +08:00
tevent e;
e.event_cards = it->ptarget;
2017-06-07 19:55:21 +02:00
e.reason_effect = core.select_effects[returns.ivalue[0]];
2015-09-25 21:07:16 +08:00
e.reason_player = it->arg1;
core.fusion_materials.clear();
2017-06-07 19:55:21 +02:00
if(!core.select_effects[returns.ivalue[0]]) {
2015-09-25 21:07:16 +08:00
core.units.pop_front();
return pduel->bufferlen;
}
core.sub_solving_event.push_back(e);
2017-10-15 14:56:58 +02:00
pduel->lua->add_param(it->ptr1, PARAM_TYPE_GROUP);
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(it->arg1 >> 16, PARAM_TYPE_INT);
2017-06-07 19:55:21 +02:00
add_process(PROCESSOR_EXECUTE_OPERATION, 0, core.select_effects[returns.ivalue[0]], 0, it->arg1 & 0xffff, 0);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
group* pgroup = pduel->new_group(core.fusion_materials);
pduel->lua->add_param(pgroup, PARAM_TYPE_GROUP);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_SUM_S: {
if(it->step == 0) {
add_process(PROCESSOR_SELECT_SUM, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
group* pgroup = pduel->new_group();
2015-12-19 09:56:22 +09:00
int32 mcount = core.must_select_cards.size();
for(int32 i = mcount; i < returns.bvalue[0]; ++i) {
card* pcard = core.select_cards[returns.bvalue[i + 1]];
2015-09-25 21:07:16 +08:00
pgroup->container.insert(pcard);
}
2015-12-19 09:56:22 +09:00
core.must_select_cards.clear();
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(pgroup, PARAM_TYPE_GROUP);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SELECT_DISFIELD_S: {
if(it->step == 0) {
2016-08-25 21:51:04 +08:00
add_process(PROCESSOR_SELECT_DISFIELD, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
2016-09-07 01:09:47 +08:00
int32 playerid = it->arg1;
int32 count = it->arg3;
2015-09-25 21:07:16 +08:00
int32 dfflag = 0;
2018-08-30 19:50:21 +08:00
uint8 pa = 0;
2015-09-25 21:07:16 +08:00
for(int32 i = 0; i < count; ++i) {
2018-08-30 19:50:21 +08:00
uint8 p = returns.bvalue[pa];
uint8 l = returns.bvalue[pa + 1];
uint8 s = returns.bvalue[pa + 2];
2016-09-07 01:09:47 +08:00
dfflag |= 0x1u << (s + (p == playerid ? 0 : 16) + (l == LOCATION_MZONE ? 0 : 8));
2015-09-25 21:07:16 +08:00
pa += 3;
}
pduel->lua->add_param(dfflag, PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON_S: {
if(it->step == 0) {
add_process(PROCESSOR_SPSUMMON, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON_STEP_S: {
if(it->step == 0) {
add_process(PROCESSOR_SPSUMMON_STEP, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3, it->arg4, it->ptr1);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SPSUMMON_COMP_S: {
if(it->step == 0) {
add_process(PROCESSOR_SPSUMMON, 1, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_RANDOM_SELECT_S: {
uint32 count = it->arg2;
group* pgroup = it->ptarget;
group* newgroup = pduel->new_group();
if(count > pgroup->container.size())
count = pgroup->container.size();
if(count == 0) {
pduel->lua->add_param(newgroup, PARAM_TYPE_GROUP);
core.units.pop_front();
return pduel->bufferlen;
}
duel* pduel = pgroup->pduel;
if(count == pgroup->container.size())
newgroup->container = pgroup->container;
else {
while(newgroup->container.size() < count) {
int32 i = pduel->get_next_integer(0, pgroup->container.size() - 1);
auto cit = pgroup->container.begin();
std::advance(cit, i);
newgroup->container.insert(*cit);
}
}
pduel->lua->add_param(newgroup, PARAM_TYPE_GROUP);
pduel->write_buffer8(MSG_RANDOM_SELECTED);
pduel->write_buffer8(it->arg1);
pduel->write_buffer8(count);
2018-09-03 16:36:45 +08:00
for(auto& pcard : newgroup->container) {
pduel->write_buffer32(pcard->get_info_location());
2015-09-25 21:07:16 +08:00
}
core.units.pop_front();
return pduel->bufferlen;
}
case PROCESSOR_DRAW_S: {
if(it->step == 0) {
add_process(PROCESSOR_DRAW, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_DAMAGE_S: {
if(it->step == 0) {
add_process(PROCESSOR_DAMAGE, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_RECOVER_S: {
if(it->step == 0) {
add_process(PROCESSOR_RECOVER, 0, it->peffect, it->ptarget, it->arg1, it->arg2);
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_EQUIP_S: {
if(it->step == 0) {
add_process(PROCESSOR_EQUIP, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3, it->arg4, it->ptr1);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_GET_CONTROL_S: {
if(it->step == 0) {
2017-05-22 16:55:48 +09:00
add_process(PROCESSOR_GET_CONTROL, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
2016-05-15 23:31:22 +09:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
2015-09-25 21:07:16 +08:00
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_SWAP_CONTROL_S: {
if(it->step == 0) {
add_process(PROCESSOR_SWAP_CONTROL, 0, it->peffect, it->ptarget, it->arg1, it->arg2, it->arg3, it->arg4, it->ptr1);
2015-09-25 21:07:16 +08:00
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_DISCARD_HAND_S: {
if(it->step == 0) {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(it->arg1);
if(it->arg3 & REASON_DISCARD)
pduel->write_buffer64(501);
2015-09-25 21:07:16 +08:00
else
pduel->write_buffer64(504);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, it->arg1, it->arg2);
it->step++;
} else if(it->step == 1) {
card_set cset;
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
2018-08-30 19:50:21 +08:00
card* pcard = core.select_cards[returns.bvalue[i + 1]];
2015-09-25 21:07:16 +08:00
cset.insert(pcard);
}
if(cset.size())
send_to(&cset, core.reason_effect, it->arg3, core.reason_player, PLAYER_NONE, LOCATION_GRAVE, 0, POS_FACEUP);
2015-09-25 21:07:16 +08:00
else
returns.ivalue[0] = 0;
it->step++;
} else {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_DISCARD_DECK_S: {
if(discard_deck(it->step, it->arg1 & 0xff, it->arg1 >> 16, it->arg2)) {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_INT);
core.units.pop_front();
} else {
it->step++;
}
return pduel->bufferlen;
}
case PROCESSOR_SORT_DECK_S: {
uint8 sort_player = it->arg1 & 0xffff;
uint8 target_player = it->arg1 >> 16;
uint8 count = it->arg2, i = 0;
if(count > player[target_player].list_main.size())
count = player[target_player].list_main.size();
if(it->step == 0) {
core.select_cards.clear();
for(auto clit = player[target_player].list_main.rbegin(); i < count; ++i, ++clit)
core.select_cards.push_back(*clit);
add_process(PROCESSOR_SORT_CARD, 0, 0, 0, sort_player, 0);
it->step++;
} else {
if(returns.bvalue[0] != -1) {
card* tc[16];
for(i = 0; i < count; ++i)
player[target_player].list_main.pop_back();
for(i = 0; i < count; ++i)
2018-08-30 19:50:21 +08:00
tc[(uint8)returns.bvalue[i]] = core.select_cards[i];
2015-09-25 21:07:16 +08:00
for(i = 0; i < count; ++i) {
player[target_player].list_main.push_back(tc[count - i - 1]);
tc[count - i - 1]->current.sequence = player[target_player].list_main.size() - 1;
}
}
if(core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) {
if(count > 0) {
card* ptop = player[target_player].list_main.back();
2016-05-31 12:47:55 +08:00
if(core.deck_reversed || (ptop->current.position == POS_FACEUP_DEFENSE)) {
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(target_player);
pduel->write_buffer8(0);
2016-05-31 12:47:55 +08:00
if(ptop->current.position != POS_FACEUP_DEFENSE)
2015-09-25 21:07:16 +08:00
pduel->write_buffer32(ptop->data.code);
else
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
}
}
core.units.pop_front();
}
return pduel->bufferlen;
}
case PROCESSOR_REMOVEOL_S: {
2018-10-25 22:36:33 +02:00
if(remove_overlay_card(it->step, it->arg3, it->ptarget, it->arg1 >> 16,
2015-09-25 21:07:16 +08:00
(it->arg1 >> 8) & 0xff, it->arg1 & 0xff, it->arg2 & 0xffff, it->arg2 >> 16)) {
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
} else {
it->step++;
}
return pduel->bufferlen;
}
case PROCESSOR_MOVETOFIELD_S: {
2018-09-04 19:36:20 +02:00
if (move_to_field(it->step, (card*)it->ptarget, it->arg1, it->arg2 & 0xff, (it->arg2 >> 8) & 0xff, it->arg3 & 0xff, (it->arg3 >> 8) & 0xff, (it->arg3 >> 16) & 0xff, it->arg4)) {
2015-09-25 21:07:16 +08:00
pduel->lua->add_param(returns.ivalue[0], PARAM_TYPE_BOOLEAN);
core.units.pop_front();
} else
it->step++;
return pduel->bufferlen;
}
}
return pduel->bufferlen;
}
int32 field::execute_cost(uint16 step, effect * triggering_effect, uint8 triggering_player) {
if(!triggering_effect->cost) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
pduel->lua->params.clear();
return TRUE;
}
if (step == 0) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
const tevent& e = core.solving_event.front();
pduel->lua->add_param(1, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT, true);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP, true);
pduel->lua->add_param(triggering_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(triggering_effect, PARAM_TYPE_EFFECT, true);
if(core.check_level == 0) {
core.shuffle_deck_check[0] = FALSE;
core.shuffle_deck_check[1] = FALSE;
core.shuffle_hand_check[0] = FALSE;
core.shuffle_hand_check[1] = FALSE;
}
core.shuffle_check_disabled = FALSE;
core.check_level++;
}
core.reason_effect = triggering_effect;
core.reason_player = triggering_player;
uint32 count = pduel->lua->params.size();
uint32 yield_value = 0;
int32 result = pduel->lua->call_coroutine(triggering_effect->cost, count, &yield_value, step);
returns.ivalue[0] = yield_value;
if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) {
core.reason_effect = 0;
core.reason_player = PLAYER_NONE;
core.check_level--;
if(core.check_level == 0) {
if(core.shuffle_hand_check[0])
shuffle(0, LOCATION_HAND);
if(core.shuffle_hand_check[1])
shuffle(1, LOCATION_HAND);
if(core.shuffle_deck_check[0])
shuffle(0, LOCATION_DECK);
if(core.shuffle_deck_check[1])
shuffle(1, LOCATION_DECK);
}
core.shuffle_check_disabled = FALSE;
return TRUE;
}
return FALSE;
}
int32 field::execute_operation(uint16 step, effect * triggering_effect, uint8 triggering_player) {
if(!triggering_effect->operation) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
pduel->lua->params.clear();
return TRUE;
}
if (step == 0) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
const tevent& e = core.solving_event.front();
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT, true);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP, true);
pduel->lua->add_param(triggering_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(triggering_effect, PARAM_TYPE_EFFECT, true);
if(core.check_level == 0) {
core.shuffle_deck_check[0] = FALSE;
core.shuffle_deck_check[1] = FALSE;
core.shuffle_hand_check[0] = FALSE;
core.shuffle_hand_check[1] = FALSE;
}
core.shuffle_check_disabled = FALSE;
core.check_level++;
}
core.reason_effect = triggering_effect;
core.reason_player = triggering_player;
uint32 count = pduel->lua->params.size();
uint32 yield_value = 0;
int32 result = pduel->lua->call_coroutine(triggering_effect->operation, count, &yield_value, step);
returns.ivalue[0] = yield_value;
if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) {
core.reason_effect = 0;
core.reason_player = PLAYER_NONE;
core.check_level--;
if(core.check_level == 0) {
if(core.shuffle_hand_check[0])
shuffle(0, LOCATION_HAND);
if(core.shuffle_hand_check[1])
shuffle(1, LOCATION_HAND);
if(core.shuffle_deck_check[0])
shuffle(0, LOCATION_DECK);
if(core.shuffle_deck_check[1])
shuffle(1, LOCATION_DECK);
2017-06-05 08:08:45 +09:00
//cost[0].count = 0;
//cost[1].count = 0;
//cost[0].amount = 0;
//cost[1].amount = 0;
2015-09-25 21:07:16 +08:00
}
core.shuffle_check_disabled = FALSE;
return TRUE;
}
return FALSE;
}
int32 field::execute_target(uint16 step, effect * triggering_effect, uint8 triggering_player) {
if(!triggering_effect->target) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
pduel->lua->params.clear();
return TRUE;
}
if (step == 0) {
core.solving_event.splice(core.solving_event.begin(), core.sub_solving_event);
const tevent& e = core.solving_event.front();
pduel->lua->add_param(1, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT, true);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP, true);
pduel->lua->add_param(triggering_player, PARAM_TYPE_INT, true);
pduel->lua->add_param(triggering_effect, PARAM_TYPE_EFFECT, true);
if(core.check_level == 0) {
core.shuffle_deck_check[0] = FALSE;
core.shuffle_deck_check[1] = FALSE;
core.shuffle_hand_check[0] = FALSE;
core.shuffle_hand_check[1] = FALSE;
}
core.shuffle_check_disabled = FALSE;
core.check_level++;
}
core.reason_effect = triggering_effect;
core.reason_player = triggering_player;
uint32 count = pduel->lua->params.size();
uint32 yield_value = 0;
int32 result = pduel->lua->call_coroutine(triggering_effect->target, count, &yield_value, step);
returns.ivalue[0] = yield_value;
if (result == COROUTINE_FINISH || result == COROUTINE_ERROR || result == OPERATION_FAIL) {
core.reason_effect = 0;
core.reason_player = PLAYER_NONE;
core.check_level--;
if(core.check_level == 0) {
if(core.shuffle_hand_check[0])
shuffle(0, LOCATION_HAND);
if(core.shuffle_hand_check[1])
shuffle(1, LOCATION_HAND);
if(core.shuffle_deck_check[0])
shuffle(0, LOCATION_DECK);
if(core.shuffle_deck_check[1])
shuffle(1, LOCATION_DECK);
}
core.shuffle_check_disabled = FALSE;
return TRUE;
}
return FALSE;
}
void field::raise_event(card* event_card, uint32 event_code, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 event_player, uint32 event_value) {
tevent new_event;
new_event.trigger_card = 0;
if (event_card) {
group* pgroup = pduel->new_group(event_card);
pgroup->is_readonly = TRUE;
new_event.event_cards = pgroup;
} else
new_event.event_cards = 0;
new_event.event_code = event_code;
new_event.reason_effect = reason_effect;
new_event.reason = reason;
new_event.reason_player = reason_player;
new_event.event_player = event_player;
new_event.event_value = event_value;
core.queue_event.push_back(new_event);
}
void field::raise_event(card_set* event_cards, uint32 event_code, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 event_player, uint32 event_value) {
tevent new_event;
new_event.trigger_card = 0;
if (event_cards) {
group* pgroup = pduel->new_group(*event_cards);
pgroup->is_readonly = TRUE;
new_event.event_cards = pgroup;
} else
new_event.event_cards = 0;
new_event.event_code = event_code;
new_event.reason_effect = reason_effect;
new_event.reason = reason;
new_event.reason_player = reason_player;
new_event.event_player = event_player;
new_event.event_value = event_value;
core.queue_event.push_back(new_event);
}
void field::raise_single_event(card* trigger_card, card_set* event_cards, uint32 event_code, effect * reason_effect, uint32 reason, uint8 reason_player, uint8 event_player, uint32 event_value) {
tevent new_event;
new_event.trigger_card = trigger_card;
if (event_cards) {
group* pgroup = pduel->new_group(*event_cards);
pgroup->is_readonly = TRUE;
new_event.event_cards = pgroup;
} else
new_event.event_cards = 0;
new_event.event_code = event_code;
new_event.reason_effect = reason_effect;
new_event.reason = reason;
new_event.reason_player = reason_player;
new_event.event_player = event_player;
new_event.event_value = event_value;
core.single_event.push_back(new_event);
}
int32 field::check_event(uint32 code, tevent * pe) {
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.point_event) {
if(ev.event_code == code) {
2015-09-25 21:07:16 +08:00
if(pe)
2018-09-03 16:36:45 +08:00
*pe = ev;
2015-09-25 21:07:16 +08:00
return TRUE;
}
}
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.instant_event) {
if(ev.event_code == code) {
2015-09-25 21:07:16 +08:00
if(pe)
2018-09-03 16:36:45 +08:00
*pe = ev;
2015-09-25 21:07:16 +08:00
return TRUE;
}
}
return FALSE;
}
int32 field::check_event_c(effect* peffect, uint8 playerid, int32 neglect_con, int32 neglect_cost, int32 copy_info, tevent* pe) {
if(peffect->code == EVENT_FREE_CHAIN) {
return peffect->is_activate_ready(playerid, nil_event, neglect_con, neglect_cost, FALSE);
}
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.point_event) {
if(ev.event_code == peffect->code &&
peffect->is_activate_ready(playerid, ev, neglect_con, neglect_cost, FALSE)) {
2015-09-25 21:07:16 +08:00
if(pe)
2018-09-03 16:36:45 +08:00
*pe = ev;
2015-09-25 21:07:16 +08:00
if(copy_info && !pduel->lua->no_action && core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
core.current_chain.back().evt = ev;
2015-09-25 21:07:16 +08:00
}
return TRUE;
}
}
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.instant_event) {
if(ev.event_code == peffect->code &&
peffect->is_activate_ready(playerid, ev, neglect_con, neglect_cost, FALSE)) {
2015-09-25 21:07:16 +08:00
if(pe)
2018-09-03 16:36:45 +08:00
*pe = ev;
2015-09-25 21:07:16 +08:00
if(copy_info && !pduel->lua->no_action && core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
core.current_chain.back().evt = ev;
2015-09-25 21:07:16 +08:00
}
return TRUE;
}
}
return FALSE;
}
int32 field::check_hint_timing(effect* peffect) {
int32 p = peffect->get_handler_player();
if(p == 0)
return (peffect->hint_timing[0] & core.hint_timing[0]) || (peffect->hint_timing[1] & core.hint_timing[1]);
else
return (peffect->hint_timing[0] & core.hint_timing[1]) || (peffect->hint_timing[1] & core.hint_timing[0]);
}
int32 field::process_phase_event(int16 step, int32 phase) {
switch(step) {
case 0: {
2018-02-01 22:50:41 +01:00
if((phase == PHASE_DRAW && (core.force_turn_end || is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_DP)))
|| (phase == PHASE_STANDBY && (core.force_turn_end || is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_SP)))
|| (phase == PHASE_BATTLE_START && (core.force_turn_end || is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP)))) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 24;
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;
chain newchain;
core.select_chains.clear();
int32 tf_count = 0, to_count = 0, fc_count = 0, cn_count = 0;
auto pr = effects.trigger_f_effect.equal_range(phase_event);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
if(!peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
core.select_chains.push_back(newchain);
tf_count++;
}
pr = effects.continuous_effect.equal_range(phase_event);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-24 23:54:05 +09:00
//effects.continuous_effect may be changed in is_activateable (e.g. Rescue Cat)
2015-09-25 21:07:16 +08:00
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
core.select_chains.push_back(newchain);
cn_count++;
}
2017-04-10 21:16:48 +08:00
for(auto eit = effects.pheff.begin(); eit != effects.pheff.end();) {
2018-07-06 21:46:52 +08:00
effect* peffect = *eit++;
2015-09-25 21:07:16 +08:00
if(peffect->code != EFFECT_SET_CONTROL)
continue;
if(!(peffect->reset_flag & phase))
continue;
uint8 pid = peffect->get_handler_player();
2018-08-09 20:10:20 +08:00
if(pid != check_player)
continue;
2015-09-25 21:07:16 +08:00
uint8 tp = infos.turn_player;
if(!(((peffect->reset_flag & RESET_SELF_TURN) && pid == tp) || ((peffect->reset_flag & RESET_OPPO_TURN) && pid != tp)))
continue;
2017-08-14 08:02:43 +09:00
if(peffect->reset_count != 1)
2015-09-25 21:07:16 +08:00
continue;
2017-04-10 21:16:48 +08:00
card* phandler = peffect->get_handler();
if(pid != phandler->current.controler) {
2017-04-10 21:16:48 +08:00
if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY))
remove_effect(peffect);
else
2017-10-25 21:28:36 +08:00
peffect->handler->remove_effect(peffect);
2017-04-10 21:16:48 +08:00
continue;
}
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
core.select_chains.push_back(newchain);
cn_count++;
}
core.spe_effect[check_player] = 0;
if(!core.hand_adjusted) {
pr = effects.trigger_o_effect.equal_range(phase_event);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
if(!peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
core.select_chains.push_back(newchain);
to_count++;
core.spe_effect[check_player]++;
}
if(phase == PHASE_DRAW)
core.hint_timing[infos.turn_player] = TIMING_DRAW_PHASE;
else if(phase == PHASE_STANDBY)
core.hint_timing[infos.turn_player] = TIMING_STANDBY_PHASE;
2015-12-21 00:25:30 +08:00
else if(phase == PHASE_BATTLE_START)
core.hint_timing[infos.turn_player] = TIMING_BATTLE_START;
2015-09-25 21:07:16 +08:00
else if(phase == PHASE_BATTLE)
core.hint_timing[infos.turn_player] = TIMING_BATTLE_END;
2017-02-10 23:58:20 +09:00
else
2015-12-21 00:25:30 +08:00
core.hint_timing[infos.turn_player] = TIMING_END_PHASE;
2015-09-25 21:07:16 +08:00
pr = effects.activate_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(check_hint_timing(peffect))
core.spe_effect[check_player]++;
core.select_chains.push_back(newchain);
fc_count++;
}
pr = effects.quick_o_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
if(!peffect->is_chainable(check_player) || !peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(check_hint_timing(peffect))
core.spe_effect[check_player]++;
core.select_chains.push_back(newchain);
fc_count++;
}
2017-11-12 21:51:44 +09:00
pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-12 21:51:44 +09:00
if(peffect->get_handler_player() != check_player || !peffect->is_activateable(check_player, nil_event))
continue;
peffect->id = infos.field_id++;
newchain.triggering_effect = peffect;
core.select_chains.push_back(newchain);
fc_count++;
}
2015-09-25 21:07:16 +08:00
}
if(core.select_chains.size() == 0) {
returns.ivalue[0] = -1;
core.units.begin()->step = 1;
return FALSE;
} else if(tf_count == 0 && cn_count == 1 && to_count == 0 && fc_count == 0) {
returns.ivalue[0] = 0;
core.units.begin()->step = 1;
return FALSE;
} else {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(check_player);
if(infos.phase == PHASE_DRAW)
pduel->write_buffer64(20);
2015-09-25 21:07:16 +08:00
else if(infos.phase == PHASE_STANDBY)
pduel->write_buffer64(21);
2015-12-21 00:25:30 +08:00
else if(infos.phase == PHASE_BATTLE_START)
pduel->write_buffer64(28);
2015-09-25 21:07:16 +08:00
else if(infos.phase == PHASE_BATTLE)
pduel->write_buffer64(25);
2015-09-25 21:07:16 +08:00
else
pduel->write_buffer64(26);
if(tf_count == 0 && to_count == 1 && fc_count == 0 && cn_count == 0) {
add_process(PROCESSOR_SELECT_EFFECTYN, 0, 0, (group*)core.select_chains[0].triggering_effect->get_handler(), check_player, 0);
return FALSE;
} else {
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, check_player, core.spe_effect[check_player] | (tf_count + cn_count ? 0x10000 : 0));
core.units.begin()->step = 1;
return FALSE;
}
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 1: {
returns.ivalue[0]--;
return FALSE;
}
case 2: {
int32 priority_passed = core.units.begin()->arg2 & 0x1;
int32 is_opponent = core.units.begin()->arg2 & 0x2;
if(returns.ivalue[0] == -1) {
if(priority_passed)
core.units.begin()->step = 19;
else {
priority_passed = 1;
is_opponent ^= 0x2;
core.units.begin()->arg2 = is_opponent | priority_passed;
core.units.begin()->step = -1;
}
return FALSE;
}
priority_passed = 0;
core.units.begin()->arg2 = is_opponent | priority_passed;
chain newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
if(!(peffect->type & EFFECT_TYPE_ACTIONS)) {
2015-10-31 15:50:37 +09:00
if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY))
2015-09-25 21:07:16 +08:00
remove_effect(peffect);
else
2017-10-25 21:28:36 +08:00
peffect->handler->remove_effect(peffect);
2015-09-25 21:07:16 +08:00
adjust_all();
core.units.begin()->step = 3;
} else if(!(peffect->type & EFFECT_TYPE_CONTINUOUS)) {
int32 check_player = infos.turn_player;
if(is_opponent)
check_player = 1 - infos.turn_player;
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = nil_event;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
newchain.triggering_player = check_player;
core.new_chains.push_back(newchain);
2016-11-16 19:52:12 +09:00
phandler->set_status(STATUS_CHAINING, TRUE);
2015-09-25 21:07:16 +08:00
peffect->dec_count(check_player);
core.select_chains.clear();
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - check_player);
infos.priorities[0] = 0;
infos.priorities[1] = 0;
} else {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 3;
}
return FALSE;
}
case 3: {
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 4: {
2016-02-01 02:12:21 +09:00
adjust_instant();
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 20: {
if(phase != PHASE_END) {
core.units.begin()->step = 24;
return FALSE;
}
int32 limit = 6;
effect_set eset;
filter_player_effect(infos.turn_player, EFFECT_HAND_LIMIT, &eset);
if(eset.size())
limit = eset.get_last()->get_value();
int32 hd = player[infos.turn_player].list_hand.size();
if(hd <= limit) {
core.units.begin()->step = 24;
return FALSE;
}
core.select_cards.clear();
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_hand)
core.select_cards.push_back(pcard);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(infos.turn_player);
pduel->write_buffer64(501);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player, hd - limit + ((hd - limit) << 16));
return FALSE;
}
case 21: {
card_set cset;
for(int32 i = 0; i < returns.bvalue[0]; ++i)
cset.insert(core.select_cards[returns.bvalue[i + 1]]);
send_to(&cset, 0, REASON_RULE + REASON_DISCARD + REASON_ADJUST, infos.turn_player, PLAYER_NONE, LOCATION_GRAVE, 0, POS_FACEUP);
return FALSE;
}
case 22: {
core.hand_adjusted = TRUE;
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
core.units.begin()->step = -1;
core.units.begin()->arg2 = 0;
return FALSE;
}
case 25: {
core.hint_timing[infos.turn_player] = 0;
reset_phase(phase);
adjust_all();
return FALSE;
}
case 26: {
core.quick_f_chain.clear();
core.instant_event.clear();
core.point_event.clear();
2016-04-20 05:16:56 +08:00
core.full_event.clear();
2015-09-25 21:07:16 +08:00
return TRUE;
}
}
return TRUE;
}
int32 field::process_point_event(int16 step, int32 skip_trigger, int32 skip_freechain, int32 skip_new) {
switch(step) {
case 0: {
core.select_chains.clear();
core.point_event.splice(core.point_event.end(), core.instant_event);
if(skip_trigger) {
core.units.begin()->step = 7;
return FALSE;
}
core.new_fchain_s.splice(core.new_fchain_s.begin(), core.new_fchain);
core.new_ochain_s.splice(core.new_ochain_s.begin(), core.new_ochain);
core.delayed_quick.clear();
core.delayed_quick_break.swap(core.delayed_quick);
core.current_player = infos.turn_player;
core.units.begin()->step = 1;
return FALSE;
}
case 1: {
return FALSE;
}
case 2: {
//forced trigger
2017-12-17 15:26:49 +08:00
core.select_chains.clear();
for (auto clit = core.new_fchain_s.begin(); clit != core.new_fchain_s.end(); ) {
2015-09-25 21:07:16 +08:00
effect* peffect = clit->triggering_effect;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2018-08-06 13:57:48 +08:00
if(phandler->is_has_relation(*clit))
clit->set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
uint8 tp = clit->triggering_player;
bool act = true;
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
&& clit->triggering_location == LOCATION_DECK && (phandler->current.location & LOCATION_DECK)) {
if((peffect->type & EFFECT_TYPE_SINGLE) && !peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)
&& peffect->code == EVENT_TO_DECK || (peffect->range & LOCATION_DECK))
clit->flag |= CHAIN_DECK_EFFECT;
else
act = false;
}
if((peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE)) &&
(!(peffect->type & EFFECT_TYPE_FIELD) || phandler->is_has_relation(*clit)) &&
((peffect->code == EVENT_FLIP && infos.phase == PHASE_DAMAGE) ||
((clit->triggering_location & 0x43) && (clit->triggering_position & POS_FACEDOWN)) ||
!(phandler->current.location & 0x43) || phandler->is_position(POS_FACEUP))) {
2015-09-25 21:07:16 +08:00
} else
act = false;
if(act) {
2017-12-17 15:26:49 +08:00
if(tp == core.current_player)
core.select_chains.push_back(*clit);
} else {
2018-09-12 21:37:38 +08:00
peffect->active_type = 0;
2017-12-17 15:26:49 +08:00
core.new_fchain_s.erase(clit++);
continue;
2015-09-25 21:07:16 +08:00
}
2017-12-17 15:26:49 +08:00
++clit;
2015-09-25 21:07:16 +08:00
}
2017-12-17 15:26:49 +08:00
if(core.select_chains.size() == 0) {
returns.ivalue[0] = -1;
} else if(core.select_chains.size() == 1) {
returns.ivalue[0] = 0;
2015-09-25 21:07:16 +08:00
} else {
2017-12-17 15:26:49 +08:00
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, core.current_player, 0x7f | 0x10000);
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 3: {
2017-12-17 15:26:49 +08:00
if(returns.ivalue[0] == -1) {
if(core.new_fchain_s.size()) {
core.current_player = 1 - infos.turn_player;
core.units.begin()->step = 1;
} else {
core.current_player = infos.turn_player;
}
return FALSE;
2015-09-25 21:07:16 +08:00
}
2017-12-17 15:26:49 +08:00
chain newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
uint8 tp = newchain.triggering_player;
peffect->get_handler()->set_status(STATUS_CHAINING, TRUE);
peffect->dec_count(tp);
core.new_chains.push_back(newchain);
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
2018-09-03 16:36:45 +08:00
core.new_fchain_s.remove_if([chain_id = newchain.chain_id](chain ch) { return ch.chain_id == chain_id; });
2017-12-17 15:26:49 +08:00
core.units.begin()->step = 1;
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 4: {
//optional trigger
2017-12-17 15:26:49 +08:00
core.select_chains.clear();
for (auto clit = core.new_ochain_s.begin(); clit != core.new_ochain_s.end(); ) {
2015-09-25 21:07:16 +08:00
effect* peffect = clit->triggering_effect;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2018-08-06 13:57:48 +08:00
if(phandler->is_has_relation(*clit))
clit->set_triggering_place(phandler);
2018-07-27 09:49:06 +08:00
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY) && (peffect->type & EFFECT_TYPE_FIELD)
&& (peffect->range & LOCATION_HAND) && phandler->current.location == LOCATION_HAND) {
2018-11-01 11:36:11 +08:00
if(!phandler->is_has_relation(*clit) && peffect->is_condition_check(phandler->current.controler, clit->evt))
2016-11-16 19:52:12 +09:00
phandler->create_relation(*clit);
2018-11-01 11:36:11 +08:00
peffect->set_activate_location();
2016-11-16 19:52:12 +09:00
clit->triggering_player = phandler->current.controler;
2017-04-12 09:35:29 +09:00
clit->set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
}
2017-12-17 15:26:49 +08:00
uint8 tp = clit->triggering_player;
bool act = true;
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
&& ((peffect->type & EFFECT_TYPE_SINGLE) && !peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)
&& phandler->is_has_relation(*clit) && clit->triggering_location == LOCATION_HAND
|| (peffect->range & LOCATION_HAND))) {
clit->flag |= CHAIN_HAND_TRIGGER;
core.new_ochain_h.push_back(*clit);
if(clit->triggering_location == LOCATION_HAND && phandler->is_position(POS_FACEDOWN)
|| peffect->range && !peffect->in_range(*clit))
act = false;
}
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
&& clit->triggering_location == LOCATION_DECK && (phandler->current.location & LOCATION_DECK)) {
if((peffect->type & EFFECT_TYPE_SINGLE) && !peffect->is_flag(EFFECT_FLAG_SINGLE_RANGE)
&& peffect->code == EVENT_TO_DECK || (peffect->range & LOCATION_DECK))
clit->flag |= CHAIN_DECK_EFFECT;
else
act = false;
}
if(peffect->is_chainable(tp) && peffect->is_activateable(tp, clit->evt, TRUE) &&
(!(peffect->type & EFFECT_TYPE_FIELD) || phandler->is_has_relation(*clit)) &&
((peffect->code == EVENT_FLIP && infos.phase == PHASE_DAMAGE) ||
((clit->triggering_location & 0x43) && (clit->triggering_position & POS_FACEDOWN)) ||
!(phandler->current.location & 0x43) ||
phandler->is_position(POS_FACEUP))) {
if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY) || !(peffect->type & EFFECT_TYPE_FIELD) || peffect->in_range(*clit)) {
if((peffect->status & EFFECT_STATUS_SPSELF) && (clit->flag & CHAIN_HAND_TRIGGER)) {
2018-09-03 16:36:45 +08:00
for(const auto& cur_ch : core.current_chain) {
if(cur_ch.triggering_player == tp
&& (cur_ch.triggering_effect->status & EFFECT_STATUS_SPSELF) && (cur_ch.flag & CHAIN_HAND_TRIGGER)) {
act = false;
break;
}
}
}
} else
act = false;
2017-12-17 15:26:49 +08:00
} else act = false;
if(act) {
if(tp == core.current_player)
core.select_chains.push_back(*clit);
} else {
2018-09-12 21:37:38 +08:00
peffect->active_type = 0;
2017-12-17 15:26:49 +08:00
core.new_ochain_s.erase(clit++);
continue;
2015-09-25 21:07:16 +08:00
}
2017-12-17 15:26:49 +08:00
++clit;
}
if(core.select_chains.size() == 0) {
returns.ivalue[0] = -1;
core.units.begin()->step = 5;
return FALSE;
} else if(core.select_chains.size() == 1 && !core.current_chain.size()) {
add_process(PROCESSOR_SELECT_EFFECTYN, 0, 0, (group*)core.select_chains[0].triggering_effect->get_handler(), core.current_player, 0);
return FALSE;
} else {
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, core.current_player, 0x7f);
core.units.begin()->step = 5;
return FALSE;
}
return FALSE;
}
case 5: {
returns.ivalue[0]--;
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 6: {
2017-12-17 15:26:49 +08:00
if(returns.ivalue[0] == -1) {
2018-09-12 21:37:38 +08:00
for(const auto& ch : core.select_chains) {
ch.triggering_effect->active_type = 0;
2018-09-03 16:36:45 +08:00
core.new_ochain_s.remove_if([chain_id = ch.chain_id](chain ch) { return ch.chain_id == chain_id; });
2018-09-12 21:37:38 +08:00
}
2017-12-17 15:26:49 +08:00
if(core.new_ochain_s.size()) {
core.current_player = 1 - infos.turn_player;
core.units.begin()->step = 3;
} else {
core.current_player = infos.turn_player;
core.units.begin()->step = 6;
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
2017-12-17 15:26:49 +08:00
chain newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
uint8 tp = newchain.triggering_player;
2016-11-16 19:52:12 +09:00
peffect->get_handler()->set_status(STATUS_CHAINING, TRUE);
2015-09-25 21:07:16 +08:00
peffect->dec_count(tp);
2017-12-17 15:26:49 +08:00
core.new_chains.push_back(newchain);
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
2018-09-03 16:36:45 +08:00
core.new_ochain_s.remove_if([chain_id = newchain.chain_id](chain ch) { return ch.chain_id == chain_id; });
core.new_ochain_h.remove_if([chain_id = newchain.chain_id](chain ch) { return ch.chain_id == chain_id; });
2017-12-17 15:26:49 +08:00
core.units.begin()->step = 3;
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 7: {
2017-12-17 15:26:49 +08:00
core.select_chains.clear();
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 8: {
2018-02-01 22:50:41 +01:00
if(!(core.duel_options & DUEL_OBSOLETE_IGNITION) || (infos.phase != PHASE_MAIN1 && infos.phase != PHASE_MAIN2))
2015-09-25 21:07:16 +08:00
return FALSE;
// Obsolete ignition effect ruling
tevent e;
if(core.current_chain.size() == 0 &&
(check_event(EVENT_SUMMON_SUCCESS, &e) || check_event(EVENT_SPSUMMON_SUCCESS, &e) || check_event(EVENT_FLIP_SUMMON_SUCCESS, &e))
&& e.reason_player == infos.turn_player) {
chain newchain;
tevent e;
e.event_cards = 0;
e.event_value = 0;
e.event_player = PLAYER_NONE;
e.reason_effect = 0;
e.reason = 0;
e.reason_player = PLAYER_NONE;
2018-03-07 09:50:28 +09:00
for(auto eit = effects.ignition_effect.begin(); eit != effects.ignition_effect.end();) {
2015-09-25 21:07:16 +08:00
effect* peffect = eit->second;
2018-03-07 09:50:28 +09:00
++eit;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
e.event_code = peffect->code;
2016-11-16 19:52:12 +09:00
if(phandler->current.location == LOCATION_MZONE && peffect->is_chainable(infos.turn_player)
2015-09-25 21:07:16 +08:00
&& peffect->is_activateable(infos.turn_player, e)) {
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = e;
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
newchain.triggering_player = infos.turn_player;
2018-10-13 22:10:13 +08:00
core.tmp_chains.push_back(newchain);
2015-09-25 21:07:16 +08:00
}
}
}
return FALSE;
}
case 9: {
infos.priorities[0] = 0;
infos.priorities[1] = 0;
if(core.current_chain.size() == 0) {
if(!core.hand_adjusted)
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, skip_freechain, infos.turn_player);
} else
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, skip_freechain, 1 - core.current_chain.back().triggering_player);
return FALSE;
}
case 10: {
core.new_ochain_h.clear();
2016-05-03 13:31:23 +08:00
core.full_event.clear();
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2015-09-25 21:07:16 +08:00
if(core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, skip_trigger | ((skip_freechain | skip_new) << 8), skip_new);
} else {
core.used_event.splice(core.used_event.end(), core.point_event);
2018-09-03 16:36:45 +08:00
for(auto& ch_lim_p : core.chain_limit_p)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim_p.function);
2017-07-23 18:03:58 +09:00
core.chain_limit_p.clear();
2015-09-25 21:07:16 +08:00
reset_chain();
returns.ivalue[0] = FALSE;
}
return TRUE;
}
2017-11-12 21:51:44 +09:00
case 30: {
int32 check_player = infos.turn_player;
nil_event.event_code = EVENT_FREE_CHAIN;
chain newchain;
core.select_chains.clear();
core.spe_effect[check_player] = 0;
auto pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-12 21:51:44 +09:00
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, nil_event)) {
core.select_chains.push_back(newchain);
core.spe_effect[check_player]++;
}
}
if(!core.select_chains.empty())
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, check_player, core.spe_effect[check_player]);
else
core.units.begin()->step = 31;
return FALSE;
}
case 31: {
if(returns.ivalue[0] == -1)
return FALSE;
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);
2017-11-12 21:51:44 +09:00
core.units.begin()->step = 29;
return FALSE;
}
case 32: {
int32 check_player = 1 - infos.turn_player;
nil_event.event_code = EVENT_FREE_CHAIN;
chain newchain;
core.select_chains.clear();
core.spe_effect[check_player] = 0;
auto pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-12 21:51:44 +09:00
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == check_player && peffect->is_activateable(check_player, nil_event)) {
core.select_chains.push_back(newchain);
core.spe_effect[check_player]++;
}
}
if(!core.select_chains.empty())
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, check_player, core.spe_effect[check_player]);
else
core.units.begin()->step = -1;
return FALSE;
}
case 33: {
2017-12-19 19:36:12 +09:00
if(returns.ivalue[0] == -1) {
core.units.begin()->step = -1;
2017-11-12 21:51:44 +09:00
return FALSE;
2017-12-19 19:36:12 +09:00
}
2017-11-12 21:51:44 +09:00
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);
2017-11-12 21:51:44 +09:00
core.units.begin()->step = 31;
return FALSE;
}
2015-09-25 21:07:16 +08:00
}
return TRUE;
}
int32 field::process_quick_effect(int16 step, int32 skip_freechain, uint8 priority) {
switch(step) {
case 0: {
2018-08-01 21:49:49 +08:00
uint8 check_player = infos.turn_player;
if(core.units.begin()->arg3)
check_player = 1 - infos.turn_player;
core.select_chains.clear();
for(auto ifit = core.quick_f_chain.begin(); ifit != core.quick_f_chain.end(); ) {
2016-05-07 06:13:42 +09:00
effect* peffect = ifit->first;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
if(peffect->is_chainable(ifit->second.triggering_player) && peffect->check_count_limit(ifit->second.triggering_player)
2016-11-16 19:52:12 +09:00
&& phandler->is_has_relation(ifit->second)) {
2018-08-01 21:49:49 +08:00
if(ifit->second.triggering_player == check_player)
core.select_chains.push_back(ifit->second);
} else {
core.quick_f_chain.erase(ifit++);
continue;
2015-09-25 21:07:16 +08:00
}
2018-08-01 21:49:49 +08:00
++ifit;
2015-09-25 21:07:16 +08:00
}
2018-08-01 21:49:49 +08:00
if(core.select_chains.size() == 0)
returns.ivalue[0] = -1;
else if(core.select_chains.size() == 1)
returns.ivalue[0] = 0;
else
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, check_player, 0x10000);
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 1: {
2018-08-01 21:49:49 +08:00
if(returns.ivalue[0] == -1) {
if(core.quick_f_chain.size()) {
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = -1;
} else if(core.new_chains.size()) {
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - core.new_chains.back().triggering_player);
infos.priorities[0] = 0;
infos.priorities[1] = 0;
return TRUE;
}
return FALSE;
}
chain newchain = core.select_chains[returns.ivalue[0]];
effect* peffect = newchain.triggering_effect;
uint8 tp = newchain.triggering_player;
peffect->get_handler()->set_status(STATUS_CHAINING, TRUE);
peffect->dec_count(tp);
core.new_chains.push_back(newchain);
core.quick_f_chain.erase(peffect);
core.units.begin()->step = -1;
return FALSE;
}
case 2: {
chain newchain;
2018-10-13 22:10:13 +08:00
if(core.tmp_chains.size())
core.select_chains.swap(core.tmp_chains);
2018-09-12 10:49:49 +08:00
for(auto evit = core.point_event.begin(); evit != core.instant_event.end(); ++evit) {
2018-09-03 21:51:53 +08:00
if(evit == core.point_event.end())
evit = core.instant_event.begin();
2018-08-01 21:49:49 +08:00
auto pr = effects.activate_effect.equal_range(evit->event_code);
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
if(!peffect->is_flag(EFFECT_FLAG_DELAY) && peffect->is_chainable(priority) && peffect->is_activateable(priority, *evit)) {
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = *evit;
newchain.triggering_effect = peffect;
newchain.set_triggering_place(phandler);
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
}
}
pr = effects.quick_o_effect.equal_range(evit->event_code);
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, *evit)) {
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = *evit;
newchain.triggering_effect = peffect;
newchain.set_triggering_place(phandler);
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
core.delayed_quick_tmp.erase(std::make_pair(peffect, *evit));
core.delayed_quick_break.erase(std::make_pair(peffect, *evit));
}
}
}
2018-09-03 16:36:45 +08:00
for(auto& ch : core.new_ochain_h) {
effect* peffect = ch.triggering_effect;
2018-08-01 21:49:49 +08:00
card* phandler = peffect->get_handler();
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY) && (peffect->type & EFFECT_TYPE_FIELD)
&& (peffect->range & LOCATION_HAND) && phandler->current.location == LOCATION_HAND) {
2018-11-01 11:36:11 +08:00
if(!phandler->is_has_relation(ch) && peffect->is_condition_check(phandler->current.controler, ch.evt))
2018-09-03 16:36:45 +08:00
phandler->create_relation(ch);
2018-11-01 11:36:11 +08:00
peffect->set_activate_location();
2018-09-03 16:36:45 +08:00
ch.triggering_player = phandler->current.controler;
ch.set_triggering_place(phandler);
2018-08-01 21:49:49 +08:00
}
bool act = true;
2018-09-03 16:36:45 +08:00
if(ch.triggering_player == priority && ch.triggering_location == LOCATION_HAND
&& phandler->is_position(POS_FACEDOWN) && !phandler->is_status(STATUS_CHAINING) && phandler->is_has_relation(ch)
&& peffect->is_chainable(priority) && peffect->is_activateable(priority, ch.evt, TRUE)) {
2018-08-01 21:49:49 +08:00
if(peffect->status & EFFECT_STATUS_SPSELF) {
2018-09-03 16:36:45 +08:00
for(const auto& cur_ch : core.current_chain) {
if(cur_ch.triggering_player == priority
&& (cur_ch.triggering_effect->status & EFFECT_STATUS_SPSELF) && (cur_ch.flag & CHAIN_HAND_TRIGGER)) {
2018-08-01 21:49:49 +08:00
act = false;
break;
}
2015-09-25 21:07:16 +08:00
}
}
2018-08-01 21:49:49 +08:00
} else
act = false;
if(act)
2018-09-03 16:36:45 +08:00
core.select_chains.push_back(ch);
2018-08-01 21:49:49 +08:00
}
//delayed activate
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.full_event) {
auto pr = effects.activate_effect.equal_range(ev.event_code);
2018-08-01 21:49:49 +08:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
peffect->set_activate_location();
2018-09-03 16:36:45 +08:00
if(peffect->is_flag(EFFECT_FLAG_DELAY) && peffect->is_chainable(priority) && peffect->is_activateable(priority, ev)) {
2018-08-01 21:49:49 +08:00
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
2018-09-03 16:36:45 +08:00
newchain.evt = ev;
2018-08-01 21:49:49 +08:00
newchain.triggering_effect = peffect;
newchain.set_triggering_place(phandler);
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
2015-09-25 21:07:16 +08:00
}
}
2018-08-01 21:49:49 +08:00
}
// delayed quick
for(auto eit = core.delayed_quick.begin(); eit != core.delayed_quick.end();) {
effect* peffect = eit->first;
const tevent& evt = eit->second;
++eit;
peffect->set_activate_location();
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, evt, TRUE, FALSE, FALSE)) {
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2018-08-01 21:49:49 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = evt;
newchain.triggering_effect = peffect;
newchain.set_triggering_place(phandler);
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
2016-04-20 05:16:56 +08:00
}
2018-08-01 21:49:49 +08:00
}
core.spe_effect[priority] = core.select_chains.size();
if(!skip_freechain) {
nil_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;
2018-03-07 09:50:28 +09:00
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2018-08-01 21:49:49 +08:00
if(peffect->is_chainable(priority) && peffect->is_activateable(priority, nil_event)) {
2017-08-13 11:13:41 +09:00
card* phandler = peffect->get_handler();
2016-03-26 01:01:46 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
2018-08-01 21:49:49 +08:00
newchain.evt = nil_event;
2016-03-26 01:01:46 +08:00
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2016-03-26 01:01:46 +08:00
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
2018-08-01 21:49:49 +08:00
if(check_hint_timing(peffect))
core.spe_effect[priority]++;
2015-09-25 21:07:16 +08:00
}
}
2018-08-01 21:49:49 +08:00
pr = effects.quick_o_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)) {
card* phandler = peffect->get_handler();
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = nil_event;
newchain.triggering_effect = peffect;
newchain.set_triggering_place(phandler);
newchain.triggering_player = priority;
core.select_chains.push_back(newchain);
if(check_hint_timing(peffect))
core.spe_effect[priority]++;
2015-09-25 21:07:16 +08:00
}
}
}
2018-08-01 21:49:49 +08:00
if(core.current_chain.size() || (core.hint_timing[0] & TIMING_ATTACK) || (core.hint_timing[1] & TIMING_ATTACK))
core.spe_effect[priority] = core.select_chains.size();
add_process(PROCESSOR_SELECT_CHAIN, 0, 0, 0, priority, core.spe_effect[priority]);
2015-09-25 21:07:16 +08:00
return FALSE;
}
2018-08-01 21:49:49 +08:00
case 3: {
2015-09-25 21:07:16 +08:00
if(core.select_chains.size() && returns.ivalue[0] != -1) {
chain newchain = core.select_chains[returns.ivalue[0]];
core.new_chains.push_back(newchain);
effect* peffect = newchain.triggering_effect;
2016-01-06 00:30:55 +09:00
core.delayed_quick.erase(std::make_pair(peffect, newchain.evt));
2016-11-16 19:52:12 +09:00
peffect->get_handler()->set_status(STATUS_CHAINING, TRUE);
2015-09-25 21:07:16 +08:00
peffect->dec_count(priority);
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - priority);
infos.priorities[0] = 0;
infos.priorities[1] = 0;
} else {
infos.priorities[priority] = 1;
if(!infos.priorities[0] || !infos.priorities[1])
add_process(PROCESSOR_QUICK_EFFECT, 1, 0, 0, skip_freechain, 1 - priority);
else {
core.hint_timing[0] &= TIMING_DAMAGE_STEP | TIMING_DAMAGE_CAL;
core.hint_timing[1] &= TIMING_DAMAGE_STEP | TIMING_DAMAGE_CAL;
core.delayed_quick.clear();
}
}
core.select_chains.clear();
return TRUE;
}
}
return TRUE;
}
int32 field::process_instant_event() {
if (core.queue_event.size() == 0)
return TRUE;
chain newchain;
chain_list tp;
chain_list ntp;
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.queue_event) {
2015-09-25 21:07:16 +08:00
//continuous events
2018-09-03 16:36:45 +08:00
auto pr = effects.continuous_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2015-09-25 21:07:16 +08:00
uint8 owner_player = peffect->get_handler_player();
2018-09-03 16:36:45 +08:00
if(peffect->is_activateable(owner_player, ev)) {
newchain.chain_id = 0;
newchain.chain_count = 0;
newchain.triggering_effect = peffect;
newchain.triggering_player = owner_player;
2018-09-03 16:36:45 +08:00
newchain.evt = ev;
newchain.target_cards = 0;
newchain.target_player = PLAYER_NONE;
newchain.target_param = 0;
newchain.disable_player = PLAYER_NONE;
newchain.disable_reason = 0;
newchain.flag = 0;
if(peffect->is_flag(EFFECT_FLAG_DELAY) && (core.chain_solving || core.conti_solving)) {
if(owner_player == infos.turn_player)
core.delayed_continuous_tp.push_back(newchain);
else
core.delayed_continuous_ntp.push_back(newchain);
2015-09-25 21:07:16 +08:00
} else {
if(owner_player == infos.turn_player)
tp.push_back(newchain);
else
ntp.push_back(newchain);
2015-09-25 21:07:16 +08:00
}
}
}
2018-09-03 16:36:45 +08:00
if(ev.event_code == EVENT_ADJUST || ((ev.event_code & 0xf000) == EVENT_PHASE_START))
2015-09-25 21:07:16 +08:00
continue;
//triggers
2018-09-03 16:36:45 +08:00
pr = effects.trigger_f_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2018-09-03 16:36:45 +08:00
if(!phandler->is_status(STATUS_EFFECT_ENABLED) || !peffect->is_condition_check(phandler->current.controler, ev))
2015-09-25 21:07:16 +08:00
continue;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
2018-09-03 16:36:45 +08:00
newchain.evt = ev;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2018-09-03 16:36:45 +08:00
if(peffect->is_flag(EFFECT_FLAG_EVENT_PLAYER) && (ev.event_player == 0 || ev.event_player == 1))
newchain.triggering_player = ev.event_player;
2018-11-01 11:36:11 +08:00
else
newchain.triggering_player = phandler->current.controler;
2015-09-25 21:07:16 +08:00
core.new_fchain.push_back(newchain);
2016-11-16 19:52:12 +09:00
phandler->create_relation(newchain);
2015-09-25 21:07:16 +08:00
}
2018-09-03 16:36:45 +08:00
pr = effects.trigger_o_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2018-11-01 11:36:11 +08:00
bool act = phandler->is_status(STATUS_EFFECT_ENABLED) && peffect->is_condition_check(phandler->current.controler, ev);
if(!act && !(peffect->range & LOCATION_HAND))
2015-09-25 21:07:16 +08:00
continue;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
2018-09-03 16:36:45 +08:00
newchain.evt = ev;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2018-09-03 16:36:45 +08:00
if(peffect->is_flag(EFFECT_FLAG_EVENT_PLAYER) && (ev.event_player == 0 || ev.event_player == 1))
newchain.triggering_player = ev.event_player;
2018-11-01 11:36:11 +08:00
else
newchain.triggering_player = phandler->current.controler;
2015-09-25 21:07:16 +08:00
core.new_ochain.push_back(newchain);
2016-03-18 16:14:56 +08:00
if(peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
2018-11-01 11:36:11 +08:00
|| !(peffect->range & LOCATION_HAND)
|| (peffect->range & phandler->current.location) && act)
2016-11-16 19:52:12 +09:00
phandler->create_relation(newchain);
2015-09-25 21:07:16 +08:00
}
//instant_f
2018-09-03 16:36:45 +08:00
pr = effects.quick_f_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2018-09-03 16:36:45 +08:00
if(peffect->is_activateable(phandler->current.controler, ev)) {
2015-09-25 21:07:16 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
2018-09-04 19:36:20 +02:00
newchain.evt = ev;
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2018-09-03 16:36:45 +08:00
if(peffect->is_flag(EFFECT_FLAG_EVENT_PLAYER) && (ev.event_player == 0 || ev.event_player == 1))
newchain.triggering_player = ev.event_player;
2018-11-01 11:36:11 +08:00
else
newchain.triggering_player = phandler->current.controler;
2015-09-25 21:07:16 +08:00
core.quick_f_chain[peffect] = newchain;
2016-11-16 19:52:12 +09:00
phandler->create_relation(newchain);
2015-09-25 21:07:16 +08:00
}
}
2016-04-20 05:16:56 +08:00
// delayed activate effect
2018-09-03 16:36:45 +08:00
core.full_event.push_back(ev);
2016-04-20 05:16:56 +08:00
// delayed quick effect
2018-09-03 16:36:45 +08:00
pr = effects.quick_o_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2018-09-03 16:36:45 +08:00
if(peffect->is_flag(EFFECT_FLAG_DELAY) && peffect->is_condition_check(peffect->get_handler()->current.controler, ev))
core.delayed_quick_tmp.emplace(peffect, ev);
2015-09-25 21:07:16 +08:00
}
}
while(tp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), tp, tp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
}
while(ntp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), ntp, ntp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
}
core.instant_event.splice(core.instant_event.end(), core.queue_event);
return TRUE;
}
int32 field::process_single_event() {
if(core.single_event.size() == 0)
return TRUE;
chain_list tp;
chain_list ntp;
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.single_event) {
card* starget = ev.trigger_card;
auto pr = starget->single_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2018-09-03 16:36:45 +08:00
process_single_event(peffect, ev, tp, ntp);
2016-11-16 19:52:12 +09:00
}
2018-09-03 16:36:45 +08:00
for(auto& pcard : starget->xyz_materials) {
pr = pcard->xmaterial_effect.equal_range(ev.event_code);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2016-11-26 11:57:24 +09:00
if(peffect->type & EFFECT_TYPE_FIELD)
continue;
2018-09-03 16:36:45 +08:00
process_single_event(peffect, ev, tp, ntp);
2015-09-25 21:07:16 +08:00
}
}
}
while(tp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), tp, tp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
}
while(ntp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), ntp, ntp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
}
core.single_event.clear();
return TRUE;
}
int32 field::process_single_event(effect* peffect, const tevent& e, chain_list& tp, chain_list& ntp) {
2016-11-16 19:52:12 +09:00
if(!(peffect->type & EFFECT_TYPE_ACTIONS))
return FALSE;
if((peffect->type & EFFECT_TYPE_FLIP) && (e.event_value & (NO_FLIP_EFFECT >> 16)))
return FALSE;
//continuous & trigger (single)
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
uint8 owner_player = peffect->get_handler_player();
if(peffect->is_activateable(owner_player, e)) {
chain newchain;
newchain.chain_id = 0;
newchain.chain_count = 0;
newchain.triggering_effect = peffect;
newchain.triggering_player = owner_player;
newchain.evt = e;
newchain.target_cards = 0;
newchain.target_player = PLAYER_NONE;
newchain.target_param = 0;
newchain.disable_player = PLAYER_NONE;
newchain.disable_reason = 0;
newchain.flag = 0;
2016-11-16 19:52:12 +09:00
if(peffect->is_flag(EFFECT_FLAG_DELAY) && (core.chain_solving || core.conti_solving)) {
if(owner_player == infos.turn_player)
core.delayed_continuous_tp.push_back(newchain);
else
core.delayed_continuous_ntp.push_back(newchain);
2016-11-16 19:52:12 +09:00
} else {
if(owner_player == infos.turn_player)
tp.push_back(newchain);
else
ntp.push_back(newchain);
2016-11-16 19:52:12 +09:00
}
}
} else {
card* phandler = peffect->get_handler();
if(!peffect->is_condition_check(phandler->current.controler, e))
return FALSE;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2016-11-16 19:52:12 +09:00
chain newchain;
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt = e;
newchain.triggering_effect = peffect;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2016-11-16 19:52:12 +09:00
if(peffect->is_flag(EFFECT_FLAG_EVENT_PLAYER) && (e.event_player == 0 || e.event_player == 1))
newchain.triggering_player = e.event_player;
else {
if(phandler->current.reason & REASON_TEMPORARY)
newchain.triggering_player = phandler->previous.controler;
else
newchain.triggering_player = newchain.triggering_controler;
}
if(core.flip_delayed && e.event_code == EVENT_FLIP) {
if (peffect->type & EFFECT_TYPE_TRIGGER_O)
core.new_ochain_b.push_back(newchain);
else
core.new_fchain_b.push_back(newchain);
} else {
if (peffect->type & EFFECT_TYPE_TRIGGER_O)
core.new_ochain.push_back(newchain);
else
core.new_fchain.push_back(newchain);
}
2018-09-12 21:37:38 +08:00
peffect->set_active_type();
2016-11-16 19:52:12 +09:00
phandler->create_relation(newchain);
effect* deffect;
if((deffect = phandler->is_affected_by_effect(EFFECT_DISABLE_EFFECT))) {
2016-11-16 19:52:12 +09:00
effect* negeff = pduel->new_effect();
negeff->owner = deffect->owner;
negeff->type = EFFECT_TYPE_SINGLE;
negeff->code = EFFECT_DISABLE_CHAIN;
negeff->value = newchain.chain_id;
negeff->reset_flag = RESET_EVENT | deffect->get_value();
phandler->add_effect(negeff);
}
}
return TRUE;
}
2015-09-25 21:07:16 +08:00
int32 field::process_idle_command(uint16 step) {
switch(step) {
case 0: {
effect* peffect;
bool must_attack = false;
2015-09-25 21:07:16 +08:00
core.select_chains.clear();
chain newchain;
nil_event.event_code = EVENT_FREE_CHAIN;
core.to_bp = TRUE;
core.to_ep = TRUE;
2018-02-01 22:50:41 +01:00
if((!(core.duel_options & DUEL_ATTACK_FIRST_TURN) && infos.turn_id == 1 && !(is_player_affected_by_effect(infos.turn_player, EFFECT_BP_FIRST_TURN))) || infos.phase == PHASE_MAIN2 || is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_BP) || core.force_turn_end)
2015-09-25 21:07:16 +08:00
core.to_bp = FALSE;
if(infos.phase == PHASE_MAIN1) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_mzone) {
if(pcard && pcard->is_capable_attack() && pcard->is_affected_by_effect(EFFECT_MUST_ATTACK)) {
must_attack = true;
break;
}
}
if(core.to_bp && (must_attack || is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_EP)))
core.to_ep = FALSE;
}
2015-09-25 21:07:16 +08:00
if((infos.phase == PHASE_MAIN1 && is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_M1))
2018-02-01 22:50:41 +01:00
|| (infos.phase == PHASE_MAIN2 && is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_M2)) || core.force_turn_end) {
2015-09-25 21:07:16 +08:00
if(core.to_bp && core.to_ep) {
core.select_options.clear();
core.select_options.push_back(80);
core.select_options.push_back(81);
add_process(PROCESSOR_SELECT_OPTION, 0, 0, 0, infos.turn_player, 0);
core.units.begin()->step = 11;
} else if(core.to_bp) {
core.units.begin()->arg1 = 6;
core.units.begin()->step = 10;
reset_phase(infos.phase);
adjust_all();
} else {
core.units.begin()->arg1 = 7;
core.units.begin()->step = 10;
reset_phase(infos.phase);
adjust_all();
}
return FALSE;
}
if((infos.phase == PHASE_MAIN2) && core.skip_m2) {
core.skip_m2 = FALSE;
returns.ivalue[0] = 7;
return FALSE;
}
2015-09-25 21:07:16 +08:00
auto pr = effects.activate_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
pr = effects.quick_o_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
2017-11-12 21:51:44 +09:00
pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-12 21:51:44 +09:00
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
2018-03-07 09:50:28 +09:00
for(auto eit = effects.ignition_effect.begin(); eit != effects.ignition_effect.end();) {
2015-09-25 21:07:16 +08:00
peffect = eit->second;
2018-03-07 09:50:28 +09:00
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
core.summonable_cards.clear();
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_hand)
if(pcard->is_can_be_summoned(infos.turn_player, FALSE, 0, 0))
core.summonable_cards.push_back(pcard);
for(auto& pcard : player[infos.turn_player].list_mzone) {
2017-03-19 23:33:20 +09:00
if(pcard && pcard->is_can_be_summoned(infos.turn_player, FALSE, 0, 0))
core.summonable_cards.push_back(pcard);
2015-09-25 21:07:16 +08:00
}
core.spsummonable_cards.clear();
effect_set eset;
filter_field_effect(EFFECT_SPSUMMON_PROC, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
2017-03-19 23:33:20 +09:00
card* pcard = eset[i]->get_handler();
2015-09-25 21:07:16 +08:00
if(!eset[i]->check_count_limit(pcard->current.controler))
continue;
if(pcard->current.controler == infos.turn_player && pcard->is_special_summonable(infos.turn_player, 0))
core.spsummonable_cards.push_back(pcard);
}
eset.clear();
filter_field_effect(EFFECT_SPSUMMON_PROC_G, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
2017-03-19 23:33:20 +09:00
card* pcard = eset[i]->get_handler();
2015-09-25 21:07:16 +08:00
if(!eset[i]->check_count_limit(infos.turn_player))
continue;
2016-03-18 16:14:56 +08:00
if(pcard->current.controler != infos.turn_player && !eset[i]->is_flag(EFFECT_FLAG_BOTH_SIDE))
2015-09-25 21:07:16 +08:00
continue;
effect* oreason = core.reason_effect;
uint8 op = core.reason_player;
core.reason_effect = eset[i];
core.reason_player = pcard->current.controler;
save_lp_cost();
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
if(pduel->lua->check_condition(eset[i]->condition, 2))
core.spsummonable_cards.push_back(pcard);
restore_lp_cost();
core.reason_effect = oreason;
core.reason_player = op;
}
core.repositionable_cards.clear();
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_mzone) {
2015-09-25 21:07:16 +08:00
if(pcard && ((pcard->is_position(POS_FACEUP | POS_FACEDOWN_ATTACK) && pcard->is_capable_change_position(infos.turn_player))
|| (pcard->is_position(POS_FACEDOWN) && pcard->is_can_be_flip_summoned(infos.turn_player))))
2017-03-19 23:33:20 +09:00
core.repositionable_cards.push_back(pcard);
2015-09-25 21:07:16 +08:00
}
core.msetable_cards.clear();
core.ssetable_cards.clear();
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_hand) {
if(pcard->is_setable_mzone(infos.turn_player, FALSE, 0, 0))
core.msetable_cards.push_back(pcard);
if(pcard->is_setable_szone(infos.turn_player))
core.ssetable_cards.push_back(pcard);
2015-09-25 21:07:16 +08:00
}
add_process(PROCESSOR_SELECT_IDLECMD, 0, 0, 0, infos.turn_player, 0);
return FALSE;
}
case 1: {
uint32 ctype = returns.ivalue[0] & 0xffff;
uint32 sel = returns.ivalue[0] >> 16;
if(ctype == 5) {
chain newchain = core.select_chains[sel];
effect* peffect = newchain.triggering_effect;
2017-11-12 21:51:44 +09:00
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
2017-11-12 21:51:44 +09:00
core.units.begin()->step = -1;
return FALSE;
}
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt.event_code = peffect->code;
newchain.evt.event_player = PLAYER_NONE;
newchain.evt.event_value = 0;
newchain.evt.event_cards = 0;
newchain.evt.reason = 0;
newchain.evt.reason_effect = 0;
newchain.evt.reason_player = PLAYER_NONE;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
newchain.triggering_player = infos.turn_player;
core.new_chains.push_back(newchain);
2016-11-16 19:52:12 +09:00
phandler->set_status(STATUS_CHAINING, TRUE);
2015-09-25 21:07:16 +08:00
peffect->dec_count(infos.turn_player);
core.select_chains.clear();
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - infos.turn_player);
infos.priorities[0] = 0;
infos.priorities[1] = 0;
core.select_chains.clear();
return FALSE;
} else if(ctype == 0) {
core.units.begin()->step = 4;
return FALSE;
} else if(ctype == 1) {
core.units.begin()->step = 5;
return FALSE;
} else if(ctype == 2) {
core.units.begin()->step = 6;
return FALSE;
} else if(ctype == 3) {
core.units.begin()->step = 7;
return FALSE;
} else if(ctype == 4) {
core.units.begin()->step = 8;
return FALSE;
} else if (ctype == 8) {
core.units.begin()->step = -1;
shuffle(infos.turn_player, LOCATION_HAND);
infos.can_shuffle = FALSE;
return FALSE;
} else {
core.units.begin()->step = 9;
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1 - infos.turn_player);
pduel->write_buffer64(23);
2015-09-25 21:07:16 +08:00
core.select_chains.clear();
core.hint_timing[infos.turn_player] = TIMING_MAIN_END;
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - infos.turn_player);
infos.priorities[infos.turn_player] = 1;
infos.priorities[1 - infos.turn_player] = 0;
core.units.begin()->arg1 = ctype;
return FALSE;
}
return TRUE;
}
case 2: {
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 5: {
card* target = core.summonable_cards[returns.ivalue[0] >> 16];
core.summon_cancelable = TRUE;
2015-09-25 21:07:16 +08:00
summon(infos.turn_player, target, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 6: {
card* target = core.spsummonable_cards[returns.ivalue[0] >> 16];
core.summon_cancelable = TRUE;
2015-09-25 21:07:16 +08:00
special_summon_rule(infos.turn_player, target, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 7: {
card* target = core.repositionable_cards[returns.ivalue[0] >> 16];
if(target->is_position(POS_FACEUP_ATTACK)) {
core.phase_action = TRUE;
2016-05-31 12:47:55 +08:00
change_position(target, 0, infos.turn_player, POS_FACEUP_DEFENSE, FALSE);
2015-09-25 21:07:16 +08:00
adjust_all();
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, FALSE, 0);
2016-05-31 12:47:55 +08:00
} else if(target->is_position(POS_FACEUP_DEFENSE)) {
2015-09-25 21:07:16 +08:00
core.phase_action = TRUE;
change_position(target, 0, infos.turn_player, POS_FACEUP_ATTACK, FALSE);
adjust_all();
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, FALSE, 0);
} else if(target->is_position(POS_FACEDOWN_ATTACK)) {
core.units.begin()->ptarget = (group*)target;
int32 positions = 0;
if(target->is_capable_change_position(infos.turn_player))
2016-05-31 12:47:55 +08:00
positions |= POS_FACEDOWN_DEFENSE;
2015-09-25 21:07:16 +08:00
if(target->is_can_be_flip_summoned(infos.turn_player))
positions |= POS_FACEUP_ATTACK;
add_process(PROCESSOR_SELECT_POSITION, 0, 0, 0, infos.turn_player + (positions << 16), target->data.code);
core.units.begin()->step = 12;
return FALSE;
2017-02-10 23:58:20 +09:00
} else
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_FLIP_SUMMON, 0, 0, (group*)target, target->current.controler, 0);
target->set_status(STATUS_FORM_CHANGED, TRUE);
core.units.begin()->step = -1;
return FALSE;
}
case 8: {
card* target = core.msetable_cards[returns.ivalue[0] >> 16];
core.summon_cancelable = TRUE;
2017-06-09 09:44:04 +09:00
mset(target->current.controler, target, 0, FALSE, 0);
2015-09-25 21:07:16 +08:00
core.units.begin()->step = -1;
return FALSE;
}
case 9: {
card* target = core.ssetable_cards[returns.ivalue[0] >> 16];
add_process(PROCESSOR_SSET, 0, 0, (group*)target, target->current.controler, target->current.controler);
core.units.begin()->step = -1;
return FALSE;
}
case 10: {
//end announce
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2015-09-25 21:07:16 +08:00
if(core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
reset_phase(infos.phase);
adjust_all();
return FALSE;
}
case 11: {
returns.ivalue[0] = core.units.begin()->arg1;
infos.can_shuffle = TRUE;
return TRUE;
}
case 12: {
if(returns.ivalue[0] == 0)
core.units.begin()->arg1 = 6;
else
core.units.begin()->arg1 = 7;
reset_phase(infos.phase);
adjust_all();
core.units.begin()->step = 10;
return FALSE;
}
case 13: {
card* target = (card*)core.units.begin()->ptarget;
if(returns.ivalue[0] == POS_FACEUP_ATTACK)
add_process(PROCESSOR_FLIP_SUMMON, 0, 0, (group*)target, target->current.controler, 0);
else {
core.phase_action = TRUE;
2016-05-31 12:47:55 +08:00
change_position(target, 0, infos.turn_player, POS_FACEDOWN_DEFENSE, FALSE);
2015-09-25 21:07:16 +08:00
adjust_all();
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, FALSE, 0);
}
target->set_status(STATUS_FORM_CHANGED, TRUE);
core.units.begin()->step = -1;
return FALSE;
}
}
return TRUE;
}
int32 field::process_battle_command(uint16 step) {
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;
2015-09-25 21:07:16 +08:00
core.chain_attack_target = 0;
}
2016-05-17 22:59:05 +08:00
core.attack_player = FALSE;
2015-09-25 21:07:16 +08:00
core.attacker = 0;
core.attack_target = 0;
2018-02-01 22:50:41 +01:00
if((peffect = is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP)) || core.force_turn_end) {
2015-12-26 01:43:08 +08:00
core.units.begin()->step = 41;
core.units.begin()->arg1 = 2;
2015-09-25 21:07:16 +08:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_BP_TWICE))
core.units.begin()->arg2 = 1;
else core.units.begin()->arg2 = 0;
2018-02-01 22:50:41 +01:00
if(core.force_turn_end || !peffect->value) {
2018-08-18 13:28:20 +08:00
reset_phase(PHASE_BATTLE_STEP);
adjust_all();
2015-12-26 01:43:08 +08:00
infos.phase = PHASE_BATTLE;
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_BATTLE, 0);
2016-04-20 13:49:15 +08:00
} else {
2015-09-25 21:07:16 +08:00
core.hint_timing[infos.turn_player] = 0;
reset_phase(PHASE_BATTLE);
adjust_all();
}
return FALSE;
}
auto pr = effects.activate_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event) && peffect->get_speed() > 1)
core.select_chains.push_back(newchain);
}
pr = effects.quick_o_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-08-13 11:13:41 +09:00
peffect->set_activate_location();
2015-09-25 21:07:16 +08:00
newchain.triggering_effect = peffect;
if(peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
2017-11-12 21:51:44 +09:00
pr = effects.continuous_effect.equal_range(EVENT_FREE_CHAIN);
2018-03-07 09:50:28 +09:00
for(auto eit = pr.first; eit != pr.second;) {
effect* peffect = eit->second;
++eit;
2017-11-12 21:51:44 +09:00
newchain.triggering_effect = peffect;
if(peffect->get_handler_player() == infos.turn_player && peffect->is_activateable(infos.turn_player, nil_event))
core.select_chains.push_back(newchain);
}
2015-09-25 21:07:16 +08:00
core.attackable_cards.clear();
card_vector first_attack;
card_vector must_attack;
if(!is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_ATTACK_ANNOUNCE)) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[infos.turn_player].list_mzone) {
2015-09-25 21:07:16 +08:00
if(!pcard)
continue;
if(!pcard->is_capable_attack_announce(infos.turn_player))
continue;
uint8 chain_attack = FALSE;
if(core.chain_attack && core.chain_attacker_id == pcard->fieldid)
2015-09-25 21:07:16 +08:00
chain_attack = TRUE;
2017-08-07 15:48:21 +09:00
card_vector cv;
get_attack_target(pcard, &cv, chain_attack);
if(cv.size() == 0 && pcard->direct_attackable == 0)
2015-09-25 21:07:16 +08:00
continue;
core.attackable_cards.push_back(pcard);
if(pcard->is_affected_by_effect(EFFECT_FIRST_ATTACK))
first_attack.push_back(pcard);
if(pcard->is_affected_by_effect(EFFECT_MUST_ATTACK))
must_attack.push_back(pcard);
}
if(first_attack.size())
core.attackable_cards = first_attack;
}
2017-08-13 18:07:11 +02:00
core.to_m2 = (core.duel_options & SPEED_DUEL) ? FALSE : TRUE;
2015-09-25 21:07:16 +08:00
core.to_ep = TRUE;
2018-02-01 22:50:41 +01:00
if(must_attack.size() || is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_M2) || core.force_turn_end)
2015-09-25 21:07:16 +08:00
core.to_m2 = FALSE;
if(must_attack.size())
core.to_ep = FALSE;
2017-09-12 21:37:52 +08:00
core.attack_cancelable = TRUE;
2017-09-14 21:35:59 +02:00
core.attack_cost_paid = FALSE;
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SELECT_BATTLECMD, 0, 0, 0, infos.turn_player, 0);
return FALSE;
}
case 1: {
int32 ctype = returns.ivalue[0] & 0xffff;
int32 sel = returns.ivalue[0] >> 16;
if(ctype == 0) {
chain newchain = core.select_chains[sel];
effect* peffect = newchain.triggering_effect;
2017-11-12 21:51:44 +09:00
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
core.select_chains.clear();
solve_continuous(peffect->get_handler_player(), peffect, nil_event);
2017-11-12 21:51:44 +09:00
core.units.begin()->step = -1;
return FALSE;
}
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
newchain.flag = 0;
newchain.chain_id = infos.field_id++;
newchain.evt.event_code = peffect->code;
newchain.evt.event_player = PLAYER_NONE;
newchain.evt.event_value = 0;
newchain.evt.event_cards = 0;
newchain.evt.reason = 0;
newchain.evt.reason_effect = 0;
newchain.evt.reason_player = PLAYER_NONE;
2017-04-12 09:35:29 +09:00
newchain.set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
newchain.triggering_player = infos.turn_player;
core.new_chains.push_back(newchain);
2016-11-16 19:52:12 +09:00
phandler->set_status(STATUS_CHAINING, TRUE);
2015-09-25 21:07:16 +08:00
peffect->dec_count(infos.turn_player);
core.select_chains.clear();
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - infos.turn_player);
infos.priorities[0] = 0;
infos.priorities[1] = 0;
core.select_chains.clear();
return FALSE;
} else if(ctype == 1) {
core.units.begin()->step = 2;
2017-09-12 21:37:52 +08:00
core.units.begin()->arg3 = FALSE;
2018-09-08 22:36:28 +08:00
core.attacker = core.attackable_cards[sel];
2015-09-25 21:07:16 +08:00
core.attacker->set_status(STATUS_ATTACK_CANCELED, FALSE);
2018-09-08 22:36:28 +08:00
core.attacker->attack_controler = core.attacker->current.controler;
2015-09-25 21:07:16 +08:00
core.pre_field[0] = core.attacker->fieldid_r;
2017-09-10 19:06:27 +02:00
effect_set eset;
2017-09-17 20:53:47 +02:00
core.tpchain.clear();
chain newchain;
2017-09-10 19:06:27 +02:00
filter_player_effect(infos.turn_player, EFFECT_ATTACK_COST, &eset, FALSE);
core.attacker->filter_effect(EFFECT_ATTACK_COST, &eset);
2015-09-25 21:07:16 +08:00
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->operation) {
2017-09-17 20:53:47 +02:00
newchain.triggering_effect = eset[i];
core.tpchain.push_back(newchain);
2017-09-12 21:37:52 +08:00
core.attack_cancelable = FALSE;
2017-09-10 19:06:27 +02:00
}
}
2017-09-17 20:53:47 +02:00
if(core.tpchain.size() > 1) {
add_process(PROCESSOR_SORT_CHAIN, 0, 0, 0, 1, infos.turn_player);
core.units.begin()->step = 13;
2017-09-17 20:53:47 +02:00
}
else if(core.tpchain.size() == 1){
core.sub_solving_event.push_back(nil_event);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, core.tpchain.begin()->triggering_effect, 0, infos.turn_player, 0);
adjust_all();
}
2015-09-25 21:07:16 +08:00
return FALSE;
} else {
core.units.begin()->step = 39;
2016-01-13 13:23:35 +08:00
core.units.begin()->arg1 = ctype;
2015-12-26 01:43:08 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1 - infos.turn_player);
pduel->write_buffer64(29);
2015-12-26 01:43:08 +08:00
core.select_chains.clear();
core.hint_timing[infos.turn_player] = TIMING_BATTLE_STEP_END;
add_process(PROCESSOR_QUICK_EFFECT, 0, 0, 0, FALSE, 1 - infos.turn_player);
infos.priorities[infos.turn_player] = 1;
infos.priorities[1 - infos.turn_player] = 0;
2015-09-25 21:07:16 +08:00
return FALSE;
}
return TRUE;
}
case 2: {
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
case 3: {
2017-09-12 21:37:52 +08:00
core.units.begin()->arg1 = FALSE;
2018-09-08 22:36:28 +08:00
if(core.attacker->is_status(STATUS_ATTACK_CANCELED)) {
2017-09-12 21:37:52 +08:00
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
2017-09-10 19:06:27 +02:00
return FALSE;
}
2017-09-14 21:35:59 +02:00
//Cancel the attack cost
if(core.attack_cost_paid != 1 && !core.attack_cancelable) {
core.units.begin()->step = -1;
return FALSE;
}
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 4: {
2016-09-30 14:49:45 +08:00
// select attack target(replay start point)
2016-05-17 22:59:05 +08:00
core.attack_player = FALSE;
core.select_cards.clear();
auto atype = get_attack_target(core.attacker, &core.select_cards, core.chain_attack);
// only self targets aviable
if (core.select_cards.size() && core.attacker->direct_attackable) {
add_process(PROCESSOR_SELECT_YESNO, 0, 0, 0, infos.turn_player, 31);
return FALSE;
}
// direct attack
if(core.attacker->direct_attackable) {
2015-09-25 21:07:16 +08:00
if(core.select_cards.size() == 0) {
returns.ivalue[0] = -2;
core.units.begin()->step = 5;
return FALSE;
}
2018-08-21 19:04:34 +08:00
add_process(PROCESSOR_SELECT_YESNO, 0, 0, 0, infos.turn_player, 31);
2015-09-25 21:07:16 +08:00
returns.ivalue[0] = -2;
core.units.begin()->step = 5;
return FALSE;
}
2017-09-12 21:37:52 +08:00
// no target and not direct attackable
2015-09-25 21:07:16 +08:00
if(core.select_cards.size() == 0) {
2017-09-12 21:37:52 +08:00
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
2015-09-25 21:07:16 +08:00
return FALSE;
}
// must attack monster
2016-05-17 22:59:05 +08:00
if(atype == 3 || is_player_affected_by_effect(infos.turn_player, EFFECT_PATRICIAN_OF_DARKNESS)) {
if(core.select_cards.size() == 1)
returns.bvalue[1] = 0;
else {
pduel->write_buffer8(MSG_BECOME_TARGET);
pduel->write_buffer8(1);
pduel->write_buffer32(core.attacker->get_info_location());
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(1 - infos.turn_player);
pduel->write_buffer64(549);
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, 1 - infos.turn_player, 0x10001);
}
} else {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(infos.turn_player);
pduel->write_buffer64(549);
2017-09-12 21:37:52 +08:00
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player + (core.attack_cancelable ? 0x20000 : 0), 0x10001);
}
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 5;
return FALSE;
}
case 5: {
// the answer of "direct attack or not"
2015-09-25 21:07:16 +08:00
if(returns.ivalue[0]) {
returns.ivalue[0] = -2;
} else {
if(core.select_cards.size()) {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(infos.turn_player);
pduel->write_buffer64(549);
2017-09-12 21:37:52 +08:00
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player + (core.attack_cancelable ? 0x20000 : 0), 0x10001);
} else {
2017-09-12 21:37:52 +08:00
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
}
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 6: {
2017-09-12 21:37:52 +08:00
if(returns.ivalue[0] == -1) {//cancel attack manually
2018-08-21 19:04:34 +08:00
if(core.units.begin()->arg1) {
core.units.begin()->step = 12;
return FALSE;
}
2015-09-25 21:07:16 +08:00
core.units.begin()->step = -1;
return FALSE;
2017-09-12 21:37:52 +08:00
}
if(returns.ivalue[0] == -2)
2015-09-25 21:07:16 +08:00
core.attack_target = 0;
else
core.attack_target = core.select_cards[returns.bvalue[1]];
if(core.attack_target)
core.pre_field[1] = core.attack_target->fieldid_r;
else
core.pre_field[1] = 0;
return FALSE;
}
case 7: {
2017-09-12 21:37:52 +08:00
if(!core.units.begin()->arg1) {
2017-09-10 15:48:29 +02:00
core.phase_action = TRUE;
2017-09-12 21:37:52 +08:00
if(core.chain_attack && core.chain_attacker_id != core.attacker->fieldid) {
core.chain_attack = FALSE;
core.chain_attacker_id = 0;
}
2017-09-10 15:48:29 +02:00
core.attack_state_count[infos.turn_player]++;
check_card_counter(core.attacker, 5, infos.turn_player);
2018-08-21 17:54:34 +08:00
core.attacker->attack_announce_count++;
2017-09-08 15:52:49 +02:00
}
2018-09-08 22:36:28 +08:00
if(core.units.begin()->arg3) {//attack announce failed
2018-08-21 19:04:34 +08:00
core.attacker->announce_count++;
2017-09-10 15:48:29 +02:00
core.chain_attack = FALSE;
2017-09-12 21:37:52 +08:00
core.units.begin()->step = -1;
2017-09-10 15:48:29 +02:00
}
2015-09-25 21:07:16 +08:00
return FALSE;
}
2017-09-12 21:37:52 +08:00
case 8: {
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_ATTACK);
pduel->write_buffer32(core.attacker->get_info_location());
if(core.attack_target) {
raise_single_event(core.attack_target, 0, EVENT_BE_BATTLE_TARGET, 0, 0, 0, 1 - infos.turn_player, 0);
raise_event(core.attack_target, EVENT_BE_BATTLE_TARGET, 0, 0, 0, 1 - infos.turn_player, 0);
2015-09-25 21:07:16 +08:00
pduel->write_buffer32(core.attack_target->get_info_location());
} else
pduel->write_buffer32(0);
core.attack_rollback = FALSE;
2017-10-15 23:15:42 +08:00
core.opp_mzone.clear();
2018-08-21 19:04:34 +08:00
for(auto& pcard : player[1 - infos.turn_player].list_mzone) {
2017-03-19 23:33:20 +09:00
if(pcard)
2017-10-15 23:15:42 +08:00
core.opp_mzone.insert(pcard->fieldid_r);
2015-09-25 21:07:16 +08:00
}
//core.units.begin()->arg1 ---> is rollbacked
2015-09-25 21:07:16 +08:00
if(!core.units.begin()->arg1) {
raise_single_event(core.attacker, 0, EVENT_ATTACK_ANNOUNCE, 0, 0, 0, infos.turn_player, 0);
raise_event(core.attacker, EVENT_ATTACK_ANNOUNCE, 0, 0, 0, infos.turn_player, 0);
}
2017-08-06 23:43:50 +09:00
core.attacker->attack_controler = core.attacker->current.controler;
core.pre_field[0] = core.attacker->fieldid_r;
2018-08-21 19:04:34 +08:00
process_single_event();
process_instant_event();
2015-09-25 21:07:16 +08:00
core.hint_timing[infos.turn_player] = TIMING_ATTACK;
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
2017-09-12 21:37:52 +08:00
case 9: {
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP)
|| core.attacker->is_status(STATUS_ATTACK_CANCELED) || core.attack_rollback) {
2017-09-12 21:37:52 +08:00
core.units.begin()->step = 10;
2015-09-25 21:07:16 +08:00
return FALSE;
}
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
pduel->write_buffer64(24);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
pduel->write_buffer64(24);
2015-09-25 21:07:16 +08:00
core.hint_timing[0] = TIMING_BATTLE_PHASE;
core.hint_timing[1] = TIMING_BATTLE_PHASE;
2017-11-12 21:51:44 +09:00
add_process(PROCESSOR_POINT_EVENT, 30, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
return FALSE;
}
2017-09-12 21:37:52 +08:00
case 10: {
2015-09-25 21:07:16 +08:00
if(returns.ivalue[0])
2017-09-12 21:37:52 +08:00
core.units.begin()->step = 8;
2015-09-25 21:07:16 +08:00
else
adjust_all();
return FALSE;
}
2017-09-12 21:37:52 +08:00
case 11: {
2015-09-25 21:07:16 +08:00
if(core.attacker->is_affected_by_effect(EFFECT_ATTACK_DISABLED)) {
core.attacker->reset(EFFECT_ATTACK_DISABLED, RESET_CODE);
pduel->write_buffer8(MSG_ATTACK_DISABLED);
core.attacker->set_status(STATUS_ATTACK_CANCELED, TRUE);
}
2018-08-21 19:04:34 +08:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP)
|| core.attacker->is_status(STATUS_ATTACK_CANCELED)) {
2018-08-21 19:04:34 +08:00
core.units.begin()->step = 12;
2015-09-25 21:07:16 +08:00
return FALSE;
}
// go to damage step
if(!core.attack_rollback) {
2018-08-21 19:04:34 +08:00
core.attacker->announce_count++;
core.attacker->announced_cards.addcard(core.attack_target);
attack_all_target_check();
2017-08-06 23:43:50 +09:00
core.units.begin()->step = 18;
2015-09-25 21:07:16 +08:00
return FALSE;
}
2017-08-07 15:48:21 +09:00
card_vector cv;
get_attack_target(core.attacker, &cv, core.chain_attack);
if(!cv.size() && !core.attacker->direct_attackable) {
2018-08-21 19:04:34 +08:00
core.units.begin()->step = 12;
2015-09-25 21:07:16 +08:00
return FALSE;
}
// replay
2015-09-25 21:07:16 +08:00
if(!core.attacker->is_affected_by_effect(EFFECT_MUST_ATTACK))
add_process(PROCESSOR_SELECT_YESNO, 0, 0, 0, infos.turn_player, 30);
else {
returns.ivalue[0] = TRUE;
}
return FALSE;
}
2017-09-12 21:37:52 +08:00
case 12: {
// answer of "replay or not"
2015-09-25 21:07:16 +08:00
if(returns.ivalue[0]) {
core.units.begin()->arg1 = TRUE;
2017-09-12 21:37:52 +08:00
core.units.begin()->arg3 = FALSE;
core.attack_cancelable = TRUE;
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 3;
}
2018-08-21 19:04:34 +08:00
return FALSE;
}
case 13: {
2018-09-17 21:14:05 +08:00
if(core.attacker->fieldid_r == core.pre_field[0]) {
core.attacker->announce_count++;
core.attacker->announced_cards.addcard(core.attack_target);
2018-08-21 17:51:57 +08:00
attack_all_target_check();
2018-09-17 21:14:05 +08:00
}
core.chain_attack = FALSE;
2015-09-25 21:07:16 +08:00
core.units.begin()->step = -1;
reset_phase(PHASE_DAMAGE);
adjust_all();
return FALSE;
}
case 14: {
2017-09-17 20:53:47 +02:00
for(auto clit = core.tpchain.begin(); clit != core.tpchain.end(); ++clit) {
core.sub_solving_event.push_back(nil_event);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, clit->triggering_effect, 0, infos.turn_player, 0);
adjust_all();
}
core.tpchain.clear();
core.units.begin()->step = 2;
return FALSE;
}
2017-08-06 23:43:50 +09:00
case 19: {
infos.phase = PHASE_DAMAGE;
core.chain_attack = FALSE;
core.units.begin()->arg1 = FALSE;
core.damage_calculated = FALSE;
core.selfdes_disabled = TRUE;
core.flip_delayed = TRUE;
core.attacker->attack_controler = core.attacker->current.controler;
core.pre_field[0] = core.attacker->fieldid_r;
if(core.attack_target) {
core.attack_target->attack_controler = core.attack_target->current.controler;
core.pre_field[1] = core.attack_target->fieldid_r;
} else
core.pre_field[1] = 0;
core.attacker->attacked_count++;
core.attacker->attacked_cards.addcard(core.attack_target);
core.battled_count[infos.turn_player]++;
adjust_all();
return FALSE;
}
2015-09-25 21:07:16 +08:00
case 20: {
2016-09-30 14:49:45 +08:00
// start of PHASE_DAMAGE;
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_DAMAGE_STEP_START);
raise_single_event(core.attacker, 0, EVENT_BATTLE_START, 0, 0, 0, 0, 0);
if(core.attack_target) {
2015-09-25 21:07:16 +08:00
raise_single_event(core.attack_target, 0, EVENT_BATTLE_START, 0, 0, 0, 0, 1);
}
2015-09-25 21:07:16 +08:00
raise_event((card*)0, EVENT_BATTLE_START, 0, 0, 0, 0, 0);
process_single_event();
process_instant_event();
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
pduel->write_buffer64(40);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
pduel->write_buffer64(40);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, TRUE);
return FALSE;
}
case 21: {
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->fieldid_r != core.pre_field[0]
|| core.attacker->current.controler != core.attacker->attack_controler
|| (core.attack_target && (core.attack_target->current.location != LOCATION_MZONE
|| core.attack_target->current.controler != core.attack_target->attack_controler
|| core.attack_target->fieldid_r != core.pre_field[1]))) {
core.units.begin()->step = 32;
2015-09-25 21:07:16 +08:00
return FALSE;
}
if(!core.attack_target) {
return FALSE;
}
core.attacker->temp.position = core.attacker->current.position;
core.attack_target->temp.position = core.attack_target->current.position;
if(core.attack_target->is_position(POS_FACEDOWN)) {
change_position(core.attack_target, 0, PLAYER_NONE, core.attack_target->current.position >> 1, 0, TRUE);
adjust_all();
}
return FALSE;
}
case 22: {
2017-08-06 23:43:50 +09:00
raise_single_event(core.attacker, 0, EVENT_BATTLE_CONFIRM, 0, 0, 0, 0, 0);
2015-09-25 21:07:16 +08:00
if(core.attack_target) {
if(core.attack_target->temp.position & POS_FACEDOWN)
core.pre_field[1] = core.attack_target->fieldid_r;
2017-08-06 23:43:50 +09:00
raise_single_event(core.attack_target, 0, EVENT_BATTLE_CONFIRM, 0, 0, 0, 0, 1);
2015-09-25 21:07:16 +08:00
}
raise_event((card*)0, EVENT_BATTLE_CONFIRM, 0, 0, 0, 0, 0);
process_single_event();
process_instant_event();
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
pduel->write_buffer64(41);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
pduel->write_buffer64(41);
2015-09-25 21:07:16 +08:00
core.hint_timing[infos.turn_player] = TIMING_DAMAGE_STEP;
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 23: {
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->fieldid_r != core.pre_field[0]
2016-05-31 12:47:55 +08:00
|| ((core.attacker->current.position & POS_DEFENSE) && !(core.attacker->is_affected_by_effect(EFFECT_DEFENSE_ATTACK)))
|| core.attacker->current.controler != core.attacker->attack_controler
|| (core.attack_target && (core.attack_target->current.location != LOCATION_MZONE
|| core.attack_target->current.controler != core.attack_target->attack_controler
|| core.attack_target->fieldid_r != core.pre_field[1]))) {
core.units.begin()->step = 32;
2015-09-25 21:07:16 +08:00
return FALSE;
}
2016-09-05 13:58:34 +08:00
infos.phase = PHASE_DAMAGE_CAL;
adjust_all();
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 24: {
2016-09-30 14:49:45 +08:00
// PHASE_DAMAGE_CAL;
2015-09-25 21:07:16 +08:00
calculate_battle_damage(0, 0, 0);
raise_single_event(core.attacker, 0, EVENT_PRE_DAMAGE_CALCULATE, 0, 0, 0, 0, 0);
if(core.attack_target)
raise_single_event(core.attack_target, 0, EVENT_PRE_DAMAGE_CALCULATE, 0, 0, 0, 0, 1);
raise_event((card*)0, EVENT_PRE_DAMAGE_CALCULATE, 0, 0, 0, 0, 0);
process_single_event();
process_instant_event();
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
pduel->write_buffer64(42);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
2017-11-12 20:15:35 +01:00
pduel->write_buffer64(42);
2015-09-25 21:07:16 +08:00
core.hint_timing[infos.turn_player] = TIMING_DAMAGE_CAL;
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, TRUE);
return FALSE;
}
case 25: {
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->fieldid_r != core.pre_field[0]
|| core.attacker->current.controler != core.attacker->attack_controler
|| (core.attack_target && (core.attack_target->current.location != LOCATION_MZONE
|| core.attack_target->current.controler != core.attack_target->attack_controler
|| core.attack_target->fieldid_r != core.pre_field[1]))) {
2016-08-23 15:21:52 +08:00
reset_phase(PHASE_DAMAGE_CAL);
2018-08-18 13:28:20 +08:00
adjust_all();
2016-08-23 15:21:52 +08:00
infos.phase = PHASE_DAMAGE;
core.units.begin()->step = 32;
2015-09-25 21:07:16 +08:00
return FALSE;
}
return FALSE;
}
case 26: {
// Duel.CalculateDamage() goes here
2016-05-31 12:45:35 +08:00
uint32 aa = core.attacker->get_attack(), ad = core.attacker->get_defense();
2015-09-25 21:07:16 +08:00
uint32 da = 0, dd = 0;
uint8 pa = core.attacker->current.controler, pd;
core.attacker->q_cache.attack = aa;
2016-05-31 12:45:35 +08:00
core.attacker->q_cache.defense = ad;
core.attacker->set_status(STATUS_BATTLE_RESULT, FALSE);
2015-09-25 21:07:16 +08:00
core.attacker->set_status(STATUS_BATTLE_DESTROYED, FALSE);
if(core.attack_target) {
da = core.attack_target->get_attack();
2016-05-31 12:45:35 +08:00
dd = core.attack_target->get_defense();
2015-09-25 21:07:16 +08:00
core.attack_target->q_cache.attack = da;
2016-05-31 12:45:35 +08:00
core.attack_target->q_cache.defense = dd;
core.attack_target->set_status(STATUS_BATTLE_RESULT, FALSE);
2015-09-25 21:07:16 +08:00
core.attack_target->set_status(STATUS_BATTLE_DESTROYED, FALSE);
pd = core.attack_target->current.controler;
if(pa != pd) {
core.attacker->set_status(STATUS_OPPO_BATTLE, TRUE);
core.attack_target->set_status(STATUS_OPPO_BATTLE, TRUE);
}
}
effect* damchange = 0;
card* reason_card = 0;
uint8 bd[2];
calculate_battle_damage(&damchange, &reason_card, bd);
if(bd[0]) {
effect* indestructable_effect = core.attacker->is_affected_by_effect(EFFECT_INDESTRUCTABLE_BATTLE, core.attack_target);
if(indestructable_effect) {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_CARD);
pduel->write_buffer8(0);
pduel->write_buffer64(indestructable_effect->owner->data.code);
2015-09-25 21:07:16 +08:00
bd[0] = FALSE;
} else
core.attacker->set_status(STATUS_BATTLE_RESULT, TRUE);
2015-09-25 21:07:16 +08:00
}
if(bd[1]) {
effect* indestructable_effect = core.attack_target->is_affected_by_effect(EFFECT_INDESTRUCTABLE_BATTLE, core.attacker);
if(indestructable_effect) {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_CARD);
pduel->write_buffer8(0);
pduel->write_buffer64(indestructable_effect->owner->data.code);
2015-09-25 21:07:16 +08:00
bd[1] = FALSE;
} else
core.attack_target->set_status(STATUS_BATTLE_RESULT, TRUE);
2015-09-25 21:07:16 +08:00
}
pduel->write_buffer8(MSG_BATTLE);
pduel->write_buffer32(core.attacker->get_info_location());
pduel->write_buffer32(aa);
pduel->write_buffer32(ad);
pduel->write_buffer8(bd[0]);
if(core.attack_target) {
pduel->write_buffer32(core.attack_target->get_info_location());
pduel->write_buffer32(da);
pduel->write_buffer32(dd);
pduel->write_buffer8(bd[1]);
} else {
pduel->write_buffer32(0);
pduel->write_buffer32(0);
pduel->write_buffer32(0);
pduel->write_buffer8(0);
}
core.units.begin()->peffect = damchange;
if(reason_card)
core.temp_var[0] = reason_card->current.controler;
if(!reason_card)
core.temp_var[1] = 0;
else if(reason_card == core.attacker)
core.temp_var[1] = 1;
else core.temp_var[1] = 2;
if(!damchange) {
if(core.battle_damage[infos.turn_player]) {
raise_single_event(core.attacker, 0, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, infos.turn_player, core.battle_damage[infos.turn_player]);
if(core.attack_target)
raise_single_event(core.attack_target, 0, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, infos.turn_player, core.battle_damage[infos.turn_player]);
raise_event(reason_card, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, infos.turn_player, core.battle_damage[infos.turn_player]);
}
if(core.battle_damage[1 - infos.turn_player]) {
raise_single_event(core.attacker, 0, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, 1 - infos.turn_player, core.battle_damage[1 - infos.turn_player]);
if(core.attack_target)
raise_single_event(core.attack_target, 0, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, 1 - infos.turn_player, core.battle_damage[1 - infos.turn_player]);
raise_event(reason_card, EVENT_PRE_BATTLE_DAMAGE, 0, 0, reason_card->current.controler, 1 - infos.turn_player, core.battle_damage[1 - infos.turn_player]);
}
}
process_single_event();
process_instant_event();
//this timing does not exist in Master Rule 3
core.damage_calculated = TRUE;
if(core.effect_damage_step)
return TRUE;
return FALSE;
}
case 27: {
infos.phase = PHASE_DAMAGE;
core.hint_timing[infos.turn_player] = 0;
core.chain_attack = FALSE;
2015-12-13 09:42:56 +09:00
core.attacker->battled_cards.addcard(core.attack_target);
if(core.attack_target)
core.attack_target->battled_cards.addcard(core.attacker);
2015-09-25 21:07:16 +08:00
uint8 reason_player = core.temp_var[0];
card* reason_card = 0;
if(core.temp_var[1] == 1)
reason_card = core.attacker;
else if(core.temp_var[1] == 2)
reason_card = core.attack_target;
effect* damchange = core.units.begin()->peffect;
if(!damchange) {
if(core.battle_damage[0])
damage(0, REASON_BATTLE, reason_player, reason_card, 0, core.battle_damage[0]);
if(core.battle_damage[1])
damage(0, REASON_BATTLE, reason_player, reason_card, 1, core.battle_damage[1]);
} else {
if(core.battle_damage[0])
damage(damchange, REASON_EFFECT, reason_player, reason_card, 0, core.battle_damage[0]);
if(core.battle_damage[1])
damage(damchange, REASON_EFFECT, reason_player, reason_card, 1, core.battle_damage[1]);
}
reset_phase(PHASE_DAMAGE_CAL);
adjust_all();
return FALSE;
}
case 28: {
card_set des;
effect* peffect;
if(core.attacker->is_status(STATUS_BATTLE_RESULT)
2015-09-25 21:07:16 +08:00
&& core.attacker->current.location == LOCATION_MZONE && core.attacker->fieldid_r == core.pre_field[0]) {
des.insert(core.attacker);
core.attacker->temp.reason = core.attacker->current.reason;
core.attacker->temp.reason_card = core.attacker->current.reason_card;
core.attacker->temp.reason_effect = core.attacker->current.reason_effect;
core.attacker->temp.reason_player = core.attacker->current.reason_player;
core.attacker->current.reason_effect = 0;
core.attacker->current.reason = REASON_BATTLE;
core.attacker->current.reason_card = core.attack_target;
core.attacker->current.reason_player = core.attack_target->current.controler;
uint32 dest = LOCATION_GRAVE;
uint32 seq = 0;
2015-09-25 21:07:16 +08:00
if((peffect = core.attack_target->is_affected_by_effect(EFFECT_BATTLE_DESTROY_REDIRECT)) && (core.attacker->data.type & TYPE_MONSTER)) {
dest = peffect->get_value(core.attacker);
seq = dest >> 16;
dest &= 0xffff;
}
core.attacker->sendto_param.set(core.attacker->owner, POS_FACEUP, dest, seq);
core.attacker->set_status(STATUS_DESTROY_CONFIRMED, TRUE);
2015-09-25 21:07:16 +08:00
}
if(core.attack_target && core.attack_target->is_status(STATUS_BATTLE_RESULT)
2015-09-25 21:07:16 +08:00
&& core.attack_target->current.location == LOCATION_MZONE && core.attack_target->fieldid_r == core.pre_field[1]) {
des.insert(core.attack_target);
core.attack_target->temp.reason = core.attack_target->current.reason;
core.attack_target->temp.reason_card = core.attack_target->current.reason_card;
core.attack_target->temp.reason_effect = core.attack_target->current.reason_effect;
core.attack_target->temp.reason_player = core.attack_target->current.reason_player;
core.attack_target->current.reason_effect = 0;
core.attack_target->current.reason = REASON_BATTLE;
core.attack_target->current.reason_card = core.attacker;
core.attack_target->current.reason_player = core.attacker->current.controler;
uint32 dest = LOCATION_GRAVE;
uint32 seq = 0;
2015-09-25 21:07:16 +08:00
if((peffect = core.attacker->is_affected_by_effect(EFFECT_BATTLE_DESTROY_REDIRECT)) && (core.attack_target->data.type & TYPE_MONSTER)) {
dest = peffect->get_value(core.attack_target);
seq = dest >> 16;
dest &= 0xffff;
}
core.attack_target->sendto_param.set(core.attack_target->owner, POS_FACEUP, dest, seq);
core.attack_target->set_status(STATUS_DESTROY_CONFIRMED, TRUE);
2015-09-25 21:07:16 +08:00
}
core.attacker->set_status(STATUS_BATTLE_RESULT, FALSE);
2015-09-25 21:07:16 +08:00
if(core.attack_target)
core.attack_target->set_status(STATUS_BATTLE_RESULT, FALSE);
2015-09-25 21:07:16 +08:00
core.battle_destroy_rep.clear();
core.desrep_chain.clear();
if(des.size()) {
group* ng = pduel->new_group();
ng->container.swap(des);
ng->is_readonly = TRUE;
add_process(PROCESSOR_DESTROY, 10, 0, ng, REASON_BATTLE, PLAYER_NONE);
core.units.begin()->ptarget = ng;
}
return FALSE;
}
case 29: {
if(core.battle_destroy_rep.size())
2016-05-09 14:09:50 +08:00
destroy(&core.battle_destroy_rep, 0, REASON_EFFECT | REASON_REPLACE, PLAYER_NONE);
if(core.desrep_chain.size())
add_process(PROCESSOR_OPERATION_REPLACE, 15, NULL, NULL, 0, 0);
adjust_all();
return FALSE;
}
case 30: {
2015-09-25 21:07:16 +08:00
group* des = core.units.begin()->ptarget;
if(des && des->container.size()) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : des->container) {
pcard->set_status(STATUS_BATTLE_DESTROYED, TRUE);
pcard->set_status(STATUS_DESTROY_CONFIRMED, FALSE);
pcard->filter_disable_related_cards();
2015-09-25 21:07:16 +08:00
}
}
core.selfdes_disabled = FALSE;
2015-09-25 21:07:16 +08:00
adjust_all();
//EVENT_BATTLE_END was here, but this timing does not exist in Master Rule 3
return FALSE;
}
case 31: {
core.flip_delayed = FALSE;
core.new_fchain.splice(core.new_fchain.begin(), core.new_fchain_b);
core.new_ochain.splice(core.new_ochain.begin(), core.new_ochain_b);
raise_single_event(core.attacker, 0, EVENT_BATTLED, 0, 0, PLAYER_NONE, 0, 0);
if(core.attack_target)
raise_single_event(core.attack_target, 0, EVENT_BATTLED, 0, 0, PLAYER_NONE, 0, 1);
raise_event((card*)0, EVENT_BATTLED, 0, 0, PLAYER_NONE, 0, 0);
process_single_event();
process_instant_event();
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
2017-11-12 20:15:35 +01:00
pduel->write_buffer64(43);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
pduel->write_buffer64(43);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, TRUE);
return FALSE;
}
case 32: {
2016-03-06 21:16:05 +08:00
group* des = core.units.begin()->ptarget;
if(des) {
2016-05-07 06:13:42 +09:00
for(auto cit = des->container.begin(); cit != des->container.end();) {
auto rm = cit++;
2016-03-06 21:16:05 +08:00
if((*rm)->current.location != LOCATION_MZONE || ((*rm)->fieldid_r != core.pre_field[0] && (*rm)->fieldid_r != core.pre_field[1]))
des->container.erase(rm);
}
add_process(PROCESSOR_DESTROY, 3, 0, des, REASON_BATTLE, PLAYER_NONE);
}
adjust_all();
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 33: {
core.units.begin()->ptarget = 0;
// for unexpected end of damage step
core.damage_calculated = TRUE;
core.selfdes_disabled = FALSE;
core.flip_delayed = FALSE;
core.new_fchain.splice(core.new_fchain.begin(), core.new_fchain_b);
core.new_ochain.splice(core.new_ochain.begin(), core.new_ochain_b);
2015-09-25 21:07:16 +08:00
card_set ing;
card_set ed;
if(core.attacker->is_status(STATUS_BATTLE_DESTROYED) && (core.attacker->current.reason & REASON_BATTLE)) {
2015-09-25 21:07:16 +08:00
raise_single_event(core.attack_target, 0, EVENT_BATTLE_DESTROYING, 0, core.attacker->current.reason, core.attack_target->current.controler, 0, 1);
raise_single_event(core.attacker, 0, EVENT_BATTLE_DESTROYED, 0, core.attacker->current.reason, core.attack_target->current.controler, 0, 0);
raise_single_event(core.attacker, 0, EVENT_DESTROYED, 0, core.attacker->current.reason, core.attack_target->current.controler, 0, 0);
ing.insert(core.attack_target);
ed.insert(core.attacker);
}
if(core.attack_target && core.attack_target->is_status(STATUS_BATTLE_DESTROYED) && (core.attack_target->current.reason & REASON_BATTLE)) {
2015-09-25 21:07:16 +08:00
raise_single_event(core.attacker, 0, EVENT_BATTLE_DESTROYING, 0, core.attack_target->current.reason, core.attacker->current.controler, 0, 0);
raise_single_event(core.attack_target, 0, EVENT_BATTLE_DESTROYED, 0, core.attack_target->current.reason, core.attacker->current.controler, 0, 1);
raise_single_event(core.attack_target, 0, EVENT_DESTROYED, 0, core.attack_target->current.reason, core.attacker->current.controler, 0, 1);
ing.insert(core.attacker);
ed.insert(core.attack_target);
}
if(ing.size())
raise_event(&ing, EVENT_BATTLE_DESTROYING, 0, 0, 0, 0, 0);
if(ed.size()) {
raise_event(&ed, EVENT_BATTLE_DESTROYED, 0, 0, 0, 0, 0);
raise_event(&ed, EVENT_DESTROYED, 0, 0, 0, 0, 0);
}
raise_single_event(core.attacker, 0, EVENT_DAMAGE_STEP_END, 0, 0, 0, 0, 0);
if(core.attack_target)
raise_single_event(core.attack_target, 0, EVENT_DAMAGE_STEP_END, 0, 0, 0, 0, 1);
raise_event((card*)0, EVENT_DAMAGE_STEP_END, 0, 0, 0, 0, 0);
core.attacker->set_status(STATUS_BATTLE_DESTROYED, FALSE);
if(core.attack_target)
2015-09-25 21:07:16 +08:00
core.attack_target->set_status(STATUS_BATTLE_DESTROYED, FALSE);
process_single_event();
process_instant_event();
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(0);
pduel->write_buffer64(44);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_EVENT);
pduel->write_buffer8(1);
pduel->write_buffer64(44);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, TRUE);
core.units.begin()->step = 38;
return FALSE;
}
case 38: {
return FALSE;
}
case 39: {
//end of damage step
core.attacker->set_status(STATUS_OPPO_BATTLE, FALSE);
if(core.attack_target)
core.attack_target->set_status(STATUS_OPPO_BATTLE, FALSE);
2015-09-25 21:07:16 +08:00
core.units.begin()->step = -1;
2015-12-26 01:43:08 +08:00
infos.phase = PHASE_BATTLE_STEP;
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_DAMAGE_STEP_END);
reset_phase(PHASE_DAMAGE);
adjust_all();
if(core.effect_damage_step)
return TRUE;
return FALSE;
}
case 40: {
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2015-12-26 01:43:08 +08:00
if(core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
for(auto& ch : core.current_chain)
ch.triggering_effect->get_handler()->set_status(STATUS_CHAINING, FALSE);
2015-12-26 01:43:08 +08:00
add_process(PROCESSOR_SOLVE_CHAIN, 0, 0, 0, FALSE, 0);
core.units.begin()->step = -1;
return FALSE;
}
reset_phase(PHASE_BATTLE_STEP);
adjust_all();
return FALSE;
}
case 41: {
2016-01-13 13:23:35 +08:00
// normal end of battle step
2015-12-26 01:43:08 +08:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_BP_TWICE))
core.units.begin()->arg2 = 1;
2017-02-10 23:58:20 +09:00
else
2015-12-26 01:43:08 +08:00
core.units.begin()->arg2 = 0;
infos.phase = PHASE_BATTLE;
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_BATTLE, 0);
adjust_all();
return FALSE;
}
case 42: {
2015-09-25 21:07:16 +08:00
core.attacker = 0;
core.attack_target = 0;
returns.ivalue[0] = core.units.begin()->arg1;
returns.ivalue[1] = core.units.begin()->arg2;
return TRUE;
}
}
return TRUE;
}
int32 field::process_damage_step(uint16 step, uint32 new_attack) {
2015-09-25 21:07:16 +08:00
switch(step) {
case 0: {
2018-10-16 16:03:03 +08:00
if(core.effect_damage_step && !new_attack)
return TRUE;
2015-09-25 21:07:16 +08:00
core.effect_damage_step = 1;
card* tmp = core.attacker;
core.attacker = (card*)core.units.begin()->peffect;
core.units.begin()->peffect = (effect*)tmp;
tmp = core.attack_target;
core.attack_target = (card*)core.units.begin()->ptarget;
core.units.begin()->ptarget = (group*)tmp;
core.units.begin()->arg1 = infos.phase;
if(core.attacker->current.location != LOCATION_MZONE || (core.attack_target && core.attack_target->current.location != LOCATION_MZONE)) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 2;
return FALSE;
}
2016-09-07 10:14:35 +08:00
if(new_attack) {
core.attack_state_count[infos.turn_player]++;
2016-06-03 23:20:47 +08:00
core.battled_count[infos.turn_player]++;
check_card_counter(core.attacker, 5, infos.turn_player);
}
2018-08-21 19:07:27 +08:00
core.attacker->announced_cards.addcard(core.attack_target);
attack_all_target_check();
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_ATTACK);
pduel->write_buffer32(core.attacker->get_info_location());
if(core.attack_target)
pduel->write_buffer32(core.attack_target->get_info_location());
else
pduel->write_buffer32(0);
2015-09-25 21:07:16 +08:00
infos.phase = PHASE_DAMAGE;
pduel->write_buffer8(MSG_DAMAGE_STEP_START);
core.pre_field[0] = core.attacker->fieldid_r;
core.attacker->attacked_count++;
if(core.attack_target) {
2015-09-25 21:07:16 +08:00
core.pre_field[1] = core.attack_target->fieldid_r;
if(core.attack_target->is_position(POS_FACEDOWN)) {
change_position(core.attack_target, 0, PLAYER_NONE, core.attack_target->current.position >> 1, 0, TRUE);
adjust_all();
}
2018-10-16 15:52:51 +08:00
} else
2015-09-25 21:07:16 +08:00
core.pre_field[1] = 0;
return FALSE;
}
case 1: {
infos.phase = PHASE_DAMAGE_CAL;
add_process(PROCESSOR_BATTLE_COMMAND, 26, 0, 0, 0, 0);
core.units.begin()->step = 2;
core.reserved = core.units.front();
return TRUE;
}
case 2: {
core.effect_damage_step = 2;
add_process(PROCESSOR_BATTLE_COMMAND, 27, 0, 0, 0, 0);
return FALSE;
}
case 3: {
core.attacker = (card*)core.units.begin()->peffect;
core.attack_target = (card*)core.units.begin()->ptarget;
if(core.attacker)
core.attacker->set_status(STATUS_ATTACK_CANCELED, TRUE);
if(core.attack_target)
core.attack_target->set_status(STATUS_ATTACK_CANCELED, TRUE);
core.effect_damage_step = 0;
infos.phase = core.units.begin()->arg1;
return TRUE;
}
}
return TRUE;
}
2018-07-06 21:46:52 +08:00
void field::calculate_battle_damage(effect** pdamchange, card** preason_card, uint8* battle_destroyed) {
2016-05-31 12:45:35 +08:00
uint32 aa = core.attacker->get_attack(), ad = core.attacker->get_defense();
2015-09-25 21:07:16 +08:00
uint32 da = 0, dd = 0, a = aa, d;
uint8 pa = core.attacker->current.controler, pd;
uint8 damp = 0;
effect* damchange = 0;
card* reason_card = 0;
uint8 bd[2] = {FALSE, FALSE};
core.battle_damage[0] = core.battle_damage[1] = 0;
2016-05-31 12:47:55 +08:00
if(core.attacker->is_position(POS_FACEUP_DEFENSE)) {
effect* defattack = core.attacker->is_affected_by_effect(EFFECT_DEFENSE_ATTACK);
2015-09-25 21:07:16 +08:00
if(defattack && defattack->get_value(core.attacker))
a = ad;
}
if(core.attack_target) {
da = core.attack_target->get_attack();
2016-05-31 12:45:35 +08:00
dd = core.attack_target->get_defense();
2015-09-25 21:07:16 +08:00
pd = core.attack_target->current.controler;
if(core.attack_target->is_position(POS_ATTACK)) {
d = da;
if(a > d) {
damchange = core.attacker->is_affected_by_effect(EFFECT_BATTLE_DAMAGE_TO_EFFECT);
if(damchange) {
damp = pd;
core.battle_damage[damp] = a - d;
reason_card = core.attacker;
} else if(!core.attacker->is_affected_by_effect(EFFECT_NO_BATTLE_DAMAGE)
&& !core.attack_target->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attacker)
&& !is_player_affected_by_effect(pd, EFFECT_AVOID_BATTLE_DAMAGE)) {
if(core.attack_target->is_affected_by_effect(EFFECT_REFLECT_BATTLE_DAMAGE, core.attacker))
damp = 1 - pd;
else damp = pd;
if(is_player_affected_by_effect(damp, EFFECT_REFLECT_BATTLE_DAMAGE))
damp = 1 - damp;
if(damp == pd || (!core.attacker->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attack_target)
&& !is_player_affected_by_effect(damp, EFFECT_AVOID_BATTLE_DAMAGE))) {
core.battle_damage[damp] = a - d;
reason_card = core.attacker;
}
}
bd[1] = TRUE;
} else if (a < d) {
damchange = core.attack_target->is_affected_by_effect(EFFECT_BATTLE_DAMAGE_TO_EFFECT);
if(damchange) {
damp = pa;
core.battle_damage[damp] = d - a;
reason_card = core.attack_target;
} else if(!core.attack_target->is_affected_by_effect(EFFECT_NO_BATTLE_DAMAGE)
&& !core.attacker->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attack_target)
&& !is_player_affected_by_effect(pa, EFFECT_AVOID_BATTLE_DAMAGE)) {
if(core.attacker->is_affected_by_effect(EFFECT_REFLECT_BATTLE_DAMAGE, core.attack_target))
damp = 1 - pa;
else damp = pa;
if(is_player_affected_by_effect(damp, EFFECT_REFLECT_BATTLE_DAMAGE))
damp = 1 - damp;
if(damp == pa || (!core.attack_target->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attacker)
&& !is_player_affected_by_effect(damp, EFFECT_AVOID_BATTLE_DAMAGE))) {
core.battle_damage[damp] = d - a;
reason_card = core.attack_target;
}
}
bd[0] = TRUE;
} else {
if(a != 0) {
bd[0] = TRUE;
bd[1] = TRUE;
}
}
} else {
d = dd;
if(a > d) {
effect_set eset;
uint8 dp[2];
dp[0] = dp[1] = 0;
core.attacker->filter_effect(EFFECT_PIERCE, &eset);
if(eset.size() && !core.attacker->is_affected_by_effect(EFFECT_NO_BATTLE_DAMAGE)
&& !core.attack_target->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attacker)) {
for(int32 i = 0; i < eset.size(); ++i)
dp[1 - eset[i]->get_handler_player()] = 1;
if(dp[0] && is_player_affected_by_effect(0, EFFECT_AVOID_BATTLE_DAMAGE))
dp[0] = 0;
if(dp[1] && is_player_affected_by_effect(1, EFFECT_AVOID_BATTLE_DAMAGE))
dp[1] = 0;
if(dp[pd] && core.attack_target->is_affected_by_effect(EFFECT_REFLECT_BATTLE_DAMAGE, core.attacker)) {
dp[pd] = 0;
dp[1 - pd] = 1;
}
if(dp[pd] && is_player_affected_by_effect(pd, EFFECT_REFLECT_BATTLE_DAMAGE)) {
dp[pd] = 0;
dp[1 - pd] = 1;
}
if(dp[1 - pd] && is_player_affected_by_effect(1 - pd, EFFECT_REFLECT_BATTLE_DAMAGE)) {
dp[pd] = 1;
dp[1 - pd] = 0;
}
if(dp[pd] && !core.attack_target->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attacker)
&& !is_player_affected_by_effect(pd, EFFECT_AVOID_BATTLE_DAMAGE))
core.battle_damage[pd] = a - d;
if(dp[1 - pd] && !core.attacker->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attack_target)
&& !is_player_affected_by_effect(1 - pd, EFFECT_AVOID_BATTLE_DAMAGE))
core.battle_damage[1 - pd] = a - d;
reason_card = core.attacker;
}
bd[1] = TRUE;
} else if (a < d) {
damchange = core.attack_target->is_affected_by_effect(EFFECT_BATTLE_DAMAGE_TO_EFFECT);
if(damchange) {
damp = pa;
core.battle_damage[damp] = d - a;
reason_card = core.attack_target;
} else if(!core.attack_target->is_affected_by_effect(EFFECT_NO_BATTLE_DAMAGE)
&& !core.attacker->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attack_target)
&& !is_player_affected_by_effect(pa, EFFECT_AVOID_BATTLE_DAMAGE)) {
if(core.attacker->is_affected_by_effect(EFFECT_REFLECT_BATTLE_DAMAGE, core.attack_target))
damp = 1 - pa;
else damp = pa;
if(is_player_affected_by_effect(damp, EFFECT_REFLECT_BATTLE_DAMAGE))
damp = 1 - damp;
if(damp == pa || (!core.attack_target->is_affected_by_effect(EFFECT_AVOID_BATTLE_DAMAGE, core.attacker)
&& !is_player_affected_by_effect(damp, EFFECT_AVOID_BATTLE_DAMAGE))) {
core.battle_damage[damp] = d - a;
reason_card = core.attack_target;
}
}
}
}
} else {
damchange = core.attacker->is_affected_by_effect(EFFECT_BATTLE_DAMAGE_TO_EFFECT);
if(damchange) {
damp = 1 - pa;
core.battle_damage[damp] = a;
reason_card = core.attacker;
} else if(!core.attacker->is_affected_by_effect(EFFECT_NO_BATTLE_DAMAGE)
&& !is_player_affected_by_effect(1 - pa, EFFECT_AVOID_BATTLE_DAMAGE)) {
damp = 1 - pa;
if(is_player_affected_by_effect(damp, EFFECT_REFLECT_BATTLE_DAMAGE))
damp = 1 - damp;
if(!is_player_affected_by_effect(damp, EFFECT_AVOID_BATTLE_DAMAGE)) {
core.battle_damage[damp] = a;
reason_card = core.attacker;
}
}
}
if(pdamchange)
*pdamchange = damchange;
if(preason_card)
*preason_card = reason_card;
if(battle_destroyed) {
battle_destroyed[0] = bd[0];
battle_destroyed[1] = bd[1];
}
}
int32 field::process_turn(uint16 step, uint8 turn_player) {
switch(step) {
case 0: {
//Pre Draw
2018-09-03 16:36:45 +08:00
for(const auto& ev : core.used_event) {
if(ev.event_cards)
pduel->delete_group(ev.event_cards);
2015-09-25 21:07:16 +08:00
}
core.used_event.clear();
2018-09-03 16:36:45 +08:00
for(auto& peffect : core.reseted_effects) {
pduel->delete_effect(peffect);
2015-09-25 21:07:16 +08:00
}
core.reseted_effects.clear();
core.effect_count_code.clear();
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[p].list_mzone) {
2015-09-25 21:07:16 +08:00
if(!pcard)
continue;
pcard->set_status(STATUS_SUMMON_TURN, FALSE);
pcard->set_status(STATUS_FLIP_SUMMON_TURN, FALSE);
pcard->set_status(STATUS_SPSUMMON_TURN, FALSE);
pcard->set_status(STATUS_SET_TURN, FALSE);
pcard->set_status(STATUS_FORM_CHANGED, FALSE);
2016-04-17 09:10:18 +08:00
pcard->indestructable_effects.clear();
2018-08-21 17:54:34 +08:00
pcard->attack_announce_count = 0;
2015-09-25 21:07:16 +08:00
pcard->announce_count = 0;
pcard->attacked_count = 0;
pcard->announced_cards.clear();
pcard->attacked_cards.clear();
pcard->battled_cards.clear();
pcard->attack_all_target = TRUE;
}
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[p].list_szone) {
2015-09-25 21:07:16 +08:00
if(!pcard)
continue;
pcard->set_status(STATUS_SET_TURN, FALSE);
2016-06-22 22:22:12 +08:00
pcard->indestructable_effects.clear();
2015-09-25 21:07:16 +08:00
}
core.summon_state_count[p] = 0;
core.normalsummon_state_count[p] = 0;
core.flipsummon_state_count[p] = 0;
core.spsummon_state_count[p] = 0;
core.spsummon_state_count_rst[p] = 0;
core.attack_state_count[p] = 0;
core.battle_phase_count[p] = 0;
2016-06-03 23:20:47 +08:00
core.battled_count[p] = 0;
2015-09-25 21:07:16 +08:00
core.summon_count[p] = 0;
core.extra_summon[p] = 0;
core.spsummon_once_map[p].clear();
core.spsummon_once_map_rst[p].clear();
2018-02-01 22:50:41 +01:00
if (player[p].recharge)
next_player(p);
2015-09-25 21:07:16 +08:00
}
2018-02-01 22:50:41 +01:00
core.force_turn_end = false;
2015-09-25 21:07:16 +08:00
core.spsummon_rst = false;
2018-09-03 16:36:45 +08:00
for(auto& peffect : effects.rechargeable)
if(!peffect->is_flag(EFFECT_FLAG_NO_TURN_RESET))
peffect->recharge();
for(auto& iter : core.summon_counter)
iter.second.second = 0;
for(auto& iter : core.normalsummon_counter)
iter.second.second = 0;
for(auto& iter : core.spsummon_counter)
iter.second.second = 0;
for(auto& iter : core.flipsummon_counter)
iter.second.second = 0;
for(auto& iter : core.attack_counter)
iter.second.second = 0;
for(auto& iter : core.chain_counter)
iter.second.second = 0;
2015-09-25 21:07:16 +08:00
if(core.global_flag & GLOBALFLAG_SPSUMMON_COUNT) {
2018-09-03 16:36:45 +08:00
for(auto& peffect : effects.spsummon_count_eff) {
2016-11-16 19:52:12 +09:00
card* pcard = peffect->get_handler();
2016-03-18 16:14:56 +08:00
if(!peffect->is_flag(EFFECT_FLAG_NO_TURN_RESET)) {
2015-09-25 21:07:16 +08:00
pcard->spsummon_counter[0] = pcard->spsummon_counter[1] = 0;
pcard->spsummon_counter_rst[0] = pcard->spsummon_counter_rst[1] = 0;
}
}
}
infos.turn_id++;
2016-11-19 17:08:04 +09:00
infos.turn_id_by_player[turn_player]++;
2015-09-25 21:07:16 +08:00
infos.turn_player = turn_player;
pduel->write_buffer8(MSG_NEW_TURN);
pduel->write_buffer8(turn_player);
if((core.duel_options & DUEL_TAG_MODE) && infos.turn_id != 1)
tag_swap(turn_player);
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_TURN)) {
core.units.begin()->step = 17;
reset_phase(PHASE_END);
adjust_all();
return FALSE;
}
infos.phase = PHASE_DRAW;
core.phase_action = FALSE;
core.hand_adjusted = FALSE;
raise_event((card*)0, EVENT_PHASE_START + PHASE_DRAW, 0, 0, 0, turn_player, 0);
process_instant_event();
adjust_all();
return FALSE;
}
case 1: {
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
2018-02-01 22:50:41 +01:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_DP) || core.force_turn_end) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 2;
reset_phase(PHASE_DRAW);
adjust_all();
return FALSE;
}
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
2015-09-25 21:07:16 +08:00
raise_event((card*)0, EVENT_PREDRAW, 0, 0, 0, turn_player, 0);
process_instant_event();
if(core.new_fchain.size() || core.new_ochain.size())
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 2: {
// Draw, new ruling
2018-02-01 22:50:41 +01:00
if((core.duel_options & DUEL_1ST_TURN_DRAW) || (infos.turn_id > 1)) {
2015-09-25 21:07:16 +08:00
int32 count = get_draw_count(infos.turn_player);
if(count > 0) {
draw(0, REASON_RULE, turn_player, turn_player, count);
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
}
}
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_DRAW, 0);
return FALSE;
}
case 3: {
2015-12-21 00:25:30 +08:00
// EVENT_PHASE_PRESTART is removed
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 4: {
2015-12-21 00:25:30 +08:00
//Standby Phase
infos.phase = PHASE_STANDBY;
core.phase_action = FALSE;
2015-09-25 21:07:16 +08:00
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
2018-02-01 22:50:41 +01:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_SP) || core.force_turn_end) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 5;
reset_phase(PHASE_STANDBY);
adjust_all();
return FALSE;
}
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
2015-09-25 21:07:16 +08:00
raise_event((card*)0, EVENT_PHASE_START + PHASE_STANDBY, 0, 0, 0, turn_player, 0);
process_instant_event();
return FALSE;
}
case 5: {
2015-12-26 01:43:08 +08:00
// EVENT_PHASE_START + PHASE_STANDBY is a special case(c89642993)
if(core.new_fchain.size() || core.new_ochain.size() || core.instant_event.back().event_code != EVENT_PHASE_START + PHASE_STANDBY)
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_STANDBY, 0);
return FALSE;
}
case 6: {
//Main1
infos.phase = PHASE_MAIN1;
core.phase_action = FALSE;
raise_event((card*)0, EVENT_PHASE_START + PHASE_MAIN1, 0, 0, 0, turn_player, 0);
process_instant_event();
adjust_all();
return FALSE;
}
case 7: {
return FALSE;
}
case 8: {
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_IDLE_COMMAND, 0, 0, 0, 0, 0);
return FALSE;
}
case 9: {
if(returns.ivalue[0] == 7) { // End Phase
core.units.begin()->step = 14;
return FALSE;
}
2015-12-26 01:43:08 +08:00
infos.phase = PHASE_BATTLE_START;
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
2015-09-25 21:07:16 +08:00
core.phase_action = FALSE;
core.battle_phase_count[infos.turn_player]++;
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
// Show the texts to indicate that BP is entered and skipped
2018-02-01 22:50:41 +01:00
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP) || core.force_turn_end) {
core.units.begin()->step = 14;
reset_phase(PHASE_BATTLE_START);
reset_phase(PHASE_BATTLE_STEP);
reset_phase(PHASE_BATTLE);
adjust_all();
return FALSE;
}
2015-12-26 01:43:08 +08:00
raise_event((card*)0, EVENT_PHASE_START + PHASE_BATTLE_START, 0, 0, 0, turn_player, 0);
2015-09-25 21:07:16 +08:00
process_instant_event();
adjust_all();
return FALSE;
}
case 10: {
2015-12-21 00:25:30 +08:00
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_BATTLE_START, 0);
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 11: {
2015-12-26 01:43:08 +08:00
infos.phase = PHASE_BATTLE_STEP;
2015-09-25 21:07:16 +08:00
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
2015-12-26 01:43:08 +08:00
core.phase_action = FALSE;
2015-09-25 21:07:16 +08:00
core.chain_attack = FALSE;
add_process(PROCESSOR_BATTLE_COMMAND, 0, 0, 0, 0, 0);
return FALSE;
}
case 12: {
2016-01-06 20:04:08 +08:00
if(core.units.begin()->arg2 == 0 && returns.ivalue[1]) { // 2nd Battle Phase
2015-09-25 21:07:16 +08:00
core.units.begin()->arg2 = 1;
core.units.begin()->step = 8;
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[p].list_mzone) {
2015-09-25 21:07:16 +08:00
if(!pcard)
continue;
2018-08-21 17:54:34 +08:00
pcard->attack_announce_count = 0;
2015-09-25 21:07:16 +08:00
pcard->announce_count = 0;
pcard->attacked_count = 0;
pcard->announced_cards.clear();
pcard->attacked_cards.clear();
pcard->battled_cards.clear();
}
}
return FALSE;
}
2017-08-13 18:07:11 +02:00
if(core.duel_options & SPEED_DUEL) {
core.units.begin()->step = 14;
adjust_all();
return FALSE;
}
core.skip_m2 = FALSE;
2018-02-01 22:50:41 +01:00
if(returns.ivalue[0] == 3 || core.force_turn_end) { // End Phase
core.skip_m2 = TRUE;
}
2015-09-25 21:07:16 +08:00
//Main2
infos.phase = PHASE_MAIN2;
core.phase_action = FALSE;
raise_event((card*)0, EVENT_PHASE_START + PHASE_MAIN2, 0, 0, 0, turn_player, 0);
process_instant_event();
adjust_all();
return FALSE;
}
case 13: {
if(core.new_fchain.size() || core.new_ochain.size())
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 14: {
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
2015-09-25 21:07:16 +08:00
infos.can_shuffle = TRUE;
add_process(PROCESSOR_IDLE_COMMAND, 0, 0, 0, 0, 0);
return FALSE;
}
case 15: {
//End Phase
infos.phase = PHASE_END;
core.phase_action = FALSE;
pduel->write_buffer8(MSG_NEW_PHASE);
2015-12-21 00:25:30 +08:00
pduel->write_buffer16(infos.phase);
2015-09-25 21:07:16 +08:00
raise_event((card*)0, EVENT_PHASE_START + PHASE_END, 0, 0, 0, turn_player, 0);
process_instant_event();
adjust_all();
return FALSE;
}
case 16: {
if(core.new_fchain.size() || core.new_ochain.size())
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 17: {
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
add_process(PROCESSOR_PHASE_EVENT, 0, 0, 0, PHASE_END, 0);
return FALSE;
}
case 18: {
raise_event((card*)0, EVENT_TURN_END, 0, 0, 0, turn_player, 0);
process_instant_event();
adjust_all();
return FALSE;
}
case 19: {
core.new_fchain.clear();
core.new_ochain.clear();
core.quick_f_chain.clear();
core.delayed_quick_tmp.clear();
core.units.begin()->step = -1;
core.units.begin()->arg1 = 1 - core.units.begin()->arg1;
return FALSE;
}
}
return TRUE;
}
int32 field::add_chain(uint16 step) {
switch (step) {
case 0: {
if (!core.new_chains.size())
return TRUE;
2016-11-16 19:52:12 +09:00
auto& clit = core.new_chains.front();
effect* peffect = clit.triggering_effect;
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
effect_set eset;
filter_player_effect(clit.triggering_player, EFFECT_ACTIVATE_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(clit.triggering_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(clit.triggering_player, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->target, 3))
continue;
if(eset[i]->operation) {
core.sub_solving_event.push_back(clit.evt);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, eset[i], 0, clit.triggering_player, 0);
}
}
if(peffect->type & EFFECT_TYPE_ACTIVATE) {
break_effect();
int32 ecode = 0;
2016-11-16 19:52:12 +09:00
if(phandler->current.location == LOCATION_HAND) {
if(phandler->data.type & TYPE_TRAP)
2015-09-25 21:07:16 +08:00
ecode = EFFECT_TRAP_ACT_IN_HAND;
else if((phandler->data.type & TYPE_SPELL) && (phandler->data.type & TYPE_QUICKPLAY || phandler->is_affected_by_effect(EFFECT_BECOME_QUICK))
2016-11-16 19:52:12 +09:00
&& infos.turn_player != phandler->current.controler)
2015-09-25 21:07:16 +08:00
ecode = EFFECT_QP_ACT_IN_NTPHAND;
2016-11-16 19:52:12 +09:00
} else if(phandler->current.location == LOCATION_SZONE) {
if((phandler->data.type & TYPE_TRAP) && phandler->get_status(STATUS_SET_TURN))
2015-09-25 21:07:16 +08:00
ecode = EFFECT_TRAP_ACT_IN_SET_TURN;
2018-11-17 13:14:43 +01:00
if((phandler->data.type & TYPE_SPELL) && (phandler->data.type & TYPE_QUICKPLAY || phandler->is_affected_by_effect(EFFECT_BECOME_QUICK)) && phandler->get_status(STATUS_SET_TURN))
ecode = EFFECT_QP_ACT_IN_SET_TURN;
2015-09-25 21:07:16 +08:00
}
if(ecode) {
eset.clear();
2016-11-16 19:52:12 +09:00
phandler->filter_effect(ecode, &eset);
2015-09-25 21:07:16 +08:00
effect* pactin = 0;
for(int32 i = 0; i < eset.size(); ++i) {
2016-03-18 16:14:56 +08:00
if(!eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT)) {
2015-09-25 21:07:16 +08:00
pactin = eset[i];
break;
}
}
if(!pactin) {
for(int32 i = 0; i < eset.size(); ++i) {
2016-11-16 19:52:12 +09:00
if(eset[i]->check_count_limit(phandler->current.controler)) {
eset[i]->dec_count(phandler->current.controler);
2015-09-25 21:07:16 +08:00
break;
}
}
}
}
if(phandler->current.location == LOCATION_SZONE) {
2016-11-16 19:52:12 +09:00
phandler->set_status(STATUS_ACT_FROM_HAND, FALSE);
change_position(phandler, 0, phandler->current.controler, POS_FACEUP, 0);
} else {
2018-09-16 23:06:57 +08:00
uint32 zone = 0xff;
2018-09-17 19:44:58 +08:00
if(!(phandler->data.type & (TYPE_FIELD | TYPE_PENDULUM)) && peffect->is_flag(EFFECT_FLAG_LIMIT_ZONE)) {
2018-09-16 23:06:57 +08:00
pduel->lua->add_param(clit.triggering_player, PARAM_TYPE_INT);
pduel->lua->add_param(clit.evt.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(clit.evt.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(clit.evt.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(clit.evt.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(clit.evt.reason, PARAM_TYPE_INT);
pduel->lua->add_param(clit.evt.reason_player, PARAM_TYPE_INT);
zone = peffect->get_value(7);
if(!zone)
zone = 0xff;
}
int32 loc = 0;
if(phandler->current.location == LOCATION_HAND) {
phandler->set_status(STATUS_ACT_FROM_HAND, TRUE);
if (phandler->data.type & TYPE_PENDULUM) {
loc=LOCATION_PZONE;
} else {
loc=LOCATION_SZONE;
}
}
if (peffect->value)
loc = peffect->value;
if (loc>0) {
phandler->enable_field_effect(false);
if (loc==LOCATION_MZONE) {
move_to_field(phandler, phandler->current.controler, phandler->current.controler, loc, POS_FACEUP_ATTACK);
} else {
move_to_field(phandler, phandler->current.controler, phandler->current.controler, loc, POS_FACEUP, FALSE, 0, FALSE, zone);
}
}
2015-09-25 21:07:16 +08:00
}
}
return FALSE;
}
case 1: {
auto& clit = core.new_chains.front();
effect* peffect = clit.triggering_effect;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
if(peffect->type & EFFECT_TYPE_ACTIVATE) {
2017-04-12 09:35:29 +09:00
clit.set_triggering_place(phandler);
2015-09-25 21:07:16 +08:00
}
pduel->write_buffer8(MSG_CHAINING);
pduel->write_buffer32(phandler->data.code);
pduel->write_buffer32(phandler->get_info_location());
pduel->write_buffer8(clit.triggering_controler);
2017-04-12 09:35:29 +09:00
pduel->write_buffer8((uint8)clit.triggering_location);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(clit.triggering_sequence);
pduel->write_buffer64(peffect->description);
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(core.current_chain.size() + 1);
break_effect();
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2016-11-16 19:52:12 +09:00
peffect->card_type = phandler->get_type();
2015-09-25 21:07:16 +08:00
if((peffect->card_type & 0x5) == 0x5)
peffect->card_type -= TYPE_TRAP;
2018-09-12 21:37:38 +08:00
peffect->set_active_type();
2016-11-16 19:52:12 +09:00
peffect->active_handler = peffect->handler->overlay_target;
2015-09-25 21:07:16 +08:00
clit.chain_count = core.current_chain.size() + 1;
clit.target_cards = 0;
clit.target_player = PLAYER_NONE;
clit.target_param = 0;
clit.disable_reason = 0;
clit.disable_player = PLAYER_NONE;
clit.replace_op = 0;
if(phandler->current.location == LOCATION_HAND)
clit.flag |= CHAIN_HAND_EFFECT;
core.current_chain.push_back(clit);
check_chain_counter(peffect, clit.triggering_player, clit.chain_count);
// triggered events which are not caused by RaiseEvent create relation with the handler
2016-03-18 16:14:56 +08:00
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY) && (!(peffect->type & 0x2a0) || (peffect->code & EVENT_PHASE) == EVENT_PHASE)) {
2016-11-16 19:52:12 +09:00
phandler->create_relation(clit);
2015-09-25 21:07:16 +08:00
}
peffect->effect_owner = clit.triggering_player;
2015-10-28 16:55:44 +08:00
// DISABLE_CHAIN should be check before cost
effect* deffect;
2016-03-18 16:14:56 +08:00
if(!peffect->is_flag(EFFECT_FLAG_FIELD_ONLY) && phandler->is_has_relation(clit) && (deffect = phandler->is_affected_by_effect(EFFECT_DISABLE_EFFECT))) {
2015-10-28 16:55:44 +08:00
effect* negeff = pduel->new_effect();
negeff->owner = deffect->owner;
negeff->type = EFFECT_TYPE_SINGLE;
negeff->code = EFFECT_DISABLE_CHAIN;
2016-07-21 22:42:10 +08:00
negeff->value = clit.chain_id;
2015-10-28 16:55:44 +08:00
negeff->reset_flag = RESET_CHAIN | RESET_EVENT | deffect->get_value();
phandler->add_effect(negeff);
}
core.new_chains.pop_front();
2017-11-26 00:05:15 +09:00
return FALSE;
}
case 2: {
auto& clit = core.current_chain.back();
int32 playerid = clit.triggering_player;
effect* peffect = clit.triggering_effect;
if(get_cteffect(peffect, playerid, TRUE)) {
const bool damage_step = infos.phase == PHASE_DAMAGE && !peffect->is_flag(EFFECT_FLAG_DAMAGE_STEP);
const bool damage_cal = infos.phase == PHASE_DAMAGE_CAL && !peffect->is_flag(EFFECT_FLAG_DAMAGE_CAL);
if(damage_step || damage_cal) {
returns.ivalue[0] = TRUE;
return FALSE;
}
2017-11-27 21:35:12 +08:00
add_process(PROCESSOR_SELECT_EFFECTYN, 0, 0, (group*)peffect->get_handler(), playerid, 94);
2017-11-26 00:05:15 +09:00
} else
returns.ivalue[0] = FALSE;
return FALSE;
}
case 3: {
if(!returns.ivalue[0]) {
core.select_chains.clear();
core.select_options.clear();
core.units.begin()->step = 4;
return FALSE;
}
if(core.select_chains.size() > 1) {
auto& clit = core.current_chain.back();
add_process(PROCESSOR_SELECT_OPTION, 0, 0, 0, clit.triggering_player, 0);
} else
returns.ivalue[0] = 0;
return FALSE;
}
case 4: {
auto& clit = core.current_chain.back();
chain& ch = core.select_chains[returns.ivalue[0]];
int32 playerid = clit.triggering_player;
effect* peffect = ch.triggering_effect;
card* phandler = peffect->get_handler();
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_OPSELECTED);
pduel->write_buffer8(playerid);
2018-03-16 19:43:51 +01:00
pduel->write_buffer64(core.select_options[returns.ivalue[0]]);
2017-11-26 00:05:15 +09:00
clit.triggering_effect = peffect;
clit.evt = ch.evt;
phandler->create_relation(clit);
peffect->dec_count(playerid);
2017-11-26 11:30:45 +09:00
if(!(peffect->type & EFFECT_TYPE_ACTIVATE)) {
peffect->type |= EFFECT_TYPE_ACTIVATE;
clit.flag |= CHAIN_ACTIVATING;
}
2017-11-26 00:05:15 +09:00
core.select_chains.clear();
core.select_options.clear();
effect* deffect = pduel->new_effect();
deffect->owner = phandler;
deffect->code = 0;
deffect->type = EFFECT_TYPE_SINGLE;
deffect->flag[0] = EFFECT_FLAG_CANNOT_DISABLE | EFFECT_FLAG_CLIENT_HINT;
deffect->description = 65;
deffect->reset_flag = RESET_CHAIN;
phandler->add_effect(deffect);
return FALSE;
}
case 5: {
auto& clit = core.current_chain.back();
effect* peffect = clit.triggering_effect;
2015-09-25 21:07:16 +08:00
if(peffect->cost) {
core.sub_solving_event.push_back(clit.evt);
add_process(PROCESSOR_EXECUTE_COST, 0, peffect, 0, clit.triggering_player, 0);
}
return FALSE;
}
2017-11-26 00:05:15 +09:00
case 6: {
2015-09-25 21:07:16 +08:00
auto& clit = core.current_chain.back();
effect* peffect = clit.triggering_effect;
if(peffect->target) {
core.sub_solving_event.push_back(clit.evt);
add_process(PROCESSOR_EXECUTE_TARGET, 0, peffect, 0, clit.triggering_player, 0);
}
return FALSE;
}
2017-11-26 00:05:15 +09:00
case 7: {
2015-09-25 21:07:16 +08:00
break_effect();
auto& clit = core.current_chain.back();
effect* peffect = clit.triggering_effect;
2016-11-16 19:52:12 +09:00
card* phandler = peffect->get_handler();
2015-09-25 21:07:16 +08:00
if(clit.target_cards && clit.target_cards->container.size()) {
2015-10-31 15:50:37 +09:00
if(peffect->is_flag(EFFECT_FLAG_CARD_TARGET)) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : clit.target_cards->container)
raise_single_event(pcard, 0, EVENT_BECOME_TARGET, peffect, 0, clit.triggering_player, 0, clit.chain_count);
2015-09-25 21:07:16 +08:00
process_single_event();
if(clit.target_cards->container.size())
raise_event(&clit.target_cards->container, EVENT_BECOME_TARGET, peffect, 0, clit.triggering_player, clit.triggering_player, clit.chain_count);
}
}
if(peffect->type & EFFECT_TYPE_ACTIVATE) {
2016-11-16 19:52:12 +09:00
core.leave_confirmed.insert(phandler);
2018-09-17 19:44:58 +08:00
if(!(phandler->data.type & (TYPE_CONTINUOUS | TYPE_FIELD | TYPE_EQUIP | TYPE_PENDULUM))
2016-11-16 19:52:12 +09:00
&& !phandler->is_affected_by_effect(EFFECT_REMAIN_FIELD))
phandler->set_status(STATUS_LEAVE_CONFIRMED, TRUE);
2015-09-25 21:07:16 +08:00
}
2018-09-17 19:44:58 +08:00
if((phandler->get_type() & (TYPE_SPELL | TYPE_TRAP))
&& (phandler->data.type & (TYPE_CONTINUOUS | TYPE_FIELD | TYPE_EQUIP | TYPE_PENDULUM))
2017-07-03 18:17:34 +09:00
&& phandler->is_has_relation(clit) && phandler->current.location == LOCATION_SZONE
&& !peffect->is_flag(EFFECT_FLAG_FIELD_ONLY))
clit.flag |= CHAIN_CONTINUOUS_CARD;
2015-09-25 21:07:16 +08:00
core.phase_action = TRUE;
2017-06-30 13:00:05 +08:00
if(clit.opinfos.count(0x200) && clit.opinfos[0x200].op_count) {
2015-09-25 21:07:16 +08:00
core.spsummon_rst = true;
set_spsummon_counter(clit.triggering_player, true, true);
if(clit.opinfos[0x200].op_player == PLAYER_ALL)
set_spsummon_counter(1 - clit.triggering_player, true, true);
2016-03-18 16:14:56 +08:00
if((core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) && peffect->is_flag(EFFECT_FLAG_CARD_TARGET)) {
2015-09-25 21:07:16 +08:00
auto& optarget = clit.opinfos[0x200];
if(optarget.op_cards) {
if(optarget.op_player == PLAYER_ALL) {
auto opit = optarget.op_cards->container.begin();
uint32 sumplayer = optarget.op_param;
if((*opit)->spsummon_code) {
core.spsummon_once_map[sumplayer][(*opit)->spsummon_code]++;
core.spsummon_once_map_rst[sumplayer][(*opit)->spsummon_code]++;
}
++opit;
if((*opit)->spsummon_code) {
core.spsummon_once_map[1 - sumplayer][(*opit)->spsummon_code]++;
core.spsummon_once_map_rst[1 - sumplayer][(*opit)->spsummon_code]++;
}
} else {
uint32 sumplayer = clit.triggering_player;
if(optarget.op_player == 1)
sumplayer = 1 - sumplayer;
2018-09-03 16:36:45 +08:00
for(auto& pcard : optarget.op_cards->container) {
if(pcard->spsummon_code) {
core.spsummon_once_map[sumplayer][pcard->spsummon_code]++;
core.spsummon_once_map_rst[sumplayer][pcard->spsummon_code]++;
2015-09-25 21:07:16 +08:00
}
}
}
}
}
}
pduel->write_buffer8(MSG_CHAINED);
pduel->write_buffer8(clit.chain_count);
2016-11-16 19:52:12 +09:00
raise_event(phandler, EVENT_CHAINING, peffect, 0, clit.triggering_player, clit.triggering_player, clit.chain_count);
2015-09-25 21:07:16 +08:00
process_instant_event();
if(core.new_chains.size())
add_process(PROCESSOR_ADD_CHAIN, 0, 0, 0, 0, 0);
adjust_all();
return TRUE;
}
}
return TRUE;
}
int32 field::sort_chain(uint16 step, uint8 tp) {
switch(step) {
case 0: {
core.select_cards.clear();
if(tp)
for(auto clit = core.tpchain.begin(); clit != core.tpchain.end(); ++clit)
2016-11-16 19:52:12 +09:00
core.select_cards.push_back(clit->triggering_effect->get_handler());
2015-09-25 21:07:16 +08:00
else
for(auto clit = core.ntpchain.begin(); clit != core.ntpchain.end(); ++clit)
2016-11-16 19:52:12 +09:00
core.select_cards.push_back(clit->triggering_effect->get_handler());
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_SORT_CARD, 0, 0, 0, tp ? infos.turn_player : (1 - infos.turn_player), 1);
return FALSE;
}
case 1: {
if(returns.bvalue[0] == -1)
return TRUE;
chain_list::iterator clit;
int32 i = 0, count;
if(tp) {
count = core.tpchain.size();
2016-03-21 18:08:57 +09:00
chain_array ch(count);
2015-09-25 21:07:16 +08:00
for(i = 0, clit = core.tpchain.begin(); i < count; ++clit, ++i)
ch[returns.bvalue[i]] = *clit;
core.tpchain.clear();
for(i = 0; i < count; ++i)
core.tpchain.push_back(ch[i]);
} else {
count = core.ntpchain.size();
2016-03-21 18:08:57 +09:00
chain_array ch(count);
2015-09-25 21:07:16 +08:00
for(i = 0, clit = core.ntpchain.begin(); i < count; ++clit, ++i)
ch[returns.bvalue[i]] = *clit;
core.ntpchain.clear();
for(i = 0; i < count; ++i)
core.ntpchain.push_back(ch[i]);
}
return TRUE;
}
}
return TRUE;
}
void field::solve_continuous(uint8 playerid, effect* peffect, const tevent& e) {
chain newchain;
newchain.chain_id = 0;
newchain.chain_count = 0;
newchain.triggering_effect = peffect;
newchain.triggering_player = playerid;
newchain.evt = e;
newchain.target_cards = 0;
newchain.target_player = PLAYER_NONE;
newchain.target_param = 0;
newchain.disable_player = PLAYER_NONE;
newchain.disable_reason = 0;
newchain.flag = 0;
core.sub_solving_continuous.push_back(newchain);
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
}
int32 field::solve_continuous(uint16 step) {
2015-09-25 21:07:16 +08:00
switch(step) {
case 0: {
core.solving_continuous.splice(core.solving_continuous.begin(), core.sub_solving_continuous);
auto& clit = core.solving_continuous.front();
effect* peffect = clit.triggering_effect;
uint8 triggering_player = clit.triggering_player;
2015-09-25 21:07:16 +08:00
if(!peffect->check_count_limit(triggering_player)) {
core.solving_continuous.pop_front();
2015-09-25 21:07:16 +08:00
return TRUE;
}
core.continuous_chain.push_back(clit);
if(peffect->is_flag(EFFECT_FLAG_DELAY) || (!(peffect->code & 0x10030000) && (peffect->code & (EVENT_PHASE | EVENT_PHASE_START))))
core.conti_solving = TRUE;
2016-02-24 01:07:54 +08:00
core.units.begin()->ptarget = (group*)core.reason_effect;
core.units.begin()->arg2 = core.reason_player;
2015-09-25 21:07:16 +08:00
if(!peffect->target)
return FALSE;
core.sub_solving_event.push_back(clit.evt);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_EXECUTE_TARGET, 0, peffect, 0, triggering_player, 0);
return FALSE;
}
case 1: {
return FALSE;
}
case 2: {
auto& clit = core.solving_continuous.front();
effect* peffect = clit.triggering_effect;
uint8 triggering_player = clit.triggering_player;
2015-09-25 21:07:16 +08:00
if(!peffect->operation)
return FALSE;
peffect->dec_count(triggering_player);
core.sub_solving_event.push_back(clit.evt);
2015-09-25 21:07:16 +08:00
add_process(PROCESSOR_EXECUTE_OPERATION, 0, peffect, 0, triggering_player, 0);
return FALSE;
}
case 3: {
auto& clit = core.solving_continuous.front();
effect* peffect = clit.triggering_effect;
uint8 triggering_player = clit.triggering_player;
2016-02-24 01:07:54 +08:00
core.reason_effect = (effect*)core.units.begin()->ptarget;
core.reason_player = core.units.begin()->arg2;
2015-09-25 21:07:16 +08:00
if(core.continuous_chain.back().target_cards)
pduel->delete_group(core.continuous_chain.back().target_cards);
2018-09-03 16:36:45 +08:00
for(auto& oit : core.continuous_chain.back().opinfos) {
if(oit.second.op_cards)
pduel->delete_group(oit.second.op_cards);
2015-09-25 21:07:16 +08:00
}
core.continuous_chain.pop_back();
core.solving_continuous.pop_front();
if(peffect->is_flag(EFFECT_FLAG_DELAY) || (!(peffect->code & 0x10030000) && (peffect->code & (EVENT_PHASE | EVENT_PHASE_START)))) {
core.conti_solving = FALSE;
adjust_all();
2016-12-07 13:28:36 +08:00
return FALSE;
}
return TRUE;
}
case 4: {
if(core.conti_player == PLAYER_NONE)
core.conti_player = infos.turn_player;
if(core.conti_player == infos.turn_player) {
if(core.delayed_continuous_tp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), core.delayed_continuous_tp, core.delayed_continuous_tp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2016-12-07 13:28:36 +08:00
} else
core.conti_player = 1 - infos.turn_player;
}
if(core.conti_player == 1 - infos.turn_player) {
if(core.delayed_continuous_ntp.size()) {
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), core.delayed_continuous_ntp, core.delayed_continuous_ntp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
} else if(core.delayed_continuous_tp.size()) {
core.conti_player = infos.turn_player;
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), core.delayed_continuous_tp, core.delayed_continuous_tp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2016-12-07 13:28:36 +08:00
} else
core.conti_player = PLAYER_NONE;
2015-09-25 21:07:16 +08:00
}
return TRUE;
}
}
return TRUE;
}
int32 field::solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2) {
if(core.current_chain.size() == 0 && step == 0)
return TRUE;
2016-05-07 06:13:42 +09:00
auto cait = core.current_chain.rbegin();
2015-09-25 21:07:16 +08:00
switch(step) {
case 0: {
if(core.spsummon_rst) {
set_spsummon_counter(0, false, true);
set_spsummon_counter(1, false, true);
for(int plr = 0; plr < 2; ++plr) {
2018-09-03 16:36:45 +08:00
for(auto& iter : core.spsummon_once_map[plr]) {
auto spcode = iter.first;
2015-09-25 21:07:16 +08:00
core.spsummon_once_map[plr][spcode] -= core.spsummon_once_map_rst[plr][spcode];
core.spsummon_once_map_rst[plr][spcode] = 0;
}
}
core.spsummon_rst = false;
}
pduel->write_buffer8(MSG_CHAIN_SOLVING);
pduel->write_buffer8(cait->chain_count);
2016-11-16 19:52:12 +09:00
add_to_disable_check_list(cait->triggering_effect->get_handler());
2015-09-25 21:07:16 +08:00
adjust_instant();
raise_event((card*)0, EVENT_CHAIN_ACTIVATING, cait->triggering_effect, 0, cait->triggering_player, cait->triggering_player, cait->chain_count);
process_instant_event();
return FALSE;
}
case 1: {
effect* peffect = cait->triggering_effect;
if(cait->flag & CHAIN_DISABLE_ACTIVATE && is_chain_negatable(cait->chain_count)) {
remove_oath_effect(peffect);
2018-10-19 17:27:05 +02:00
if(peffect->is_flag(EFFECT_FLAG_COUNT_LIMIT) && (peffect->count_flag & EFFECT_COUNT_CODE_OATH)) {
dec_effect_code(peffect->count_code, peffect->count_flag, cait->triggering_player);
2015-09-25 21:07:16 +08:00
}
check_chain_counter(peffect, cait->triggering_player, cait->chain_count, true);
raise_event((card*)0, EVENT_CHAIN_NEGATED, peffect, 0, cait->triggering_player, cait->triggering_player, cait->chain_count);
process_instant_event();
core.units.begin()->step = 9;
return FALSE;
}
2018-09-03 16:36:45 +08:00
for(auto& oeit : effects.oath)
if(oeit.second == peffect)
oeit.second = 0;
2015-09-25 21:07:16 +08:00
break_effect();
core.chain_solving = TRUE;
raise_event((card*)0, EVENT_CHAIN_SOLVING, peffect, 0, cait->triggering_player, cait->triggering_player, cait->chain_count);
process_instant_event();
return FALSE;
}
case 2: {
core.spsummon_state_count_tmp[0] = core.spsummon_state_count[0];
core.spsummon_state_count_tmp[1] = core.spsummon_state_count[1];
effect* peffect = cait->triggering_effect;
2016-11-16 19:52:12 +09:00
card* pcard = peffect->get_handler();
if((peffect->type & EFFECT_TYPE_ACTIVATE) && pcard->is_has_relation(*cait)) {
2016-04-08 19:38:51 +08:00
pcard->enable_field_effect(true);
2018-02-01 22:50:41 +01:00
if((core.duel_options & DUEL_1_FIELD)) {
2015-09-25 21:07:16 +08:00
if(pcard->data.type & TYPE_FIELD) {
card* fscard = player[1 - pcard->current.controler].list_szone[5];
if(fscard && fscard->is_position(POS_FACEUP))
2016-04-08 19:38:51 +08:00
fscard->enable_field_effect(false);
2015-09-25 21:07:16 +08:00
}
}
adjust_instant();
}
if(is_chain_disablable(cait->chain_count)) {
2016-07-21 22:42:10 +08:00
if(is_chain_disabled(cait->chain_count) || (pcard->get_status(STATUS_DISABLED | STATUS_FORBIDDEN) && pcard->is_has_relation(*cait))) {
2015-09-25 21:07:16 +08:00
if(!(cait->flag & CHAIN_DISABLE_EFFECT)) {
pduel->write_buffer8(MSG_CHAIN_DISABLED);
pduel->write_buffer8(cait->chain_count);
}
2018-07-22 11:51:39 +08:00
raise_event((card*)0, EVENT_CHAIN_DISABLED, peffect, 0, cait->triggering_player, cait->triggering_player, cait->chain_count);
2015-09-25 21:07:16 +08:00
process_instant_event();
core.units.begin()->step = 3;
return FALSE;
}
}
if(cait->replace_op) {
core.units.begin()->arg4 = cait->triggering_effect->operation;
2015-09-25 21:07:16 +08:00
cait->triggering_effect->operation = cait->replace_op;
} else
core.units.begin()->arg4 = 0;
2017-07-03 18:17:34 +09:00
if((cait->flag & CHAIN_CONTINUOUS_CARD) && !pcard->is_has_relation(*cait))
return FALSE;
2015-09-25 21:07:16 +08:00
if(cait->triggering_effect->operation) {
core.sub_solving_event.push_back(cait->evt);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, cait->triggering_effect, 0, cait->triggering_player, 0);
}
return FALSE;
}
case 3: {
effect* peffect = cait->triggering_effect;
if(core.units.begin()->arg4) {
peffect->operation = core.units.begin()->arg4;
2015-09-25 21:07:16 +08:00
}
core.special_summoning.clear();
core.equiping_cards.clear();
return FALSE;
}
case 4: {
if(core.units.begin()->arg4 == 0) {
2017-06-30 13:00:05 +08:00
if(cait->opinfos.count(0x200) && cait->opinfos[0x200].op_count) {
2015-09-25 21:07:16 +08:00
if(core.spsummon_state_count_tmp[cait->triggering_player] == core.spsummon_state_count[cait->triggering_player])
set_spsummon_counter(cait->triggering_player);
if(cait->opinfos[0x200].op_player == PLAYER_ALL && core.spsummon_state_count_tmp[1 - cait->triggering_player] == core.spsummon_state_count[1 - cait->triggering_player])
set_spsummon_counter(1 - cait->triggering_player);
//sometimes it may add twice, only works for once per turn
2015-10-31 15:50:37 +09:00
if(cait->triggering_effect->is_flag(EFFECT_FLAG_CARD_TARGET)) {
2015-09-25 21:07:16 +08:00
auto& optarget = cait->opinfos[0x200];
if(optarget.op_cards) {
if(optarget.op_player == PLAYER_ALL) {
uint32 sumplayer = optarget.op_param;
if(core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) {
auto opit = optarget.op_cards->container.begin();
if((*opit)->spsummon_code)
core.spsummon_once_map[sumplayer][(*opit)->spsummon_code]++;
++opit;
if((*opit)->spsummon_code)
core.spsummon_once_map[1 - sumplayer][(*opit)->spsummon_code]++;
}
auto opit = optarget.op_cards->container.begin();
check_card_counter(*opit, 3, sumplayer);
++opit;
check_card_counter(*opit, 3, 1 - sumplayer);
} else {
uint32 sumplayer = cait->triggering_player;
if(optarget.op_player == 1)
sumplayer = 1 - sumplayer;
2018-09-03 16:36:45 +08:00
for(auto& ptarget : optarget.op_cards->container) {
if((core.global_flag & GLOBALFLAG_SPSUMMON_ONCE) && ptarget->spsummon_code)
core.spsummon_once_map[sumplayer][ptarget->spsummon_code]++;
check_card_counter(ptarget, 3, sumplayer);
2015-09-25 21:07:16 +08:00
}
}
}
}
}
}
core.spsummon_state_count_tmp[0] = 0;
core.spsummon_state_count_tmp[1] = 0;
core.chain_solving = FALSE;
if(core.delayed_continuous_tp.size()) {
2015-09-25 21:07:16 +08:00
core.conti_player = infos.turn_player;
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), core.delayed_continuous_tp, core.delayed_continuous_tp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
} else if(core.delayed_continuous_ntp.size()) {
2015-09-25 21:07:16 +08:00
core.conti_player = 1 - infos.turn_player;
core.sub_solving_continuous.splice(core.sub_solving_continuous.end(), core.delayed_continuous_ntp, core.delayed_continuous_ntp.begin());
add_process(PROCESSOR_SOLVE_CONTINUOUS, 0, 0, 0, 0, 0);
2016-04-20 13:49:15 +08:00
} else
2015-09-25 21:07:16 +08:00
core.conti_player = PLAYER_NONE;
pduel->write_buffer8(MSG_CHAIN_SOLVED);
pduel->write_buffer8(cait->chain_count);
raise_event((card*)0, EVENT_CHAIN_SOLVED, cait->triggering_effect, 0, cait->triggering_player, cait->triggering_player, cait->chain_count);
2015-12-31 22:32:09 +08:00
adjust_disable_check_list();
2015-09-25 21:07:16 +08:00
process_instant_event();
core.units.begin()->step = 9;
return FALSE;
}
case 10: {
effect* peffect = cait->triggering_effect;
2016-11-16 19:52:12 +09:00
card* pcard = peffect->get_handler();
2018-06-24 22:38:54 +08:00
if((peffect->type & EFFECT_TYPE_ACTIVATE) && (cait->flag & CHAIN_ACTIVATING))
peffect->type &= ~EFFECT_TYPE_ACTIVATE;
if((cait->flag & CHAIN_HAND_EFFECT) && !pcard->is_position(POS_FACEUP) && (pcard->current.location == LOCATION_HAND))
2015-09-25 21:07:16 +08:00
shuffle(pcard->current.controler, LOCATION_HAND);
if(cait->target_cards && cait->target_cards->container.size()) {
2018-09-03 16:36:45 +08:00
for(auto& ptarget : cait->target_cards->container)
ptarget->release_relation(*cait);
2015-09-25 21:07:16 +08:00
}
if((pcard->data.type & TYPE_EQUIP) && (peffect->type & EFFECT_TYPE_ACTIVATE)
2016-08-23 19:18:26 +02:00
&& !pcard->equiping_target && pcard->is_has_relation(*cait))
2016-12-28 19:17:34 +08:00
destroy(pcard, 0, REASON_RULE, PLAYER_NONE);
2018-02-01 22:50:41 +01:00
if((core.duel_options & DUEL_1_FIELD)) {
2015-09-25 21:07:16 +08:00
if((pcard->data.type & TYPE_FIELD) && (peffect->type & EFFECT_TYPE_ACTIVATE)
2016-01-06 00:49:14 +09:00
&& !pcard->is_status(STATUS_LEAVE_CONFIRMED) && pcard->is_has_relation(*cait)) {
2015-09-25 21:07:16 +08:00
card* fscard = player[1 - pcard->current.controler].list_szone[5];
if(fscard && fscard->is_position(POS_FACEUP))
destroy(fscard, 0, REASON_RULE, 1 - pcard->current.controler);
}
}
peffect->active_type = 0;
2016-11-16 19:52:12 +09:00
peffect->active_handler = 0;
2016-01-06 00:49:14 +09:00
pcard->release_relation(*cait);
2015-09-25 21:07:16 +08:00
if(cait->target_cards)
pduel->delete_group(cait->target_cards);
2018-09-03 16:36:45 +08:00
for(auto& oit : cait->opinfos) {
if(oit.second.op_cards)
pduel->delete_group(oit.second.op_cards);
2015-09-25 21:07:16 +08:00
}
2018-09-03 16:36:45 +08:00
for(auto& cit : core.delayed_enable_set) {
if(cit->current.location == LOCATION_MZONE)
cit->enable_field_effect(true);
2015-09-25 21:07:16 +08:00
}
core.delayed_enable_set.clear();
adjust_all();
core.current_chain.pop_back();
if(!core.current_chain.size()) {
2018-09-03 16:36:45 +08:00
for(auto& ch_lim : core.chain_limit)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim.function);
2017-07-23 18:03:58 +09:00
core.chain_limit.clear();
2015-09-25 21:07:16 +08:00
return FALSE;
}
core.units.begin()->step = -1;
return FALSE;
}
case 11: {
for(auto cit = core.leave_confirmed.begin(); cit != core.leave_confirmed.end();) {
auto rm = cit++;
if(!(*rm)->is_status(STATUS_LEAVE_CONFIRMED))
core.leave_confirmed.erase(rm);
}
if(core.leave_confirmed.size())
send_to(&core.leave_confirmed, 0, REASON_RULE, PLAYER_NONE, PLAYER_NONE, LOCATION_GRAVE, 0, POS_FACEUP);
return FALSE;
}
case 12: {
core.used_event.splice(core.used_event.end(), core.point_event);
pduel->write_buffer8(MSG_CHAIN_END);
2018-09-03 16:36:45 +08:00
for(auto& ch_lim_p : core.chain_limit_p)
luaL_unref(pduel->lua->lua_state, LUA_REGISTRYINDEX, ch_lim_p.function);
2017-07-23 18:03:58 +09:00
core.chain_limit_p.clear();
2015-09-25 21:07:16 +08:00
reset_chain();
if(core.summoning_card || core.effect_damage_step == 1)
2015-09-25 21:07:16 +08:00
core.subunits.push_back(core.reserved);
return FALSE;
}
case 13: {
raise_event((card*)0, EVENT_CHAIN_END, 0, 0, 0, 0, 0);
process_instant_event();
2016-10-16 15:14:36 +08:00
adjust_all();
2016-09-07 10:14:35 +08:00
if(chainend_arg1 != 0x101 || chainend_arg2 != TRUE) {
core.hint_timing[0] |= TIMING_CHAIN_END;
core.hint_timing[1] |= TIMING_CHAIN_END;
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, chainend_arg1, chainend_arg2);
}
2015-09-25 21:07:16 +08:00
returns.ivalue[0] = TRUE;
return TRUE;
}
}
return TRUE;
}
int32 field::break_effect() {
core.hint_timing[0] &= TIMING_DAMAGE_STEP | TIMING_DAMAGE_CAL;
core.hint_timing[1] &= TIMING_DAMAGE_STEP | TIMING_DAMAGE_CAL;
for (auto chit = core.new_ochain.begin(); chit != core.new_ochain.end();) {
auto rm = chit++;
effect* peffect = rm->triggering_effect;
2016-03-18 16:14:56 +08:00
if (!peffect->is_flag(EFFECT_FLAG_DELAY)) {
if (peffect->is_flag(EFFECT_FLAG_FIELD_ONLY)
2017-04-12 09:35:29 +09:00
|| !(peffect->type & EFFECT_TYPE_FIELD) || peffect->in_range(*rm)) {
2015-09-25 21:07:16 +08:00
pduel->write_buffer8(MSG_MISSED_EFFECT);
2016-11-16 19:52:12 +09:00
pduel->write_buffer32(peffect->get_handler()->get_info_location());
pduel->write_buffer32(peffect->get_handler()->data.code);
2015-09-25 21:07:16 +08:00
}
core.new_ochain.erase(rm);
}
}
2016-03-26 01:01:46 +08:00
core.delayed_quick_break.insert(core.delayed_quick_tmp.begin(), core.delayed_quick_tmp.end());
core.delayed_quick_tmp.clear();
2015-09-25 21:07:16 +08:00
core.used_event.splice(core.used_event.end(), core.instant_event);
adjust_instant();
return 0;
}
void field::adjust_instant() {
adjust_disable_check_list();
adjust_self_destroy_set();
}
void field::adjust_all() {
core.readjust_map.clear();
add_process(PROCESSOR_ADJUST, 0, 0, 0, 0, 0);
}
void field::refresh_location_info_instant() {
effect_set eset;
2017-03-14 23:54:51 +09:00
uint32 dis1 = player[0].disabled_location | (player[1].disabled_location << 16);
2015-09-25 21:07:16 +08:00
player[0].disabled_location = 0;
player[1].disabled_location = 0;
filter_field_effect(EFFECT_DISABLE_FIELD, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint32 value = eset[i]->get_value();
player[0].disabled_location |= value & 0xff7f;
player[1].disabled_location |= (value >> 16) & 0xff7f;
2015-09-25 21:07:16 +08:00
}
eset.clear();
filter_field_effect(EFFECT_USE_EXTRA_MZONE, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint8 p = eset[i]->get_handler_player();
uint32 value = eset[i]->get_value();
2015-09-25 21:07:16 +08:00
player[p].disabled_location |= (value >> 16) & 0x1f;
}
eset.clear();
filter_field_effect(EFFECT_USE_EXTRA_SZONE, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint8 p = eset[i]->get_handler_player();
uint32 value = eset[i]->get_value();
2015-09-25 21:07:16 +08:00
player[p].disabled_location |= (value >> 8) & 0x1f00;
}
2017-03-30 00:42:22 +09:00
player[0].disabled_location |= (((player[1].disabled_location >> 5) & 1) << 6) | (((player[1].disabled_location >> 6) & 1) << 5);
player[1].disabled_location |= (((player[0].disabled_location >> 5) & 1) << 6) | (((player[0].disabled_location >> 6) & 1) << 5);
2017-03-14 23:54:51 +09:00
uint32 dis2 = player[0].disabled_location | (player[1].disabled_location << 16);
2015-09-25 21:07:16 +08:00
if(dis1 != dis2) {
pduel->write_buffer8(MSG_FIELD_DISABLED);
pduel->write_buffer32(dis2);
}
}
int32 field::refresh_location_info(uint16 step) {
switch(step) {
case 0: {
effect_set eset;
2017-08-13 18:07:11 +02:00
if (core.duel_options & SPEED_DUEL) {
player[0].used_location |= 0x1111;
player[1].used_location |= 0x1111;
}
2015-09-25 21:07:16 +08:00
core.units.begin()->arg2 = player[0].disabled_location | (player[1].disabled_location << 16);
player[0].disabled_location = 0;
player[1].disabled_location = 0;
core.disfield_effects.clear();
2018-10-16 15:52:51 +08:00
core.extra_mzone_effects.clear();
core.extra_szone_effects.clear();
2015-09-25 21:07:16 +08:00
filter_field_effect(EFFECT_DISABLE_FIELD, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint32 value = eset[i]->get_value();
if(value && !eset[i]->is_flag(EFFECT_FLAG_REPEAT)) {
player[0].disabled_location |= value & 0xff7f;
player[1].disabled_location |= (value >> 16) & 0xff7f;
2015-09-25 21:07:16 +08:00
} else
core.disfield_effects.add_item(eset[i]);
}
eset.clear();
filter_field_effect(EFFECT_USE_EXTRA_MZONE, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint8 p = eset[i]->get_handler_player();
uint32 value = eset[i]->get_value();
2015-09-25 21:07:16 +08:00
player[p].disabled_location |= (value >> 16) & 0x1f;
2016-08-25 21:51:04 +08:00
if((uint32)field_used_count[(value >> 16) & 0x1f] < (value & 0xffff))
2018-10-16 15:52:51 +08:00
core.extra_mzone_effects.add_item(eset[i]);
2015-09-25 21:07:16 +08:00
}
eset.clear();
filter_field_effect(EFFECT_USE_EXTRA_SZONE, &eset);
for (int32 i = 0; i < eset.size(); ++i) {
2018-07-06 21:46:52 +08:00
uint8 p = eset[i]->get_handler_player();
uint32 value = eset[i]->get_value();
2015-09-25 21:07:16 +08:00
player[p].disabled_location |= (value >> 8) & 0x1f00;
2016-08-25 21:51:04 +08:00
if((uint32)field_used_count[(value >> 16) & 0x1f] < (value & 0xffff))
2018-10-16 15:52:51 +08:00
core.extra_szone_effects.add_item(eset[i]);
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 1: {
2018-10-09 20:18:10 +08:00
if(core.disfield_effects.size() == 0) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 2;
return FALSE;
}
effect* peffect = core.disfield_effects[0];
core.units.begin()->peffect = peffect;
core.disfield_effects.remove_item(0);
if(!peffect->operation) {
peffect->value = 0x80;
core.units.begin()->step = 0;
return FALSE;
}
core.sub_solving_event.push_back(nil_event);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, peffect, 0, peffect->get_handler_player(), 0);
return FALSE;
}
case 2: {
returns.ivalue[0] &= 0xff7fff7f;
2015-09-25 21:07:16 +08:00
if(returns.ivalue[0] == 0)
returns.ivalue[0] = 0x80;
if(core.units.begin()->peffect->get_handler_player() == 0) {
core.units.begin()->peffect->value = returns.ivalue[0];
player[0].disabled_location |= returns.ivalue[0] & 0xff7f;
player[1].disabled_location |= (returns.ivalue[0] >> 16) & 0xff7f;
2015-09-25 21:07:16 +08:00
} else {
core.units.begin()->peffect->value = ((returns.ivalue[0] << 16) | (returns.ivalue[0] >> 16));
player[1].disabled_location |= returns.ivalue[0] & 0xff7f;
player[0].disabled_location |= (returns.ivalue[0] >> 16) & 0xff7f;
2015-09-25 21:07:16 +08:00
}
core.units.begin()->step = 0;
return FALSE;
}
case 3: {
2018-10-16 15:52:51 +08:00
if(core.extra_mzone_effects.size() == 0) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 4;
return FALSE;
}
2018-10-16 15:52:51 +08:00
effect* peffect = core.extra_mzone_effects[0];
2015-09-25 21:07:16 +08:00
core.units.begin()->peffect = peffect;
2018-10-16 15:52:51 +08:00
core.extra_mzone_effects.remove_item(0);
2016-08-25 21:51:04 +08:00
uint32 p = peffect->get_handler_player();
uint32 mzone_flag = (player[p].disabled_location | player[p].used_location) & 0x1f;
if(mzone_flag == 0x1f) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 4;
return FALSE;
}
2016-08-25 21:51:04 +08:00
int32 val = peffect->get_value();
int32 dis_count = (val & 0xffff) - field_used_count[(val >> 16) & 0x1f];
int32 empty_count = 5 - field_used_count[mzone_flag];
2017-07-03 22:30:46 +08:00
uint32 flag = mzone_flag | 0xffffffe0;
2016-08-25 21:51:04 +08:00
if(dis_count > empty_count)
dis_count = empty_count;
core.units.begin()->arg1 = dis_count;
add_process(PROCESSOR_SELECT_DISFIELD, 0, 0, 0, p, flag, dis_count);
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 4: {
2016-08-25 21:51:04 +08:00
uint32 dis_count = core.units.begin()->arg1;
uint32 mzone_flag = 0;
2018-07-06 21:46:52 +08:00
uint8 pt = 0;
2016-08-25 21:51:04 +08:00
for(uint32 i = 0; i < dis_count; ++i) {
2018-07-06 21:46:52 +08:00
uint8 s = returns.bvalue[pt + 2];
2016-08-25 21:51:04 +08:00
mzone_flag |= 0x1u << s;
2015-09-25 21:07:16 +08:00
pt += 3;
}
effect* peffect = core.units.begin()->peffect;
2016-08-25 21:51:04 +08:00
player[peffect->get_handler_player()].disabled_location |= mzone_flag;
peffect->value = (int32)(peffect->value | (mzone_flag << 16));
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 2;
return FALSE;
}
case 5: {
2018-10-16 15:52:51 +08:00
if(core.extra_szone_effects.size() == 0) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 6;
return FALSE;
}
2018-10-16 15:52:51 +08:00
effect* peffect = core.extra_szone_effects[0];
2015-09-25 21:07:16 +08:00
core.units.begin()->peffect = peffect;
2018-10-16 15:52:51 +08:00
core.extra_szone_effects.remove_item(0);
2016-08-25 21:51:04 +08:00
uint32 p = peffect->get_handler_player();
2017-03-14 23:54:51 +09:00
uint32 szone_flag = ((player[p].disabled_location | player[p].used_location) >> 8) & 0x1f;
2016-08-25 21:51:04 +08:00
if(szone_flag == 0x1f) {
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 6;
return FALSE;
}
2016-08-25 21:51:04 +08:00
int32 val = peffect->get_value();
uint32 dis_count = (val & 0xffff) - field_used_count[(val >> 16) & 0x1f];
uint32 empty_count = 5 - field_used_count[szone_flag];
2016-10-13 15:52:41 +08:00
uint32 flag = (szone_flag << 8) | 0xffffe0ff;
2016-08-25 21:51:04 +08:00
if(dis_count > empty_count)
dis_count = empty_count;
core.units.begin()->arg1 = dis_count;
add_process(PROCESSOR_SELECT_DISFIELD, 0, 0, 0, p, flag, dis_count);
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 6: {
2016-08-25 21:51:04 +08:00
uint32 dis_count = core.units.begin()->arg1;
uint32 szone_flag = 0;
2018-07-06 21:46:52 +08:00
uint8 pt = 0;
2016-08-25 21:51:04 +08:00
for(uint32 i = 0; i < dis_count; ++i) {
2018-07-06 21:46:52 +08:00
uint8 s = returns.bvalue[pt + 2];
2016-08-25 21:51:04 +08:00
szone_flag |= 0x1u << s;
2015-09-25 21:07:16 +08:00
pt += 3;
}
effect* peffect = core.units.begin()->peffect;
2016-08-25 21:51:04 +08:00
player[peffect->get_handler_player()].disabled_location |= szone_flag << 8;
peffect->value = (int32)(peffect->value | (szone_flag << 16));
2015-09-25 21:07:16 +08:00
core.units.begin()->step = 4;
return FALSE;
}
case 7: {
2017-03-30 00:42:22 +09:00
player[0].disabled_location |= (((player[1].disabled_location >> 5) & 1) << 6) | (((player[1].disabled_location >> 6) & 1) << 5);
player[1].disabled_location |= (((player[0].disabled_location >> 5) & 1) << 6) | (((player[0].disabled_location >> 6) & 1) << 5);
2015-09-25 21:07:16 +08:00
uint32 dis = player[0].disabled_location | (player[1].disabled_location << 16);
if(dis != (uint32)core.units.begin()->arg2) {
pduel->write_buffer8(MSG_FIELD_DISABLED);
pduel->write_buffer32(dis);
}
return TRUE;
}
}
return TRUE;
}
int32 field::adjust_step(uint16 step) {
switch(step) {
case 0: {
core.re_adjust = FALSE;
return FALSE;
}
case 1: {
//win check(deck=0 or lp=0)
2018-02-01 22:50:41 +01:00
if(!core.force_turn_end){
uint32 winp = 5, rea = 1;
if (player[0].lp <= 0 && player[1].lp > 0 && !is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_LP)) {
winp = 1;
2018-02-01 22:50:41 +01:00
rea = 1;
}
if (core.overdraw[0] && !core.overdraw[1] && !is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_DECK)) {
winp = 1;
2018-02-01 22:50:41 +01:00
rea = 2;
}
if (player[1].lp <= 0 && player[0].lp > 0 && !is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_LP)) {
winp = 0;
rea = 1;
}
if (core.overdraw[1] && !core.overdraw[0] && !is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_DECK)) {
winp = 0;
rea = 2;
}
if (player[1].lp <= 0 && player[0].lp <= 0 && !(is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_LP) && is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_LP))) {
if (is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_LP))
winp = 0;
else if (is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_LP))
winp = 1;
else
winp = PLAYER_NONE;
rea = 1;
}
if (core.overdraw[1] && core.overdraw[0] && !(is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_DECK) && is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_DECK))) {
if (is_player_affected_by_effect(0, EFFECT_CANNOT_LOSE_DECK))
winp = 0;
else if (is_player_affected_by_effect(1, EFFECT_CANNOT_LOSE_DECK))
winp = 1;
else
winp = PLAYER_NONE;
rea = 2;
}
if (core.duel_options & DUEL_RELAY_MODE) {
if (winp == PLAYER_NONE) {
bool p1 = relay_check(0);
bool p2 = relay_check(1);
if (p1 && !p2)
winp = 0;
else if (!p1 && p2)
winp = 1;
else if (p1 && p2) {
winp = 5;
core.overdraw[0] = core.overdraw[1] = FALSE;
}
} else if (winp < PLAYER_NONE)
if (relay_check(1 - winp)) {
winp = 5;
core.overdraw[0] = core.overdraw[1] = FALSE;
}
}
if(winp != 5) {
pduel->write_buffer8(MSG_WIN);
pduel->write_buffer8(winp);
pduel->write_buffer8(rea);
core.overdraw[0] = core.overdraw[1] = FALSE;
core.win_player = 5;
core.win_reason = 0;
} else if(core.win_player != 5) {
pduel->write_buffer8(MSG_WIN);
pduel->write_buffer8(core.win_player);
pduel->write_buffer8(core.win_reason);
core.win_player = 5;
core.win_reason = 0;
core.overdraw[0] = core.overdraw[1] = FALSE;
}
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 2: {
//disable check
uint8 tp = infos.turn_player;
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[tp].list_mzone) {
2015-09-25 21:07:16 +08:00
if(pcard)
add_to_disable_check_list(pcard);
}
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[tp].list_szone) {
2015-09-25 21:07:16 +08:00
if(pcard)
add_to_disable_check_list(pcard);
}
tp = 1 - tp;
}
adjust_disable_check_list();
add_process(PROCESSOR_REFRESH_LOC, 0, 0, 0, 0, 0);
return FALSE;
}
case 3: {
//trap monster
uint8 tp = infos.turn_player;
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[tp].list_mzone) {
2015-09-25 21:07:16 +08:00
if(!pcard) continue;
2016-10-03 15:51:51 +08:00
if((pcard->get_type() & TYPE_TRAPMONSTER) && pcard->is_affected_by_effect(EFFECT_DISABLE_TRAPMONSTER)) {
2015-09-25 21:07:16 +08:00
pcard->reset(RESET_TURN_SET, RESET_EVENT);
refresh_location_info_instant();
2016-10-03 15:51:51 +08:00
move_to_field(pcard, tp, tp, LOCATION_SZONE, pcard->current.position, FALSE, 2);
2015-09-25 21:07:16 +08:00
core.re_adjust = TRUE;
}
}
tp = 1 - tp;
}
return FALSE;
}
case 4: {
//1-5 control
core.control_adjust_set[0].clear();
core.control_adjust_set[1].clear();
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[p].list_mzone) {
2015-09-25 21:07:16 +08:00
if(!pcard) continue;
2016-10-16 01:03:02 +09:00
uint8 cur = pcard->current.controler;
uint8 ref = pcard->refresh_control_status();
2016-10-16 04:03:16 +09:00
if(cur != ref && pcard->is_capable_change_control())
2015-09-25 21:07:16 +08:00
core.control_adjust_set[p].insert(pcard);
}
}
if(core.control_adjust_set[0].size() || core.control_adjust_set[1].size()) {
core.re_adjust = TRUE;
add_process(PROCESSOR_CONTROL_ADJUST, 0, 0, 0, 0, 0);
}
2016-10-16 04:03:16 +09:00
core.last_control_changed_id = infos.field_id;
2015-09-25 21:07:16 +08:00
return FALSE;
}
2016-10-16 01:03:02 +09:00
case 5: {
//remove brainwashing
if(core.global_flag & GLOBALFLAG_BRAINWASHING_CHECK) {
2016-10-16 04:03:16 +09:00
core.control_adjust_set[0].clear();
core.control_adjust_set[1].clear();
2016-10-16 01:03:02 +09:00
effect_set eset;
filter_field_effect(EFFECT_REMOVE_BRAINWASHING, &eset, FALSE);
2017-03-14 17:56:08 +09:00
uint32 res = eset.size() ? TRUE : FALSE;
2016-10-16 01:03:02 +09:00
if(res) {
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[p].list_mzone) {
2016-10-16 01:03:02 +09:00
// remove EFFECT_SET_CONTROL
2016-10-16 01:25:13 +09:00
if(pcard && pcard->is_affected_by_effect(EFFECT_REMOVE_BRAINWASHING)) {
2016-10-16 01:03:02 +09:00
pcard->reset(EFFECT_SET_CONTROL, RESET_CODE);
2016-10-16 04:03:16 +09:00
if(p != pcard->owner && pcard->is_capable_change_control())
core.control_adjust_set[p].insert(pcard);
2016-10-16 01:25:13 +09:00
}
2016-10-16 01:03:02 +09:00
}
}
}
core.remove_brainwashing = res;
2016-10-16 04:03:16 +09:00
if(core.control_adjust_set[0].size() || core.control_adjust_set[1].size()) {
core.re_adjust = TRUE;
add_process(PROCESSOR_CONTROL_ADJUST, 0, 0, 0, 0, 0);
}
2016-10-16 01:03:02 +09:00
}
2017-10-06 11:23:09 +09:00
core.units.begin()->step = 7;
return FALSE;
}
case 8: {
if(adjust_grant_effect())
core.re_adjust = TRUE;
2015-09-25 21:07:16 +08:00
return FALSE;
}
2016-10-16 04:03:16 +09:00
case 9: {
2015-09-25 21:07:16 +08:00
if(core.selfdes_disabled) {
core.units.begin()->step = 10;
return FALSE;
}
//self destroy
adjust_self_destroy_set();
return FALSE;
}
case 10: {
//equip check
uint8 tp = infos.turn_player;
2016-05-21 06:37:06 +09:00
card_set destroy_set;
2015-09-25 21:07:16 +08:00
for(uint8 p = 0; p < 2; ++p) {
for(uint8 i = 0; i < 5; ++i) {
2016-05-21 06:37:06 +09:00
card* pcard = player[tp].list_szone[i];
2015-09-25 21:07:16 +08:00
if(pcard && pcard->equiping_target && !pcard->is_affected_by_effect(EFFECT_EQUIP_LIMIT, pcard->equiping_target))
2016-05-21 06:37:06 +09:00
destroy_set.insert(pcard);
2015-09-25 21:07:16 +08:00
}
tp = 1 - tp;
}
2016-05-21 06:37:06 +09:00
if(destroy_set.size()) {
2015-09-25 21:07:16 +08:00
core.re_adjust = TRUE;
2016-05-21 06:37:06 +09:00
destroy(&destroy_set, 0, REASON_RULE, PLAYER_NONE);
2015-09-25 21:07:16 +08:00
}
return FALSE;
}
case 11: {
//position
uint32 tp = infos.turn_player, pos;
card_set pos_adjust;
effect_set eset;
for(uint8 p = 0; p < 2; ++p) {
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[tp].list_mzone) {
2017-04-03 11:38:54 +08:00
if(!pcard || (pcard->data.type & TYPE_LINK) || pcard->is_affected_by_effect(EFFECT_CANNOT_CHANGE_POS_E))
2015-09-25 21:07:16 +08:00
continue;
eset.clear();
pcard->filter_effect(EFFECT_SET_POSITION, &eset);
if(eset.size()) {
pos = eset.get_last()->get_value();
if((pos & 0xff) != pcard->current.position) {
pos_adjust.insert(pcard);
2016-09-29 15:20:17 +08:00
pcard->position_param = pos;
2015-09-25 21:07:16 +08:00
if(pcard->is_status(STATUS_JUST_POS))
pcard->set_status(STATUS_CONTINUOUS_POS, TRUE);
else
pcard->set_status(STATUS_CONTINUOUS_POS, FALSE);
} else
pcard->set_status(STATUS_CONTINUOUS_POS, FALSE);
pcard->set_status(STATUS_JUST_POS, FALSE);
}
}
tp = 1 - tp;
}
if(pos_adjust.size()) {
core.re_adjust = TRUE;
group* ng = pduel->new_group();
ng->container.swap(pos_adjust);
ng->is_readonly = TRUE;
add_process(PROCESSOR_CHANGEPOS, 0, 0, ng, PLAYER_NONE, TRUE);
}
return FALSE;
}
case 12: {
//shuffle check
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[0].list_hand) {
2015-12-04 08:30:30 +09:00
effect* pub = pcard->is_affected_by_effect(EFFECT_PUBLIC);
if(!pub && pcard->is_position(POS_FACEUP))
2015-09-25 21:07:16 +08:00
core.shuffle_hand_check[0] = TRUE;
pcard->current.position = pub ? POS_FACEUP : POS_FACEDOWN;
2015-09-25 21:07:16 +08:00
}
2018-09-03 16:36:45 +08:00
for(auto& pcard : player[1].list_hand) {
2015-12-04 08:30:30 +09:00
effect* pub = pcard->is_affected_by_effect(EFFECT_PUBLIC);
if(!pub && pcard->is_position(POS_FACEUP))
2015-09-25 21:07:16 +08:00
core.shuffle_hand_check[1] = TRUE;
pcard->current.position = pub ? POS_FACEUP : POS_FACEDOWN;
2015-09-25 21:07:16 +08:00
}
if(core.shuffle_hand_check[infos.turn_player])
shuffle(infos.turn_player, LOCATION_HAND);
if(core.shuffle_hand_check[1 - infos.turn_player])
shuffle(1 - infos.turn_player, LOCATION_HAND);
return FALSE;
}
case 13: {
//reverse_deck
effect_set eset;
uint32 res = 0;
if(core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) {
filter_field_effect(EFFECT_REVERSE_DECK, &eset, FALSE);
res = eset.size() ? TRUE : FALSE;
if(core.deck_reversed ^ res) {
reverse_deck(0);
reverse_deck(1);
pduel->write_buffer8(MSG_REVERSE_DECK);
if(res) {
if(player[0].list_main.size()) {
card* ptop = player[0].list_main.back();
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(0);
pduel->write_buffer8(0);
2016-05-31 12:47:55 +08:00
if(ptop->current.position != POS_FACEUP_DEFENSE)
2015-09-25 21:07:16 +08:00
pduel->write_buffer32(ptop->data.code);
else
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
if(player[1].list_main.size()) {
card* ptop = player[1].list_main.back();
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(1);
pduel->write_buffer8(0);
2016-05-31 12:47:55 +08:00
if(ptop->current.position != POS_FACEUP_DEFENSE)
2015-09-25 21:07:16 +08:00
pduel->write_buffer32(ptop->data.code);
else
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
}
}
core.deck_reversed = res;
}
return FALSE;
}
case 14: {
//attack cancel
card* attacker = core.attacker;
if(!attacker)
return FALSE;
if(!attacker->is_affected_by_effect(EFFECT_UNSTOPPABLE_ATTACK)){
if(attacker->is_status(STATUS_ATTACK_CANCELED))
return FALSE;
if(!core.attacker->is_capable_attack()
|| core.attacker->current.controler != core.attacker->attack_controler
|| core.attacker->fieldid_r != core.pre_field[0]) {
attacker->set_status(STATUS_ATTACK_CANCELED, TRUE);
return FALSE;
}
}
2015-09-25 21:07:16 +08:00
if(core.attack_rollback)
return FALSE;
2017-10-15 23:15:42 +08:00
std::set<uint16> fidset;
2018-08-21 19:04:34 +08:00
for(auto& pcard : player[1 - infos.turn_player].list_mzone) {
2017-10-15 23:15:42 +08:00
if(pcard)
fidset.insert(pcard->fieldid_r);
2015-09-25 21:07:16 +08:00
}
if(fidset != core.opp_mzone || !confirm_attack_target())
2017-10-15 23:15:42 +08:00
core.attack_rollback = TRUE;
2015-09-25 21:07:16 +08:00
return FALSE;
}
case 15: {
raise_event((card*)0, EVENT_ADJUST, 0, 0, PLAYER_NONE, PLAYER_NONE, 0);
process_instant_event();
return FALSE;
}
case 16: {
if(core.re_adjust) {
core.units.begin()->step = -1;
return FALSE;
}
if(core.shuffle_hand_check[0])
shuffle(0, LOCATION_HAND);
if(core.shuffle_hand_check[1])
shuffle(1, LOCATION_HAND);
if(core.shuffle_deck_check[0])
shuffle(0, LOCATION_DECK);
if(core.shuffle_deck_check[1])
shuffle(1, LOCATION_DECK);
return TRUE;
}
}
return TRUE;
}