Commit dfac0fbd authored by mercury233's avatar mercury233
parents e235487a d850977a
......@@ -2124,7 +2124,7 @@ int32 card::destination_redirect(uint8 destination, uint32 reason) {
// cmit->second[0]: permanent
// cmit->second[1]: reset while negated
int32 card::add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly) {
if(!is_can_add_counter(playerid, countertype, count, singly))
if(!is_can_add_counter(playerid, countertype, count, singly, 0))
return FALSE;
uint16 cttype = countertype & ~COUNTER_NEED_ENABLE;
auto pr = counters.insert(std::make_pair(cttype, counter_map::mapped_type()));
......@@ -2182,15 +2182,27 @@ int32 card::remove_counter(uint16 countertype, uint16 count) {
pduel->write_buffer16(count);
return TRUE;
}
int32 card::is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly) {
int32 card::is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly, uint32 loc) {
effect_set eset;
if(!pduel->game_field->is_player_can_place_counter(playerid, this, countertype, count))
return FALSE;
if(!(current.location & LOCATION_ONFIELD) || !is_position(POS_FACEUP))
return FALSE;
if((countertype & COUNTER_NEED_ENABLE) && is_status(STATUS_DISABLED))
return FALSE;
if(!(countertype & COUNTER_WITHOUT_PERMIT) && !is_affected_by_effect(EFFECT_COUNTER_PERMIT + (countertype & 0xffff)))
uint32 check = countertype & COUNTER_WITHOUT_PERMIT;
if(!check) {
filter_effect(EFFECT_COUNTER_PERMIT + (countertype & 0xffff), &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 prange = eset[i]->get_value();
if(loc)
check = loc & prange;
else
check = current.is_location(prange) && is_position(POS_FACEUP);
if(check)
break;
}
eset.clear();
}
if(!check)
return FALSE;
uint16 cttype = countertype & ~COUNTER_NEED_ENABLE;
int32 limit = -1;
......
......@@ -265,7 +265,7 @@ public:
int32 destination_redirect(uint8 destination, uint32 reason);
int32 add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly);
int32 remove_counter(uint16 countertype, uint16 count);
int32 is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly);
int32 is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count, uint8 singly, uint32 loc);
int32 get_counter(uint16 countertype);
void set_material(card_set* materials);
void add_card_target(card* pcard);
......
......@@ -259,6 +259,7 @@ struct processor {
group* limit_xyz;
int32 limit_xyz_minc;
int32 limit_xyz_maxc;
uint8 attack_cancelable;
uint8 attack_rollback;
uint8 effect_damage_step;
int32 battle_damage[2];
......
......@@ -208,6 +208,8 @@ static const struct luaL_Reg cardlib[] = {
{ "IsLevelAbove", scriptlib::card_is_level_above },
{ "IsRankBelow", scriptlib::card_is_rank_below },
{ "IsRankAbove", scriptlib::card_is_rank_above },
{ "IsLinkBelow", scriptlib::card_is_link_below },
{ "IsLinkAbove", scriptlib::card_is_link_above },
{ "IsAttackBelow", scriptlib::card_is_attack_below },
{ "IsAttackAbove", scriptlib::card_is_attack_above },
{ "IsDefenseBelow", scriptlib::card_is_defense_below },
......
......@@ -843,7 +843,7 @@ int32 scriptlib::card_is_not_tuner(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 type = pcard->get_type();
uint32 type = pcard->get_synchro_type();
if(!(type & TYPE_TUNER) || pcard->is_affected_by_effect(EFFECT_NONTUNER))
lua_pushboolean(L, 1);
else
......@@ -2016,6 +2016,30 @@ int32 scriptlib::card_is_rank_above(lua_State *L) {
lua_pushboolean(L, pcard->get_rank() >= rnk);
return 1;
}
int32 scriptlib::card_is_link_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 lnk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_LINK) || (pcard->status & STATUS_NO_LEVEL)
|| (!(pcard->data.type & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE)))
lua_pushboolean(L, 0);
else
lua_pushboolean(L, pcard->get_link() <= lnk);
return 1;
}
int32 scriptlib::card_is_link_above(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 lnk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_LINK) || (pcard->status & STATUS_NO_LEVEL)
|| (!(pcard->data.type & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE)))
lua_pushboolean(L, 0);
else
lua_pushboolean(L, pcard->get_link() >= lnk);
return 1;
}
int32 scriptlib::card_is_attack_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
......@@ -2177,8 +2201,7 @@ int32 scriptlib::card_enable_counter_permit(lua_State *L) {
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_COUNTER_PERMIT | countertype;
peffect->flag[0] = EFFECT_FLAG_SINGLE_RANGE;
peffect->range = prange;
peffect->value = prange;
pcard->add_effect(peffect);
return 0;
}
......@@ -2218,7 +2241,10 @@ int32 scriptlib::card_is_can_add_counter(lua_State *L) {
uint8 singly = FALSE;
if(lua_gettop(L) > 3)
singly = lua_toboolean(L, 4);
lua_pushboolean(L, pcard->is_can_add_counter(pcard->pduel->game_field->core.reason_player, countertype, count, singly));
uint32 loc = 0;
if(lua_gettop(L) > 4)
loc = lua_tointeger(L, 5);
lua_pushboolean(L, pcard->is_can_add_counter(pcard->pduel->game_field->core.reason_player, countertype, count, singly, loc));
return 1;
}
int32 scriptlib::card_is_can_remove_counter(lua_State *L) {
......
......@@ -935,21 +935,58 @@ int32 scriptlib::duel_is_environment(lua_State *L) {
uint32 playerid = PLAYER_ALL;
if(lua_gettop(L) >= 2)
playerid = lua_tointeger(L, 2);
uint32 loc = LOCATION_FZONE + LOCATION_ONFIELD;
if(lua_gettop(L) >= 3)
loc = lua_tointeger(L, 3);
if(playerid != 0 && playerid != 1 && playerid != PLAYER_ALL)
return 0;
duel* pduel = interpreter::get_duel_info(L);
int32 ret = 0, fc = 0;
card* pcard = pduel->game_field->player[0].list_szone[5];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED)) {
fc = 1;
if(code == pcard->get_code() && (playerid == 0 || playerid == PLAYER_ALL))
ret = 1;
if(loc & LOCATION_FZONE) {
card* pcard = pduel->game_field->player[0].list_szone[5];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED)) {
fc = 1;
if(code == pcard->get_code() && (playerid == 0 || playerid == PLAYER_ALL))
ret = 1;
}
pcard = pduel->game_field->player[1].list_szone[5];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED)) {
fc = 1;
if(code == pcard->get_code() && (playerid == 1 || playerid == PLAYER_ALL))
ret = 1;
}
}
pcard = pduel->game_field->player[1].list_szone[5];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED)) {
fc = 1;
if(code == pcard->get_code() && (playerid == 1 || playerid == PLAYER_ALL))
ret = 1;
if(!ret && (loc & LOCATION_SZONE)) {
if(playerid == 0 || playerid == PLAYER_ALL) {
for(auto cit = pduel->game_field->player[0].list_szone.begin(); cit != pduel->game_field->player[0].list_szone.end(); ++cit) {
card* pcard = *cit;
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED) && code == pcard->get_code())
ret = 1;
}
}
if(playerid == 1 || playerid == PLAYER_ALL) {
for(auto cit = pduel->game_field->player[1].list_szone.begin(); cit != pduel->game_field->player[1].list_szone.end(); ++cit) {
card* pcard = *cit;
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED) && code == pcard->get_code())
ret = 1;
}
}
}
if(!ret && (loc & LOCATION_MZONE)) {
if(playerid == 0 || playerid == PLAYER_ALL) {
for(auto cit = pduel->game_field->player[0].list_mzone.begin(); cit != pduel->game_field->player[0].list_mzone.end(); ++cit) {
card* pcard = *cit;
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED) && code == pcard->get_code())
ret = 1;
}
}
if(playerid == 1 || playerid == PLAYER_ALL) {
for(auto cit = pduel->game_field->player[1].list_mzone.begin(); cit != pduel->game_field->player[1].list_mzone.end(); ++cit) {
card* pcard = *cit;
if(pcard && pcard->is_position(POS_FACEUP) && pcard->get_status(STATUS_EFFECT_ENABLED) && code == pcard->get_code())
ret = 1;
}
}
}
if(!fc) {
effect_set eset;
......@@ -1265,9 +1302,25 @@ int32 scriptlib::duel_shuffle_setcard(lua_State *L) {
int32 scriptlib::duel_change_attacker(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* target = *(card**) lua_touserdata(L, 1);
duel* pduel = target->pduel;
pduel->game_field->core.attacker = target;
card* attacker = *(card**) lua_touserdata(L, 1);
int32 ignore_count = FALSE;
if(lua_gettop(L) >= 2)
ignore_count = lua_toboolean(L, 2);
duel* pduel = attacker->pduel;
if(pduel->game_field->core.attacker == attacker)
return 0;
pduel->game_field->core.attacker = attacker;
attacker->attack_controler = attacker->current.controler;
pduel->game_field->core.pre_field[0] = attacker->fieldid_r;
if(!ignore_count) {
card* attack_target = pduel->game_field->core.attack_target;
attacker->announce_count++;
attacker->announced_cards.addcard(attack_target);
if(pduel->game_field->infos.phase == PHASE_DAMAGE) {
attacker->attacked_count++;
attacker->attacked_cards.addcard(attack_target);
}
}
return 0;
}
int32 scriptlib::duel_change_attack_target(lua_State *L) {
......
......@@ -2839,6 +2839,7 @@ int32 field::process_battle_command(uint16 step) {
core.to_m2 = FALSE;
if(must_attack.size())
core.to_ep = FALSE;
core.attack_cancelable = TRUE;
add_process(PROCESSOR_SELECT_BATTLECMD, 0, 0, 0, infos.turn_player, 0);
return FALSE;
}
......@@ -2872,25 +2873,20 @@ int32 field::process_battle_command(uint16 step) {
return FALSE;
} else if(ctype == 1) {
core.units.begin()->step = 2;
core.units.begin()->arg3 = FALSE;
card* attacker = core.attackable_cards[sel];
if(core.chain_attack && core.chain_attacker_id != attacker->fieldid) {
core.chain_attack = FALSE;
core.chain_attacker_id = 0;
}
core.attacker = attacker;
core.attacker->set_status(STATUS_ATTACK_CANCELED, FALSE);
core.pre_field[0] = core.attacker->fieldid_r;
core.phase_action = TRUE;
core.attack_state_count[infos.turn_player]++;
check_card_counter(core.attacker, 5, infos.turn_player);
core.attacker->announce_count++;
effect_set eset;
filter_player_effect(infos.turn_player, EFFECT_ATTACK_COST, &eset, FALSE);
core.attacker->filter_effect(EFFECT_ATTACK_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->operation) {
core.attack_cancelable = FALSE;
core.sub_solving_event.push_back(nil_event);
add_process(PROCESSOR_EXECUTE_OPERATION, 0, eset[i], 0, infos.turn_player, 0);
adjust_all();
}
}
return FALSE;
......@@ -2921,12 +2917,12 @@ int32 field::process_battle_command(uint16 step) {
return FALSE;
}
case 3: {
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->fieldid_r != core.pre_field[0]) {
core.chain_attack = FALSE;
core.units.begin()->step = -1;
core.units.begin()->arg1 = FALSE;
if(core.attacker->current.location != LOCATION_MZONE || core.attacker->current.controler != infos.turn_player || core.attacker->fieldid_r != core.pre_field[0]) {
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
return FALSE;
}
core.units.begin()->arg1 = FALSE;
return FALSE;
}
case 4: {
......@@ -2951,10 +2947,10 @@ int32 field::process_battle_command(uint16 step) {
core.units.begin()->step = 5;
return FALSE;
}
// no target
// no target and not direct attackable
if(core.select_cards.size() == 0) {
core.chain_attack = FALSE;
core.units.begin()->step = -1;
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
return FALSE;
}
// must attack monster
......@@ -2976,7 +2972,7 @@ int32 field::process_battle_command(uint16 step) {
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(infos.turn_player);
pduel->write_buffer32(549);
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player + (core.units.begin()->arg1 ? 0x20000 : 0), 0x10001);
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player + (core.attack_cancelable ? 0x20000 : 0), 0x10001);
}
core.units.begin()->step = 5;
return FALSE;
......@@ -2991,20 +2987,22 @@ int32 field::process_battle_command(uint16 step) {
pduel->write_buffer8(HINT_SELECTMSG);
pduel->write_buffer8(infos.turn_player);
pduel->write_buffer32(549);
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player, 0x10001);
add_process(PROCESSOR_SELECT_CARD, 0, 0, 0, infos.turn_player + (core.attack_cancelable ? 0x20000 : 0), 0x10001);
} else {
core.chain_attack = FALSE;
core.units.begin()->step = -1;
core.units.begin()->arg3 = TRUE;
core.units.begin()->step = 6;
}
}
return FALSE;
}
case 6: {
if(returns.ivalue[0] == -1) {
core.chain_attack = FALSE;
if(returns.ivalue[0] == -1) {//cancel attack manually
if(core.units.begin()->arg1)
core.chain_attack = FALSE;
core.units.begin()->step = -1;
return FALSE;
} else if(returns.ivalue[0] == -2)
}
if(returns.ivalue[0] == -2)
core.attack_target = 0;
else
core.attack_target = core.select_cards[returns.bvalue[1]];
......@@ -3012,11 +3010,28 @@ int32 field::process_battle_command(uint16 step) {
core.pre_field[1] = core.attack_target->fieldid_r;
else
core.pre_field[1] = 0;
if(!core.units.begin()->arg1)
core.attacker->announced_cards.addcard(core.attack_target);
return FALSE;
}
case 7: {
if(!core.units.begin()->arg1) {
core.phase_action = TRUE;
if(core.chain_attack && core.chain_attacker_id != core.attacker->fieldid) {
core.chain_attack = FALSE;
core.chain_attacker_id = 0;
}
core.attack_state_count[infos.turn_player]++;
check_card_counter(core.attacker, 5, infos.turn_player);
core.attacker->announce_count++;
if(!core.units.begin()->arg3)
core.attacker->announced_cards.addcard(core.attack_target);
}
if(core.units.begin()->arg3) {
core.chain_attack = FALSE;
core.units.begin()->step = -1;
}
return FALSE;
}
case 8: {
bool evt = false;
attack_all_target_check();
pduel->write_buffer8(MSG_ATTACK);
......@@ -3052,9 +3067,9 @@ int32 field::process_battle_command(uint16 step) {
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 8: {
case 9: {
if(is_player_affected_by_effect(infos.turn_player, EFFECT_SKIP_BP) || core.attack_rollback) {
core.units.begin()->step = 9;
core.units.begin()->step = 10;
return FALSE;
}
pduel->write_buffer8(MSG_HINT);
......@@ -3070,14 +3085,14 @@ int32 field::process_battle_command(uint16 step) {
add_process(PROCESSOR_POINT_EVENT, 0, 0, 0, 0, 0);
return FALSE;
}
case 9: {
case 10: {
if(returns.ivalue[0])
core.units.begin()->step = 7;
core.units.begin()->step = 8;
else
adjust_all();
return FALSE;
}
case 10: {
case 11: {
uint8 rollback = core.attack_rollback;
bool atk_disabled = false;
uint32 acon = core.attacker->attack_controler;
......@@ -3146,10 +3161,12 @@ int32 field::process_battle_command(uint16 step) {
}
return FALSE;
}
case 11: {
case 12: {
// answer of "replay or not"
if(returns.ivalue[0]) {
core.units.begin()->arg1 = TRUE;
core.units.begin()->arg3 = FALSE;
core.attack_cancelable = TRUE;
core.units.begin()->step = 3;
return FALSE;
}
......
......@@ -210,6 +210,8 @@ public:
static int32 card_is_level_above(lua_State *L);
static int32 card_is_rank_below(lua_State *L);
static int32 card_is_rank_above(lua_State *L);
static int32 card_is_link_below(lua_State *L);
static int32 card_is_link_above(lua_State *L);
static int32 card_is_attack_below(lua_State *L);
static int32 card_is_attack_above(lua_State *L);
static int32 card_is_defense_below(lua_State *L);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment