Commit 64fc24ab authored by Momobako's avatar Momobako

update_core

parent b948b420
......@@ -60,6 +60,9 @@ void card::attacker_map::addcard(card* pcard) {
auto pr = emplace(fid, std::make_pair(pcard, 0));
pr.first->second.second++;
}
void card_data::clear() {
std::memset(this, 0, sizeof(card_data));
}
card::card(duel* pd) {
scrtype = 1;
ref_handle = 0;
......@@ -3158,7 +3161,7 @@ int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect
return TRUE;
}
int32 card::is_setable_szone(uint8 playerid, uint8 ignore_fd) {
if(!(data.type & TYPE_FIELD) && !ignore_fd && pduel->game_field->get_useable_count(current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_TOFIELD) <= 0)
if(!(data.type & TYPE_FIELD) && !ignore_fd && pduel->game_field->get_useable_count(this, current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_TOFIELD) <= 0)
return FALSE;
if(data.type & TYPE_MONSTER && !is_affected_by_effect(EFFECT_MONSTER_SSET))
return FALSE;
......@@ -3530,9 +3533,9 @@ int32 card::is_control_can_be_changed(int32 ignore_mzone, uint32 zone) {
return FALSE;
if(current.location != LOCATION_MZONE)
return FALSE;
if(!ignore_mzone && pduel->game_field->get_useable_count(1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL, zone) <= 0)
if(!ignore_mzone && pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL, zone) <= 0)
return FALSE;
if((get_type() & TYPE_TRAPMONSTER) && pduel->game_field->get_useable_count(1 - current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_CONTROL) <= 0)
if((get_type() & TYPE_TRAPMONSTER) && pduel->game_field->get_useable_count(this, 1 - current.controler, LOCATION_SZONE, current.controler, LOCATION_REASON_CONTROL) <= 0)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_CONTROL))
return FALSE;
......
......@@ -34,6 +34,8 @@ struct card_data {
uint32 lscale;
uint32 rscale;
uint32 link_marker;
void clear();
};
struct card_state {
......
......@@ -49,6 +49,8 @@ card* duel::new_card(uint32 code) {
cards.insert(pcard);
if(code)
::read_card(code, &(pcard->data));
else
pcard->data.clear();
pcard->data.code = code;
lua->register_card(pcard);
return pcard;
......
......@@ -201,7 +201,7 @@ int32 effect::is_activateable(uint8 playerid, const tevent& e, int32 neglect_con
&& !pduel->game_field->is_location_useable(playerid, LOCATION_PZONE, 1))
return FALSE;
} else if(!(handler->data.type & TYPE_FIELD)
&& pduel->game_field->get_useable_count(playerid, LOCATION_SZONE, playerid, LOCATION_REASON_TOFIELD) <= 0)
&& pduel->game_field->get_useable_count(handler, playerid, LOCATION_SZONE, playerid, LOCATION_REASON_TOFIELD) <= 0)
return FALSE;
} else if(handler->current.location == LOCATION_SZONE) {
if(handler->is_position(POS_FACEUP))
......
......@@ -565,19 +565,51 @@ int32 field::is_location_useable(uint32 playerid, uint32 location, uint32 sequen
// list: store local flag in list
// return: usable count of LOCATION_MZONE or real LOCATION_SZONE of playerid requested by uplayer (may be negative)
int32 field::get_useable_count(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone, uint32* list) {
if(core.duel_rule >= 4 && location == LOCATION_MZONE && pcard->current.location == LOCATION_EXTRA)
if(location == LOCATION_MZONE && pcard->current.location == LOCATION_EXTRA)
return get_useable_count_fromex(pcard, playerid, uplayer, zone, list);
else
return get_useable_count(playerid, location, uplayer, reason, zone, list);
return get_useable_count_other(pcard, playerid, location, uplayer, reason, zone, list);
}
int32 field::get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
bool use_temp_card = false;
if(!pcard) {
use_temp_card = true;
pcard = temp_card;
pcard->current.location = LOCATION_EXTRA;
}
int useable_count = 0;
if(core.duel_rule >= 4)
useable_count = get_useable_count_fromex_rule4(pcard, playerid, uplayer, zone, list);
else
useable_count = get_useable_count_other(pcard, playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone, list);
if(use_temp_card)
pcard->current.location = 0;
return useable_count;
}
int32 field::get_spsummonable_count(card* pcard, uint8 playerid, uint32 zone, uint32* list) {
if(core.duel_rule >= 4 && pcard->current.location == LOCATION_EXTRA)
if(pcard->current.location == LOCATION_EXTRA)
return get_spsummonable_count_fromex(pcard, playerid, playerid, zone, list);
else
return get_tofield_count(playerid, LOCATION_MZONE, playerid, LOCATION_REASON_TOFIELD, zone, list);
return get_tofield_count(pcard, playerid, LOCATION_MZONE, playerid, LOCATION_REASON_TOFIELD, zone, list);
}
int32 field::get_useable_count(uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone, uint32* list) {
int32 count = get_tofield_count(playerid, location, uplayer, reason, zone, list);
int32 field::get_spsummonable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
bool use_temp_card = false;
if(!pcard) {
use_temp_card = true;
pcard = temp_card;
pcard->current.location = LOCATION_EXTRA;
}
int spsummonable_count = 0;
if(core.duel_rule >= 4)
spsummonable_count = get_spsummonable_count_fromex_rule4(pcard, playerid, uplayer, zone, list);
else
spsummonable_count = get_tofield_count(pcard, playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone, list);
if(use_temp_card)
pcard->current.location = 0;
return spsummonable_count;
}
int32 field::get_useable_count_other(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone, uint32* list) {
int32 count = get_tofield_count(pcard, playerid, location, uplayer, reason, zone, list);
int32 limit;
if(location == LOCATION_MZONE)
limit = get_mzone_limit(playerid, uplayer, reason);
......@@ -587,16 +619,28 @@ int32 field::get_useable_count(uint8 playerid, uint8 location, uint8 uplayer, ui
count = limit;
return count;
}
int32 field::get_tofield_count(uint8 playerid, uint8 location, uint32 uplayer, uint32 reason, uint32 zone, uint32* list) {
int32 field::get_tofield_count(card* pcard, uint8 playerid, uint8 location, uint32 uplayer, uint32 reason, uint32 zone, uint32* list) {
if (location != LOCATION_MZONE && location != LOCATION_SZONE)
return 0;
uint32 flag = player[playerid].disabled_location | player[playerid].used_location;
effect_set eset;
if(location == LOCATION_MZONE && (reason & LOCATION_REASON_TOFIELD)) {
effect_set eset;
if(uplayer < 2)
filter_player_effect(uplayer, EFFECT_MUST_USE_MZONE, &eset);
if(pcard)
pcard->filter_effect(EFFECT_MUST_USE_MZONE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 value = eset[i]->get_value();
if(eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT) && eset[i]->count_limit == 0)
continue;
uint32 value = 0x1f;
if(eset[i]->is_flag(EFFECT_FLAG_PLAYER_TARGET))
value = eset[i]->get_value();
else {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason, PARAM_TYPE_INT);
value = eset[i]->get_value(pcard, 3);
}
if(eset[i]->get_handler_player() == playerid)
flag |= ~value & 0x1f;
else
......@@ -614,20 +658,32 @@ int32 field::get_tofield_count(uint8 playerid, uint8 location, uint32 uplayer, u
*list = flag;
return count;
}
int32 field::get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
int32 count = get_spsummonable_count_fromex(pcard, playerid, uplayer, zone, list);
int32 field::get_useable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
int32 count = get_spsummonable_count_fromex_rule4(pcard, playerid, uplayer, zone, list);
int32 limit = get_mzone_limit(playerid, uplayer, LOCATION_REASON_TOFIELD);
if(count > limit)
count = limit;
return count;
}
int32 field::get_spsummonable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
int32 field::get_spsummonable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
uint32 flag = player[playerid].disabled_location | player[playerid].used_location;
effect_set eset;
if(uplayer < 2)
filter_player_effect(uplayer, EFFECT_MUST_USE_MZONE, &eset);
if(pcard)
pcard->filter_effect(EFFECT_MUST_USE_MZONE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 value = eset[i]->get_value();
if(eset[i]->is_flag(EFFECT_FLAG_COUNT_LIMIT) && eset[i]->count_limit == 0)
continue;
uint32 value = 0x1f;
if(eset[i]->is_flag(EFFECT_FLAG_PLAYER_TARGET))
value = eset[i]->get_value();
else {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(LOCATION_REASON_TOFIELD, PARAM_TYPE_INT);
value = eset[i]->get_value(pcard, 3);
}
if(eset[i]->get_handler_player() == playerid)
flag |= ~value & 0x1f;
else
......@@ -2753,7 +2809,7 @@ int32 field::check_tribute(card* pcard, int32 min, int32 max, group* mg, uint8 t
return FALSE;
zone &= 0x1f;
int32 s = 0;
int32 ct = get_tofield_count(toplayer, LOCATION_MZONE, sumplayer, LOCATION_REASON_TOFIELD, zone);
int32 ct = get_tofield_count(pcard, toplayer, LOCATION_MZONE, sumplayer, LOCATION_REASON_TOFIELD, zone);
if(ct <= 0 && max <= 0)
return FALSE;
for(auto it = release_list.begin(); it != release_list.end(); ++it) {
......@@ -3109,7 +3165,9 @@ int32 field::is_player_can_flipsummon(uint8 playerid, card * pcard) {
}
int32 field::is_player_can_spsummon_monster(uint8 playerid, uint8 toplayer, uint8 sumpos, uint32 sumtype, card_data* pdata) {
temp_card->data = *pdata;
return is_player_can_spsummon(core.reason_effect, sumtype, sumpos, playerid, toplayer, temp_card);
int32 result = is_player_can_spsummon(core.reason_effect, sumtype, sumpos, playerid, toplayer, temp_card);
temp_card->data.clear();
return result;
}
int32 field::is_player_can_release(uint8 playerid, card * pcard) {
effect_set eset;
......
......@@ -355,11 +355,13 @@ public:
card* get_field_card(uint32 playerid, uint32 location, uint32 sequence);
int32 is_location_useable(uint32 playerid, uint32 location, uint32 sequence);
int32 get_useable_count(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone = 0xff, uint32* list = 0);
int32 get_spsummonable_count(card* pcard, uint8 playerid, uint32 zone = 0xff, uint32* list = 0);
int32 get_useable_count(uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone = 0xff, uint32* list = 0);
int32 get_tofield_count(uint8 playerid, uint8 location, uint32 uplayer, uint32 reason, uint32 zone = 0xff, uint32* list = 0);
int32 get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone = 0xff, uint32* list = 0);
int32 get_spsummonable_count(card* pcard, uint8 playerid, uint32 zone = 0xff, uint32* list = 0);
int32 get_spsummonable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone = 0xff, uint32* list = 0);
int32 get_useable_count_other(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone = 0xff, uint32* list = 0);
int32 get_tofield_count(card* pcard, uint8 playerid, uint8 location, uint32 uplayer, uint32 reason, uint32 zone = 0xff, uint32* list = 0);
int32 get_useable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone = 0xff, uint32* list = 0);
int32 get_spsummonable_count_fromex_rule4(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone = 0xff, uint32* list = 0);
int32 get_mzone_limit(uint8 playerid, uint8 uplayer, uint32 reason);
int32 get_szone_limit(uint8 playerid, uint8 uplayer, uint32 reason);
uint32 get_linked_zone(int32 playerid);
......@@ -533,6 +535,7 @@ public:
void change_position(card_set* targets, effect* reason_effect, uint32 reason_player, uint32 au, uint32 ad, uint32 du, uint32 dd, uint32 flag, uint32 enable = FALSE);
void change_position(card* target, effect* reason_effect, uint32 reason_player, uint32 npos, uint32 flag, uint32 enable = FALSE);
void operation_replace(int32 type, int32 step, group* targets);
void select_tribute_cards(card* target, uint8 playerid, uint8 cancelable, int32 min, int32 max, uint8 toplayer, uint32 zone);
int32 remove_counter(uint16 step, uint32 reason, card* pcard, uint8 rplayer, uint8 s, uint8 o, uint16 countertype, uint16 count);
int32 remove_overlay_card(uint16 step, uint32 reason, card* pcard, uint8 rplayer, uint8 s, uint8 o, uint16 min, uint16 max);
......@@ -566,7 +569,7 @@ public:
int32 select_synchro_material(int16 step, uint8 playerid, card* pcard, int32 min, int32 max, card* smat, group* mg);
int32 select_xyz_material(int16 step, uint8 playerid, uint32 lv, card* pcard, int32 min, int32 max);
int32 select_release_cards(int16 step, uint8 playerid, uint8 cancelable, int32 min, int32 max);
int32 select_tribute_cards(int16 step, uint8 playerid, uint8 cancelable, int32 min, int32 max, uint8 toplayer, uint32 zone);
int32 select_tribute_cards(int16 step, card* target, uint8 playerid, uint8 cancelable, int32 min, int32 max, uint8 toplayer, uint32 zone);
int32 toss_coin(uint16 step, effect* reason_effect, uint8 reason_player, uint8 playerid, uint8 count);
int32 toss_dice(uint16 step, effect* reason_effect, uint8 reason_player, uint8 playerid, uint8 count1, uint8 count2);
int32 rock_paper_scissors(uint16 step, uint8 repeat);
......
......@@ -1648,7 +1648,7 @@ int32 scriptlib::duel_get_location_count(lua_State *L) {
uint32 zone = 0xff;
if(lua_gettop(L) >= 5)
zone = lua_tonumberint(L, 5);
lua_pushinteger(L, pduel->game_field->get_useable_count(playerid, location, uplayer, reason, zone));
lua_pushinteger(L, pduel->game_field->get_useable_count(NULL, playerid, location, uplayer, reason, zone));
return 1;
}
int32 scriptlib::duel_get_mzone_count(lua_State *L) {
......@@ -1695,7 +1695,7 @@ int32 scriptlib::duel_get_mzone_count(lua_State *L) {
reason = lua_tonumberint(L, 4);
if(lua_gettop(L) >= 5)
zone = lua_tonumberint(L, 5);
lua_pushinteger(L, pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, uplayer, reason, zone));
lua_pushinteger(L, pduel->game_field->get_useable_count(NULL, playerid, LOCATION_MZONE, uplayer, reason, zone));
if(swapped) {
pduel->game_field->player[0].used_location = used_location[0];
pduel->game_field->player[1].used_location = used_location[1];
......@@ -1750,10 +1750,7 @@ int32 scriptlib::duel_get_location_count_fromex(lua_State *L) {
uint32 zone = 0xff;
if(lua_gettop(L) >= 5)
zone = lua_tonumberint(L, 5);
if(pduel->game_field->core.duel_rule >= 4)
lua_pushinteger(L, pduel->game_field->get_useable_count_fromex(scard, playerid, uplayer, zone));
else
lua_pushinteger(L, pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone));
lua_pushinteger(L, pduel->game_field->get_useable_count_fromex(scard, playerid, uplayer, zone));
if(swapped) {
pduel->game_field->player[0].used_location = used_location[0];
pduel->game_field->player[1].used_location = used_location[1];
......@@ -1772,18 +1769,15 @@ int32 scriptlib::duel_get_usable_mzone_count(lua_State *L) {
if(lua_gettop(L) >= 2)
uplayer = lua_tonumberint(L, 2);
uint32 zone = 0xff;
if(pduel->game_field->core.duel_rule >= 4) {
uint32 flag1, flag2;
int32 ct1 = pduel->game_field->get_tofield_count(playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone, &flag1);
int32 ct2 = pduel->game_field->get_spsummonable_count_fromex(0, playerid, uplayer, zone, &flag2);
int32 ct3 = field::field_used_count[~(flag1 | flag2) & 0x1f];
int32 count = ct1 + ct2 - ct3;
int32 limit = pduel->game_field->get_mzone_limit(playerid, uplayer, LOCATION_REASON_TOFIELD);
if(count > limit)
count = limit;
lua_pushinteger(L, count);
} else
lua_pushinteger(L, pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone));
uint32 flag1, flag2;
int32 ct1 = pduel->game_field->get_tofield_count(NULL, playerid, LOCATION_MZONE, uplayer, LOCATION_REASON_TOFIELD, zone, &flag1);
int32 ct2 = pduel->game_field->get_spsummonable_count_fromex(NULL, playerid, uplayer, zone, &flag2);
int32 ct3 = field::field_used_count[~(flag1 | flag2) & 0x1f];
int32 count = ct1 + ct2 - ct3;
int32 limit = pduel->game_field->get_mzone_limit(playerid, uplayer, LOCATION_REASON_TOFIELD);
if(count > limit)
count = limit;
lua_pushinteger(L, count);
return 1;
}
int32 scriptlib::duel_get_linked_group(lua_State *L) {
......@@ -2466,7 +2460,8 @@ int32 scriptlib::duel_select_tribute(lua_State *L) {
pduel->game_field->core.release_cards_ex.clear();
pduel->game_field->core.release_cards_ex_oneof.clear();
pduel->game_field->get_summon_release_list(target, &pduel->game_field->core.release_cards, &pduel->game_field->core.release_cards_ex, &pduel->game_field->core.release_cards_ex_oneof, mg, ex);
pduel->game_field->add_process(PROCESSOR_SELECT_TRIBUTE_S, 0, 0, 0, playerid, (max << 16) + min, toplayer, zone);
pduel->game_field->select_tribute_cards(0, playerid, 0, min, max, toplayer, zone);
pduel->game_field->core.subunits.back().type = PROCESSOR_SELECT_TRIBUTE_S;
return lua_yield(L, 0);
}
/**
......@@ -3136,19 +3131,19 @@ int32 scriptlib::duel_select_disable_field(lua_State * L) {
duel* pduel = interpreter::get_duel_info(L);
uint32 ct1 = 0, ct2 = 0, ct3 = 0, ct4 = 0, plist = 0, flag = 0xffffffff;
if(location1 & LOCATION_MZONE) {
ct1 = pduel->game_field->get_useable_count(playerid, LOCATION_MZONE, PLAYER_NONE, 0, 0xff, &plist);
ct1 = pduel->game_field->get_useable_count(NULL, playerid, LOCATION_MZONE, PLAYER_NONE, 0, 0xff, &plist);
flag = (flag & 0xffffff00) | plist;
}
if(location1 & LOCATION_SZONE) {
ct2 = pduel->game_field->get_useable_count(playerid, LOCATION_SZONE, PLAYER_NONE, 0, 0xff, &plist);
ct2 = pduel->game_field->get_useable_count(NULL, playerid, LOCATION_SZONE, PLAYER_NONE, 0, 0xff, &plist);
flag = (flag & 0xffff00ff) | (plist << 8);
}
if(location2 & LOCATION_MZONE) {
ct3 = pduel->game_field->get_useable_count(1 - playerid, LOCATION_MZONE, PLAYER_NONE, 0, 0xff, &plist);
ct3 = pduel->game_field->get_useable_count(NULL, 1 - playerid, LOCATION_MZONE, PLAYER_NONE, 0, 0xff, &plist);
flag = (flag & 0xff00ffff) | (plist << 16);
}
if(location2 & LOCATION_SZONE) {
ct4 = pduel->game_field->get_useable_count(1 - playerid, LOCATION_SZONE, PLAYER_NONE, 0, 0xff, &plist);
ct4 = pduel->game_field->get_useable_count(NULL, 1 - playerid, LOCATION_SZONE, PLAYER_NONE, 0, 0xff, &plist);
flag = (flag & 0xffffff) | (plist << 24);
}
flag |= filter | 0xe0e0e0e0;
......
This diff is collapsed.
......@@ -195,7 +195,7 @@ int32 field::process() {
return pduel->bufferlen;
}
case PROCESSOR_SELECT_TRIBUTE: {
if (select_tribute_cards(it->step, it->arg1 & 0xff, (it->arg1 >> 16) & 0xff, (it->arg2) & 0xff, (it->arg2 >> 16) & 0xff, it->arg3, it->arg4))
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))
core.units.pop_front();
else
it->step++;
......
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