Commit 68c7985f authored by fluorohydride's avatar fluorohydride

submodule

parent cf93f6c3
[submodule "ocgcore"]
path = ocgcore
url = git@github.com:Fluorohydride/ygopro-core.git
Subproject commit e8420f07388d2f47adab11ba8d3fd5d3462837dd
/*
* card.cpp
*
* Created on: 2010-5-7
* Author: Argon
*/
#include "card.h"
#include "field.h"
#include "effect.h"
#include "duel.h"
#include "group.h"
#include "interpreter.h"
#include "ocgapi.h"
#include <memory.h>
#include <iostream>
#include <algorithm>
bool card_sort::operator()(void* const & p1, void* const & p2) const {
card* c1 = (card*)p1;
card* c2 = (card*)p2;
return c1->cardid < c2->cardid;
}
bool card::card_operation_sort(card* c1, card* c2) {
duel* pduel = c1->pduel;
int32 cp1 = c1->overlay_target ? c1->overlay_target->current.controler : c1->current.controler;
int32 cp2 = c2->overlay_target ? c2->overlay_target->current.controler : c2->current.controler;
if(cp1 != cp2) {
if(cp1 == PLAYER_NONE || cp2 == PLAYER_NONE)
return cp1 < cp2;
if(pduel->game_field->infos.turn_player == 0)
return cp1 < cp2;
else
return cp1 > cp2;
}
if(c1->current.location != c2->current.location)
return c1->current.location < c2->current.location;
if(c1->current.location & LOCATION_OVERLAY) {
if(c1->overlay_target->current.sequence != c2->overlay_target->current.sequence)
return c1->overlay_target->current.sequence < c2->overlay_target->current.sequence;
else return c1->current.sequence < c2->current.sequence;
} else {
if(c1->current.location & 0x71)
return c1->current.sequence > c2->current.sequence;
else
return c1->current.sequence < c2->current.sequence;
}
}
card::card(duel* pd) {
scrtype = 1;
ref_handle = 0;
pduel = pd;
owner = PLAYER_NONE;
operation_param = 0;
status = 0;
memset(&q_cache, 0xff, sizeof(query_cache));
equiping_target = 0;
pre_equip_target = 0;
overlay_target = 0;
memset(&current, 0, sizeof(card_state));
memset(&previous, 0, sizeof(card_state));
memset(&temp, 0xff, sizeof(card_state));
unique_pos[0] = unique_pos[1] = 0;
spsummon_counter[0] = spsummon_counter[1] = 0;
spsummon_counter_rst[0] = spsummon_counter_rst[1] = 0;
unique_code = 0;
assume_type = 0;
assume_value = 0;
spsummon_code = 0;
current.controler = PLAYER_NONE;
}
card::~card() {
indexer.clear();
relations.clear();
counters.clear();
equiping_cards.clear();
material_cards.clear();
single_effect.clear();
field_effect.clear();
equip_effect.clear();
relate_effect.clear();
}
uint32 card::get_infos(byte* buf, int32 query_flag, int32 use_cache) {
int32* p = (int32*)buf;
int32 tdata = 0;
p += 2;
if(query_flag & QUERY_CODE) *p++ = data.code;
if(query_flag & QUERY_POSITION) *p++ = get_info_location();
if(!use_cache) {
if(query_flag & QUERY_ALIAS) q_cache.code = *p++ = get_code();
if(query_flag & QUERY_TYPE) q_cache.type = *p++ = get_type();
if(query_flag & QUERY_LEVEL) q_cache.level = *p++ = get_level();
if(query_flag & QUERY_RANK) q_cache.rank = *p++ = get_rank();
if(query_flag & QUERY_ATTRIBUTE) q_cache.attribute = *p++ = get_attribute();
if(query_flag & QUERY_RACE) q_cache.race = *p++ = get_race();
if(query_flag & QUERY_ATTACK) q_cache.attack = *p++ = get_attack();
if(query_flag & QUERY_DEFENCE) q_cache.defence = *p++ = get_defence();
if(query_flag & QUERY_BASE_ATTACK) q_cache.base_attack = *p++ = get_base_attack();
if(query_flag & QUERY_BASE_DEFENCE) q_cache.base_defence = *p++ = get_base_defence();
if(query_flag & QUERY_REASON) q_cache.reason = *p++ = current.reason;
} else {
if((query_flag & QUERY_ALIAS) && ((uint32)(tdata = get_code()) != q_cache.alias)) {
q_cache.alias = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_ALIAS;
if((query_flag & QUERY_TYPE) && ((uint32)(tdata = get_type()) != q_cache.type)) {
q_cache.type = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_TYPE;
if((query_flag & QUERY_LEVEL) && ((uint32)(tdata = get_level()) != q_cache.level)) {
q_cache.level = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_LEVEL;
if((query_flag & QUERY_RANK) && ((uint32)(tdata = get_rank()) != q_cache.rank)) {
q_cache.rank = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_RANK;
if((query_flag & QUERY_ATTRIBUTE) && ((uint32)(tdata = get_attribute()) != q_cache.attribute)) {
q_cache.attribute = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_ATTRIBUTE;
if((query_flag & QUERY_RACE) && ((uint32)(tdata = get_race()) != q_cache.race)) {
q_cache.race = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_RACE;
if((query_flag & QUERY_ATTACK) && ((tdata = get_attack()) != q_cache.attack)) {
q_cache.attack = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_ATTACK;
if((query_flag & QUERY_DEFENCE) && ((tdata = get_defence()) != q_cache.defence)) {
q_cache.defence = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_DEFENCE;
if((query_flag & QUERY_BASE_ATTACK) && ((tdata = get_base_attack()) != q_cache.base_attack)) {
q_cache.base_attack = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_BASE_ATTACK;
if((query_flag & QUERY_BASE_DEFENCE) && ((tdata = get_base_defence()) != q_cache.base_defence)) {
q_cache.base_defence = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_BASE_DEFENCE;
if((query_flag & QUERY_REASON) && ((uint32)(tdata = current.reason) != q_cache.reason)) {
q_cache.reason = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_REASON;
}
if(query_flag & QUERY_REASON_CARD)
*p++ = current.reason_card ? current.reason_card->get_info_location() : 0;
if(query_flag & QUERY_EQUIP_CARD) {
if(equiping_target)
*p++ = equiping_target->get_info_location();
else
query_flag &= ~QUERY_EQUIP_CARD;
}
if(query_flag & QUERY_TARGET_CARD) {
*p++ = effect_target_cards.size();
card_set::iterator cit;
for(cit = effect_target_cards.begin(); cit != effect_target_cards.end(); ++cit)
*p++ = (*cit)->get_info_location();
}
if(query_flag & QUERY_OVERLAY_CARD) {
*p++ = xyz_materials.size();
for(auto clit = xyz_materials.begin(); clit != xyz_materials.end(); ++clit)
*p++ = (*clit)->data.code;
}
if(query_flag & QUERY_COUNTERS) {
*p++ = counters.size();
counter_map::iterator cmit;
for(cmit = counters.begin(); cmit != counters.end(); ++cmit)
*p++ = cmit->first + (cmit->second << 16);
}
if(query_flag & QUERY_OWNER)
*p++ = owner;
if(query_flag & QUERY_IS_DISABLED) {
tdata = (status & STATUS_DISABLED) ? 1 : 0;
if(!use_cache || (tdata != q_cache.is_disabled)) {
q_cache.is_disabled = tdata;
*p++ = tdata;
} else
query_flag &= ~QUERY_IS_DISABLED;
}
if(query_flag & QUERY_IS_PUBLIC)
*p++ = (status & STATUS_IS_PUBLIC) ? 1 : 0;
if(!use_cache) {
if(query_flag & QUERY_LSCALE) q_cache.lscale = *p++ = get_lscale();
if(query_flag & QUERY_RSCALE) q_cache.rscale = *p++ = get_rscale();
} else {
if((query_flag & QUERY_LSCALE) && ((uint32)(tdata = get_lscale()) != q_cache.lscale)) {
q_cache.lscale = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_LSCALE;
if((query_flag & QUERY_RSCALE) && ((uint32)(tdata = get_rscale()) != q_cache.rscale)) {
q_cache.rscale = tdata;
*p++ = tdata;
} else query_flag &= ~QUERY_RSCALE;
}
*(uint32*)buf = (byte*)p - buf;
*(uint32*)(buf + 4) = query_flag;
return (byte*)p - buf;
}
uint32 card::get_info_location() {
if(overlay_target) {
uint32 c = overlay_target->current.controler;
uint32 l = overlay_target->current.location | LOCATION_OVERLAY;
uint32 s = overlay_target->current.sequence;
uint32 ss = current.sequence;
return c + (l << 8) + (s << 16) + (ss << 24);
} else {
uint32 c = current.controler;
uint32 l = current.location;
uint32 s = current.sequence;
uint32 ss = current.position;
return c + (l << 8) + (s << 16) + (ss << 24);
}
}
// get the current code
uint32 card::get_code() {
if(assume_type == ASSUME_CODE)
return assume_value;
if(!(current.location & 0x1c)) {
if(data.alias)
return data.alias;
return data.code;
}
if (temp.code != 0xffffffff)
return temp.code;
effect_set effects;
uint32 code = data.code;
temp.code = data.code;
filter_effect(EFFECT_CHANGE_CODE, &effects);
if (effects.size())
code = effects.get_last()->get_value(this);
temp.code = 0xffffffff;
if (code == data.code) {
if(data.alias && !is_affected_by_effect(EFFECT_ADD_CODE))
code = data.alias;
} else {
card_data dat;
read_card(code, &dat);
if (dat.alias)
code = dat.alias;
}
return code;
}
// get the current second-code
uint32 card::get_another_code() {
if(is_affected_by_effect(EFFECT_CHANGE_CODE))
return 0;
effect_set eset;
filter_effect(EFFECT_ADD_CODE, &eset);
if(!eset.size())
return 0;
uint32 otcode = eset.get_last()->get_value(this);
if(get_code() != otcode)
return otcode;
return 0;
}
int32 card::is_set_card(uint32 set_code) {
uint32 code = get_code();
uint64 setcode;
if (code == data.code) {
setcode = data.setcode;
} else {
card_data dat;
::read_card(code, &dat);
setcode = dat.setcode;
}
uint32 settype = set_code & 0xfff;
uint32 setsubtype = set_code & 0xf000;
while(setcode) {
if ((setcode & 0xfff) == settype && (setcode & 0xf000 & setsubtype) == setsubtype)
return TRUE;
setcode = setcode >> 16;
}
//add set code
effect_set eset;
filter_effect(EFFECT_ADD_SETCODE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 value = eset[i]->get_value(this);
if ((value & 0xfff) == settype && (value & 0xf000 & setsubtype) == setsubtype)
return TRUE;
}
//another code
uint32 code2 = get_another_code();
uint64 setcode2;
if (code2 != 0) {
card_data dat;
::read_card(code2, &dat);
setcode2 = dat.setcode;
} else {
return FALSE;
}
while(setcode2) {
if ((setcode2 & 0xfff) == settype && (setcode2 & 0xf000 & setsubtype) == setsubtype)
return TRUE;
setcode2 = setcode2 >> 16;
}
return FALSE;
}
int32 card::is_pre_set_card(uint32 set_code) {
uint32 code = previous.code;
uint64 setcode;
if (code == data.code) {
setcode = data.setcode;
} else {
card_data dat;
::read_card(code, &dat);
setcode = dat.setcode;
}
uint32 settype = set_code & 0xfff;
uint32 setsubtype = set_code & 0xf000;
while(setcode) {
if ((setcode & 0xfff) == settype && (setcode & 0xf000 & setsubtype) == setsubtype)
return TRUE;
setcode = setcode >> 16;
}
//add set code
effect_set eset;
filter_effect(EFFECT_ADD_SETCODE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 value = eset[i]->get_value(this);
if ((value & 0xfff) == settype && (value & 0xf000 & setsubtype) == setsubtype)
return TRUE;
}
//another code
uint32 code2 = previous.code2;
uint64 setcode2;
if (code2 != 0) {
card_data dat;
::read_card(code2, &dat);
setcode2 = dat.setcode;
} else {
return FALSE;
}
while(setcode2) {
if ((setcode2 & 0xfff) == settype && (setcode2 & 0xf000 & setsubtype) == setsubtype)
return TRUE;
setcode2 = setcode2 >> 16;
}
return FALSE;
}
uint32 card::get_type() {
if(assume_type == ASSUME_TYPE)
return assume_value;
if(!(current.location & 0x1e))
return data.type;
if((current.location == LOCATION_SZONE) && (current.sequence >= 6))
return TYPE_PENDULUM + TYPE_SPELL;
if (temp.type != 0xffffffff)
return temp.type;
effect_set effects;
int32 type = data.type;
temp.type = data.type;
filter_effect(EFFECT_ADD_TYPE, &effects, FALSE);
filter_effect(EFFECT_REMOVE_TYPE, &effects, FALSE);
filter_effect(EFFECT_CHANGE_TYPE, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
if (effects[i]->code == EFFECT_ADD_TYPE)
type |= effects[i]->get_value(this);
else if (effects[i]->code == EFFECT_REMOVE_TYPE)
type &= ~(effects[i]->get_value(this));
else
type = effects[i]->get_value(this);
temp.type = type;
}
temp.type = 0xffffffff;
return type;
}
int32 card::get_base_attack(uint8 swap) {
if (current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if (current.location != LOCATION_MZONE || status & STATUS_SUMMONING)
return data.attack;
if (temp.base_attack != -1)
return temp.base_attack;
if(!swap && is_affected_by_effect(EFFECT_SWAP_BASE_AD))
return get_base_defence(TRUE);
int32 batk = data.attack;
temp.base_attack = data.attack;
if(temp.base_attack < 0)
temp.base_attack = 0;
effect_set effects;
filter_effect(EFFECT_SET_BASE_ATTACK, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
batk = effects[i]->get_value(this);
if (batk < 0)
batk = 0;
temp.base_attack = batk;
}
if (batk < 0)
batk = 0;
temp.base_attack = -1;
return batk;
}
int32 card::get_attack() {
if(assume_type == ASSUME_ATTACK)
return assume_value;
if (current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if (current.location != LOCATION_MZONE || status & STATUS_SUMMONING)
return data.attack;
if (temp.attack != -1)
return temp.attack;
int32 atk;
calc_attack_defence(&atk, 0);
return atk;
}
int32 card::get_base_defence(uint8 swap) {
if (current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if (current.location != LOCATION_MZONE || status & STATUS_SUMMONING)
return data.defence;
if (temp.base_defence != -1)
return temp.base_defence;
if(!swap && is_affected_by_effect(EFFECT_SWAP_BASE_AD))
return get_base_attack(TRUE);
int32 bdef = data.defence;
temp.base_defence = data.defence;
if(temp.base_defence < 0)
temp.base_defence = 0;
effect_set effects;
filter_effect(EFFECT_SET_BASE_DEFENCE, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
bdef = effects[i]->get_value(this);
if (bdef < 0)
bdef = 0;
temp.base_defence = bdef;
}
if (bdef < 0)
bdef = 0;
temp.base_defence = -1;
return bdef;
}
int32 card::get_defence() {
if(assume_type == ASSUME_DEFENCE)
return assume_value;
if (current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if (current.location != LOCATION_MZONE || status & STATUS_SUMMONING)
return data.defence;
if (temp.defence != -1)
return temp.defence;
int32 def;
calc_attack_defence(0, &def);
return def;
}
void card::calc_attack_defence(int32 *patk, int32 *pdef) {
uint32 base_atk = get_base_attack();
uint32 base_def = get_base_defence();
temp.base_attack = base_atk;
temp.base_defence = base_def;
int32 up_atk = 0, upc_atk = 0;
int32 up_def = 0, upc_def = 0;
effect_set eset;
filter_effect(EFFECT_SWAP_AD, &eset, FALSE);
int32 swap = eset.size();
if(swap || patk) {
temp.attack = base_atk;
filter_effect(EFFECT_UPDATE_ATTACK, &eset, FALSE);
filter_effect(EFFECT_SET_ATTACK, &eset, FALSE);
filter_effect(EFFECT_SET_ATTACK_FINAL, &eset, FALSE);
}
if(swap || pdef) {
temp.defence = base_def;
filter_effect(EFFECT_UPDATE_DEFENCE, &eset, FALSE);
filter_effect(EFFECT_SET_DEFENCE, &eset, FALSE);
filter_effect(EFFECT_SET_DEFENCE_FINAL, &eset, FALSE);
}
eset.sort();
int32 rev = FALSE;
if (is_affected_by_effect(EFFECT_REVERSE_UPDATE))
rev = TRUE;
effect_set effects_atk, effects_def;
int32 swap_final = FALSE;
for (int32 i = 0; i < eset.size(); ++i) {
switch (eset[i]->code) {
case EFFECT_UPDATE_ATTACK:
if ((eset[i]->type & EFFECT_TYPE_SINGLE) && !(eset[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up_atk += eset[i]->get_value(this);
else
upc_atk += eset[i]->get_value(this);
break;
case EFFECT_SET_ATTACK:
base_atk = eset[i]->get_value(this);
if (!(eset[i]->type & EFFECT_TYPE_SINGLE))
up_atk = 0;
break;
case EFFECT_SET_ATTACK_FINAL:
if ((eset[i]->type & EFFECT_TYPE_SINGLE) && !(eset[i]->flag & EFFECT_FLAG_SINGLE_RANGE)) {
base_atk = eset[i]->get_value(this);
up_atk = 0;
upc_atk = 0;
} else
effects_atk.add_item(eset[i]);
break;
case EFFECT_UPDATE_DEFENCE:
if ((eset[i]->type & EFFECT_TYPE_SINGLE) && !(eset[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up_def += eset[i]->get_value(this);
else
upc_def += eset[i]->get_value(this);
break;
case EFFECT_SET_DEFENCE:
base_def = eset[i]->get_value(this);
if (!(eset[i]->type & EFFECT_TYPE_SINGLE))
up_def = 0;
break;
case EFFECT_SET_DEFENCE_FINAL:
if ((eset[i]->type & EFFECT_TYPE_SINGLE) && !(eset[i]->flag & EFFECT_FLAG_SINGLE_RANGE)) {
base_def = eset[i]->get_value(this);
up_def = 0;
upc_def = 0;
} else
effects_def.add_item(eset[i]);
break;
case EFFECT_SWAP_AD:
if ((eset[i]->type & EFFECT_TYPE_SINGLE) && !(eset[i]->flag & EFFECT_FLAG_SINGLE_RANGE)) {
int32 a = base_atk + up_atk + upc_atk;
int32 d = base_def + up_def + upc_def;
base_atk = d;
up_atk = 0;
upc_atk = 0;
base_def = a;
up_def = 0;
upc_def = 0;
} else
swap_final = !swap_final;
break;
}
if (!rev) {
if (temp.attack != -1)
temp.attack = base_atk + up_atk + upc_atk;
if (temp.defence != -1)
temp.defence = base_def + up_def + upc_def;
} else {
if (temp.attack != -1)
temp.attack = base_atk - up_atk - upc_atk;
if (temp.defence != -1)
temp.defence = base_def - up_def - upc_def;
}
}
if (swap_final) {
int32 atk = temp.attack;
int32 def = temp.defence;
temp.attack = def;
temp.defence = atk;
}
if (patk) {
for (int32 i = 0; i < effects_atk.size(); ++i)
temp.attack = effects_atk[i]->get_value(this);
int32 atk = temp.attack;
if (atk < 0)
atk = 0;
*patk = atk;
}
if (pdef) {
for (int32 i = 0; i < effects_def.size(); ++i)
temp.defence = effects_def[i]->get_value(this);
int32 def = temp.defence;
if (def < 0)
def = 0;
*pdef = def;
}
temp.base_attack = -1;
temp.attack = -1;
temp.base_defence = -1;
temp.defence = -1;
}
uint32 card::get_level() {
if((data.type & TYPE_XYZ) || (status & STATUS_NO_LEVEL)
|| (current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER)))
return 0;
if(assume_type == ASSUME_LEVEL)
return assume_value;
if(!(current.location & LOCATION_MZONE) && !(data.type & TYPE_MONSTER))
return data.level;
if (temp.level != 0xffffffff)
return temp.level;
effect_set effects;
int32 level = data.level;
temp.level = level;
int32 up = 0, upc = 0;
filter_effect(EFFECT_UPDATE_LEVEL, &effects, FALSE);
filter_effect(EFFECT_CHANGE_LEVEL, &effects, FALSE);
filter_effect(EFFECT_CHANGE_LEVEL_FINAL, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
switch (effects[i]->code) {
case EFFECT_UPDATE_LEVEL:
if ((effects[i]->type & EFFECT_TYPE_SINGLE) && !(effects[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up += effects[i]->get_value(this);
else
upc += effects[i]->get_value(this);
break;
case EFFECT_CHANGE_LEVEL:
level = effects[i]->get_value(this);
up = 0;
break;
case EFFECT_CHANGE_LEVEL_FINAL:
level = effects[i]->get_value(this);
up = 0;
upc = 0;
break;
}
temp.level = level + up + upc;
}
level += up + upc;
if(level < 1 && (get_type() & TYPE_MONSTER))
level = 1;
temp.level = 0xffffffff;
return level;
}
uint32 card::get_rank() {
if(!(data.type & TYPE_XYZ) || (status & STATUS_NO_LEVEL))
return 0;
if(assume_type == ASSUME_RANK)
return assume_value;
if(!(current.location & LOCATION_MZONE))
return data.level;
if (temp.level != 0xffffffff)
return temp.level;
effect_set effects;
int32 rank = data.level;
temp.level = rank;
int32 up = 0, upc = 0;
filter_effect(EFFECT_UPDATE_RANK, &effects, FALSE);
filter_effect(EFFECT_CHANGE_RANK, &effects, FALSE);
filter_effect(EFFECT_CHANGE_RANK_FINAL, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
switch (effects[i]->code) {
case EFFECT_UPDATE_RANK:
if ((effects[i]->type & EFFECT_TYPE_SINGLE) && !(effects[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up += effects[i]->get_value(this);
else
upc += effects[i]->get_value(this);
break;
case EFFECT_CHANGE_RANK:
rank = effects[i]->get_value(this);
up = 0;
break;
case EFFECT_CHANGE_RANK_FINAL:
rank = effects[i]->get_value(this);
up = 0;
upc = 0;
break;
}
temp.level = rank + up + upc;
}
rank += up + upc;
if(rank < 1 && (get_type() & TYPE_MONSTER))
rank = 1;
temp.level = 0xffffffff;
return rank;
}
uint32 card::get_synchro_level(card* pcard) {
if((data.type & TYPE_XYZ) || (status & STATUS_NO_LEVEL))
return 0;
uint32 lev;
effect_set eset;
filter_effect(EFFECT_SYNCHRO_LEVEL, &eset);
if(eset.size())
lev = eset[0]->get_value(pcard);
else
lev = get_level();
return lev;
}
uint32 card::get_ritual_level(card* pcard) {
if((data.type & TYPE_XYZ) || (status & STATUS_NO_LEVEL))
return 0;
uint32 lev;
effect_set eset;
filter_effect(EFFECT_RITUAL_LEVEL, &eset);
if(eset.size())
lev = eset[0]->get_value(pcard);
else
lev = get_level();
return lev;
}
uint32 card::check_xyz_level(card* pcard, uint32 lv) {
if(status & STATUS_NO_LEVEL)
return 0;
uint32 lev;
effect_set eset;
filter_effect(EFFECT_XYZ_LEVEL, &eset);
if(!eset.size()) {
lev = get_level();
if(lev == lv)
return lev;
return 0;
}
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
lev = eset[0]->get_value(2);
if(((lev & 0xfff) == lv))
return lev & 0xffff;
if(((lev >> 16) & 0xfff) == lv)
return (lev >> 16) & 0xffff;
return 0;
}
uint32 card::get_attribute() {
if(assume_type == ASSUME_ATTRIBUTE)
return assume_value;
if(current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if(!(current.location & (LOCATION_MZONE)) && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_TRAPMONSTER))
return data.attribute;
if (temp.attribute != 0xffffffff)
return temp.attribute;
effect_set effects;
effect_set effects2;
int32 attribute = data.attribute;
temp.attribute = data.attribute;
filter_effect(EFFECT_ADD_ATTRIBUTE, &effects, FALSE);
filter_effect(EFFECT_REMOVE_ATTRIBUTE, &effects);
filter_effect(EFFECT_CHANGE_ATTRIBUTE, &effects2);
for (int32 i = 0; i < effects.size(); ++i) {
if (effects[i]->code == EFFECT_ADD_ATTRIBUTE)
attribute |= effects[i]->get_value(this);
else
attribute &= ~(effects[i]->get_value(this));
temp.attribute = attribute;
}
for (int32 i = 0; i < effects2.size(); ++i) {
attribute = effects2[i]->get_value(this);
temp.attribute = attribute;
}
temp.attribute = 0xffffffff;
return attribute;
}
uint32 card::get_race() {
if(assume_type == ASSUME_RACE)
return assume_value;
if(current.location != LOCATION_MZONE && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER))
return 0;
if(!(current.location & (LOCATION_MZONE)) && !(data.type & TYPE_MONSTER) && !(get_type() & TYPE_TRAPMONSTER))
return data.race;
if (temp.race != 0xffffffff)
return temp.race;
effect_set effects;
effect_set effects2;
int32 race = data.race;
temp.race = data.race;
filter_effect(EFFECT_ADD_RACE, &effects, FALSE);
filter_effect(EFFECT_REMOVE_RACE, &effects);
filter_effect(EFFECT_CHANGE_RACE, &effects2);
for (int32 i = 0; i < effects.size(); ++i) {
if (effects[i]->code == EFFECT_ADD_RACE)
race |= effects[i]->get_value(this);
else
race &= ~(effects[i]->get_value(this));
temp.race = race;
}
for (int32 i = 0; i < effects2.size(); ++i) {
race = effects2[i]->get_value(this);
temp.race = race;
}
temp.race = 0xffffffff;
return race;
}
uint32 card::get_lscale() {
if(!(current.location & LOCATION_SZONE))
return data.lscale;
if (temp.lscale != 0xffffffff)
return temp.lscale;
effect_set effects;
int32 lscale = data.lscale;
temp.lscale = data.lscale;
int32 up = 0, upc = 0;
filter_effect(EFFECT_UPDATE_LSCALE, &effects, FALSE);
filter_effect(EFFECT_CHANGE_LSCALE, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
if (effects[i]->code == EFFECT_UPDATE_LSCALE) {
if ((effects[i]->type & EFFECT_TYPE_SINGLE) && !(effects[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up += effects[i]->get_value(this);
else
upc += effects[i]->get_value(this);
} else {
lscale = effects[i]->get_value(this);
up = 0;
}
temp.lscale = lscale;
}
lscale += up + upc;
temp.lscale = 0xffffffff;
return lscale;
}
uint32 card::get_rscale() {
if(!(current.location & LOCATION_SZONE))
return data.rscale;
if (temp.rscale != 0xffffffff)
return temp.rscale;
effect_set effects;
int32 rscale = data.rscale;
temp.rscale = data.rscale;
int32 up = 0, upc = 0;
filter_effect(EFFECT_UPDATE_RSCALE, &effects, FALSE);
filter_effect(EFFECT_CHANGE_RSCALE, &effects);
for (int32 i = 0; i < effects.size(); ++i) {
if (effects[i]->code == EFFECT_UPDATE_RSCALE) {
if ((effects[i]->type & EFFECT_TYPE_SINGLE) && !(effects[i]->flag & EFFECT_FLAG_SINGLE_RANGE))
up += effects[i]->get_value(this);
else
upc += effects[i]->get_value(this);
} else {
rscale = effects[i]->get_value(this);
up = 0;
}
temp.rscale = rscale;
}
rscale += up + upc;
temp.rscale = 0xffffffff;
return rscale;
}
int32 card::is_position(int32 pos) {
return current.position & pos;
}
void card::set_status(uint32 status, int32 enabled) {
if (enabled)
this->status |= status;
else
this->status &= ~status;
}
int32 card::get_status(uint32 status) {
return this->status & status;
}
int32 card::is_status(uint32 status) {
if ((this->status & status) == status)
return TRUE;
return FALSE;
}
void card::equip(card *target, uint32 send_msg) {
if (equiping_target)
return;
target->equiping_cards.insert(this);
equiping_target = target;
for (auto it = equip_effect.begin(); it != equip_effect.end(); ++it) {
if (it->second->is_disable_related())
pduel->game_field->add_to_disable_check_list(equiping_target);
}
if(send_msg) {
pduel->write_buffer8(MSG_EQUIP);
pduel->write_buffer32(get_info_location());
pduel->write_buffer32(target->get_info_location());
}
return;
}
void card::unequip() {
if (!equiping_target)
return;
for (auto it = equip_effect.begin(); it != equip_effect.end(); ++it) {
if (it->second->is_disable_related())
pduel->game_field->add_to_disable_check_list(equiping_target);
}
equiping_target->equiping_cards.erase(this);
pre_equip_target = equiping_target;
equiping_target = 0;
return;
}
int32 card::get_union_count() {
card_set::iterator cit;
int32 count = 0;
for(cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
if(((*cit)->data.type & TYPE_UNION) && (*cit)->is_status(STATUS_UNION))
count++;
}
return count;
}
void card::xyz_overlay(card_set* materials) {
if(materials->size() == 0)
return;
card_set des;
if(materials->size() == 1) {
card* pcard = *materials->begin();
pcard->reset(RESET_LEAVE + RESET_OVERLAY, RESET_EVENT);
if(pcard->unique_code)
pduel->game_field->remove_unique_card(pcard);
if(pcard->equiping_target)
pcard->unequip();
xyz_add(pcard, &des);
} else {
field::card_vector cv;
for(auto cit = materials->begin(); cit != materials->end(); ++cit)
cv.push_back(*cit);
std::sort(cv.begin(), cv.end(), card::card_operation_sort);
for(auto cvit = cv.begin(); cvit != cv.end(); ++cvit) {
(*cvit)->reset(RESET_LEAVE + RESET_OVERLAY, RESET_EVENT);
if((*cvit)->unique_code)
pduel->game_field->remove_unique_card(*cvit);
if((*cvit)->equiping_target)
(*cvit)->unequip();
xyz_add(*cvit, &des);
}
}
if(des.size())
pduel->game_field->destroy(&des, 0, REASON_LOST_TARGET + REASON_RULE, PLAYER_NONE);
else
pduel->game_field->adjust_instant();
}
void card::xyz_add(card* mat, card_set* des) {
if(mat->overlay_target == this)
return;
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(mat->data.code);
if(mat->overlay_target) {
pduel->write_buffer8(mat->overlay_target->current.controler);
pduel->write_buffer8(mat->overlay_target->current.location | LOCATION_OVERLAY);
pduel->write_buffer8(mat->overlay_target->current.sequence);
pduel->write_buffer8(mat->current.sequence);
mat->overlay_target->xyz_remove(mat);
} else {
pduel->write_buffer8(mat->current.controler);
pduel->write_buffer8(mat->current.location);
pduel->write_buffer8(mat->current.sequence);
pduel->write_buffer8(mat->current.position);
mat->enable_field_effect(false);
pduel->game_field->remove_card(mat);
pduel->game_field->add_to_disable_check_list(mat);
}
pduel->write_buffer8(current.controler);
pduel->write_buffer8(current.location | LOCATION_OVERLAY);
pduel->write_buffer8(current.sequence);
pduel->write_buffer8(current.position);
pduel->write_buffer32(REASON_XYZ + REASON_MATERIAL);
xyz_materials.push_back(mat);
for(auto cit = mat->equiping_cards.begin(); cit != mat->equiping_cards.end();) {
auto rm = cit++;
des->insert(*rm);
(*rm)->unequip();
}
mat->overlay_target = this;
mat->current.controler = PLAYER_NONE;
mat->current.location = LOCATION_OVERLAY;
mat->current.sequence = xyz_materials.size() - 1;
mat->current.reason = REASON_XYZ + REASON_MATERIAL;
}
void card::xyz_remove(card* mat) {
if(mat->overlay_target != this)
return;
xyz_materials.erase(xyz_materials.begin() + mat->current.sequence);
mat->previous.controler = mat->current.controler;
mat->previous.location = mat->current.location;
mat->previous.sequence = mat->current.sequence;
mat->current.controler = PLAYER_NONE;
mat->current.location = 0;
mat->current.sequence = 0;
mat->overlay_target = 0;
for(auto clit = xyz_materials.begin(); clit != xyz_materials.end(); ++clit)
(*clit)->current.sequence = clit - xyz_materials.begin();
}
void card::apply_field_effect() {
if (current.controler == PLAYER_NONE)
return;
for (auto it = field_effect.begin(); it != field_effect.end(); ++it) {
if (it->second->in_range(current.location, current.sequence) || ((it->second->range & LOCATION_HAND)
&& (it->second->type & EFFECT_TYPE_TRIGGER_O) && !(it->second->code & EVENT_PHASE))) {
pduel->game_field->add_effect(it->second);
}
}
if(unique_code && (current.location & LOCATION_ONFIELD))
pduel->game_field->add_unique_card(this);
spsummon_counter[0] = spsummon_counter[1] = 0;
spsummon_counter_rst[0] = spsummon_counter_rst[1] = 0;
}
void card::cancel_field_effect() {
if (current.controler == PLAYER_NONE)
return;
for (auto it = field_effect.begin(); it != field_effect.end(); ++it) {
if (it->second->in_range(current.location, current.sequence) || ((it->second->range & LOCATION_HAND)
&& (it->second->type & EFFECT_TYPE_TRIGGER_O) && !(it->second->code & EVENT_PHASE))) {
pduel->game_field->remove_effect(it->second);
}
}
if(unique_code && (current.location & LOCATION_ONFIELD))
pduel->game_field->remove_unique_card(this);
}
void card::enable_field_effect(int32 enabled) {
if (current.location == 0)
return;
if ((enabled && get_status(STATUS_EFFECT_ENABLED)) || (!enabled && !get_status(STATUS_EFFECT_ENABLED)))
return;
refresh_disable_status();
if (enabled) {
set_status(STATUS_EFFECT_ENABLED, TRUE);
effect_container::iterator it;
for (it = single_effect.begin(); it != single_effect.end(); ++it) {
if ((it->second->flag & EFFECT_FLAG_SINGLE_RANGE) && it->second->in_range(current.location, current.sequence))
it->second->id = pduel->game_field->infos.field_id++;
}
for (it = field_effect.begin(); it != field_effect.end(); ++it) {
if (it->second->in_range(current.location, current.sequence))
it->second->id = pduel->game_field->infos.field_id++;
}
if(current.location == LOCATION_SZONE) {
for (it = equip_effect.begin(); it != equip_effect.end(); ++it)
it->second->id = pduel->game_field->infos.field_id++;
}
if (get_status(STATUS_DISABLED))
reset(RESET_DISABLE, RESET_EVENT);
} else
set_status(STATUS_EFFECT_ENABLED, FALSE);
filter_immune_effect();
if (get_status(STATUS_DISABLED))
return;
filter_disable_related_cards();
}
int32 card::add_effect(effect* peffect) {
effect_container::iterator it, rm;
if (get_status(STATUS_COPYING_EFFECT) && (peffect->flag & EFFECT_FLAG_UNCOPYABLE)) {
pduel->uncopy.insert(peffect);
return 0;
}
if (indexer.find(peffect) != indexer.end())
return 0;
card* check_target = this;
if (peffect->type & EFFECT_TYPE_SINGLE) {
if((peffect->code == EFFECT_SET_ATTACK || peffect->code == EFFECT_SET_BASE_ATTACK) && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE)) {
for(it = single_effect.begin(); it != single_effect.end();) {
rm = it++;
if((rm->second->code == EFFECT_SET_ATTACK || rm->second->code == EFFECT_SET_ATTACK_FINAL)
&& !(rm->second->flag & EFFECT_FLAG_SINGLE_RANGE))
remove_effect(rm->second);
}
}
if(peffect->code == EFFECT_SET_ATTACK_FINAL && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE)) {
for(it = single_effect.begin(); it != single_effect.end();) {
rm = it++;
if((rm->second->code == EFFECT_UPDATE_ATTACK || rm->second->code == EFFECT_SET_ATTACK
|| rm->second->code == EFFECT_SET_ATTACK_FINAL) && !(rm->second->flag & EFFECT_FLAG_SINGLE_RANGE))
remove_effect(rm->second);
}
}
if((peffect->code == EFFECT_SET_DEFENCE || peffect->code == EFFECT_SET_BASE_DEFENCE) && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE)) {
for(it = single_effect.begin(); it != single_effect.end();) {
rm = it++;
if((rm->second->code == EFFECT_SET_DEFENCE || rm->second->code == EFFECT_SET_DEFENCE_FINAL)
&& !(rm->second->flag & EFFECT_FLAG_SINGLE_RANGE))
remove_effect(rm->second);
}
}
if(peffect->code == EFFECT_SET_DEFENCE_FINAL && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE)) {
for(it = single_effect.begin(); it != single_effect.end();) {
rm = it++;
if((rm->second->code == EFFECT_UPDATE_DEFENCE || rm->second->code == EFFECT_SET_DEFENCE
|| rm->second->code == EFFECT_SET_DEFENCE_FINAL) && !(rm->second->flag & EFFECT_FLAG_SINGLE_RANGE))
remove_effect(rm->second);
}
}
it = single_effect.insert(make_pair(peffect->code, peffect));
} else if (peffect->type & EFFECT_TYPE_FIELD)
it = field_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_EQUIP) {
it = equip_effect.insert(make_pair(peffect->code, peffect));
if (equiping_target)
check_target = equiping_target;
else
check_target = 0;
} else
return 0;
peffect->id = pduel->game_field->infos.field_id++;
peffect->card_type = data.type;
if(get_status(STATUS_INITIALIZING))
peffect->flag |= EFFECT_FLAG_INITIAL;
if (get_status(STATUS_COPYING_EFFECT)) {
peffect->copy_id = pduel->game_field->infos.copy_id;
peffect->reset_flag |= pduel->game_field->core.copy_reset;
peffect->reset_count = (peffect->reset_count & 0xffffff00) | pduel->game_field->core.copy_reset_count;
}
if((peffect->flag & EFFECT_FLAG_COPY_INHERIT) && pduel->game_field->core.reason_effect
&& (pduel->game_field->core.reason_effect->copy_id)) {
peffect->copy_id = pduel->game_field->core.reason_effect->copy_id;
peffect->reset_flag |= pduel->game_field->core.reason_effect->reset_flag;
if((peffect->reset_count & 0xff) > (pduel->game_field->core.reason_effect->reset_count & 0xff))
peffect->reset_count = (peffect->reset_count & 0xffffff00) | (pduel->game_field->core.reason_effect->reset_count & 0xff);
}
indexer.insert(make_pair(peffect, it));
peffect->handler = this;
if((peffect->type & 0x7e0)
|| (pduel->game_field->core.reason_effect && (pduel->game_field->core.reason_effect->status & EFFECT_STATUS_ACTIVATED)))
peffect->status |= EFFECT_STATUS_ACTIVATED;
if (peffect->in_range(current.location, current.sequence) && (peffect->type & EFFECT_TYPE_FIELD))
pduel->game_field->add_effect(peffect);
if (current.controler != PLAYER_NONE && check_target) {
if (peffect->is_disable_related())
pduel->game_field->add_to_disable_check_list(check_target);
}
if(peffect->flag & EFFECT_FLAG_OATH) {
effect* reason_effect = pduel->game_field->core.reason_effect;
pduel->game_field->effects.oath.insert(make_pair(peffect, reason_effect));
}
if(peffect->reset_flag & RESET_PHASE) {
pduel->game_field->effects.pheff.insert(peffect);
if((peffect->reset_count & 0xff) == 0)
peffect->reset_count += 1;
}
if(peffect->reset_flag & RESET_CHAIN)
pduel->game_field->effects.cheff.insert(peffect);
if(peffect->flag & EFFECT_FLAG_COUNT_LIMIT)
pduel->game_field->effects.rechargeable.insert(peffect);
if(peffect->flag & EFFECT_FLAG_CLIENT_HINT) {
pduel->write_buffer8(MSG_CARD_HINT);
pduel->write_buffer32(get_info_location());
pduel->write_buffer8(CHINT_DESC_ADD);
pduel->write_buffer32(peffect->description);
}
if(peffect->type & EFFECT_TYPE_SINGLE && peffect->code == EFFECT_UPDATE_LEVEL && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE)) {
int32 val = peffect->get_value(this);
if(val > 0) {
pduel->game_field->raise_single_event(this, 0, EVENT_LEVEL_UP, peffect, 0, 0, 0, val);
pduel->game_field->process_single_event();
}
}
return peffect->id;
}
void card::remove_effect(effect* peffect) {
auto it = indexer.find(peffect);
if (it == indexer.end())
return;
remove_effect(peffect, it->second);
}
void card::remove_effect(effect* peffect, effect_container::iterator it) {
card* check_target = this;
if (peffect->type & EFFECT_TYPE_SINGLE)
single_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_FIELD) {
check_target = 0;
if (peffect->in_range(current.location, current.sequence) && get_status(STATUS_EFFECT_ENABLED) && !get_status(STATUS_DISABLED)) {
if (peffect->is_disable_related())
pduel->game_field->update_disable_check_list(peffect);
}
field_effect.erase(it);
if (peffect->in_range(current.location, current.sequence))
pduel->game_field->remove_effect(peffect);
} else if (peffect->type & EFFECT_TYPE_EQUIP) {
equip_effect.erase(it);
if (equiping_target)
check_target = equiping_target;
else
check_target = 0;
}
if ((current.controler != PLAYER_NONE) && !get_status(STATUS_DISABLED) && check_target) {
if (peffect->is_disable_related())
pduel->game_field->add_to_disable_check_list(check_target);
}
indexer.erase(peffect);
if(peffect->flag & EFFECT_FLAG_OATH)
pduel->game_field->effects.oath.erase(peffect);
if(peffect->reset_flag & RESET_PHASE)
pduel->game_field->effects.pheff.erase(peffect);
if(peffect->reset_flag & RESET_CHAIN)
pduel->game_field->effects.cheff.erase(peffect);
if(peffect->flag & EFFECT_FLAG_COUNT_LIMIT)
pduel->game_field->effects.rechargeable.erase(peffect);
if(((peffect->code & 0xf0000) == EFFECT_COUNTER_PERMIT) && (peffect->type & EFFECT_TYPE_SINGLE)) {
auto cmit = counters.find(peffect->code & 0xffff);
if(cmit != counters.end()) {
pduel->write_buffer8(MSG_REMOVE_COUNTER);
pduel->write_buffer16(cmit->first);
pduel->write_buffer8(current.controler);
pduel->write_buffer8(current.location);
pduel->write_buffer8(current.sequence);
pduel->write_buffer8(cmit->second);
counters.erase(cmit);
}
}
if(peffect->flag & EFFECT_FLAG_CLIENT_HINT) {
pduel->write_buffer8(MSG_CARD_HINT);
pduel->write_buffer32(get_info_location());
pduel->write_buffer8(CHINT_DESC_REMOVE);
pduel->write_buffer32(peffect->description);
}
if(peffect->code == EFFECT_UNIQUE_CHECK) {
pduel->game_field->remove_unique_card(this);
unique_pos[0] = unique_pos[1] = 0;
unique_code = 0;
}
pduel->game_field->core.reseted_effects.insert(peffect);
}
int32 card::copy_effect(uint32 code, uint32 reset, uint32 count) {
card_data cdata;
read_card(code, &cdata);
if(cdata.type & TYPE_NORMAL)
return -1;
set_status(STATUS_COPYING_EFFECT, TRUE);
uint32 cr = pduel->game_field->core.copy_reset;
uint8 crc = pduel->game_field->core.copy_reset_count;
pduel->game_field->core.copy_reset = reset;
pduel->game_field->core.copy_reset_count = count;
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->call_code_function(code, (char*) "initial_effect", 1, 0);
pduel->game_field->infos.copy_id++;
set_status(STATUS_COPYING_EFFECT, FALSE);
pduel->game_field->core.copy_reset = cr;
pduel->game_field->core.copy_reset_count = crc;
for(auto eit = pduel->uncopy.begin(); eit != pduel->uncopy.end(); ++eit)
pduel->delete_effect(*eit);
pduel->uncopy.clear();
return pduel->game_field->infos.copy_id - 1;
}
// add EFFECT_SET_CONTROL
void card::reset(uint32 id, uint32 reset_type) {
effect* peffect;
if (reset_type != RESET_EVENT && reset_type != RESET_PHASE && reset_type != RESET_CODE && reset_type != RESET_COPY && reset_type != RESET_CARD)
return;
if (reset_type == RESET_EVENT) {
for (auto rit = relations.begin(); rit != relations.end();) {
auto rrm = rit++;
if (rrm->second & 0xffff0000 & id)
relations.erase(rrm);
}
if(id & 0x47c0000)
relate_effect.clear();
if(id & 0x5fc0000) {
announced_cards.clear();
attacked_cards.clear();
announce_count = 0;
attacked_count = 0;
attack_all_target = TRUE;
}
if(id & 0x5fe0000) {
battled_cards.clear();
reset_effect_count();
auto pr = field_effect.equal_range(EFFECT_DISABLE_FIELD);
for(; pr.first != pr.second; ++pr.first)
pr.first->second->value = 0;
set_status(STATUS_UNION, FALSE);
}
if(id & 0x57e0000) {
counters.clear();
for(auto cit = effect_target_owner.begin(); cit != effect_target_owner.end(); ++cit)
(*cit)->effect_target_cards.erase(this);
for(auto cit = effect_target_cards.begin(); cit != effect_target_cards.end(); ++cit) {
card* pcard = *cit;
pcard->effect_target_owner.erase(this);
for(auto it = pcard->single_effect.begin(); it != pcard->single_effect.end();) {
auto rm = it++;
peffect = rm->second;
if((peffect->owner == this) && (peffect->flag & EFFECT_FLAG_OWNER_RELATE))
pcard->remove_effect(peffect, rm);
}
}
effect_target_owner.clear();
effect_target_cards.clear();
}
if(id & 0x3fe0000) {
auto pr = field_effect.equal_range(EFFECT_USE_EXTRA_MZONE);
for(; pr.first != pr.second; ++pr.first)
pr.first->second->value = pr.first->second->value & 0xffff;
pr = field_effect.equal_range(EFFECT_USE_EXTRA_SZONE);
for(; pr.first != pr.second; ++pr.first)
pr.first->second->value = pr.first->second->value & 0xffff;
}
if(id & RESET_DISABLE) {
for(auto cmit = counters.begin(); cmit != counters.end();) {
auto rm = cmit++;
if(rm->first & COUNTER_NEED_ENABLE) {
pduel->write_buffer8(MSG_REMOVE_COUNTER);
pduel->write_buffer16(rm->first);
pduel->write_buffer8(current.controler);
pduel->write_buffer8(current.location);
pduel->write_buffer8(current.sequence);
pduel->write_buffer8(rm->second);
counters.erase(rm);
}
}
}
if(id & RESET_TURN_SET) {
effect* peffect = check_control_effect();
if(peffect) {
effect* new_effect = pduel->new_effect();
new_effect->id = peffect->id;
new_effect->owner = this;
new_effect->handler = this;
new_effect->type = EFFECT_TYPE_SINGLE;
new_effect->code = EFFECT_SET_CONTROL;
new_effect->value = current.controler;
new_effect->flag = EFFECT_FLAG_CANNOT_DISABLE;
new_effect->reset_flag = RESET_EVENT | 0xec0000;
this->add_effect(new_effect);
}
}
}
for (auto i = indexer.begin(); i != indexer.end();) {
auto rm = i++;
peffect = rm->first;
auto it = rm->second;
if (peffect->reset(id, reset_type))
remove_effect(peffect, it);
}
}
void card::reset_effect_count() {
for (auto i = indexer.begin(); i != indexer.end(); ++i) {
effect* peffect = i->first;
if (peffect->flag & EFFECT_FLAG_COUNT_LIMIT)
peffect->recharge();
}
}
int32 card::refresh_disable_status() {
int32 pre_dis = is_status(STATUS_DISABLED);
filter_immune_effect();
if (!is_affected_by_effect(EFFECT_CANNOT_DISABLE) && is_affected_by_effect(EFFECT_DISABLE))
set_status(STATUS_DISABLED, TRUE);
else
set_status(STATUS_DISABLED, FALSE);
int32 cur_dis = is_status(STATUS_DISABLED);
if(pre_dis != cur_dis)
filter_immune_effect();
return is_status(STATUS_DISABLED);
}
uint8 card::refresh_control_status() {
uint8 final = owner;
if(pduel->game_field->core.remove_brainwashing && is_affected_by_effect(EFFECT_REMOVE_BRAINWASHING))
return final;
effect_set eset;
filter_effect(EFFECT_SET_CONTROL, &eset);
if(eset.size())
final = (uint8) (eset.get_last()->get_value(this, 0));
return final;
}
void card::count_turn(uint16 ct) {
turn_counter = ct;
pduel->write_buffer8(MSG_CARD_HINT);
pduel->write_buffer32(get_info_location());
pduel->write_buffer8(CHINT_TURN);
pduel->write_buffer32(ct);
}
void card::create_relation(card* target, uint32 reset) {
if (relations.find(target) != relations.end())
return;
relations[target] = reset;
}
void card::create_relation(effect* peffect) {
auto it = relate_effect.find(peffect);
if (it != relate_effect.end())
++it->second;
else
relate_effect[peffect] = 1;
}
int32 card::is_has_relation(card* target) {
if (relations.find(target) != relations.end())
return TRUE;
return FALSE;
}
int32 card::is_has_relation(effect* peffect) {
if (relate_effect.find(peffect) != relate_effect.end())
return TRUE;
return FALSE;
}
void card::release_relation(card* target) {
if (relations.find(target) == relations.end())
return;
relations.erase(target);
}
void card::release_relation(effect* peffect) {
auto it = relate_effect.find(peffect);
if (it != relate_effect.end() && --it->second == 0)
relate_effect.erase(it);
}
int32 card::leave_field_redirect(uint32 reason) {
effect_set es;
uint32 redirect;
if(data.type & TYPE_TOKEN)
return 0;
filter_effect(EFFECT_LEAVE_FIELD_REDIRECT, &es);
for(int32 i = 0; i < es.size(); ++i) {
redirect = es[i]->get_value(this, 0);
if((redirect & LOCATION_HAND) && !is_affected_by_effect(EFFECT_CANNOT_TO_HAND) && pduel->game_field->is_player_can_send_to_hand(current.controler, this))
return redirect;
else if((redirect & LOCATION_DECK) && !is_affected_by_effect(EFFECT_CANNOT_TO_DECK) && pduel->game_field->is_player_can_send_to_deck(current.controler, this))
return redirect;
else if((redirect & LOCATION_REMOVED) && !is_affected_by_effect(EFFECT_CANNOT_REMOVE) && pduel->game_field->is_player_can_remove(current.controler, this))
return redirect;
}
return 0;
}
int32 card::destination_redirect(uint8 destination, uint32 reason) {
effect_set es;
uint32 redirect;
if(data.type & TYPE_TOKEN)
return 0;
if(destination == LOCATION_HAND)
filter_effect(EFFECT_TO_HAND_REDIRECT, &es);
else if(destination == LOCATION_DECK)
filter_effect(EFFECT_TO_DECK_REDIRECT, &es);
else if(destination == LOCATION_GRAVE)
filter_effect(EFFECT_TO_GRAVE_REDIRECT, &es);
else if(destination == LOCATION_REMOVED)
filter_effect(EFFECT_REMOVE_REDIRECT, &es);
else return 0;
for(int32 i = 0; i < es.size(); ++i) {
redirect = es[i]->get_value(this, 0);
if((redirect & LOCATION_HAND) && !is_affected_by_effect(EFFECT_CANNOT_TO_HAND) && pduel->game_field->is_player_can_send_to_hand(current.controler, this))
return redirect;
if((redirect & LOCATION_DECK) && !is_affected_by_effect(EFFECT_CANNOT_TO_DECK) && pduel->game_field->is_player_can_send_to_deck(current.controler, this))
return redirect;
if((redirect & LOCATION_REMOVED) && !is_affected_by_effect(EFFECT_CANNOT_REMOVE) && pduel->game_field->is_player_can_remove(current.controler, this))
return redirect;
}
return 0;
}
int32 card::add_counter(uint8 playerid, uint16 countertype, uint16 count) {
if(!is_can_add_counter(playerid, countertype, count))
return FALSE;
counters[countertype] += count;
pduel->write_buffer8(MSG_ADD_COUNTER);
pduel->write_buffer16(countertype);
pduel->write_buffer8(current.controler);
pduel->write_buffer8(current.location);
pduel->write_buffer8(current.sequence);
pduel->write_buffer8(count);
return TRUE;
}
int32 card::remove_counter(uint16 countertype, uint16 count) {
counter_map::iterator cmit = counters.find(countertype);
if(cmit == counters.end())
return FALSE;
if(cmit->second <= count)
counters.erase(cmit);
else cmit->second -= count;
pduel->write_buffer8(MSG_REMOVE_COUNTER);
pduel->write_buffer16(countertype);
pduel->write_buffer8(current.controler);
pduel->write_buffer8(current.location);
pduel->write_buffer8(current.sequence);
pduel->write_buffer8(count);
return TRUE;
}
int32 card::is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count) {
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_NEED_PERMIT) && !is_affected_by_effect(EFFECT_COUNTER_PERMIT + (countertype & 0xffff)))
return FALSE;
int32 limit = -1;
int32 cur = 0;
counter_map::iterator cmit = counters.find(countertype);
if(cmit != counters.end())
cur = cmit->second;
filter_effect(EFFECT_COUNTER_LIMIT + countertype, &eset);
for(int32 i = 0; i < eset.size(); ++i)
limit = eset[i]->get_value();
if(limit > 0 && (cur + count > limit))
return FALSE;
return TRUE;
}
int32 card::get_counter(uint16 countertype) {
counter_map::iterator cmit = counters.find(countertype);
if(cmit == counters.end())
return 0;
return cmit->second;
}
void card::set_material(card_set* materials) {
if(!materials) {
material_cards.clear();
return;
}
material_cards = *materials;
for(auto cit = material_cards.begin(); cit != material_cards.end(); ++cit)
(*cit)->current.reason_card = this;
effect_set eset;
filter_effect(EFFECT_MATERIAL_CHECK, &eset);
for(int i = 0; i < eset.size(); ++i) {
eset[i]->get_value(this);
}
}
void card::add_card_target(card* pcard) {
effect_target_cards.insert(pcard);
pcard->effect_target_owner.insert(this);
pduel->write_buffer8(MSG_CARD_TARGET);
pduel->write_buffer32(get_info_location());
pduel->write_buffer32(pcard->get_info_location());
}
void card::cancel_card_target(card* pcard) {
auto cit = effect_target_cards.find(pcard);
if(cit != effect_target_cards.end()) {
effect_target_cards.erase(cit);
pcard->effect_target_owner.erase(this);
pduel->write_buffer8(MSG_CANCEL_TARGET);
pduel->write_buffer32(get_info_location());
pduel->write_buffer32(pcard->get_info_location());
}
}
void card::filter_effect(int32 code, effect_set* eset, uint8 sort) {
effect* peffect;
auto rg = single_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && (!(peffect->flag & EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect)))
eset->add_item(peffect);
}
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
rg = (*cit)->equip_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && is_affect_by_effect(peffect))
eset->add_item(peffect);
}
}
rg = pduel->game_field->effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (!(peffect->flag & EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available()
&& peffect->is_target(this) && is_affect_by_effect(peffect))
eset->add_item(peffect);
}
if(sort)
eset->sort();
}
void card::filter_single_effect(int32 code, effect_set* eset, uint8 sort) {
effect* peffect;
auto rg = single_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && !(peffect->flag & EFFECT_FLAG_SINGLE_RANGE))
eset->add_item(peffect);
}
if(sort)
eset->sort();
}
void card::filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort) {
auto rg = single_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first)
eset->add_item(rg.first->second);
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
rg = (*cit)->equip_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first)
eset->add_item(rg.first->second);
}
if(sort)
eset->sort();
}
void card::filter_immune_effect() {
effect* peffect;
immune_effect.clear();
auto rg = single_effect.equal_range(EFFECT_IMMUNE_EFFECT);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available())
immune_effect.add_item(peffect);
}
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
rg = (*cit)->equip_effect.equal_range(EFFECT_IMMUNE_EFFECT);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available())
immune_effect.add_item(peffect);
}
}
rg = pduel->game_field->effects.aura_effect.equal_range(EFFECT_IMMUNE_EFFECT);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_target(this) && peffect->is_available())
immune_effect.add_item(peffect);
}
immune_effect.sort();
}
void card::filter_disable_related_cards() {
for (auto it = indexer.begin(); it != indexer.end(); ++it) {
effect* peffect = it->first;
if (peffect->is_disable_related()) {
if (peffect->type & EFFECT_TYPE_FIELD)
pduel->game_field->update_disable_check_list(peffect);
else if ((peffect->type & EFFECT_TYPE_EQUIP) && equiping_target)
pduel->game_field->add_to_disable_check_list(equiping_target);
}
}
}
int32 card::filter_summon_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute) {
effect_set eset;
filter_effect(EFFECT_LIMIT_SUMMON_PROC, &eset);
if(eset.size()) {
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute)
&& pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]);
}
if(peset->size())
return -1;
return -2;
}
eset.clear();
filter_effect(EFFECT_SUMMON_PROC, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute)
&& pduel->game_field->is_player_can_summon(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]);
}
if(!pduel->game_field->is_player_can_summon(SUMMON_TYPE_NORMAL, playerid, this))
return FALSE;
int32 rcount = get_summon_tribute_count();
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(min > 0 && !pduel->game_field->is_player_can_summon(SUMMON_TYPE_ADVANCE, playerid, this))
return FALSE;
int32 fcount = pduel->game_field->get_useable_count(current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_TOFIELD);
if(max <= -fcount)
return FALSE;
if(min < -fcount + 1)
min = -fcount + 1;
if(max < min_tribute)
return FALSE;
if(min < min_tribute)
min = min_tribute;
if(min == 0)
return TRUE;
int32 m = pduel->game_field->get_summon_release_list(this, 0, 0, 0);
if(m >= min)
return TRUE;
return FALSE;
}
int32 card::filter_set_procedure(uint8 playerid, effect_set* peset, uint8 ignore_count, uint8 min_tribute) {
effect_set eset;
filter_effect(EFFECT_LIMIT_SET_PROC, &eset);
if(eset.size()) {
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute)
&& pduel->game_field->is_player_can_mset(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]);
}
if(peset->size())
return -1;
return -2;
}
eset.clear();
filter_effect(EFFECT_SET_PROC, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->check_count_limit(playerid) && is_summonable(eset[i], min_tribute)
&& pduel->game_field->is_player_can_mset(eset[i]->get_value(this), playerid, this))
peset->add_item(eset[i]);
}
if(!pduel->game_field->is_player_can_mset(SUMMON_TYPE_NORMAL, playerid, this))
return FALSE;
int32 rcount = get_set_tribute_count();
int32 min = rcount & 0xffff, max = (rcount >> 16) & 0xffff;
if(min > 0 && !pduel->game_field->is_player_can_mset(SUMMON_TYPE_ADVANCE, playerid, this))
return FALSE;
int32 fcount = pduel->game_field->get_useable_count(current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_TOFIELD);
if(max <= -fcount)
return FALSE;
if(min < -fcount + 1)
min = -fcount + 1;
if(max < min_tribute)
return FALSE;
if(min < min_tribute)
min = min_tribute;
if(min == 0)
return TRUE;
int32 m = pduel->game_field->get_summon_release_list(this, 0, 0, 0);
if(m >= min)
return TRUE;
return FALSE;
}
void card::filter_spsummon_procedure(uint8 playerid, effect_set* peset, uint32 summon_type) {
auto pr = field_effect.equal_range(EFFECT_SPSUMMON_PROC);
uint8 toplayer;
uint8 topos;
effect* peffect;
for(; pr.first != pr.second; ++pr.first) {
peffect = pr.first->second;
if(peffect->flag & EFFECT_FLAG_SPSUM_PARAM) {
topos = peffect->s_range;
if(peffect->o_range == 0)
toplayer = playerid;
else
toplayer = 1 - playerid;
} else {
topos = POS_FACEUP;
toplayer = playerid;
}
if(peffect->is_available() && peffect->check_count_limit(playerid) && is_summonable(peffect)
&& !pduel->game_field->check_unique_onfield(this, toplayer)) {
uint32 sumtype = peffect->get_value(this);
if((!summon_type || summon_type == sumtype)
&& pduel->game_field->is_player_can_spsummon(peffect, sumtype, topos, playerid, toplayer, this))
peset->add_item(peffect);
}
}
}
void card::filter_spsummon_procedure_g(uint8 playerid, effect_set* peset) {
auto pr = field_effect.equal_range(EFFECT_SPSUMMON_PROC_G);
for(; pr.first != pr.second; ++pr.first) {
effect* peffect = pr.first->second;
if(!peffect->is_available() || !peffect->check_count_limit(playerid))
continue;
if(current.controler != playerid && !(peffect->flag & EFFECT_FLAG_BOTH_SIDE))
continue;
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = peffect;
pduel->game_field->core.reason_player = this->current.controler;
pduel->game_field->save_lp_cost();
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
if(pduel->lua->check_condition(peffect->condition, 2))
peset->add_item(peffect);
pduel->game_field->restore_lp_cost();
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
}
}
effect* card::is_affected_by_effect(int32 code) {
effect* peffect;
auto rg = single_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && (!(peffect->flag & EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect)))
return peffect;
}
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
rg = (*cit)->equip_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && is_affect_by_effect(peffect))
return peffect;
}
}
rg = pduel->game_field->effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (!(peffect->flag & EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available()
&& peffect->is_target(this) && is_affect_by_effect(peffect))
return peffect;
}
return 0;
}
effect* card::is_affected_by_effect(int32 code, card* target) {
effect* peffect;
auto rg = single_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && (!(peffect->flag & EFFECT_FLAG_SINGLE_RANGE) || is_affect_by_effect(peffect))
&& peffect->get_value(target))
return peffect;
}
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
rg = (*cit)->equip_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (peffect->is_available() && is_affect_by_effect(peffect) && peffect->get_value(target))
return peffect;
}
}
rg = pduel->game_field->effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
peffect = rg.first->second;
if (!(peffect->flag & EFFECT_FLAG_PLAYER_TARGET) && peffect->is_available()
&& peffect->is_target(this) && is_affect_by_effect(peffect) && peffect->get_value(target))
return peffect;
}
return 0;
}
effect* card::check_control_effect() {
effect* ret_effect = 0;
for (auto cit = equiping_cards.begin(); cit != equiping_cards.end(); ++cit) {
auto rg = (*cit)->equip_effect.equal_range(EFFECT_SET_CONTROL);
for (; rg.first != rg.second; ++rg.first) {
effect* peffect = rg.first->second;
if(!ret_effect || peffect->id > ret_effect->id)
ret_effect = peffect;
}
}
auto rg = single_effect.equal_range(EFFECT_SET_CONTROL);
for (; rg.first != rg.second; ++rg.first) {
effect* peffect = rg.first->second;
if(!(peffect->flag & EFFECT_FLAG_SINGLE_RANGE))
continue;
if(!ret_effect || peffect->id > ret_effect->id)
ret_effect = peffect;
}
return ret_effect;
}
int32 card::fusion_check(group* fusion_m, card* cg, int32 chkf) {
auto ecit = single_effect.find(EFFECT_FUSION_MATERIAL);
if(ecit == single_effect.end())
return FALSE;
effect* peffect = ecit->second;
if(!peffect->condition)
return FALSE;
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(fusion_m, PARAM_TYPE_GROUP);
pduel->lua->add_param(cg, PARAM_TYPE_CARD);
pduel->lua->add_param(chkf, PARAM_TYPE_INT);
return pduel->lua->check_condition(peffect->condition, 4);
}
void card::fusion_select(uint8 playerid, group* fusion_m, card* cg, int32 chkf) {
effect* peffect = 0;
auto ecit = single_effect.find(EFFECT_FUSION_MATERIAL);
if(ecit != single_effect.end())
peffect = ecit->second;
pduel->game_field->add_process(PROCESSOR_SELECT_FUSION, 0, peffect, fusion_m, playerid + (chkf << 16), (ptr)cg);
}
int32 card::is_equipable(card* pcard) {
effect_set eset;
if(this == pcard || pcard->current.location != LOCATION_MZONE)
return FALSE;
filter_effect(EFFECT_EQUIP_LIMIT, &eset);
if(eset.size() == 0)
return FALSE;
for(int32 i = 0; i < eset.size(); ++i)
if(eset[i]->get_value(pcard))
return TRUE;
return FALSE;
}
int32 card::is_summonable() {
if(!(data.type & TYPE_MONSTER))
return FALSE;
return !is_affected_by_effect(EFFECT_UNSUMMONABLE_CARD);
}
int32 card::is_summonable(effect* peffect) {
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = peffect;
pduel->game_field->core.reason_player = this->current.controler;
pduel->game_field->save_lp_cost();
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
uint32 result = FALSE;
if(pduel->game_field->core.limit_tuner || pduel->game_field->core.limit_syn) {
pduel->lua->add_param(pduel->game_field->core.limit_tuner, PARAM_TYPE_CARD);
pduel->lua->add_param(pduel->game_field->core.limit_syn, PARAM_TYPE_GROUP);
if(pduel->lua->check_condition(peffect->condition, 4))
result = TRUE;
} else if(pduel->game_field->core.limit_xyz) {
pduel->lua->add_param(pduel->game_field->core.limit_xyz, PARAM_TYPE_GROUP);
if(pduel->lua->check_condition(peffect->condition, 3))
result = TRUE;
} else {
if(pduel->lua->check_condition(peffect->condition, 2))
result = TRUE;
}
pduel->game_field->restore_lp_cost();
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
return result;
}
int32 card::is_summonable(effect* peffect, uint8 min_tribute) {
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = peffect;
pduel->game_field->core.reason_player = this->current.controler;
pduel->game_field->save_lp_cost();
uint32 result = FALSE;
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(min_tribute, PARAM_TYPE_INT);
if(pduel->lua->check_condition(peffect->condition, 3))
result = TRUE;
pduel->game_field->restore_lp_cost();
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
return result;
}
int32 card::is_can_be_summoned(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) {
if(!is_summonable())
return FALSE;
if(pduel->game_field->check_unique_onfield(this, playerid))
return FALSE;
if(!ignore_count && (pduel->game_field->core.extra_summon[playerid] || !is_affected_by_effect(EFFECT_EXTRA_SUMMON_COUNT))
&& pduel->game_field->core.summon_count[playerid] >= pduel->game_field->get_summon_count_limit(playerid))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_SUMMON_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
if(current.location == LOCATION_MZONE) {
if(is_position(POS_FACEDOWN)
|| !is_affected_by_effect(EFFECT_DUAL_SUMMONABLE)
|| is_affected_by_effect(EFFECT_DUAL_STATUS)
|| !pduel->game_field->is_player_can_summon(SUMMON_TYPE_DUAL, playerid, this)
|| is_affected_by_effect(EFFECT_CANNOT_SUMMON)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
} else if(current.location == LOCATION_HAND) {
if(is_affected_by_effect(EFFECT_CANNOT_SUMMON)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
if(!ignore_count && !pduel->game_field->core.extra_summon[playerid]
&& pduel->game_field->core.summon_count[playerid] >= pduel->game_field->get_summon_count_limit(playerid)) {
effect* pextra = is_affected_by_effect(EFFECT_EXTRA_SUMMON_COUNT);
if(pextra && !(pextra->flag & EFFECT_FLAG_FUNC_VALUE)) {
int32 count = pextra->get_value();
if(min_tribute < count)
min_tribute = count;
}
}
effect_set proc;
int32 res = filter_summon_procedure(playerid, &proc, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !proc.size())
|| (peffect && (proc.size() == 0) && !pduel->game_field->is_player_can_summon(peffect->get_value(), playerid, this))) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
}
int32 card::get_summon_tribute_count() {
int32 min = 0, max = 0;
int32 minul = 0, maxul = 0;
int32 level = get_level();
if(level < 5)
return 0;
else if(level < 7)
min = max = 1;
else
min = max = 2;
effect_set eset;
filter_effect(EFFECT_DECREASE_TRIBUTE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
int32 dec = eset[i]->get_value(this);
if(!(eset[i]->flag & EFFECT_FLAG_COUNT_LIMIT)) {
if(minul < (dec & 0xffff))
minul = dec & 0xffff;
if(maxul < (dec >> 16))
maxul = dec >> 16;
} else if((eset[i]->reset_count & 0xf00) > 0) {
min -= dec & 0xffff;
max -= dec >> 16;
}
}
min -= minul;
max -= maxul;
if(min < 0) min = 0;
if(max < min) max = min;
return min + (max << 16);
}
int32 card::get_set_tribute_count() {
int32 min = 0, max = 0;
int32 level = get_level();
if(level < 5)
return 0;
else if(level < 7)
min = max = 1;
else
min = max = 2;
effect_set eset;
filter_effect(EFFECT_DECREASE_TRIBUTE_SET, &eset);
if(eset.size()) {
int32 dec = eset.get_last()->get_value(this);
min -= dec & 0xffff;
max -= dec >> 16;
}
if(min < 0) min = 0;
if(max < min) max = min;
return min + (max << 16);
}
int32 card::is_can_be_flip_summoned(uint8 playerid) {
if(is_status(STATUS_SUMMON_TURN) || is_status(STATUS_FLIP_SUMMON_TURN) || is_status(STATUS_SPSUMMON_TURN) || is_status(STATUS_FORM_CHANGED))
return FALSE;
if(announce_count > 0)
return FALSE;
if(current.location != LOCATION_MZONE)
return FALSE;
if(!(current.position & POS_FACEDOWN))
return FALSE;
if(pduel->game_field->check_unique_onfield(this, playerid))
return FALSE;
if(!pduel->game_field->is_player_can_flipsummon(playerid, this))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_FLIP_SUMMON))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_POSITION))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_FLIPSUMMON_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
}
int32 card::is_special_summonable(uint8 playerid, uint32 summon_type) {
if(!(data.type & TYPE_MONSTER))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_SPECIAL_SUMMON))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_SPSUMMON_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
eset.clear();
filter_spsummon_procedure(playerid, &eset, summon_type);
pduel->game_field->core.limit_tuner = 0;
pduel->game_field->core.limit_xyz = 0;
pduel->game_field->core.limit_syn = 0;
pduel->game_field->restore_lp_cost();
return eset.size();
}
int32 card::is_can_be_special_summoned(effect * reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer, uint8 nocheck, uint8 nolimit) {
if(current.location == LOCATION_MZONE)
return FALSE;
if(current.location == LOCATION_REMOVED && (current.position & POS_FACEDOWN))
return FALSE;
if(is_affected_by_effect(EFFECT_REVIVE_LIMIT) && !is_status(STATUS_PROC_COMPLETE)) {
if((!nolimit && (current.location & 0x38)) || (!nocheck && !nolimit && (current.location & 0x3)))
return FALSE;
if(!nolimit && (data.type & TYPE_PENDULUM) && current.location == LOCATION_EXTRA && (current.position & POS_FACEUP))
return FALSE;
}
//face-up pendulum xyz/syn, STATUS_PROC_COMPLETE
if((data.type & TYPE_PENDULUM) && current.location == LOCATION_EXTRA && (current.position & POS_FACEUP) &&
(sumtype == SUMMON_TYPE_SYNCHRO || sumtype == SUMMON_TYPE_XYZ))
return FALSE;
if(((sumpos & POS_FACEDOWN) == 0) && pduel->game_field->check_unique_onfield(this, toplayer))
return FALSE;
sumtype |= SUMMON_TYPE_SPECIAL;
if((sumplayer == 0 || sumplayer == 1) && !pduel->game_field->is_player_can_spsummon(reason_effect, sumtype, sumpos, sumplayer, toplayer, this))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_SPECIAL_SUMMON))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_SPSUMMON_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(sumplayer, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
if(!nocheck) {
eset.clear();
if(!(data.type & TYPE_MONSTER)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
filter_effect(EFFECT_SPSUMMON_CONDITION, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(reason_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(sumplayer, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
pduel->lua->add_param(sumpos, PARAM_TYPE_INT);
pduel->lua->add_param(toplayer, PARAM_TYPE_INT);
if(!eset[i]->check_value_condition(5)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
}
int32 card::is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute) {
if(!(data.type & TYPE_MONSTER))
return FALSE;
if(is_affected_by_effect(EFFECT_UNSUMMONABLE_CARD))
return FALSE;
if(current.location != LOCATION_HAND)
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_MSET))
return FALSE;
if(!ignore_count && (pduel->game_field->core.extra_summon[playerid] || !is_affected_by_effect(EFFECT_EXTRA_SET_COUNT))
&& pduel->game_field->core.summon_count[playerid] >= pduel->game_field->get_summon_count_limit(playerid))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_MSET_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
if(!ignore_count && !pduel->game_field->core.extra_summon[playerid]
&& pduel->game_field->core.summon_count[playerid] >= pduel->game_field->get_summon_count_limit(playerid)) {
effect* pextra = is_affected_by_effect(EFFECT_EXTRA_SET_COUNT);
if(pextra && !(pextra->flag & EFFECT_FLAG_FUNC_VALUE)) {
int32 count = pextra->get_value();
if(min_tribute < count)
min_tribute = count;
}
}
eset.clear();
int32 res = filter_set_procedure(playerid, &eset, ignore_count, min_tribute);
if((peffect && res < 0) || (!peffect && (!res || res == -2) && !eset.size())
|| (peffect && (eset.size() == 0) && !pduel->game_field->is_player_can_mset(peffect->get_value(), playerid, this))) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
pduel->game_field->restore_lp_cost();
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)
return FALSE;
if(data.type & TYPE_MONSTER && !is_affected_by_effect(EFFECT_MONSTER_SSET))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_SSET))
return FALSE;
if(!pduel->game_field->is_player_can_sset(playerid, this))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
filter_effect(EFFECT_SSET_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
}
int32 card::is_affect_by_effect(effect* peffect) {
if(is_status(STATUS_SUMMONING))
return FALSE;
if(!peffect || (peffect->flag & EFFECT_FLAG_IGNORE_IMMUNE))
return TRUE;
if(peffect->is_immuned(&immune_effect))
return FALSE;
return TRUE;
}
int32 card::is_destructable() {
if(overlay_target)
return FALSE;
if(current.location & (LOCATION_GRAVE + LOCATION_REMOVED))
return FALSE;
if(is_affected_by_effect(EFFECT_INDESTRUCTABLE))
return FALSE;
return TRUE;
}
int32 card::is_destructable_by_battle(card * pcard) {
if(is_affected_by_effect(EFFECT_INDESTRUCTABLE_BATTLE, pcard))
return FALSE;
return TRUE;
}
effect* card::check_indestructable_by_effect(effect* peffect, uint8 playerid) {
if(!peffect)
return 0;
effect_set eset;
filter_effect(EFFECT_INDESTRUCTABLE_EFFECT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
if(eset[i]->check_value_condition(3))
return eset[i];
}
return 0;
}
int32 card::is_destructable_by_effect(effect* peffect, uint8 playerid) {
return !check_indestructable_by_effect(peffect, playerid);
}
int32 card::is_removeable(uint8 playerid) {
if(!pduel->game_field->is_player_can_remove(playerid, this))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_REMOVE))
return FALSE;
return TRUE;
}
int32 card::is_removeable_as_cost(uint8 playerid) {
if(is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
return FALSE;
if(!pduel->game_field->is_player_can_remove(playerid, this))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_REMOVE))
return FALSE;
return TRUE;
}
int32 card::is_releasable_by_summon(uint8 playerid, card *pcard) {
if(is_status(STATUS_SUMMONING))
return FALSE;
if(overlay_target)
return FALSE;
if(current.location & (LOCATION_GRAVE + LOCATION_REMOVED))
return FALSE;
if(!pduel->game_field->is_player_can_release(playerid, this))
return FALSE;
if(is_affected_by_effect(EFFECT_UNRELEASABLE_SUM, pcard))
return FALSE;
if(pcard->is_affected_by_effect(EFFECT_TRIBUTE_LIMIT, this))
return FALSE;
return TRUE;
}
int32 card::is_releasable_by_nonsummon(uint8 playerid) {
if(is_status(STATUS_SUMMONING))
return FALSE;
if(overlay_target)
return FALSE;
if(current.location & (LOCATION_GRAVE + LOCATION_REMOVED))
return FALSE;
if((current.location == LOCATION_HAND) && (data.type & (TYPE_SPELL | TYPE_TRAP)))
return FALSE;
if(!pduel->game_field->is_player_can_release(playerid, this))
return FALSE;
if(is_affected_by_effect(EFFECT_UNRELEASABLE_NONSUM))
return FALSE;
return TRUE;
}
int32 card::is_releasable_by_effect(uint8 playerid, effect* peffect) {
if(!peffect)
return TRUE;
effect_set eset;
filter_effect(EFFECT_UNRELEASABLE_EFFECT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
if(eset[i]->check_value_condition(3))
return FALSE;
}
return TRUE;
}
int32 card::is_capable_send_to_grave(uint8 playerid) {
if(is_affected_by_effect(EFFECT_CANNOT_TO_GRAVE))
return FALSE;
if(!pduel->game_field->is_player_can_send_to_grave(playerid, this))
return FALSE;
return TRUE;
}
int32 card::is_capable_send_to_hand(uint8 playerid) {
if(is_status(STATUS_LEAVE_CONFIRMED))
return FALSE;
if((current.location == LOCATION_EXTRA) && (data.type & (TYPE_FUSION + TYPE_SYNCHRO + TYPE_XYZ)))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_TO_HAND))
return FALSE;
if(!pduel->game_field->is_player_can_send_to_hand(playerid, this))
return FALSE;
return TRUE;
}
int32 card::is_capable_send_to_deck(uint8 playerid) {
if(is_status(STATUS_LEAVE_CONFIRMED))
return FALSE;
if((current.location == LOCATION_EXTRA) && (data.type & (TYPE_FUSION + TYPE_SYNCHRO + TYPE_XYZ)))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_TO_DECK))
return FALSE;
if(!pduel->game_field->is_player_can_send_to_deck(playerid, this))
return FALSE;
return TRUE;
}
int32 card::is_capable_send_to_extra(uint8 playerid) {
if(!(data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ | TYPE_PENDULUM)))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_TO_DECK))
return FALSE;
if(!pduel->game_field->is_player_can_send_to_deck(playerid, this))
return FALSE;
return TRUE;
}
int32 card::is_capable_cost_to_grave(uint8 playerid) {
uint32 redirect = 0;
uint32 dest = LOCATION_GRAVE;
if(data.type & TYPE_TOKEN)
return FALSE;
if((data.type & TYPE_PENDULUM) && (current.location & LOCATION_ONFIELD) && !is_affected_by_effect(EFFECT_CANNOT_TO_DECK))
return FALSE;
if(current.location == LOCATION_GRAVE)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
return FALSE;
if(!is_capable_send_to_grave(playerid))
return FALSE;
uint32 op_param = operation_param;
operation_param = dest << 8;
if(current.location & LOCATION_ONFIELD)
redirect = leave_field_redirect(REASON_COST) & 0xffff;
if(redirect) dest = redirect;
redirect = destination_redirect(dest, REASON_COST) & 0xffff;
if(redirect) dest = redirect;
operation_param = op_param;
if(dest != LOCATION_GRAVE)
return FALSE;
return TRUE;
}
int32 card::is_capable_cost_to_hand(uint8 playerid) {
uint32 redirect = 0;
uint32 dest = LOCATION_HAND;
if(data.type & (TYPE_TOKEN | TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ))
return FALSE;
if(current.location == LOCATION_HAND)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
return FALSE;
if(!is_capable_send_to_hand(playerid))
return FALSE;
uint32 op_param = operation_param;
operation_param = dest << 8;
if(current.location & LOCATION_ONFIELD)
redirect = leave_field_redirect(REASON_COST) & 0xffff;
if(redirect) dest = redirect;
redirect = destination_redirect(dest, REASON_COST) & 0xffff;
if(redirect) dest = redirect;
operation_param = op_param;
if(dest != LOCATION_HAND)
return FALSE;
return TRUE;
}
int32 card::is_capable_cost_to_deck(uint8 playerid) {
uint32 redirect = 0;
uint32 dest = LOCATION_DECK;
if(data.type & (TYPE_TOKEN | TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ))
return FALSE;
if(current.location == LOCATION_DECK)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
return FALSE;
if(!is_capable_send_to_deck(playerid))
return FALSE;
uint32 op_param = operation_param;
operation_param = dest << 8;
if(current.location & LOCATION_ONFIELD)
redirect = leave_field_redirect(REASON_COST) & 0xffff;
if(redirect) dest = redirect;
redirect = destination_redirect(dest, REASON_COST) & 0xffff;
if(redirect) dest = redirect;
operation_param = op_param;
if(dest != LOCATION_DECK)
return FALSE;
return TRUE;
}
int32 card::is_capable_cost_to_extra(uint8 playerid) {
uint32 redirect = 0;
uint32 dest = LOCATION_DECK;
if(!(data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ)))
return FALSE;
if(current.location == LOCATION_EXTRA)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
return FALSE;
if(!is_capable_send_to_deck(playerid))
return FALSE;
uint32 op_param = operation_param;
operation_param = dest << 8;
if(current.location & LOCATION_ONFIELD)
redirect = leave_field_redirect(REASON_COST) & 0xffff;
if(redirect) dest = redirect;
redirect = destination_redirect(dest, REASON_COST) & 0xffff;
if(redirect) dest = redirect;
operation_param = op_param;
if(dest != LOCATION_DECK)
return FALSE;
return TRUE;
}
int32 card::is_capable_attack() {
if(!is_position(POS_FACEUP_ATTACK) && !(is_position(POS_FACEUP_DEFENCE) && is_affected_by_effect(EFFECT_DEFENCE_ATTACK)))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_ATTACK))
return FALSE;
if(is_affected_by_effect(EFFECT_ATTACK_DISABLED))
return FALSE;
if(pduel->game_field->is_player_affected_by_effect(pduel->game_field->infos.turn_player, EFFECT_SKIP_BP))
return FALSE;
return TRUE;
}
int32 card::is_capable_attack_announce(uint8 playerid) {
if(!is_capable_attack())
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_ATTACK_ANNOUNCE))
return FALSE;
pduel->game_field->save_lp_cost();
effect_set eset;
pduel->game_field->filter_player_effect(playerid, EFFECT_ATTACK_COST, &eset, FALSE);
filter_effect(EFFECT_ATTACK_COST, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3)) {
pduel->game_field->restore_lp_cost();
return FALSE;
}
}
pduel->game_field->restore_lp_cost();
return TRUE;
}
int32 card::is_capable_change_position(uint8 playerid) {
if(is_status(STATUS_SUMMON_TURN) || is_status(STATUS_FLIP_SUMMON_TURN) || is_status(STATUS_SPSUMMON_TURN) || is_status(STATUS_FORM_CHANGED))
return FALSE;
if(announce_count > 0)
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_POSITION))
return FALSE;
if(pduel->game_field->is_player_affected_by_effect(playerid, EFFECT_CANNOT_CHANGE_POSITION))
return FALSE;
return TRUE;
}
int32 card::is_capable_turn_set(uint8 playerid) {
if(data.type & TYPE_TOKEN)
return FALSE;
if(is_position(POS_FACEDOWN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_TURN_SET))
return FALSE;
if(pduel->game_field->is_player_affected_by_effect(playerid, EFFECT_CANNOT_TURN_SET))
return FALSE;
return TRUE;
}
int32 card::is_capable_change_control() {
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_CONTROL))
return FALSE;
return TRUE;
}
int32 card::is_control_can_be_changed() {
if(current.controler == PLAYER_NONE)
return FALSE;
if(current.location != LOCATION_MZONE)
return FALSE;
if(pduel->game_field->get_useable_count(1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL) <= 0)
return FALSE;
if((data.type & TYPE_TRAPMONSTER) && pduel->game_field->get_useable_count(1 - current.controler, LOCATION_MZONE, current.controler, LOCATION_REASON_CONTROL) <= 0)
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_CHANGE_CONTROL))
return FALSE;
return TRUE;
}
int32 card::is_capable_be_battle_target(card* pcard) {
if(is_affected_by_effect(EFFECT_CANNOT_BE_BATTLE_TARGET, pcard))
return FALSE;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SELECT_BATTLE_TARGET, this))
return FALSE;
if(is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
return FALSE;
return TRUE;
}
int32 card::is_capable_be_effect_target(effect* peffect, uint8 playerid) {
if(is_status(STATUS_SUMMONING) || is_status(STATUS_BATTLE_DESTROYED))
return FALSE;
effect_set eset;
filter_effect(EFFECT_CANNOT_BE_EFFECT_TARGET, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(eset[i]->get_value(peffect, 1))
return FALSE;
}
eset.clear();
peffect->handler->filter_effect(EFFECT_CANNOT_SELECT_EFFECT_TARGET, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(this, PARAM_TYPE_CARD);
if(eset[i]->get_value(peffect, 1))
return FALSE;
}
return TRUE;
}
int32 card::is_can_be_fusion_material(uint8 ignore_mon) {
if(!ignore_mon && !(get_type() & TYPE_MONSTER))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(is_affected_by_effect(EFFECT_CANNOT_BE_FUSION_MATERIAL))
return FALSE;
return TRUE;
}
int32 card::is_can_be_synchro_material(card* scard, card* tuner) {
if(data.type & TYPE_XYZ)
return FALSE;
if(!(get_type() & TYPE_MONSTER))
return FALSE;
if(scard && current.location == LOCATION_MZONE && current.controler != scard->current.controler && !is_affected_by_effect(EFFECT_SYNCHRO_MATERIAL))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
//special fix for scrap chimera, not perfect yet
if(tuner && (pduel->game_field->core.global_flag & GLOBALFLAG_SCRAP_CHIMERA)) {
if(is_affected_by_effect(EFFECT_SCRAP_CHIMERA, tuner))
return false;
}
effect_set eset;
filter_effect(EFFECT_CANNOT_BE_SYNCHRO_MATERIAL, &eset);
for(int32 i = 0; i < eset.size(); ++i)
if(eset[i]->get_value(scard))
return FALSE;
return TRUE;
}
int32 card::is_can_be_ritual_material(card* scard) {
if(!(get_type() & TYPE_MONSTER))
return FALSE;
if(current.location == LOCATION_GRAVE) {
effect_set eset;
filter_effect(EFFECT_EXTRA_RITUAL_MATERIAL, &eset);
for(int32 i = 0; i < eset.size(); ++i)
if(eset[i]->get_value(scard))
return TRUE;
return FALSE;
}
return TRUE;
}
int32 card::is_can_be_xyz_material(card* scard) {
if(data.type & TYPE_TOKEN)
return FALSE;
if(!(get_type() & TYPE_MONSTER))
return FALSE;
if(is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
effect_set eset;
filter_effect(EFFECT_CANNOT_BE_XYZ_MATERIAL, &eset);
for(int32 i = 0; i < eset.size(); ++i)
if(eset[i]->get_value(scard))
return FALSE;
return TRUE;
}
/*
* card.h
*
* Created on: 2010-4-8
* Author: Argon
*/
#ifndef CARD_H_
#define CARD_H_
#include "common.h"
#include "effectset.h"
#include <set>
#include <map>
class card;
class duel;
class effect;
class group;
struct card_data {
uint32 code;
uint32 alias;
uint64 setcode;
uint32 type;
uint32 level;
uint32 attribute;
uint32 race;
int32 attack;
int32 defence;
uint32 lscale;
uint32 rscale;
};
struct card_state {
uint32 code;
uint32 code2;
uint32 type;
uint32 level;
uint32 rank;
uint32 lscale;
uint32 rscale;
uint32 attribute;
uint32 race;
int32 attack;
int32 defence;
int32 base_attack;
int32 base_defence;
uint8 controler;
uint8 location;
uint8 sequence;
uint8 position;
uint32 reason;
card* reason_card;
uint8 reason_player;
effect* reason_effect;
};
struct query_cache {
uint32 code;
uint32 alias;
uint32 type;
uint32 level;
uint32 rank;
uint32 attribute;
uint32 race;
int32 attack;
int32 defence;
int32 base_attack;
int32 base_defence;
uint32 reason;
int32 is_public;
int32 is_disabled;
uint32 lscale;
uint32 rscale;
};
class card {
public:
typedef std::vector<card*> card_vector;
typedef std::multimap<uint32, effect*> effect_container;
typedef std::set<card*, card_sort> card_set;
typedef std::map<effect*, effect_container::iterator> effect_indexer;
typedef std::map<effect*, uint32> effect_relation;
typedef std::map<card*, uint32> relation_map;
typedef std::map<uint16, uint16> counter_map;
typedef std::map<uint16, card*> attacker_map;
int32 scrtype;
int32 ref_handle;
duel* pduel;
card_data data;
card_state previous;
card_state temp;
card_state current;
query_cache q_cache;
uint8 owner;
uint8 summon_player;
uint32 summon_info;
uint32 status;
uint32 operation_param;
uint8 announce_count;
uint8 attacked_count;
uint8 attack_all_target;
uint16 cardid;
uint32 fieldid;
uint32 fieldid_r;
uint16 turnid;
uint16 turn_counter;
uint8 unique_pos[2];
uint16 unique_uid;
uint32 unique_code;
uint32 spsummon_code;
uint16 spsummon_counter[2];
uint16 spsummon_counter_rst[2];
uint8 assume_type;
uint32 assume_value;
effect* unique_effect;
card* equiping_target;
card* pre_equip_target;
card* overlay_target;
relation_map relations;
counter_map counters;
attacker_map announced_cards;
attacker_map attacked_cards;
attacker_map battled_cards;
card_set equiping_cards;
card_set material_cards;
card_set effect_target_owner;
card_set effect_target_cards;
card_vector xyz_materials;
effect_container single_effect;
effect_container field_effect;
effect_container equip_effect;
effect_indexer indexer;
effect_relation relate_effect;
effect_set_v immune_effect;
explicit card(duel* pd);
~card();
static bool card_operation_sort(card* c1, card* c2);
uint32 get_infos(byte* buf, int32 query_flag, int32 use_cache = TRUE);
uint32 get_info_location();
uint32 get_code();
uint32 get_another_code();
int32 is_set_card(uint32 set_code);
int32 is_pre_set_card(uint32 set_code);
uint32 get_type();
int32 get_base_attack(uint8 swap = FALSE);
int32 get_attack();
int32 get_base_defence(uint8 swap = FALSE);
int32 get_defence();
void calc_attack_defence(int32 *patk, int32 *pdef);
uint32 get_level();
uint32 get_rank();
uint32 get_synchro_level(card* pcard);
uint32 get_ritual_level(card* pcard);
uint32 check_xyz_level(card* pcard, uint32 lv);
uint32 get_attribute();
uint32 get_race();
uint32 get_lscale();
uint32 get_rscale();
int32 is_position(int32 pos);
void set_status(uint32 status, int32 enabled);
int32 get_status(uint32 status);
int32 is_status(uint32 status);
void equip(card *target, uint32 send_msg = TRUE);
void unequip();
int32 get_union_count();
void xyz_overlay(card_set* materials);
void xyz_add(card* mat, card_set* des);
void xyz_remove(card* mat);
void apply_field_effect();
void cancel_field_effect();
void enable_field_effect(int32 enabled);
int32 add_effect(effect* peffect);
void remove_effect(effect* peffect);
void remove_effect(effect* peffect, effect_container::iterator it);
int32 copy_effect(uint32 code, uint32 reset, uint32 count);
void reset(uint32 id, uint32 reset_type);
void reset_effect_count();
int32 refresh_disable_status();
uint8 refresh_control_status();
void count_turn(uint16 ct);
void create_relation(card* target, uint32 reset);
void create_relation(effect* peffect);
int32 is_has_relation(card* target);
int32 is_has_relation(effect* peffect);
void release_relation(card* target);
void release_relation(effect* peffect);
int32 leave_field_redirect(uint32 reason);
int32 destination_redirect(uint8 destination, uint32 reason);
int32 add_counter(uint8 playerid, uint16 countertype, uint16 count);
int32 remove_counter(uint16 countertype, uint16 count);
int32 is_can_add_counter(uint8 playerid, uint16 countertype, uint16 count);
int32 get_counter(uint16 countertype);
void set_material(card_set* materials);
void add_card_target(card* pcard);
void cancel_card_target(card* pcard);
void filter_effect(int32 code, effect_set* eset, uint8 sort = TRUE);
void filter_single_effect(int32 code, effect_set* eset, uint8 sort = TRUE);
void filter_single_continuous_effect(int32 code, effect_set* eset, uint8 sort = TRUE);
void filter_immune_effect();
void filter_disable_related_cards();
int32 filter_summon_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute);
int32 filter_set_procedure(uint8 playerid, effect_set* eset, uint8 ignore_count, uint8 min_tribute);
void filter_spsummon_procedure(uint8 playerid, effect_set* eset, uint32 summon_type);
void filter_spsummon_procedure_g(uint8 playerid, effect_set* eset);
effect* is_affected_by_effect(int32 code);
effect* is_affected_by_effect(int32 code, card* target);
effect* check_control_effect();
int32 fusion_check(group* fusion_m, card* cg, int32 chkf);
void fusion_select(uint8 playerid, group* fusion_m, card* cg, int32 chkf);
int32 is_equipable(card* pcard);
int32 is_summonable();
int32 is_summonable(effect* peffect);
int32 is_summonable(effect* peffect, uint8 min_tribute);
int32 is_can_be_summoned(uint8 playerid, uint8 ingore_count, effect* peffect, uint8 min_tribute);
int32 get_summon_tribute_count();
int32 get_set_tribute_count();
int32 is_can_be_flip_summoned(uint8 playerid);
int32 is_special_summonable(uint8 playerid, uint32 summon_type);
int32 is_can_be_special_summoned(effect* reason_effect, uint32 sumtype, uint8 sumpos, uint8 sumplayer, uint8 toplayer, uint8 nocheck, uint8 nolimit);
int32 is_setable_mzone(uint8 playerid, uint8 ignore_count, effect* peffect, uint8 min_tribute);
int32 is_setable_szone(uint8 playerid, uint8 ignore_fd = 0);
int32 is_affect_by_effect(effect* peffect);
int32 is_destructable();
int32 is_destructable_by_battle(card* pcard);
effect* check_indestructable_by_effect(effect* peffect, uint8 playerid);
int32 is_destructable_by_effect(effect* peffect, uint8 playerid);
int32 is_removeable(uint8 playerid);
int32 is_removeable_as_cost(uint8 playerid);
int32 is_releasable_by_summon(uint8 playerid, card* pcard);
int32 is_releasable_by_nonsummon(uint8 playerid);
int32 is_releasable_by_effect(uint8 playerid, effect* peffect);
int32 is_capable_send_to_grave(uint8 playerid);
int32 is_capable_send_to_hand(uint8 playerid);
int32 is_capable_send_to_deck(uint8 playerid);
int32 is_capable_send_to_extra(uint8 playerid);
int32 is_capable_cost_to_grave(uint8 playerid);
int32 is_capable_cost_to_hand(uint8 playerid);
int32 is_capable_cost_to_deck(uint8 playerid);
int32 is_capable_cost_to_extra(uint8 playerid);
int32 is_capable_attack();
int32 is_capable_attack_announce(uint8 playerid);
int32 is_capable_change_position(uint8 playerid);
int32 is_capable_turn_set(uint8 playerid);
int32 is_capable_change_control();
int32 is_control_can_be_changed();
int32 is_capable_be_battle_target(card* pcard);
int32 is_capable_be_effect_target(effect* peffect, uint8 playerid);
int32 is_can_be_fusion_material(uint8 ignore_mon = FALSE);
int32 is_can_be_synchro_material(card* scard, card* tuner = 0);
int32 is_can_be_ritual_material(card* scard);
int32 is_can_be_xyz_material(card* scard);
};
//Locations
#define LOCATION_DECK 0x01 //
#define LOCATION_HAND 0x02 //
#define LOCATION_MZONE 0x04 //
#define LOCATION_SZONE 0x08 //
#define LOCATION_GRAVE 0x10 //
#define LOCATION_REMOVED 0x20 //
#define LOCATION_EXTRA 0x40 //
#define LOCATION_OVERLAY 0x80 //
#define LOCATION_ONFIELD 0x0c //
#define LOCATION_FZONE 0x100 //
#define LOCATION_PZONE 0x200 //
//Positions
#define POS_FACEUP_ATTACK 0x1
#define POS_FACEDOWN_ATTACK 0x2
#define POS_FACEUP_DEFENCE 0x4
#define POS_FACEDOWN_DEFENCE 0x8
#define POS_FACEUP 0x5
#define POS_FACEDOWN 0xa
#define POS_ATTACK 0x3
#define POS_DEFENCE 0xc
#define NO_FLIP_EFFECT 0x10000
//Types
#define TYPE_MONSTER 0x1 //
#define TYPE_SPELL 0x2 //
#define TYPE_TRAP 0x4 //
#define TYPE_NORMAL 0x10 //
#define TYPE_EFFECT 0x20 //
#define TYPE_FUSION 0x40 //
#define TYPE_RITUAL 0x80 //
#define TYPE_TRAPMONSTER 0x100 //
#define TYPE_SPIRIT 0x200 //
#define TYPE_UNION 0x400 //
#define TYPE_DUAL 0x800 //
#define TYPE_TUNER 0x1000 //
#define TYPE_SYNCHRO 0x2000 //
#define TYPE_TOKEN 0x4000 //
#define TYPE_QUICKPLAY 0x10000 //
#define TYPE_CONTINUOUS 0x20000 //
#define TYPE_EQUIP 0x40000 //
#define TYPE_FIELD 0x80000 //
#define TYPE_COUNTER 0x100000 //
#define TYPE_FLIP 0x200000 //
#define TYPE_TOON 0x400000 //
#define TYPE_XYZ 0x800000 //
#define TYPE_PENDULUM 0x1000000 //
//Attributes
#define ATTRIBUTE_EARTH 0x01 //
#define ATTRIBUTE_WATER 0x02 //
#define ATTRIBUTE_FIRE 0x04 //
#define ATTRIBUTE_WIND 0x08 //
#define ATTRIBUTE_LIGHT 0x10 //
#define ATTRIBUTE_DARK 0x20 //
#define ATTRIBUTE_DEVINE 0x40 //
//Races
#define RACE_WARRIOR 0x1 //
#define RACE_SPELLCASTER 0x2 //
#define RACE_FAIRY 0x4 //
#define RACE_FIEND 0x8 //
#define RACE_ZOMBIE 0x10 //
#define RACE_MACHINE 0x20 //
#define RACE_AQUA 0x40 //
#define RACE_PYRO 0x80 //
#define RACE_ROCK 0x100 //
#define RACE_WINDBEAST 0x200 //
#define RACE_PLANT 0x400 //
#define RACE_INSECT 0x800 //
#define RACE_THUNDER 0x1000 //
#define RACE_DRAGON 0x2000 //
#define RACE_BEAST 0x4000 //
#define RACE_BEASTWARRIOR 0x8000 //
#define RACE_DINOSAUR 0x10000 //
#define RACE_FISH 0x20000 //
#define RACE_SEASERPENT 0x40000 //
#define RACE_REPTILE 0x80000 //
#define RACE_PSYCHO 0x100000 //
#define RACE_DEVINE 0x200000 //
#define RACE_CREATORGOD 0x400000 //
#define RACE_PHANTOMDRAGON 0x800000 //
//Reason
#define REASON_DESTROY 0x1 //
#define REASON_RELEASE 0x2 //
#define REASON_TEMPORARY 0x4 //
#define REASON_MATERIAL 0x8 //
#define REASON_SUMMON 0x10 //
#define REASON_BATTLE 0x20 //
#define REASON_EFFECT 0x40 //
#define REASON_COST 0x80 //
#define REASON_ADJUST 0x100 //
#define REASON_LOST_TARGET 0x200 //
#define REASON_RULE 0x400 //
#define REASON_SPSUMMON 0x800 //
#define REASON_DISSUMMON 0x1000 //
#define REASON_FLIP 0x2000 //
#define REASON_DISCARD 0x4000 //
#define REASON_RDAMAGE 0x8000 //
#define REASON_RRECOVER 0x10000 //
#define REASON_RETURN 0x20000 //
#define REASON_FUSION 0x40000 //
#define REASON_SYNCHRO 0x80000 //
#define REASON_RITUAL 0x100000 //
#define REASON_XYZ 0x200000 //
#define REASON_REPLACE 0x1000000 //
#define REASON_DRAW 0x2000000 //
#define REASON_REDIRECT 0x4000000 //
//Summon Type
#define SUMMON_TYPE_NORMAL 0x10000000
#define SUMMON_TYPE_ADVANCE 0x11000000
#define SUMMON_TYPE_DUAL 0x12000000
#define SUMMON_TYPE_FLIP 0x20000000
#define SUMMON_TYPE_SPECIAL 0x40000000
#define SUMMON_TYPE_FUSION 0x43000000
#define SUMMON_TYPE_RITUAL 0x45000000
#define SUMMON_TYPE_SYNCHRO 0x46000000
#define SUMMON_TYPE_XYZ 0x49000000
#define SUMMON_TYPE_PENDULUM 0x4a000000
//Status
#define STATUS_DISABLED 0x0001 //
#define STATUS_TO_ENABLE 0x0002 //
#define STATUS_TO_DISABLE 0x0004 //
#define STATUS_PROC_COMPLETE 0x0008 //
#define STATUS_SET_TURN 0x0010 //
#define STATUS_NO_LEVEL 0x0020 //
#define STATUS_REVIVE_LIMIT 0x0040 //
#define STATUS_SPSUMMON_STEP 0x0080 //
#define STATUS_FORM_CHANGED 0x0100 //
#define STATUS_SUMMONING 0x0200 //
#define STATUS_EFFECT_ENABLED 0x0400 //
#define STATUS_SUMMON_TURN 0x0800 //
#define STATUS_DESTROY_CONFIRMED 0x1000 //
#define STATUS_LEAVE_CONFIRMED 0x2000 //
#define STATUS_BATTLE_DESTROYED 0x4000 //
#define STATUS_COPYING_EFFECT 0x8000 //
#define STATUS_CHAINING 0x10000 //
#define STATUS_SUMMON_DISABLED 0x20000 //
#define STATUS_ACTIVATE_DISABLED 0x40000 //
#define STATUS_UNSUMMONABLE_CARD 0x80000 //
#define STATUS_UNION 0x100000
#define STATUS_ATTACK_CANCELED 0x200000
#define STATUS_INITIALIZING 0x400000
#define STATUS_ACTIVATED 0x800000
#define STATUS_JUST_POS 0x1000000
#define STATUS_CONTINUOUS_POS 0x2000000
#define STATUS_IS_PUBLIC 0x4000000
#define STATUS_ACT_FROM_HAND 0x8000000
#define STATUS_OPPO_BATTLE 0x10000000
#define STATUS_FLIP_SUMMON_TURN 0x20000000
#define STATUS_SPSUMMON_TURN 0x40000000
//Counter
#define COUNTER_NEED_PERMIT 0x1000
#define COUNTER_NEED_ENABLE 0x2000
//Query list
#define QUERY_CODE 0x1
#define QUERY_POSITION 0x2
#define QUERY_ALIAS 0x4
#define QUERY_TYPE 0x8
#define QUERY_LEVEL 0x10
#define QUERY_RANK 0x20
#define QUERY_ATTRIBUTE 0x40
#define QUERY_RACE 0x80
#define QUERY_ATTACK 0x100
#define QUERY_DEFENCE 0x200
#define QUERY_BASE_ATTACK 0x400
#define QUERY_BASE_DEFENCE 0x800
#define QUERY_REASON 0x1000
#define QUERY_REASON_CARD 0x2000
#define QUERY_EQUIP_CARD 0x4000
#define QUERY_TARGET_CARD 0x8000
#define QUERY_OVERLAY_CARD 0x10000
#define QUERY_COUNTERS 0x20000
#define QUERY_OWNER 0x40000
#define QUERY_IS_DISABLED 0x80000
#define QUERY_IS_PUBLIC 0x100000
#define QUERY_LSCALE 0x200000
#define QUERY_RSCALE 0x400000
#define ASSUME_CODE 1
#define ASSUME_TYPE 2
#define ASSUME_LEVEL 3
#define ASSUME_RANK 4
#define ASSUME_ATTRIBUTE 5
#define ASSUME_RACE 6
#define ASSUME_ATTACK 7
#define ASSUME_DEFENCE 8
#endif /* CARD_H_ */
/*
* common.h
*
* Created on: 2009-1-7
* Author: Argon.Sun
*/
#ifndef COMMON_H_
#define COMMON_H_
#ifdef _MSC_VER
#pragma warning(disable: 4244)
#endif
typedef unsigned long uptr;
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef unsigned char byte;
typedef long ptr;
typedef long long int64;
typedef int int32;
typedef short int16;
typedef char int8;
typedef int BOOL;
#define MATCH_ALL(x,y) (((x)&(y))==(y))
#define MATCH_ANY(x,y) ((x)&(y))
#define ADD_BIT(x,y) ((x)|=(y))
#define REMOVE_BIT(x,y) ((x)&=~(y))
#define OPERATION_SUCCESS 1
#define OPERATION_FAIL 0
#define OPERATION_CANCELED -1
#define TRUE 1
#define FALSE 0
#ifndef NULL
#define NULL 0
#endif
struct card_sort {
bool operator()(void* const & c1, void* const & c2) const;
};
#endif /* COMMON_H_ */
/*
* duel.cpp
*
* Created on: 2010-5-2
* Author: Argon
*/
#include "duel.h"
#include "interpreter.h"
#include "field.h"
#include "card.h"
#include "effect.h"
#include "group.h"
#include "ocgapi.h"
#include <memory.h>
duel::duel() {
lua = new interpreter(this);
game_field = new field(this);
game_field->temp_card = new_card(0);
clear_buffer();
}
duel::~duel() {
for(std::set<card*>::iterator cit = cards.begin(); cit != cards.end(); ++cit)
delete *cit;
for(std::set<group*>::iterator git = groups.begin(); git != groups.end(); ++git)
delete *git;
for(std::set<effect*>::iterator eit = effects.begin(); eit != effects.end(); ++eit)
delete *eit;
delete lua;
delete game_field;
}
void duel::clear() {
for(std::set<card*>::iterator cit = cards.begin(); cit != cards.end(); ++cit)
delete *cit;
for(std::set<group*>::iterator git = groups.begin(); git != groups.end(); ++git)
delete *git;
for(std::set<effect*>::iterator eit = effects.begin(); eit != effects.end(); ++eit)
delete *eit;
delete game_field;
cards.clear();
groups.clear();
effects.clear();
game_field = new field(this);
game_field->temp_card = new_card(0);
}
card* duel::new_card(uint32 code) {
card* pcard = new card(this);
cards.insert(pcard);
if(code)
::read_card(code, &(pcard->data));
pcard->data.code = code;
lua->register_card(pcard);
return pcard;
}
group* duel::register_group(group* pgroup) {
groups.insert(pgroup);
if(lua->call_depth)
sgroups.insert(pgroup);
lua->register_group(pgroup);
return pgroup;
}
group* duel::new_group() {
group* pgroup = new group(this);
return register_group(pgroup);
}
group* duel::new_group(card* pcard) {
group* pgroup = new group(this, pcard);
return register_group(pgroup);
}
group* duel::new_group(const card_set& cset) {
group* pgroup = new group(this, cset);
return register_group(pgroup);
}
effect* duel::new_effect() {
effect* peffect = new effect(this);
effects.insert(peffect);
lua->register_effect(peffect);
return peffect;
}
void duel::delete_card(card* pcard) {
cards.erase(pcard);
delete pcard;
}
void duel::delete_group(group* pgroup) {
lua->unregister_group(pgroup);
groups.erase(pgroup);
sgroups.erase(pgroup);
delete pgroup;
}
void duel::delete_effect(effect* peffect) {
lua->unregister_effect(peffect);
effects.erase(peffect);
delete peffect;
}
int32 duel::read_buffer(byte* buf) {
memcpy(buf, buffer, bufferlen);
return bufferlen;
}
void duel::release_script_group() {
std::set<group*>::iterator sit;
for(sit = sgroups.begin(); sit != sgroups.end(); ++sit) {
group* pgroup = *sit;
if(pgroup->is_readonly == 0) {
lua->unregister_group(pgroup);
groups.erase(pgroup);
delete pgroup;
}
}
sgroups.clear();
}
void duel::restore_assumes() {
std::set<card*>::iterator sit;
for(sit = assumes.begin(); sit != assumes.end(); ++sit)
(*sit)->assume_type = 0;
assumes.clear();
}
void duel::write_buffer32(uint32 value) {
*((uint32*)bufferp) = value;
bufferp += 4;
bufferlen += 4;
}
void duel::write_buffer16(uint16 value) {
*((uint16*)bufferp) = value;
bufferp += 2;
bufferlen += 2;
}
void duel::write_buffer8(uint8 value) {
*((uint8*)bufferp) = value;
bufferp += 1;
bufferlen += 1;
}
void duel::clear_buffer() {
bufferlen = 0;
bufferp = buffer;
}
void duel::set_responsei(uint32 resp) {
game_field->returns.ivalue[0] = resp;
}
void duel::set_responseb(byte* resp) {
memcpy(game_field->returns.bvalue, resp, 64);
}
int32 duel::get_next_integer(int32 l, int32 h) {
return (int32) (random.real() * (h - l + 1)) + l;
}
/*
* duel.h
*
* Created on: 2010-4-8
* Author: Argon
*/
#ifndef DUEL_H_
#define DUEL_H_
#include "common.h"
#include "mtrandom.h"
#include <set>
class card;
class group;
class effect;
class field;
class interpreter;
struct duel_arg {
int16 start_lp;
int8 start_hand;
int8 draw_count;
};
class duel {
public:
typedef std::set<card*, card_sort> card_set;
char strbuffer[256];
byte buffer[0x1000];
uint32 bufferlen;
byte* bufferp;
interpreter* lua;
field* game_field;
mtrandom random;
std::set<card*> cards;
std::set<card*> assumes;
std::set<group*> groups;
std::set<group*> sgroups;
std::set<effect*> effects;
std::set<effect*> uncopy;
duel();
~duel();
void clear();
card* new_card(uint32 code);
group* new_group();
group* new_group(card* pcard);
group* new_group(const card_set& cset);
effect* new_effect();
void delete_card(card* pcard);
void delete_group(group* pgroup);
void delete_effect(effect* peffect);
void release_script_group();
void restore_assumes();
int32 read_buffer(byte* buf);
void write_buffer32(uint32 value);
void write_buffer16(uint16 value);
void write_buffer8(uint8 value);
void clear_buffer();
void set_responsei(uint32 resp);
void set_responseb(byte* resp);
int32 get_next_integer(int32 l, int32 h);
private:
group* register_group(group* pgroup);
};
//Player
#define PLAYER_NONE 2 //
#define PLAYER_ALL 3 //
//Phase
#define PHASE_DRAW 0x01 //
#define PHASE_STANDBY 0x02 //
#define PHASE_MAIN1 0x04 //
#define PHASE_BATTLE 0x08 //
#define PHASE_DAMAGE 0x10 //
#define PHASE_DAMAGE_CAL 0x20 //
#define PHASE_MAIN2 0x40 //
#define PHASE_END 0x80 //
//Options
#define DUEL_TEST_MODE 0x01
#define DUEL_ATTACK_FIRST_TURN 0x02
#define DUEL_NO_CHAIN_HINT 0x04
#define DUEL_OBSOLETE_RULING 0x08
#define DUEL_PSEUDO_SHUFFLE 0x10
#define DUEL_TAG_MODE 0x20
#define DUEL_SIMPLE_AI 0x40
#endif /* DUEL_H_ */
/*
* effect.cpp
*
* Created on: 2010-5-7
* Author: Argon
*/
#include "effect.h"
#include "card.h"
#include "duel.h"
#include "group.h"
#include "interpreter.h"
bool effect_sort_id(const effect* e1, const effect* e2) {
return e1->id < e2->id;
};
effect::effect(duel* pd) {
scrtype = 3;
ref_handle = 0;
pduel = pd;
owner = 0;
handler = 0;
description = 0;
effect_owner = PLAYER_NONE;
card_type = 0;
active_type = 0;
id = 0;
code = 0;
type = 0;
flag = 0;
copy_id = 0;
range = 0;
s_range = 0;
o_range = 0;
reset_count = 0;
reset_flag = 0;
count_code = 0;
category = 0;
label = 0;
label_object = 0;
hint_timing[0] = 0;
hint_timing[1] = 0;
field_ref = 0;
status = 0;
condition = 0;
cost = 0;
target = 0;
value = 0;
operation = 0;
}
effect::~effect() {
}
int32 effect::is_disable_related() {
if (code == EFFECT_IMMUNE_EFFECT || code == EFFECT_DISABLE || code == EFFECT_CANNOT_DISABLE)
return TRUE;
return FALSE;
}
int32 effect::is_available() {
if (type & EFFECT_TYPE_ACTIONS)
return FALSE;
if (type & EFFECT_TYPE_SINGLE) {
if (handler->current.controler == PLAYER_NONE)
return FALSE;
if((flag & EFFECT_FLAG_SINGLE_RANGE) && !in_range(handler->current.location, handler->current.sequence))
return FALSE;
if((flag & EFFECT_FLAG_SINGLE_RANGE) && (handler->current.location & LOCATION_ONFIELD)
&& (handler->is_position(POS_FACEDOWN) || (!handler->is_status(STATUS_EFFECT_ENABLED) && !(flag & EFFECT_FLAG_IMMEDIATELY_APPLY))))
return FALSE;
if((flag & EFFECT_FLAG_OWNER_RELATE) && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && owner->is_status(STATUS_DISABLED))
return FALSE;
if(owner == handler && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && handler->get_status(STATUS_DISABLED))
return FALSE;
}
if (type & EFFECT_TYPE_EQUIP) {
if(handler->current.controler == PLAYER_NONE)
return FALSE;
if((flag & EFFECT_FLAG_OWNER_RELATE) && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && owner->is_status(STATUS_DISABLED))
return FALSE;
if(owner == handler && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && handler->get_status(STATUS_DISABLED))
return FALSE;
if(!(flag & EFFECT_FLAG_SET_AVAILABLE)) {
if(!(handler->get_status(STATUS_EFFECT_ENABLED)))
return FALSE;
if(!handler->is_position(POS_FACEUP))
return FALSE;
}
}
if (type & EFFECT_TYPE_FIELD) {
if (!(flag & EFFECT_FLAG_FIELD_ONLY)) {
if(handler->current.controler == PLAYER_NONE)
return FALSE;
if((flag & EFFECT_FLAG_OWNER_RELATE) && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && owner->is_status(STATUS_DISABLED))
return FALSE;
if(owner == handler && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && handler->get_status(STATUS_DISABLED))
return FALSE;
if(handler->is_status(STATUS_BATTLE_DESTROYED) && !(flag & EFFECT_FLAG_AVAILABLE_BD))
return FALSE;
if(!handler->get_status(STATUS_EFFECT_ENABLED) && !(flag & EFFECT_FLAG_IMMEDIATELY_APPLY))
return FALSE;
if(!in_range(handler->current.location, handler->current.sequence))
return FALSE;
if((handler->current.location & LOCATION_ONFIELD) && !handler->is_position(POS_FACEUP))
return FALSE;
}
}
if (!condition)
return TRUE;
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
int32 res = pduel->lua->check_condition(condition, 1);
if(res) {
if(!(status & EFFECT_STATUS_AVAILABLE))
id = pduel->game_field->infos.field_id++;
status |= EFFECT_STATUS_AVAILABLE;
} else
status &= ~EFFECT_STATUS_AVAILABLE;
return res;
}
int32 effect::check_count_limit(uint8 playerid) {
if((flag & EFFECT_FLAG_COUNT_LIMIT)) {
if(count_code == 0) {
if((reset_count & 0xf00) == 0)
return FALSE;
} else {
uint32 code = count_code & 0xfffffff;
uint32 count = (reset_count >> 12) & 0xf;
if(code == 1) {
if(pduel->game_field->get_effect_code((count_code & 0xf0000000) | handler->fieldid, PLAYER_NONE) >= count)
return FALSE;
} else {
if(pduel->game_field->get_effect_code(count_code, playerid) >= count)
return FALSE;
}
}
}
return TRUE;
}
int32 effect::is_activateable(uint8 playerid, const tevent& e, int32 neglect_cond, int32 neglect_cost, int32 neglect_target) {
if(!(type & EFFECT_TYPE_ACTIONS))
return FALSE;
if(!check_count_limit(playerid))
return FALSE;
if (!(flag & EFFECT_FLAG_FIELD_ONLY)) {
if (type & EFFECT_TYPE_ACTIVATE) {
if(handler->current.controler != playerid)
return FALSE;
if(pduel->game_field->check_unique_onfield(handler, playerid))
return FALSE;
if(!(handler->data.type & TYPE_COUNTER)) {
if((code < 1132 || code > 1149) && pduel->game_field->infos.phase == PHASE_DAMAGE && !(flag & EFFECT_FLAG_DAMAGE_STEP))
return FALSE;
if((code < 1134 || code > 1136) && pduel->game_field->infos.phase == PHASE_DAMAGE_CAL && !(flag & EFFECT_FLAG_DAMAGE_CAL))
return FALSE;
}
if(handler->current.location == LOCATION_HAND) {
if(handler->data.type & TYPE_MONSTER) {
if(!(handler->data.type & TYPE_PENDULUM))
return FALSE;
if(pduel->game_field->player[playerid].list_szone[6] && pduel->game_field->player[playerid].list_szone[7])
return FALSE;
} else if(!(handler->data.type & TYPE_FIELD)
&& pduel->game_field->get_useable_count(playerid, LOCATION_SZONE, playerid, LOCATION_REASON_TOFIELD) <= 0)
return FALSE;
} else if(handler->current.location == LOCATION_SZONE) {
if(handler->is_position(POS_FACEUP))
return FALSE;
if(handler->get_status(STATUS_SET_TURN)) {
if((handler->data.type & TYPE_SPELL) && (handler->data.type & TYPE_QUICKPLAY))
return FALSE;
}
}
int32 ecode = 0;
if(handler->current.location == LOCATION_HAND) {
if(handler->data.type & TYPE_TRAP)
ecode = EFFECT_TRAP_ACT_IN_HAND;
else if((handler->data.type & TYPE_SPELL) && pduel->game_field->infos.turn_player != playerid) {
if(handler->data.type & TYPE_QUICKPLAY)
ecode = EFFECT_QP_ACT_IN_NTPHAND;
else
return FALSE;
}
} else if(handler->current.location == LOCATION_SZONE) {
if((handler->data.type & TYPE_TRAP) && handler->get_status(STATUS_SET_TURN))
ecode = EFFECT_TRAP_ACT_IN_SET_TURN;
}
if(ecode) {
int32 available = false;
effect_set eset;
handler->filter_effect(ecode, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(eset[i]->check_count_limit(playerid)) {
available = true;
break;
}
}
if(!available)
return FALSE;
}
if(handler->is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(handler->is_affected_by_effect(EFFECT_CANNOT_TRIGGER))
return FALSE;
} else if(!(type & EFFECT_TYPE_CONTINUOUS)) {
if((handler->current.location & (LOCATION_ONFIELD | LOCATION_REMOVED)) && (code != EVENT_FLIP && !(flag & EFFECT_FLAG_SET_AVAILABLE))
&& (!handler->is_position(POS_FACEUP) || !handler->is_status(STATUS_EFFECT_ENABLED)))
return FALSE;
if(!(type & (EFFECT_TYPE_FLIP | EFFECT_TYPE_TRIGGER_F))
&& !((type & EFFECT_TYPE_SINGLE)
&& (code == EVENT_TO_GRAVE || code == EVENT_DESTROYED || code == EVENT_SPSUMMON_SUCCESS || code == EVENT_TO_HAND))) {
if((code < 1132 || code > 1149) && pduel->game_field->infos.phase == PHASE_DAMAGE && !(flag & EFFECT_FLAG_DAMAGE_STEP))
return FALSE;
if((code < 1134 || code > 1136) && pduel->game_field->infos.phase == PHASE_DAMAGE_CAL && !(flag & EFFECT_FLAG_DAMAGE_CAL))
return FALSE;
}
if((type & EFFECT_TYPE_FIELD) && (handler->current.controler != playerid) && !(flag & EFFECT_FLAG_BOTH_SIDE))
return FALSE;
if(handler->is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
if(handler->is_affected_by_effect(EFFECT_CANNOT_TRIGGER))
return FALSE;
} else {
if(!(flag & EFFECT_FLAG_AVAILABLE_BD) && (type & EFFECT_TYPE_FIELD) && handler->is_status(STATUS_BATTLE_DESTROYED))
return FALSE;
if(((type & EFFECT_TYPE_FIELD) || ((type & EFFECT_TYPE_SINGLE) && (flag & EFFECT_FLAG_SINGLE_RANGE))) && (handler->current.location & LOCATION_ONFIELD)
&& (!handler->is_position(POS_FACEUP) || !handler->is_status(STATUS_EFFECT_ENABLED)))
return FALSE;
if((type & EFFECT_TYPE_SINGLE) && (flag & EFFECT_FLAG_SINGLE_RANGE) && !in_range(handler->current.location, handler->current.sequence))
return FALSE;
if((flag & EFFECT_FLAG_OWNER_RELATE) && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && owner->is_status(STATUS_DISABLED))
return FALSE;
if((handler == owner) && !(flag & EFFECT_FLAG_CANNOT_DISABLE) && handler->is_status(STATUS_DISABLED))
return FALSE;
}
} else {
if((get_owner_player() != playerid) && !(flag & EFFECT_FLAG_BOTH_SIDE))
return FALSE;
}
pduel->game_field->save_lp_cost();
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = this;
pduel->game_field->core.reason_player = playerid;
int32 result = TRUE;
if(!(type & EFFECT_TYPE_CONTINUOUS))
result = is_action_check(playerid);
if(result)
result = is_activate_ready(playerid, e, neglect_cond, neglect_cost, neglect_target);
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
pduel->game_field->restore_lp_cost();
return result;
}
// check EFFECT_CANNOT_ACTIVATE
int32 effect::is_action_check(uint8 playerid) {
effect_set eset;
pduel->game_field->filter_player_effect(playerid, EFFECT_CANNOT_ACTIVATE, &eset);
for(int i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(eset[i]->check_value_condition(2))
return FALSE;
}
eset.clear();
pduel->game_field->filter_player_effect(playerid, EFFECT_ACTIVATE_COST, &eset);
for(int i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->target, 3))
continue;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(eset[i]->cost, 3))
return FALSE;
}
return TRUE;
}
// check condition, cost(chk=0), target(chk=0)
int32 effect::is_activate_ready(uint8 playerid, const tevent& e, int32 neglect_cond, int32 neglect_cost, int32 neglect_target) {
if (!neglect_cond && condition) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT);
if (!pduel->lua->check_condition(condition, 8)) {
return FALSE;
}
}
if(!neglect_cost && cost && !(type & EFFECT_TYPE_CONTINUOUS)) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT);
pduel->lua->add_param((ptr)0, PARAM_TYPE_INT);
if (!pduel->lua->check_condition(cost, 9)) {
return FALSE;
}
}
if(!neglect_target && target) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT);
pduel->lua->add_param((ptr)0, PARAM_TYPE_INT);
if (!pduel->lua->check_condition(target, 9)) {
return FALSE;
}
}
return TRUE;
}
int32 effect::is_condition_check(uint8 playerid, const tevent& e) {
if(!(type & EFFECT_TYPE_ACTIVATE) && (handler->current.location & (LOCATION_ONFIELD | LOCATION_REMOVED)) && !handler->is_position(POS_FACEUP))
return FALSE;
if(!condition)
return TRUE;
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = this;
pduel->game_field->core.reason_player = playerid;
pduel->game_field->save_lp_cost();
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(e.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(e.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(e.reason, PARAM_TYPE_INT);
pduel->lua->add_param(e.reason_player, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(condition, 8)) {
pduel->game_field->restore_lp_cost();
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
return FALSE;
}
pduel->game_field->restore_lp_cost();
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
return TRUE;
}
int32 effect::is_activate_check(uint8 playerid, const tevent& e, int32 neglect_cond, int32 neglect_cost, int32 neglect_target) {
pduel->game_field->save_lp_cost();
effect* oreason = pduel->game_field->core.reason_effect;
uint8 op = pduel->game_field->core.reason_player;
pduel->game_field->core.reason_effect = this;
pduel->game_field->core.reason_player = playerid;
int32 result = is_activate_ready(playerid, e, neglect_cond, neglect_cost, neglect_target);
pduel->game_field->core.reason_effect = oreason;
pduel->game_field->core.reason_player = op;
pduel->game_field->restore_lp_cost();
return result;
}
int32 effect::is_target(card* pcard) {
if(type & EFFECT_TYPE_ACTIONS)
return FALSE;
if((type & EFFECT_TYPE_SINGLE) || (type & EFFECT_TYPE_EQUIP))
return TRUE;
if(pcard && !(flag & EFFECT_FLAG_SET_AVAILABLE) && (pcard->current.location & LOCATION_ONFIELD)
&& !pcard->is_position(POS_FACEUP))
return FALSE;
if(!(flag & EFFECT_FLAG_IGNORE_RANGE)) {
if(pcard->get_status(STATUS_SUMMONING + STATUS_SUMMON_DISABLED))
return FALSE;
if(flag & EFFECT_FLAG_ABSOLUTE_TARGET) {
if(pcard->current.controler == 0) {
if (!(s_range & pcard->current.location))
return FALSE;
} else {
if(!(o_range & pcard->current.location))
return FALSE;
}
} else {
if(pcard->current.controler == get_handler_player()) {
if(!(s_range & pcard->current.location))
return FALSE;
} else {
if(!(o_range & pcard->current.location))
return FALSE;
}
}
}
if(target) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
if (!pduel->lua->check_condition(target, 2)) {
return FALSE;
}
}
return TRUE;
}
int32 effect::is_target_player(uint8 playerid) {
if(!(flag & EFFECT_FLAG_PLAYER_TARGET))
return FALSE;
uint8 self = get_handler_player();
if(flag & EFFECT_FLAG_ABSOLUTE_TARGET) {
if(s_range && playerid == 0 )
return TRUE;
if(o_range && playerid == 1 )
return TRUE;
} else {
if(s_range && self == playerid)
return TRUE;
if(o_range && self != playerid)
return TRUE;
}
return FALSE;
}
int32 effect::is_player_effect_target(card* pcard) {
if(target) {
handler->pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
handler->pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
if(!handler->pduel->lua->check_condition(target, 2)) {
return FALSE;
}
}
return TRUE;
}
int32 effect::is_immuned(effect_set_v* effects) {
effect* peffect;
for (int i = 0; i < effects->count; ++i) {
peffect = effects->at(i);
if(peffect->value) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
if(peffect->check_value_condition(1))
return TRUE;
}
}
return FALSE;
}
int32 effect::is_chainable(uint8 tp) {
if(!(type & EFFECT_TYPE_ACTIONS))
return FALSE;
int32 sp = get_speed();
if((type & EFFECT_TYPE_ACTIVATE) && (sp <= 1) && !(flag & EFFECT_FLAG_COF))
return FALSE;
if(pduel->game_field->core.current_chain.size()) {
if(!(flag & EFFECT_FLAG_FIELD_ONLY) && (type & EFFECT_TYPE_TRIGGER_O)
&& (handler->current.location == LOCATION_HAND)) {
if(pduel->game_field->core.current_chain.rbegin()->triggering_effect->get_speed() > 2)
return FALSE;
} else if(sp < pduel->game_field->core.current_chain.rbegin()->triggering_effect->get_speed())
return FALSE;
}
if(pduel->game_field->core.chain_limit) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pduel->game_field->core.chain_limp, PARAM_TYPE_INT);
pduel->lua->add_param(tp, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(pduel->game_field->core.chain_limit, 3))
return FALSE;
}
if(pduel->game_field->core.chain_limit_p) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pduel->game_field->core.chain_limp_p, PARAM_TYPE_INT);
pduel->lua->add_param(tp, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(pduel->game_field->core.chain_limit_p, 3))
return FALSE;
}
return TRUE;
}
//return: this can be reset by reset_level or not
//RESET_CODE can only reset single effects without EFFECT_FLAG_SINGLE_RANGE
//RESET_DISABLE is valid only when owner == handler
int32 effect::reset(uint32 reset_level, uint32 reset_type) {
switch (reset_type) {
case RESET_EVENT: {
if(!(reset_flag & RESET_EVENT))
return FALSE;
if(owner != handler)
reset_level &= ~RESET_DISABLE;
if(reset_level & 0xffff0000 & reset_flag)
return TRUE;
return FALSE;
break;
}
case RESET_CARD: {
return owner && (owner->data.code == reset_level);
break;
}
case RESET_PHASE: {
if(!(reset_flag & RESET_PHASE))
return FALSE;
uint8 pid = get_handler_player();
uint8 tp = handler->pduel->game_field->infos.turn_player;
if((((reset_flag & RESET_SELF_TURN) && pid == tp) || ((reset_flag & RESET_OPPO_TURN) && pid != tp))
&& (reset_level & 0xff & reset_flag))
reset_count--;
if((reset_count & 0xff) == 0)
return TRUE;
return FALSE;
break;
}
case RESET_CODE: {
return (code == reset_level) && (type & EFFECT_TYPE_SINGLE) && !(type & EFFECT_TYPE_ACTIONS)
&& !(flag & EFFECT_FLAG_SINGLE_RANGE);
break;
}
case RESET_COPY: {
return copy_id == reset_level;
break;
}
}
return FALSE;
}
void effect::dec_count(uint32 playerid) {
if(!(flag & EFFECT_FLAG_COUNT_LIMIT))
return;
if(count_code == 0) {
if((reset_count & 0xf00) == 0)
return;
reset_count -= 0x100;
} else {
uint32 code = count_code & 0xfffffff;
if(code == 1)
pduel->game_field->add_effect_code((count_code & 0xf0000000) | handler->fieldid, PLAYER_NONE);
else
pduel->game_field->add_effect_code(count_code, playerid);
}
}
void effect::recharge() {
if((flag & EFFECT_FLAG_COUNT_LIMIT) && (count_code == 0)) {
reset_count &= 0xf0ff;
reset_count |= (reset_count >> 4) & 0xf00;
}
}
int32 effect::get_value(uint32 extraargs) {
if(flag & EFFECT_FLAG_FUNC_VALUE) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT, TRUE);
int32 res = pduel->lua->get_function_value(value, 1 + extraargs);
return res;
} else {
pduel->lua->params.clear();
return (int32)value;
}
}
int32 effect::get_value(card* pcard, uint32 extraargs) {
if(flag & EFFECT_FLAG_FUNC_VALUE) {
pduel->lua->add_param(pcard, PARAM_TYPE_CARD, TRUE);
pduel->lua->add_param(this, PARAM_TYPE_EFFECT, TRUE);
int32 res = pduel->lua->get_function_value(value, 2 + extraargs);
return res;
} else {
pduel->lua->params.clear();
return (int32)value;
}
}
int32 effect::get_value(effect* peffect, uint32 extraargs) {
if(flag & EFFECT_FLAG_FUNC_VALUE) {
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT, TRUE);
pduel->lua->add_param(this, PARAM_TYPE_EFFECT, TRUE);
int32 res = pduel->lua->get_function_value(value, 2 + extraargs);
return res;
} else {
pduel->lua->params.clear();
return (int32)value;
}
}
int32 effect::check_value_condition(uint32 extraargs) {
if(flag & EFFECT_FLAG_FUNC_VALUE) {
pduel->lua->add_param(this, PARAM_TYPE_EFFECT, TRUE);
int32 res = pduel->lua->check_condition(value, 1 + extraargs);
return res;
} else {
pduel->lua->params.clear();
return (int32)value;
}
}
int32 effect::get_speed() {
if(!(type & EFFECT_TYPE_ACTIONS))
return 0;
if(type & (EFFECT_TYPE_TRIGGER_O | EFFECT_TYPE_TRIGGER_F | EFFECT_TYPE_IGNITION))
return 1;
else if(type & (EFFECT_TYPE_QUICK_O | EFFECT_TYPE_QUICK_F))
return 2;
else if(type & EFFECT_TYPE_ACTIVATE) {
if(handler->data.type & TYPE_MONSTER)
return 0;
else if(handler->data.type & TYPE_SPELL) {
if(handler->data.type & TYPE_QUICKPLAY)
return 2;
return 1;
} else {
if (handler->data.type & TYPE_COUNTER)
return 3;
return 2;
}
}
return 0;
}
uint8 effect::get_owner_player() {
if(effect_owner != PLAYER_NONE)
return effect_owner;
return owner->current.controler;
}
uint8 effect::get_handler_player() {
if(flag & EFFECT_FLAG_FIELD_ONLY)
return effect_owner;
return handler->current.controler;
}
int32 effect::in_range(int32 loc, int32 seq) {
if(loc != LOCATION_SZONE)
return range & loc;
if(seq < 5)
return range & LOCATION_SZONE;
if(seq == 5)
return range & (LOCATION_SZONE | LOCATION_FZONE);
return range & LOCATION_PZONE;
}
/*
* effect.h
*
* Created on: 2010-3-13
* Author: Argon
*/
#ifndef EFFECT_H_
#define EFFECT_H_
#include "common.h"
#include "field.h"
#include "effectset.h"
#include <stdlib.h>
#include <vector>
#include <map>
using namespace std;
class card;
class duel;
class group;
class effect;
struct tevent;
struct effect_set;
struct effect_set_v;
class effect {
public:
int32 scrtype;
int32 ref_handle;
duel* pduel;
card* owner;
card* handler;
uint8 effect_owner;
uint32 description;
uint32 code;
uint32 flag;
uint32 id;
uint16 type;
uint16 copy_id;
uint16 range;
uint16 s_range;
uint16 o_range;
uint16 reset_count;
uint32 reset_flag;
uint32 count_code;
uint32 category;
uint32 label;
uint32 hint_timing[2];
uint32 card_type;
uint32 active_type;
uint16 field_ref;
uint16 status;
void* label_object;
int32 condition;
int32 cost;
int32 target;
int32 value;
int32 operation;
explicit effect(duel* pd);
~effect();
int32 is_disable_related();
int32 is_available();
int32 check_count_limit(uint8 playerid);
int32 is_activateable(uint8 playerid, const tevent& e, int32 neglect_cond = FALSE, int32 neglect_cost = FALSE, int32 neglect_target = FALSE);
int32 is_action_check(uint8 playerid);
int32 is_activate_ready(uint8 playerid, const tevent& e, int32 neglect_cond = FALSE, int32 neglect_cost = FALSE, int32 neglect_target = FALSE);
int32 is_condition_check(uint8 playerid, const tevent& e);
int32 is_activate_check(uint8 playerid, const tevent& e, int32 neglect_cond = FALSE, int32 neglect_cost = FALSE, int32 neglect_target = FALSE);
int32 is_target(card* pcard);
int32 is_target_player(uint8 playerid);
int32 is_player_effect_target(card* pcard);
int32 is_immuned(effect_set_v* effects);
int32 is_chainable(uint8 tp);
int32 reset(uint32 reset_level, uint32 reset_type);
void dec_count(uint32 playerid = 2);
void recharge();
int32 get_value(uint32 extraargs = 0);
int32 get_value(card* pcard, uint32 extraargs = 0);
int32 get_value(effect* peffect, uint32 extraargs = 0);
int32 check_value_condition(uint32 extraargs = 0);
int32 get_speed();
uint8 get_owner_player();
uint8 get_handler_player();
int32 in_range(int32 loc, int32 seq);
};
//status
#define EFFECT_STATUS_AVAILABLE 0x0001
#define EFFECT_STATUS_ACTIVATED 0x0002
#define EFFECT_COUNT_CODE_OATH 0x10000000
#define EFFECT_COUNT_CODE_DUEL 0x20000000
//========== Reset ==========
#define RESET_DRAW PHASE_DRAW
#define RESET_STANDBY PHASE_STANDBY
#define RESET_MAIN1 PHASE_MAIN1
#define RESET_BATTLE PHASE_BATTLE
#define RESET_DAMAGE PHASE_DAMAGE
#define RESET_DAMAGE_CAL PHASE_DAMAGE_CAL
#define RESET_MAIN2 PHASE_MAIN2
#define RESET_END PHASE_END
#define RESET_SELF_TURN 0x0100
#define RESET_OPPO_TURN 0x0200
#define RESET_PHASE 0x0400
#define RESET_CHAIN 0x0800
#define RESET_EVENT 0x1000
#define RESET_CARD 0x2000
#define RESET_CODE 0x4000
#define RESET_COPY 0x8000
#define RESET_DISABLE 0x00010000
#define RESET_TURN_SET 0x00020000
#define RESET_TOGRAVE 0x00040000
#define RESET_REMOVE 0x00080000
#define RESET_TEMP_REMOVE 0x00100000
#define RESET_TOHAND 0x00200000
#define RESET_TODECK 0x00400000
#define RESET_LEAVE 0x00800000
#define RESET_TOFIELD 0x01000000
#define RESET_CONTROL 0x02000000
#define RESET_OVERLAY 0x04000000
#define RESET_MSCHANGE 0x08000000
//========== Types ==========
#define EFFECT_TYPE_SINGLE 0x0001 //
#define EFFECT_TYPE_FIELD 0x0002 //
#define EFFECT_TYPE_EQUIP 0x0004 //
#define EFFECT_TYPE_ACTIONS 0x0008 //
#define EFFECT_TYPE_ACTIVATE 0x0010 //
#define EFFECT_TYPE_FLIP 0x0020 //
#define EFFECT_TYPE_IGNITION 0x0040 //
#define EFFECT_TYPE_TRIGGER_O 0x0080 //
#define EFFECT_TYPE_QUICK_O 0x0100 //
#define EFFECT_TYPE_TRIGGER_F 0x0200 //
#define EFFECT_TYPE_QUICK_F 0x0400 //
#define EFFECT_TYPE_CONTINUOUS 0x0800 //
//========== Flags ==========
#define EFFECT_FLAG_INITIAL 0x0001 //
#define EFFECT_FLAG_FUNC_VALUE 0x0002 //
#define EFFECT_FLAG_COUNT_LIMIT 0x0004 //
#define EFFECT_FLAG_FIELD_ONLY 0x0008 //
#define EFFECT_FLAG_CARD_TARGET 0x0010 //
#define EFFECT_FLAG_IGNORE_RANGE 0x0020 //
#define EFFECT_FLAG_ABSOLUTE_TARGET 0x0040 //
#define EFFECT_FLAG_IGNORE_IMMUNE 0x0080 //
#define EFFECT_FLAG_SET_AVAILABLE 0x0100 //
#define EFFECT_FLAG_CONTINUOUS 0x0200 //
#define EFFECT_FLAG_CANNOT_DISABLE 0x0400 //
#define EFFECT_FLAG_PLAYER_TARGET 0x0800 //
#define EFFECT_FLAG_BOTH_SIDE 0x1000 //
#define EFFECT_FLAG_COPY_INHERIT 0x2000 //
#define EFFECT_FLAG_DAMAGE_STEP 0x4000 //
#define EFFECT_FLAG_DAMAGE_CAL 0x8000 //
#define EFFECT_FLAG_DELAY 0x10000 //
#define EFFECT_FLAG_SINGLE_RANGE 0x20000 //
#define EFFECT_FLAG_UNCOPYABLE 0x40000 //
#define EFFECT_FLAG_OATH 0x80000 //
#define EFFECT_FLAG_SPSUM_PARAM 0x100000 //
#define EFFECT_FLAG_REPEAT 0x200000 //
#define EFFECT_FLAG_NO_TURN_RESET 0x400000 //
#define EFFECT_FLAG_EVENT_PLAYER 0x800000 //
#define EFFECT_FLAG_OWNER_RELATE 0x1000000 //
#define EFFECT_FLAG_AVAILABLE_BD 0x2000000 //
#define EFFECT_FLAG_CLIENT_HINT 0x4000000 //
#define EFFECT_FLAG_CHAIN_UNIQUE 0x8000000 //
#define EFFECT_FLAG_NAGA 0x10000000 //
#define EFFECT_FLAG_COF 0x20000000 //
#define EFFECT_FLAG_CVAL_CHECK 0x40000000 //
#define EFFECT_FLAG_IMMEDIATELY_APPLY 0x80000000 //
//========== Codes ==========
#define EFFECT_IMMUNE_EFFECT 1 //
#define EFFECT_DISABLE 2 //
#define EFFECT_CANNOT_DISABLE 3 //
#define EFFECT_SET_CONTROL 4 //
#define EFFECT_CANNOT_CHANGE_CONTROL 5 //
#define EFFECT_CANNOT_ACTIVATE 6 //
#define EFFECT_CANNOT_TRIGGER 7 //
#define EFFECT_DISABLE_EFFECT 8 //
#define EFFECT_DISABLE_CHAIN 9 //
#define EFFECT_DISABLE_TRAPMONSTER 10 //
#define EFFECT_CANNOT_INACTIVATE 12 //
#define EFFECT_CANNOT_DISEFFECT 13 //
#define EFFECT_CANNOT_CHANGE_POSITION 14 //
#define EFFECT_TRAP_ACT_IN_HAND 15 //
#define EFFECT_TRAP_ACT_IN_SET_TURN 16 //
#define EFFECT_REMAIN_FIELD 17 //
#define EFFECT_MONSTER_SSET 18 //
#define EFFECT_CANNOT_SUMMON 20 //
#define EFFECT_CANNOT_FLIP_SUMMON 21 //
#define EFFECT_CANNOT_SPECIAL_SUMMON 22 //
#define EFFECT_CANNOT_MSET 23 //
#define EFFECT_CANNOT_SSET 24 //
#define EFFECT_CANNOT_DRAW 25 //
#define EFFECT_CANNOT_DISABLE_SUMMON 26 //
#define EFFECT_CANNOT_DISABLE_SPSUMMON 27 //
#define EFFECT_SET_SUMMON_COUNT_LIMIT 28 //
#define EFFECT_EXTRA_SUMMON_COUNT 29 //
#define EFFECT_SPSUMMON_CONDITION 30 //
#define EFFECT_REVIVE_LIMIT 31 //
#define EFFECT_SUMMON_PROC 32 //
#define EFFECT_LIMIT_SUMMON_PROC 33 //
#define EFFECT_SPSUMMON_PROC 34 //
#define EFFECT_EXTRA_SET_COUNT 35 //
#define EFFECT_SET_PROC 36 //
#define EFFECT_LIMIT_SET_PROC 37 //
#define EFFECT_DEVINE_LIGHT 38 //
#define EFFECT_CANNOT_DISABLE_FLIP_SUMMON 39 //
#define EFFECT_INDESTRUCTABLE 40 //
#define EFFECT_INDESTRUCTABLE_EFFECT 41 //
#define EFFECT_INDESTRUCTABLE_BATTLE 42 //
#define EFFECT_UNRELEASABLE_SUM 43 //
#define EFFECT_UNRELEASABLE_NONSUM 44 //
#define EFFECT_DESTROY_SUBSTITUTE 45 //
#define EFFECT_CANNOT_RELEASE 46 //
#define EFFECT_INDESTRUCTABLE_COUNT 47 //
#define EFFECT_UNRELEASABLE_EFFECT 48 //
#define EFFECT_DESTROY_REPLACE 50 //
#define EFFECT_RELEASE_REPLACE 51 //
#define EFFECT_SEND_REPLACE 52 //
#define EFFECT_CANNOT_DISCARD_HAND 55 //
#define EFFECT_CANNOT_DISCARD_DECK 56 //
#define EFFECT_CANNOT_USE_AS_COST 57 //
#define EFFECT_CANNOT_PLACE_COUNTER 58 //
#define EFFECT_LEAVE_FIELD_REDIRECT 60 //
#define EFFECT_TO_HAND_REDIRECT 61 //
#define EFFECT_TO_DECK_REDIRECT 62 //
#define EFFECT_TO_GRAVE_REDIRECT 63 //
#define EFFECT_REMOVE_REDIRECT 64 //
#define EFFECT_CANNOT_TO_HAND 65 //
#define EFFECT_CANNOT_TO_DECK 66 //
#define EFFECT_CANNOT_REMOVE 67 //
#define EFFECT_CANNOT_TO_GRAVE 68 //
#define EFFECT_CANNOT_TURN_SET 69 //
#define EFFECT_CANNOT_BE_BATTLE_TARGET 70 //
#define EFFECT_CANNOT_BE_EFFECT_TARGET 71 //
#define EFFECT_IGNORE_BATTLE_TARGET 72 //
#define EFFECT_CANNOT_DIRECT_ATTACK 73 //
#define EFFECT_DIRECT_ATTACK 74 //
#define EFFECT_DUAL_STATUS 75 //
#define EFFECT_EQUIP_LIMIT 76 //
#define EFFECT_DUAL_SUMMONABLE 77 //
#define EFFECT_REVERSE_DAMAGE 80 //
#define EFFECT_REVERSE_RECOVER 81 //
#define EFFECT_CHANGE_DAMAGE 82 //
#define EFFECT_REFLECT_DAMAGE 83 //
#define EFFECT_CANNOT_ATTACK 85 //
#define EFFECT_CANNOT_ATTACK_ANNOUNCE 86 //
#define EFFECT_CANNOT_CHANGE_POS_E 87 //
#define EFFECT_ACTIVATE_COST 90 //
#define EFFECT_SUMMON_COST 91 //
#define EFFECT_SPSUMMON_COST 92 //
#define EFFECT_FLIPSUMMON_COST 93 //
#define EFFECT_MSET_COST 94 //
#define EFFECT_SSET_COST 95 //
#define EFFECT_ATTACK_COST 96 //
#define EFFECT_UPDATE_ATTACK 100 //
#define EFFECT_SET_ATTACK 101 //
#define EFFECT_SET_ATTACK_FINAL 102 //
#define EFFECT_SET_BASE_ATTACK 103 //
#define EFFECT_UPDATE_DEFENCE 104 //
#define EFFECT_SET_DEFENCE 105 //
#define EFFECT_SET_DEFENCE_FINAL 106 //
#define EFFECT_SET_BASE_DEFENCE 107 //
#define EFFECT_REVERSE_UPDATE 108 //
#define EFFECT_SWAP_AD 109 //
#define EFFECT_SWAP_BASE_AD 110 //
#define EFFECT_ADD_CODE 113 //
#define EFFECT_CHANGE_CODE 114 //
#define EFFECT_ADD_TYPE 115 //
#define EFFECT_REMOVE_TYPE 116 //
#define EFFECT_CHANGE_TYPE 117 //
#define EFFECT_ADD_RACE 120 //
#define EFFECT_REMOVE_RACE 121 //
#define EFFECT_CHANGE_RACE 122 //
#define EFFECT_ADD_ATTRIBUTE 125 //
#define EFFECT_REMOVE_ATTRIBUTE 126 //
#define EFFECT_CHANGE_ATTRIBUTE 127 //
#define EFFECT_UPDATE_LEVEL 130 //
#define EFFECT_CHANGE_LEVEL 131 //
#define EFFECT_UPDATE_RANK 132 //
#define EFFECT_CHANGE_RANK 133 //
#define EFFECT_UPDATE_LSCALE 134 //
#define EFFECT_CHANGE_LSCALE 135 //
#define EFFECT_UPDATE_RSCALE 136 //
#define EFFECT_CHANGE_RSCALE 137 //
#define EFFECT_SET_POSITION 140 //
#define EFFECT_SELF_DESTROY 141 //
#define EFFECT_SELF_TOGRAVE 142
#define EFFECT_DOUBLE_TRIBUTE 150
#define EFFECT_DECREASE_TRIBUTE 151
#define EFFECT_DECREASE_TRIBUTE_SET 152
#define EFFECT_EXTRA_RELEASE 153
#define EFFECT_TRIBUTE_LIMIT 154
#define EFFECT_EXTRA_RELEASE_SUM 155
#define EFFECT_PUBLIC 160
#define EFFECT_COUNTER_PERMIT 0x10000
#define EFFECT_COUNTER_LIMIT 0x20000
#define EFFECT_RCOUNTER_REPLACE 0x30000
#define EFFECT_LPCOST_CHANGE 170
#define EFFECT_LPCOST_REPLACE 171
#define EFFECT_SKIP_DP 180
#define EFFECT_SKIP_SP 181
#define EFFECT_SKIP_M1 182
#define EFFECT_SKIP_BP 183
#define EFFECT_SKIP_M2 184
#define EFFECT_CANNOT_BP 185
#define EFFECT_CANNOT_M2 186
#define EFFECT_CANNOT_EP 187
#define EFFECT_SKIP_TURN 188
#define EFFECT_DEFENCE_ATTACK 190
#define EFFECT_MUST_ATTACK 191
#define EFFECT_FIRST_ATTACK 192
#define EFFECT_ATTACK_ALL 193
#define EFFECT_EXTRA_ATTACK 194
#define EFFECT_MUST_BE_ATTACKED 195
#define EFFECT_AUTO_BE_ATTACKED 196
#define EFFECT_ATTACK_DISABLED 197
#define EFFECT_NO_BATTLE_DAMAGE 200
#define EFFECT_AVOID_BATTLE_DAMAGE 201
#define EFFECT_REFLECT_BATTLE_DAMAGE 202
#define EFFECT_PIERCE 203
#define EFFECT_BATTLE_DESTROY_REDIRECT 204
#define EFFECT_BATTLE_DAMAGE_TO_EFFECT 205
#define EFFECT_TOSS_COIN_REPLACE 220
#define EFFECT_TOSS_DICE_REPLACE 221
#define EFFECT_FUSION_MATERIAL 230
#define EFFECT_CHAIN_MATERIAL 231
#define EFFECT_SYNCHRO_MATERIAL 232
#define EFFECT_XYZ_MATERIAL 233
#define EFFECT_FUSION_SUBSTITUTE 234
#define EFFECT_CANNOT_BE_FUSION_MATERIAL 235
#define EFFECT_CANNOT_BE_SYNCHRO_MATERIAL 236
#define EFFECT_SYNCHRO_MATERIAL_CUSTOM 237
#define EFFECT_CANNOT_BE_XYZ_MATERIAL 238
#define EFFECT_SYNCHRO_LEVEL 240
#define EFFECT_RITUAL_LEVEL 241
#define EFFECT_XYZ_LEVEL 242
#define EFFECT_EXTRA_RITUAL_MATERIAL 243
#define EFFECT_NONTUNER 244
#define EFFECT_OVERLAY_REMOVE_REPLACE 245
#define EFFECT_SCRAP_CHIMERA 246
#define EFFECT_SPSUM_EFFECT_ACTIVATED 250
#define EFFECT_MATERIAL_CHECK 251
#define EFFECT_DISABLE_FIELD 260
#define EFFECT_USE_EXTRA_MZONE 261
#define EFFECT_USE_EXTRA_SZONE 262
#define EFFECT_MAX_MZONE 263
#define EFFECT_MAX_SZONE 264
#define EFFECT_HAND_LIMIT 270
#define EFFECT_DRAW_COUNT 271
#define EFFECT_SPIRIT_DONOT_RETURN 280
#define EFFECT_SPIRIT_MAYNOT_RETURN 281
#define EFFECT_CHANGE_ENVIRONMENT 290
#define EFFECT_NECRO_VALLEY 291
#define EFFECT_FORBIDDEN 292
#define EFFECT_NECRO_VALLEY_IM 293
#define EFFECT_REVERSE_DECK 294
#define EFFECT_REMOVE_BRAINWASHING 295
#define EFFECT_BP_TWICE 296
#define EFFECT_UNIQUE_CHECK 297
#define EFFECT_MATCH_KILL 300
#define EFFECT_SYNCHRO_CHECK 310
#define EFFECT_QP_ACT_IN_NTPHAND 311
#define EFFECT_MUST_BE_SMATERIAL 312
#define EFFECT_TO_GRAVE_REDIRECT_CB 313
#define EFFECT_CHANGE_LEVEL_FINAL 314
#define EFFECT_CHANGE_RANK_FINAL 315
#define EFFECT_SPSUMMON_PROC_G 320
#define EFFECT_SPSUMMON_COUNT_LIMIT 330
#define EFFECT_LEFT_SPSUMMON_COUNT 331
#define EFFECT_CANNOT_SELECT_BATTLE_TARGET 332
#define EFFECT_CANNOT_SELECT_EFFECT_TARGET 333
#define EFFECT_ADD_SETCODE 334
#define EFFECT_NO_EFFECT_DAMAGE 335
#define EFFECT_UNSUMMONABLE_CARD 336
#define EFFECT_DISABLE_CHAIN_FIELD 337
#define EVENT_STARTUP 1000
#define EVENT_FLIP 1001
#define EVENT_FREE_CHAIN 1002
#define EVENT_DESTROY 1010
#define EVENT_REMOVE 1011
#define EVENT_TO_HAND 1012
#define EVENT_TO_DECK 1013
#define EVENT_TO_GRAVE 1014
#define EVENT_LEAVE_FIELD 1015
#define EVENT_CHANGE_POS 1016
#define EVENT_RELEASE 1017
#define EVENT_DISCARD 1018
#define EVENT_LEAVE_FIELD_P 1019
#define EVENT_CHAIN_SOLVING 1020
#define EVENT_CHAIN_ACTIVATING 1021
#define EVENT_CHAIN_SOLVED 1022
#define EVENT_CHAIN_ACTIVATED 1023
#define EVENT_CHAIN_NEGATED 1024
#define EVENT_CHAIN_DISABLED 1025
#define EVENT_CHAIN_END 1026
#define EVENT_CHAINING 1027
#define EVENT_BECOME_TARGET 1028
#define EVENT_DESTROYED 1029
#define EVENT_ADJUST 1040
#define EVENT_SUMMON_SUCCESS 1100
#define EVENT_FLIP_SUMMON_SUCCESS 1101
#define EVENT_SPSUMMON_SUCCESS 1102
#define EVENT_SUMMON 1103
#define EVENT_FLIP_SUMMON 1104
#define EVENT_SPSUMMON 1105
#define EVENT_MSET 1106
#define EVENT_SSET 1107
#define EVENT_BE_MATERIAL 1108
#define EVENT_BE_PRE_MATERIAL 1109
#define EVENT_DRAW 1110
#define EVENT_DAMAGE 1111
#define EVENT_RECOVER 1112
#define EVENT_PREDRAW 1113
#define EVENT_CONTROL_CHANGED 1120
#define EVENT_EQUIP 1121
#define EVENT_ATTACK_ANNOUNCE 1130
#define EVENT_BE_BATTLE_TARGET 1131
#define EVENT_BATTLE_START 1132
#define EVENT_BATTLE_CONFIRM 1133
#define EVENT_PRE_DAMAGE_CALCULATE 1134
#define EVENT_DAMAGE_CALCULATING 1135
#define EVENT_PRE_BATTLE_DAMAGE 1136
#define EVENT_BATTLE_END 1137
#define EVENT_BATTLED 1138
#define EVENT_BATTLE_DESTROYING 1139
#define EVENT_BATTLE_DESTROYED 1140
#define EVENT_DAMAGE_STEP_END 1141
#define EVENT_ATTACK_DISABLED 1142
#define EVENT_BATTLE_DAMAGE 1143
#define EVENT_TOSS_DICE 1150
#define EVENT_TOSS_COIN 1151
#define EVENT_TOSS_COIN_NEGATE 1152
#define EVENT_TOSS_DICE_NEGATE 1153
#define EVENT_LEVEL_UP 1200
#define EVENT_PAY_LPCOST 1201
#define EVENT_DETACH_MATERIAL 1202
#define EVENT_RETURN_TO_GRAVE 1203
#define EVENT_TURN_END 1210
#define EVENT_PHASE 0x1000
#define EVENT_PHASE_START 0x2000
#define EVENT_PHASE_PRESTART 0x2100
#define EVENT_ADD_COUNTER 0x10000
#define EVENT_REMOVE_COUNTER 0x20000
#endif /* EFFECT_H_ */
/*
* effectset.h
*
* Created on: 2011-10-8
* Author: Argon
*/
#ifndef EFFECTSET_H_
#define EFFECTSET_H_
#include <stdlib.h>
#include <array>
#include <vector>
#include <algorithm>
class effect;
bool effect_sort_id(const effect* e1, const effect* e2);
struct effect_set {
effect_set(): count(0) {}
void add_item(effect* peffect) {
if(count >= 64) return;
container[count++] = peffect;
}
void remove_item(int index) {
if(index >= count)
return;
if(index == count - 1) {
count--;
return;
}
for(int i = index; i < count - 1; ++i)
container[i] = container[i + 1];
count--;
}
void clear() {
count = 0;
}
int size() const {
return count;
}
void sort() {
if(count < 2)
return;
std::sort(container.begin(), container.begin() + count, effect_sort_id);
}
effect* const& get_last() const {
return container[count - 1];
}
effect*& get_last() {
return container[count - 1];
}
effect* const& operator[] (int index) const {
return container[index];
}
effect*& operator[] (int index) {
return container[index];
}
effect* const& at(int index) const {
return container[index];
}
effect*& at(int index) {
return container[index];
}
private:
std::array<effect*, 64> container;
int count;
};
struct effect_set_v {
effect_set_v(): count(0) {}
void add_item(effect* peffect) {
container.push_back(peffect);
count++;
}
void remove_item(int index) {
if(index >= count)
return;
container.erase(container.begin() + index);
count--;
}
void clear() {
container.clear();
count = 0;
}
void sort() {
if(count < 2)
return;
std::sort(container.begin(), container.begin() + count, effect_sort_id);
}
effect*& get_last() {
return container[count - 1];
}
effect*& operator[] (int index) {
return container[index];
}
effect*& at(int index) {
return container[index];
}
std::vector<effect*> container;
int count;
};
#endif //EFFECTSET_H_
/*
* field.cpp
*
* Created on: 2010-7-21
* Author: Argon
*/
#include "field.h"
#include "duel.h"
#include "card.h"
#include "group.h"
#include "effect.h"
#include "interpreter.h"
#include <iostream>
#include <cstring>
#include <map>
int32 field::field_used_count[32] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5};
bool chain::chain_operation_sort(const chain& c1, const chain& c2) {
return c1.triggering_effect->id < c2.triggering_effect->id;
}
bool tevent::operator< (const tevent& v) const {
return memcmp(this, &v, sizeof(tevent)) < 0;
}
field::field(duel* pduel) {
this->pduel = pduel;
infos.field_id = 1;
infos.copy_id = 1;
infos.can_shuffle = TRUE;
infos.turn_id = 0;
infos.card_id = 1;
infos.phase = 0;
infos.turn_player = 0;
for (int i = 0; i < 2; ++i) {
cost[i].count = 0;
cost[i].amount = 0;
core.hint_timing[i] = 0;
player[i].lp = 8000;
player[i].start_count = 5;
player[i].draw_count = 1;
player[i].disabled_location = 0;
player[i].used_location = 0;
player[i].extra_p_count = 0;
player[i].list_mzone.reserve(5);
player[i].list_szone.reserve(8);
player[i].list_main.reserve(45);
player[i].list_hand.reserve(10);
player[i].list_grave.reserve(30);
player[i].list_remove.reserve(30);
player[i].list_extra.reserve(15);
for(int j = 0; j < 5; ++j)
player[i].list_mzone.push_back(0);
for(int j = 0; j < 8; ++j)
player[i].list_szone.push_back(0);
core.shuffle_deck_check[i] = FALSE;
core.shuffle_hand_check[i] = FALSE;
}
core.pre_field[0] = 0;
core.pre_field[1] = 0;
for (int i = 0; i < 5; ++i)
core.opp_mzone[i] = 0;
core.summoning_card = 0;
core.summon_depth = 0;
core.summon_cancelable = FALSE;
core.chain_limit = 0;
core.chain_limit_p = 0;
core.chain_solving = FALSE;
core.conti_solving = FALSE;
core.conti_player = PLAYER_NONE;
core.win_player = 5;
core.win_reason = 0;
core.reason_effect = 0;
core.reason_player = PLAYER_NONE;
core.selfdes_disabled = FALSE;
core.flip_delayed = FALSE;
core.overdraw[0] = FALSE;
core.overdraw[1] = FALSE;
core.check_level = 0;
core.limit_tuner = 0;
core.limit_xyz = 0;
core.limit_syn = 0;
core.duel_options = 0;
core.attacker = 0;
core.attack_target = 0;
core.attack_rollback = FALSE;
core.deck_reversed = FALSE;
core.remove_brainwashing = FALSE;
core.effect_damage_step = FALSE;
core.shuffle_check_disabled = FALSE;
core.global_flag = 0;
nil_event.event_code = 0;
nil_event.event_cards = 0;
nil_event.event_player = PLAYER_NONE;
nil_event.event_value = 0;
nil_event.reason = 0;
nil_event.reason_effect = 0;
nil_event.reason_player = PLAYER_NONE;
}
field::~field() {
}
void field::reload_field_info() {
pduel->write_buffer8(MSG_RELOAD_FIELD);
card* pcard;
for(int playerid = 0; playerid < 2; ++playerid) {
pduel->write_buffer32(player[playerid].lp);
for(uint32 i = 0; i < 5; ++i) {
pcard = player[playerid].list_mzone[i];
if(pcard) {
pduel->write_buffer8(1);
pduel->write_buffer8(pcard->current.position);
pduel->write_buffer8(pcard->xyz_materials.size());
} else {
pduel->write_buffer8(0);
}
}
for(uint32 i = 0; i < 8; ++i) {
pcard = player[playerid].list_szone[i];
if(pcard) {
pduel->write_buffer8(1);
pduel->write_buffer8(pcard->current.position);
} else {
pduel->write_buffer8(0);
}
}
pduel->write_buffer8(player[playerid].list_main.size());
pduel->write_buffer8(player[playerid].list_hand.size());
pduel->write_buffer8(player[playerid].list_grave.size());
pduel->write_buffer8(player[playerid].list_remove.size());
pduel->write_buffer8(player[playerid].list_extra.size());
pduel->write_buffer8(player[playerid].extra_p_count);
}
pduel->write_buffer8(core.current_chain.size());
for(auto chit = core.current_chain.begin(); chit != core.current_chain.end(); ++chit) {
effect* peffect = chit->triggering_effect;
pduel->write_buffer32(peffect->handler->data.code);
pduel->write_buffer32(peffect->handler->get_info_location());
pduel->write_buffer8(chit->triggering_controler);
pduel->write_buffer8(chit->triggering_location);
pduel->write_buffer8(chit->triggering_sequence);
pduel->write_buffer32(peffect->description);
}
}
void field::add_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence) {
if (pcard->current.location != 0)
return;
if (!is_location_useable(playerid, location, sequence))
return;
if((pcard->data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ)) && (location & (LOCATION_HAND | LOCATION_DECK))) {
location = LOCATION_EXTRA;
pcard->operation_param = (pcard->operation_param & 0x00ffffff) | (POS_FACEDOWN_DEFENCE << 24);
}
pcard->current.controler = playerid;
pcard->current.location = location;
switch (location) {
case LOCATION_MZONE:
player[playerid].list_mzone[sequence] = pcard;
pcard->current.sequence = sequence;
break;
case LOCATION_SZONE:
player[playerid].list_szone[sequence] = pcard;
pcard->current.sequence = sequence;
break;
case LOCATION_DECK:
if (sequence == 0) { //deck top
player[playerid].list_main.push_back(pcard);
pcard->current.sequence = player[playerid].list_main.size() - 1;
pcard->current.position = POS_FACEUP_ATTACK;
} else if (sequence == 1) { //deck button
player[playerid].list_main.insert(player[playerid].list_main.begin(), pcard);
reset_sequence(playerid, LOCATION_DECK);
pcard->current.position = POS_FACEDOWN;
} else { //deck top & shuffle
player[playerid].list_main.push_back(pcard);
pcard->current.sequence = player[playerid].list_main.size() - 1;
if(!core.shuffle_check_disabled)
core.shuffle_deck_check[playerid] = TRUE;
pcard->current.position = POS_FACEDOWN;
}
break;
case LOCATION_HAND:
player[playerid].list_hand.push_back(pcard);
pcard->current.sequence = player[playerid].list_hand.size() - 1;
if(!(pcard->current.reason & REASON_DRAW) && !core.shuffle_check_disabled)
core.shuffle_hand_check[playerid] = TRUE;
break;
case LOCATION_GRAVE:
player[playerid].list_grave.push_back(pcard);
pcard->current.sequence = player[playerid].list_grave.size() - 1;
break;
case LOCATION_REMOVED:
player[playerid].list_remove.push_back(pcard);
pcard->current.sequence = player[playerid].list_remove.size() - 1;
break;
case LOCATION_EXTRA:
player[playerid].list_extra.push_back(pcard);
pcard->current.sequence = player[playerid].list_extra.size() - 1;
break;
}
pcard->apply_field_effect();
pcard->fieldid = infos.field_id++;
pcard->fieldid_r = pcard->fieldid;
pcard->turnid = infos.turn_id;
if (location == LOCATION_MZONE)
player[playerid].used_location |= 1 << sequence;
if (location == LOCATION_SZONE)
player[playerid].used_location |= 256 << sequence;
}
void field::remove_card(card* pcard) {
if (pcard->current.controler == PLAYER_NONE || pcard->current.location == 0)
return;
uint8 playerid = pcard->current.controler;
switch (pcard->current.location) {
case LOCATION_MZONE:
player[playerid].list_mzone[pcard->current.sequence] = 0;
break;
case LOCATION_SZONE:
player[playerid].list_szone[pcard->current.sequence] = 0;
break;
case LOCATION_DECK:
player[playerid].list_main.erase(player[playerid].list_main.begin() + pcard->current.sequence);
reset_sequence(playerid, LOCATION_DECK);
if(!core.shuffle_check_disabled)
core.shuffle_deck_check[playerid] = TRUE;
break;
case LOCATION_HAND:
player[playerid].list_hand.erase(player[playerid].list_hand.begin() + pcard->current.sequence);
reset_sequence(playerid, LOCATION_HAND);
break;
case LOCATION_GRAVE:
player[playerid].list_grave.erase(player[playerid].list_grave.begin() + pcard->current.sequence);
reset_sequence(playerid, LOCATION_GRAVE);
break;
case LOCATION_REMOVED:
player[playerid].list_remove.erase(player[playerid].list_remove.begin() + pcard->current.sequence);
reset_sequence(playerid, LOCATION_REMOVED);
break;
case LOCATION_EXTRA:
player[playerid].list_extra.erase(player[playerid].list_extra.begin() + pcard->current.sequence);
reset_sequence(playerid, LOCATION_EXTRA);
break;
}
pcard->cancel_field_effect();
if (pcard->current.location == LOCATION_MZONE)
player[playerid].used_location &= ~(1 << pcard->current.sequence);
if (pcard->current.location == LOCATION_SZONE)
player[playerid].used_location &= ~(256 << pcard->current.sequence);
pcard->previous.controler = pcard->current.controler;
pcard->previous.location = pcard->current.location;
pcard->previous.sequence = pcard->current.sequence;
pcard->previous.position = pcard->current.position;
pcard->current.controler = PLAYER_NONE;
pcard->current.location = 0;
pcard->current.sequence = 0;
}
void field::move_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence) {
if (!is_location_useable(playerid, location, sequence))
return;
uint8 preplayer = pcard->current.controler;
uint8 presequence = pcard->current.sequence;
if((pcard->data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ)) && (location & (LOCATION_HAND | LOCATION_DECK))) {
location = LOCATION_EXTRA;
pcard->operation_param = (pcard->operation_param & 0x00ffffff) | (POS_FACEDOWN_DEFENCE << 24);
}
if (pcard->current.location) {
if (pcard->current.location == location) {
if (pcard->current.location == LOCATION_DECK) {
if(preplayer == playerid) {
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
player[preplayer].list_main.erase(player[preplayer].list_main.begin() + pcard->current.sequence);
if (sequence == 0) { //deck top
player[playerid].list_main.push_back(pcard);
} else if (sequence == 1) {
player[playerid].list_main.insert(player[playerid].list_main.begin(), pcard);
} else {
player[playerid].list_main.push_back(pcard);
if(!core.shuffle_check_disabled)
core.shuffle_deck_check[playerid] = true;
}
reset_sequence(playerid, LOCATION_DECK);
pcard->previous.controler = preplayer;
pcard->current.controler = playerid;
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->current.reason);
return;
} else
remove_card(pcard);
} else if(location & LOCATION_ONFIELD) {
if (playerid == preplayer && sequence == presequence)
return;
if((location == LOCATION_MZONE && (sequence < 0 || sequence > 4 || player[playerid].list_mzone[sequence]))
|| (location == LOCATION_SZONE && (sequence < 0 || sequence > 4 || player[playerid].list_szone[sequence])))
return;
if(preplayer == playerid) {
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
}
pcard->previous.controler = pcard->current.controler;
pcard->previous.location = pcard->current.location;
pcard->previous.sequence = pcard->current.sequence;
pcard->previous.position = pcard->current.position;
if (location == LOCATION_MZONE) {
player[preplayer].list_mzone[presequence] = 0;
player[preplayer].used_location &= ~(1 << presequence);
player[playerid].list_mzone[sequence] = pcard;
player[playerid].used_location |= 1 << sequence;
pcard->current.controler = playerid;
pcard->current.sequence = sequence;
} else {
player[preplayer].list_szone[presequence] = 0;
player[preplayer].used_location &= ~(256 << presequence);
player[playerid].list_szone[sequence] = pcard;
player[playerid].used_location |= 256 << sequence;
pcard->current.controler = playerid;
pcard->current.sequence = sequence;
}
if(preplayer == playerid) {
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->current.reason);
}
return;
} else if(location == LOCATION_HAND) {
if(preplayer == playerid)
return;
remove_card(pcard);
} else {
if(location == LOCATION_GRAVE) {
if(pcard->current.sequence == player[pcard->current.controler].list_grave.size() - 1)
return;
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
player[pcard->current.controler].list_grave.erase(player[pcard->current.controler].list_grave.begin() + pcard->current.sequence);
player[pcard->current.controler].list_grave.push_back(pcard);
reset_sequence(pcard->current.controler, LOCATION_GRAVE);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->current.reason);
} else if(location == LOCATION_REMOVED) {
if(pcard->current.sequence == player[pcard->current.controler].list_remove.size() - 1)
return;
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
player[pcard->current.controler].list_remove.erase(player[pcard->current.controler].list_remove.begin() + pcard->current.sequence);
player[pcard->current.controler].list_remove.push_back(pcard);
reset_sequence(pcard->current.controler, LOCATION_REMOVED);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->current.reason);
} else {
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
player[pcard->current.controler].list_extra.erase(player[pcard->current.controler].list_extra.begin() + pcard->current.sequence);
player[pcard->current.controler].list_extra.push_back(pcard);
reset_sequence(pcard->current.controler, LOCATION_EXTRA);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->current.reason);
}
return;
}
} else {
if((pcard->data.type & TYPE_PENDULUM) && (location == LOCATION_GRAVE)
&& pcard->is_capable_send_to_extra(playerid)
&& (((pcard->current.location == LOCATION_MZONE) && !pcard->is_status(STATUS_SUMMON_DISABLED))
|| ((pcard->current.location == LOCATION_SZONE) && !pcard->is_status(STATUS_ACTIVATE_DISABLED)))) {
location = LOCATION_EXTRA;
pcard->operation_param = (pcard->operation_param & 0x00ffffff) | (POS_FACEUP_DEFENCE << 24);
}
remove_card(pcard);
}
}
add_card(playerid, pcard, location, sequence);
}
// add EFFECT_SET_CONTROL
void field::set_control(card* pcard, uint8 playerid, uint16 reset_phase, uint8 reset_count) {
if((core.remove_brainwashing && pcard->is_affected_by_effect(EFFECT_REMOVE_BRAINWASHING)) || pcard->refresh_control_status() == playerid)
return;
effect* peffect = pduel->new_effect();
if(core.reason_effect)
peffect->owner = core.reason_effect->handler;
else
peffect->owner = pcard;
peffect->handler = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_SET_CONTROL;
peffect->value = playerid;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT | 0xc6c0000;
if(reset_count) {
peffect->reset_flag |= RESET_PHASE | reset_phase;
if(!(peffect->reset_flag & (RESET_SELF_TURN | RESET_OPPO_TURN)))
peffect->reset_flag |= (RESET_SELF_TURN | RESET_OPPO_TURN);
peffect->reset_count |= reset_count & 0xff;
}
pcard->add_effect(peffect);
pcard->current.controler = playerid;
}
card* field::get_field_card(uint8 playerid, uint8 location, uint8 sequence) {
switch(location) {
case LOCATION_MZONE: {
if(sequence < 5)
return player[playerid].list_mzone[sequence];
else
return 0;
break;
}
case LOCATION_SZONE: {
if(sequence < 8)
return player[playerid].list_szone[sequence];
else
return 0;
break;
}
case LOCATION_DECK: {
if(sequence < player[playerid].list_main.size())
return player[playerid].list_main[sequence];
else
return 0;
break;
}
case LOCATION_HAND: {
if(sequence < player[playerid].list_hand.size())
return player[playerid].list_hand[sequence];
else
return 0;
break;
}
case LOCATION_GRAVE: {
if(sequence < player[playerid].list_grave.size())
return player[playerid].list_grave[sequence];
else
return 0;
break;
}
case LOCATION_REMOVED: {
if(sequence < player[playerid].list_remove.size())
return player[playerid].list_remove[sequence];
else
return 0;
break;
}
case LOCATION_EXTRA: {
if(sequence < player[playerid].list_extra.size())
return player[playerid].list_extra[sequence];
else
return 0;
break;
}
}
return 0;
}
int32 field::is_location_useable(uint8 playerid, uint8 location, uint8 sequence) {
if (location != LOCATION_MZONE && location != LOCATION_SZONE)
return TRUE;
int32 flag = player[playerid].disabled_location | player[playerid].used_location;
if (location == LOCATION_MZONE && flag & (1 << sequence))
return FALSE;
if (location == LOCATION_SZONE && flag & (256 << sequence))
return FALSE;
return TRUE;
}
int32 field::get_useable_count(uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32* list) {
if (location != LOCATION_MZONE && location != LOCATION_SZONE)
return 0;
uint32 flag = player[playerid].disabled_location | player[playerid].used_location;
uint32 used_flag = player[playerid].used_location;
effect_set eset;
if (location == LOCATION_MZONE) {
flag = (flag & 0x1f);
used_flag = (used_flag & 0x1f);
if(uplayer < 2)
filter_player_effect(playerid, EFFECT_MAX_MZONE, &eset);
} else {
flag = (flag & 0x1f00) >> 8;
used_flag = (used_flag & 0x1f00) >> 8;
if(uplayer < 2)
filter_player_effect(playerid, EFFECT_MAX_SZONE, &eset);
}
if(list)
*list = flag;
if(eset.size()) {
int32 max = 5;
for (int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(uplayer, PARAM_TYPE_INT);
pduel->lua->add_param(reason, PARAM_TYPE_INT);
int32 v = eset[i]->get_value(3);
if (max > v)
max = v;
}
int32 block = 5 - field_used_count[flag];
int32 limit = max - field_used_count[used_flag];
return block < limit ? block : limit;
} else {
return 5 - field_used_count[flag];
}
}
void field::shuffle(uint8 playerid, uint8 location) {
if(!(location & (LOCATION_HAND | LOCATION_DECK)))
return;
card_vector& svector = (location == LOCATION_HAND) ? player[playerid].list_hand : player[playerid].list_main;
if(svector.size() == 0)
return;
if(location == LOCATION_HAND) {
bool shuffle = false;
for(auto cit = svector.begin(); cit != svector.end(); ++cit)
if(!(*cit)->is_status(STATUS_IS_PUBLIC))
shuffle = true;
if(!shuffle) {
core.shuffle_hand_check[playerid] = FALSE;
return;
}
}
if(location == LOCATION_HAND || !(core.duel_options & DUEL_PSEUDO_SHUFFLE)) {
if(svector.size() > 1) {
uint32 i = 0, s = svector.size(), r;
for(i = 0; i < s - 1; ++i) {
r = pduel->get_next_integer(i, s - 1);
card* t = svector[i];
svector[i] = svector[r];
svector[r] = t;
}
reset_sequence(playerid, location);
}
}
if(location == LOCATION_HAND) {
pduel->write_buffer8(MSG_SHUFFLE_HAND);
pduel->write_buffer8(playerid);
pduel->write_buffer8(player[playerid].list_hand.size());
for(auto cit = svector.begin(); cit != svector.end(); ++cit)
pduel->write_buffer32((*cit)->data.code);
core.shuffle_hand_check[playerid] = FALSE;
} else {
pduel->write_buffer8(MSG_SHUFFLE_DECK);
pduel->write_buffer8(playerid);
core.shuffle_deck_check[playerid] = FALSE;
if(core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) {
card* ptop = svector.back();
if(core.deck_reversed || (ptop->current.position == POS_FACEUP_DEFENCE)) {
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(playerid);
pduel->write_buffer8(0);
if(ptop->current.position != POS_FACEUP_DEFENCE)
pduel->write_buffer32(ptop->data.code);
else
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
}
}
}
void field::reset_sequence(uint8 playerid, uint8 location) {
if(location & (LOCATION_ONFIELD))
return;
card_vector::iterator cit;
uint32 i = 0;
switch(location) {
case LOCATION_DECK:
for(cit = player[playerid].list_main.begin(), i = 0; cit != player[playerid].list_main.end(); ++cit, ++i)
(*cit)->current.sequence = i;
break;
case LOCATION_HAND:
for(cit = player[playerid].list_hand.begin(), i = 0; cit != player[playerid].list_hand.end(); ++cit, ++i)
(*cit)->current.sequence = i;
break;
case LOCATION_EXTRA:
for(cit = player[playerid].list_extra.begin(), i = 0; cit != player[playerid].list_extra.end(); ++cit, ++i)
(*cit)->current.sequence = i;
break;
case LOCATION_GRAVE:
for(cit = player[playerid].list_grave.begin(), i = 0; cit != player[playerid].list_grave.end(); ++cit, ++i)
(*cit)->current.sequence = i;
break;
case LOCATION_REMOVED:
for(cit = player[playerid].list_remove.begin(), i = 0; cit != player[playerid].list_remove.end(); ++cit, ++i)
(*cit)->current.sequence = i;
break;
}
}
void field::swap_deck_and_grave(uint8 playerid) {
card_vector::iterator clit;
for(clit = player[playerid].list_grave.begin(); clit != player[playerid].list_grave.end(); ++clit) {
(*clit)->previous.location = LOCATION_GRAVE;
(*clit)->previous.sequence = (*clit)->current.sequence;
(*clit)->enable_field_effect(false);
(*clit)->cancel_field_effect();
}
for(clit = player[playerid].list_main.begin(); clit != player[playerid].list_main.end(); ++clit) {
(*clit)->previous.location = LOCATION_DECK;
(*clit)->previous.sequence = (*clit)->current.sequence;
(*clit)->enable_field_effect(false);
(*clit)->cancel_field_effect();
}
player[playerid].list_grave.swap(player[playerid].list_main);
card_vector ex;
for(clit = player[playerid].list_main.begin(); clit != player[playerid].list_main.end(); ) {
if((*clit)->data.type & (TYPE_FUSION | TYPE_SYNCHRO | TYPE_XYZ)) {
ex.push_back(*clit);
clit = player[playerid].list_main.erase(clit);
} else
++clit;
}
for(clit = player[playerid].list_grave.begin(); clit != player[playerid].list_grave.end(); ++clit) {
(*clit)->current.location = LOCATION_GRAVE;
(*clit)->current.reason = REASON_EFFECT;
(*clit)->current.reason_effect = core.reason_effect;
(*clit)->current.reason_player = core.reason_player;
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
(*clit)->reset(RESET_TOGRAVE, RESET_EVENT);
}
for(clit = player[playerid].list_main.begin(); clit != player[playerid].list_main.end(); ++clit) {
(*clit)->current.location = LOCATION_DECK;
(*clit)->current.reason = REASON_EFFECT;
(*clit)->current.reason_effect = core.reason_effect;
(*clit)->current.reason_player = core.reason_player;
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
(*clit)->reset(RESET_TODECK, RESET_EVENT);
}
for(clit = ex.begin(); clit != ex.end(); ++clit) {
(*clit)->current.location = LOCATION_EXTRA;
(*clit)->current.reason = REASON_EFFECT;
(*clit)->current.reason_effect = core.reason_effect;
(*clit)->current.reason_player = core.reason_player;
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
(*clit)->reset(RESET_TODECK, RESET_EVENT);
}
player[playerid].list_extra.insert(player[playerid].list_extra.end(), ex.begin(), ex.end());
reset_sequence(playerid, LOCATION_GRAVE);
reset_sequence(playerid, LOCATION_EXTRA);
pduel->write_buffer8(MSG_SWAP_GRAVE_DECK);
pduel->write_buffer8(playerid);
shuffle(playerid, LOCATION_DECK);
}
void field::reverse_deck(uint8 playerid) {
int32 count = player[playerid].list_main.size();
if(count == 0)
return;
for(int i = 0; i < count / 2; ++i) {
card* tmp = player[playerid].list_main[i];
tmp->current.sequence = count - 1 - i;
player[playerid].list_main[count - 1 - i]->current.sequence = i;
player[playerid].list_main[i] = player[playerid].list_main[count - 1 - i];
player[playerid].list_main[count - 1 - i] = tmp;
}
}
void field::tag_swap(uint8 playerid) {
card_vector::iterator clit;
//main
for(clit = player[playerid].list_main.begin(); clit != player[playerid].list_main.end(); ++clit) {
(*clit)->enable_field_effect(false);
(*clit)->cancel_field_effect();
}
std::swap(player[playerid].list_main, player[playerid].tag_list_main);
for(clit = player[playerid].list_main.begin(); clit != player[playerid].list_main.end(); ++clit) {
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
}
//hand
for(clit = player[playerid].list_hand.begin(); clit != player[playerid].list_hand.end(); ++clit) {
(*clit)->enable_field_effect(false);
(*clit)->cancel_field_effect();
}
std::swap(player[playerid].list_hand, player[playerid].tag_list_hand);
for(clit = player[playerid].list_hand.begin(); clit != player[playerid].list_hand.end(); ++clit) {
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
}
//extra
for(clit = player[playerid].list_extra.begin(); clit != player[playerid].list_extra.end(); ++clit) {
(*clit)->enable_field_effect(false);
(*clit)->cancel_field_effect();
}
std::swap(player[playerid].list_extra, player[playerid].tag_list_extra);
for(clit = player[playerid].list_extra.begin(); clit != player[playerid].list_extra.end(); ++clit) {
(*clit)->apply_field_effect();
(*clit)->enable_field_effect(true);
}
pduel->write_buffer8(MSG_TAG_SWAP);
pduel->write_buffer8(playerid);
pduel->write_buffer8(player[playerid].list_main.size());
pduel->write_buffer8(player[playerid].list_extra.size());
pduel->write_buffer8(player[playerid].list_hand.size());
if(core.deck_reversed && player[playerid].list_main.size())
pduel->write_buffer32(player[playerid].list_main.back()->data.code);
else
pduel->write_buffer32(0);
for(auto cit = player[playerid].list_hand.begin(); cit != player[playerid].list_hand.end(); ++cit)
pduel->write_buffer32((*cit)->data.code | ((*cit)->is_status(STATUS_IS_PUBLIC) ? 0x80000000 : 0));
}
void field::add_effect(effect* peffect, uint8 owner_player) {
if (!peffect->handler) {
peffect->flag |= EFFECT_FLAG_FIELD_ONLY;
peffect->handler = peffect->owner;
peffect->effect_owner = owner_player;
peffect->id = infos.field_id++;
}
if((peffect->type & 0x7e0)
|| (core.reason_effect && (core.reason_effect->status & EFFECT_STATUS_ACTIVATED)))
peffect->status |= EFFECT_STATUS_ACTIVATED;
peffect->card_type = peffect->owner->data.type;
effect_container::iterator it;
if (!(peffect->type & EFFECT_TYPE_ACTIONS)) {
it = effects.aura_effect.insert(make_pair(peffect->code, peffect));
if(peffect->code == EFFECT_SPSUMMON_COUNT_LIMIT)
effects.spsummon_count_eff.insert(peffect);
} else {
if (peffect->type & EFFECT_TYPE_IGNITION)
it = effects.ignition_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_ACTIVATE)
it = effects.activate_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_TRIGGER_O && peffect->type & EFFECT_TYPE_FIELD)
it = effects.trigger_o_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_TRIGGER_F && peffect->type & EFFECT_TYPE_FIELD)
it = effects.trigger_f_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_QUICK_O)
it = effects.quick_o_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_QUICK_F)
it = effects.quick_f_effect.insert(make_pair(peffect->code, peffect));
else if (peffect->type & EFFECT_TYPE_CONTINUOUS)
it = effects.continuous_effect.insert(make_pair(peffect->code, peffect));
}
effects.indexer.insert(make_pair(peffect, it));
if((peffect->flag & EFFECT_FLAG_FIELD_ONLY)) {
if(peffect->flag & EFFECT_FLAG_OATH)
effects.oath.insert(make_pair(peffect, core.reason_effect));
if(peffect->reset_flag & RESET_PHASE)
effects.pheff.insert(peffect);
if(peffect->reset_flag & RESET_CHAIN)
effects.cheff.insert(peffect);
if(peffect->flag & EFFECT_FLAG_COUNT_LIMIT)
effects.rechargeable.insert(peffect);
}
}
void field::remove_effect(effect* peffect) {
auto eit = effects.indexer.find(peffect);
if (eit == effects.indexer.end())
return;
auto it = eit->second;
if (!(peffect->type & EFFECT_TYPE_ACTIONS)) {
effects.aura_effect.erase(it);
if(peffect->code == EFFECT_SPSUMMON_COUNT_LIMIT)
effects.spsummon_count_eff.erase(peffect);
} else {
if (peffect->type & EFFECT_TYPE_IGNITION)
effects.ignition_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_ACTIVATE)
effects.activate_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_TRIGGER_O)
effects.trigger_o_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_TRIGGER_F)
effects.trigger_f_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_QUICK_O)
effects.quick_o_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_QUICK_F)
effects.quick_f_effect.erase(it);
else if (peffect->type & EFFECT_TYPE_CONTINUOUS)
effects.continuous_effect.erase(it);
}
effects.indexer.erase(peffect);
if((peffect->flag & EFFECT_FLAG_FIELD_ONLY)) {
if(peffect->flag & EFFECT_FLAG_OATH)
effects.oath.erase(peffect);
if(peffect->reset_flag & RESET_PHASE)
effects.pheff.erase(peffect);
if(peffect->reset_flag & RESET_CHAIN)
effects.cheff.erase(peffect);
if(peffect->flag & EFFECT_FLAG_COUNT_LIMIT)
effects.rechargeable.erase(peffect);
core.reseted_effects.insert(peffect);
}
}
void field::remove_oath_effect(effect* reason_effect) {
for(auto oeit = effects.oath.begin(); oeit != effects.oath.end();) {
auto rm = oeit++;
if(rm->second == reason_effect) {
effect* peffect = rm->first;
effects.oath.erase(rm);
if(peffect->flag & EFFECT_FLAG_FIELD_ONLY)
remove_effect(peffect);
else
peffect->handler->remove_effect(peffect);
}
}
}
void field::reset_effect(uint32 id, uint32 reset_type) {
int32 result;
for (auto it = effects.indexer.begin(); it != effects.indexer.end();) {
auto rm = it++;
auto peffect = rm->first;
auto pit = rm->second;
if (!(peffect->flag & EFFECT_FLAG_FIELD_ONLY))
continue;
result = peffect->reset(id, reset_type);
if (result) {
if (!(peffect->type & EFFECT_TYPE_ACTIONS)) {
if (peffect->is_disable_related())
update_disable_check_list(peffect);
effects.aura_effect.erase(pit);
} else {
if (peffect->type & EFFECT_TYPE_IGNITION)
effects.ignition_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_ACTIVATE)
effects.activate_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_TRIGGER_O)
effects.trigger_o_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_TRIGGER_F)
effects.trigger_f_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_QUICK_O)
effects.quick_o_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_QUICK_F)
effects.quick_f_effect.erase(pit);
else if (peffect->type & EFFECT_TYPE_CONTINUOUS)
effects.continuous_effect.erase(pit);
}
effects.indexer.erase(peffect);
pduel->delete_effect(peffect);
}
}
}
void field::reset_phase(uint32 phase) {
for(auto eit = effects.pheff.begin(); eit != effects.pheff.end();) {
auto rm = eit++;
if((*rm)->reset(phase, RESET_PHASE)) {
if((*rm)->flag & EFFECT_FLAG_FIELD_ONLY)
remove_effect((*rm));
else
(*rm)->handler->remove_effect((*rm));
}
}
}
void field::reset_chain() {
for(auto eit = effects.cheff.begin(); eit != effects.cheff.end();) {
auto rm = eit++;
if((*rm)->flag & EFFECT_FLAG_FIELD_ONLY)
remove_effect((*rm));
else
(*rm)->handler->remove_effect((*rm));
}
}
void field::add_effect_code(uint32 code, uint32 playerid) {
auto& count_map = (code & EFFECT_COUNT_CODE_DUEL) ? core.effect_count_code_duel : core.effect_count_code;
count_map[code + (playerid << 30)]++;
}
uint32 field::get_effect_code(uint32 code, uint32 playerid) {
auto& count_map = (code & EFFECT_COUNT_CODE_DUEL) ? core.effect_count_code_duel : core.effect_count_code;
auto iter = count_map.find(code + (playerid << 30));
if(iter == count_map.end())
return 0;
return iter->second;
}
void field::dec_effect_code(uint32 code, uint32 playerid) {
auto& count_map = (code & EFFECT_COUNT_CODE_DUEL) ? core.effect_count_code_duel : core.effect_count_code;
auto iter = count_map.find(code + (playerid << 30));
if(iter == count_map.end())
return;
if(iter->second > 0)
iter->second--;
}
void field::filter_field_effect(uint32 code, effect_set* eset, uint8 sort) {
effect* peffect;
auto rg = effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ) {
peffect = rg.first->second;
++rg.first;
if (peffect->is_available())
eset->add_item(peffect);
}
if(sort)
eset->sort();
}
void field::filter_affected_cards(effect* peffect, card_set* cset) {
if ((peffect->type & EFFECT_TYPE_ACTIONS) || !(peffect->type & EFFECT_TYPE_FIELD) || (peffect->flag & EFFECT_FLAG_PLAYER_TARGET))
return;
uint8 self = peffect->get_handler_player();
if(self == PLAYER_NONE)
return;
card* pcard;
card_vector::iterator it;
uint16 range = peffect->s_range;
for(uint32 p = 0; p < 2; ++p) {
if (range & LOCATION_MZONE) {
for (int i = 0; i < 5; ++i) {
pcard = player[self].list_mzone[i];
if (pcard && peffect->is_target(pcard))
cset->insert(pcard);
}
}
if (range & LOCATION_SZONE) {
for (int i = 0; i < 8; ++i) {
pcard = player[self].list_szone[i];
if (pcard && peffect->is_target(pcard))
cset->insert(pcard);
}
}
if (range & LOCATION_GRAVE) {
for (it = player[self].list_grave.begin(); it != player[self].list_grave.end(); ++it) {
pcard = *it;
if (peffect->is_target(pcard))
cset->insert(pcard);
}
}
if (range & LOCATION_REMOVED) {
for (it = player[self].list_remove.begin(); it != player[self].list_remove.end(); ++it) {
pcard = *it;
if (peffect->is_target(pcard))
cset->insert(pcard);
}
}
if (range & LOCATION_HAND) {
for (it = player[self].list_hand.begin(); it != player[self].list_hand.end(); ++it) {
pcard = *it;
if (peffect->is_target(pcard))
cset->insert(pcard);
}
}
range = peffect->o_range;
self = 1 - self;
}
}
void field::filter_player_effect(uint8 playerid, uint32 code, effect_set* eset, uint8 sort) {
auto rg = effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
effect* peffect = rg.first->second;
if (peffect->is_target_player(playerid) && peffect->is_available())
eset->add_item(peffect);
}
if(sort)
eset->sort();
}
int32 field::filter_matching_card(int32 findex, uint8 self, uint32 location1, uint32 location2, group* pgroup, card* pexception, uint32 extraargs, card** pret, int32 fcount, int32 is_target) {
if(self != 0 && self != 1)
return FALSE;
card* pcard;
int32 count = 0;
uint32 location = location1;
for(uint32 p = 0; p < 2; ++p) {
if(location & LOCATION_MZONE) {
for(uint32 i = 0; i < 5; ++i) {
pcard = player[self].list_mzone[i];
if(pcard && !pcard->is_status(STATUS_SUMMONING) && !pcard->is_status(STATUS_SUMMON_DISABLED) && !pcard->is_status(STATUS_SPSUMMON_STEP)
&& pcard != pexception && pduel->lua->check_matching(pcard, findex, extraargs)
&& (!is_target || pcard->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = pcard;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(pcard);
}
}
}
}
if(location & LOCATION_SZONE) {
for(uint32 i = 0; i < 8; ++i) {
pcard = player[self].list_szone[i];
if(pcard && pcard != pexception && pduel->lua->check_matching(pcard, findex, extraargs)
&& (!is_target || pcard->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = pcard;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(pcard);
}
}
}
}
if(location & LOCATION_DECK) {
for(auto cit = player[self].list_main.rbegin(); cit != player[self].list_main.rend(); ++cit) {
if(*cit != pexception && pduel->lua->check_matching(*cit, findex, extraargs)
&& (!is_target || (*cit)->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = *cit;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(*cit);
}
}
}
}
if(location & LOCATION_EXTRA) {
for(auto cit = player[self].list_extra.rbegin(); cit != player[self].list_extra.rend(); ++cit) {
if(*cit != pexception && pduel->lua->check_matching(*cit, findex, extraargs)
&& (!is_target || (*cit)->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = *cit;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(*cit);
}
}
}
}
if(location & LOCATION_HAND) {
for(auto cit = player[self].list_hand.begin(); cit != player[self].list_hand.end(); ++cit) {
if(*cit != pexception && pduel->lua->check_matching(*cit, findex, extraargs)
&& (!is_target || (*cit)->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = *cit;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(*cit);
}
}
}
}
if(location & LOCATION_GRAVE) {
for(auto cit = player[self].list_grave.rbegin(); cit != player[self].list_grave.rend(); ++cit) {
if(*cit != pexception && pduel->lua->check_matching(*cit, findex, extraargs)
&& (!is_target || (*cit)->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = *cit;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(*cit);
}
}
}
}
if(location & LOCATION_REMOVED) {
for(auto cit = player[self].list_remove.rbegin(); cit != player[self].list_remove.rend(); ++cit) {
if(*cit != pexception && pduel->lua->check_matching(*cit, findex, extraargs)
&& (!is_target || (*cit)->is_capable_be_effect_target(core.reason_effect, core.reason_player))) {
if(pret) {
*pret = *cit;
return TRUE;
}
count ++;
if(fcount && count >= fcount)
return TRUE;
if(pgroup) {
pgroup->container.insert(*cit);
}
}
}
}
location = location2;
self = 1 - self;
}
return FALSE;
}
int32 field::filter_field_card(uint8 self, uint32 location1, uint32 location2, group* pgroup) {
if(self != 0 && self != 1)
return 0;
uint32 location = location1;
uint32 count = 0;
card* pcard;
for(uint32 p = 0; p < 2; ++p) {
if(location & LOCATION_MZONE) {
for(int i = 0; i < 5; ++i) {
pcard = player[self].list_mzone[i];
if(pcard && !pcard->is_status(STATUS_SUMMONING)) {
if(pgroup)
pgroup->container.insert(pcard);
count++;
}
}
}
if(location & LOCATION_SZONE) {
for(int i = 0; i < 8; ++i) {
pcard = player[self].list_szone[i];
if(pcard) {
if(pgroup)
pgroup->container.insert(pcard);
count++;
}
}
}
if(location & LOCATION_HAND) {
if(pgroup)
pgroup->container.insert(player[self].list_hand.begin(), player[self].list_hand.end());
count += player[self].list_hand.size();
}
if(location & LOCATION_DECK) {
if(pgroup)
pgroup->container.insert(player[self].list_main.rbegin(), player[self].list_main.rend());
count += player[self].list_main.size();
}
if(location & LOCATION_EXTRA) {
if(pgroup)
pgroup->container.insert(player[self].list_extra.rbegin(), player[self].list_extra.rend());
count += player[self].list_extra.size();
}
if(location & LOCATION_GRAVE) {
if(pgroup)
pgroup->container.insert(player[self].list_grave.rbegin(), player[self].list_grave.rend());
count += player[self].list_grave.size();
}
if(location & LOCATION_REMOVED) {
if(pgroup)
pgroup->container.insert(player[self].list_remove.rbegin(), player[self].list_remove.rend());
count += player[self].list_remove.size();
}
location = location2;
self = 1 - self;
}
return count;
}
effect* field::is_player_affected_by_effect(uint8 playerid, uint32 code) {
auto rg = effects.aura_effect.equal_range(code);
for (; rg.first != rg.second; ++rg.first) {
effect* peffect = rg.first->second;
if (peffect->is_target_player(playerid) && peffect->is_available())
return peffect;
}
return 0;
}
int32 field::get_release_list(uint8 playerid, card_set* release_list, card_set* ex_list, int32 use_con, int32 use_hand, int32 fun, int32 exarg, card* exp) {
card* pcard;
uint32 rcount = 0;
for(uint32 i = 0; i < 5; ++i) {
pcard = player[playerid].list_mzone[i];
if(pcard && pcard != exp && pcard->is_releasable_by_nonsummon(playerid)
&& (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
if(release_list)
release_list->insert(pcard);
pcard->operation_param = 1;
rcount++;
}
}
if(use_hand) {
for(uint32 i = 0; i < player[playerid].list_hand.size(); ++i) {
pcard = player[playerid].list_hand[i];
if(pcard && pcard != exp && pcard->is_releasable_by_nonsummon(playerid)
&& (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
if(release_list)
release_list->insert(pcard);
pcard->operation_param = 1;
rcount++;
}
}
}
for(uint32 i = 0; i < 5; ++i) {
pcard = player[1 - playerid].list_mzone[i];
if(pcard && pcard != exp && (pcard->is_position(POS_FACEUP) || !use_con) && pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)
&& pcard->is_releasable_by_nonsummon(playerid) && (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
if(ex_list)
ex_list->insert(pcard);
pcard->operation_param = 1;
rcount++;
}
}
return rcount;
}
int32 field::check_release_list(uint8 playerid, int32 count, int32 use_con, int32 use_hand, int32 fun, int32 exarg, card* exp) {
card* pcard;
for(uint32 i = 0; i < 5; ++i) {
pcard = player[playerid].list_mzone[i];
if(pcard && pcard != exp && pcard->is_releasable_by_nonsummon(playerid)
&& (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
count--;
if(count == 0)
return TRUE;
}
}
if(use_hand) {
for(uint32 i = 0; i < player[playerid].list_hand.size(); ++i) {
pcard = player[playerid].list_hand[i];
if(pcard && pcard != exp && pcard->is_releasable_by_nonsummon(playerid)
&& (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
count--;
if(count == 0)
return TRUE;
}
}
}
for(uint32 i = 0; i < 5; ++i) {
pcard = player[1 - playerid].list_mzone[i];
if(pcard && pcard != exp && (!use_con || pcard->is_position(POS_FACEUP)) && pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)
&& pcard->is_releasable_by_nonsummon(playerid) && (!use_con || pduel->lua->check_matching(pcard, fun, exarg))) {
count--;
if(count == 0)
return TRUE;
}
}
return FALSE;
}
int32 field::get_summon_release_list(card* target, card_set* release_list, card_set* ex_list, card_set* ex_list_sum, group* mg, uint32 ex) {
uint8 p = target->current.controler;
card* pcard;
uint32 rcount = 0;
for(int i = 0; i < 5; ++i) {
pcard = player[p].list_mzone[i];
if(pcard && pcard->is_releasable_by_summon(p, target)) {
if(mg && !mg->has_card(pcard))
continue;
if(release_list)
release_list->insert(pcard);
if(pcard->is_affected_by_effect(EFFECT_DOUBLE_TRIBUTE, target))
pcard->operation_param = 2;
else
pcard->operation_param = 1;
rcount += pcard->operation_param;
}
}
uint32 ex_sum_max = 0;
for(int i = 0; i < 5; ++i) {
pcard = player[1 - p].list_mzone[i];
if(!(pcard && pcard->is_releasable_by_summon(p, target)))
continue;
if(mg && !mg->has_card(pcard))
continue;
if(ex || pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)) {
if(ex_list)
ex_list->insert(pcard);
if(pcard->is_affected_by_effect(EFFECT_DOUBLE_TRIBUTE, target))
pcard->operation_param = 2;
else
pcard->operation_param = 1;
rcount += pcard->operation_param;
} else {
effect* peffect = pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE_SUM);
if(!peffect || ((peffect->flag & EFFECT_FLAG_COUNT_LIMIT) && (peffect->reset_count & 0xf00) == 0))
continue;
if(ex_list_sum)
ex_list_sum->insert(pcard);
if(pcard->is_affected_by_effect(EFFECT_DOUBLE_TRIBUTE, target))
pcard->operation_param = 2;
else
pcard->operation_param = 1;
if(ex_sum_max < pcard->operation_param)
ex_sum_max = pcard->operation_param;
}
}
return rcount + ex_sum_max;
}
int32 field::get_summon_count_limit(uint8 playerid) {
effect_set eset;
filter_player_effect(playerid, EFFECT_SET_SUMMON_COUNT_LIMIT, &eset);
int32 count = 1, c;
for(int32 i = 0; i < eset.size(); ++i) {
c = eset[i]->get_value();
if(c > count)
count = c;
}
return count;
}
int32 field::get_draw_count(uint8 playerid) {
effect_set eset;
filter_player_effect(infos.turn_player, EFFECT_DRAW_COUNT, &eset);
int32 count = player[playerid].draw_count;
if(eset.size())
count = eset.get_last()->get_value();
return count;
}
void field::get_ritual_material(uint8 playerid, effect* peffect, card_set* material) {
card* pcard;
for(int i = 0; i < 5; ++i) {
pcard = player[playerid].list_mzone[i];
if(pcard && pcard->get_level() && pcard->is_affect_by_effect(core.reason_effect)
&& pcard->is_releasable_by_nonsummon(playerid) && pcard->is_releasable_by_effect(playerid, peffect))
material->insert(pcard);
}
for(int i = 0; i < 5; ++i) {
pcard = player[1 - playerid].list_mzone[i];
if(pcard && pcard->get_level() && pcard->is_affect_by_effect(core.reason_effect)
&& pcard->is_affected_by_effect(EFFECT_EXTRA_RELEASE)
&& pcard->is_releasable_by_nonsummon(playerid) && pcard->is_releasable_by_effect(playerid, peffect))
material->insert(pcard);
}
for(auto cit = player[playerid].list_hand.begin(); cit != player[playerid].list_hand.end(); ++cit)
if(((*cit)->data.type & TYPE_MONSTER) && (*cit)->is_releasable_by_nonsummon(playerid))
material->insert((*cit));
for(auto cit = player[playerid].list_grave.begin(); cit != player[playerid].list_grave.end(); ++cit)
if(((*cit)->data.type & TYPE_MONSTER) && (*cit)->is_affected_by_effect(EFFECT_EXTRA_RITUAL_MATERIAL) && (*cit)->is_removeable(playerid))
material->insert((*cit));
}
void field::ritual_release(card_set* material) {
card_set rel;
card_set rem;
for(auto cit = material->begin(); cit != material->end(); ++cit) {
if((*cit)->current.location == LOCATION_GRAVE)
rem.insert(*cit);
else
rel.insert(*cit);
}
release(&rel, core.reason_effect, REASON_RITUAL + REASON_EFFECT + REASON_MATERIAL, core.reason_player);
send_to(&rem, core.reason_effect, REASON_RITUAL + REASON_EFFECT + REASON_MATERIAL, core.reason_player, PLAYER_NONE, LOCATION_REMOVED, 0, POS_FACEUP);
}
void field::get_xyz_material(card* scard, int32 findex, uint32 lv, int32 maxc) {
card* pcard = 0;
int32 playerid = scard->current.controler;
core.xmaterial_lst.clear();
uint32 xyz_level;
for(int i = 0; i < 5; ++i) {
pcard = player[playerid].list_mzone[i];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->is_can_be_xyz_material(scard) && (xyz_level = pcard->check_xyz_level(scard, lv))
&& (findex == 0 || pduel->lua->check_matching(pcard, findex, 0)))
core.xmaterial_lst.insert(std::make_pair((xyz_level >> 12) & 0xf, pcard));
}
for(int i = 0; i < 5; ++i) {
pcard = player[1 - playerid].list_mzone[i];
if(pcard && pcard->is_position(POS_FACEUP) && pcard->is_can_be_xyz_material(scard) && (xyz_level = pcard->check_xyz_level(scard, lv))
&& pcard->is_affected_by_effect(EFFECT_XYZ_MATERIAL) && (findex == 0 || pduel->lua->check_matching(pcard, findex, 0)))
core.xmaterial_lst.insert(std::make_pair((xyz_level >> 12) & 0xf, pcard));
}
if(core.global_flag & GLOBALFLAG_XMAT_COUNT_LIMIT) {
if(maxc > (int32)core.xmaterial_lst.size())
maxc = (int32)core.xmaterial_lst.size();
auto iter = core.xmaterial_lst.lower_bound(maxc);
core.xmaterial_lst.erase(core.xmaterial_lst.begin(), iter);
}
}
void field::get_overlay_group(uint8 self, uint8 s, uint8 o, card_set* pset) {
uint8 c = s;
card* pcard;
for(int p = 0; p < 2; ++p) {
if(c) {
for(int i = 0; i < 5; ++i) {
pcard = player[self].list_mzone[i];
if(pcard && !pcard->is_status(STATUS_SUMMONING) && pcard->xyz_materials.size())
pset->insert(pcard->xyz_materials.begin(), pcard->xyz_materials.end());
}
}
self = 1 - self;
c = o;
}
}
int32 field::get_overlay_count(uint8 self, uint8 s, uint8 o) {
uint8 c = s;
uint32 count = 0;
for(int p = 0; p < 2; ++p) {
if(c) {
for(int i = 0; i < 5; ++i) {
card* pcard = player[self].list_mzone[i];
if(pcard && !pcard->is_status(STATUS_SUMMONING))
count += pcard->xyz_materials.size();
}
}
self = 1 - self;
c = o;
}
return count;
}
void field::update_disable_check_list(effect* peffect) {
card_set cset;
filter_affected_cards(peffect, &cset);
for (auto it = cset.begin(); it != cset.end(); ++it)
add_to_disable_check_list(*it);
}
void field::add_to_disable_check_list(card* pcard) {
if (effects.disable_check_set.find(pcard) != effects.disable_check_set.end())
return;
effects.disable_check_set.insert(pcard);
effects.disable_check_list.push_back(pcard);
}
void field::adjust_disable_check_list() {
card* checking;
int32 pre_disable, new_disable;
if (!effects.disable_check_list.size())
return;
card_set checked;
do {
checked.clear();
while (effects.disable_check_list.size()) {
checking = effects.disable_check_list.front();
effects.disable_check_list.pop_front();
effects.disable_check_set.erase(checking);
checked.insert(checking);
if (checking->is_status(STATUS_TO_ENABLE + STATUS_TO_DISABLE))
continue;
pre_disable = checking->is_status(STATUS_DISABLED);
checking->refresh_disable_status();
new_disable = checking->is_status(STATUS_DISABLED);
if (pre_disable != new_disable && checking->is_status(STATUS_EFFECT_ENABLED)) {
checking->filter_disable_related_cards();
if (pre_disable)
checking->set_status(STATUS_TO_ENABLE, TRUE);
else
checking->set_status(STATUS_TO_DISABLE, TRUE);
}
}
for (card_set::iterator it = checked.begin(); it != checked.end(); ++it) {
if((*it)->is_status(STATUS_DISABLED) && (*it)->is_status(STATUS_TO_DISABLE) && !(*it)->is_status(STATUS_TO_ENABLE))
(*it)->reset(RESET_DISABLE, RESET_EVENT);
(*it)->set_status(STATUS_TO_ENABLE + STATUS_TO_DISABLE, FALSE);
}
} while(effects.disable_check_list.size());
}
void field::adjust_self_destroy_set() {
if(core.selfdes_disabled || !core.self_destroy_set.empty() || !core.self_tograve_set.empty())
return;
card_set cset;
for(uint8 p = 0; p < 2; ++p) {
for(uint8 i = 0; i < 5; ++i) {
card* pcard = player[p].list_mzone[i];
if(pcard && pcard->is_position(POS_FACEUP))
cset.insert(pcard);
}
for(uint8 i = 0; i < 8; ++i) {
card* pcard = player[p].list_szone[i];
if(pcard && pcard->is_position(POS_FACEUP))
cset.insert(pcard);
}
}
core.self_destroy_set.clear();
core.self_tograve_set.clear();
effect* peffect;
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
if((!pcard->is_status(STATUS_DISABLED) && (peffect = check_unique_onfield(pcard, pcard->current.controler)))
|| (peffect = pcard->is_affected_by_effect(EFFECT_SELF_DESTROY))) {
core.self_destroy_set.insert(pcard);
pcard->current.reason_effect = peffect;
pcard->current.reason_player = peffect->get_handler_player();
}
}
if(core.global_flag & GLOBALFLAG_SELF_TOGRAVE) {
for(auto cit = cset.begin(); cit != cset.end(); ++cit) {
card* pcard = *cit;
if(peffect = pcard->is_affected_by_effect(EFFECT_SELF_TOGRAVE)) {
core.self_tograve_set.insert(pcard);
pcard->current.reason_effect = peffect;
pcard->current.reason_player = peffect->get_handler_player();
}
}
}
if(!core.self_destroy_set.empty() || !core.self_tograve_set.empty())
add_process(PROCESSOR_SELF_DESTROY, 0, 0, 0, 0, 0);
}
void field::add_unique_card(card* pcard) {
uint8 con = pcard->current.controler;
if(pcard->unique_pos[0])
core.unique_cards[con].insert(pcard);
if(pcard->unique_pos[1])
core.unique_cards[1 - con].insert(pcard);
pcard->unique_uid = infos.copy_id++;
}
void field::remove_unique_card(card* pcard) {
uint8 con = pcard->current.controler;
if(con == PLAYER_NONE)
return;
if(pcard->unique_pos[0])
core.unique_cards[con].erase(pcard);
if(pcard->unique_pos[1])
core.unique_cards[1 - con].erase(pcard);
}
effect* field::check_unique_onfield(card* pcard, uint8 controler) {
if(!pcard->unique_code)
return 0;
for(auto iter = core.unique_cards[controler].begin(); iter != core.unique_cards[controler].end(); ++iter) {
card* ucard = *iter;
if((ucard != pcard) && ucard->get_status(STATUS_EFFECT_ENABLED) && (ucard->unique_code == pcard->unique_code)
&& (!(pcard->current.location & LOCATION_ONFIELD) || pcard->is_position(POS_FACEDOWN) || (ucard->unique_uid < pcard->unique_uid)))
return pcard->unique_effect;
}
return 0;
}
int32 field::check_spsummon_once(card* pcard, uint8 playerid) {
if(pcard->spsummon_code == 0)
return TRUE;
auto iter = core.spsummon_once_map[playerid].find(pcard->spsummon_code);
return (iter == core.spsummon_once_map[playerid].end()) || (iter->second == 0);
}
void field::check_card_counter(card* pcard, int32 counter_type, int32 playerid) {
auto& counter_map = (counter_type == 1) ? core.summon_counter :
(counter_type == 2) ? core.normalsummon_counter :
(counter_type == 3) ? core.spsummon_counter :
(counter_type == 4) ? core.flipsummon_counter : core.attack_counter;
for(auto iter = counter_map.begin(); iter != counter_map.end(); ++iter) {
auto& info = iter->second;
if((playerid == 0) && (info.second & 0xffff) != 0)
continue;
if((playerid == 1) && (info.second & 0xffff0000) != 0)
continue;
if(info.first) {
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
if(!pduel->lua->check_condition(info.first, 1)) {
if(playerid == 0)
info.second += 0x1;
else
info.second += 0x10000;
}
}
}
}
void field::check_chain_counter(effect* peffect, int32 playerid, int32 chainid, bool cancel) {
for(auto iter = core.chain_counter.begin(); iter != core.chain_counter.end(); ++iter) {
auto& info = iter->second;
if(info.first) {
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(chainid, PARAM_TYPE_INT);
if(!pduel->lua->check_condition(info.first, 3)) {
if(playerid == 0) {
if(!cancel)
info.second += 0x1;
else if(info.second & 0xffff)
info.second -= 0x1;
} else {
if(!cancel)
info.second += 0x10000;
else if(info.second & 0xffff0000)
info.second -= 0x10000;
}
}
}
}
}
void field::set_spsummon_counter(uint8 playerid, bool add, bool chain) {
if(add) {
core.spsummon_state_count[playerid]++;
if(chain)
core.spsummon_state_count_rst[playerid]++;
} else {
if(chain) {
core.spsummon_state_count[playerid] -= core.spsummon_state_count_rst[playerid];
core.spsummon_state_count_rst[playerid] = 0;
} else
core.spsummon_state_count[playerid]--;
}
if(core.global_flag & GLOBALFLAG_SPSUMMON_COUNT) {
for(auto iter = effects.spsummon_count_eff.begin(); iter != effects.spsummon_count_eff.end(); ++iter) {
effect* peffect = *iter;
card* pcard = peffect->handler;
if(add) {
if(pcard->is_status(STATUS_EFFECT_ENABLED) && !pcard->is_status(STATUS_DISABLED) && pcard->is_position(POS_FACEUP)) {
if(((playerid == pcard->current.controler) && peffect->s_range) || ((playerid != pcard->current.controler) && peffect->o_range)) {
pcard->spsummon_counter[playerid]++;
if(chain)
pcard->spsummon_counter_rst[playerid]++;
}
}
} else {
pcard->spsummon_counter[playerid] -= pcard->spsummon_counter_rst[playerid];
pcard->spsummon_counter_rst[playerid] = 0;
}
}
}
}
int32 field::check_spsummon_counter(uint8 playerid, uint8 ct) {
if(core.global_flag & GLOBALFLAG_SPSUMMON_COUNT) {
for(auto iter = effects.spsummon_count_eff.begin(); iter != effects.spsummon_count_eff.end(); ++iter) {
effect* peffect = *iter;
card* pcard = peffect->handler;
uint16 val = (uint16)peffect->value;
if(pcard->is_status(STATUS_EFFECT_ENABLED) && !pcard->is_status(STATUS_DISABLED) && pcard->is_position(POS_FACEUP)) {
if(pcard->spsummon_counter[playerid] + ct > val)
return FALSE;
}
}
}
return TRUE;
}
int32 field::check_lp_cost(uint8 playerid, uint32 lp) {
effect_set eset;
int32 val = lp;
if(lp == 0)
return TRUE;
filter_player_effect(playerid, EFFECT_LPCOST_CHANGE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(core.reason_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(val, PARAM_TYPE_INT);
val = eset[i]->get_value(3);
if(val <= 0)
return TRUE;
}
tevent e;
e.event_cards = 0;
e.event_player = playerid;
e.event_value = lp;
e.reason = 0;
e.reason_effect = core.reason_effect;
e.reason_player = playerid;
if(effect_replace_check(EFFECT_LPCOST_REPLACE, e))
return true;
cost[playerid].amount += val;
if(cost[playerid].amount <= player[playerid].lp)
return TRUE;
return FALSE;
}
void field::save_lp_cost() {
for(uint8 playerid = 0; playerid < 2; ++playerid) {
if(cost[playerid].count < 8)
cost[playerid].lpstack[cost[playerid].count] = cost[playerid].amount;
cost[playerid].count++;
}
}
void field::restore_lp_cost() {
for(uint8 playerid = 0; playerid < 2; ++playerid) {
cost[playerid].count--;
if(cost[playerid].count < 8)
cost[playerid].amount = cost[playerid].lpstack[cost[playerid].count];
}
}
uint32 field::get_field_counter(uint8 self, uint8 s, uint8 o, uint16 countertype) {
uint8 c = s;
uint32 count = 0;
for(int p = 0; p < 2; ++p) {
if(c) {
for(int i = 0; i < 5; ++i) {
if(player[self].list_mzone[i])
count += player[self].list_mzone[i]->get_counter(countertype);
}
for(int i = 0; i < 8; ++i) {
if(player[self].list_szone[i])
count += player[self].list_szone[i]->get_counter(countertype);
}
}
self = 1 - self;
c = o;
}
return count;
}
int32 field::effect_replace_check(uint32 code, const tevent& e) {
auto pr = effects.continuous_effect.equal_range(code);
for (; pr.first != pr.second; ++pr.first) {
effect* peffect = pr.first->second;
if(peffect->is_activateable(peffect->get_handler_player(), e))
return TRUE;
}
return FALSE;
}
int32 field::get_attack_target(card* pcard, card_vector* v, uint8 chain_attack) {
uint8 p = pcard->current.controler;
effect* peffect;
card* atarget;
pcard->operation_param = 0;
card_vector must_be_attack;
card_vector* pv;
card_vector::iterator cit;
for(uint32 i = 0; i < 5; ++i) {
atarget = player[1 - p].list_mzone[i];
if(atarget && atarget->is_affected_by_effect(EFFECT_MUST_BE_ATTACKED, pcard))
must_be_attack.push_back(atarget);
}
if(pcard->attack_all_target && (peffect = pcard->is_affected_by_effect(EFFECT_ATTACK_ALL))) {
if(pcard->announced_cards.size()) {
if(must_be_attack.size())
pv = &must_be_attack;
else
pv = &player[1 - p].list_mzone;
for(cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
if(!atarget || pcard->announced_cards.count(atarget->fieldid_r))
continue;
if(atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
continue;
if(atarget->is_affected_by_effect(EFFECT_CANNOT_BE_BATTLE_TARGET, pcard))
continue;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SELECT_BATTLE_TARGET, atarget))
continue;
pduel->lua->add_param(atarget, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
continue;
v->push_back(atarget);
}
return must_be_attack.size() ? TRUE : FALSE;
}
} else if(!chain_attack) {
uint32 extrac = 0;
if((peffect = pcard->is_affected_by_effect(EFFECT_EXTRA_ATTACK)))
extrac = peffect->get_value(pcard);
if(pcard->announce_count >= extrac + 1)
return FALSE;
}
uint32 mcount = 0;
if(must_be_attack.size())
pv = &must_be_attack;
else
pv = &player[1 - p].list_mzone;
for(cit = pv->begin(); cit != pv->end(); ++cit) {
atarget = *cit;
if(!atarget)
continue;
if(atarget->is_affected_by_effect(EFFECT_IGNORE_BATTLE_TARGET))
continue;
mcount++;
if(atarget->is_affected_by_effect(EFFECT_CANNOT_BE_BATTLE_TARGET, pcard))
continue;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SELECT_BATTLE_TARGET, atarget))
continue;
if(chain_attack && core.chain_attack_target && atarget != core.chain_attack_target)
continue;
v->push_back(atarget);
}
if(must_be_attack.size())
return TRUE;
if((mcount == 0 || pcard->is_affected_by_effect(EFFECT_DIRECT_ATTACK))
&& !pcard->is_affected_by_effect(EFFECT_CANNOT_DIRECT_ATTACK)
&& !(chain_attack && core.chain_attack_target))
pcard->operation_param = 1;
return must_be_attack.size() ? TRUE : FALSE;
}
void field::attack_all_target_check() {
if(!core.attacker)
return;
if(!core.attack_target) {
core.attacker->attack_all_target = FALSE;
return;
}
effect* peffect = core.attacker->is_affected_by_effect(EFFECT_ATTACK_ALL);
if(!peffect)
return;
pduel->lua->add_param(core.attack_target, PARAM_TYPE_CARD);
if(!peffect->check_value_condition(1))
core.attacker->attack_all_target = FALSE;
}
int32 field::check_synchro_material(card* pcard, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg) {
card* tuner;
if(core.global_flag & GLOBALFLAG_MUST_BE_SMATERIAL) {
effect_set eset;
filter_player_effect(pcard->current.controler, EFFECT_MUST_BE_SMATERIAL, &eset);
if(eset.size())
return check_tuner_material(pcard, eset[0]->handler, findex1, findex2, min, max, smat, mg);
}
if(mg) {
for(auto cit = mg->container.begin(); cit != mg->container.end(); ++cit) {
tuner = *cit;
if(check_tuner_material(pcard, tuner, findex1, findex2, min, max, smat, mg))
return TRUE;
}
} else {
for(uint8 p = 0; p < 2; ++p) {
for(int32 i = 0; i < 5; ++i) {
tuner = player[p].list_mzone[i];
if(check_tuner_material(pcard, tuner, findex1, findex2, min, max, smat, mg))
return TRUE;
}
}
}
return FALSE;
}
int32 field::check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg) {
effect* peffect;
if(tuner && tuner->is_position(POS_FACEUP) && (tuner->get_type() & TYPE_TUNER) && tuner->is_can_be_synchro_material(pcard)) {
effect* pcheck = tuner->is_affected_by_effect(EFFECT_SYNCHRO_CHECK);
if(pcheck)
pcheck->get_value(tuner);
if((mg && !mg->has_card(tuner)) || !pduel->lua->check_matching(tuner, findex1, 0)) {
pduel->restore_assumes();
return FALSE;
}
if((peffect = tuner->is_affected_by_effect(EFFECT_SYNCHRO_MATERIAL_CUSTOM, pcard))) {
if(!peffect->target) {
pduel->restore_assumes();
return FALSE;
}
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(findex2, PARAM_TYPE_INDEX);
pduel->lua->add_param(min, PARAM_TYPE_INT);
pduel->lua->add_param(max, PARAM_TYPE_INT);
if(pduel->lua->check_condition(peffect->target, 5)) {
pduel->restore_assumes();
return TRUE;
}
} else {
int32 l = tuner->get_synchro_level(pcard);
int32 l1 = l & 0xffff;
//int32 l2 = l >> 16;
int32 lv = pcard->get_level();
lv -= l1;
if(lv <= 0) {
pduel->restore_assumes();
return FALSE;
}
if(smat) {
if(pcheck)
pcheck->get_value(smat);
if(!smat->is_position(POS_FACEUP) || !smat->is_can_be_synchro_material(pcard, tuner) || !pduel->lua->check_matching(smat, findex2, 0)) {
pduel->restore_assumes();
return FALSE;
}
l = smat->get_synchro_level(pcard);
l1 = l & 0xffff;
lv -= l1;
min--;
max--;
if(lv <= 0) {
pduel->restore_assumes();
if(lv == 0 && min == 0)
return TRUE;
return FALSE;
}
if(max == 0) {
pduel->restore_assumes();
return FALSE;
}
}
card_vector nsyn;
card* pm;
if(mg) {
for(auto cit = mg->container.begin(); cit != mg->container.end(); ++cit) {
pm = *cit;
if(pm != tuner && pm != smat && pm->is_can_be_synchro_material(pcard, tuner)) {
if(pcheck)
pcheck->get_value(pm);
if(pm->current.location == LOCATION_MZONE && !pm->is_position(POS_FACEUP))
continue;
if(!pduel->lua->check_matching(pm, findex2, 0))
continue;
nsyn.push_back(pm);
pm->operation_param = pm->get_synchro_level(pcard);
}
}
} else {
for(uint8 p = 0; p < 2; ++p) {
for(int32 i = 0; i < 5; ++i) {
pm = player[p].list_mzone[i];
if(pm && pm != tuner && pm != smat && pm->is_position(POS_FACEUP) && pm->is_can_be_synchro_material(pcard, tuner)) {
if(pcheck)
pcheck->get_value(pm);
if(!pduel->lua->check_matching(pm, findex2, 0))
continue;
nsyn.push_back(pm);
pm->operation_param = pm->get_synchro_level(pcard);
}
}
}
}
if(!(core.global_flag & GLOBALFLAG_SCRAP_CHIMERA)) {
if(check_with_sum_limit(&nsyn, lv, 0, 1, min, max)) {
pduel->restore_assumes();
return TRUE;
}
} else {
effect* pscrap = 0;
for(auto cit = nsyn.begin(); cit != nsyn.end(); ++cit) {
pscrap = (*cit)->is_affected_by_effect(EFFECT_SCRAP_CHIMERA);
if(pscrap)
break;
}
if(pscrap) {
card_vector nsyn_filtered;
for(auto cit = nsyn.begin(); cit != nsyn.end(); ++cit) {
if(!pscrap->get_value(*cit))
nsyn_filtered.push_back(*cit);
}
if(nsyn_filtered.size() == nsyn.size()) {
if(check_with_sum_limit(&nsyn, lv, 0, 1, min, max)) {
pduel->restore_assumes();
return TRUE;
}
} else {
if(check_with_sum_limit(&nsyn_filtered, lv, 0, 1, min, max)) {
pduel->restore_assumes();
return TRUE;
}
card_vector nsyn_removed;
for(auto cit = nsyn.begin(); cit != nsyn.end(); ++cit) {
if(!(*cit)->is_affected_by_effect(EFFECT_SCRAP_CHIMERA))
nsyn_removed.push_back(*cit);
}
if(check_with_sum_limit(&nsyn_removed, lv, 0, 1, min, max)) {
pduel->restore_assumes();
return TRUE;
}
}
} else {
if(check_with_sum_limit(&nsyn, lv, 0, 1, min, max)) {
pduel->restore_assumes();
return TRUE;
}
}
}
}
}
pduel->restore_assumes();
return FALSE;
}
int32 field::check_with_sum_limit(card_vector* mats, int32 acc, int32 index, int32 count, int32 min, int32 max) {
if((uint32)index >= mats->size())
return FALSE;
int32 op1 = mats->at(index)->operation_param & 0xffff;
int32 op2 = (mats->at(index)->operation_param >> 16) & 0xffff;
if((op1 == acc || op2 == acc) && count >= min && count <= max)
return TRUE;
return (acc > op1 && check_with_sum_limit(mats, acc - op1, index + 1, count + 1, min, max))
|| (op2 && acc > op2 && check_with_sum_limit(mats, acc - op2, index + 1, count + 1, min, max))
|| check_with_sum_limit(mats, acc, index + 1, count, min, max);
}
int32 field::check_xyz_material(card* scard, int32 findex, int32 lv, int32 min, int32 max, group* mg) {
if(mg) {
uint32 xyz_level;
core.xmaterial_lst.clear();
for (auto cit = mg->container.begin(); cit != mg->container.end(); ++cit) {
if((xyz_level = (*cit)->check_xyz_level(scard, lv)) && (findex == 0 || pduel->lua->check_matching(*cit, findex, 0)))
core.xmaterial_lst.insert(std::make_pair((xyz_level >> 12) & 0xf, *cit));
}
if(core.global_flag & GLOBALFLAG_XMAT_COUNT_LIMIT) {
if(max > (int32)core.xmaterial_lst.size())
max = (int32)core.xmaterial_lst.size();
auto iter = core.xmaterial_lst.lower_bound(max);
core.xmaterial_lst.erase(core.xmaterial_lst.begin(), iter);
}
} else
get_xyz_material(scard, findex, lv, max);
return (int32)core.xmaterial_lst.size() >= min;
}
int32 field::is_player_can_draw(uint8 playerid) {
return !is_player_affected_by_effect(playerid, EFFECT_CANNOT_DRAW);
}
int32 field::is_player_can_discard_deck(uint8 playerid, int32 count) {
if(player[playerid].list_main.size() < (uint32)count)
return FALSE;
return !is_player_affected_by_effect(playerid, EFFECT_CANNOT_DISCARD_DECK);
}
int32 field::is_player_can_discard_deck_as_cost(uint8 playerid, int32 count) {
if(player[playerid].list_main.size() < (uint32)count)
return FALSE;
if(is_player_affected_by_effect(playerid, EFFECT_CANNOT_DISCARD_DECK))
return FALSE;
if((count == 1) && core.deck_reversed)
return player[playerid].list_main.back()->is_capable_cost_to_grave(playerid);
effect_set eset;
filter_field_effect(EFFECT_TO_GRAVE_REDIRECT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
uint32 redirect = eset[i]->get_value();
if((redirect & LOCATION_REMOVED) && player[playerid].list_main.back()->is_affected_by_effect(EFFECT_CANNOT_REMOVE))
continue;
uint8 p = eset[i]->get_handler_player();
if((p == playerid && eset[i]->s_range & LOCATION_DECK) || (p != playerid && eset[i]->o_range & LOCATION_DECK))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_discard_hand(uint8 playerid, card * pcard, effect * peffect, uint32 reason) {
if(pcard->current.location != LOCATION_HAND)
return FALSE;
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_DISCARD_HAND, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(reason, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 4))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_summon(uint8 playerid) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_summon(uint32 sumtype, uint8 playerid, card * pcard) {
effect_set eset;
sumtype |= SUMMON_TYPE_NORMAL;
filter_player_effect(playerid, EFFECT_CANNOT_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 4))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_mset(uint32 sumtype, uint8 playerid, card * pcard) {
effect_set eset;
sumtype |= SUMMON_TYPE_NORMAL;
filter_player_effect(playerid, EFFECT_CANNOT_MSET, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 4))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_sset(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_SSET, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_spsummon(uint8 playerid) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_SPECIAL_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
}
return is_player_can_spsummon_count(playerid, 1);
}
int32 field::is_player_can_spsummon(effect * peffect, uint32 sumtype, uint8 sumpos, uint8 playerid, uint8 toplayer, card * pcard) {
effect_set eset;
if(pcard->is_affected_by_effect(EFFECT_CANNOT_SPECIAL_SUMMON))
return FALSE;
if(pcard->is_affected_by_effect(EFFECT_FORBIDDEN))
return FALSE;
sumtype |= SUMMON_TYPE_SPECIAL;
if(sumpos & POS_FACEDOWN && is_player_affected_by_effect(playerid, EFFECT_DEVINE_LIGHT))
sumpos = (sumpos & POS_FACEUP) | (sumpos >> 1);
filter_player_effect(playerid, EFFECT_CANNOT_SPECIAL_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
pduel->lua->add_param(sumtype, PARAM_TYPE_INT);
pduel->lua->add_param(sumpos, PARAM_TYPE_INT);
pduel->lua->add_param(toplayer, PARAM_TYPE_INT);
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
if (pduel->lua->check_condition(eset[i]->target, 7))
return FALSE;
}
if(!check_spsummon_once(pcard, playerid))
return FALSE;
if(!check_spsummon_counter(playerid))
return FALSE;
return TRUE;
}
int32 field::is_player_can_flipsummon(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_FLIP_SUMMON, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_spsummon_monster(uint8 playerid, uint8 toplayer, uint8 sumpos, card_data * pdata) {
temp_card->data = *pdata;
return is_player_can_spsummon(core.reason_effect, SUMMON_TYPE_SPECIAL, sumpos, playerid, toplayer, temp_card);
}
int32 field::is_player_can_release(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_RELEASE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_spsummon_count(uint8 playerid, uint32 count) {
effect_set eset;
filter_player_effect(playerid, EFFECT_LEFT_SPSUMMON_COUNT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(core.reason_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
int32 v = eset[i]->get_value(2);
if(v < (int32)count)
return FALSE;
}
return check_spsummon_counter(playerid, count);
}
int32 field::is_player_can_place_counter(uint8 playerid, card * pcard, uint16 countertype, uint16 count) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_PLACE_COUNTER, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_remove_counter(uint8 playerid, card * pcard, uint8 s, uint8 o, uint16 countertype, uint16 count, uint32 reason) {
if((pcard && pcard->get_counter(countertype) >= count) || (!pcard && get_field_counter(playerid, s, o, countertype) >= count))
return TRUE;
pair<effect_container::iterator, effect_container::iterator> pr;
pr = effects.continuous_effect.equal_range(EFFECT_RCOUNTER_REPLACE + countertype);
effect* peffect;
tevent e;
e.event_cards = 0;
e.event_player = playerid;
e.event_value = count;
e.reason = reason;
e.reason_effect = core.reason_effect;
e.reason_player = playerid;
for (; pr.first != pr.second; ++pr.first) {
peffect = pr.first->second;
if(peffect->is_activateable(peffect->get_handler_player(), e))
return TRUE;
}
return FALSE;
}
int32 field::is_player_can_remove_overlay_card(uint8 playerid, card * pcard, uint8 s, uint8 o, uint16 min, uint32 reason) {
if((pcard && pcard->xyz_materials.size() >= min) || (!pcard && get_overlay_count(playerid, s, o) >= min))
return TRUE;
pair<effect_container::iterator, effect_container::iterator> pr;
pr = effects.continuous_effect.equal_range(EFFECT_OVERLAY_REMOVE_REPLACE);
effect* peffect;
tevent e;
e.event_cards = 0;
e.event_player = playerid;
e.event_value = min;
e.reason = reason;
e.reason_effect = core.reason_effect;
e.reason_player = playerid;
for (; pr.first != pr.second; ++pr.first) {
peffect = pr.first->second;
if(peffect->is_activateable(peffect->get_handler_player(), e))
return TRUE;
}
return FALSE;
}
int32 field::is_player_can_send_to_grave(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_TO_GRAVE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_send_to_hand(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_TO_HAND, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_send_to_deck(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_TO_DECK, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_player_can_remove(uint8 playerid, card * pcard) {
effect_set eset;
filter_player_effect(playerid, EFFECT_CANNOT_REMOVE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
if(!eset[i]->target)
return FALSE;
pduel->lua->add_param(eset[i], PARAM_TYPE_EFFECT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
pduel->lua->add_param(playerid, PARAM_TYPE_INT);
if (pduel->lua->check_condition(eset[i]->target, 3))
return FALSE;
}
return TRUE;
}
int32 field::is_chain_negatable(uint8 chaincount, uint8 naga_check) {
effect_set eset;
if(chaincount < 0 || chaincount > core.current_chain.size())
return FALSE;
effect* peffect;
if(chaincount == 0)
peffect = core.current_chain.back().triggering_effect;
else
peffect = core.current_chain[chaincount - 1].triggering_effect;
if(naga_check && peffect->flag & EFFECT_FLAG_NAGA)
return FALSE;
if(peffect->flag & EFFECT_FLAG_CANNOT_DISABLE)
return FALSE;
filter_field_effect(EFFECT_CANNOT_INACTIVATE, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(chaincount, PARAM_TYPE_INT);
if(eset[i]->check_value_condition(1))
return FALSE;
}
return TRUE;
}
int32 field::is_chain_disablable(uint8 chaincount, uint8 naga_check) {
effect_set eset;
if(chaincount < 0 || chaincount > core.current_chain.size())
return FALSE;
effect* peffect;
if(chaincount == 0)
peffect = core.current_chain.back().triggering_effect;
else
peffect = core.current_chain[chaincount - 1].triggering_effect;
if(naga_check && peffect->flag & EFFECT_FLAG_NAGA)
return FALSE;
if(peffect->flag & EFFECT_FLAG_CANNOT_DISABLE)
return FALSE;
filter_field_effect(EFFECT_CANNOT_DISEFFECT, &eset);
for(int32 i = 0; i < eset.size(); ++i) {
pduel->lua->add_param(chaincount, PARAM_TYPE_INT);
if(eset[i]->check_value_condition(1))
return FALSE;
}
return TRUE;
}
int32 field::check_chain_target(uint8 chaincount, card * pcard) {
if(chaincount < 0 || chaincount > core.current_chain.size())
return FALSE;
chain* pchain;
if(chaincount == 0)
pchain = &core.current_chain.back();
else
pchain = &core.current_chain[chaincount - 1];
effect* peffect = pchain->triggering_effect;
uint8 tp = pchain->triggering_player;
if(!(peffect->flag & EFFECT_FLAG_CARD_TARGET) || !peffect->target)
return FALSE;
if(!pcard->is_capable_be_effect_target(peffect, tp))
return false;
pduel->lua->add_param(peffect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(tp, PARAM_TYPE_INT);
pduel->lua->add_param(pchain->evt.event_cards , PARAM_TYPE_GROUP);
pduel->lua->add_param(pchain->evt.event_player, PARAM_TYPE_INT);
pduel->lua->add_param(pchain->evt.event_value, PARAM_TYPE_INT);
pduel->lua->add_param(pchain->evt.reason_effect , PARAM_TYPE_EFFECT);
pduel->lua->add_param(pchain->evt.reason, PARAM_TYPE_INT);
pduel->lua->add_param(pchain->evt.reason_player, PARAM_TYPE_INT);
pduel->lua->add_param((ptr)0, PARAM_TYPE_INT);
pduel->lua->add_param(pcard, PARAM_TYPE_CARD);
return pduel->lua->check_condition(peffect->target, 10);
}
int32 field::is_able_to_enter_bp() {
return ((core.duel_options & DUEL_ATTACK_FIRST_TURN) || infos.turn_id != 1)
&& infos.phase < PHASE_BATTLE
&& !is_player_affected_by_effect(infos.turn_player, EFFECT_CANNOT_BP);
}
/*
* field.h
*
* Created on: 2010-5-8
* Author: Argon
*/
#ifndef FIELD_H_
#define FIELD_H_
#include "memory.h"
#include "common.h"
#include "effectset.h"
#include <vector>
#include <set>
#include <map>
#include <list>
#include <array>
#include <functional>
#include <unordered_map>
#include <unordered_set>
class card;
struct card_data;
class duel;
class group;
class effect;
struct tevent {
card* trigger_card;
group* event_cards;
effect* reason_effect;
uint32 event_code;
uint32 event_value;
uint32 reason;
uint8 event_player;
uint8 reason_player;
bool operator< (const tevent& v) const;
};
struct optarget {
group* op_cards;
uint8 op_count;
uint8 op_player;
int32 op_param;
};
struct chain {
typedef std::map<uint32, optarget > opmap;
uint16 chain_id;
uint8 chain_count;
uint8 triggering_player;
uint8 triggering_controler;
uint8 triggering_location;
uint8 triggering_sequence;
effect* triggering_effect;
group* target_cards;
int32 replace_op;
uint8 target_player;
int32 target_param;
effect* disable_reason;
uint8 disable_player;
tevent evt;
opmap opinfos;
uint32 flag;
static bool chain_operation_sort(const chain& c1, const chain& c2);
};
struct player_info {
typedef std::vector<card*> card_vector;
int32 lp;
int32 start_count;
int32 draw_count;
uint32 used_location;
uint32 disabled_location;
uint32 extra_p_count;
card_vector list_mzone;
card_vector list_szone;
card_vector list_main;
card_vector list_grave;
card_vector list_hand;
card_vector list_remove;
card_vector list_extra;
card_vector tag_list_main;
card_vector tag_list_hand;
card_vector tag_list_extra;
};
struct field_effect {
typedef std::multimap<uint32, effect*> effect_container;
typedef std::map<effect*, effect_container::iterator> effect_indexer;
typedef std::map<effect*, effect*> oath_effects;
typedef std::set<effect*> effect_collection;
effect_container aura_effect;
effect_container ignition_effect;
effect_container activate_effect;
effect_container trigger_o_effect;
effect_container trigger_f_effect;
effect_container quick_o_effect;
effect_container quick_f_effect;
effect_container continuous_effect;
effect_indexer indexer;
oath_effects oath;
effect_collection pheff;
effect_collection cheff;
effect_collection rechargeable;
effect_collection spsummon_count_eff;
std::list<card*> disable_check_list;
std::set<card*, card_sort> disable_check_set;
};
struct field_info {
int32 field_id;
int16 copy_id;
int16 turn_id;
int16 card_id;
uint8 phase;
uint8 turn_player;
uint8 priorities[2];
uint8 can_shuffle;
};
struct lpcost {
int32 count;
int32 amount;
int32 lpstack[8];
};
struct processor_unit {
uint16 type;
uint16 step;
effect* peffect;
group* ptarget;
ptr arg1;
ptr arg2;
};
union return_value {
int8 bvalue[64];
int16 svalue[32];
int32 ivalue[16];
int64 lvalue[8];
};
struct processor {
typedef std::vector<effect*> effect_vector;
typedef std::vector<card*> card_vector;
typedef std::vector<uint32> option_vector;
typedef std::list<card*> card_list;
typedef std::list<tevent> event_list;
typedef std::list<chain> chain_list;
typedef std::map<effect*, chain> instant_f_list;
typedef std::vector<chain> chain_array;
typedef std::list<processor_unit> processor_list;
typedef std::set<card*, card_sort> card_set;
typedef std::set<effect*> effect_collection;
typedef std::set<std::pair<effect*, tevent> > delayed_effect_collection;
processor_list units;
processor_list subunits;
processor_unit reserved;
card_vector select_cards;
card_vector summonable_cards;
card_vector spsummonable_cards;
card_vector repositionable_cards;
card_vector msetable_cards;
card_vector ssetable_cards;
card_vector attackable_cards;
effect_vector select_effects;
option_vector select_options;
event_list point_event;
event_list instant_event;
event_list queue_event;
event_list used_event;
event_list single_event;
event_list solving_event;
event_list sub_solving_event;
chain_array select_chains;
chain_array current_chain;
chain_list tpchain;
chain_list ntpchain;
chain_list continuous_chain;
chain_list desrep_chain;
chain_list new_fchain;
chain_list new_fchain_s;
chain_list new_ochain;
chain_list new_ochain_s;
chain_list new_fchain_b;
chain_list new_ochain_b;
chain_list new_ochain_h;
chain_list new_chains;
chain_list tmp_chain;
delayed_effect_collection delayed_quick_tmp;
delayed_effect_collection delayed_quick_break;
delayed_effect_collection delayed_quick;
instant_f_list quick_f_chain;
card_set leave_confirmed;
card_set special_summoning;
card_set equiping_cards;
card_set control_adjust_set[2];
card_set self_destroy_set;
card_set self_tograve_set;
card_set release_cards;
card_set release_cards_ex;
card_set release_cards_ex_sum;
card_set destroy_set;
card_set battle_destroy_rep;
card_set fusion_materials;
card_set synchro_materials;
card_set operated_set;
card_set discarded_set;
card_set destroy_canceled;
card_set delayed_enable_set;
effect_set_v disfield_effects;
effect_set_v extraz_effects;
effect_set_v extraz_effects_e;
std::set<effect*> reseted_effects;
std::list<effect*> delayed_tp;
std::list<effect*> delayed_ntp;
event_list delayed_tev;
event_list delayed_ntev;
std::unordered_map<card*, uint32> readjust_map;
std::unordered_set<card*> unique_cards[2];
std::unordered_map<uint32, uint32> effect_count_code;
std::unordered_map<uint32, uint32> effect_count_code_duel;
std::unordered_map<uint32, uint32> spsummon_once_map[2];
std::unordered_map<uint32, uint32> spsummon_once_map_rst[2];
std::multimap<int32, card*, std::greater<int32> > xmaterial_lst;
ptr temp_var[4];
uint32 global_flag;
uint16 pre_field[2];
uint16 opp_mzone[5];
int32 chain_limit;
uint8 chain_limp;
int32 chain_limit_p;
uint8 chain_limp_p;
uint8 chain_solving;
uint8 conti_solving;
uint8 win_player;
uint8 win_reason;
uint8 re_adjust;
effect* reason_effect;
uint8 reason_player;
card* summoning_card;
uint8 summon_depth;
uint8 summon_cancelable;
card* attacker;
card* sub_attacker;
card* attack_target;
card* sub_attack_target;
card* limit_tuner;
group* limit_xyz;
group* limit_syn;
uint8 attack_cancelable;
uint8 attack_rollback;
uint8 effect_damage_step;
int32 battle_damage[2];
int32 summon_count[2];
uint8 extra_summon[2];
int32 spe_effect[2];
int32 duel_options;
uint32 copy_reset;
uint8 copy_reset_count;
uint8 dice_result[5];
uint8 coin_result[5];
uint8 to_bp;
uint8 to_m2;
uint8 to_ep;
uint8 skip_m2;
uint8 chain_attack;
card* chain_attack_target;
uint8 selfdes_disabled;
uint8 overdraw[2];
int32 check_level;
uint8 shuffle_check_disabled;
uint8 shuffle_hand_check[2];
uint8 shuffle_deck_check[2];
uint8 deck_reversed;
uint8 remove_brainwashing;
uint8 flip_delayed;
uint8 damage_calculated;
uint8 hand_adjusted;
uint8 summon_state_count[2];
uint8 normalsummon_state_count[2];
uint8 flipsummon_state_count[2];
uint8 spsummon_state_count[2];
uint8 spsummon_state_count_rst[2];
uint8 spsummon_state_count_tmp[2];
bool spsummon_rst;
uint8 attack_state_count[2];
uint8 battle_phase_count[2];
uint8 phase_action;
uint8 battle_phase_action;
uint32 hint_timing[2];
uint8 current_player;
uint8 conti_player;
std::unordered_map<uint32, std::pair<uint32, uint32> > summon_counter;
std::unordered_map<uint32, std::pair<uint32, uint32> > normalsummon_counter;
std::unordered_map<uint32, std::pair<uint32, uint32> > spsummon_counter;
std::unordered_map<uint32, std::pair<uint32, uint32> > flipsummon_counter;
std::unordered_map<uint32, std::pair<uint32, uint32> > attack_counter;
std::unordered_map<uint32, std::pair<uint32, uint32> > chain_counter;
};
class field {
public:
typedef std::multimap<uint32, effect*> effect_container;
typedef std::map<effect*, effect_container::iterator> effect_indexer;
typedef std::set<card*, card_sort> card_set;
typedef std::vector<effect*> effect_vector;
typedef std::vector<card*> card_vector;
typedef std::list<card*> card_list;
typedef std::list<tevent> event_list;
typedef std::list<chain> chain_list;
typedef std::map<effect*, chain> instant_f_list;
typedef std::vector<chain> chain_array;
typedef std::list<processor_unit> processor_list;
typedef std::map<effect*, effect*> oath_effects;
duel* pduel;
player_info player[2];
card* temp_card;
field_info infos;
lpcost cost[2];
field_effect effects;
processor core;
return_value returns;
tevent nil_event;
static int32 field_used_count[32];
explicit field(duel* pduel);
~field();
void reload_field_info();
void add_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence);
void remove_card(card* pcard);
void move_card(uint8 playerid, card* pcard, uint8 location, uint8 sequence);
void set_control(card* pcard, uint8 playerid, uint16 reset_phase, uint8 reset_count);
card* get_field_card(uint8 playerid, uint8 location, uint8 sequence);
int32 is_location_useable(uint8 playerid, uint8 location, uint8 sequence);
int32 get_useable_count(uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32* list = 0);
void shuffle(uint8 playerid, uint8 location);
void reset_sequence(uint8 playerid, uint8 location);
void swap_deck_and_grave(uint8 playerid);
void reverse_deck(uint8 playerid);
void tag_swap(uint8 playerid);
void add_effect(effect* peffect, uint8 owner_player = 2);
void remove_effect(effect* peffect);
void remove_oath_effect(effect* reason_effect);
void reset_effect(uint32 id, uint32 reset_type);
void reset_phase(uint32 phase);
void reset_chain();
void add_effect_code(uint32 code, uint32 playerid);
uint32 get_effect_code(uint32 code, uint32 playerid);
void dec_effect_code(uint32 code, uint32 playerid);
void filter_field_effect(uint32 code, effect_set* eset, uint8 sort = TRUE);
void filter_affected_cards(effect* peffect, card_set* cset);
void filter_player_effect(uint8 playerid, uint32 code, effect_set* eset, uint8 sort = TRUE);
int32 filter_matching_card(int32 findex, uint8 self, uint32 location1, uint32 location2, group* pgroup, card* pexception, uint32 extraargs, card** pret = 0, int32 fcount = 0, int32 is_target = FALSE);
int32 filter_field_card(uint8 self, uint32 location, uint32 location2, group* pgroup);
effect* is_player_affected_by_effect(uint8 playerid, uint32 code);
int32 get_release_list(uint8 playerid, card_set* release_list, card_set* ex_list, int32 use_con, int32 use_hand, int32 fun, int32 exarg, card* exp);
int32 check_release_list(uint8 playerid, int32 count, int32 use_con, int32 use_hand, int32 fun, int32 exarg, card* exp);
int32 get_summon_release_list(card* target, card_set* release_list, card_set* ex_list, card_set* ex_list_sum, group* mg = 0, uint32 ex = 0);
int32 get_summon_count_limit(uint8 playerid);
int32 get_draw_count(uint8 playerid);
void get_ritual_material(uint8 playerid, effect* peffect, card_set* material);
void ritual_release(card_set* material);
void get_xyz_material(card* scard, int32 findex, uint32 lv, int32 maxc);
void get_overlay_group(uint8 self, uint8 s, uint8 o, card_set* pset);
int32 get_overlay_count(uint8 self, uint8 s, uint8 o);
void update_disable_check_list(effect* peffect);
void add_to_disable_check_list(card* pcard);
void adjust_disable_check_list();
void adjust_self_destroy_set();
void add_unique_card(card* pcard);
void remove_unique_card(card* pcard);
effect* check_unique_onfield(card* pcard, uint8 controler);
int32 check_spsummon_once(card* pcard, uint8 playerid);
void check_card_counter(card* pcard, int32 counter_type, int32 playerid);
void check_chain_counter(effect* peffect, int32 playerid, int32 chainid, bool cancel = false);
void set_spsummon_counter(uint8 playerid, bool add = true, bool chain = false);
int32 check_spsummon_counter(uint8 playerid, uint8 ct = 1);
int32 check_lp_cost(uint8 playerid, uint32 cost);
void save_lp_cost();
void restore_lp_cost();
int32 pay_lp_cost(uint32 step, uint8 playerid, uint32 cost);
uint32 get_field_counter(uint8 self, uint8 s, uint8 o, uint16 countertype);
int32 effect_replace_check(uint32 code, const tevent& e);
int32 get_attack_target(card* pcard, card_vector* v, uint8 chain_attack = FALSE);
void attack_all_target_check();
int32 check_synchro_material(card* pcard, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg);
int32 check_tuner_material(card* pcard, card* tuner, int32 findex1, int32 findex2, int32 min, int32 max, card* smat, group* mg);
int32 check_with_sum_limit(card_vector* mats, int32 acc, int32 index, int32 count, int32 min, int32 max);
int32 check_xyz_material(card* pcard, int32 findex, int32 lv, int32 min, int32 max, group* mg);
int32 is_player_can_draw(uint8 playerid);
int32 is_player_can_discard_deck(uint8 playerid, int32 count);
int32 is_player_can_discard_deck_as_cost(uint8 playerid, int32 count);
int32 is_player_can_discard_hand(uint8 playerid, card* pcard, effect* peffect, uint32 reason);
int32 is_player_can_summon(uint8 playerid);
int32 is_player_can_summon(uint32 sumtype, uint8 playerid, card* pcard);
int32 is_player_can_mset(uint32 sumtype, uint8 playerid, card* pcard);
int32 is_player_can_sset(uint8 playerid, card* pcard);
int32 is_player_can_spsummon(uint8 playerid);
int32 is_player_can_spsummon(effect* peffect, uint32 sumtype, uint8 sumpos, uint8 playerid, uint8 toplayer, card* pcard);
int32 is_player_can_flipsummon(uint8 playerid, card* pcard);
int32 is_player_can_spsummon_monster(uint8 playerid, uint8 toplayer, uint8 sumpos, card_data* pdata);
int32 is_player_can_spsummon_count(uint8 playerid, uint32 count);
int32 is_player_can_release(uint8 playerid, card* pcard);
int32 is_player_can_place_counter(uint8 playerid, card* pcard, uint16 countertype, uint16 count);
int32 is_player_can_remove_counter(uint8 playerid, card* pcard, uint8 s, uint8 o, uint16 countertype, uint16 count, uint32 reason);
int32 is_player_can_remove_overlay_card(uint8 playerid, card* pcard, uint8 s, uint8 o, uint16 count, uint32 reason);
int32 is_player_can_send_to_grave(uint8 playerid, card* pcard);
int32 is_player_can_send_to_hand(uint8 playerid, card* pcard);
int32 is_player_can_send_to_deck(uint8 playerid, card* pcard);
int32 is_player_can_remove(uint8 playerid, card* pcard);
int32 is_chain_negatable(uint8 chaincount, uint8 naga_check = FALSE);
int32 is_chain_disablable(uint8 chaincount, uint8 naga_check = FALSE);
int32 check_chain_target(uint8 chaincount, card* pcard);
int32 is_able_to_enter_bp();
void add_process(uint16 type, uint16 step, effect* peffect, group* target, ptr arg1, ptr arg2);
int32 process();
int32 execute_cost(uint16 step, effect* peffect, uint8 triggering_player);
int32 execute_operation(uint16 step, effect* peffect, uint8 triggering_player);
int32 execute_target(uint16 step, effect* peffect, uint8 triggering_player);
void raise_event(card* event_card, uint32 event_code, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 event_player, uint32 event_value);
void raise_event(card_set* event_cards, uint32 event_code, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 event_player, uint32 event_value);
void 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);
int32 check_event(uint32 code, tevent* pe = 0);
int32 check_event_c(effect* peffect, uint8 playerid, int32 neglect_con, int32 neglect_cost, int32 copy_info, tevent* pe = 0);
int32 check_hint_timing(effect* peffect);
int32 process_phase_event(int16 step, int32 phase_event);
int32 process_point_event(int16 step, int32 skip_trigger, int32 skip_freechain, int32 skip_new);
int32 process_quick_effect(int16 step, int32 skip_freechain, uint8 priority);
int32 process_instant_event();
int32 process_single_event();
int32 process_idle_command(uint16 step);
int32 process_battle_command(uint16 step);
int32 process_damage_step(uint16 step);
void calculate_battle_damage(effect** pdamchange, card** preason_card, uint8* battle_destroyed);
int32 process_turn(uint16 step, uint8 turn_player);
int32 add_chain(uint16 step);
int32 sort_chain(uint16 step, uint8 tp);
int32 solve_continuous(uint16 step, effect* peffect, uint8 triggering_player);
int32 solve_chain(uint16 step, uint32 chainend_arg1, uint32 chainend_arg2);
int32 break_effect();
void adjust_instant();
void adjust_all();
void refresh_location_info_instant();
int32 refresh_location_info(uint16 step);
int32 adjust_step(uint16 step);
//operations
int32 negate_chain(uint8 chaincount);
int32 disable_chain(uint8 chaincount);
void change_chain_effect(uint8 chaincount, int32 replace_op);
void change_target(uint8 chaincount, group* targets);
void change_target_player(uint8 chaincount, uint8 playerid);
void change_target_param(uint8 chaincount, int32 param);
void remove_counter(uint32 reason, card* pcard, uint32 rplayer, uint32 s, uint32 o, uint32 countertype, uint32 count);
void remove_overlay_card(uint32 reason, card* pcard, uint32 rplayer, uint32 s, uint32 o, uint16 min, uint16 max);
void get_control(effect* reason_effect, uint32 reason_player, card* pcard, uint32 playerid, uint32 reset_phase, uint32 reset_count);
void swap_control(effect* reason_effect, uint32 reason_player, card* pcard1, card* pcard2, uint32 reset_phase, uint32 reset_count);
void equip(uint32 equip_player, card* equip_card, card* target, uint32 up, uint32 is_step);
void draw(effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 count);
void damage(effect* reason_effect, uint32 reason, uint32 reason_player, card* pcard, uint32 playerid, uint32 amount);
void recover(effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 amount);
void summon(uint32 sumplayer, card* target, effect* proc, uint32 ignore_count, uint32 min_tribute);
void special_summon_rule(uint32 sumplayer, card* target, uint32 summon_type);
void special_summon(card_set* target, uint32 sumtype, uint32 sumplayer, uint32 playerid, uint32 nocheck, uint32 nolimit, uint32 positions);
void special_summon_step(card* target, uint32 sumtype, uint32 sumplayer, uint32 playerid, uint32 nocheck, uint32 nolimit, uint32 positions);
void special_summon_complete(effect* reason_effect, uint8 reason_player);
void destroy(card_set* targets, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid = 2, uint32 destination = 0, uint32 sequence = 0);
void destroy(card* target, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid = 2, uint32 destination = 0, uint32 sequence = 0);
void release(card_set* targets, effect* reason_effect, uint32 reason, uint32 reason_player);
void release(card* target, effect* reason_effect, uint32 reason, uint32 reason_player);
void send_to(card_set* targets, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 destination, uint32 sequence, uint32 position);
void send_to(card* target, effect* reason_effect, uint32 reason, uint32 reason_player, uint32 playerid, uint32 destination, uint32 sequence, uint32 position);
void move_to_field(card* target, uint32 move_player, uint32 playerid, uint32 destination, uint32 positions, uint32 enable = FALSE, uint32 ret = FALSE, uint32 is_equip = FALSE);
void change_position(card_set* targets, effect* reason_effect, uint32 reason_player, uint32 au, uint32 ad, uint32 du, uint32 dd, uint32 noflip, uint32 enable = FALSE);
void change_position(card* target, effect* reason_effect, uint32 reason_player, uint32 npos, uint32 noflip, uint32 enable = FALSE);
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);
int32 get_control(uint16 step, effect* reason_effect, uint8 reason_player, card* pcard, uint8 playerid, uint16 reset_phase, uint8 reset_count);
int32 swap_control(uint16 step, effect* reason_effect, uint8 reason_player, card* pcard1, card* pcard2, uint16 reset_phase, uint8 reset_count);
int32 control_adjust(uint16 step);
int32 self_destroy(uint16 step);
int32 equip(uint16 step, uint8 equip_player, card* equip_card, card* target, uint32 up, uint32 is_step);
int32 draw(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 playerid, uint32 count);
int32 damage(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, card* pcard, uint8 playerid, uint32 amount);
int32 recover(uint16 step, effect* reason_effect, uint32 reason, uint8 reason_player, uint8 playerid, uint32 amount);
int32 summon(uint16 step, uint8 sumplayer, card* target, effect* proc, uint8 ignore_count, uint8 min_tribute);
int32 flip_summon(uint16 step, uint8 sumplayer, card* target);
int32 mset(uint16 step, uint8 setplayer, card* ptarget, effect* proc, uint8 ignore_count, uint8 min_tribute);
int32 sset(uint16 step, uint8 setplayer, uint8 toplayer, card* ptarget);
int32 sset_g(uint16 step, uint8 setplayer, uint8 toplayer, group* ptarget);
int32 special_summon_rule(uint16 step, uint8 sumplayer, card* target, uint32 summon_type);
int32 special_summon_step(uint16 step, group* targets, card* target);
int32 special_summon(uint16 step, effect* reason_effect, uint8 reason_player, group* targets);
int32 destroy(uint16 step, group* targets, card* target, uint8 battle);
int32 destroy(uint16 step, group* targets, effect* reason_effect, uint32 reason, uint8 reason_player);
int32 release(uint16 step, group* targets, card* target);
int32 release(uint16 step, group* targets, effect* reason_effect, uint32 reason, uint8 reason_player);
int32 send_to(uint16 step, group* targets, card* target);
int32 send_to(uint16 step, group* targets, effect* reason_effect, uint32 reason, uint8 reason_player);
int32 discard_deck(uint16 step, uint8 playerid, uint8 count, uint32 reason);
int32 move_to_field(uint16 step, card* target, uint32 enable, uint32 ret, uint32 is_equip);
int32 change_position(uint16 step, group* targets, effect* reason_effect, uint8 reason_player, uint32 enable);
int32 operation_replace(uint16 step, effect* replace_effect, group* targets, ptr arg, ptr replace_type);
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 check_field, uint8 cancelable, int32 min, int32 max);
int32 select_tribute_cards(int16 step, uint8 playerid, uint8 cancelable, int32 min, int32 max);
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 select_battle_command(uint16 step, uint8 playerid);
int32 select_idle_command(uint16 step, uint8 playerid);
int32 select_effect_yes_no(uint16 step, uint8 playerid, card* pcard);
int32 select_yes_no(uint16 step, uint8 playerid, uint32 description);
int32 select_option(uint16 step, uint8 playerid);
int32 select_card(uint16 step, uint8 playerid, uint8 cancelable, uint8 min, uint8 max);
int32 select_chain(uint16 step, uint8 playerid, uint8 spe_count, uint8 forced);
int32 select_place(uint16 step, uint8 playerid, uint32 flag, uint8 count);
int32 select_position(uint16 step, uint8 playerid, uint32 code, uint8 positions);
int32 select_tribute(uint16 step, uint8 playerid, uint8 cancelable, uint8 min, uint8 max);
int32 select_counter(uint16 step, uint8 playerid, uint16 countertype, uint16 count);
int32 select_with_sum_limit(int16 step, uint8 playerid, int32 acc, int32 min, int max);
int32 sort_card(int16 step, uint8 playerid, uint8 is_chain);
int32 announce_race(int16 step, uint8 playerid, int32 count, int32 available);
int32 announce_attribute(int16 step, uint8 playerid, int32 count, int32 available);
int32 announce_card(int16 step, uint8 playerid);
int32 announce_number(int16 step, uint8 playerid);
};
//Location Use Reason
#define LOCATION_REASON_TOFIELD 0x1
#define LOCATION_REASON_CONTROL 0x2
//Chain Info
#define CHAIN_DISABLE_ACTIVATE 0x01
#define CHAIN_DISABLE_EFFECT 0x02
#define CHAIN_HAND_EFFECT 0x04
#define CHAININFO_CHAIN_COUNT 0x01
#define CHAININFO_TRIGGERING_EFFECT 0x02
#define CHAININFO_TRIGGERING_PLAYER 0x04
#define CHAININFO_TRIGGERING_CONTROLER 0x08
#define CHAININFO_TRIGGERING_LOCATION 0x10
#define CHAININFO_TRIGGERING_SEQUENCE 0x20
#define CHAININFO_TARGET_CARDS 0x40
#define CHAININFO_TARGET_PLAYER 0x80
#define CHAININFO_TARGET_PARAM 0x100
#define CHAININFO_DISABLE_REASON 0x200
#define CHAININFO_DISABLE_PLAYER 0x400
#define CHAININFO_CHAIN_ID 0x800
#define CHAININFO_TYPE 0x1000
#define CHAININFO_EXTTYPE 0x2000
//Timing
#define TIMING_DRAW_PHASE 0x1
#define TIMING_STANDBY_PHASE 0x2
#define TIMING_MAIN_END 0x4
#define TIMING_BATTLE_START 0x8
#define TIMING_BATTLE_END 0x10
#define TIMING_END_PHASE 0x20
#define TIMING_SUMMON 0x40
#define TIMING_SPSUMMON 0x80
#define TIMING_FLIPSUMMON 0x100
#define TIMING_MSET 0x200
#define TIMING_SSET 0x400
#define TIMING_POS_CHANGE 0x800
#define TIMING_ATTACK 0x1000
#define TIMING_DAMAGE_STEP 0x2000
#define TIMING_DAMAGE_CAL 0x4000
#define TIMING_CHAIN_END 0x8000
#define TIMING_DRAW 0x10000
#define TIMING_DAMAGE 0x20000
#define TIMING_RECOVER 0x40000
#define TIMING_DESTROY 0x80000
#define TIMING_REMOVE 0x100000
#define TIMING_TOHAND 0x200000
#define TIMING_TODECK 0x400000
#define TIMING_TOGRAVE 0x800000
#define TIMING_BATTLE_PHASE 0x1000000
#define TIMING_EQUIP 0x2000000
#define GLOBALFLAG_DECK_REVERSE_CHECK 0x1
#define GLOBALFLAG_BRAINWASHING_CHECK 0x2
#define GLOBALFLAG_SCRAP_CHIMERA 0x4
#define GLOBALFLAG_DELAYED_QUICKEFFECT 0x8
#define GLOBALFLAG_DETACH_EVENT 0x10
#define GLOBALFLAG_MUST_BE_SMATERIAL 0x20
#define GLOBALFLAG_SPSUMMON_COUNT 0x40
#define GLOBALFLAG_XMAT_COUNT_LIMIT 0x80
#define GLOBALFLAG_SELF_TOGRAVE 0x100
#define GLOBALFLAG_SPSUMMON_ONCE 0x200
//
#define PROCESSOR_NONE 0
#define PROCESSOR_WAITING 0x10000
#define PROCESSOR_END 0x20000
#define PROCESSOR_ADJUST 1
#define PROCESSOR_HINT 2
#define PROCESSOR_TURN 3
#define PROCESSOR_WAIT 4
#define PROCESSOR_REFRESH_LOC 5
#define PROCESSOR_SELECT_IDLECMD 10
#define PROCESSOR_SELECT_EFFECTYN 11
#define PROCESSOR_SELECT_BATTLECMD 12
#define PROCESSOR_SELECT_YESNO 13
#define PROCESSOR_SELECT_OPTION 14
#define PROCESSOR_SELECT_CARD 15
#define PROCESSOR_SELECT_CHAIN 16
#define PROCESSOR_SELECT_PLACE 18
#define PROCESSOR_SELECT_POSITION 19
#define PROCESSOR_SELECT_TRIBUTE_P 20
#define PROCESSOR_SORT_CHAIN 21
#define PROCESSOR_SELECT_COUNTER 22
#define PROCESSOR_SELECT_SUM 23
#define PROCESSOR_SELECT_DISFIELD 24
#define PROCESSOR_SORT_CARD 25
#define PROCESSOR_SELECT_RELEASE 26
#define PROCESSOR_SELECT_TRIBUTE 27
#define PROCESSOR_POINT_EVENT 30
#define PROCESSOR_QUICK_EFFECT 31
#define PROCESSOR_IDLE_COMMAND 32
#define PROCESSOR_PHASE_EVENT 33
#define PROCESSOR_BATTLE_COMMAND 34
#define PROCESSOR_DAMAGE_STEP 35
#define PROCESSOR_ADD_CHAIN 40
#define PROCESSOR_SOLVE_CHAIN 42
#define PROCESSOR_SOLVE_CONTINUOUS 43
#define PROCESSOR_EXECUTE_COST 44
#define PROCESSOR_EXECUTE_OPERATION 45
#define PROCESSOR_EXECUTE_TARGET 46
#define PROCESSOR_DESTROY 50
#define PROCESSOR_RELEASE 51
#define PROCESSOR_SENDTO 52
#define PROCESSOR_MOVETOFIELD 53
#define PROCESSOR_CHANGEPOS 54
#define PROCESSOR_OPERATION_REPLACE 55
#define PROCESSOR_DESTROY_STEP 56
#define PROCESSOR_RELEASE_STEP 57
#define PROCESSOR_SENDTO_STEP 58
#define PROCESSOR_SUMMON_RULE 60
#define PROCESSOR_SPSUMMON_RULE 61
#define PROCESSOR_SPSUMMON 62
#define PROCESSOR_FLIP_SUMMON 63
#define PROCESSOR_MSET 64
#define PROCESSOR_SSET 65
#define PROCESSOR_SPSUMMON_STEP 66
#define PROCESSOR_SSET_G 67
#define PROCESSOR_DRAW 70
#define PROCESSOR_DAMAGE 71
#define PROCESSOR_RECOVER 72
#define PROCESSOR_EQUIP 73
#define PROCESSOR_GET_CONTROL 74
#define PROCESSOR_SWAP_CONTROL 75
#define PROCESSOR_CONTROL_ADJUST 76
#define PROCESSOR_SELF_DESTROY 77
#define PROCESSOR_PAY_LPCOST 80
#define PROCESSOR_REMOVE_COUNTER 81
#define PROCESSOR_ATTACK_DISABLE 82
#define PROCESSOR_DESTROY_S 100
#define PROCESSOR_RELEASE_S 101
#define PROCESSOR_SENDTO_S 102
#define PROCESSOR_CHANGEPOS_S 103
#define PROCESSOR_ANNOUNCE_RACE 110
#define PROCESSOR_ANNOUNCE_ATTRIB 111
#define PROCESSOR_ANNOUNCE_LEVEL 112
#define PROCESSOR_ANNOUNCE_CARD 113
#define PROCESSOR_ANNOUNCE_TYPE 114
#define PROCESSOR_ANNOUNCE_NUMBER 115
#define PROCESSOR_ANNOUNCE_COIN 116
#define PROCESSOR_TOSS_DICE 117
#define PROCESSOR_TOSS_COIN 118
#define PROCESSOR_SELECT_YESNO_S 120
#define PROCESSOR_SELECT_OPTION_S 121
#define PROCESSOR_SELECT_CARD_S 122
#define PROCESSOR_SELECT_EFFECTYN_S 123
#define PROCESSOR_SELECT_PLACE_S 125
#define PROCESSOR_SELECT_POSITION_S 126
#define PROCESSOR_SELECT_TRIBUTE_S 127
#define PROCESSOR_SORT_CARDS_S 128
#define PROCESSOR_SELECT_RELEASE_S 129
#define PROCESSOR_SELECT_TARGET 130
#define PROCESSOR_SELECT_FUSION 131
#define PROCESSOR_SELECT_SYNCHRO 132
#define PROCESSOR_SELECT_SUM_S 133
#define PROCESSOR_SELECT_DISFIELD_S 134
#define PROCESSOR_SPSUMMON_S 135
#define PROCESSOR_SPSUMMON_STEP_S 136
#define PROCESSOR_SPSUMMON_COMP_S 137
#define PROCESSOR_RANDOM_SELECT_S 138
#define PROCESSOR_SELECT_XMATERIAL 139
#define PROCESSOR_DRAW_S 140
#define PROCESSOR_DAMAGE_S 141
#define PROCESSOR_RECOVER_S 142
#define PROCESSOR_EQUIP_S 143
#define PROCESSOR_GET_CONTROL_S 144
#define PROCESSOR_SWAP_CONTROL_S 145
#define PROCESSOR_DISCARD_HAND_S 150
#define PROCESSOR_DISCARD_DECK_S 151
#define PROCESSOR_SORT_DECK_S 152
#define PROCESSOR_REMOVEOL_S 160
#define PROCESSOR_MOVETOFIELD_S 161
//Hints
#define HINT_EVENT 1
#define HINT_MESSAGE 2
#define HINT_SELECTMSG 3
#define HINT_OPSELECTED 4
#define HINT_EFFECT 5
#define HINT_RACE 6
#define HINT_ATTRIB 7
#define HINT_CODE 8
#define HINT_NUMBER 9
#define HINT_CARD 10
//
#define CHINT_TURN 1
#define CHINT_CARD 2
#define CHINT_RACE 3
#define CHINT_ATTRIBUTE 4
#define CHINT_NUMBER 5
#define CHINT_DESC_ADD 6
#define CHINT_DESC_REMOVE 7
//Messages
#define MSG_RETRY 1
#define MSG_HINT 2
#define MSG_WAITING 3
#define MSG_START 4
#define MSG_WIN 5
#define MSG_UPDATE_DATA 6
#define MSG_UPDATE_CARD 7
#define MSG_REQUEST_DECK 8
#define MSG_SELECT_BATTLECMD 10
#define MSG_SELECT_IDLECMD 11
#define MSG_SELECT_EFFECTYN 12
#define MSG_SELECT_YESNO 13
#define MSG_SELECT_OPTION 14
#define MSG_SELECT_CARD 15
#define MSG_SELECT_CHAIN 16
#define MSG_SELECT_PLACE 18
#define MSG_SELECT_POSITION 19
#define MSG_SELECT_TRIBUTE 20
#define MSG_SORT_CHAIN 21
#define MSG_SELECT_COUNTER 22
#define MSG_SELECT_SUM 23
#define MSG_SELECT_DISFIELD 24
#define MSG_SORT_CARD 25
#define MSG_CONFIRM_DECKTOP 30
#define MSG_CONFIRM_CARDS 31
#define MSG_SHUFFLE_DECK 32
#define MSG_SHUFFLE_HAND 33
#define MSG_REFRESH_DECK 34
#define MSG_SWAP_GRAVE_DECK 35
#define MSG_SHUFFLE_SET_CARD 36
#define MSG_REVERSE_DECK 37
#define MSG_DECK_TOP 38
#define MSG_NEW_TURN 40
#define MSG_NEW_PHASE 41
#define MSG_MOVE 50
#define MSG_POS_CHANGE 53
#define MSG_SET 54
#define MSG_SWAP 55
#define MSG_FIELD_DISABLED 56
#define MSG_SUMMONING 60
#define MSG_SUMMONED 61
#define MSG_SPSUMMONING 62
#define MSG_SPSUMMONED 63
#define MSG_FLIPSUMMONING 64
#define MSG_FLIPSUMMONED 65
#define MSG_CHAINING 70
#define MSG_CHAINED 71
#define MSG_CHAIN_SOLVING 72
#define MSG_CHAIN_SOLVED 73
#define MSG_CHAIN_END 74
#define MSG_CHAIN_NEGATED 75
#define MSG_CHAIN_DISABLED 76
#define MSG_CARD_SELECTED 80
#define MSG_RANDOM_SELECTED 81
#define MSG_BECOME_TARGET 83
#define MSG_DRAW 90
#define MSG_DAMAGE 91
#define MSG_RECOVER 92
#define MSG_EQUIP 93
#define MSG_LPUPDATE 94
#define MSG_UNEQUIP 95
#define MSG_CARD_TARGET 96
#define MSG_CANCEL_TARGET 97
#define MSG_PAY_LPCOST 100
#define MSG_ADD_COUNTER 101
#define MSG_REMOVE_COUNTER 102
#define MSG_ATTACK 110
#define MSG_BATTLE 111
#define MSG_ATTACK_DISABLED 112
#define MSG_DAMAGE_STEP_START 113
#define MSG_DAMAGE_STEP_END 114
#define MSG_MISSED_EFFECT 120
#define MSG_BE_CHAIN_TARGET 121
#define MSG_CREATE_RELATION 122
#define MSG_RELEASE_RELATION 123
#define MSG_TOSS_COIN 130
#define MSG_TOSS_DICE 131
#define MSG_ANNOUNCE_RACE 140
#define MSG_ANNOUNCE_ATTRIB 141
#define MSG_ANNOUNCE_CARD 142
#define MSG_ANNOUNCE_NUMBER 143
#define MSG_CARD_HINT 160
#define MSG_TAG_SWAP 161
#define MSG_RELOAD_FIELD 162
#define MSG_AI_NAME 163
#define MSG_SHOW_HINT 164
#define MSG_MATCH_KILL 170
#define MSG_CUSTOM_MSG 180
#endif /* FIELD_H_ */
/*
* group.cpp
*
* Created on: 2010-8-3
* Author: Argon
*/
#include "group.h"
#include "card.h"
#include "duel.h"
group::group(duel* pd) {
scrtype = 2;
ref_handle = 0;
pduel = pd;
is_readonly = FALSE;
}
group::group(duel* pd, card* pcard) {
container.insert(pcard);
scrtype = 2;
ref_handle = 0;
pduel = pd;
is_readonly = FALSE;
}
group::group(duel* pd, const card_set& cset): container(cset) {
scrtype = 2;
ref_handle = 0;
pduel = pd;
is_readonly = FALSE;
}
group::~group() {
}
/*
* group.h
*
* Created on: 2010-5-6
* Author: Argon
*/
#ifndef GROUP_H_
#define GROUP_H_
#include "common.h"
#include <set>
#include <list>
class card;
class duel;
class group {
public:
typedef std::set<card*, card_sort> card_set;
int32 scrtype;
int32 ref_handle;
duel* pduel;
card_set container;
card_set::iterator it;
uint32 is_readonly;
inline bool has_card(card* c) {
return container.find(c) != container.end();
}
explicit group(duel* pd);
group(duel* pd, card* pcard);
group(duel* pd, const card_set& cset);
~group();
};
#endif /* GROUP_H_ */
/*
* interpreter.cpp
*
* Created on: 2010-4-28
* Author: Argon
*/
#include <stdio.h>
#include <iostream>
#include "duel.h"
#include "group.h"
#include "card.h"
#include "effect.h"
#include "scriptlib.h"
#include "ocgapi.h"
#include "interpreter.h"
static const struct luaL_Reg cardlib[] = {
{ "GetCode", scriptlib::card_get_code },
{ "GetOriginalCode", scriptlib::card_get_origin_code },
{ "GetOriginalCodeRule", scriptlib::card_get_origin_code_rule },
{ "IsSetCard", scriptlib::card_is_set_card },
{ "IsPreviousSetCard", scriptlib::card_is_pre_set_card },
{ "GetType", scriptlib::card_get_type },
{ "GetOriginalType", scriptlib::card_get_origin_type },
{ "GetLevel", scriptlib::card_get_level },
{ "GetRank", scriptlib::card_get_rank },
{ "GetSynchroLevel", scriptlib::card_get_synchro_level },
{ "GetRitualLevel", scriptlib::card_get_ritual_level },
{ "GetOriginalLevel", scriptlib::card_get_origin_level },
{ "GetOriginalRank", scriptlib::card_get_origin_rank },
{ "IsXyzLevel", scriptlib::card_is_xyz_level },
{ "GetLeftScale", scriptlib::card_get_lscale },
{ "GetOriginalLeftScale", scriptlib::card_get_origin_lscale },
{ "GetRightScale", scriptlib::card_get_rscale },
{ "GetOriginalRightScale", scriptlib::card_get_origin_rscale },
{ "GetAttribute", scriptlib::card_get_attribute },
{ "GetOriginalAttribute", scriptlib::card_get_origin_attribute },
{ "GetRace", scriptlib::card_get_race },
{ "GetOriginalRace", scriptlib::card_get_origin_race },
{ "GetAttack", scriptlib::card_get_attack },
{ "GetBaseAttack", scriptlib::card_get_origin_attack },
{ "GetTextAttack", scriptlib::card_get_text_attack },
{ "GetDefence", scriptlib::card_get_defence },
{ "GetBaseDefence", scriptlib::card_get_origin_defence },
{ "GetTextDefence", scriptlib::card_get_text_defence },
{ "GetPreviousCodeOnField", scriptlib::card_get_previous_code_onfield },
{ "GetPreviousTypeOnField", scriptlib::card_get_previous_type_onfield },
{ "GetPreviousLevelOnField", scriptlib::card_get_previous_level_onfield },
{ "GetPreviousRankOnField", scriptlib::card_get_previous_rank_onfield },
{ "GetPreviousAttributeOnField", scriptlib::card_get_previous_attribute_onfield },
{ "GetPreviousRaceOnField", scriptlib::card_get_previous_race_onfield },
{ "GetPreviousAttackOnField", scriptlib::card_get_previous_attack_onfield },
{ "GetPreviousDefenceOnField", scriptlib::card_get_previous_defence_onfield },
{ "GetOwner", scriptlib::card_get_owner },
{ "GetControler", scriptlib::card_get_controler },
{ "GetPreviousControler", scriptlib::card_get_previous_controler },
{ "GetReason", scriptlib::card_get_reason },
{ "GetReasonCard", scriptlib::card_get_reason_card },
{ "GetReasonPlayer", scriptlib::card_get_reason_player },
{ "GetReasonEffect", scriptlib::card_get_reason_effect },
{ "GetPosition", scriptlib::card_get_position },
{ "GetPreviousPosition", scriptlib::card_get_previous_position },
{ "GetBattlePosition", scriptlib::card_get_battle_position },
{ "GetLocation", scriptlib::card_get_location },
{ "GetPreviousLocation", scriptlib::card_get_previous_location },
{ "GetSequence", scriptlib::card_get_sequence },
{ "GetPreviousSequence", scriptlib::card_get_previous_sequence },
{ "GetSummonType", scriptlib::card_get_summon_type },
{ "GetSummonLocation", scriptlib::card_get_summon_location },
{ "GetSummonPlayer", scriptlib::card_get_summon_player },
{ "GetDestination", scriptlib::card_get_destination },
{ "GetLeaveFieldDest", scriptlib::card_get_leave_field_dest },
{ "GetTurnID", scriptlib::card_get_turnid },
{ "GetFieldID", scriptlib::card_get_fieldid },
{ "GetRealFieldID", scriptlib::card_get_fieldidr },
{ "IsCode", scriptlib::card_is_code },
{ "IsType", scriptlib::card_is_type },
{ "IsRace", scriptlib::card_is_race },
{ "IsAttribute", scriptlib::card_is_attribute },
{ "IsReason", scriptlib::card_is_reason },
{ "IsStatus", scriptlib::card_is_status },
{ "IsNotTuner", scriptlib::card_is_not_tuner },
{ "SetStatus", scriptlib::card_set_status },
{ "IsDualState", scriptlib::card_is_dual_state },
{ "EnableDualState", scriptlib::card_enable_dual_state },
{ "SetTurnCounter", scriptlib::card_set_turn_counter },
{ "GetTurnCounter", scriptlib::card_get_turn_counter },
{ "SetMaterial", scriptlib::card_set_material },
{ "GetMaterial", scriptlib::card_get_material },
{ "GetMaterialCount", scriptlib::card_get_material_count },
{ "GetEquipGroup", scriptlib::card_get_equip_group },
{ "GetEquipCount", scriptlib::card_get_equip_count },
{ "GetEquipTarget", scriptlib::card_get_equip_target },
{ "GetPreviousEquipTarget", scriptlib::card_get_pre_equip_target },
{ "CheckEquipTarget", scriptlib::card_check_equip_target },
{ "GetUnionCount", scriptlib::card_get_union_count },
{ "GetOverlayGroup", scriptlib::card_get_overlay_group },
{ "GetOverlayCount", scriptlib::card_get_overlay_count },
{ "GetOverlayTarget", scriptlib::card_get_overlay_target },
{ "CheckRemoveOverlayCard", scriptlib::card_check_remove_overlay_card },
{ "RemoveOverlayCard", scriptlib::card_remove_overlay_card },
{ "GetAttackedGroup", scriptlib::card_get_attacked_group },
{ "GetAttackedGroupCount", scriptlib::card_get_attacked_group_count },
{ "GetAttackedCount", scriptlib::card_get_attacked_count },
{ "GetBattledGroup", scriptlib::card_get_battled_group },
{ "GetBattledGroupCount", scriptlib::card_get_battled_group_count },
{ "GetAttackAnnouncedCount", scriptlib::card_get_attack_announced_count },
{ "IsDirectAttacked", scriptlib::card_is_direct_attacked },
{ "SetCardTarget", scriptlib::card_set_card_target },
{ "GetCardTarget", scriptlib::card_get_card_target },
{ "GetFirstCardTarget", scriptlib::card_get_first_card_target },
{ "GetCardTargetCount", scriptlib::card_get_card_target_count },
{ "IsHasCardTarget", scriptlib::card_is_has_card_target },
{ "CancelCardTarget", scriptlib::card_cancel_card_target },
{ "GetOwnerTarget", scriptlib::card_get_owner_target },
{ "GetOwnerTargetCount", scriptlib::card_get_owner_target_count },
{ "GetActivateEffect", scriptlib::card_get_activate_effect },
{ "CheckActivateEffect", scriptlib::card_check_activate_effect },
{ "RegisterEffect", scriptlib::card_register_effect },
{ "IsHasEffect", scriptlib::card_is_has_effect },
{ "ResetEffect", scriptlib::card_reset_effect },
{ "GetEffectCount", scriptlib::card_get_effect_count },
{ "RegisterFlagEffect", scriptlib::card_register_flag_effect },
{ "GetFlagEffect", scriptlib::card_get_flag_effect },
{ "ResetFlagEffect", scriptlib::card_reset_flag_effect },
{ "SetFlagEffectLabel", scriptlib::card_set_flag_effect_label },
{ "GetFlagEffectLabel", scriptlib::card_get_flag_effect_label },
{ "CreateRelation", scriptlib::card_create_relation },
{ "ReleaseRelation", scriptlib::card_release_relation },
{ "CreateEffectRelation", scriptlib::card_create_effect_relation },
{ "ReleaseEffectRelation", scriptlib::card_release_effect_relation },
{ "ClearEffectRelation", scriptlib::card_clear_effect_relation },
{ "IsRelateToEffect", scriptlib::card_is_relate_to_effect },
{ "IsRelateToCard", scriptlib::card_is_relate_to_card },
{ "IsRelateToBattle", scriptlib::card_is_relate_to_battle },
{ "CopyEffect", scriptlib::card_copy_effect },
{ "EnableUnsummonable", scriptlib::card_enable_unsummonable },
{ "EnableReviveLimit", scriptlib::card_enable_revive_limit },
{ "CompleteProcedure", scriptlib::card_complete_procedure },
{ "IsDisabled", scriptlib::card_is_disabled },
{ "IsDestructable", scriptlib::card_is_destructable },
{ "IsSummonableCard", scriptlib::card_is_summonable },
{ "IsSpecialSummonable", scriptlib::card_is_special_summonable },
{ "IsSynchroSummonable", scriptlib::card_is_synchro_summonable },
{ "IsXyzSummonable", scriptlib::card_is_xyz_summonable },
{ "IsSummonable", scriptlib::card_is_can_be_summoned },
{ "IsMSetable", scriptlib::card_is_msetable },
{ "IsSSetable", scriptlib::card_is_ssetable },
{ "IsCanBeSpecialSummoned", scriptlib::card_is_can_be_special_summoned },
{ "IsAbleToHand", scriptlib::card_is_able_to_hand },
{ "IsAbleToDeck", scriptlib::card_is_able_to_deck },
{ "IsAbleToExtra", scriptlib::card_is_able_to_extra },
{ "IsAbleToGrave", scriptlib::card_is_able_to_grave },
{ "IsAbleToRemove", scriptlib::card_is_able_to_remove },
{ "IsAbleToHandAsCost", scriptlib::card_is_able_to_hand_as_cost },
{ "IsAbleToDeckAsCost", scriptlib::card_is_able_to_deck_as_cost },
{ "IsAbleToExtraAsCost", scriptlib::card_is_able_to_extra_as_cost },
{ "IsAbleToDeckOrExtraAsCost", scriptlib::card_is_able_to_deck_or_extra_as_cost },
{ "IsAbleToGraveAsCost", scriptlib::card_is_able_to_grave_as_cost },
{ "IsAbleToRemoveAsCost", scriptlib::card_is_able_to_remove_as_cost },
{ "IsReleasable", scriptlib::card_is_releasable },
{ "IsReleasableByEffect", scriptlib::card_is_releasable_by_effect },
{ "IsDiscardable", scriptlib::card_is_discardable },
{ "IsAttackable", scriptlib::card_is_attackable },
{ "IsChainAttackable", scriptlib::card_is_chain_attackable },
{ "IsFaceup", scriptlib::card_is_faceup },
{ "IsAttackPos", scriptlib::card_is_attack_pos },
{ "IsFacedown", scriptlib::card_is_facedown },
{ "IsDefencePos", scriptlib::card_is_defence_pos },
{ "IsPosition", scriptlib::card_is_position },
{ "IsPreviousPosition", scriptlib::card_is_pre_position },
{ "IsControler", scriptlib::card_is_controler },
{ "IsOnField", scriptlib::card_is_onfield },
{ "IsLocation", scriptlib::card_is_location },
{ "IsPreviousLocation", scriptlib::card_is_pre_location },
{ "IsLevelBelow", scriptlib::card_is_level_below },
{ "IsLevelAbove", scriptlib::card_is_level_above },
{ "IsRankBelow", scriptlib::card_is_rank_below },
{ "IsRankAbove", scriptlib::card_is_rank_above },
{ "IsAttackBelow", scriptlib::card_is_attack_below },
{ "IsAttackAbove", scriptlib::card_is_attack_above },
{ "IsDefenceBelow", scriptlib::card_is_defence_below },
{ "IsDefenceAbove", scriptlib::card_is_defence_above },
{ "IsPublic", scriptlib::card_is_public },
{ "IsForbidden", scriptlib::card_is_forbidden },
{ "IsAbleToChangeControler", scriptlib::card_is_able_to_change_controler },
{ "IsControlerCanBeChanged", scriptlib::card_is_controler_can_be_changed },
{ "AddCounter", scriptlib::card_add_counter },
{ "RemoveCounter", scriptlib::card_remove_counter },
{ "GetCounter", scriptlib::card_get_counter },
{ "EnableCounterPermit", scriptlib::card_enable_counter_permit },
{ "SetCounterLimit", scriptlib::card_set_counter_limit },
{ "IsCanTurnSet", scriptlib::card_is_can_turn_set },
{ "IsCanAddCounter", scriptlib::card_is_can_add_counter },
{ "IsCanRemoveCounter", scriptlib::card_is_can_remove_counter },
{ "IsCanBeFusionMaterial", scriptlib::card_is_can_be_fusion_material },
{ "IsCanBeSynchroMaterial", scriptlib::card_is_can_be_synchro_material },
{ "IsCanBeRitualMaterial", scriptlib::card_is_can_be_ritual_material },
{ "IsCanBeXyzMaterial", scriptlib::card_is_can_be_xyz_material },
{ "CheckFusionMaterial", scriptlib::card_check_fusion_material },
{ "IsImmuneToEffect", scriptlib::card_is_immune_to_effect },
{ "IsCanBeEffectTarget", scriptlib::card_is_can_be_effect_target },
{ "IsCanBeBattleTarget", scriptlib::card_is_can_be_battle_target },
{ "AddTrapMonsterAttribute", scriptlib::card_add_trap_monster_attribute },
{ "TrapMonsterBlock", scriptlib::card_trap_monster_block },
{ "CancelToGrave", scriptlib::card_cancel_to_grave },
{ "GetTributeRequirement", scriptlib::card_get_tribute_requirement },
{ "GetBattleTarget", scriptlib::card_get_battle_target },
{ "GetAttackableTarget", scriptlib::card_get_attackable_target },
{ "SetHint", scriptlib::card_set_hint },
{ "ReverseInDeck", scriptlib::card_reverse_in_deck },
{ "SetUniqueOnField", scriptlib::card_set_unique_onfield },
{ "CheckUniqueOnField", scriptlib::card_check_unique_onfield },
{ "ResetNegateEffect", scriptlib::card_reset_negate_effect },
{ "AssumeProperty", scriptlib::card_assume_prop },
{ "SetSPSummonOnce", scriptlib::card_set_spsummon_once },
{ NULL, NULL }
};
static const struct luaL_Reg effectlib[] = {
{ "CreateEffect", scriptlib::effect_new },
{ "GlobalEffect", scriptlib::effect_newex },
{ "Clone", scriptlib::effect_clone },
{ "Reset", scriptlib::effect_reset },
{ "GetFieldID", scriptlib::effect_get_field_id },
{ "SetDescription", scriptlib::effect_set_description },
{ "SetCode", scriptlib::effect_set_code },
{ "SetRange", scriptlib::effect_set_range },
{ "SetTargetRange", scriptlib::effect_set_target_range },
{ "SetAbsoluteRange", scriptlib::effect_set_absolute_range },
{ "SetCountLimit", scriptlib::effect_set_count_limit },
{ "SetReset", scriptlib::effect_set_reset },
{ "SetType", scriptlib::effect_set_type },
{ "SetProperty", scriptlib::effect_set_property },
{ "SetLabel", scriptlib::effect_set_label },
{ "SetLabelObject", scriptlib::effect_set_label_object },
{ "SetCategory", scriptlib::effect_set_category },
{ "SetHintTiming", scriptlib::effect_set_hint_timing },
{ "SetCondition", scriptlib::effect_set_condition },
{ "SetTarget", scriptlib::effect_set_target },
{ "SetCost", scriptlib::effect_set_cost },
{ "SetValue", scriptlib::effect_set_value },
{ "SetOperation", scriptlib::effect_set_operation },
{ "SetOwnerPlayer", scriptlib::effect_set_owner_player },
{ "GetDescription", scriptlib::effect_get_description },
{ "GetCode", scriptlib::effect_get_code },
{ "GetType", scriptlib::effect_get_type },
{ "GetProperty", scriptlib::effect_get_property },
{ "GetLabel", scriptlib::effect_get_label },
{ "GetLabelObject", scriptlib::effect_get_label_object },
{ "GetCategory", scriptlib::effect_get_category },
{ "GetOwner", scriptlib::effect_get_owner },
{ "GetHandler", scriptlib::effect_get_handler },
{ "GetCondition", scriptlib::effect_get_condition },
{ "GetTarget", scriptlib::effect_get_target },
{ "GetCost", scriptlib::effect_get_cost },
{ "GetValue", scriptlib::effect_get_value },
{ "GetOperation", scriptlib::effect_get_operation },
{ "GetActiveType", scriptlib::effect_get_active_type },
{ "IsActiveType", scriptlib::effect_is_active_type },
{ "GetOwnerPlayer", scriptlib::effect_get_owner_player },
{ "GetHandlerPlayer", scriptlib::effect_get_handler_player },
{ "IsHasProperty", scriptlib::effect_is_has_property },
{ "IsHasCategory", scriptlib::effect_is_has_category },
{ "IsHasType", scriptlib::effect_is_has_type },
{ "IsActivatable", scriptlib::effect_is_activatable },
{ "IsActivated", scriptlib::effect_is_activated },
{ "GetActivateLocation", scriptlib::effect_get_activate_location },
{ NULL, NULL }
};
static const struct luaL_Reg grouplib[] = {
{ "CreateGroup", scriptlib::group_new },
{ "KeepAlive", scriptlib::group_keep_alive },
{ "DeleteGroup", scriptlib::group_delete },
{ "Clone", scriptlib::group_clone },
{ "FromCards", scriptlib::group_from_cards },
{ "Clear", scriptlib::group_clear },
{ "AddCard", scriptlib::group_add_card },
{ "RemoveCard", scriptlib::group_remove_card },
{ "GetNext", scriptlib::group_get_next },
{ "GetFirst", scriptlib::group_get_first },
{ "GetCount", scriptlib::group_get_count },
{ "ForEach", scriptlib::group_for_each },
{ "Filter", scriptlib::group_filter },
{ "FilterCount", scriptlib::group_filter_count },
{ "FilterSelect", scriptlib::group_filter_select },
{ "Select", scriptlib::group_select },
{ "RandomSelect", scriptlib::group_random_select },
{ "IsExists", scriptlib::group_is_exists },
{ "CheckWithSumEqual", scriptlib::group_check_with_sum_equal },
{ "SelectWithSumEqual", scriptlib::group_select_with_sum_equal },
{ "CheckWithSumGreater", scriptlib::group_check_with_sum_greater },
{ "SelectWithSumGreater", scriptlib::group_select_with_sum_greater },
{ "GetMinGroup", scriptlib::group_get_min_group },
{ "GetMaxGroup", scriptlib::group_get_max_group },
{ "GetSum", scriptlib::group_get_sum },
{ "GetClassCount", scriptlib::group_get_class_count },
{ "Remove", scriptlib::group_remove },
{ "Merge", scriptlib::group_merge },
{ "Sub", scriptlib::group_sub },
{ "Equal", scriptlib::group_equal },
{ "IsContains", scriptlib::group_is_contains },
{ "SearchCard", scriptlib::group_search_card },
{ NULL, NULL }
};
static const struct luaL_Reg duellib[] = {
{ "EnableGlobalFlag", scriptlib::duel_enable_global_flag },
{ "GetLP", scriptlib::duel_get_lp },
{ "SetLP", scriptlib::duel_set_lp },
{ "GetTurnPlayer", scriptlib::duel_get_turn_player },
{ "GetTurnCount", scriptlib::duel_get_turn_count },
{ "GetDrawCount", scriptlib::duel_get_draw_count },
{ "RegisterEffect", scriptlib::duel_register_effect },
{ "RegisterFlagEffect", scriptlib::duel_register_flag_effect },
{ "GetFlagEffect", scriptlib::duel_get_flag_effect },
{ "ResetFlagEffect", scriptlib::duel_reset_flag_effect },
{ "Destroy", scriptlib::duel_destroy },
{ "Remove", scriptlib::duel_remove },
{ "SendtoGrave", scriptlib::duel_sendto_grave },
{ "SendtoHand", scriptlib::duel_sendto_hand },
{ "SendtoDeck", scriptlib::duel_sendto_deck },
{ "GetOperatedGroup", scriptlib::duel_get_operated_group },
{ "Summon", scriptlib::duel_summon },
{ "SpecialSummonRule", scriptlib::duel_special_summon_rule },
{ "SynchroSummon", scriptlib::duel_synchro_summon },
{ "XyzSummon", scriptlib::duel_xyz_summon },
{ "MSet", scriptlib::duel_setm },
{ "SSet", scriptlib::duel_sets },
{ "CreateToken", scriptlib::duel_create_token },
{ "SpecialSummon", scriptlib::duel_special_summon },
{ "SpecialSummonStep", scriptlib::duel_special_summon_step },
{ "SpecialSummonComplete", scriptlib::duel_special_summon_complete },
{ "RemoveCounter", scriptlib::duel_remove_counter },
{ "IsCanRemoveCounter", scriptlib::duel_is_can_remove_counter },
{ "GetCounter", scriptlib::duel_get_counter },
{ "ChangePosition", scriptlib::duel_change_form },
{ "Release", scriptlib::duel_release },
{ "MoveToField", scriptlib::duel_move_to_field },
{ "ReturnToField", scriptlib::duel_return_to_field },
{ "MoveSequence", scriptlib::duel_move_sequence },
{ "SetChainLimit", scriptlib::duel_set_chain_limit },
{ "SetChainLimitTillChainEnd", scriptlib::duel_set_chain_limit_p },
{ "GetChainMaterial", scriptlib::duel_get_chain_material },
{ "ConfirmDecktop", scriptlib::duel_confirm_decktop },
{ "ConfirmCards", scriptlib::duel_confirm_cards },
{ "SortDecktop", scriptlib::duel_sort_decktop },
{ "CheckEvent", scriptlib::duel_check_event },
{ "RaiseEvent", scriptlib::duel_raise_event },
{ "RaiseSingleEvent", scriptlib::duel_raise_single_event },
{ "CheckTiming", scriptlib::duel_check_timing },
{ "GetEnvironment", scriptlib::duel_get_environment },
{ "IsEnvironment", scriptlib::duel_is_environment },
{ "Win", scriptlib::duel_win },
{ "Draw", scriptlib::duel_draw },
{ "Damage", scriptlib::duel_damage },
{ "Recover", scriptlib::duel_recover },
{ "Equip", scriptlib::duel_equip },
{ "EquipComplete", scriptlib::duel_equip_complete },
{ "GetControl", scriptlib::duel_get_control },
{ "SwapControl", scriptlib::duel_swap_control },
{ "CheckLPCost", scriptlib::duel_check_lp_cost },
{ "PayLPCost", scriptlib::duel_pay_lp_cost },
{ "DiscardDeck", scriptlib::duel_discard_deck },
{ "DiscardHand", scriptlib::duel_discard_hand },
{ "DisableShuffleCheck", scriptlib::duel_disable_shuffle_check },
{ "ShuffleDeck", scriptlib::duel_shuffle_deck },
{ "ShuffleHand", scriptlib::duel_shuffle_hand },
{ "ShuffleSetCard", scriptlib::duel_shuffle_setcard },
{ "ChangeAttacker", scriptlib::duel_change_attacker },
{ "ReplaceAttacker", scriptlib::duel_replace_attacker },
{ "ChangeAttackTarget", scriptlib::duel_change_attack_target },
{ "ReplaceAttackTarget", scriptlib::duel_replace_attack_target },
{ "CalculateDamage", scriptlib::duel_calculate_damage },
{ "GetBattleDamage", scriptlib::duel_get_battle_damage },
{ "ChangeBattleDamage", scriptlib::duel_change_battle_damage },
{ "ChangeTargetCard", scriptlib::duel_change_target },
{ "ChangeTargetPlayer", scriptlib::duel_change_target_player },
{ "ChangeTargetParam", scriptlib::duel_change_target_param },
{ "BreakEffect", scriptlib::duel_break_effect },
{ "ChangeChainOperation", scriptlib::duel_change_effect },
{ "NegateActivation", scriptlib::duel_negate_activate },
{ "NegateEffect", scriptlib::duel_negate_effect },
{ "NegateRelatedChain", scriptlib::duel_negate_related_chain },
{ "NegateSummon", scriptlib::duel_disable_summon },
{ "IncreaseSummonedCount", scriptlib::duel_increase_summon_count },
{ "CheckSummonedCount", scriptlib::duel_check_summon_count },
{ "GetLocationCount", scriptlib::duel_get_location_count },
{ "GetFieldCard", scriptlib::duel_get_field_card },
{ "CheckLocation", scriptlib::duel_check_location },
{ "GetCurrentChain", scriptlib::duel_get_current_chain },
{ "GetChainInfo", scriptlib::duel_get_chain_info },
{ "GetFirstTarget", scriptlib::duel_get_first_target },
{ "GetCurrentPhase", scriptlib::duel_get_current_phase },
{ "SkipPhase", scriptlib::duel_skip_phase },
{ "IsDamageCalculated", scriptlib::duel_is_damage_calculated },
{ "GetAttacker", scriptlib::duel_get_attacker },
{ "GetAttackTarget", scriptlib::duel_get_attack_target },
{ "NegateAttack", scriptlib::duel_disable_attack },
{ "ChainAttack", scriptlib::duel_chain_attack },
{ "Readjust", scriptlib::duel_readjust },
{ "AdjustInstantly", scriptlib::duel_adjust_instantly },
{ "GetFieldGroup", scriptlib::duel_get_field_group },
{ "GetFieldGroupCount", scriptlib::duel_get_field_group_count },
{ "GetDecktopGroup", scriptlib::duel_get_decktop_group },
{ "GetMatchingGroup", scriptlib::duel_get_matching_group },
{ "GetMatchingGroupCount", scriptlib::duel_get_matching_count },
{ "GetFirstMatchingCard", scriptlib::duel_get_first_matching_card },
{ "IsExistingMatchingCard", scriptlib::duel_is_existing_matching_card },
{ "SelectMatchingCard", scriptlib::duel_select_matching_cards },
{ "GetReleaseGroup", scriptlib::duel_get_release_group },
{ "GetReleaseGroupCount", scriptlib::duel_get_release_group_count },
{ "CheckReleaseGroup", scriptlib::duel_check_release_group },
{ "SelectReleaseGroup", scriptlib::duel_select_release_group },
{ "CheckReleaseGroupEx", scriptlib::duel_check_release_group_ex },
{ "SelectReleaseGroupEx", scriptlib::duel_select_release_group_ex },
{ "GetTributeGroup", scriptlib::duel_get_tribute_group },
{ "GetTributeCount", scriptlib::duel_get_tribute_count },
{ "SelectTribute", scriptlib::duel_select_tribute },
{ "GetTargetCount", scriptlib::duel_get_target_count },
{ "IsExistingTarget", scriptlib::duel_is_existing_target },
{ "SelectTarget", scriptlib::duel_select_target },
{ "SelectFusionMaterial", scriptlib::duel_select_fusion_material },
{ "SetFusionMaterial", scriptlib::duel_set_fusion_material },
{ "SetSynchroMaterial", scriptlib::duel_set_synchro_material },
{ "SelectSynchroMaterial", scriptlib::duel_select_synchro_material },
{ "CheckSynchroMaterial", scriptlib::duel_check_synchro_material },
{ "SelectTunerMaterial", scriptlib::duel_select_tuner_material },
{ "CheckTunerMaterial", scriptlib::duel_check_tuner_material },
{ "GetRitualMaterial", scriptlib::duel_get_ritual_material },
{ "ReleaseRitualMaterial", scriptlib::duel_release_ritual_material },
{ "SetTargetCard", scriptlib::duel_set_target_card },
{ "ClearTargetCard", scriptlib::duel_clear_target_card },
{ "SetTargetPlayer", scriptlib::duel_set_target_player },
{ "SetTargetParam", scriptlib::duel_set_target_param },
{ "SetOperationInfo", scriptlib::duel_set_operation_info },
{ "GetOperationInfo", scriptlib::duel_get_operation_info },
{ "GetOperationCount", scriptlib::duel_get_operation_count },
{ "CheckXyzMaterial", scriptlib::duel_check_xyz_material },
{ "SelectXyzMaterial", scriptlib::duel_select_xyz_material },
{ "Overlay", scriptlib::duel_overlay },
{ "GetOverlayGroup", scriptlib::duel_get_overlay_group },
{ "GetOverlayCount", scriptlib::duel_get_overlay_count },
{ "CheckRemoveOverlayCard", scriptlib::duel_check_remove_overlay_card },
{ "RemoveOverlayCard", scriptlib::duel_remove_overlay_card },
{ "Hint", scriptlib::duel_hint },
{ "HintSelection", scriptlib::duel_hint_selection },
{ "SelectEffectYesNo", scriptlib::duel_select_effect_yesno },
{ "SelectYesNo", scriptlib::duel_select_yesno },
{ "SelectOption", scriptlib::duel_select_option },
{ "SelectSequence", scriptlib::duel_select_sequence },
{ "SelectPosition", scriptlib::duel_select_position },
{ "SelectDisableField", scriptlib::duel_select_disable_field },
{ "AnnounceRace", scriptlib::duel_announce_race },
{ "AnnounceAttribute", scriptlib::duel_announce_attribute },
{ "AnnounceLevel", scriptlib::duel_announce_level },
{ "AnnounceCard", scriptlib::duel_announce_card },
{ "AnnounceType", scriptlib::duel_announce_type },
{ "AnnounceNumber", scriptlib::duel_announce_number },
{ "AnnounceCoin", scriptlib::duel_announce_coin },
{ "TossCoin", scriptlib::duel_toss_coin },
{ "TossDice", scriptlib::duel_toss_dice },
{ "GetCoinResult", scriptlib::duel_get_coin_result },
{ "GetDiceResult", scriptlib::duel_get_dice_result },
{ "SetCoinResult", scriptlib::duel_set_coin_result },
{ "SetDiceResult", scriptlib::duel_set_dice_result },
{ "IsPlayerAffectedByEffect", scriptlib::duel_is_player_affected_by_effect },
{ "IsPlayerCanDraw", scriptlib::duel_is_player_can_draw },
{ "IsPlayerCanDiscardDeck", scriptlib::duel_is_player_can_discard_deck },
{ "IsPlayerCanDiscardDeckAsCost", scriptlib::duel_is_player_can_discard_deck_as_cost },
{ "IsPlayerCanSummon", scriptlib::duel_is_player_can_summon },
{ "IsPlayerCanSpecialSummon", scriptlib::duel_is_player_can_spsummon },
{ "IsPlayerCanFlipSummon", scriptlib::duel_is_player_can_flipsummon },
{ "IsPlayerCanSpecialSummonMonster", scriptlib::duel_is_player_can_spsummon_monster },
{ "IsPlayerCanSpecialSummonCount", scriptlib::duel_is_player_can_spsummon_count },
{ "IsPlayerCanRelease", scriptlib::duel_is_player_can_release },
{ "IsPlayerCanRemove", scriptlib::duel_is_player_can_remove },
{ "IsPlayerCanSendtoHand", scriptlib::duel_is_player_can_send_to_hand },
{ "IsPlayerCanSendtoGrave", scriptlib::duel_is_player_can_send_to_grave },
{ "IsPlayerCanSendtoDeck", scriptlib::duel_is_player_can_send_to_deck },
{ "IsChainNegatable", scriptlib::duel_is_chain_negatable },
{ "IsChainDisablable", scriptlib::duel_is_chain_disablable },
{ "CheckChainTarget", scriptlib::duel_check_chain_target },
{ "CheckChainUniqueness", scriptlib::duel_check_chain_uniqueness },
{ "GetActivityCount", scriptlib::duel_get_activity_count },
{ "CheckPhaseActivity", scriptlib::duel_check_phase_activity },
{ "AddCustomActivityCounter", scriptlib::duel_add_custom_activity_counter },
{ "GetCustomActivityCount", scriptlib::duel_get_custom_activity_count },
{ "IsAbleToEnterBP", scriptlib::duel_is_able_to_enter_bp },
{ "VenomSwampCheck", scriptlib::duel_venom_swamp_check },
{ "SwapDeckAndGrave", scriptlib::duel_swap_deck_and_grave },
{ "MajesticCopy", scriptlib::duel_majestic_copy },
{ NULL, NULL }
};
static const struct luaL_Reg debuglib[] = {
{ "Message", scriptlib::debug_message },
{ "AddCard", scriptlib::debug_add_card },
{ "SetPlayerInfo", scriptlib::debug_set_player_info },
{ "PreEquip", scriptlib::debug_pre_equip },
{ "PreSetTarget", scriptlib::debug_pre_set_target },
{ "PreAddCounter", scriptlib::debug_pre_add_counter },
{ "ReloadFieldBegin", scriptlib::debug_reload_field_begin },
{ "ReloadFieldEnd", scriptlib::debug_reload_field_end },
{ "SetAIName", scriptlib::debug_set_ai_name },
{ "ShowHint", scriptlib::debug_show_hint },
{ NULL, NULL }
};
interpreter::interpreter(duel* pd): coroutines(256) {
lua_state = luaL_newstate();
current_state = lua_state;
pduel = pd;
no_action = 0;
call_depth = 0;
set_duel_info(lua_state, pd);
//Initial
luaL_openlibs(lua_state);
lua_pushnil(lua_state);
lua_setglobal(lua_state, "file");
lua_pushnil(lua_state);
lua_setglobal(lua_state, "io");
lua_pushnil(lua_state);
lua_setglobal(lua_state, "os");
lua_getglobal(lua_state, "bit32");
lua_setglobal(lua_state, "bit");
//open all libs
luaL_newlib(lua_state, cardlib);
lua_pushstring(lua_state, "__index");
lua_pushvalue(lua_state, -2);
lua_rawset(lua_state, -3);
lua_setglobal(lua_state, "Card");
luaL_newlib(lua_state, effectlib);
lua_pushstring(lua_state, "__index");
lua_pushvalue(lua_state, -2);
lua_rawset(lua_state, -3);
lua_setglobal(lua_state, "Effect");
luaL_newlib(lua_state, grouplib);
lua_pushstring(lua_state, "__index");
lua_pushvalue(lua_state, -2);
lua_rawset(lua_state, -3);
lua_setglobal(lua_state, "Group");
luaL_newlib(lua_state, duellib);
lua_setglobal(lua_state, "Duel");
luaL_newlib(lua_state, debuglib);
lua_setglobal(lua_state, "Debug");
//extra scripts
load_script((char*) "./script/constant.lua");
load_script((char*) "./script/utility.lua");
}
interpreter::~interpreter() {
lua_close(lua_state);
}
int32 interpreter::register_card(card *pcard) {
//create a card in by userdata
card ** ppcard = (card**) lua_newuserdata(lua_state, sizeof(card*));
*ppcard = pcard;
pcard->ref_handle = luaL_ref(lua_state, LUA_REGISTRYINDEX);
//some userdata may be created in script like token so use current_state
lua_rawgeti(current_state, LUA_REGISTRYINDEX, pcard->ref_handle);
//load script
if(pcard->data.alias && (pcard->data.alias < pcard->data.code + 10) && (pcard->data.code < pcard->data.alias + 10))
load_card_script(pcard->data.alias);
else
load_card_script(pcard->data.code);
//set metatable of pointer to base script
lua_setmetatable(current_state, -2);
lua_pop(current_state, 1);
//Initial
if(pcard->data.code && (!(pcard->data.type & TYPE_NORMAL) || (pcard->data.type & TYPE_PENDULUM))) {
pcard->set_status(STATUS_INITIALIZING, TRUE);
add_param(pcard, PARAM_TYPE_CARD);
call_card_function(pcard, (char*) "initial_effect", 1, 0);
pcard->set_status(STATUS_INITIALIZING, FALSE);
}
pcard->cardid = pduel->game_field->infos.card_id++;
return OPERATION_SUCCESS;
}
void interpreter::register_effect(effect *peffect) {
if (!peffect)
return;
//create a effect in by userdata
effect ** ppeffect = (effect**) lua_newuserdata(lua_state, sizeof(effect*));
*ppeffect = peffect;
peffect->ref_handle = luaL_ref(lua_state, LUA_REGISTRYINDEX);
//set metatable of pointer to base script
lua_rawgeti(lua_state, LUA_REGISTRYINDEX, peffect->ref_handle);
lua_getglobal(lua_state, "Effect");
lua_setmetatable(lua_state, -2);
lua_pop(lua_state, 1);
}
void interpreter::unregister_effect(effect *peffect) {
if (!peffect)
return;
if(peffect->condition)
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->condition);
if(peffect->cost)
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->cost);
if(peffect->target)
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->target);
if(peffect->operation)
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->operation);
if(peffect->value && (peffect->flag & EFFECT_FLAG_FUNC_VALUE))
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->value);
luaL_unref(lua_state, LUA_REGISTRYINDEX, peffect->ref_handle);
peffect->ref_handle = 0;
}
void interpreter::register_group(group *pgroup) {
if (!pgroup)
return;
//create a group in by userdata
group ** ppgroup = (group**) lua_newuserdata(lua_state, sizeof(group*));
*ppgroup = pgroup;
pgroup->ref_handle = luaL_ref(lua_state, LUA_REGISTRYINDEX);
//set metatable of pointer to base script
lua_rawgeti(lua_state, LUA_REGISTRYINDEX, pgroup->ref_handle);
lua_getglobal(lua_state, "Group");
lua_setmetatable(lua_state, -2);
lua_pop(lua_state, 1);
}
void interpreter::unregister_group(group *pgroup) {
if (!pgroup)
return;
luaL_unref(lua_state, LUA_REGISTRYINDEX, pgroup->ref_handle);
pgroup->ref_handle = 0;
}
int32 interpreter::load_script(char* script_name) {
int32 error;
int32 len = 0;
byte* buffer = read_script(script_name, &len);
if (!buffer)
return OPERATION_FAIL;
no_action++;
error = luaL_loadbuffer(current_state, (const char*) buffer, len, (const char*) script_name) || lua_pcall(current_state, 0, 0, 0);
if (error) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
return OPERATION_FAIL;
}
no_action--;
return OPERATION_SUCCESS;
}
int32 interpreter::load_card_script(uint32 code) {
char class_name[20];
char script_name[64];
sprintf(class_name, "c%d", code);
lua_getglobal(current_state, class_name);
//if script is not loaded, create and load it
if (lua_isnil(current_state, -1)) {
lua_pop(current_state, 1);
//create a table & set metatable
lua_createtable(current_state, 0, 0);
lua_setglobal(current_state, class_name);
lua_getglobal(current_state, class_name);
lua_getglobal(current_state, "Card");
lua_setmetatable(current_state, -2);
lua_pushstring(current_state, "__index");
lua_pushvalue(current_state, -2);
lua_rawset(current_state, -3);
//load extra scripts
sprintf(script_name, "./script/c%d.lua", code);
if (!load_script(script_name)) {
return OPERATION_FAIL;
}
}
return OPERATION_SUCCESS;
}
void interpreter::add_param(void *param, int32 type, bool front) {
if(front)
params.push_front(make_pair(param, type));
else
params.push_back(make_pair(param, type));
}
void interpreter::add_param(ptr param, int32 type, bool front) {
if(front)
params.push_front(make_pair((void*)param, type));
else
params.push_back(make_pair((void*)param, type));
}
void interpreter::push_param(lua_State* L, bool is_coroutine) {
uint32 type;
int32 pushed = 0;
for (auto it = params.begin(); it != params.end(); ++it) {
type = it->second;
switch(type) {
case PARAM_TYPE_INT:
lua_pushinteger(L, (ptr) it->first);
break;
case PARAM_TYPE_STRING:
lua_pushstring(L, (const char *) it->first);
break;
case PARAM_TYPE_BOOLEAN:
lua_pushboolean(L, (ptr) it->first);
break;
case PARAM_TYPE_CARD: {
if (it->first)
lua_rawgeti(L, LUA_REGISTRYINDEX, ((card*)it->first)->ref_handle);
else
lua_pushnil(L);
break;
}
case PARAM_TYPE_EFFECT: {
if (it->first)
lua_rawgeti(L, LUA_REGISTRYINDEX, ((effect*)it->first)->ref_handle);
else
lua_pushnil(L);
break;
}
case PARAM_TYPE_GROUP: {
if (it->first)
lua_rawgeti(L, LUA_REGISTRYINDEX, ((group*)it->first)->ref_handle);
else
lua_pushnil(L);
break;
}
case PARAM_TYPE_FUNCTION: {
function2value(L, (ptr)it->first);
break;
}
case PARAM_TYPE_INDEX: {
int32 index = (int32)(ptr)it->first;
if(index > 0)
lua_pushvalue(L, index);
else if(is_coroutine) {
//copy value from current_state to new stack
lua_pushvalue(current_state, index);
int32 ref = luaL_ref(current_state, LUA_REGISTRYINDEX);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
luaL_unref(current_state, LUA_REGISTRYINDEX, ref);
} else {
//the calling function is pushed before the params, so the actual index is: index - pushed -1
lua_pushvalue(L, index - pushed - 1);
}
break;
}
}
pushed++;
}
params.clear();
}
int32 interpreter::call_function(int32 f, uint32 param_count, uint32 ret_count) {
if (!f) {
sprintf(pduel->strbuffer, "\"CallFunction\": attempt to call a null function.");
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
if (param_count != params.size()) {
sprintf(pduel->strbuffer, "\"CallFunction\": incorrect parameter count (%d expected, %ud pushed)", param_count, params.size());
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
function2value(current_state, f);
if (!lua_isfunction(current_state, -1)) {
sprintf(pduel->strbuffer, "\"CallFunction\": attempt to call an error function");
handle_message(pduel, 1);
lua_pop(current_state, 1);
params.clear();
return OPERATION_FAIL;
}
no_action++;
call_depth++;
push_param(current_state);
if (lua_pcall(current_state, param_count, ret_count, 0)) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_SUCCESS;
}
int32 interpreter::call_card_function(card* pcard, char* f, uint32 param_count, uint32 ret_count) {
if (param_count != params.size()) {
sprintf(pduel->strbuffer, "\"CallCardFunction\"(c%d.%s): incorrect parameter count", pcard->data.code, f);
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
card2value(current_state, pcard);
lua_getfield(current_state, -1, f);
if (!lua_isfunction(current_state, -1)) {
sprintf(pduel->strbuffer, "\"CallCardFunction\"(c%d.%s): attempt to call an error function", pcard->data.code, f);
handle_message(pduel, 1);
lua_pop(current_state, 2);
params.clear();
return OPERATION_FAIL;
}
no_action++;
call_depth++;
lua_remove(current_state, -2);
push_param(current_state);
if (lua_pcall(current_state, param_count, ret_count, 0)) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_SUCCESS;
}
int32 interpreter::call_code_function(uint32 code, char* f, uint32 param_count, uint32 ret_count) {
if (param_count != params.size()) {
sprintf(pduel->strbuffer, "\"CallCodeFunction\": incorrect parameter count");
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
load_card_script(code);
lua_getfield(current_state, -1, f);
if (!lua_isfunction(current_state, -1)) {
sprintf(pduel->strbuffer, "\"CallCodeFunction\": attempt to call an error function");
handle_message(pduel, 1);
lua_pop(current_state, 2);
params.clear();
return OPERATION_FAIL;
}
lua_remove(current_state, -2);
no_action++;
call_depth++;
push_param(current_state);
if (lua_pcall(current_state, param_count, ret_count, 0)) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_SUCCESS;
}
int32 interpreter::check_condition(int32 f, uint32 param_count) {
int32 result;
if(!f) {
params.clear();
return TRUE;
}
no_action++;
call_depth++;
if (call_function(f, param_count, 1)) {
result = lua_toboolean(current_state, -1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return result;
}
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
int32 interpreter::check_matching(card* pcard, int32 findex, int32 extraargs) {
int32 result;
if(!findex || lua_isnil(current_state, findex))
return TRUE;
no_action++;
call_depth++;
lua_pushvalue(current_state, findex);
interpreter::card2value(current_state, pcard);
for(int32 i = 0; i < extraargs; ++i)
lua_pushvalue(current_state, (int32)(-extraargs - 2));
if (lua_pcall(current_state, 1 + extraargs, 1, 0)) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
result = lua_toboolean(current_state, -1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return result;
}
int32 interpreter::get_operation_value(card* pcard, int32 findex, int32 extraargs) {
int32 result;
if(!findex || lua_isnil(current_state, findex))
return 0;
no_action++;
call_depth++;
lua_pushvalue(current_state, findex);
interpreter::card2value(current_state, pcard);
for(int32 i = 0; i < extraargs; ++i)
lua_pushvalue(current_state, (int32)(-extraargs - 2));
if (lua_pcall(current_state, 1 + extraargs, 1, 0)) {
sprintf(pduel->strbuffer, lua_tostring(current_state, -1));
handle_message(pduel, 1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
result = lua_tointeger(current_state, -1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return result;
}
int32 interpreter::get_function_value(int32 f, uint32 param_count) {
int32 result;
if(!f) {
params.clear();
return 0;
}
no_action++;
call_depth++;
if (call_function(f, param_count, 1)) {
if (lua_isboolean(current_state, -1))
result = lua_toboolean(current_state, -1);
else
result = lua_tointeger(current_state, -1);
lua_pop(current_state, 1);
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return result;
}
no_action--;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
int32 interpreter::call_coroutine(int32 f, uint32 param_count, uint32 * yield_value, uint16 step) {
*yield_value = 0;
if (!f) {
sprintf(pduel->strbuffer, "\"CallCoroutine\": attempt to call a null function");
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
if (param_count != params.size()) {
sprintf(pduel->strbuffer, "\"CallCoroutine\": incorrect parameter count");
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
coroutine_map::iterator it;
it = coroutines.find(f);
lua_State* rthread;
if (it == coroutines.end()) {
rthread = lua_newthread(lua_state);
function2value(rthread, f);
if(!lua_isfunction(rthread, -1)) {
sprintf(pduel->strbuffer, "\"CallCoroutine\": attempt to call an error function");
handle_message(pduel, 1);
params.clear();
return OPERATION_FAIL;
}
call_depth++;
coroutines.insert(make_pair(f, rthread));
} else {
rthread = it->second;
if(step == 0) {
sprintf(pduel->strbuffer, "recursive event trigger detected.");
handle_message(pduel, 1);
params.clear();
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return OPERATION_FAIL;
}
}
push_param(rthread, true);
current_state = rthread;
int32 result = lua_resume(rthread, 0, param_count);
if (result == 0) {
coroutines.erase(f);
if(yield_value)
*yield_value = lua_isboolean(rthread, -1) ? lua_toboolean(rthread, -1) : lua_tointeger(rthread, -1);
current_state = lua_state;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return COROUTINE_FINISH;
} else if (result == LUA_YIELD) {
return COROUTINE_YIELD;
} else {
coroutines.erase(f);
sprintf(pduel->strbuffer, lua_tostring(rthread, -1));
handle_message(pduel, 1);
lua_pop(rthread, 1);
current_state = lua_state;
call_depth--;
if(call_depth == 0) {
pduel->release_script_group();
pduel->restore_assumes();
}
return COROUTINE_ERROR;
}
}
//Convert a pointer to a lua value, +1 -0
void interpreter::card2value(lua_State* L, card* pcard) {
if (!pcard || pcard->ref_handle == 0)
lua_pushnil(L);
else
lua_rawgeti(L, LUA_REGISTRYINDEX, pcard->ref_handle);
}
void interpreter::group2value(lua_State* L, group* pgroup) {
if (!pgroup || pgroup->ref_handle == 0)
lua_pushnil(L);
else
lua_rawgeti(L, LUA_REGISTRYINDEX, pgroup->ref_handle);
}
void interpreter::effect2value(lua_State* L, effect* peffect) {
if (!peffect || peffect->ref_handle == 0)
lua_pushnil(L);
else
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->ref_handle);
}
void interpreter::function2value(lua_State* L, int32 func_ref) {
if (!func_ref)
lua_pushnil(L);
else
lua_rawgeti(L, LUA_REGISTRYINDEX, func_ref);
}
int32 interpreter::get_function_handle(lua_State* L, int32 index) {
lua_pushvalue(L, index);
int32 ref = luaL_ref(L, LUA_REGISTRYINDEX);
return ref;
}
void interpreter::set_duel_info(lua_State* L, duel* pduel) {
lua_pushlightuserdata(L, pduel);
luaL_ref(L, LUA_REGISTRYINDEX);
}
duel* interpreter::get_duel_info(lua_State * L) {
lua_rawgeti(L, LUA_REGISTRYINDEX, 3);
duel* pduel = (duel*)lua_topointer(L, -1);
lua_pop(L, 1);
return pduel;
}
/*
* interpreter.h
*
* Created on: 2010-4-28
* Author: Argon
*/
#ifndef INTERPRETER_H_
#define INTERPRETER_H_
extern "C" {
#ifdef WIN32
#include <lua/lua.h>
#include <lua/lauxlib.h>
#include <lua/lualib.h>
#else
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#endif
}
#include "common.h"
#include <unordered_map>
#include <list>
class card;
class effect;
class group;
class duel;
class interpreter {
public:
typedef std::unordered_map<int32, lua_State*> coroutine_map;
typedef std::list<std::pair<void*, uint32> > param_list;
duel* pduel;
char msgbuf[64];
lua_State* lua_state;
lua_State* current_state;
param_list params;
param_list resumes;
coroutine_map coroutines;
int32 no_action;
int32 call_depth;
explicit interpreter(duel* pd);
~interpreter();
int32 register_card(card *pcard);
void register_effect(effect* peffect);
void unregister_effect(effect* peffect);
void register_group(group* pgroup);
void unregister_group(group* pgroup);
int32 load_script(char* buffer);
int32 load_card_script(uint32 code);
void add_param(void* param, int32 type, bool front = false);
void add_param(ptr param, int32 type, bool front = false);
void push_param(lua_State* L, bool is_coroutine = false);
int32 call_function(int32 f, uint32 param_count, uint32 ret_count);
int32 call_card_function(card *pcard, char *f, uint32 param_count, uint32 ret_count);
int32 call_code_function(uint32 code, char *f, uint32 param_count, uint32 ret_count);
int32 check_condition(int32 f, uint32 param_count);
int32 check_matching(card* pcard, int32 findex, int32 extraargs);
int32 get_operation_value(card* pcard, int32 findex, int32 extraargs);
int32 get_function_value(int32 f, uint32 param_count);
int32 call_coroutine(int32 f, uint32 param_count, uint32* yield_value, uint16 step);
static void card2value(lua_State* L, card* pcard);
static void group2value(lua_State* L, group* pgroup);
static void effect2value(lua_State* L, effect* peffect);
static void function2value(lua_State* L, int32 pointer);
static int32 get_function_handle(lua_State* L, int32 index);
static void set_duel_info(lua_State* L, duel* pduel);
static duel* get_duel_info(lua_State* L);
};
#define PARAM_TYPE_INT 0x01
#define PARAM_TYPE_STRING 0x02
#define PARAM_TYPE_CARD 0x04
#define PARAM_TYPE_GROUP 0x08
#define PARAM_TYPE_EFFECT 0x10
#define PARAM_TYPE_FUNCTION 0x20
#define PARAM_TYPE_BOOLEAN 0x40
#define PARAM_TYPE_INDEX 0x80
#define COROUTINE_FINISH 1
#define COROUTINE_YIELD 2
#define COROUTINE_ERROR 3
#endif /* INTERPRETER_H_ */
/*
* libcard.cpp
*
* Created on: 2010-5-6
* Author: Argon
*/
#include "scriptlib.h"
#include "duel.h"
#include "field.h"
#include "card.h"
#include "effect.h"
#include "group.h"
#include <iostream>
int32 scriptlib::card_get_code(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_code());
uint32 otcode = pcard->get_another_code();
if(otcode) {
lua_pushinteger(L, otcode);
return 2;
}
return 1;
}
// GetOriginalCode(): get the original code printed on card
// return: 1 int
int32 scriptlib::card_get_origin_code(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->data.alias) {
int32 dif = pcard->data.code - pcard->data.alias;
if(dif > -10 && dif < 10)
lua_pushinteger(L, pcard->data.alias);
else
lua_pushinteger(L, pcard->data.code);
} else
lua_pushinteger(L, pcard->data.code);
return 1;
}
// GetOriginalCodeRule(): get the original code in duel (can be different from printed code)
// return: 1-2 int
int32 scriptlib::card_get_origin_code_rule(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
effect_set eset;
pcard->filter_effect(EFFECT_ADD_CODE, &eset);
if(pcard->data.alias && !eset.size())
lua_pushinteger(L, pcard->data.alias);
else {
lua_pushinteger(L, pcard->data.code);
if(eset.size()) {
uint32 otcode = eset.get_last()->get_value(pcard);
lua_pushinteger(L, otcode);
return 2;
}
}
return 1;
}
int32 scriptlib::card_is_set_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 set_code = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->is_set_card(set_code));
return 1;
}
int32 scriptlib::card_is_pre_set_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 set_code = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->is_pre_set_card(set_code));
return 1;
}
int32 scriptlib::card_get_type(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_type());
return 1;
}
int32 scriptlib::card_get_origin_type(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->data.type);
return 1;
}
int32 scriptlib::card_get_level(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_level());
return 1;
}
int32 scriptlib::card_get_rank(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_rank());
return 1;
}
int32 scriptlib::card_get_synchro_level(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* scard = *(card**) lua_touserdata(L, 2);
lua_pushinteger(L, pcard->get_synchro_level(scard));
return 1;
}
int32 scriptlib::card_get_ritual_level(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* scard = *(card**) lua_touserdata(L, 2);
lua_pushinteger(L, pcard->get_ritual_level(scard));
return 1;
}
int32 scriptlib::card_get_origin_level(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if((pcard->data.type & TYPE_XYZ) || (pcard->status & STATUS_NO_LEVEL))
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.level);
return 1;
}
int32 scriptlib::card_get_origin_rank(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(!(pcard->data.type & TYPE_XYZ))
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.level);
return 1;
}
int32 scriptlib::card_is_xyz_level(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* xyzcard = *(card**) lua_touserdata(L, 2);
uint32 lv = lua_tointeger(L, 3);
lua_pushboolean(L, pcard->check_xyz_level(xyzcard, lv));
return 1;
}
int32 scriptlib::card_get_lscale(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_lscale());
return 1;
}
int32 scriptlib::card_get_origin_lscale(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->data.lscale);
return 1;
}
int32 scriptlib::card_get_rscale(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_rscale());
return 1;
}
int32 scriptlib::card_get_origin_rscale(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->data.rscale);
return 1;
}
int32 scriptlib::card_get_attribute(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_attribute());
return 1;
}
int32 scriptlib::card_get_origin_attribute(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_NO_LEVEL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.attribute);
return 1;
}
int32 scriptlib::card_get_race(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_race());
return 1;
}
int32 scriptlib::card_get_origin_race(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_NO_LEVEL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.race);
return 1;
}
int32 scriptlib::card_get_attack(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_attack());
return 1;
}
int32 scriptlib::card_get_origin_attack(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_base_attack());
return 1;
}
int32 scriptlib::card_get_text_attack(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_NO_LEVEL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.attack);
return 1;
}
int32 scriptlib::card_get_defence(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_defence());
return 1;
}
int32 scriptlib::card_get_origin_defence(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_base_defence());
return 1;
}
int32 scriptlib::card_get_text_defence(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_NO_LEVEL)
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->data.defence);
return 1;
}
int32 scriptlib:: card_get_previous_code_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.code);
if(pcard->previous.code2) {
lua_pushinteger(L, pcard->previous.code2);
return 2;
}
return 1;
}
int32 scriptlib::card_get_previous_type_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.type);
return 1;
}
int32 scriptlib::card_get_previous_level_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.level);
return 1;
}
int32 scriptlib::card_get_previous_rank_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.rank);
return 1;
}
int32 scriptlib::card_get_previous_attribute_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.attribute);
return 1;
}
int32 scriptlib::card_get_previous_race_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.race);
return 1;
}
int32 scriptlib::card_get_previous_attack_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.attack);
return 1;
}
int32 scriptlib::card_get_previous_defence_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.defence);
return 1;
}
int32 scriptlib::card_get_owner(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->owner);
return 1;
}
int32 scriptlib::card_get_controler(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->current.controler);
return 1;
}
int32 scriptlib::card_get_previous_controler(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.controler);
return 1;
}
int32 scriptlib::card_get_reason(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->current.reason);
return 1;
}
int32 scriptlib::card_get_reason_card(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
interpreter::card2value(L, pcard->current.reason_card);
return 1;
}
int32 scriptlib::card_get_reason_player(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->current.reason_player);
return 1;
}
int32 scriptlib::card_get_reason_effect(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
interpreter::effect2value(L, pcard->current.reason_effect);
return 1;
}
int32 scriptlib::card_get_position(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->current.position);
return 1;
}
int32 scriptlib::card_get_previous_position(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.position);
return 1;
}
int32 scriptlib::card_get_battle_position(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->temp.position);
return 1;
}
int32 scriptlib::card_get_location(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->is_status(STATUS_SUMMONING) || pcard->is_status(STATUS_SUMMON_DISABLED))
lua_pushinteger(L, 0);
else
lua_pushinteger(L, pcard->current.location);
return 1;
}
int32 scriptlib::card_get_previous_location(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.location);
return 1;
}
int32 scriptlib::card_get_sequence(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->current.sequence);
return 1;
}
int32 scriptlib::card_get_previous_sequence(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->previous.sequence);
return 1;
}
int32 scriptlib::card_get_summon_type(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->summon_info & 0xff00ffff);
return 1;
}
int32 scriptlib::card_get_summon_location(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, (pcard->summon_info >> 16) & 0xff);
return 1;
}
int32 scriptlib::card_get_summon_player(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->summon_player);
return 1;
}
int32 scriptlib::card_get_destination(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, (pcard->operation_param >> 8) & 0xff);
return 1;
}
int32 scriptlib::card_get_leave_field_dest(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->leave_field_redirect(REASON_EFFECT));
return 1;
}
int32 scriptlib::card_get_turnid(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->turnid);
return 1;
}
int32 scriptlib::card_get_fieldid(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->fieldid);
return 1;
}
int32 scriptlib::card_get_fieldidr(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->fieldid_r);
return 1;
}
int32 scriptlib::card_is_code(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 code1 = pcard->get_code();
uint32 code2 = pcard->get_another_code();
uint32 count = lua_gettop(L) - 1;
uint32 result = FALSE;
for(uint32 i = 0; i < count; ++i) {
if(lua_isnil(L, i + 2))
continue;
uint32 tcode = lua_tointeger(L, i + 2);
if(code1 == tcode || (code2 && code2 == tcode)) {
result = TRUE;
break;
}
}
lua_pushboolean(L, result);
return 1;
}
int32 scriptlib::card_is_type(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 ttype = lua_tointeger(L, 2);
if(pcard->get_type() & ttype)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_race(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 trace = lua_tointeger(L, 2);
if(pcard->get_race() & trace)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_attribute(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 tattrib = lua_tointeger(L, 2);
if(pcard->get_attribute() & tattrib)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_reason(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 treason = lua_tointeger(L, 2);
if(pcard->current.reason & treason)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_status(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 tstatus = lua_tounsigned(L, 2);
if(pcard->status & tstatus)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
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();
if(!(type & TYPE_TUNER) || pcard->is_affected_by_effect(EFFECT_NONTUNER))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_set_status(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_COPYING_EFFECT)
return 0;
uint32 tstatus = lua_tounsigned(L, 2);
int32 enable = lua_toboolean(L, 3);
pcard->set_status(tstatus, enable);
return 0;
}
int32 scriptlib::card_is_dual_state(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, (ptr)pcard->is_affected_by_effect(EFFECT_DUAL_STATUS));
return 1;
}
int32 scriptlib::card_enable_dual_state(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
effect* deffect = pduel->new_effect();
deffect->owner = pcard;
deffect->code = EFFECT_DUAL_STATUS;
deffect->type = EFFECT_TYPE_SINGLE;
deffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
deffect->reset_flag = RESET_EVENT + 0x1fe0000;
pcard->add_effect(deffect);
return 0;
}
int32 scriptlib::card_set_turn_counter(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 ct = lua_tointeger(L, 2);
pcard->count_turn(ct);
return 0;
}
int32 scriptlib::card_get_turn_counter(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->turn_counter);
return 1;
}
int32 scriptlib::card_set_material(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(!lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_GROUP, 2);
group* pgroup = *(group**) lua_touserdata(L, 2);
pcard->set_material(&pgroup->container);
} else
pcard->set_material(0);
return 0;
}
int32 scriptlib::card_get_material(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group(pcard->material_cards);
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_material_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->material_cards.size());
return 1;
}
int32 scriptlib::card_get_equip_group(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group(pcard->equiping_cards);
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_equip_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->equiping_cards.size());
return 1;
}
int32 scriptlib::card_get_equip_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
interpreter::card2value(L, pcard->equiping_target);
return 1;
}
int32 scriptlib::card_get_pre_equip_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
interpreter::card2value(L, pcard->pre_equip_target);
return 1;
}
int32 scriptlib::card_check_equip_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* target = *(card**) lua_touserdata(L, 2);
if(pcard->is_affected_by_effect(EFFECT_EQUIP_LIMIT, target)
&& (!pcard->is_status(STATUS_UNION) || target->get_union_count() == 0))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_get_union_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->get_union_count());
return 1;
}
int32 scriptlib::card_get_overlay_group(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group();
pgroup->container.insert(pcard->xyz_materials.begin(), pcard->xyz_materials.end());
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_overlay_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->xyz_materials.size());
return 1;
}
int32 scriptlib::card_get_overlay_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
interpreter::card2value(L, pcard->overlay_target);
return 1;
}
int32 scriptlib::card_check_remove_overlay_card(lua_State *L) {
check_param_count(L, 4);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
int32 count = lua_tointeger(L, 3);
int32 reason = lua_tointeger(L, 4);
duel* pduel = pcard->pduel;
lua_pushboolean(L, pduel->game_field->is_player_can_remove_overlay_card(playerid, pcard, 0, 0, count, reason));
return 1;
}
int32 scriptlib::card_remove_overlay_card(lua_State *L) {
check_action_permission(L);
check_param_count(L, 5);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
int32 min = lua_tointeger(L, 3);
int32 max = lua_tointeger(L, 4);
int32 reason = lua_tointeger(L, 5);
duel* pduel = pcard->pduel;
pduel->game_field->remove_overlay_card(reason, pcard, playerid, 0, 0, min, max);
return lua_yield(L, 0);
}
int32 scriptlib::card_get_attacked_group(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group();
card::attacker_map::iterator cit;
for(cit = pcard->attacked_cards.begin(); cit != pcard->attacked_cards.end(); ++cit) {
if(cit->second)
pgroup->container.insert(cit->second);
}
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_attacked_group_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->attacked_cards.size());
return 1;
}
int32 scriptlib::card_get_attacked_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->attacked_count);
return 1;
}
int32 scriptlib::card_get_battled_group(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group();
card::attacker_map::iterator cit;
for(cit = pcard->battled_cards.begin(); cit != pcard->battled_cards.end(); ++cit) {
if(cit->second)
pgroup->container.insert(cit->second);
}
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_battled_group_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->battled_cards.size());
return 1;
}
int32 scriptlib::card_get_attack_announced_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->announce_count);
return 1;
}
int32 scriptlib::card_is_direct_attacked(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
bool ret = false;
for(auto cit = pcard->attacked_cards.begin(); cit != pcard->attacked_cards.end(); ++cit)
if(cit->first == 0)
ret = true;
lua_pushboolean(L, ret);
return 1;
}
int32 scriptlib::card_set_card_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* ocard = *(card**) lua_touserdata(L, 2);
pcard->add_card_target(ocard);
return 0;
}
int32 scriptlib::card_get_card_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group(pcard->effect_target_cards);
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_first_card_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->effect_target_cards.size())
interpreter::card2value(L, *pcard->effect_target_cards.begin());
else lua_pushnil(L);
return 1;
}
int32 scriptlib::card_get_card_target_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->effect_target_cards.size());
return 1;
}
int32 scriptlib::card_is_has_card_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* rcard = *(card**) lua_touserdata(L, 2);
lua_pushboolean(L, pcard->effect_target_cards.count(rcard));
return 1;
}
int32 scriptlib::card_cancel_card_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* rcard = *(card**) lua_touserdata(L, 2);
pcard->cancel_card_target(rcard);
return 0;
}
int32 scriptlib::card_get_owner_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
group* pgroup = pcard->pduel->new_group(pcard->effect_target_owner);
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::card_get_owner_target_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushinteger(L, pcard->effect_target_owner.size());
return 1;
}
int32 scriptlib::card_get_activate_effect(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 count = 0;
for(auto eit = pcard->field_effect.begin(); eit != pcard->field_effect.end(); ++eit) {
if(eit->second->type & EFFECT_TYPE_ACTIVATE) {
interpreter::effect2value(L, eit->second);
count++;
}
}
return count;
}
int32 scriptlib::card_check_activate_effect(lua_State *L) {
check_param_count(L, 4);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 neglect_con = lua_toboolean(L, 2);
int32 neglect_cost = lua_toboolean(L, 3);
int32 copy_info = lua_toboolean(L, 4);
duel* pduel = pcard->pduel;
tevent pe;
for(auto eit = pcard->field_effect.begin(); eit != pcard->field_effect.end(); ++eit) {
effect* peffect = eit->second;
if((peffect->type & EFFECT_TYPE_ACTIVATE)
&& pduel->game_field->check_event_c(peffect, pduel->game_field->core.reason_player, neglect_con, neglect_cost, copy_info, &pe)) {
if(!copy_info || (peffect->code == EVENT_FREE_CHAIN)) {
interpreter::effect2value(L, peffect);
return 1;
} else {
interpreter::effect2value(L, peffect);
interpreter::group2value(L, pe.event_cards);
lua_pushinteger(L, pe.event_player);
lua_pushinteger(L, pe.event_value);
interpreter::effect2value(L, pe.reason_effect);
lua_pushinteger(L, pe.reason);
lua_pushinteger(L, pe.reason_player);
return 7;
}
}
}
return 0;
}
int32 scriptlib::card_register_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
int32 forced = lua_toboolean(L, 3);
duel* pduel = pcard->pduel;
if(peffect->owner == pduel->game_field->temp_card)
return 0;
if(!forced && pduel->game_field->core.reason_effect && !pcard->is_affect_by_effect(pduel->game_field->core.reason_effect)) {
pduel->game_field->core.reseted_effects.insert(peffect);
return 0;
}
int32 id;
if (peffect->handler)
id = -1;
else
id = pcard->add_effect(peffect);
lua_pushinteger(L, id);
return 1;
}
int32 scriptlib::card_is_has_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 code = lua_tointeger(L, 2);
if(pcard && pcard->is_affected_by_effect(code))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_reset_effect(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 code = lua_tointeger(L, 2);
uint32 type = lua_tointeger(L, 3);
pcard->reset(code, type);
return 0;
}
int32 scriptlib::card_get_effect_count(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 code = lua_tointeger(L, 2);
effect_set eset;
pcard->filter_effect(code, &eset);
lua_pushinteger(L, eset.size());
return 1;
}
int32 scriptlib::card_register_flag_effect(lua_State *L) {
check_param_count(L, 5);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 code = (lua_tointeger(L, 2) & 0xfffffff) | 0x10000000;
int32 reset = lua_tointeger(L, 3);
int32 flag = lua_tointeger(L, 4);
int32 count = lua_tointeger(L, 5);
int32 lab = 0;
int32 desc = 0;
if(lua_gettop(L) >= 6)
lab = lua_tointeger(L, 6);
if(lua_gettop(L) >= 7)
desc = lua_tointeger(L, 7);
if(count == 0)
count = 1;
if(reset & (RESET_PHASE) && !(reset & (RESET_SELF_TURN | RESET_OPPO_TURN)))
reset |= (RESET_SELF_TURN | RESET_OPPO_TURN);
duel* pduel = pcard->pduel;
effect* peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->handler = 0;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = code;
peffect->reset_flag = reset;
peffect->flag = flag | EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_count |= count & 0xff;
peffect->label = lab;
peffect->description = desc;
pcard->add_effect(peffect);
interpreter::effect2value(L, peffect);
return 1;
}
int32 scriptlib::card_get_flag_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 code = (lua_tointeger(L, 2) & 0xfffffff) | 0x10000000;
lua_pushinteger(L, pcard->single_effect.count(code));
return 1;
}
int32 scriptlib::card_reset_flag_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 code = (lua_tointeger(L, 2) & 0xfffffff) | 0x10000000;
pcard->reset(code, RESET_CODE);
return 0;
}
int32 scriptlib::card_set_flag_effect_label(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 code = (lua_tointeger(L, 2) & 0xfffffff) | 0x10000000;
int lab = lua_tointeger(L, 3);
auto eit = pcard->single_effect.find(code);
if(eit == pcard->single_effect.end())
lua_pushboolean(L, FALSE);
else {
eit->second->label = lab;
lua_pushboolean(L, TRUE);
}
return 1;
}
int32 scriptlib::card_get_flag_effect_label(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 code = (lua_tointeger(L, 2) & 0xfffffff) | 0x10000000;
auto eit = pcard->single_effect.find(code);
if(eit == pcard->single_effect.end())
lua_pushnil(L);
else
lua_pushinteger(L, eit->second->label);
return 1;
}
int32 scriptlib::card_create_relation(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* rcard = *(card**) lua_touserdata(L, 2);
uint32 reset = lua_tointeger(L, 3);
pcard->create_relation(rcard, reset);
return 0;
}
int32 scriptlib::card_release_relation(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* rcard = *(card**) lua_touserdata(L, 2);
pcard->release_relation(rcard);
return 0;
}
int32 scriptlib::card_create_effect_relation(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
pcard->create_relation(peffect);
return 0;
}
int32 scriptlib::card_release_effect_relation(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
pcard->release_relation(peffect);
return 0;
}
int32 scriptlib::card_clear_effect_relation(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
pcard->relate_effect.clear();
return 0;
}
int32 scriptlib::card_is_relate_to_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
if(pcard && pcard->is_has_relation(peffect))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_relate_to_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* rcard = *(card**) lua_touserdata(L, 2);
if(pcard && pcard->is_has_relation(rcard))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_relate_to_battle(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
if(pcard->fieldid_r == pduel->game_field->core.pre_field[0] || pcard->fieldid_r == pduel->game_field->core.pre_field[1])
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_copy_effect(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 code = lua_tointeger(L, 2);
uint32 reset = lua_tointeger(L, 3);
uint32 count = lua_tointeger(L, 4);
if(count == 0)
count = 1;
if(reset & RESET_PHASE && !(reset & (RESET_SELF_TURN | RESET_OPPO_TURN)))
reset |= (RESET_SELF_TURN | RESET_OPPO_TURN);
lua_pushinteger(L, pcard->copy_effect(code, reset, count));
return 1;
}
int32 scriptlib::card_enable_unsummonable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
if(!pcard->is_status(STATUS_COPYING_EFFECT)) {
effect* peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->code = EFFECT_UNSUMMONABLE_CARD;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE | EFFECT_FLAG_UNCOPYABLE;
pcard->add_effect(peffect);
}
return 0;
}
int32 scriptlib::card_enable_revive_limit(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
if(!pcard->is_status(STATUS_COPYING_EFFECT)) {
effect* peffect1 = pduel->new_effect();
peffect1->owner = pcard;
peffect1->code = EFFECT_UNSUMMONABLE_CARD;
peffect1->type = EFFECT_TYPE_SINGLE;
peffect1->flag = EFFECT_FLAG_CANNOT_DISABLE | EFFECT_FLAG_UNCOPYABLE;
pcard->add_effect(peffect1);
effect* peffect2 = pduel->new_effect();
peffect2->owner = pcard;
peffect2->code = EFFECT_REVIVE_LIMIT;
peffect2->type = EFFECT_TYPE_SINGLE;
peffect2->flag = EFFECT_FLAG_CANNOT_DISABLE | EFFECT_FLAG_UNCOPYABLE;
pcard->add_effect(peffect2);
}
return 0;
}
int32 scriptlib::card_complete_procedure(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
pcard->set_status(STATUS_PROC_COMPLETE, TRUE);
return 0;
}
int32 scriptlib::card_is_disabled(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_status(STATUS_DISABLED));
return 1;
}
int32 scriptlib::card_is_destructable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
effect* peffect = 0;
if(lua_gettop(L) > 1) {
check_param(L, PARAM_TYPE_EFFECT, 2);
peffect = *(effect**) lua_touserdata(L, 2);
}
card* pcard = *(card**) lua_touserdata(L, 1);
if(peffect)
lua_pushboolean(L, pcard->is_destructable_by_effect(peffect, pcard->pduel->game_field->core.reason_player));
else
lua_pushboolean(L, pcard->is_destructable());
return 1;
}
int32 scriptlib::card_is_summonable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card * pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_summonable());
return 1;
}
int32 scriptlib::card_is_msetable(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
uint32 ign = lua_toboolean(L, 2);
effect* peffect = 0;
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_EFFECT, 3);
peffect = *(effect**)lua_touserdata(L, 3);
}
uint32 minc = 0;
if(lua_gettop(L) > 3)
minc = lua_tointeger(L, 4);
lua_pushboolean(L, pcard->is_setable_mzone(p, ign, peffect, minc));
return 1;
}
int32 scriptlib::card_is_ssetable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
uint32 ign = FALSE;
if(lua_gettop(L) >= 2)
ign = lua_toboolean(L, 2);
lua_pushboolean(L, pcard->is_setable_szone(p, ign));
return 1;
}
int32 scriptlib::card_is_special_summonable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
lua_pushboolean(L, pcard->is_special_summonable(p, 0));
return 1;
}
int32 scriptlib::card_is_synchro_summonable(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(!(pcard->data.type & TYPE_SYNCHRO))
return 0;
card* tuner = 0;
group* mg = 0;
if(!lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_CARD, 2);
tuner = *(card**) lua_touserdata(L, 2);
}
if(lua_gettop(L) >= 3) {
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_GROUP, 3);
mg = *(group**) lua_touserdata(L, 3);
}
}
uint32 p = pcard->pduel->game_field->core.reason_player;
pcard->pduel->game_field->core.limit_tuner = tuner;
pcard->pduel->game_field->core.limit_syn = mg;
lua_pushboolean(L, pcard->is_special_summonable(p, SUMMON_TYPE_SYNCHRO));
return 1;
}
int32 scriptlib::card_is_xyz_summonable(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(!(pcard->data.type & TYPE_XYZ))
return 0;
group* materials = 0;
if(!lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_GROUP, 2);
materials = *(group**) lua_touserdata(L, 2);
}
uint32 p = pcard->pduel->game_field->core.reason_player;
pcard->pduel->game_field->core.limit_xyz = materials;
lua_pushboolean(L, pcard->is_special_summonable(p, SUMMON_TYPE_XYZ));
return 1;
}
int32 scriptlib::card_is_can_be_summoned(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
uint32 ign = lua_toboolean(L, 2);
effect* peffect = 0;
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_EFFECT, 3);
peffect = *(effect**)lua_touserdata(L, 3);
}
uint32 minc = 0;
if(lua_gettop(L) > 3)
minc = lua_tointeger(L, 4);
lua_pushboolean(L, pcard->is_can_be_summoned(p, ign, peffect, minc));
return 1;
}
int32 scriptlib::card_is_can_be_special_summoned(lua_State *L) {
check_param_count(L, 6);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
uint32 sumtype = lua_tointeger(L, 3);
uint32 sumplayer = lua_tointeger(L, 4);
uint32 nocheck = lua_toboolean(L, 5);
uint32 nolimit = lua_toboolean(L, 6);
uint32 sumpos = POS_FACEUP;
uint32 toplayer = sumplayer;
if(lua_gettop(L) > 6)
sumpos = lua_tointeger(L, 7);
if(lua_gettop(L) > 7)
toplayer = lua_tointeger(L, 8);
if(pcard->is_can_be_special_summoned(peffect, sumtype, sumpos, sumplayer, toplayer, nocheck, nolimit))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_hand(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_send_to_hand(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_grave(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_send_to_grave(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_deck(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_send_to_deck(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_extra(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_send_to_extra(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_remove(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(lua_gettop(L) >= 2)
p = lua_tointeger(L, 2);
if(pcard->is_removeable(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_hand_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_cost_to_hand(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_grave_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_cost_to_grave(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_deck_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_cost_to_deck(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_extra_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_capable_cost_to_extra(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_deck_or_extra_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
int32 val = (pcard->data.type & 0x802040) ? pcard->is_capable_cost_to_extra(p) : pcard->is_capable_cost_to_deck(p);
if(val)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_remove_as_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_removeable_as_cost(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_releasable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
if(pcard->is_releasable_by_nonsummon(p))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_releasable_by_effect(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
effect* re = pcard->pduel->game_field->core.reason_effect;
if(pcard->is_releasable_by_effect(p, re))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_discardable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 p = pcard->pduel->game_field->core.reason_player;
effect* pe = pcard->pduel->game_field->core.reason_effect;
uint32 reason = REASON_COST;
if(lua_gettop(L) > 1)
reason = lua_tointeger(L, 2);
if((reason != REASON_COST || !pcard->is_affected_by_effect(EFFECT_CANNOT_USE_AS_COST))
&& pcard->pduel->game_field->is_player_can_discard_hand(p, pcard, pe, reason))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_attackable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_capable_attack());
return 1;
}
int32 scriptlib::card_is_chain_attackable(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
int32 monsteronly = FALSE;
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
int32 ac = 2;
if(lua_gettop(L) > 1)
ac = lua_tointeger(L, 2);
if(lua_gettop(L) > 2)
monsteronly = lua_toboolean(L, 3);
card* attacker = pduel->game_field->core.attacker;
if(attacker->is_status(STATUS_BATTLE_DESTROYED)
|| attacker->current.controler != pduel->game_field->infos.turn_player
|| attacker->fieldid_r != pduel->game_field->core.pre_field[0]
|| !attacker->is_capable_attack_announce(pduel->game_field->infos.turn_player)
|| (ac != 0 && attacker->announce_count >= ac)
|| (ac == 2 && attacker->is_affected_by_effect(EFFECT_EXTRA_ATTACK))) {
lua_pushboolean(L, 0);
return 1;
}
pduel->game_field->core.select_cards.clear();
pduel->game_field->get_attack_target(attacker, &pduel->game_field->core.select_cards, TRUE);
if(pduel->game_field->core.select_cards.size() == 0 && (monsteronly || attacker->operation_param == 0))
lua_pushboolean(L, 0);
else
lua_pushboolean(L, 1);
return 1;
}
int32 scriptlib::card_is_faceup(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_position(POS_FACEUP));
return 1;
}
int32 scriptlib::card_is_attack_pos(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_position(POS_ATTACK));
return 1;
}
int32 scriptlib::card_is_facedown(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_position(POS_FACEDOWN));
return 1;
}
int32 scriptlib::card_is_defence_pos(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_position(POS_DEFENCE));
return 1;
}
int32 scriptlib::card_is_position(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 pos = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->is_position(pos));
return 1;
}
int32 scriptlib::card_is_pre_position(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 pos = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->previous.position & pos);
return 1;
}
int32 scriptlib::card_is_controler(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 con = lua_tointeger(L, 2);
if(pcard->current.controler == con)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_onfield(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if((pcard->current.location & LOCATION_ONFIELD) && !pcard->is_status(STATUS_SUMMONING) && !pcard->is_status(STATUS_SUMMON_DISABLED))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_location(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 loc = lua_tointeger(L, 2);
if(pcard->current.location == LOCATION_MZONE) {
if((loc & LOCATION_MZONE) && !pcard->is_status(STATUS_SUMMONING) && !pcard->is_status(STATUS_SUMMON_DISABLED))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
} else
lua_pushboolean(L, pcard->current.location & loc);
return 1;
}
int32 scriptlib::card_is_pre_location(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 loc = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->previous.location & loc);
return 1;
}
int32 scriptlib::card_is_level_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 lvl = lua_tointeger(L, 2);
if((pcard->data.type & TYPE_XYZ) || (pcard->status & STATUS_NO_LEVEL)
|| (!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE)))
lua_pushboolean(L, 0);
else
lua_pushboolean(L, pcard->get_level() <= lvl);
return 1;
}
int32 scriptlib::card_is_level_above(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 lvl = lua_tointeger(L, 2);
if((pcard->data.type & TYPE_XYZ) || (pcard->status & STATUS_NO_LEVEL)
|| (!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE)))
lua_pushboolean(L, 0);
else
lua_pushboolean(L, pcard->get_level() >= lvl);
return 1;
}
int32 scriptlib::card_is_rank_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 rnk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_XYZ) || (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_rank() <= rnk);
return 1;
}
int32 scriptlib::card_is_rank_above(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 rnk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_XYZ) || (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_rank() >= rnk);
return 1;
}
int32 scriptlib::card_is_attack_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 atk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE))
lua_pushboolean(L, 0);
else {
int _atk = pcard->get_attack();
lua_pushboolean(L, _atk >= 0 && _atk <= atk);
}
return 1;
}
int32 scriptlib::card_is_attack_above(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 atk = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE))
lua_pushboolean(L, 0);
else {
int _atk = pcard->get_attack();
lua_pushboolean(L, _atk >= atk);
}
return 1;
}
int32 scriptlib::card_is_defence_below(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 def = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE))
lua_pushboolean(L, 0);
else {
int _def = pcard->get_defence();
lua_pushboolean(L, _def >= 0 && _def <= def);
}
return 1;
}
int32 scriptlib::card_is_defence_above(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 def = lua_tointeger(L, 2);
if(!(pcard->data.type & TYPE_MONSTER) && !(pcard->get_type() & TYPE_MONSTER) && !(pcard->current.location & LOCATION_MZONE))
lua_pushboolean(L, 0);
else {
int _def = pcard->get_defence();
lua_pushboolean(L, _def >= def);
}
return 1;
}
int32 scriptlib::card_is_public(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->is_status(STATUS_IS_PUBLIC))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_forbidden(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->is_affected_by_effect(EFFECT_FORBIDDEN))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_able_to_change_controler(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->is_capable_change_control())
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_is_controler_can_be_changed(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->is_control_can_be_changed())
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_add_counter(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 countertype = lua_tointeger(L, 2);
uint32 count = lua_tointeger(L, 3);
if(pcard->is_affect_by_effect(pcard->pduel->game_field->core.reason_effect))
lua_pushboolean(L, pcard->add_counter(pcard->pduel->game_field->core.reason_player, countertype, count));
else lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::card_remove_counter(lua_State *L) {
check_action_permission(L);
check_param_count(L, 5);
check_param(L, PARAM_TYPE_CARD, 1);
card * pcard = *(card**) lua_touserdata(L, 1);
uint32 rplayer = lua_tointeger(L, 2);
uint32 countertype = lua_tointeger(L, 3);
uint32 count = lua_tointeger(L, 4);
uint32 reason = lua_tointeger(L, 5);
if(countertype == 0) {
for(auto cmit = pcard->counters.begin(); cmit != pcard->counters.end(); ++cmit) {
pcard->pduel->write_buffer8(MSG_REMOVE_COUNTER);
pcard->pduel->write_buffer16(cmit->first);
pcard->pduel->write_buffer8(pcard->current.controler);
pcard->pduel->write_buffer8(pcard->current.location);
pcard->pduel->write_buffer8(pcard->current.sequence);
pcard->pduel->write_buffer8(cmit->second);
}
pcard->counters.clear();
return 0;
} else {
pcard->pduel->game_field->remove_counter(reason, pcard, rplayer, 0, 0, countertype, count);
return lua_yield(L, 0);
}
}
int32 scriptlib::card_get_counter(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 countertype = lua_tointeger(L, 2);
if(countertype == 0)
lua_pushinteger(L, pcard->counters.size());
else
lua_pushinteger(L, pcard->get_counter(countertype));
return 1;
}
int32 scriptlib::card_enable_counter_permit(lua_State *L) {
check_param_count(L, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 countertype = lua_tointeger(L, 2);
uint32 prange;
if(lua_gettop(L) > 2)
prange = lua_tointeger(L, 3);
else if(pcard->data.type & TYPE_MONSTER)
prange = LOCATION_MZONE;
else
prange = LOCATION_SZONE | LOCATION_FZONE;
effect* peffect = pcard->pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_COUNTER_PERMIT | countertype;
peffect->flag = EFFECT_FLAG_SINGLE_RANGE;
peffect->range = prange;
pcard->add_effect(peffect);
return 0;
}
int32 scriptlib::card_set_counter_limit(lua_State *L) {
check_param_count(L, 3);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 countertype = lua_tointeger(L, 2);
int32 limit = lua_tointeger(L, 3);
effect* peffect = pcard->pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_COUNTER_LIMIT | countertype;
peffect->value = limit;
pcard->add_effect(peffect);
return 0;
}
int32 scriptlib::card_is_can_turn_set(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
lua_pushboolean(L, pcard->is_capable_turn_set(pcard->pduel->game_field->core.reason_player));
return 1;
}
int32 scriptlib::card_is_can_add_counter(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 countertype = lua_tointeger(L, 2);
uint32 count = lua_tointeger(L, 3);
lua_pushboolean(L, pcard->is_can_add_counter(pcard->pduel->game_field->core.reason_player, countertype, count));
return 1;
}
int32 scriptlib::card_is_can_remove_counter(lua_State *L) {
check_param_count(L, 5);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
uint32 countertype = lua_tointeger(L, 3);
uint32 count = lua_tointeger(L, 4);
uint32 reason = lua_tointeger(L, 5);
lua_pushboolean(L, pcard->pduel->game_field->is_player_can_remove_counter(playerid, pcard, 0, 0, countertype, count, reason));
return 1;
}
int32 scriptlib::card_is_can_be_fusion_material(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 ign = FALSE;
if(lua_gettop(L) >= 2)
ign = lua_toboolean(L, 2);
lua_pushboolean(L, pcard->is_can_be_fusion_material(ign));
return 1;
}
int32 scriptlib::card_is_can_be_synchro_material(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
card* scard = 0;
card* tuner = 0;
if(lua_gettop(L) >= 2) {
check_param(L, PARAM_TYPE_CARD, 2);
scard = *(card**) lua_touserdata(L, 2);
}
if(lua_gettop(L) >= 3) {
check_param(L, PARAM_TYPE_CARD, 3);
tuner = *(card**) lua_touserdata(L, 3);
}
lua_pushboolean(L, pcard->is_can_be_synchro_material(scard, tuner));
return 1;
}
int32 scriptlib::card_is_can_be_ritual_material(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
card* scard = 0;
if(lua_gettop(L) >= 2 && !lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_CARD, 2);
scard = *(card**) lua_touserdata(L, 2);
}
lua_pushboolean(L, pcard->is_can_be_ritual_material(scard));
return 1;
}
int32 scriptlib::card_is_can_be_xyz_material(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
card* scard = 0;
if(lua_gettop(L) >= 2 && !lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_CARD, 2);
scard = *(card**) lua_touserdata(L, 2);
}
lua_pushboolean(L, pcard->is_can_be_xyz_material(scard));
return 1;
}
int32 scriptlib::card_check_fusion_material(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 chkf = PLAYER_NONE;
group* pgroup = 0;
if(lua_gettop(L) > 1 && !lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_GROUP, 2);
pgroup = *(group**) lua_touserdata(L, 2);
}
card* cg = 0;
if(lua_gettop(L) > 2 && !lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_CARD, 3);
cg = *(card**) lua_touserdata(L, 3);
}
if(lua_gettop(L) > 3)
chkf = lua_tointeger(L, 4);
lua_pushboolean(L, pcard->fusion_check(pgroup, cg, chkf));
return 1;
}
int32 scriptlib::card_is_immune_to_effect(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_EFFECT, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
effect* peffect = *(effect**) lua_touserdata(L, 2);
lua_pushboolean(L, !pcard->is_affect_by_effect(peffect));
return 1;
}
int32 scriptlib::card_is_can_be_effect_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
effect* peffect = pduel->game_field->core.reason_effect;
if(lua_gettop(L) > 1) {
check_param(L, PARAM_TYPE_EFFECT, 2);
peffect = *(effect**) lua_touserdata(L, 2);
}
lua_pushboolean(L, pcard->is_capable_be_effect_target(peffect, pduel->game_field->core.reason_player));
return 1;
}
int32 scriptlib::card_is_can_be_battle_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* pcard = *(card**) lua_touserdata(L, 1);
card* bcard = *(card**) lua_touserdata(L, 2);
lua_pushboolean(L, pcard->is_capable_be_battle_target(bcard));
return 1;
}
int32 scriptlib::card_add_trap_monster_attribute(lua_State *L) {
check_param_count(L, 7);
check_param(L, PARAM_TYPE_CARD, 1);
int32 extra_type = lua_tointeger(L, 2);
int32 attribute = lua_tointeger(L, 3);
int32 race = lua_tointeger(L, 4);
int32 level = lua_tointeger(L, 5);
int32 atk = lua_tointeger(L, 6);
int32 def = lua_tointeger(L, 7);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
//type
effect* peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_ADD_TYPE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = TYPE_MONSTER | TYPE_TRAPMONSTER | extra_type;
pcard->add_effect(peffect);
//attribute
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_ADD_ATTRIBUTE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = attribute;
pcard->add_effect(peffect);
//race
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_ADD_RACE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = race;
pcard->add_effect(peffect);
//level
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_CHANGE_LEVEL;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = level;
pcard->add_effect(peffect);
//atk
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_SET_BASE_ATTACK;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = atk;
pcard->add_effect(peffect);
//def
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_SET_BASE_DEFENCE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x47e0000;
peffect->value = def;
pcard->add_effect(peffect);
pcard->set_status(STATUS_NO_LEVEL, FALSE);
return 0;
}
int32 scriptlib::card_trap_monster_block(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
//extra block
effect* peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_FIELD;
peffect->range = LOCATION_MZONE;
peffect->code = EFFECT_USE_EXTRA_SZONE;
peffect->flag = EFFECT_FLAG_CANNOT_DISABLE;
peffect->reset_flag = RESET_EVENT + 0x5fe0000;
peffect->value = 1 + (0x10000 << pcard->previous.sequence);
pcard->add_effect(peffect);
return 0;
}
int32 scriptlib::card_cancel_to_grave(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
bool cancel = true;
if(lua_gettop(L) > 1)
cancel = lua_toboolean(L, 2) != 0;
if(cancel)
pcard->set_status(STATUS_LEAVE_CONFIRMED, FALSE);
else {
pcard->pduel->game_field->core.leave_confirmed.insert(pcard);
pcard->set_status(STATUS_LEAVE_CONFIRMED, TRUE);
}
return 0;
}
int32 scriptlib::card_get_tribute_requirement(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 rcount = pcard->get_summon_tribute_count();
lua_pushinteger(L, rcount & 0xffff);
lua_pushinteger(L, (rcount >> 16) & 0xffff);
return 2;
}
int32 scriptlib::card_get_battle_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
if(pduel->game_field->core.attacker == pcard)
interpreter::card2value(L, pduel->game_field->core.attack_target);
else if(pduel->game_field->core.attack_target == pcard)
interpreter::card2value(L, pduel->game_field->core.attacker);
else lua_pushnil(L);
return 1;
}
int32 scriptlib::card_get_attackable_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
field::card_vector targets;
pduel->game_field->get_attack_target(pcard, &targets);
group* newgroup = pduel->new_group();
newgroup->container.insert(targets.begin(), targets.end());
interpreter::group2value(L, newgroup);
lua_pushboolean(L, pcard->operation_param);
return 2;
}
int32 scriptlib::card_set_hint(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
uint32 type = lua_tointeger(L, 2);
uint32 value = lua_tointeger(L, 3);
if(type >= CHINT_DESC_ADD)
return 0;
pduel->write_buffer8(MSG_CARD_HINT);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer8(type);
pduel->write_buffer32(value);
return 0;
}
int32 scriptlib::card_reverse_in_deck(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->current.location != LOCATION_DECK)
return 0;
pcard->current.position = POS_FACEUP_DEFENCE;
duel* pduel = pcard->pduel;
if(pcard->current.sequence == pduel->game_field->player[pcard->current.controler].list_main.size() - 1) {
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(0);
pduel->write_buffer32(pcard->data.code | 0x80000000);
}
return 0;
}
int32 scriptlib::card_set_unique_onfield(lua_State *L) {
check_param_count(L, 4);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
pcard->unique_pos[0] = lua_tointeger(L, 2);
pcard->unique_pos[1] = lua_tointeger(L, 3);
pcard->unique_code = lua_tointeger(L, 4);
effect* peffect = pcard->pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = EFFECT_UNIQUE_CHECK;
peffect->flag = EFFECT_FLAG_COPY_INHERIT;
pcard->add_effect(peffect);
pcard->unique_effect = peffect;
if(pcard->current.location & LOCATION_ONFIELD)
pcard->pduel->game_field->add_unique_card(pcard);
return 0;
}
int32 scriptlib::card_check_unique_onfield(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 check_player = lua_tointeger(L, 2);
lua_pushboolean(L, pcard->pduel->game_field->check_unique_onfield(pcard, check_player) ? 0 : 1);
return 1;
}
int32 scriptlib::card_reset_negate_effect(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
int32 count = lua_gettop(L) - 1;
for(int32 i = 0; i < count; ++i)
pcard->reset(lua_tointeger(L, i + 2), RESET_CARD);
return 0;
}
int32 scriptlib::card_assume_prop(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
pcard->assume_type = lua_tointeger(L, 2);
pcard->assume_value = lua_tointeger(L, 3);
pcard->pduel->assumes.insert(pcard);
return 0;
}
int32 scriptlib::card_set_spsummon_once(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
if(pcard->status & STATUS_COPYING_EFFECT)
return 0;
pcard->spsummon_code = lua_tointeger(L, 2);
pcard->pduel->game_field->core.global_flag |= GLOBALFLAG_SPSUMMON_ONCE;
return 0;
}
/*
* libdebug.cpp
*
* Created on: 2012-2-8
* Author: Argon
*/
#include <string.h>
#include "scriptlib.h"
#include "duel.h"
#include "field.h"
#include "card.h"
#include "effect.h"
#include "ocgapi.h"
int32 scriptlib::debug_message(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
lua_getglobal(L, "tostring");
lua_pushvalue(L, -2);
lua_pcall(L, 1, 1, 0);
sprintf(pduel->strbuffer, "%s", lua_tostring(L, -1));
handle_message(pduel, 2);
return 0;
}
int32 scriptlib::debug_add_card(lua_State *L) {
check_param_count(L, 6);
duel* pduel = interpreter::get_duel_info(L);
int32 code = lua_tointeger(L, 1);
int32 owner = lua_tointeger(L, 2);
int32 playerid = lua_tointeger(L, 3);
int32 location = lua_tointeger(L, 4);
int32 sequence = lua_tointeger(L, 5);
int32 position = lua_tointeger(L, 6);
int32 proc = lua_toboolean(L, 7);
if(owner != 0 && owner != 1)
return 0;
if(playerid != 0 && playerid != 1)
return 0;
if(pduel->game_field->is_location_useable(playerid, location, sequence)) {
card* pcard = pduel->new_card(code);
pcard->owner = owner;
pduel->game_field->add_card(playerid, pcard, location, sequence);
pcard->current.position = position;
if(!(location & LOCATION_ONFIELD) || (position & POS_FACEUP)) {
pcard->enable_field_effect(TRUE);
pduel->game_field->adjust_instant();
}
if((pcard->data.type & TYPE_PENDULUM) && (location == LOCATION_EXTRA) && (position & POS_FACEUP))
pduel->game_field->player[playerid].extra_p_count += 1;
if(proc)
pcard->set_status(STATUS_PROC_COMPLETE, TRUE);
interpreter::card2value(L, pcard);
return 1;
} else if(location == LOCATION_MZONE) {
card* pcard = pduel->new_card(code);
pcard->owner = owner;
card* fcard = pduel->game_field->get_field_card(playerid, location, sequence);
fcard->xyz_materials.push_back(pcard);
pcard->overlay_target = fcard;
pcard->current.controler = PLAYER_NONE;
pcard->current.location = LOCATION_OVERLAY;
pcard->current.sequence = fcard->xyz_materials.size() - 1;
interpreter::card2value(L, pcard);
return 1;
}
return 0;
}
int32 scriptlib::debug_set_player_info(lua_State *L) {
check_param_count(L, 4);
duel* pduel = interpreter::get_duel_info(L);
uint32 playerid = lua_tointeger(L, 1);
uint32 lp = lua_tointeger(L, 2);
uint32 startcount = lua_tointeger(L, 3);
uint32 drawcount = lua_tointeger(L, 4);
if(playerid != 0 && playerid != 1)
return 0;
pduel->game_field->player[playerid].lp = lp;
pduel->game_field->player[playerid].start_count = startcount;
pduel->game_field->player[playerid].draw_count = drawcount;
return 0;
}
int32 scriptlib::debug_pre_equip(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* equip_card = *(card**) lua_touserdata(L, 1);
card* target = *(card**) lua_touserdata(L, 2);
if((equip_card->current.location != LOCATION_SZONE)
|| (target->current.location != LOCATION_MZONE)
|| (target->current.position & POS_FACEDOWN))
lua_pushboolean(L, 0);
else {
equip_card->equip(target, FALSE);
equip_card->effect_target_cards.insert(target);
target->effect_target_owner.insert(equip_card);
lua_pushboolean(L, 1);
}
return 1;
}
int32 scriptlib::debug_pre_set_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
check_param(L, PARAM_TYPE_CARD, 2);
card* t_card = *(card**) lua_touserdata(L, 1);
card* target = *(card**) lua_touserdata(L, 2);
t_card->add_card_target(target);
return 0;
}
int32 scriptlib::debug_pre_add_counter(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
uint32 ctype = lua_tointeger(L, 2);
uint32 ccount = lua_tointeger(L, 3);
pcard->counters[ctype] += ccount;
return 0;
}
int32 scriptlib::debug_reload_field_begin(lua_State *L) {
check_param_count(L, 1);
duel* pduel = interpreter::get_duel_info(L);
uint32 flag = lua_tointeger(L, 1);
pduel->clear();
pduel->game_field->core.duel_options = flag;
return 0;
}
int32 scriptlib::debug_reload_field_end(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
pduel->game_field->core.shuffle_hand_check[0] = FALSE;
pduel->game_field->core.shuffle_hand_check[1] = FALSE;
pduel->game_field->core.shuffle_deck_check[0] = FALSE;
pduel->game_field->core.shuffle_deck_check[1] = FALSE;
pduel->game_field->reload_field_info();
return 0;
}
int32 scriptlib::debug_set_ai_name(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_STRING, 1);
duel* pduel = interpreter::get_duel_info(L);
pduel->write_buffer8(MSG_AI_NAME);
const char* pstr = lua_tostring(L, 1);
int len = strlen(pstr);
if(len > 100)
len = 100;
pduel->write_buffer16(len);
memcpy(pduel->bufferp, pstr, len);
pduel->bufferp += len;
pduel->bufferlen += len;
pduel->write_buffer8(0);
return 0;
}
int32 scriptlib::debug_show_hint(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_STRING, 1);
duel* pduel = interpreter::get_duel_info(L);
pduel->write_buffer8(MSG_SHOW_HINT);
const char* pstr = lua_tostring(L, 1);
int len = strlen(pstr);
if(len > 1024)
len = 1024;
pduel->write_buffer16(len);
memcpy(pduel->bufferp, pstr, len);
pduel->bufferp += len;
pduel->bufferlen += len;
pduel->write_buffer8(0);
return 0;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* libeffect.cpp
*
* Created on: 2010-7-20
* Author: Argon
*/
#include "scriptlib.h"
#include "duel.h"
#include "field.h"
#include "card.h"
#include "effect.h"
int32 scriptlib::effect_new(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_CARD, 1);
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
effect* peffect = pduel->new_effect();
peffect->effect_owner = pduel->game_field->core.reason_player;
peffect->owner = pcard;
interpreter::effect2value(L, peffect);
return 1;
}
int32 scriptlib::effect_newex(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
effect* peffect = pduel->new_effect();
peffect->effect_owner = 0;
peffect->owner = pduel->game_field->temp_card;
interpreter::effect2value(L, peffect);
return 1;
}
int32 scriptlib::effect_clone(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
duel* pduel = peffect->pduel;
effect* ceffect = pduel->new_effect();
int32 ref = ceffect->ref_handle;
*ceffect = *peffect;
ceffect->ref_handle = ref;
ceffect->handler = 0;
ceffect->effect_owner = peffect->effect_owner;
if(peffect->condition) {
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->condition);
ceffect->condition = luaL_ref(L, LUA_REGISTRYINDEX);
}
if(peffect->cost) {
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->cost);
ceffect->cost = luaL_ref(L, LUA_REGISTRYINDEX);
}
if(peffect->target) {
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->target);
ceffect->target = luaL_ref(L, LUA_REGISTRYINDEX);
}
if(peffect->operation) {
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->operation);
ceffect->operation = luaL_ref(L, LUA_REGISTRYINDEX);
}
if(peffect->value && (peffect->flag & EFFECT_FLAG_FUNC_VALUE)) {
lua_rawgeti(L, LUA_REGISTRYINDEX, peffect->value);
ceffect->value = luaL_ref(L, LUA_REGISTRYINDEX);
}
interpreter::effect2value(L, ceffect);
return 1;
}
int32 scriptlib::effect_reset(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->owner == 0)
return 0;
if(peffect->flag & EFFECT_FLAG_FIELD_ONLY)
peffect->pduel->game_field->remove_effect(peffect);
else
peffect->handler->remove_effect(peffect);
return 0;
}
int32 scriptlib::effect_get_field_id(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushinteger(L, peffect->id);
return 1;
}
int32 scriptlib::effect_set_description(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
peffect->description = v;
return 0;
}
int32 scriptlib::effect_set_code(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
peffect->code = v;
return 0;
}
int32 scriptlib::effect_set_range(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
peffect->range = v;
return 0;
}
int32 scriptlib::effect_set_target_range(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 s = lua_tointeger(L, 2);
int32 o = lua_tointeger(L, 3);
peffect->s_range = s;
peffect->o_range = o;
peffect->flag &= ~EFFECT_FLAG_ABSOLUTE_TARGET;
return 0;
}
int32 scriptlib::effect_set_absolute_range(lua_State *L) {
check_param_count(L, 4);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 playerid = lua_tointeger(L, 2);
int32 s = lua_tointeger(L, 3);
int32 o = lua_tointeger(L, 4);
if(playerid == 0) {
peffect->s_range = s;
peffect->o_range = o;
} else {
peffect->s_range = o;
peffect->o_range = s;
}
peffect->flag |= EFFECT_FLAG_ABSOLUTE_TARGET;
return 0;
}
int32 scriptlib::effect_set_count_limit(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
uint32 code = 0;
if(lua_gettop(L) >= 3)
code = lua_tointeger(L, 3);
if(v == 0)
v = 1;
peffect->flag |= EFFECT_FLAG_COUNT_LIMIT;
peffect->reset_count |= ((v << 12) & 0xf000) | ((v << 8) & 0xf00);
peffect->count_code = code;
return 0;
}
int32 scriptlib::effect_set_reset(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
int32 c = lua_tointeger(L, 3);
if(c == 0)
c = 1;
if(v & (RESET_PHASE) && !(v & (RESET_SELF_TURN | RESET_OPPO_TURN)))
v |= (RESET_SELF_TURN | RESET_OPPO_TURN);
peffect->reset_flag = v;
peffect->reset_count = (peffect->reset_count & 0xff00) | (c & 0xff);
return 0;
}
int32 scriptlib::effect_set_type(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
if (v & 0x0ff0)
v |= EFFECT_TYPE_ACTIONS;
else
v &= ~EFFECT_TYPE_ACTIONS;
if(v & 0x550)
v |= EFFECT_TYPE_FIELD;
if(v & EFFECT_TYPE_ACTIVATE)
peffect->range = LOCATION_SZONE + LOCATION_FZONE + LOCATION_HAND;
if(v & EFFECT_TYPE_FLIP) {
peffect->code = EVENT_FLIP;
if(!(v & EFFECT_TYPE_TRIGGER_O))
v |= EFFECT_TYPE_TRIGGER_F;
}
peffect->type = v;
return 0;
}
int32 scriptlib::effect_set_property(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 v = lua_tounsigned(L, 2);
peffect->flag = (peffect->flag & 0x4f) | (v & ~0x4f);
return 0;
}
int32 scriptlib::effect_set_label(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
peffect->label = v;
return 0;
}
int32 scriptlib::effect_set_label_object(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(lua_isnil(L, 2)) {
peffect->label_object = 0;
return 0;
}
if(!lua_isuserdata(L, 2))
luaL_error(L, "Parameter 2 should be \"Card\" or \"Effect\" or \"Group\".");
void* p = *(void**)lua_touserdata(L, 2);
peffect->label_object = p;
return 0;
}
int32 scriptlib::effect_set_category(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 v = lua_tointeger(L, 2);
peffect->category = v;
return 0;
}
int32 scriptlib::effect_set_hint_timing(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 vs = lua_tointeger(L, 2);
int32 vo = vs;
if(lua_gettop(L) >= 3)
vo = lua_tointeger(L, 3);
peffect->hint_timing[0] = vs;
peffect->hint_timing[1] = vo;
return 0;
}
int32 scriptlib::effect_set_condition(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->condition)
luaL_unref(L, LUA_REGISTRYINDEX, peffect->condition);
peffect->condition = interpreter::get_function_handle(L, 2);
return 0;
}
int32 scriptlib::effect_set_target(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->target)
luaL_unref(L, LUA_REGISTRYINDEX, peffect->target);
peffect->target = interpreter::get_function_handle(L, 2);
return 0;
}
int32 scriptlib::effect_set_cost(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->cost)
luaL_unref(L, LUA_REGISTRYINDEX, peffect->cost);
peffect->cost = interpreter::get_function_handle(L, 2);
return 0;
}
int32 scriptlib::effect_set_value(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->value && (peffect->flag & EFFECT_FLAG_FUNC_VALUE))
luaL_unref(L, LUA_REGISTRYINDEX, peffect->value);
if (lua_isfunction(L, 2)) {
peffect->value = interpreter::get_function_handle(L, 2);
peffect->flag |= EFFECT_FLAG_FUNC_VALUE;
} else {
peffect->flag &= ~EFFECT_FLAG_FUNC_VALUE;
if(lua_isboolean(L, 2))
peffect->value = lua_toboolean(L, 2);
else
peffect->value = lua_tointeger(L, 2);
}
return 0;
}
int32 scriptlib::effect_set_operation(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->operation)
luaL_unref(L, LUA_REGISTRYINDEX, peffect->operation);
if(!lua_isnil(L, 2)) {
check_param(L, PARAM_TYPE_FUNCTION, 2);
peffect->operation = interpreter::get_function_handle(L, 2);
} else
peffect->operation = 0;
return 0;
}
int32 scriptlib::effect_set_owner_player(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
int32 p = lua_tointeger(L, 2);
if(p != 0 && p != 1)
return 0;
peffect->effect_owner = p;
return 0;
}
int32 scriptlib::effect_get_description(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushinteger(L, peffect->description);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_code(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushinteger(L, peffect->code);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_type(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushinteger(L, peffect->type);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_property(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushunsigned(L, peffect->flag);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_label(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushinteger(L, peffect->label);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_label_object(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (!peffect->label_object) {
lua_pushnil(L);
return 1;
}
int32 type = *(int32*)peffect->label_object;
if(type == 1)
interpreter::card2value(L, (card*)peffect->label_object);
else if(type == 2)
interpreter::group2value(L, (group*)peffect->label_object);
else if(type == 3)
interpreter::effect2value(L, (effect*)peffect->label_object);
else lua_pushnil(L);
return 1;
}
int32 scriptlib::effect_get_category(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if (peffect) {
lua_pushinteger(L, peffect->category);
return 1;
}
return 0;
}
int32 scriptlib::effect_get_owner(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::card2value(L, peffect->owner);
return 1;
}
int32 scriptlib::effect_get_handler(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::card2value(L, peffect->handler);
return 1;
}
int32 scriptlib::effect_get_owner_player(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushinteger(L, peffect->get_owner_player());
return 1;
}
int32 scriptlib::effect_get_handler_player(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushinteger(L, peffect->get_handler_player());
return 1;
}
int32 scriptlib::effect_get_condition(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::function2value(L, peffect->condition);
return 1;
}
int32 scriptlib::effect_get_target(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::function2value(L, peffect->target);
return 1;
}
int32 scriptlib::effect_get_cost(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::function2value(L, peffect->cost);
return 1;
}
int32 scriptlib::effect_get_value(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
if(peffect->flag & EFFECT_FLAG_FUNC_VALUE)
interpreter::function2value(L, peffect->value);
else
lua_pushinteger(L, (int32)peffect->value);
return 1;
}
int32 scriptlib::effect_get_operation(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
interpreter::function2value(L, peffect->operation);
return 1;
}
int32 scriptlib::effect_get_active_type(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 atype;
if(peffect->type & 0x7f0) {
if(peffect->active_type)
atype = peffect->active_type;
else if((peffect->type & EFFECT_TYPE_ACTIVATE) && (peffect->handler->data.type & TYPE_PENDULUM))
atype = TYPE_PENDULUM + TYPE_SPELL;
else
atype = peffect->handler->get_type();
} else
atype = peffect->owner->get_type();
lua_pushinteger(L, atype);
return 1;
}
int32 scriptlib::effect_is_active_type(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 tpe = lua_tointeger(L, 2);
uint32 atype;
if(peffect->type & 0x7f0) {
if(peffect->active_type)
atype = peffect->active_type;
else if((peffect->type & EFFECT_TYPE_ACTIVATE) && (peffect->handler->data.type & TYPE_PENDULUM))
atype = TYPE_PENDULUM + TYPE_SPELL;
else
atype = peffect->handler->get_type();
} else
atype = peffect->owner->get_type();
lua_pushboolean(L, atype & tpe);
return 1;
}
int32 scriptlib::effect_is_has_property(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 tflag = lua_tounsigned(L, 2);
if (peffect && (peffect->flag & tflag))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::effect_is_has_category(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 tcate = lua_tointeger(L, 2);
if (peffect && (peffect->category & tcate))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::effect_is_has_type(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
uint32 ttype = lua_tointeger(L, 2);
if (peffect && (peffect->type & ttype))
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::effect_is_activatable(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_EFFECT, 1);
uint32 playerid = lua_tointeger(L, 2);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushboolean(L, peffect->is_activateable(playerid, peffect->pduel->game_field->nil_event));
return 1;
}
int32 scriptlib::effect_is_activated(lua_State * L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushboolean(L, (peffect->status & EFFECT_STATUS_ACTIVATED));
return 1;
}
int32 scriptlib::effect_get_activate_location(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_EFFECT, 1);
effect* peffect = *(effect**) lua_touserdata(L, 1);
lua_pushinteger(L, peffect->s_range);
return 1;
}
\ No newline at end of file
/*
* libgroup.cpp
*
* Created on: 2010-5-6
* Author: Argon
*/
#include "scriptlib.h"
#include "group.h"
#include "card.h"
#include "effect.h"
#include "duel.h"
int32 scriptlib::group_new(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
group* pgroup = pduel->new_group();
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::group_clone(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
group* newgroup = pduel->new_group(pgroup->container);
interpreter::group2value(L, newgroup);
return 1;
}
int32 scriptlib::group_from_cards(lua_State *L) {
duel* pduel = interpreter::get_duel_info(L);
group* pgroup = pduel->new_group();
card* pcard;
void* p;
for(int32 i = 0; i < lua_gettop(L); ++i) {
p = lua_touserdata(L, i + 1);
if(p) {
pcard = *(card**)p;
pgroup->container.insert(pcard);
}
}
interpreter::group2value(L, pgroup);
return 1;
}
int32 scriptlib::group_delete(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
duel* pduel = interpreter::get_duel_info(L);
group* pgroup = *(group**) lua_touserdata(L, 1);
if(pgroup->is_readonly != 2)
return 0;
pgroup->is_readonly = 0;
pduel->sgroups.insert(pgroup);
return 0;
}
int32 scriptlib::group_keep_alive(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
duel* pduel = interpreter::get_duel_info(L);
group* pgroup = *(group**) lua_touserdata(L, 1);
if(pgroup->is_readonly == 1)
return 0;
pgroup->is_readonly = 2;
pduel->sgroups.erase(pgroup);
return 0;
}
int32 scriptlib::group_clear(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
if (pgroup->is_readonly != 1) {
pgroup->container.clear();
}
return 0;
}
int32 scriptlib::group_add_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_CARD, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
card* pcard = *(card**) lua_touserdata(L, 2);
if (pgroup->is_readonly != 1) {
pgroup->container.insert(pcard);
}
return 0;
}
int32 scriptlib::group_remove_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_CARD, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
card* pcard = *(card**) lua_touserdata(L, 2);
if (pgroup->is_readonly != 1) {
pgroup->container.erase(pcard);
}
return 0;
}
int32 scriptlib::group_get_next(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
if(pgroup->it == pgroup->container.end())
lua_pushnil(L);
else {
++pgroup->it;
if (pgroup->it == pgroup->container.end())
lua_pushnil(L);
else
interpreter::card2value(L, (*(pgroup->it)));
}
return 1;
}
int32 scriptlib::group_get_first(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
if (pgroup->container.size()) {
pgroup->it = pgroup->container.begin();
interpreter::card2value(L, (*(pgroup->it)));
} else
lua_pushnil(L);
return 1;
}
int32 scriptlib::group_get_count(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
lua_pushinteger(L, pgroup->container.size());
return 1;
}
int32 scriptlib::group_for_each(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
duel* pduel = interpreter::get_duel_info(L);
group* pgroup = *(group**) lua_touserdata(L, 1);
int32 f = interpreter::get_function_handle(L, 2);
group::card_set::iterator it;
for (it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
pduel->lua->add_param((*it), PARAM_TYPE_CARD);
pduel->lua->call_function(f, 1, 0);
}
return 0;
}
int32 scriptlib::group_filter(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
card* pexception = 0;
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_CARD, 3);
pexception = *(card**) lua_touserdata(L, 3);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
group* new_group = pduel->new_group();
uint32 extraargs = lua_gettop(L) - 3;
group::card_set::iterator it;
for (it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
if((*it) != pexception && pduel->lua->check_matching(*it, 2, extraargs)) {
new_group->container.insert(*it);
}
}
interpreter::group2value(L, new_group);
return 1;
}
int32 scriptlib::group_filter_count(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
card* pexception = 0;
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_CARD, 3);
pexception = *(card**) lua_touserdata(L, 3);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 extraargs = lua_gettop(L) - 3;
uint32 count = 0;
group::card_set::iterator it;
for (it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
if((*it) != pexception && pduel->lua->check_matching(*it, 2, extraargs))
count++;
}
lua_pushinteger(L, count);
return 1;
}
int32 scriptlib::group_filter_select(lua_State *L) {
check_action_permission(L);
check_param_count(L, 6);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 3);
card* pexception = 0;
if(!lua_isnil(L, 6)) {
check_param(L, PARAM_TYPE_CARD, 6);
pexception = *(card**) lua_touserdata(L, 6);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
uint32 min = lua_tointeger(L, 4);
uint32 max = lua_tointeger(L, 5);
uint32 extraargs = lua_gettop(L) - 6;
pduel->game_field->core.select_cards.clear();
group::card_set::iterator it;
for (it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
if((*it) != pexception && pduel->lua->check_matching(*it, 3, extraargs))
pduel->game_field->core.select_cards.push_back(*it);
}
pduel->game_field->add_process(PROCESSOR_SELECT_CARD_S, 0, 0, 0, playerid, min + (max << 16));
return lua_yield(L, 0);
}
int32 scriptlib::group_select(lua_State *L) {
check_action_permission(L);
check_param_count(L, 5);
check_param(L, PARAM_TYPE_GROUP, 1);
card* pexception = 0;
if(!lua_isnil(L, 5)) {
check_param(L, PARAM_TYPE_CARD, 5);
pexception = *(card**) lua_touserdata(L, 5);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
uint32 min = lua_tointeger(L, 3);
uint32 max = lua_tointeger(L, 4);
pduel->game_field->core.select_cards.clear();
group::card_set::iterator it;
for (it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
if((*it) != pexception)
pduel->game_field->core.select_cards.push_back(*it);
}
pduel->game_field->add_process(PROCESSOR_SELECT_CARD_S, 0, 0, 0, playerid, min + (max << 16));
return lua_yield(L, 0);
}
int32 scriptlib::group_random_select(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
group* pgroup = *(group**) lua_touserdata(L, 1);
int32 playerid = lua_tointeger(L, 2);
int32 count = lua_tointeger(L, 3);
pgroup->pduel->game_field->add_process(PROCESSOR_RANDOM_SELECT_S, 0, 0, pgroup, playerid, count);
return lua_yield(L, 0);
}
int32 scriptlib::group_is_exists(lua_State *L) {
check_param_count(L, 4);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
card* pcard = 0;
if(!lua_isnil(L, 4)) {
check_param(L, PARAM_TYPE_CARD, 4);
pcard = *(card**) lua_touserdata(L, 4);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 count = lua_tointeger(L, 3);
uint32 extraargs = lua_gettop(L) - 4;
uint32 fcount = 0;
uint32 result = FALSE;
for (auto it = pgroup->container.begin(); it != pgroup->container.end(); ++it) {
if((*it) != pcard && pduel->lua->check_matching(*it, 2, extraargs)) {
fcount++;
if(fcount >= count) {
result = TRUE;
break;
}
}
}
lua_pushboolean(L, result);
return 1;
}
int32 scriptlib::group_check_with_sum_equal(lua_State *L) {
check_param_count(L, 5);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 acc = lua_tointeger(L, 3);
int32 min = lua_tointeger(L, 4);
int32 max = lua_tointeger(L, 5);
if(min <= 0)
min = 1;
if(max < min)
max = min;
int32 extraargs = lua_gettop(L) - 5;
field::card_vector cv;
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
(*cit)->operation_param = pduel->lua->get_operation_value(*cit, 2, extraargs);
cv.push_back(*cit);
}
lua_pushboolean(L, pduel->game_field->check_with_sum_limit(&cv, acc, 0, 1, min, max));
return 1;
}
int32 scriptlib::group_select_with_sum_equal(lua_State *L) {
check_action_permission(L);
check_param_count(L, 6);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 3);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
int32 acc = lua_tointeger(L, 4);
int32 min = lua_tointeger(L, 5);
int32 max = lua_tointeger(L, 6);
if(min <= 0)
min = 1;
if(max < min)
max = min;
int32 extraargs = lua_gettop(L) - 6;
pduel->game_field->core.select_cards.clear();
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
(*cit)->operation_param = pduel->lua->get_operation_value(*cit, 3, extraargs);
pduel->game_field->core.select_cards.push_back(*cit);
}
if(!pduel->game_field->check_with_sum_limit(&pduel->game_field->core.select_cards, acc, 0, 1, min, max))
return 0;
pduel->game_field->add_process(PROCESSOR_SELECT_SUM_S, 0, 0, 0, acc, playerid + (min << 16) + (max << 24));
return lua_yield(L, 0);
}
int32 scriptlib::group_check_with_sum_greater(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 acc = lua_tointeger(L, 3);
int32 extraargs = lua_gettop(L) - 3;
int32 sum = 0, op, op1, op2;
group::card_set::iterator cit;
for(cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
op = pduel->lua->get_operation_value(*cit, 2, extraargs);
op1 = op & 0xffff;
op2 = op >> 16;
sum += op1 > op2 ? op1 : op2;
}
if(sum >= acc)
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::group_select_with_sum_greater(lua_State *L) {
check_action_permission(L);
check_param_count(L, 4);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 3);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 playerid = lua_tointeger(L, 2);
if(playerid != 0 && playerid != 1)
return 0;
int32 acc = lua_tointeger(L, 4);
int32 extraargs = lua_gettop(L) - 4;
field::card_set::iterator cit;
pduel->game_field->core.select_cards.clear();
int32 sum = 0, op, op1, op2;
for(cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit) {
op = pduel->lua->get_operation_value(*cit, 3, extraargs);
op1 = op & 0xffff;
op2 = op >> 16;
sum += op1 > op2 ? op1 : op2;
(*cit)->operation_param = op;
pduel->game_field->core.select_cards.push_back(*cit);
}
if(sum < acc)
return 0;
pduel->game_field->add_process(PROCESSOR_SELECT_SUM_S, 0, 0, 0, acc, playerid);
return lua_yield(L, 0);
}
int32 scriptlib::group_get_min_group(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
if(pgroup->container.size() == 0)
return 0;
group* newgroup = pduel->new_group();
int32 min, op;
int32 extraargs = lua_gettop(L) - 2;
field::card_set::iterator cit = pgroup->container.begin();
min = pduel->lua->get_operation_value(*cit, 2, extraargs);
newgroup->container.insert(*cit);
++cit;
for(; cit != pgroup->container.end(); ++cit) {
op = pduel->lua->get_operation_value(*cit, 2, extraargs);
if(op == min)
newgroup->container.insert(*cit);
else if(op < min) {
newgroup->container.clear();
newgroup->container.insert(*cit);
min = op;
}
}
interpreter::group2value(L, newgroup);
lua_pushinteger(L, min);
return 2;
}
int32 scriptlib::group_get_max_group(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
if(pgroup->container.size() == 0)
return 0;
group* newgroup = pduel->new_group();
int32 max, op;
int32 extraargs = lua_gettop(L) - 2;
field::card_set::iterator cit = pgroup->container.begin();
max = pduel->lua->get_operation_value(*cit, 2, extraargs);
newgroup->container.insert(*cit);
++cit;
for(; cit != pgroup->container.end(); ++cit) {
op = pduel->lua->get_operation_value(*cit, 2, extraargs);
if(op == max)
newgroup->container.insert(*cit);
else if(op > max) {
newgroup->container.clear();
newgroup->container.insert(*cit);
max = op;
}
}
interpreter::group2value(L, newgroup);
lua_pushinteger(L, max);
return 2;
}
int32 scriptlib::group_get_sum(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 extraargs = lua_gettop(L) - 2;
int32 sum = 0;
field::card_set::iterator cit = pgroup->container.begin();
for(; cit != pgroup->container.end(); ++cit) {
sum += pduel->lua->get_operation_value(*cit, 2, extraargs);
}
lua_pushinteger(L, sum);
return 1;
}
int32 scriptlib::group_get_class_count(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
int32 extraargs = lua_gettop(L) - 2;
std::set<uint32> er;
field::card_set::iterator cit = pgroup->container.begin();
for(; cit != pgroup->container.end(); ++cit) {
er.insert(pduel->lua->get_operation_value(*cit, 2, extraargs));
}
lua_pushinteger(L, er.size());
return 1;
}
int32 scriptlib::group_remove(lua_State *L) {
check_param_count(L, 3);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
card* pexception = 0;
if(!lua_isnil(L, 3)) {
check_param(L, PARAM_TYPE_CARD, 3);
pexception = *(card**) lua_touserdata(L, 3);
}
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 extraargs = lua_gettop(L) - 3;
if(pgroup->is_readonly == 1)
return 0;
group::card_set::iterator cit, rm;
for (cit = pgroup->container.begin(); cit != pgroup->container.end();) {
rm = cit++;
if((*rm) != pexception && pduel->lua->check_matching(*rm, 2, extraargs)) {
pgroup->container.erase(rm);
}
}
return 0;
}
int32 scriptlib::group_merge(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_GROUP, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
group* mgroup = *(group**) lua_touserdata(L, 2);
if(pgroup->is_readonly == 1)
return 0;
pgroup->container.insert(mgroup->container.begin(), mgroup->container.end());
return 0;
}
int32 scriptlib::group_sub(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_GROUP, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
group* sgroup = *(group**) lua_touserdata(L, 2);
if(pgroup->is_readonly == 1)
return 0;
group::card_set::iterator cit;
for (cit = sgroup->container.begin(); cit != sgroup->container.end(); ++cit) {
pgroup->container.erase(*cit);
}
return 0;
}
int32 scriptlib::group_equal(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_GROUP, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
group* sgroup = *(group**) lua_touserdata(L, 2);
if(pgroup->container.size() != sgroup->container.size()) {
lua_pushboolean(L, 0);
return 1;
}
auto pit = pgroup->container.begin();
auto sit = sgroup->container.begin();
for (; pit != pgroup->container.end(); ++pit, ++sit) {
if((*pit) != (*sit)) {
lua_pushboolean(L, 0);
return 1;
}
}
lua_pushboolean(L, 1);
return 1;
}
int32 scriptlib::group_is_contains(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_CARD, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
card* pcard = *(card**) lua_touserdata(L, 2);
if(pgroup->container.find(pcard) != pgroup->container.end())
lua_pushboolean(L, 1);
else
lua_pushboolean(L, 0);
return 1;
}
int32 scriptlib::group_search_card(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_GROUP, 1);
check_param(L, PARAM_TYPE_FUNCTION, 2);
group* pgroup = *(group**) lua_touserdata(L, 1);
duel* pduel = pgroup->pduel;
uint32 extraargs = lua_gettop(L) - 2;
field::card_set::iterator cit;
for(cit = pgroup->container.begin(); cit != pgroup->container.end(); ++cit)
if(pduel->lua->check_matching(*cit, 2, extraargs)) {
interpreter::card2value(L, *cit);
return 1;
}
return 0;
}
/*
* mem.cpp
*
* Created on: 2011-9-8
* Author: argon
*/
//#define USE_TCMALLOC
#ifdef USE_TCMALLOC
#define PERFTOOLS_DLL_DECL
#include <tcmalloc.h>
void* operator new(size_t size) {
return tc_malloc(size);
}
void* operator new[](size_t size) {
return tc_malloc(size);
}
void* operator new(size_t size, const std::nothrow_t& nt) {
return tc_malloc(size);
}
void* operator new[](size_t size, const std::nothrow_t& nt) {
return tc_malloc(size);
}
void operator delete(void* p) {
return tc_free(p);
}
void operator delete[](void* p) {
return tc_free(p);
}
void operator delete(void* p, const std::nothrow_t& nt) {
return tc_free(p);
}
void operator delete[](void* p, const std::nothrow_t& nt) {
return tc_free(p);
}
#endif //USE_TCMALLOC
/*
* mtrandom.h
*
* Created on: 2009-10-18
* Author: Argon.Sun
*/
#ifndef MTRANDOM_H_
#define MTRANDOM_H_
//Mersenne Twister
class mtrandom {
public:
mtrandom() :
left(1) {
init();
}
explicit mtrandom(unsigned int seed) :
left(1) {
init(seed);
}
mtrandom(unsigned int* init_key, int key_length) :
left(1) {
int i = 1, j = 0;
int k = N > key_length ? N : key_length;
init();
for (; k; --k) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30))
* 1664525UL)) + init_key[j] + j; // non linear
state[i] &= 4294967295UL;
++i;
++j;
if (i >= N) {
state[0] = state[N - 1];
i = 1;
}
if (j >= key_length)
j = 0;
}
for (k = N - 1; k; --k) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30))
* 1566083941UL)) - i;
state[i] &= 4294967295UL;
++i;
if (i >= N) {
state[0] = state[N - 1];
i = 1;
}
}
state[0] = 2147483648UL;
}
void reset(unsigned int rs) {
init(rs);
next_state();
}
unsigned int rand() {
unsigned int y;
if (0 == --left)
next_state();
y = *next++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
double real() {
return (double) rand() / 0xffffffffUL;
}
double res53() {
unsigned int a = rand() >> 5, b = rand() >> 6;
return (a * 67108864.0 + b) / 9007199254740992.0;
}
void init(unsigned int seed = 19650218UL) {
state[0] = seed & 4294967295UL;
for (int j = 1; j < N; ++j) {
state[j] = (1812433253UL * (state[j - 1] ^ (state[j - 1] >> 30))
+ j);
state[j] &= 4294967295UL; // for >32 bit machines
}
}
private:
void next_state() {
unsigned int* p = state;
int i;
for (i = N - M + 1; --i; ++p)
*p = (p[M] ^ twist(p[0], p[1]));
for (i = M; --i; ++p)
*p = (p[M - N] ^ twist(p[0], p[1]));
*p = p[M - N] ^ twist(p[0], state[0]);
left = N;
next = state;
}
unsigned int mixbits(unsigned int u, unsigned int v) const {
return (u & 2147483648UL) | (v & 2147483647UL);
}
unsigned int twist(unsigned int u, unsigned int v) const {
return ((mixbits(u, v) >> 1) ^ (v & 1UL ? 2567483615UL : 0UL));
}
static const int N = 624, M = 397;
unsigned int state[N];
unsigned int left;
unsigned int* next;
};
#endif /* MTRANDOM_H_ */
/*
* interface.cpp
*
* Created on: 2010-5-2
* Author: Argon
*/
#include <stdio.h>
#include <string.h>
#include "ocgapi.h"
#include "duel.h"
#include "card.h"
#include "group.h"
#include "effect.h"
#include "field.h"
#include "interpreter.h"
#include <set>
script_reader sreader = default_script_reader;
card_reader creader = default_card_reader;
message_handler mhandler = default_message_handler;
byte buffer[0x10000];
std::set<duel*> duel_set;
extern "C" DECL_DLLEXPORT void set_script_reader(script_reader f) {
sreader = f;
}
extern "C" DECL_DLLEXPORT void set_card_reader(card_reader f) {
creader = f;
}
extern "C" DECL_DLLEXPORT void set_message_handler(message_handler f) {
mhandler = f;
}
byte* read_script(const char* script_name, int* len) {
return sreader(script_name, len);
}
uint32 read_card(uint32 code, card_data* data) {
return creader(code, data);
}
uint32 handle_message(void* pduel, uint32 msg_type) {
return mhandler(pduel, msg_type);
}
byte* default_script_reader(const char* script_name, int* slen) {
FILE *fp;
fp = fopen(script_name, "rb");
if (!fp)
return 0;
fseek(fp, 0, SEEK_END);
uint32 len = ftell(fp);
if (len > 0x10000) {
fclose(fp);
return 0;
}
fseek(fp, 0, SEEK_SET);
fread(buffer, len, 1, fp);
fclose(fp);
*slen = len;
return buffer;
}
uint32 default_card_reader(uint32 code, card_data* data) {
return 0;
}
uint32 default_message_handler(void* pduel, uint32 message_type) {
return 0;
}
extern "C" DECL_DLLEXPORT ptr create_duel(uint32 seed) {
duel* pduel = new duel();
duel_set.insert(pduel);
pduel->random.reset(seed);
return (ptr)pduel;
}
extern "C" DECL_DLLEXPORT void start_duel(ptr pduel, int options) {
duel* pd = (duel*)pduel;
pd->game_field->core.duel_options |= options;
pd->game_field->core.shuffle_hand_check[0] = FALSE;
pd->game_field->core.shuffle_hand_check[1] = FALSE;
pd->game_field->core.shuffle_deck_check[0] = FALSE;
pd->game_field->core.shuffle_deck_check[1] = FALSE;
if(pd->game_field->player[0].start_count > 0)
pd->game_field->draw(0, REASON_RULE, PLAYER_NONE, 0, pd->game_field->player[0].start_count);
if(pd->game_field->player[1].start_count > 0)
pd->game_field->draw(0, REASON_RULE, PLAYER_NONE, 1, pd->game_field->player[1].start_count);
if(options & DUEL_TAG_MODE) {
for(int i = 0; i < pd->game_field->player[0].start_count && pd->game_field->player[0].tag_list_main.size(); ++i) {
card* pcard = *pd->game_field->player[0].tag_list_main.rbegin();
pd->game_field->player[0].tag_list_main.pop_back();
pd->game_field->player[0].tag_list_hand.push_back(pcard);
pcard->current.controler = 0;
pcard->current.location = LOCATION_HAND;
pcard->current.sequence = pd->game_field->player[0].tag_list_hand.size() - 1;
}
for(int i = 0; i < pd->game_field->player[1].start_count && pd->game_field->player[1].tag_list_main.size(); ++i) {
card* pcard = *pd->game_field->player[1].tag_list_main.rbegin();
pd->game_field->player[1].tag_list_main.pop_back();
pd->game_field->player[1].tag_list_hand.push_back(pcard);
pcard->current.controler = 1;
pcard->current.location = LOCATION_HAND;
pcard->current.sequence = pd->game_field->player[1].tag_list_hand.size() - 1;
}
}
pd->game_field->add_process(PROCESSOR_TURN, 0, 0, 0, 0, 0);
}
extern "C" DECL_DLLEXPORT void end_duel(ptr pduel) {
duel* pd = (duel*)pduel;
if(duel_set.count(pd)) {
duel_set.erase(pd);
delete pd;
}
}
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount) {
duel* pd = (duel*)pduel;
if(lp > 0)
pd->game_field->player[playerid].lp = lp;
if(startcount >= 0)
pd->game_field->player[playerid].start_count = startcount;
if(drawcount >= 0)
pd->game_field->player[playerid].draw_count = drawcount;
}
extern "C" DECL_DLLEXPORT void get_log_message(ptr pduel, byte* buf) {
strcpy((char*)buf, ((duel*)pduel)->strbuffer);
}
extern "C" DECL_DLLEXPORT int32 get_message(ptr pduel, byte* buf) {
int32 len = ((duel*)pduel)->read_buffer(buf);
((duel*)pduel)->clear_buffer();
return len;
}
extern "C" DECL_DLLEXPORT int32 process(ptr pduel) {
duel* pd = (duel*)pduel;
int result = pd->game_field->process();
while((result & 0xffff) == 0 && (result & 0xf0000) == 0)
result = pd->game_field->process();
return result;
}
extern "C" DECL_DLLEXPORT void new_card(ptr pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position) {
duel* ptduel = (duel*)pduel;
if(ptduel->game_field->is_location_useable(playerid, location, sequence)) {
card* pcard = ptduel->new_card(code);
pcard->owner = owner;
ptduel->game_field->add_card(playerid, pcard, location, sequence);
pcard->current.position = position;
if(!(location & LOCATION_ONFIELD) || (position & POS_FACEUP)) {
pcard->enable_field_effect(TRUE);
ptduel->game_field->adjust_instant();
}
if(location & LOCATION_ONFIELD) {
if(location == LOCATION_MZONE)
pcard->set_status(STATUS_PROC_COMPLETE, TRUE);
}
}
}
extern "C" DECL_DLLEXPORT void new_tag_card(ptr pduel, uint32 code, uint8 owner, uint8 location) {
duel* ptduel = (duel*)pduel;
if(owner > 1 || !(location & 0x41))
return;
card* pcard = ptduel->new_card(code);
switch(location) {
case LOCATION_DECK:
ptduel->game_field->player[owner].tag_list_main.push_back(pcard);
pcard->owner = owner;
pcard->current.controler = owner;
pcard->current.location = LOCATION_DECK;
pcard->current.sequence = ptduel->game_field->player[owner].tag_list_main.size() - 1;
break;
case LOCATION_EXTRA:
ptduel->game_field->player[owner].tag_list_extra.push_back(pcard);
pcard->owner = owner;
pcard->current.controler = owner;
pcard->current.location = LOCATION_EXTRA;
pcard->current.sequence = ptduel->game_field->player[owner].tag_list_extra.size() - 1;
break;
}
}
extern "C" DECL_DLLEXPORT int32 query_card(ptr pduel, uint8 playerid, uint8 location, uint8 sequence, int32 query_flag, byte* buf, int32 use_cache) {
if(playerid != 0 && playerid != 1)
return 0;
duel* ptduel = (duel*)pduel;
card* pcard = 0;
location &= 0x7f;
if(location & LOCATION_ONFIELD)
pcard = ptduel->game_field->get_field_card(playerid, location, sequence);
else {
field::card_vector* lst = 0;
if(location == LOCATION_HAND )
lst = &ptduel->game_field->player[playerid].list_hand;
else if(location == LOCATION_GRAVE )
lst = &ptduel->game_field->player[playerid].list_grave;
else if(location == LOCATION_REMOVED )
lst = &ptduel->game_field->player[playerid].list_remove;
else if(location == LOCATION_EXTRA )
lst = &ptduel->game_field->player[playerid].list_extra;
else if(location == LOCATION_DECK )
lst = &ptduel->game_field->player[playerid].list_main;
if(!lst || sequence > lst->size())
pcard = 0;
else {
auto cit = lst->begin();
for(uint32 i = 0; i < sequence; ++i, ++cit);
pcard = *cit;
}
}
if(pcard)
return pcard->get_infos(buf, query_flag, use_cache);
else {
*((int32*)buf) = 4;
return 4;
}
}
extern "C" DECL_DLLEXPORT int32 query_field_count(ptr pduel, uint8 playerid, uint8 location) {
duel* ptduel = (duel*)pduel;
if(playerid != 0 && playerid != 1)
return 0;
if(location == LOCATION_HAND)
return ptduel->game_field->player[playerid].list_hand.size();
if(location == LOCATION_GRAVE)
return ptduel->game_field->player[playerid].list_grave.size();
if(location == LOCATION_REMOVED)
return ptduel->game_field->player[playerid].list_remove.size();
if(location == LOCATION_EXTRA)
return ptduel->game_field->player[playerid].list_extra.size();
if(location == LOCATION_DECK)
return ptduel->game_field->player[playerid].list_main.size();
if(location == LOCATION_MZONE) {
uint32 count = 0;
for(uint32 i = 0; i < 5; ++i)
if(ptduel->game_field->player[playerid].list_mzone[i]) count++;
return count;
}
if(location == LOCATION_SZONE) {
uint32 count = 0;
for(uint32 i = 0; i < 8; ++i)
if(ptduel->game_field->player[playerid].list_szone[i]) count++;
return count;
}
return 0;
}
extern "C" DECL_DLLEXPORT int32 query_field_card(ptr pduel, uint8 playerid, uint8 location, int32 query_flag, byte* buf, int32 use_cache) {
if(playerid != 0 && playerid != 1)
return 0;
duel* ptduel = (duel*)pduel;
card* pcard;
uint32 ct = 0, clen;
byte* p = buf;
if(location == LOCATION_MZONE) {
for(uint32 i = 0; i < 5; ++i) {
pcard = ptduel->game_field->player[playerid].list_mzone[i];
if(pcard) {
ct += clen = pcard->get_infos(p, query_flag, use_cache);
p += clen;
} else {
*((int32*)p) = 4;
ct += 4;
p += 4;
}
}
} else if(location == LOCATION_SZONE) {
for(uint32 i = 0; i < 8; ++i) {
pcard = ptduel->game_field->player[playerid].list_szone[i];
if(pcard) {
ct += clen = pcard->get_infos(p, query_flag, use_cache);
p += clen;
} else {
*((int32*)p) = 4;
ct += 4;
p += 4;
}
}
} else {
field::card_vector* lst;
field::card_vector::iterator cit;
if(location == LOCATION_HAND )
lst = &ptduel->game_field->player[playerid].list_hand;
else if(location == LOCATION_GRAVE )
lst = &ptduel->game_field->player[playerid].list_grave;
else if(location == LOCATION_REMOVED )
lst = &ptduel->game_field->player[playerid].list_remove;
else if(location == LOCATION_EXTRA )
lst = &ptduel->game_field->player[playerid].list_extra;
else if(location == LOCATION_DECK )
lst = &ptduel->game_field->player[playerid].list_main;
for(cit = lst->begin(); cit != lst->end(); ++cit) {
ct += clen = (*cit)->get_infos(p, query_flag, use_cache);
p += clen;
}
}
return ct;
}
extern "C" DECL_DLLEXPORT int32 query_field_info(ptr pduel, byte* buf) {
duel* ptduel = (duel*)pduel;
*buf++ = MSG_RELOAD_FIELD;
card* pcard;
for(int playerid = 0; playerid < 2; ++playerid) {
*((int*)(buf)) = ptduel->game_field->player[playerid].lp;
buf += 4;
for(uint32 i = 0; i < 5; ++i) {
pcard = ptduel->game_field->player[playerid].list_mzone[i];
if(pcard) {
*buf++ = 1;
*buf++ = pcard->current.position;
*buf++ = pcard->xyz_materials.size();
} else {
*buf++ = 0;
}
}
for(uint32 i = 0; i < 8; ++i) {
pcard = ptduel->game_field->player[playerid].list_szone[i];
if(pcard) {
*buf++ = 1;
*buf++ = pcard->current.position;
} else {
*buf++ = 0;
}
}
*buf++ = ptduel->game_field->player[playerid].list_main.size();
*buf++ = ptduel->game_field->player[playerid].list_hand.size();
*buf++ = ptduel->game_field->player[playerid].list_grave.size();
*buf++ = ptduel->game_field->player[playerid].list_remove.size();
*buf++ = ptduel->game_field->player[playerid].list_extra.size();
}
*buf++ = ptduel->game_field->core.current_chain.size();
for(auto chit = ptduel->game_field->core.current_chain.begin(); chit != ptduel->game_field->core.current_chain.end(); ++chit) {
effect* peffect = chit->triggering_effect;
*((int*)(buf)) = peffect->handler->data.code;
buf += 4;
*((int*)(buf)) = peffect->handler->get_info_location();
buf += 4;
*buf++ = chit->triggering_controler;
*buf++ = chit->triggering_location;
*buf++ = chit->triggering_sequence;
*((int*)(buf)) = peffect->description;
buf += 4;
}
return 0;
}
extern "C" DECL_DLLEXPORT void set_responsei(ptr pduel, int32 value) {
((duel*)pduel)->set_responsei(value);
}
extern "C" DECL_DLLEXPORT void set_responseb(ptr pduel, byte* buf) {
((duel*)pduel)->set_responseb(buf);
}
extern "C" DECL_DLLEXPORT int32 preload_script(ptr pduel, char* script, int32 len) {
return ((duel*)pduel)->lua->load_script(script);
}
/*
* interface.h
*
* Created on: 2010-4-28
* Author: Argon
*/
#ifndef OCGAPI_H_
#define OCGAPI_H_
#include "common.h"
#ifdef WIN32
#include <windows.h>
#define DECL_DLLEXPORT __declspec(dllexport)
#else
#define DECL_DLLEXPORT
#endif
class card;
struct card_data;
struct card_info;
class group;
class effect;
class interpreter;
typedef byte* (*script_reader)(const char*, int*);
typedef uint32 (*card_reader)(uint32, card_data*);
typedef uint32 (*message_handler)(void*, uint32);
extern "C" DECL_DLLEXPORT void set_script_reader(script_reader f);
extern "C" DECL_DLLEXPORT void set_card_reader(card_reader f);
extern "C" DECL_DLLEXPORT void set_message_handler(message_handler f);
byte* read_script(const char* script_name, int* len);
uint32 read_card(uint32 code, card_data* data);
uint32 handle_message(void* pduel, uint32 message_type);
extern "C" DECL_DLLEXPORT ptr create_duel(uint32 seed);
extern "C" DECL_DLLEXPORT void start_duel(ptr pduel, int32 options);
extern "C" DECL_DLLEXPORT void end_duel(ptr pduel);
extern "C" DECL_DLLEXPORT void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);
extern "C" DECL_DLLEXPORT void get_log_message(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT int32 get_message(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT int32 process(ptr pduel);
extern "C" DECL_DLLEXPORT void new_card(ptr pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position);
extern "C" DECL_DLLEXPORT void new_tag_card(ptr pduel, uint32 code, uint8 owner, uint8 location);
extern "C" DECL_DLLEXPORT int32 query_card(ptr pduel, uint8 playerid, uint8 location, uint8 sequence, int32 query_flag, byte* buf, int32 use_cache);
extern "C" DECL_DLLEXPORT int32 query_field_count(ptr pduel, uint8 playerid, uint8 location);
extern "C" DECL_DLLEXPORT int32 query_field_card(ptr pduel, uint8 playerid, uint8 location, int32 query_flag, byte* buf, int32 use_cache);
extern "C" DECL_DLLEXPORT int32 query_field_info(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT void set_responsei(ptr pduel, int32 value);
extern "C" DECL_DLLEXPORT void set_responseb(ptr pduel, byte* buf);
extern "C" DECL_DLLEXPORT int32 preload_script(ptr pduel, char* script, int32 len);
byte* default_script_reader(const char* script_name, int* len);
uint32 default_card_reader(uint32 code, card_data* data);
uint32 default_message_handler(void* pduel, uint32 msg_type);
#endif /* OCGAPI_H_ */
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* playerop.cpp
*
* Created on: 2010-12-22
* Author: Argon
*/
#include "field.h"
#include "duel.h"
#include "effect.h"
#include "card.h"
#include <memory.h>
#include <algorithm>
int32 field::select_battle_command(uint16 step, uint8 playerid) {
if(step == 0) {
pduel->write_buffer8(MSG_SELECT_BATTLECMD);
pduel->write_buffer8(playerid);
uint32 i;
card* pcard;
effect* peffect;
//Activatable
pduel->write_buffer8(core.select_chains.size());
std::sort(core.select_chains.begin(), core.select_chains.end(), chain::chain_operation_sort);
for(i = 0; i < core.select_chains.size(); ++i) {
peffect = core.select_chains[i].triggering_effect;
pcard = peffect->handler;
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer32(peffect->description);
}
//Attackable
pduel->write_buffer8(core.attackable_cards.size());
for(i = 0; i < core.attackable_cards.size(); ++i) {
pcard = core.attackable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer8(pcard->operation_param);
}
//M2, EP
if(core.to_m2)
pduel->write_buffer8(1);
else
pduel->write_buffer8(0);
if(core.to_ep)
pduel->write_buffer8(1);
else
pduel->write_buffer8(0);
return FALSE;
} else {
uint32 t = returns.ivalue[0] & 0xffff;
uint32 s = returns.ivalue[0] >> 16;
if(t < 0 || t > 3 || s < 0
|| (t == 0 && s >= core.select_chains.size())
|| (t == 1 && s >= core.attackable_cards.size())
|| (t == 2 && !core.to_m2)
|| (t == 3 && !core.to_ep)) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_idle_command(uint16 step, uint8 playerid) {
if(step == 0) {
uint32 i;
card* pcard;
effect* peffect;
pduel->write_buffer8(MSG_SELECT_IDLECMD);
pduel->write_buffer8(playerid);
//idle summon
pduel->write_buffer8(core.summonable_cards.size());
for(i = 0; i < core.summonable_cards.size(); ++i) {
pcard = core.summonable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
//idle spsummon
pduel->write_buffer8(core.spsummonable_cards.size());
for(i = 0; i < core.spsummonable_cards.size(); ++i) {
pcard = core.spsummonable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
//idle pos change
pduel->write_buffer8(core.repositionable_cards.size());
for(i = 0; i < core.repositionable_cards.size(); ++i) {
pcard = core.repositionable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
//idle mset
pduel->write_buffer8(core.msetable_cards.size());
for(i = 0; i < core.msetable_cards.size(); ++i) {
pcard = core.msetable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
//idle sset
pduel->write_buffer8(core.ssetable_cards.size());
for(i = 0; i < core.ssetable_cards.size(); ++i) {
pcard = core.ssetable_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
//idle activate
pduel->write_buffer8(core.select_chains.size());
std::sort(core.select_chains.begin(), core.select_chains.end(), chain::chain_operation_sort);
for(i = 0; i < core.select_chains.size(); ++i) {
peffect = core.select_chains[i].triggering_effect;
pcard = peffect->handler;
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer32(peffect->description);
}
//To BP
if(infos.phase == PHASE_MAIN1 && core.to_bp)
pduel->write_buffer8(1);
else
pduel->write_buffer8(0);
if(core.to_ep)
pduel->write_buffer8(1);
else
pduel->write_buffer8(0);
if(infos.can_shuffle && player[playerid].list_hand.size() > 1)
pduel->write_buffer8(1);
else
pduel->write_buffer8(0);
return FALSE;
} else {
uint32 t = returns.ivalue[0] & 0xffff;
uint32 s = returns.ivalue[0] >> 16;
if(t < 0 || t > 8 || s < 0
|| (t == 0 && s >= core.summonable_cards.size())
|| (t == 1 && s >= core.spsummonable_cards.size())
|| (t == 2 && s >= core.repositionable_cards.size())
|| (t == 3 && s >= core.msetable_cards.size())
|| (t == 4 && s >= core.ssetable_cards.size())
|| (t == 5 && s >= core.select_chains.size())
|| (t == 6 && (infos.phase != PHASE_MAIN1 || !core.to_bp))
|| (t == 7 && !core.to_ep)
|| (t == 8 && !(infos.can_shuffle && player[playerid].list_hand.size() > 1))) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_effect_yes_no(uint16 step, uint8 playerid, card* pcard) {
if(step == 0) {
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.ivalue[0] = 1;
return TRUE;
}
pduel->write_buffer8(MSG_SELECT_EFFECTYN);
pduel->write_buffer8(playerid);
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
returns.ivalue[0] = -1;
return FALSE;
} else {
if(returns.ivalue[0] != 0 && returns.ivalue[0] != 1) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_yes_no(uint16 step, uint8 playerid, uint32 description) {
if(step == 0) {
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.ivalue[0] = 1;
return TRUE;
}
pduel->write_buffer8(MSG_SELECT_YESNO);
pduel->write_buffer8(playerid);
pduel->write_buffer32(description);
returns.ivalue[0] = -1;
return FALSE;
} else {
if(returns.ivalue[0] != 0 && returns.ivalue[0] != 1) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_option(uint16 step, uint8 playerid) {
if(step == 0) {
returns.ivalue[0] = -1;
if(core.select_options.size() == 0)
return TRUE;
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.ivalue[0] = 0;
return TRUE;
}
pduel->write_buffer8(MSG_SELECT_OPTION);
pduel->write_buffer8(playerid);
pduel->write_buffer8(core.select_options.size());
for(uint32 i = 0; i < core.select_options.size(); ++i)
pduel->write_buffer32(core.select_options[i]);
return FALSE;
} else {
if(returns.ivalue[0] < 0 || returns.ivalue[0] >= (int32)core.select_options.size()) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_card(uint16 step, uint8 playerid, uint8 cancelable, uint8 min, uint8 max) {
if(step == 0) {
returns.bvalue[0] = 0;
if(max == 0 || core.select_cards.empty())
return TRUE;
if(max > 63)
max = 63;
if(max > core.select_cards.size())
max = core.select_cards.size();
if(min > max)
min = max;
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.bvalue[0] = min;
for(uint8 i = 0; i < min; ++i)
returns.bvalue[i + 1] = i;
return TRUE;
}
core.units.begin()->arg2 = ((uint32)min) + (((uint32)max) << 16);
pduel->write_buffer8(MSG_SELECT_CARD);
pduel->write_buffer8(playerid);
pduel->write_buffer8(cancelable);
pduel->write_buffer8(min);
pduel->write_buffer8(max);
pduel->write_buffer8(core.select_cards.size());
card* pcard;
std::sort(core.select_cards.begin(), core.select_cards.end(), card::card_operation_sort);
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
pcard = core.select_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
}
return FALSE;
} else {
if(cancelable && returns.ivalue[0] == -1)
return TRUE;
byte c[64];
memset(c, 0, 64);
if(returns.bvalue[0] < min || returns.bvalue[0] > max) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
uint8 m = core.select_cards.size(), v = 0;
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
v = returns.bvalue[i + 1];
if(v < 0 || v >= m || v >= 63 || c[v]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
c[v] = 1;
}
return TRUE;
}
}
int32 field::select_chain(uint16 step, uint8 playerid, uint8 spe_count, uint8 forced) {
if(step == 0) {
returns.ivalue[0] = -1;
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
if(core.select_chains.size() == 0)
returns.ivalue[0] = -1;
else {
bool act = true;
for(auto chit = core.current_chain.begin(); chit != core.current_chain.end(); ++chit)
if(chit->triggering_player == 1)
act = false;
if(act)
returns.ivalue[0] = 0;
else
returns.ivalue[0] = -1;
}
return TRUE;
}
pduel->write_buffer8(MSG_SELECT_CHAIN);
pduel->write_buffer8(playerid);
pduel->write_buffer8(core.select_chains.size());
pduel->write_buffer8(spe_count);
pduel->write_buffer8(forced);
pduel->write_buffer32(pduel->game_field->core.hint_timing[playerid]);
pduel->write_buffer32(pduel->game_field->core.hint_timing[1 - playerid]);
std::sort(core.select_chains.begin(), core.select_chains.end(), chain::chain_operation_sort);
for(uint32 i = 0; i < core.select_chains.size(); ++i) {
effect* peffect = core.select_chains[i].triggering_effect;
card* pcard = peffect->handler;
if(!(peffect->type & EFFECT_TYPE_ACTIONS))
pcard = peffect->owner;
if(peffect->flag & EFFECT_FLAG_FIELD_ONLY)
pduel->write_buffer32(1000000000 + pcard->data.code);
else
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(peffect->description);
}
return FALSE;
} else {
if((returns.ivalue[0] < 0 && forced) || returns.ivalue[0] >= (int32)core.select_chains.size()) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_place(uint16 step, uint8 playerid, uint32 flag, uint8 count) {
if(step == 0) {
if(count == 0)
return TRUE;
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.bvalue[0] = 1;
flag = ~flag;
if(flag & 0x1f) {
returns.bvalue[1] = LOCATION_MZONE;
if(flag & 0x4) returns.bvalue[2] = 2;
else if(flag & 0x2) returns.bvalue[2] = 1;
else if(flag & 0x8) returns.bvalue[2] = 3;
else if(flag & 0x1) returns.bvalue[2] = 0;
else returns.bvalue[2] = 4;
} else {
returns.bvalue[1] = LOCATION_SZONE;
if(flag & 0x400) returns.bvalue[2] = 2;
else if(flag & 0x200) returns.bvalue[2] = 1;
else if(flag & 0x800) returns.bvalue[2] = 3;
else if(flag & 0x100) returns.bvalue[2] = 0;
else returns.bvalue[2] = 4;
}
return true;
}
if(core.units.begin()->type == PROCESSOR_SELECT_PLACE)
pduel->write_buffer8(MSG_SELECT_PLACE);
else
pduel->write_buffer8(MSG_SELECT_DISFIELD);
pduel->write_buffer8(playerid);
pduel->write_buffer8(count);
pduel->write_buffer32(flag);
returns.bvalue[0] = 0;
return FALSE;
} else {
uint8 pt = 0, p, l, s;
for(int8 i = 0; i < count; ++i) {
p = returns.bvalue[pt];
l = returns.bvalue[pt + 1];
s = returns.bvalue[pt + 2];
if((p != 0 && p != 1) || ((l != LOCATION_MZONE) && (l != LOCATION_SZONE)) || s >= 5
|| ((1 << s) & (flag >> (((p == playerid) ? 0 : 16) + ((l == LOCATION_MZONE) ? 0 : 8))))) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
pt += 3;
}
return TRUE;
}
}
int32 field::select_position(uint16 step, uint8 playerid, uint32 code, uint8 positions) {
if(step == 0) {
if(positions == 0) {
returns.ivalue[0] = POS_FACEUP_ATTACK;
return TRUE;
}
positions &= 0xf;
if(positions == 0x1 || positions == 0x2 || positions == 0x4 || positions == 0x8) {
returns.ivalue[0] = positions;
return TRUE;
}
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
if(positions & 0x4)
returns.ivalue[0] = 0x4;
else if(positions & 0x1)
returns.ivalue[0] = 0x1;
else if(positions & 0x8)
returns.ivalue[0] = 0x8;
else
returns.ivalue[0] = 0x2;
return TRUE;
}
pduel->write_buffer8(MSG_SELECT_POSITION);
pduel->write_buffer8(playerid);
pduel->write_buffer32(code);
pduel->write_buffer8(positions);
returns.ivalue[0] = 0;
return FALSE;
} else {
uint32 pos = returns.ivalue[0];
if(pos != 0x1 && pos != 0x2 && pos != 0x4 && pos != 0x8 && !(pos & positions)) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_tribute(uint16 step, uint8 playerid, uint8 cancelable, uint8 min, uint8 max) {
if(step == 0) {
returns.bvalue[0] = 0;
if(max == 0 || core.select_cards.empty())
return TRUE;
uint8 tm = 0;
for(uint32 i = 0; i < core.select_cards.size(); ++i)
tm += core.select_cards[i]->operation_param;
if(max > 5)
max = 5;
if(max > tm)
max = tm;
if(min > max)
min = max;
core.units.begin()->arg2 = ((uint32)min) + (((uint32)max) << 16);
pduel->write_buffer8(MSG_SELECT_TRIBUTE);
pduel->write_buffer8(playerid);
pduel->write_buffer8(cancelable);
pduel->write_buffer8(min);
pduel->write_buffer8(max);
pduel->write_buffer8(core.select_cards.size());
card* pcard;
std::sort(core.select_cards.begin(), core.select_cards.end(), card::card_operation_sort);
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
pcard = core.select_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer8(pcard->operation_param);
}
return FALSE;
} else {
if(cancelable && returns.ivalue[0] == -1)
return TRUE;
byte c[64];
memset(c, 0, 64);
if(returns.bvalue[0] > max) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
uint8 m = core.select_cards.size(), v = 0, tt = 0;
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
v = returns.bvalue[i + 1];
if(v < 0 || v >= m || v >= 6 || c[v]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
c[v] = 1;
tt += core.select_cards[v]->operation_param;
}
if(tt < min) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
int32 field::select_counter(uint16 step, uint8 playerid, uint16 countertype, uint16 count) {
if(step == 0) {
if(core.select_cards.empty() || count == 0)
return TRUE;
uint8 tm = 0;
for(uint32 i = 0; i < core.select_cards.size(); ++i)
tm += core.select_cards[i]->operation_param;
if(count > tm) {
count = tm;
core.units.begin()->arg2 = countertype + (((uint32)count) << 16);
}
pduel->write_buffer8(MSG_SELECT_COUNTER);
pduel->write_buffer8(playerid);
pduel->write_buffer16(countertype);
pduel->write_buffer8((uint8)count);
pduel->write_buffer8(core.select_cards.size());
card* pcard;
std::sort(core.select_cards.begin(), core.select_cards.end(), card::card_operation_sort);
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
pcard = core.select_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer8(pcard->operation_param);
}
return FALSE;
} else {
uint16 ct = 0;
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
if(core.select_cards[i]->operation_param < (uint32)returns.bvalue[i]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
ct += returns.bvalue[i];
}
if(ct != count) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
}
return TRUE;
}
int32 select_sum_check1(int32* oparam, int32 size, int32 index, int32 count, int32 acc, int32 min) {
if(acc == 0 || index == size)
return FALSE;
int32 o1 = oparam[index] & 0xffff;
int32 o2 = oparam[index] >> 16;
if((o1 == acc || o2 == acc) && index == size - 1 && count >= min)
return TRUE;
return (acc > o1 && select_sum_check1(oparam, size, index + 1, count + 1, acc - o1, min))
|| (o2 > 0 && acc > o2 && select_sum_check1(oparam, size, index + 1, count + 1, acc - o2, min));
}
int32 field::select_with_sum_limit(int16 step, uint8 playerid, int32 acc, int32 min, int32 max) {
if(step == 0) {
returns.bvalue[0] = 0;
if(core.select_cards.empty())
return TRUE;
pduel->write_buffer8(MSG_SELECT_SUM);
if(max)
pduel->write_buffer8(0);
else
pduel->write_buffer8(1);
if(max < min)
max = min;
pduel->write_buffer8(playerid);
pduel->write_buffer32(acc & 0xffff);
pduel->write_buffer8(min);
pduel->write_buffer8(max);
pduel->write_buffer8(core.select_cards.size());
card* pcard;
std::sort(core.select_cards.begin(), core.select_cards.end(), card::card_operation_sort);
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
pcard = core.select_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
pduel->write_buffer32(pcard->operation_param);
}
return FALSE;
} else {
byte c[64];
memset(c, 0, 64);
if(min) {
int32 oparam[16];
if(returns.bvalue[0] < min || returns.bvalue[0] > max) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
uint8 m = core.select_cards.size(), v = 0;
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
v = returns.bvalue[i + 1];
if(v < 0 || v >= m || c[v]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
c[v] = 1;
oparam[i] = core.select_cards[v]->operation_param;
}
if(!select_sum_check1(oparam, returns.bvalue[0], 0, 1, acc, min)) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
} else {
uint8 m = core.select_cards.size(), v = 0;
int32 op, o1, o2, sum = 0, mx = 0, mn = 0x7fffffff;
int16 ms[16];
for(int32 i = 0; i < returns.bvalue[0]; ++i) {
v = returns.bvalue[i + 1];
if(v < 0 || v >= m || c[v]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
c[v] = 1;
op = core.select_cards[v]->operation_param;
o1 = op & 0xffff;
o2 = op >> 16;
sum += ms[i] = (o2 && o2 < o1) ? o2 : o1;
mx += (o2 > o1) ? o2 : o1;
if(ms[i] < mn)
mn = ms[i];
}
if(mx < acc || sum - mn >= acc) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
return TRUE;
}
}
return TRUE;
}
int32 field::sort_card(int16 step, uint8 playerid, uint8 is_chain) {
if(step == 0) {
returns.bvalue[0] = 0;
if((playerid == 1) && (core.duel_options & DUEL_SIMPLE_AI)) {
returns.ivalue[0] = -1;
return TRUE;
}
if(core.select_cards.empty())
return TRUE;
if(is_chain)
pduel->write_buffer8(MSG_SORT_CHAIN);
else
pduel->write_buffer8(MSG_SORT_CARD);
pduel->write_buffer8(playerid);
pduel->write_buffer8(core.select_cards.size());
card* pcard;
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
pcard = core.select_cards[i];
pduel->write_buffer32(pcard->data.code);
pduel->write_buffer8(pcard->current.controler);
pduel->write_buffer8(pcard->current.location);
pduel->write_buffer8(pcard->current.sequence);
}
return FALSE;
} else {
if(returns.bvalue[0] == -1)
return TRUE;
uint8 seq[64];
memset(seq, 0, 64);
for(uint32 i = 0; i < core.select_cards.size(); ++i) {
if(returns.bvalue[i] < 0 || returns.bvalue[i] >= (int32)core.select_cards.size() || seq[(int32)returns.bvalue[i]]) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
seq[(int32)returns.bvalue[i]] = 1;
}
return TRUE;
}
return TRUE;
}
int32 field::announce_race(int16 step, uint8 playerid, int32 count, int32 available) {
if(step == 0) {
int32 scount = 0;
for(int32 ft = 0x1; ft != 0x1000000; ft <<= 1) {
if(ft & available)
scount++;
}
if(scount <= count) {
count = scount;
core.units.begin()->arg1 = (count << 16) + playerid;
}
pduel->write_buffer8(MSG_ANNOUNCE_RACE);
pduel->write_buffer8(playerid);
pduel->write_buffer8(count);
pduel->write_buffer32(available);
return FALSE;
} else {
int32 rc = returns.ivalue[0];
int32 sel = 0;
for(int32 ft = 0x1; ft != 0x1000000; ft <<= 1) {
if(!(ft & rc)) continue;
if(!(ft & available)) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
sel++;
}
if(sel != count) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_RACE);
pduel->write_buffer8(playerid);
pduel->write_buffer32(returns.ivalue[0]);
return TRUE;
}
return TRUE;
}
int32 field::announce_attribute(int16 step, uint8 playerid, int32 count, int32 available) {
if(step == 0) {
int32 scount = 0;
for(int32 ft = 0x1; ft != 0x80; ft <<= 1) {
if(ft & available)
scount++;
}
if(scount <= count) {
count = scount;
core.units.begin()->arg1 = (count << 16) + playerid;
}
pduel->write_buffer8(MSG_ANNOUNCE_ATTRIB);
pduel->write_buffer8(playerid);
pduel->write_buffer8(count);
pduel->write_buffer32(available);
return FALSE;
} else {
int32 rc = returns.ivalue[0];
int32 sel = 0;
for(int32 ft = 0x1; ft != 0x80; ft <<= 1) {
if(!(ft & rc)) continue;
if(!(ft & available)) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
sel++;
}
if(sel != count) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_ATTRIB);
pduel->write_buffer8(playerid);
pduel->write_buffer32(returns.ivalue[0]);
return TRUE;
}
return TRUE;
}
int32 field::announce_card(int16 step, uint8 playerid) {
if(step == 0) {
pduel->write_buffer8(MSG_ANNOUNCE_CARD);
pduel->write_buffer8(playerid);
return FALSE;
} else {
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_CODE);
pduel->write_buffer8(playerid);
pduel->write_buffer32(returns.ivalue[0]);
return TRUE;
}
return TRUE;
}
int32 field::announce_number(int16 step, uint8 playerid) {
if(step == 0) {
pduel->write_buffer8(MSG_ANNOUNCE_NUMBER);
pduel->write_buffer8(playerid);
pduel->write_buffer8(core.select_options.size());
for(uint32 i = 0; i < core.select_options.size(); ++i)
pduel->write_buffer32(core.select_options[i]);
return FALSE;
} else {
int32 ret = returns.ivalue[0];
if(ret < 0 || ret >= (int32)core.select_options.size() || ret >= 63) {
pduel->write_buffer8(MSG_RETRY);
return FALSE;
}
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(HINT_NUMBER);
pduel->write_buffer8(playerid);
pduel->write_buffer32(core.select_options[returns.ivalue[0]]);
return TRUE;
}
}
project "ocgcore"
kind "StaticLib"
files { "**.cc", "**.cpp", "**.c", "**.h" }
configuration "windows"
includedirs { ".." }
configuration "not vs*"
buildoptions { "-std=gnu++0x" }
configuration "not windows"
includedirs { "/usr/include/lua", "/usr/include/lua5.2", "/usr/include/lua/5.2" }
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* scriptlib.cpp
*
* Created on: 2010-7-29
* Author: Argon
*/
#include "scriptlib.h"
#include "duel.h"
int32 scriptlib::check_param(lua_State* L, int32 param_type, int32 index, int32 retfalse) {
int32 result;
switch (param_type) {
case PARAM_TYPE_CARD:
if (lua_isuserdata(L, index)) {
result = **(int32**)lua_touserdata(L, index);
if(result == 1)
return TRUE;
}
if(retfalse)
return FALSE;
luaL_error(L, "Parameter %d should be \"Card\".", index);
break;
case PARAM_TYPE_GROUP:
if (lua_isuserdata(L, index)) {
result = **(int32**)lua_touserdata(L, index);
if(result == 2)
return TRUE;
}
if(retfalse)
return FALSE;
luaL_error(L, "Parameter %d should be \"Group\".", index);
break;
case PARAM_TYPE_EFFECT:
if (lua_isuserdata(L, index)) {
result = **(int32**)lua_touserdata(L, index);
if(result == 3)
return TRUE;
}
if(retfalse)
return FALSE;
luaL_error(L, "Parameter %d should be \"Effect\".", index);
break;
case PARAM_TYPE_FUNCTION:
if (lua_isfunction(L, index))
return TRUE;
if(retfalse)
return FALSE;
luaL_error(L, "Parameter %d should be \"Function\".", index);
break;
case PARAM_TYPE_STRING:
if (lua_isstring(L, index))
return TRUE;
if(retfalse)
return FALSE;
luaL_error(L, "Parameter %d should be \"String\".", index);
break;
}
return FALSE;
}
int32 scriptlib::check_param_count(lua_State* L, int32 count) {
if (lua_gettop(L) < count)
luaL_error(L, "%d Parameters are needed.", count);
return TRUE;
}
int32 scriptlib::check_action_permission(lua_State* L) {
duel* pduel = interpreter::get_duel_info(L);
if(pduel->lua->no_action)
luaL_error(L, "Action is not allowed here.");
return TRUE;
}
/*
* scriptlib.h
*
* Created on: 2009-1-20
* Author: Argon.Sun
*/
#ifndef SCRIPTLIB_H_
#define SCRIPTLIB_H_
#include "common.h"
#include "interpreter.h"
class scriptlib {
public:
static int32 check_param(lua_State* L, int32 param_type, int32 index, BOOL retfalse = FALSE);
static int32 check_param_count(lua_State* L, int32 count);
static int32 check_action_permission(lua_State* L);
//card lib
static int32 card_get_code(lua_State *L);
static int32 card_get_origin_code(lua_State *L);
static int32 card_get_origin_code_rule(lua_State *L);
static int32 card_is_set_card(lua_State *L);
static int32 card_is_pre_set_card(lua_State *L);
static int32 card_get_type(lua_State *L);
static int32 card_get_origin_type(lua_State *L);
static int32 card_get_level(lua_State *L);
static int32 card_get_rank(lua_State *L);
static int32 card_get_synchro_level(lua_State *L);
static int32 card_get_ritual_level(lua_State *L);
static int32 card_get_origin_level(lua_State *L);
static int32 card_get_origin_rank(lua_State *L);
static int32 card_is_xyz_level(lua_State *L);
static int32 card_get_lscale(lua_State *L);
static int32 card_get_origin_lscale(lua_State *L);
static int32 card_get_rscale(lua_State *L);
static int32 card_get_origin_rscale(lua_State *L);
static int32 card_get_attribute(lua_State *L);
static int32 card_get_origin_attribute(lua_State *L);
static int32 card_get_race(lua_State *L);
static int32 card_get_origin_race(lua_State *L);
static int32 card_get_attack(lua_State *L);
static int32 card_get_origin_attack(lua_State *L);
static int32 card_get_text_attack(lua_State *L);
static int32 card_get_defence(lua_State *L);
static int32 card_get_origin_defence(lua_State *L);
static int32 card_get_text_defence(lua_State *L);
static int32 card_get_previous_code_onfield(lua_State *L);
static int32 card_get_previous_type_onfield(lua_State *L);
static int32 card_get_previous_level_onfield(lua_State *L);
static int32 card_get_previous_rank_onfield(lua_State *L);
static int32 card_get_previous_attribute_onfield(lua_State *L);
static int32 card_get_previous_race_onfield(lua_State *L);
static int32 card_get_previous_attack_onfield(lua_State *L);
static int32 card_get_previous_defence_onfield(lua_State *L);
static int32 card_get_owner(lua_State *L);
static int32 card_get_controler(lua_State *L);
static int32 card_get_previous_controler(lua_State *L);
static int32 card_get_reason(lua_State *L);
static int32 card_get_reason_card(lua_State *L);
static int32 card_get_reason_player(lua_State *L);
static int32 card_get_reason_effect(lua_State *L);
static int32 card_get_position(lua_State *L);
static int32 card_get_previous_position(lua_State *L);
static int32 card_get_battle_position(lua_State *L);
static int32 card_get_location(lua_State *L);
static int32 card_get_previous_location(lua_State *L);
static int32 card_get_sequence(lua_State *L);
static int32 card_get_previous_sequence(lua_State *L);
static int32 card_get_summon_type(lua_State *L);
static int32 card_get_summon_location(lua_State *L);
static int32 card_get_summon_player(lua_State *L);
static int32 card_get_destination(lua_State *L);
static int32 card_get_leave_field_dest(lua_State *L);
static int32 card_get_turnid(lua_State *L);
static int32 card_get_fieldid(lua_State *L);
static int32 card_get_fieldidr(lua_State *L);
static int32 card_is_code(lua_State *L);
static int32 card_is_type(lua_State *L);
static int32 card_is_race(lua_State *L);
static int32 card_is_attribute(lua_State *L);
static int32 card_is_reason(lua_State *L);
static int32 card_is_status(lua_State *L);
static int32 card_is_not_tuner(lua_State *L);
static int32 card_set_status(lua_State *L);
static int32 card_is_dual_state(lua_State *L);
static int32 card_enable_dual_state(lua_State *L);
static int32 card_set_turn_counter(lua_State *L);
static int32 card_get_turn_counter(lua_State *L);
static int32 card_set_material(lua_State *L);
static int32 card_get_material(lua_State *L);
static int32 card_get_material_count(lua_State *L);
static int32 card_get_equip_group(lua_State *L);
static int32 card_get_equip_count(lua_State *L);
static int32 card_get_equip_target(lua_State *L);
static int32 card_get_pre_equip_target(lua_State *L);
static int32 card_check_equip_target(lua_State *L);
static int32 card_get_union_count(lua_State *L);
static int32 card_get_overlay_group(lua_State *L);
static int32 card_get_overlay_count(lua_State *L);
static int32 card_get_overlay_target(lua_State *L);
static int32 card_check_remove_overlay_card(lua_State *L);
static int32 card_remove_overlay_card(lua_State *L);
static int32 card_get_attacked_group(lua_State *L);
static int32 card_get_attacked_group_count(lua_State *L);
static int32 card_get_attacked_count(lua_State *L);
static int32 card_get_battled_group(lua_State *L);
static int32 card_get_battled_group_count(lua_State *L);
static int32 card_get_attack_announced_count(lua_State *L);
static int32 card_is_direct_attacked(lua_State *L);
static int32 card_set_card_target(lua_State *L);
static int32 card_get_card_target(lua_State *L);
static int32 card_get_first_card_target(lua_State *L);
static int32 card_get_card_target_count(lua_State *L);
static int32 card_is_has_card_target(lua_State *L);
static int32 card_cancel_card_target(lua_State *L);
static int32 card_get_owner_target(lua_State *L);
static int32 card_get_owner_target_count(lua_State *L);
static int32 card_get_activate_effect(lua_State *L);
static int32 card_check_activate_effect(lua_State *L);
static int32 card_register_effect(lua_State *L);
static int32 card_is_has_effect(lua_State *L);
static int32 card_reset_effect(lua_State *L);
static int32 card_get_effect_count(lua_State *L);
static int32 card_register_flag_effect(lua_State *L);
static int32 card_get_flag_effect(lua_State *L);
static int32 card_reset_flag_effect(lua_State *L);
static int32 card_set_flag_effect_label(lua_State *L);
static int32 card_get_flag_effect_label(lua_State *L);
static int32 card_create_relation(lua_State *L);
static int32 card_release_relation(lua_State *L);
static int32 card_create_effect_relation(lua_State *L);
static int32 card_release_effect_relation(lua_State *L);
static int32 card_clear_effect_relation(lua_State *L);
static int32 card_is_relate_to_effect(lua_State *L);
static int32 card_is_relate_to_card(lua_State *L);
static int32 card_is_relate_to_battle(lua_State *L);
static int32 card_copy_effect(lua_State *L);
static int32 card_enable_unsummonable(lua_State *L);
static int32 card_enable_revive_limit(lua_State *L);
static int32 card_complete_procedure(lua_State *L);
static int32 card_is_disabled(lua_State *L);
static int32 card_is_destructable(lua_State *L);
static int32 card_is_summonable(lua_State *L);
static int32 card_is_msetable(lua_State *L);
static int32 card_is_ssetable(lua_State *L);
static int32 card_is_special_summonable(lua_State *L);
static int32 card_is_synchro_summonable(lua_State *L);
static int32 card_is_xyz_summonable(lua_State *L);
static int32 card_is_can_be_summoned(lua_State *L);
static int32 card_is_can_be_special_summoned(lua_State *L);
static int32 card_is_able_to_hand(lua_State *L);
static int32 card_is_able_to_grave(lua_State *L);
static int32 card_is_able_to_deck(lua_State *L);
static int32 card_is_able_to_extra(lua_State *L);
static int32 card_is_able_to_remove(lua_State *L);
static int32 card_is_able_to_hand_as_cost(lua_State *L);
static int32 card_is_able_to_grave_as_cost(lua_State *L);
static int32 card_is_able_to_deck_as_cost(lua_State *L);
static int32 card_is_able_to_extra_as_cost(lua_State *L);
static int32 card_is_able_to_deck_or_extra_as_cost(lua_State *L);
static int32 card_is_able_to_remove_as_cost(lua_State *L);
static int32 card_is_releasable(lua_State *L);
static int32 card_is_releasable_by_effect(lua_State *L);
static int32 card_is_discardable(lua_State *L);
static int32 card_is_attackable(lua_State *L);
static int32 card_is_chain_attackable(lua_State *L);
static int32 card_is_faceup(lua_State *L);
static int32 card_is_attack_pos(lua_State *L);
static int32 card_is_facedown(lua_State *L);
static int32 card_is_defence_pos(lua_State *L);
static int32 card_is_position(lua_State *L);
static int32 card_is_pre_position(lua_State *L);
static int32 card_is_controler(lua_State *L);
static int32 card_is_onfield(lua_State *L);
static int32 card_is_location(lua_State *L);
static int32 card_is_pre_location(lua_State *L);
static int32 card_is_level_below(lua_State *L);
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_attack_below(lua_State *L);
static int32 card_is_attack_above(lua_State *L);
static int32 card_is_defence_below(lua_State *L);
static int32 card_is_defence_above(lua_State *L);
static int32 card_is_public(lua_State *L);
static int32 card_is_forbidden(lua_State *L);
static int32 card_is_able_to_change_controler(lua_State *L);
static int32 card_is_controler_can_be_changed(lua_State *L);
static int32 card_add_counter(lua_State *L);
static int32 card_remove_counter(lua_State *L);
static int32 card_get_counter(lua_State *L);
static int32 card_enable_counter_permit(lua_State *L);
static int32 card_set_counter_limit(lua_State *L);
static int32 card_is_can_turn_set(lua_State *L);
static int32 card_is_can_add_counter(lua_State *L);
static int32 card_is_can_remove_counter(lua_State *L);
static int32 card_is_can_be_fusion_material(lua_State *L);
static int32 card_is_can_be_synchro_material(lua_State *L);
static int32 card_is_can_be_ritual_material(lua_State *L);
static int32 card_is_can_be_xyz_material(lua_State *L);
static int32 card_check_fusion_material(lua_State *L);
static int32 card_is_immune_to_effect(lua_State *L);
static int32 card_is_can_be_effect_target(lua_State *L);
static int32 card_is_can_be_battle_target(lua_State *L);
static int32 card_add_trap_monster_attribute(lua_State *L);
static int32 card_trap_monster_block(lua_State *L);
static int32 card_cancel_to_grave(lua_State *L);
static int32 card_get_tribute_requirement(lua_State *L);
static int32 card_get_battle_target(lua_State *L);
static int32 card_get_attackable_target(lua_State *L);
static int32 card_set_hint(lua_State *L);
static int32 card_reverse_in_deck(lua_State *L);
static int32 card_set_unique_onfield(lua_State *L);
static int32 card_check_unique_onfield(lua_State *L);
static int32 card_reset_negate_effect(lua_State *L);
static int32 card_assume_prop(lua_State *L);
static int32 card_set_spsummon_once(lua_State *L);
//Effect functions
static int32 effect_new(lua_State *L);
static int32 effect_newex(lua_State *L);
static int32 effect_clone(lua_State *L);
static int32 effect_reset(lua_State *L);
static int32 effect_get_field_id(lua_State *L);
static int32 effect_set_description(lua_State *L);
static int32 effect_set_code(lua_State *L);
static int32 effect_set_range(lua_State *L);
static int32 effect_set_target_range(lua_State *L);
static int32 effect_set_absolute_range(lua_State *L);
static int32 effect_set_count_limit(lua_State *L);
static int32 effect_set_reset(lua_State *L);
static int32 effect_set_type(lua_State *L);
static int32 effect_set_property(lua_State *L);
static int32 effect_set_label(lua_State *L);
static int32 effect_set_label_object(lua_State *L);
static int32 effect_set_category(lua_State *L);
static int32 effect_set_hint_timing(lua_State *L);
static int32 effect_set_condition(lua_State *L);
static int32 effect_set_target(lua_State *L);
static int32 effect_set_cost(lua_State *L);
static int32 effect_set_value(lua_State *L);
static int32 effect_set_operation(lua_State *L);
static int32 effect_set_owner_player(lua_State *L);
static int32 effect_get_description(lua_State *L);
static int32 effect_get_code(lua_State *L);
static int32 effect_get_type(lua_State *L);
static int32 effect_get_property(lua_State *L);
static int32 effect_get_label(lua_State *L);
static int32 effect_get_label_object(lua_State *L);
static int32 effect_get_category(lua_State *L);
static int32 effect_get_owner(lua_State *L);
static int32 effect_get_handler(lua_State *L);
static int32 effect_get_owner_player(lua_State *L);
static int32 effect_get_handler_player(lua_State *L);
static int32 effect_get_condition(lua_State *L);
static int32 effect_get_target(lua_State *L);
static int32 effect_get_cost(lua_State *L);
static int32 effect_get_value(lua_State *L);
static int32 effect_get_operation(lua_State *L);
static int32 effect_get_active_type(lua_State *L);
static int32 effect_is_active_type(lua_State *L);
static int32 effect_is_has_property(lua_State *L);
static int32 effect_is_has_category(lua_State *L);
static int32 effect_is_has_type(lua_State *L);
static int32 effect_is_activatable(lua_State *L);
static int32 effect_is_activated(lua_State *L);
static int32 effect_get_activate_location(lua_State *L);
//Group functions
static int32 group_new(lua_State *L);
static int32 group_clone(lua_State *L);
static int32 group_from_cards(lua_State *L);
static int32 group_delete(lua_State *L);
static int32 group_keep_alive(lua_State *L);
static int32 group_clear(lua_State *L);
static int32 group_add_card(lua_State *L);
static int32 group_remove_card(lua_State *L);
static int32 group_get_next(lua_State *L);
static int32 group_get_first(lua_State *L);
static int32 group_get_count(lua_State *L);
static int32 group_for_each(lua_State *L);
static int32 group_filter(lua_State *L);
static int32 group_filter_count(lua_State *L);
static int32 group_filter_select(lua_State *L);
static int32 group_select(lua_State *L);
static int32 group_random_select(lua_State *L);
static int32 group_is_exists(lua_State *L);
static int32 group_check_with_sum_equal(lua_State *L);
static int32 group_select_with_sum_equal(lua_State *L);
static int32 group_check_with_sum_greater(lua_State *L);
static int32 group_select_with_sum_greater(lua_State *L);
static int32 group_get_min_group(lua_State *L);
static int32 group_get_max_group(lua_State *L);
static int32 group_get_sum(lua_State *L);
static int32 group_get_class_count(lua_State *L);
static int32 group_remove(lua_State *L);
static int32 group_merge(lua_State *L);
static int32 group_sub(lua_State *L);
static int32 group_equal(lua_State *L);
static int32 group_is_contains(lua_State *L);
static int32 group_search_card(lua_State *L);
//Duel functions
static int32 duel_enable_global_flag(lua_State *L);
static int32 duel_get_lp(lua_State *L);
static int32 duel_set_lp(lua_State *L);
static int32 duel_get_turn_player(lua_State *L);
static int32 duel_get_turn_count(lua_State *L);
static int32 duel_get_draw_count(lua_State *L);
static int32 duel_register_effect(lua_State *L);
static int32 duel_register_flag_effect(lua_State *L);
static int32 duel_reset_flag_effect(lua_State *L);
static int32 duel_get_flag_effect(lua_State *L);
static int32 duel_destroy(lua_State *L);
static int32 duel_remove(lua_State *L);
static int32 duel_sendto_grave(lua_State *L);
static int32 duel_summon(lua_State *L);
static int32 duel_special_summon_rule(lua_State *L);
static int32 duel_synchro_summon(lua_State *L);
static int32 duel_xyz_summon(lua_State *L);
static int32 duel_setm(lua_State *L);
static int32 duel_sets(lua_State *L);
static int32 duel_create_token(lua_State *L);
static int32 duel_special_summon(lua_State *L);
static int32 duel_special_summon_step(lua_State *L);
static int32 duel_special_summon_complete(lua_State *L);
static int32 duel_sendto_hand(lua_State *L);
static int32 duel_sendto_deck(lua_State *L);
static int32 duel_get_operated_group(lua_State *L);
static int32 duel_remove_counter(lua_State *L);
static int32 duel_is_can_remove_counter(lua_State *L);
static int32 duel_get_counter(lua_State *L);
static int32 duel_change_form(lua_State *L);
static int32 duel_release(lua_State *L);
static int32 duel_move_to_field(lua_State *L);
static int32 duel_return_to_field(lua_State *L);
static int32 duel_move_sequence(lua_State *L);
static int32 duel_set_chain_limit(lua_State *L);
static int32 duel_set_chain_limit_p(lua_State *L);
static int32 duel_get_chain_material(lua_State *L);
static int32 duel_confirm_decktop(lua_State *L);
static int32 duel_confirm_cards(lua_State *L);
static int32 duel_sort_decktop(lua_State *L);
static int32 duel_check_event(lua_State *L);
static int32 duel_raise_event(lua_State *L);
static int32 duel_raise_single_event(lua_State *L);
static int32 duel_check_timing(lua_State *L);
static int32 duel_get_environment(lua_State *L);
static int32 duel_is_environment(lua_State *L);
static int32 duel_win(lua_State *L);
static int32 duel_draw(lua_State *L);
static int32 duel_damage(lua_State *L);
static int32 duel_recover(lua_State *L);
static int32 duel_equip(lua_State *L);
static int32 duel_equip_complete(lua_State *L);
static int32 duel_get_control(lua_State *L);
static int32 duel_swap_control(lua_State *L);
static int32 duel_check_lp_cost(lua_State *L);
static int32 duel_pay_lp_cost(lua_State *L);
static int32 duel_discard_deck(lua_State *L);
static int32 duel_discard_hand(lua_State *L);
static int32 duel_disable_shuffle_check(lua_State *L);
static int32 duel_shuffle_deck(lua_State *L);
static int32 duel_shuffle_hand(lua_State *L);
static int32 duel_shuffle_setcard(lua_State *L);
static int32 duel_change_attacker(lua_State *L);
static int32 duel_replace_attacker(lua_State *L);
static int32 duel_change_attack_target(lua_State *L);
static int32 duel_replace_attack_target(lua_State *L);
static int32 duel_calculate_damage(lua_State *L);
static int32 duel_get_battle_damage(lua_State *L);
static int32 duel_change_battle_damage(lua_State *L);
static int32 duel_change_target(lua_State *L);
static int32 duel_change_target_player(lua_State *L);
static int32 duel_change_target_param(lua_State *L);
static int32 duel_break_effect(lua_State *L);
static int32 duel_change_effect(lua_State *L);
static int32 duel_negate_activate(lua_State *L);
static int32 duel_negate_effect(lua_State *L);
static int32 duel_negate_related_chain(lua_State *L);
static int32 duel_disable_summon(lua_State *L);
static int32 duel_increase_summon_count(lua_State *L);
static int32 duel_check_summon_count(lua_State *L);
static int32 duel_get_location_count(lua_State *L);
static int32 duel_get_field_card(lua_State *L);
static int32 duel_check_location(lua_State *L);
static int32 duel_get_current_chain(lua_State *L);
static int32 duel_get_chain_info(lua_State *L);
static int32 duel_get_first_target(lua_State *L);
static int32 duel_get_current_phase(lua_State *L);
static int32 duel_skip_phase(lua_State *L);
static int32 duel_is_damage_calculated(lua_State *L);
static int32 duel_get_attacker(lua_State *L);
static int32 duel_get_attack_target(lua_State *L);
static int32 duel_disable_attack(lua_State *L);
static int32 duel_chain_attack(lua_State *L);
static int32 duel_readjust(lua_State *L);
static int32 duel_adjust_instantly(lua_State *L);
static int32 duel_get_field_group(lua_State *L);
static int32 duel_get_field_group_count(lua_State *L);
static int32 duel_get_decktop_group(lua_State *L);
static int32 duel_get_matching_group(lua_State *L);
static int32 duel_get_matching_count(lua_State *L);
static int32 duel_get_first_matching_card(lua_State *L);
static int32 duel_is_existing_matching_card(lua_State *L);
static int32 duel_select_matching_cards(lua_State *L);
static int32 duel_get_release_group(lua_State *L);
static int32 duel_get_release_group_count(lua_State *L);
static int32 duel_check_release_group(lua_State *L);
static int32 duel_select_release_group(lua_State *L);
static int32 duel_check_release_group_ex(lua_State *L);
static int32 duel_select_release_group_ex(lua_State *L);
static int32 duel_get_tribute_group(lua_State *L);
static int32 duel_get_tribute_count(lua_State *L);
static int32 duel_select_tribute(lua_State *L);
static int32 duel_get_target_count(lua_State *L);
static int32 duel_is_existing_target(lua_State *L);
static int32 duel_select_target(lua_State *L);
static int32 duel_select_fusion_material(lua_State *L);
static int32 duel_set_fusion_material(lua_State *L);
static int32 duel_set_synchro_material(lua_State *L);
static int32 duel_select_synchro_material(lua_State *L);
static int32 duel_check_synchro_material(lua_State *L);
static int32 duel_select_tuner_material(lua_State *L);
static int32 duel_check_tuner_material(lua_State *L);
static int32 duel_get_ritual_material(lua_State *L);
static int32 duel_release_ritual_material(lua_State *L);
static int32 duel_set_target_card(lua_State *L);
static int32 duel_clear_target_card(lua_State *L);
static int32 duel_set_target_player(lua_State *L);
static int32 duel_set_target_param(lua_State *L);
static int32 duel_set_operation_info(lua_State *L);
static int32 duel_get_operation_info(lua_State *L);
static int32 duel_get_operation_count(lua_State *L);
static int32 duel_check_xyz_material(lua_State *L);
static int32 duel_select_xyz_material(lua_State *L);
static int32 duel_overlay(lua_State *L);
static int32 duel_get_overlay_group(lua_State *L);
static int32 duel_get_overlay_count(lua_State *L);
static int32 duel_check_remove_overlay_card(lua_State *L);
static int32 duel_remove_overlay_card(lua_State *L);
static int32 duel_hint(lua_State *L);
static int32 duel_hint_selection(lua_State *L);
static int32 duel_select_effect_yesno(lua_State *L);
static int32 duel_select_yesno(lua_State *L);
static int32 duel_select_option(lua_State *L);
static int32 duel_select_sequence(lua_State *L);
static int32 duel_select_position(lua_State *L);
static int32 duel_select_disable_field(lua_State *L);
static int32 duel_announce_race(lua_State *L);
static int32 duel_announce_attribute(lua_State *L);
static int32 duel_announce_level(lua_State *L);
static int32 duel_announce_card(lua_State *L);
static int32 duel_announce_type(lua_State *L);
static int32 duel_announce_number(lua_State *L);
static int32 duel_announce_coin(lua_State *L);
static int32 duel_toss_coin(lua_State *L);
static int32 duel_toss_dice(lua_State *L);
static int32 duel_get_coin_result(lua_State *L);
static int32 duel_get_dice_result(lua_State *L);
static int32 duel_set_coin_result(lua_State *L);
static int32 duel_set_dice_result(lua_State *L);
static int32 duel_is_player_affected_by_effect(lua_State *L);
static int32 duel_is_player_can_draw(lua_State *L);
static int32 duel_is_player_can_discard_deck(lua_State *L);
static int32 duel_is_player_can_discard_deck_as_cost(lua_State *L);
static int32 duel_is_player_can_summon(lua_State *L);
static int32 duel_is_player_can_spsummon(lua_State *L);
static int32 duel_is_player_can_flipsummon(lua_State *L);
static int32 duel_is_player_can_spsummon_monster(lua_State *L);
static int32 duel_is_player_can_spsummon_count(lua_State *L);
static int32 duel_is_player_can_release(lua_State *L);
static int32 duel_is_player_can_remove(lua_State *L);
static int32 duel_is_player_can_send_to_hand(lua_State *L);
static int32 duel_is_player_can_send_to_grave(lua_State *L);
static int32 duel_is_player_can_send_to_deck(lua_State *L);
static int32 duel_is_chain_negatable(lua_State *L);
static int32 duel_is_chain_disablable(lua_State *L);
static int32 duel_check_chain_target(lua_State *L);
static int32 duel_check_chain_uniqueness(lua_State *L);
static int32 duel_get_activity_count(lua_State *L);
static int32 duel_check_phase_activity(lua_State *L);
static int32 duel_add_custom_activity_counter(lua_State *L);
static int32 duel_get_custom_activity_count(lua_State *L);
static int32 duel_is_able_to_enter_bp(lua_State *L);
//specific card functions
static int32 duel_venom_swamp_check(lua_State *L);
static int32 duel_swap_deck_and_grave(lua_State *L);
static int32 duel_majestic_copy(lua_State *L);
//preload
static int32 debug_message(lua_State *L);
static int32 debug_add_card(lua_State *L);
static int32 debug_set_player_info(lua_State *L);
static int32 debug_pre_equip(lua_State *L);
static int32 debug_pre_set_target(lua_State *L);
static int32 debug_pre_add_counter(lua_State *L);
static int32 debug_reload_field_begin(lua_State *L);
static int32 debug_reload_field_end(lua_State *L);
static int32 debug_set_ai_name(lua_State *L);
static int32 debug_show_hint(lua_State *L);
};
#endif /* SCRIPTLIB_H_ */
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