mirror of
https://github.com/edo9300/ygopro-core
synced 2026-08-25 16:23:07 -04:00
Move Group's lifetime management to Lua (#166)
No longer manage a Group's lifetime explicitly in native code, but instead leverage Lua's garbage collector to handle it's lifetime. In this change, Groups will be stored internally in the core inside a weak table, so that they will still be reference-able when needed, but if no reference were to exist in Lua code, they will be subject to garbage collection. Whenever a Group is used by native code, its wrapped by a owned_lua template class, this is akin to std::shared_ptr--It reference counts the usages of that group internally in the core, including managing it in the Lua registry index when in use, so that it won't be collected. With this approach, the exponential memory usage growth caused by long running procedures due to the creation hundredths of thousands of groups per iteration, is mitigated, since the temporary groups will be reaped more frequently, as opposed to the old approach of them being cleared only after the topmost Lua function had finished executing. For now a single GC step is triggered whenever the total number of groups is more than 2048--an arbitrary value that seems to work well enough, but which can be changed/optimized after proper profiling. A major upgrade with this approach is the removal of the concept of Groups "kept alive" and having to "explicitly delete" them to make them outlive a Lua function execution, since they will now follow Lua's variables lifetime properly.
This commit is contained in:
parent
5628753a4f
commit
4ab85de875
16 changed files with 361 additions and 291 deletions
37
duel.cpp
37
duel.cpp
|
|
@ -28,12 +28,17 @@ duel::duel(const OCG_DuelOptions& options, bool& valid_lua_lib) :
|
|||
duel::~duel() {
|
||||
for(auto& pcard : cards)
|
||||
delete pcard;
|
||||
for(auto& pgroup : groups)
|
||||
delete pgroup;
|
||||
for(auto& pgroup : groups) {
|
||||
pgroup->container.clear();
|
||||
pgroup->is_iterator_dirty = true;
|
||||
}
|
||||
for(auto& peffect : effects)
|
||||
delete peffect;
|
||||
delete game_field;
|
||||
delete lua;
|
||||
// TODO: this should actually be an assertion as no group should outlive the lua state
|
||||
for(auto& pgroup : groups)
|
||||
delete pgroup;
|
||||
}
|
||||
#if defined(__GNUC__) || defined(__clang_analyzer__)
|
||||
#pragma GCC diagnostic push
|
||||
|
|
@ -43,17 +48,23 @@ void duel::clear() {
|
|||
static constexpr OCG_DuelOptions default_options{ {},0,{8000,5,1},{8000,5,1} };
|
||||
for(auto& pcard : cards)
|
||||
delete pcard;
|
||||
for(auto& pgroup : groups) {
|
||||
lua->unregister_group(pgroup);
|
||||
delete pgroup;
|
||||
}
|
||||
for(auto& peffect : effects) {
|
||||
lua->unregister_effect(peffect);
|
||||
delete peffect;
|
||||
}
|
||||
delete game_field;
|
||||
//force full garbage collection to clean the groups
|
||||
lua->collect(true);
|
||||
cards.clear();
|
||||
groups.clear();
|
||||
/*
|
||||
TODO: how to properly handle groups that are still around after the field was destroyed?
|
||||
If they're still here, it means they're still living as global variables somewhere, for now we
|
||||
deal with them by clearing their containers that could have been pointing to now deleted cards
|
||||
*/
|
||||
for(auto& pgroup : groups) {
|
||||
pgroup->container.clear();
|
||||
pgroup->is_iterator_dirty = true;
|
||||
}
|
||||
effects.clear();
|
||||
game_field = new field(this, default_options);
|
||||
game_field->temp_card = new_card(0);
|
||||
|
|
@ -81,9 +92,7 @@ void duel::delete_card(card* 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) {
|
||||
|
|
@ -101,16 +110,6 @@ void duel::generate_buffer() {
|
|||
}
|
||||
messages.clear();
|
||||
}
|
||||
void duel::release_script_group() {
|
||||
for(auto& pgroup : sgroups) {
|
||||
if(pgroup->is_readonly == 0) {
|
||||
lua->unregister_group(pgroup);
|
||||
groups.erase(pgroup);
|
||||
delete pgroup;
|
||||
}
|
||||
}
|
||||
sgroups.clear();
|
||||
}
|
||||
void duel::restore_assumes() {
|
||||
for(auto& pcard : assumes)
|
||||
pcard->assume.clear();
|
||||
|
|
|
|||
21
duel.h
21
duel.h
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
|
||||
* Copyright (c) 2016-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2016-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#include "common.h"
|
||||
#include "group.h"
|
||||
#include "interpreter.h"
|
||||
#include "lua_obj.h"
|
||||
#include "ocgapi_types.h"
|
||||
#include "RNG/Xoshiro256.hpp"
|
||||
|
||||
|
|
@ -66,7 +67,6 @@ public:
|
|||
std::unordered_set<card*> cards;
|
||||
std::unordered_set<card*> assumes;
|
||||
std::unordered_set<group*> groups;
|
||||
std::unordered_set<group*> sgroups;
|
||||
std::unordered_set<effect*> effects;
|
||||
std::unordered_set<effect*> uncopy;
|
||||
|
||||
|
|
@ -88,19 +88,22 @@ public:
|
|||
|
||||
card* new_card(uint32_t code);
|
||||
template<typename... Args>
|
||||
group* new_group(Args&&... args) {
|
||||
group* pgroup = new group(this, std::forward<Args>(args)...);
|
||||
groups.insert(pgroup);
|
||||
if(lua->call_depth)
|
||||
sgroups.insert(pgroup);
|
||||
lua->register_group(pgroup);
|
||||
owned_lua<group> new_group(Args&&... args) {
|
||||
auto pgroup = [&]() {
|
||||
auto* pgroup = new group(this, std::forward<Args>(args)...);
|
||||
groups.insert(pgroup);
|
||||
lua->register_group(pgroup);
|
||||
return owned_lua<group>{pgroup};
|
||||
}();
|
||||
if(groups.size() > 2048) {
|
||||
lua->collect();
|
||||
}
|
||||
return pgroup;
|
||||
}
|
||||
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();
|
||||
void generate_buffer();
|
||||
void write_buffer(const void* data, size_t size);
|
||||
|
|
|
|||
11
field.cpp
11
field.cpp
|
|
@ -5,7 +5,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
#include <algorithm> //std::sort, std::swap, std::find, std::find_if, std::min, std::none_of
|
||||
#include <cstring> //std::memcmp
|
||||
#include <tuple> //std::tie
|
||||
#include <utility> //std::move
|
||||
#include <vector>
|
||||
#include "card.h"
|
||||
|
|
@ -53,8 +53,13 @@ void chain::set_triggering_state(card* pcard) {
|
|||
setcode.clear();
|
||||
pcard->get_set_card(setcode);
|
||||
}
|
||||
bool tevent::operator< (const tevent& v) const {
|
||||
return std::memcmp(this, &v, sizeof(tevent)) < 0;
|
||||
bool tevent::operator< (const tevent& rhs) const {
|
||||
return std::tie(trigger_card, event_cards, reason_effect,
|
||||
event_code, event_value, reason,
|
||||
event_player, reason_player, global_id) <
|
||||
std::tie(rhs.trigger_card, rhs.event_cards, rhs.reason_effect,
|
||||
rhs.event_code, rhs.event_value, rhs.reason,
|
||||
rhs.event_player, rhs.reason_player, rhs.global_id);
|
||||
}
|
||||
field::field(duel* _pduel, const OCG_DuelOptions& options) :pduel(_pduel), player({ {options.team1, options.team2} }) {
|
||||
core.duel_options = options.flags;
|
||||
|
|
|
|||
11
field.h
11
field.h
|
|
@ -20,6 +20,7 @@
|
|||
#include "card.h"
|
||||
#include "common.h"
|
||||
#include "containers_fwd.h"
|
||||
#include "lua_obj.h"
|
||||
#include "processor_unit.h"
|
||||
#include "progressivebuffer.h"
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ class effect;
|
|||
|
||||
struct tevent {
|
||||
card* trigger_card{};
|
||||
group* event_cards{};
|
||||
owned_lua<group> event_cards;
|
||||
effect* reason_effect{};
|
||||
uint32_t event_code{};
|
||||
uint32_t event_value{};
|
||||
|
|
@ -40,7 +41,7 @@ struct tevent {
|
|||
bool operator< (const tevent& v) const;
|
||||
};
|
||||
struct optarget {
|
||||
group* op_cards;
|
||||
owned_lua<group> op_cards;
|
||||
uint8_t op_count;
|
||||
uint8_t op_player;
|
||||
int32_t op_param;
|
||||
|
|
@ -69,7 +70,7 @@ struct chain {
|
|||
uint32_t flag;
|
||||
uint32_t event_id;
|
||||
effect* triggering_effect;
|
||||
group* target_cards;
|
||||
owned_lua<group> target_cards;
|
||||
effect* disable_reason;
|
||||
applied_chain_counter_t* applied_chain_counters;
|
||||
opmap opinfos;
|
||||
|
|
@ -311,8 +312,8 @@ struct processor {
|
|||
bool set_forced_attack;
|
||||
card* forced_attacker;
|
||||
card* forced_attack_target;
|
||||
group* must_use_mats;
|
||||
group* only_use_mats;
|
||||
owned_lua<group> must_use_mats;
|
||||
owned_lua<group> only_use_mats;
|
||||
int32_t forced_summon_minc;
|
||||
int32_t forced_summon_maxc;
|
||||
bool attack_cancelable;
|
||||
|
|
|
|||
2
group.h
2
group.h
|
|
@ -20,7 +20,7 @@ class group : public lua_obj_helper<LuaParam::GROUP> {
|
|||
public:
|
||||
card_set container;
|
||||
card_set::iterator it;
|
||||
uint8_t is_readonly{ 0 };
|
||||
bool is_readonly{ false };
|
||||
bool is_iterator_dirty{ true };
|
||||
|
||||
bool has_card(card* c) const {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,21 @@ interpreter::interpreter(duel* pd, const OCG_DuelOptions& options, bool& valid_l
|
|||
nil_out("dofile");
|
||||
nil_out("loadfile");
|
||||
}
|
||||
{
|
||||
/*
|
||||
Creates a table and sets a metatable to it making a table with weak keys, which
|
||||
will then be used in place of the LUA_REGISTRYINDEX table to keep track of groups
|
||||
when they are not owned by the core
|
||||
*/
|
||||
luaL_checkstack(lua_state, 4, nullptr);
|
||||
lua_newtable(lua_state);
|
||||
lua_newtable(lua_state);
|
||||
lua_pushliteral(lua_state, "__mode");
|
||||
lua_pushliteral(lua_state, "v");
|
||||
lua_rawset(lua_state, -3); // metatable._mode='v'
|
||||
lua_setmetatable(lua_state, -2);
|
||||
weak_lua_references = ensure_luaL_stack(luaL_ref, lua_state, LUA_REGISTRYINDEX);
|
||||
}
|
||||
// Open all card scripting libs
|
||||
scriptlib::push_card_lib(lua_state);
|
||||
scriptlib::push_effect_lib(lua_state);
|
||||
|
|
@ -152,7 +167,7 @@ static inline void remove_object(lua_State* L, lua_obj* obj, lua_obj* replacemen
|
|||
obj->ref_handle = 0;
|
||||
}
|
||||
void interpreter::register_effect(effect* peffect) {
|
||||
register_obj(peffect, "Effect");
|
||||
register_obj(peffect, "Effect", false);
|
||||
}
|
||||
void interpreter::unregister_effect(effect* peffect) {
|
||||
if (!peffect)
|
||||
|
|
@ -172,14 +187,15 @@ void interpreter::unregister_effect(effect* peffect) {
|
|||
remove_object(lua_state, peffect, &deleted);
|
||||
}
|
||||
void interpreter::register_group(group* pgroup) {
|
||||
register_obj(pgroup, "Group");
|
||||
register_obj(pgroup, "Group", true);
|
||||
}
|
||||
void interpreter::unregister_group(group* pgroup) {
|
||||
remove_object(lua_state, pgroup, &deleted);
|
||||
}
|
||||
void interpreter::register_obj(lua_obj* obj, const char* tablename) {
|
||||
void interpreter::register_obj(lua_obj* obj, const char* tablename, bool weak) {
|
||||
if(!obj)
|
||||
return;
|
||||
if(weak) {
|
||||
luaL_checkstack(lua_state, 1, nullptr);
|
||||
lua_rawgeti(lua_state, LUA_REGISTRYINDEX, weak_lua_references);
|
||||
}
|
||||
luaL_checkstack(lua_state, 3, nullptr);
|
||||
lua_obj** pobj = create_object(lua_state);
|
||||
*pobj = obj;
|
||||
|
|
@ -187,7 +203,15 @@ void interpreter::register_obj(lua_obj* obj, const char* tablename) {
|
|||
lua_getglobal(lua_state, tablename);
|
||||
lua_setmetatable(lua_state, -2);
|
||||
//pops the lua object from the stack and takes a reference of it
|
||||
obj->ref_handle = ensure_luaL_stack(luaL_ref, lua_state, LUA_REGISTRYINDEX);
|
||||
if(weak) {
|
||||
obj->weak_ref_handle = ensure_luaL_stack(luaL_ref, lua_state, -2);
|
||||
lua_pop(lua_state, 1);
|
||||
} else {
|
||||
obj->ref_handle = ensure_luaL_stack(luaL_ref, lua_state, LUA_REGISTRYINDEX);
|
||||
}
|
||||
}
|
||||
void interpreter::collect(bool full) {
|
||||
lua_gc(current_state, full ? LUA_GCCOLLECT : LUA_GCSTEP, 0);
|
||||
}
|
||||
bool interpreter::load_script(const char* buffer, int len, const char* script_name) {
|
||||
if(!buffer)
|
||||
|
|
@ -340,7 +364,6 @@ inline int interpreter::call_lua(lua_State* L, int nargs, int nresults) {
|
|||
--no_action;
|
||||
--call_depth;
|
||||
if(call_depth == 0) {
|
||||
pduel->release_script_group();
|
||||
pduel->restore_assumes();
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -574,7 +597,6 @@ int32_t interpreter::call_coroutine(int32_t function, uint32_t param_count, lua_
|
|||
ensure_luaL_stack(luaL_unref, lua_state, LUA_REGISTRYINDEX, ref);
|
||||
--call_depth;
|
||||
if(call_depth == 0) {
|
||||
pduel->release_script_group();
|
||||
pduel->restore_assumes();
|
||||
}
|
||||
return ret_error("recursive event trigger detected.");
|
||||
|
|
@ -603,7 +625,6 @@ int32_t interpreter::call_coroutine(int32_t function, uint32_t param_count, lua_
|
|||
ensure_luaL_stack(luaL_unref, lua_state, LUA_REGISTRYINDEX, ref);
|
||||
--call_depth;
|
||||
if(call_depth == 0) {
|
||||
pduel->release_script_group();
|
||||
pduel->restore_assumes();
|
||||
}
|
||||
return (result == LUA_OK) ? COROUTINE_FINISH : COROUTINE_ERROR;
|
||||
|
|
@ -612,6 +633,16 @@ int32_t interpreter::clone_lua_ref(int32_t lua_ref) {
|
|||
lua_rawgeti(current_state, LUA_REGISTRYINDEX, lua_ref);
|
||||
return ensure_luaL_stack(luaL_ref, current_state, LUA_REGISTRYINDEX);
|
||||
}
|
||||
int32_t interpreter::strong_from_weak_ref(int32_t weak_lua_ref) {
|
||||
push_weak_ref(current_state, weak_lua_ref);
|
||||
return ensure_luaL_stack(luaL_ref, current_state, LUA_REGISTRYINDEX);
|
||||
}
|
||||
void interpreter::push_weak_ref(lua_State* L, int32_t weak_lua_ref) {
|
||||
luaL_checkstack(L, 2, nullptr);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, weak_lua_references);
|
||||
lua_rawgeti(L, -1, weak_lua_ref);
|
||||
lua_remove(L, -2);
|
||||
}
|
||||
void* interpreter::get_ref_object(int32_t ref_handler) {
|
||||
if(ref_handler == 0)
|
||||
return nullptr;
|
||||
|
|
@ -623,8 +654,10 @@ void* interpreter::get_ref_object(int32_t ref_handler) {
|
|||
}
|
||||
//Convert a pointer to a lua value, +1 -0
|
||||
void interpreter::pushobject(lua_State* L, lua_obj* obj) {
|
||||
if(!obj || obj->ref_handle == 0)
|
||||
if(!obj || (obj->ref_handle == 0 && obj->weak_ref_handle == 0))
|
||||
lua_pushnil(L);
|
||||
else if(obj->ref_handle == 0)
|
||||
obj->pduel->lua->push_weak_ref(L, obj->weak_ref_handle);
|
||||
else
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, obj->ref_handle);
|
||||
}
|
||||
|
|
@ -660,3 +693,23 @@ void interpreter::print_stacktrace(lua_State* L) {
|
|||
pduel->handle_message(lua_get_string_or_empty(L, -1), OCG_LOG_TYPE_FOR_DEBUG);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void lua_obj::incr_ref() {
|
||||
if(ref_handle == 0) {
|
||||
ref_handle = pduel->lua->strong_from_weak_ref(weak_ref_handle);
|
||||
}
|
||||
++num_ref;
|
||||
}
|
||||
|
||||
void lua_obj::decr_ref() {
|
||||
if(--num_ref == 0) {
|
||||
auto* L = pduel->lua->current_state;
|
||||
/*
|
||||
"ensure_luaL_stack" is not used because that would raise a lua error
|
||||
TODO: what to do here? assert if this fails?
|
||||
*/
|
||||
lua_checkstack(L, 5);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, ref_handle);
|
||||
ref_handle = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
|
||||
* Copyright (c) 2017-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2017-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -54,6 +54,7 @@ public:
|
|||
int32_t no_action;
|
||||
int32_t call_depth;
|
||||
lua_invalid deleted;
|
||||
int weak_lua_references;
|
||||
|
||||
interpreter(duel* pd, const OCG_DuelOptions& options, bool& valid_lua_lib);
|
||||
~interpreter();
|
||||
|
|
@ -62,8 +63,9 @@ public:
|
|||
void register_effect(effect* peffect);
|
||||
void unregister_effect(effect* peffect);
|
||||
void register_group(group* pgroup);
|
||||
void unregister_group(group* pgroup);
|
||||
void register_obj(lua_obj* obj, const char* tablename);
|
||||
void register_obj(lua_obj* obj, const char* tablename, bool weak);
|
||||
|
||||
void collect(bool full = false);
|
||||
|
||||
bool load_script(const char* buffer, int len = 0, const char* script_name = nullptr);
|
||||
bool load_card_script(uint32_t code);
|
||||
|
|
@ -93,6 +95,8 @@ public:
|
|||
bool get_function_value(int32_t f, uint32_t param_count, std::vector<lua_Integer>& result);
|
||||
int32_t call_coroutine(int32_t f, uint32_t param_count, lua_Integer* yield_value, uint16_t step);
|
||||
int32_t clone_lua_ref(int32_t lua_ref);
|
||||
int32_t strong_from_weak_ref(int32_t weak_lua_ref);
|
||||
void push_weak_ref(lua_State* L, int32_t weak_lua_ref);
|
||||
void* get_ref_object(int32_t ref_handler);
|
||||
bool call_function(int param_count, int ret_count);
|
||||
inline bool ret_fail(const char* message);
|
||||
|
|
|
|||
36
libcard.cpp
36
libcard.cpp
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
|
||||
* Copyright (c) 2017-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2017-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -217,7 +217,7 @@ LUA_FUNCTION(IsLinkMarker) {
|
|||
LUA_FUNCTION(GetLinkedGroup) {
|
||||
card_set cset;
|
||||
self->get_linked_cards(&cset);
|
||||
group* pgroup = pduel->new_group(cset);
|
||||
auto pgroup = pduel->new_group(cset);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -248,7 +248,7 @@ LUA_FUNCTION(GetFreeLinkedZone) {
|
|||
LUA_FUNCTION(GetMutualLinkedGroup) {
|
||||
card_set cset;
|
||||
self->get_mutual_linked_cards(&cset);
|
||||
group* pgroup = pduel->new_group(cset);
|
||||
auto pgroup = pduel->new_group(cset);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -280,7 +280,7 @@ LUA_FUNCTION(GetColumnGroup) {
|
|||
auto right = lua_get<uint8_t, 0>(L, 3);
|
||||
card_set cset;
|
||||
self->get_column_cards(&cset, left, right);
|
||||
group* pgroup = pduel->new_group(cset);
|
||||
auto pgroup = pduel->new_group(cset);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -888,7 +888,7 @@ LUA_FUNCTION(SetMaterial) {
|
|||
return 0;
|
||||
}
|
||||
LUA_FUNCTION(GetMaterial) {
|
||||
group* pgroup = pduel->new_group(self->material_cards);
|
||||
auto pgroup = pduel->new_group(self->material_cards);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -897,7 +897,7 @@ LUA_FUNCTION(GetMaterialCount) {
|
|||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(GetEquipGroup) {
|
||||
group* pgroup = pduel->new_group(self->equiping_cards);
|
||||
auto pgroup = pduel->new_group(self->equiping_cards);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -939,7 +939,7 @@ LUA_FUNCTION(GetUnionCount) {
|
|||
return 2;
|
||||
}
|
||||
LUA_FUNCTION(GetOverlayGroup) {
|
||||
group* pgroup = pduel->new_group(self->xyz_materials);
|
||||
auto pgroup = pduel->new_group(self->xyz_materials);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -958,7 +958,7 @@ LUA_FUNCTION(CheckRemoveOverlayCard) {
|
|||
return 0;
|
||||
auto count = lua_get<uint16_t>(L, 3);
|
||||
auto reason = lua_get<uint32_t>(L, 4);
|
||||
group* pgroup = pduel->new_group(self);
|
||||
auto pgroup = pduel->new_group(self);
|
||||
lua_pushboolean(L, pduel->game_field->is_player_can_remove_overlay_card(playerid, pgroup, 0, 0, count, reason));
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -971,7 +971,7 @@ LUA_FUNCTION(RemoveOverlayCard) {
|
|||
auto min = lua_get<uint16_t>(L, 3);
|
||||
auto max = lua_get<uint16_t>(L, 4);
|
||||
auto reason = lua_get<uint32_t>(L, 5);
|
||||
group* pgroup = pduel->new_group(self);
|
||||
auto pgroup = pduel->new_group(self);
|
||||
pduel->game_field->remove_overlay_card(reason, pgroup, playerid, 0, 0, min, max);
|
||||
return yieldk({
|
||||
lua_pushinteger(L, pduel->game_field->returns.at<int32_t>(0));
|
||||
|
|
@ -979,7 +979,7 @@ LUA_FUNCTION(RemoveOverlayCard) {
|
|||
});
|
||||
}
|
||||
LUA_FUNCTION(GetAttackedGroup) {
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
for(auto& cit : self->attacked_cards) {
|
||||
if(cit.second.first)
|
||||
pgroup->container.insert(cit.second.first);
|
||||
|
|
@ -996,7 +996,7 @@ LUA_FUNCTION(GetAttackedCount) {
|
|||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(GetBattledGroup) {
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
for(auto& cit : self->battled_cards) {
|
||||
if(cit.second.first)
|
||||
pgroup->container.insert(cit.second.first);
|
||||
|
|
@ -1023,7 +1023,7 @@ LUA_FUNCTION(SetCardTarget) {
|
|||
return 0;
|
||||
}
|
||||
LUA_FUNCTION(GetCardTarget) {
|
||||
group* pgroup = pduel->new_group(self->effect_target_cards);
|
||||
auto pgroup = pduel->new_group(self->effect_target_cards);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1050,7 +1050,7 @@ LUA_FUNCTION(CancelCardTarget) {
|
|||
return 0;
|
||||
}
|
||||
LUA_FUNCTION(GetOwnerTarget) {
|
||||
group* pgroup = pduel->new_group(self->effect_target_owner);
|
||||
auto pgroup = pduel->new_group(self->effect_target_owner);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1383,8 +1383,8 @@ inline int32_t spsummonable_rule(lua_State* L, uint32_t cardtype, uint32_t sumty
|
|||
auto pcard = lua_get<card*, true>(L, 1);
|
||||
if(!(pcard->data.type & cardtype))
|
||||
return 0;
|
||||
group* must = nullptr;
|
||||
group* materials = nullptr;
|
||||
owned_lua<group> must = nullptr;
|
||||
owned_lua<group> materials = nullptr;
|
||||
if(auto [pcard_, pgroup_] = lua_get_card_or_group<true>(L, 2 + offset); pcard_)
|
||||
must = pduel->new_group(pcard_);
|
||||
else if(pgroup_)
|
||||
|
|
@ -1921,10 +1921,10 @@ LUA_FUNCTION(IsCanBeMaterial) {
|
|||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(CheckFusionMaterial) {
|
||||
group* pgroup = nullptr;
|
||||
owned_lua<group> pgroup = nullptr;
|
||||
if(lua_gettop(L) > 1 && !lua_isnoneornil(L, 2))
|
||||
pgroup = lua_get<group*, true>(L, 2);
|
||||
group* cg = nullptr;
|
||||
owned_lua<group> cg = nullptr;
|
||||
if(auto _pcard = lua_get<card*>(L, 3))
|
||||
cg = pduel->new_group(_pcard);
|
||||
else
|
||||
|
|
@ -2045,7 +2045,7 @@ LUA_FUNCTION(GetAttackableTarget) {
|
|||
card_vector targets;
|
||||
bool chain_attack = pduel->game_field->core.chain_attacker_id == self->fieldid;
|
||||
pduel->game_field->get_attack_target(self, &targets, chain_attack);
|
||||
group* newgroup = pduel->new_group(targets);
|
||||
auto newgroup = pduel->new_group(targets);
|
||||
interpreter::pushobject(L, newgroup);
|
||||
lua_pushboolean(L, self->direct_attackable);
|
||||
return 2;
|
||||
|
|
|
|||
78
libduel.cpp
78
libduel.cpp
|
|
@ -274,21 +274,21 @@ inline int32_t spsummon_rule(lua_State* L, uint32_t summon_type, uint32_t offset
|
|||
if(playerid != 0 && playerid != 1)
|
||||
return 0;
|
||||
auto pcard = lua_get<card*, true>(L, 2);
|
||||
group* must = nullptr;
|
||||
owned_lua<group> must = nullptr;
|
||||
if(auto _pcard = lua_get<card*>(L, 3 + offset)) {
|
||||
must = pduel->new_group(_pcard);
|
||||
must->is_readonly = TRUE;
|
||||
must->is_readonly = true;
|
||||
} else if(auto pgroup = lua_get<group*>(L, 3 + offset)) {
|
||||
must = pduel->new_group(pgroup);
|
||||
must->is_readonly = TRUE;
|
||||
must->is_readonly = true;
|
||||
}
|
||||
group* materials = nullptr;
|
||||
owned_lua<group> materials = nullptr;
|
||||
if(auto _pcard = lua_get<card*>(L, 4 + offset)) {
|
||||
materials = pduel->new_group(_pcard);
|
||||
materials->is_readonly = TRUE;
|
||||
materials->is_readonly = true;
|
||||
} else if(auto pgroup = lua_get<group*>(L, 4 + offset)) {
|
||||
materials = pduel->new_group(pgroup);
|
||||
materials->is_readonly = TRUE;
|
||||
materials->is_readonly = true;
|
||||
}
|
||||
auto minc = lua_get<uint16_t, 0>(L, 5 + offset);
|
||||
auto maxc = lua_get<uint16_t, 0>(L, 6 + offset);
|
||||
|
|
@ -561,7 +561,7 @@ LUA_STATIC_FUNCTION(RemoveCards) {
|
|||
return 0;
|
||||
}
|
||||
LUA_STATIC_FUNCTION(GetOperatedGroup) {
|
||||
group* pgroup = pduel->new_group(pduel->game_field->core.operated_set);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->core.operated_set);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1310,7 +1310,7 @@ LUA_STATIC_FUNCTION(DiscardHand) {
|
|||
auto min = lua_get<uint16_t>(L, 3);
|
||||
auto max = lua_get<uint16_t>(L, 4);
|
||||
auto reason = lua_get<uint32_t>(L, 5);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, playerid, LOCATION_HAND, 0, pgroup, pexception, pexgroup, extraargs);
|
||||
pduel->game_field->core.select_cards.assign(pgroup->container.begin(), pgroup->container.end());
|
||||
if(pduel->game_field->core.select_cards.size() == 0) {
|
||||
|
|
@ -1804,7 +1804,7 @@ LUA_STATIC_FUNCTION(GetLinkedGroup) {
|
|||
location2 = LOCATION_MZONE;
|
||||
card_set cset;
|
||||
pduel->game_field->get_linked_cards(rplayer, location1, location2, &cset);
|
||||
group* pgroup = pduel->new_group(std::move(cset));
|
||||
auto pgroup = pduel->new_group(std::move(cset));
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2163,7 +2163,7 @@ LUA_STATIC_FUNCTION(GetFieldGroup) {
|
|||
auto playerid = lua_get<uint8_t>(L, 1);
|
||||
auto location1 = lua_get<uint16_t>(L, 2);
|
||||
auto location2 = lua_get<uint16_t>(L, 3);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_field_card(playerid, location1, location2, pgroup);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2193,7 +2193,7 @@ LUA_STATIC_FUNCTION(GetDecktopGroup) {
|
|||
auto& main = pduel->game_field->player[playerid].list_main;
|
||||
const auto count = std::min<size_t>(lua_get<uint32_t>(L, 2), main.size());
|
||||
const auto offset = main.size() - count;
|
||||
group* pgroup = pduel->new_group(main.begin() + offset, main.end());
|
||||
auto pgroup = pduel->new_group(main.begin() + offset, main.end());
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2202,7 +2202,7 @@ LUA_STATIC_FUNCTION(GetDeckbottomGroup) {
|
|||
auto playerid = lua_get<uint8_t>(L, 1);
|
||||
auto& main = pduel->game_field->player[playerid].list_main;
|
||||
const auto count = std::min<size_t>(lua_get<uint32_t>(L, 2), main.size());
|
||||
group* pgroup = pduel->new_group(main.begin(), main.begin() + count);
|
||||
auto pgroup = pduel->new_group(main.begin(), main.begin() + count);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2215,7 +2215,7 @@ LUA_STATIC_FUNCTION(GetExtraTopGroup) {
|
|||
check_param_count(L, 2);
|
||||
auto playerid = lua_get<uint8_t>(L, 1);
|
||||
auto count = lua_get<uint32_t>(L, 2);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
auto cit = pduel->game_field->player[playerid].list_extra.rbegin() + pduel->game_field->player[playerid].extra_p_count;
|
||||
for(uint32_t i = 0; i < count && cit != pduel->game_field->player[playerid].list_extra.rend(); ++i, ++cit)
|
||||
pgroup->container.insert(*cit);
|
||||
|
|
@ -2238,7 +2238,7 @@ LUA_STATIC_FUNCTION(GetMatchingGroup) {
|
|||
auto self = lua_get<uint8_t>(L, 2);
|
||||
auto location1 = lua_get<uint16_t>(L, 3);
|
||||
auto location2 = lua_get<uint16_t>(L, 4);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, self, location1, location2, pgroup, pexception, pexgroup, extraargs);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2259,7 +2259,7 @@ LUA_STATIC_FUNCTION(GetMatchingGroupCount) {
|
|||
auto self = lua_get<uint8_t>(L, 2);
|
||||
auto location1 = lua_get<uint16_t>(L, 3);
|
||||
auto location2 = lua_get<uint16_t>(L, 4);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, self, location1, location2, pgroup, pexception, pexgroup, extraargs);
|
||||
lua_pushinteger(L, pgroup->container.size());
|
||||
return 1;
|
||||
|
|
@ -2336,7 +2336,7 @@ LUA_STATIC_FUNCTION(SelectMatchingCard) {
|
|||
auto location2 = lua_get<uint16_t>(L, 5);
|
||||
auto min = lua_get<uint16_t>(L, 6);
|
||||
auto max = lua_get<uint16_t>(L, 7);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, self, location1, location2, pgroup, pexception, pexgroup, extraargs);
|
||||
pduel->game_field->core.select_cards.assign(pgroup->container.begin(), pgroup->container.end());
|
||||
pduel->game_field->emplace_process<Processors::SelectCard>(playerid, cancelable, min, max);
|
||||
|
|
@ -2395,7 +2395,7 @@ LUA_STATIC_FUNCTION(GetReleaseGroup) {
|
|||
bool hand = lua_get<bool, false>(L, 2);
|
||||
bool oppo = lua_get<bool, false>(L, 3);
|
||||
const auto reason = lua_get<uint32_t, REASON_COST>(L, 4);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->get_release_list(playerid, &pgroup->container, &pgroup->container, &pgroup->container, hand, 0, 0, nullptr, nullptr, oppo, reason);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2523,7 +2523,7 @@ LUA_STATIC_FUNCTION(SelectReleaseGroupEx) {
|
|||
LUA_STATIC_FUNCTION(GetTributeGroup) {
|
||||
check_param_count(L, 1);
|
||||
auto target = lua_get<card*, true>(L, 1);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->get_summon_release_list(target, &(pgroup->container), &(pgroup->container), &(pgroup->container));
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2599,7 +2599,7 @@ LUA_STATIC_FUNCTION(GetTargetCount) {
|
|||
auto self = lua_get<uint8_t>(L, 2);
|
||||
auto location1 = lua_get<uint16_t>(L, 3);
|
||||
auto location2 = lua_get<uint16_t>(L, 4);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, self, location1, location2, pgroup, pexception, pexgroup, extraargs, nullptr, 0, true);
|
||||
lua_pushinteger(L, pgroup->container.size());
|
||||
return 1;
|
||||
|
|
@ -2655,7 +2655,7 @@ LUA_STATIC_FUNCTION(SelectTarget) {
|
|||
auto max = lua_get<uint16_t>(L, 7);
|
||||
if(pduel->game_field->core.current_chain.size() == 0)
|
||||
return 0;
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->filter_matching_card(findex, self, location1, location2, pgroup, pexception, pexgroup, extraargs, nullptr, 0, true);
|
||||
pduel->game_field->core.select_cards.assign(pgroup->container.begin(), pgroup->container.end());
|
||||
pduel->game_field->emplace_process<Processors::SelectCard>(playerid, cancelable, min, max);
|
||||
|
|
@ -2668,14 +2668,14 @@ LUA_STATIC_FUNCTION(SelectTarget) {
|
|||
if(ch) {
|
||||
if(!ch->target_cards) {
|
||||
ch->target_cards = pduel->new_group();
|
||||
ch->target_cards->is_readonly = TRUE;
|
||||
ch->target_cards->is_readonly = true;
|
||||
}
|
||||
ch->target_cards->container.insert(pduel->game_field->return_cards.list.begin(), pduel->game_field->return_cards.list.end());
|
||||
effect* peffect = ch->triggering_effect;
|
||||
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
|
||||
interpreter::pushobject(L, ch->target_cards);
|
||||
} else {
|
||||
group* pret = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
auto pret = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
for(auto& pcard : pret->container) {
|
||||
pcard->create_relation(*ch);
|
||||
if(peffect->is_flag(EFFECT_FLAG_CARD_TARGET)) {
|
||||
|
|
@ -2698,7 +2698,7 @@ LUA_STATIC_FUNCTION(SelectFusionMaterial) {
|
|||
return 0;
|
||||
auto pcard = lua_get<card*, true>(L, 2);
|
||||
auto pgroup = lua_get<group*, true>(L, 3);
|
||||
group* forced_materials = nullptr;
|
||||
owned_lua<group> forced_materials = nullptr;
|
||||
if(auto pcard_ = lua_get<card*>(L, 4))
|
||||
forced_materials = pduel->new_group(pcard_);
|
||||
else
|
||||
|
|
@ -2706,7 +2706,7 @@ LUA_STATIC_FUNCTION(SelectFusionMaterial) {
|
|||
auto chkf = lua_get<uint32_t, PLAYER_NONE>(L, 5);
|
||||
pduel->game_field->emplace_process<Processors::SelectFusion>(playerid, pgroup, chkf, forced_materials, pcard);
|
||||
return yieldk({
|
||||
group* pgroup = pduel->new_group(pduel->game_field->core.fusion_materials);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->core.fusion_materials);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
});
|
||||
|
|
@ -2723,7 +2723,7 @@ LUA_STATIC_FUNCTION(GetRitualMaterial) {
|
|||
if(playerid != 0 && playerid != 1)
|
||||
return 0;
|
||||
bool check_level = lua_get<bool, true>(L, 2);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->get_ritual_material(playerid, pduel->game_field->core.reason_effect, &pgroup->container, check_level);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2740,7 +2740,7 @@ LUA_STATIC_FUNCTION(GetFusionMaterial) {
|
|||
auto playerid = lua_get<uint8_t>(L, 1);
|
||||
if(playerid != 0 && playerid != 1)
|
||||
return 0;
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->get_fusion_material(playerid, &pgroup->container);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2758,7 +2758,7 @@ LUA_STATIC_FUNCTION(SetSelectedCard) {
|
|||
return 0;
|
||||
}
|
||||
LUA_STATIC_FUNCTION(GrabSelectedCard) {
|
||||
group* pgroup = pduel->new_group(pduel->game_field->core.must_select_cards);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->core.must_select_cards);
|
||||
pduel->game_field->core.must_select_cards.clear();
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -2772,9 +2772,9 @@ LUA_STATIC_FUNCTION(SetTargetCard) {
|
|||
return 0;
|
||||
if(!ch->target_cards) {
|
||||
ch->target_cards = pduel->new_group();
|
||||
ch->target_cards->is_readonly = TRUE;
|
||||
ch->target_cards->is_readonly = true;
|
||||
}
|
||||
group* targets = ch->target_cards;
|
||||
auto targets = ch->target_cards;
|
||||
effect* peffect = ch->triggering_effect;
|
||||
if(peffect->type & EFFECT_TYPE_CONTINUOUS) {
|
||||
if(pcard)
|
||||
|
|
@ -2852,11 +2852,8 @@ LUA_STATIC_FUNCTION(SetOperationInfo) {
|
|||
// and the core always assume the group is exactly 2 cards
|
||||
if(cate == 0x200 && playerid == PLAYER_ALL && opt.op_cards->container.size() != 2)
|
||||
lua_error(L, "Called Duel.SetOperationInfo with CATEGORY_SPECIAL_SUMMON and PLAYER_ALL but the group size wasn't exactly 2.");
|
||||
opt.op_cards->is_readonly = TRUE;
|
||||
opt.op_cards->is_readonly = true;
|
||||
}
|
||||
auto omit = ch->opinfos.find(cate);
|
||||
if(omit != ch->opinfos.end() && omit->second.op_cards)
|
||||
pduel->delete_group(omit->second.op_cards);
|
||||
ch->opinfos[cate] = std::move(opt);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2899,11 +2896,8 @@ LUA_STATIC_FUNCTION(SetPossibleOperationInfo) {
|
|||
optarget opt{ nullptr, count, playerid, param };
|
||||
if(pobj && (pobj->lua_type == LuaParam::CARD || pobj->lua_type == LuaParam::GROUP)) {
|
||||
opt.op_cards = pduel->new_group(pobj);
|
||||
opt.op_cards->is_readonly = TRUE;
|
||||
opt.op_cards->is_readonly = true;
|
||||
}
|
||||
auto omit = ch->possibleopinfos.find(cate);
|
||||
if(omit != ch->possibleopinfos.end() && omit->second.op_cards)
|
||||
pduel->delete_group(omit->second.op_cards);
|
||||
ch->possibleopinfos[cate] = std::move(opt);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2947,15 +2941,7 @@ LUA_STATIC_FUNCTION(ClearOperationInfo) {
|
|||
chain* ch = pduel->game_field->get_chain(ct);
|
||||
if(!ch)
|
||||
return 0;
|
||||
for(auto& oit : ch->opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
ch->opinfos.clear();
|
||||
for(auto& oit : ch->possibleopinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
ch->possibleopinfos.clear();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2986,7 +2972,7 @@ LUA_STATIC_FUNCTION(GetOverlayGroup) {
|
|||
auto self = lua_get<uint8_t>(L, 2);
|
||||
auto oppo = lua_get<uint8_t>(L, 3);
|
||||
group* targetsgroup = lua_get<group*>(L, 4);
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
pduel->game_field->get_overlay_group(rplayer, self, oppo, &pgroup->container, targetsgroup);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
|
|||
41
libgroup.cpp
41
libgroup.cpp
|
|
@ -25,13 +25,13 @@ namespace {
|
|||
using namespace scriptlib;
|
||||
|
||||
void assert_readonly_group(lua_State* L, group* pgroup) {
|
||||
if(pgroup->is_readonly != 1)
|
||||
if(!pgroup->is_readonly)
|
||||
return;
|
||||
lua_error(L, "attempt to modify a read only group");
|
||||
}
|
||||
|
||||
LUA_STATIC_FUNCTION(CreateGroup) {
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
lua_iterate_table_or_stack(L, 1, lua_gettop(L), [L, &container = pgroup->container] {
|
||||
if(!lua_isnil(L, -1)) {
|
||||
auto pcard = lua_get<card*, true>(L, -1);
|
||||
|
|
@ -43,22 +43,14 @@ LUA_STATIC_FUNCTION(CreateGroup) {
|
|||
}
|
||||
LUA_FUNCTION_ALIAS(FromCards);
|
||||
LUA_FUNCTION(Clone) {
|
||||
group* newgroup = pduel->new_group(self);
|
||||
auto newgroup = pduel->new_group(self);
|
||||
interpreter::pushobject(L, newgroup);
|
||||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(DeleteGroup) {
|
||||
if(self->is_readonly != 2)
|
||||
return 0;
|
||||
self->is_readonly = 0;
|
||||
pduel->sgroups.insert(self);
|
||||
return 0;
|
||||
}
|
||||
LUA_FUNCTION(KeepAlive) {
|
||||
if(self->is_readonly != 1) {
|
||||
self->is_readonly = 2;
|
||||
pduel->sgroups.erase(self);
|
||||
}
|
||||
interpreter::pushobject(L, self);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -140,7 +132,7 @@ LUA_FUNCTION(Filter) {
|
|||
for(auto& pcard : pexgroup->container)
|
||||
cset.erase(pcard);
|
||||
}
|
||||
group* new_group = pduel->new_group();
|
||||
auto new_group = pduel->new_group();
|
||||
uint32_t extraargs = lua_gettop(L) - 3;
|
||||
for(auto& pcard : cset) {
|
||||
if(pduel->lua->check_matching(pcard, findex, extraargs)) {
|
||||
|
|
@ -313,7 +305,7 @@ LUA_FUNCTION(RandomSelect) {
|
|||
check_param_count(L, 3);
|
||||
auto playerid = lua_get<uint8_t>(L, 2);
|
||||
size_t count = lua_get<uint32_t>(L, 3);
|
||||
group* newgroup = pduel->new_group();
|
||||
auto newgroup = pduel->new_group();
|
||||
if(count > self->container.size())
|
||||
count = self->container.size();
|
||||
if(count == 0) {
|
||||
|
|
@ -422,13 +414,13 @@ LUA_FUNCTION(SelectWithSumEqual) {
|
|||
}
|
||||
if(!field::check_with_sum_limit_m(cv, acc, 0, min, max, mcount, nullptr)) {
|
||||
pduel->game_field->core.must_select_cards.clear();
|
||||
group* empty_group = pduel->new_group();
|
||||
auto empty_group = pduel->new_group();
|
||||
interpreter::pushobject(L, empty_group);
|
||||
return 1;
|
||||
}
|
||||
pduel->game_field->emplace_process<Processors::SelectSum>(playerid, acc, min, max);
|
||||
return yieldk({
|
||||
group* pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
pduel->game_field->core.must_select_cards.clear();
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -482,13 +474,13 @@ LUA_FUNCTION(SelectWithSumGreater) {
|
|||
}
|
||||
if(!field::check_with_sum_greater_limit_m(cv, acc, 0, 0xffff, mcount, nullptr)) {
|
||||
pduel->game_field->core.must_select_cards.clear();
|
||||
group* empty_group = pduel->new_group();
|
||||
auto empty_group = pduel->new_group();
|
||||
interpreter::pushobject(L, empty_group);
|
||||
return 1;
|
||||
}
|
||||
pduel->game_field->emplace_process<Processors::SelectSum>(playerid, acc, 0, 0);
|
||||
return yieldk({
|
||||
group* pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
pduel->game_field->core.must_select_cards.clear();
|
||||
interpreter::pushobject(L, pgroup);
|
||||
return 1;
|
||||
|
|
@ -499,7 +491,7 @@ LUA_FUNCTION(GetMinGroup) {
|
|||
const auto findex = lua_get<function, true>(L, 2);
|
||||
if(self->container.size() == 0)
|
||||
return 0;
|
||||
group* newgroup = pduel->new_group();
|
||||
auto newgroup = pduel->new_group();
|
||||
int64_t min, op;
|
||||
int32_t extraargs = lua_gettop(L) - 2;
|
||||
auto cit = self->container.begin();
|
||||
|
|
@ -525,7 +517,7 @@ LUA_FUNCTION(GetMaxGroup) {
|
|||
const auto findex = lua_get<function, true>(L, 2);
|
||||
if(self->container.size() == 0)
|
||||
return 0;
|
||||
group* newgroup = pduel->new_group();
|
||||
auto newgroup = pduel->new_group();
|
||||
int64_t max, op;
|
||||
int32_t extraargs = lua_gettop(L) - 2;
|
||||
auto cit = self->container.begin();
|
||||
|
|
@ -669,8 +661,9 @@ std::tuple<group*, group*, card*> get_binary_op_group_card_parameters(lua_State*
|
|||
}
|
||||
LUA_STATIC_FUNCTION(__band) {
|
||||
check_param_count(L, 2);
|
||||
auto [pgroup1, pgroup2, pcard] = get_binary_op_group_card_parameters(L);
|
||||
card_set cset;
|
||||
if(auto [pgroup1, pgroup2, pcard] = get_binary_op_group_card_parameters(L); pcard) {
|
||||
if(pcard) {
|
||||
if(pgroup1->has_card(pcard)) {
|
||||
cset.insert(pcard);
|
||||
}
|
||||
|
|
@ -684,7 +677,7 @@ LUA_STATIC_FUNCTION(__band) {
|
|||
LUA_STATIC_FUNCTION(__add) {
|
||||
check_param_count(L, 2);
|
||||
auto [pgroup1, pgroup2, pcard] = get_binary_op_group_card_parameters(L);
|
||||
group* newgroup = pduel->new_group(pgroup1);
|
||||
auto newgroup = pduel->new_group(pgroup1);
|
||||
if(pcard) {
|
||||
newgroup->container.insert(pcard);
|
||||
} else {
|
||||
|
|
@ -696,7 +689,7 @@ LUA_STATIC_FUNCTION(__add) {
|
|||
LUA_FUNCTION(__sub) {
|
||||
check_param_count(L, 2);
|
||||
auto [pcard, pgroup] = lua_get_card_or_group(L, 2);
|
||||
group* newgroup = pduel->new_group(self);
|
||||
auto newgroup = pduel->new_group(self);
|
||||
if(pgroup) {
|
||||
for(auto& _pcard : pgroup->container)
|
||||
newgroup->container.erase(_pcard);
|
||||
|
|
@ -733,6 +726,10 @@ LUA_FUNCTION(__le) {
|
|||
lua_pushboolean(L, self->container.size() <= sgroup->container.size());
|
||||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(__gc) {
|
||||
pduel->delete_group(self);
|
||||
return 1;
|
||||
}
|
||||
LUA_FUNCTION(IsContains) {
|
||||
check_param_count(L, 2);
|
||||
auto pcard = lua_get<card*, true>(L, 2);
|
||||
|
|
|
|||
72
lua_obj.h
72
lua_obj.h
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2020-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
#define LUA_OBJ_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility> // std::exchange
|
||||
|
||||
enum class LuaParam : uint8_t {
|
||||
INT = 1,
|
||||
|
|
@ -21,14 +22,83 @@ enum class LuaParam : uint8_t {
|
|||
};
|
||||
|
||||
class duel;
|
||||
template<typename T>
|
||||
class owned_lua;
|
||||
|
||||
class lua_obj {
|
||||
template<typename T>
|
||||
friend class owned_lua;
|
||||
public:
|
||||
duel* pduel{ nullptr };
|
||||
int32_t ref_handle{};
|
||||
int32_t weak_ref_handle{};
|
||||
LuaParam lua_type;
|
||||
protected:
|
||||
lua_obj(LuaParam _lua_type, duel* _pduel) :pduel(_pduel), lua_type(_lua_type) {}
|
||||
private:
|
||||
int num_ref{};
|
||||
void incr_ref();
|
||||
void decr_ref();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class owned_lua {
|
||||
T* obj{};
|
||||
owned_lua<T>& assign(T* other) {
|
||||
if(obj) {
|
||||
obj->decr_ref();
|
||||
}
|
||||
obj = other;
|
||||
if(obj) {
|
||||
obj->incr_ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
using lua_type = T*;
|
||||
owned_lua() = default;
|
||||
owned_lua(T* obj_) : obj(obj_) {
|
||||
if(obj) {
|
||||
obj->incr_ref();
|
||||
}
|
||||
}
|
||||
owned_lua(const owned_lua<T>& other) : owned_lua(other.obj) {}
|
||||
owned_lua(owned_lua<T>&& other) : obj(other.obj) {
|
||||
other.obj = nullptr;
|
||||
}
|
||||
~owned_lua() {
|
||||
if(obj) {
|
||||
obj->decr_ref();
|
||||
}
|
||||
}
|
||||
owned_lua<T>& operator=(owned_lua<T>&& rhs) {
|
||||
if(obj) {
|
||||
obj->decr_ref();
|
||||
}
|
||||
obj = std::exchange(rhs.obj, nullptr);
|
||||
return *this;
|
||||
}
|
||||
owned_lua<T>& operator=(const owned_lua<T>& rhs) {
|
||||
return assign(rhs.obj);
|
||||
}
|
||||
owned_lua<T>& operator=(T* rhs) {
|
||||
return assign(rhs);
|
||||
}
|
||||
operator T* () const {
|
||||
return obj;
|
||||
}
|
||||
T* operator-> () const {
|
||||
return obj;
|
||||
}
|
||||
bool operator ==(const owned_lua<T>& other) const {
|
||||
return obj == other.obj;
|
||||
}
|
||||
bool operator <(const owned_lua<T>& other) const {
|
||||
return obj < other.obj;
|
||||
}
|
||||
explicit operator bool() const {
|
||||
return obj != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<LuaParam _Type>
|
||||
|
|
|
|||
120
operations.cpp
120
operations.cpp
|
|
@ -81,7 +81,7 @@ void field::change_target(uint8_t chaincount, group* targets) {
|
|||
return;
|
||||
if(chaincount > core.current_chain.size() || chaincount < 1)
|
||||
chaincount = static_cast<uint8_t>(core.current_chain.size());
|
||||
group* ot = core.current_chain[chaincount - 1].target_cards;
|
||||
auto ot = core.current_chain[chaincount - 1].target_cards;
|
||||
if(ot) {
|
||||
effect* te = core.current_chain[chaincount - 1].triggering_effect;
|
||||
for(auto& pcard : ot->container)
|
||||
|
|
@ -119,26 +119,26 @@ void field::remove_overlay_card(uint32_t reason, group* pgroup, uint32_t rplayer
|
|||
emplace_process<Processors::RemoveOverlay>(reason, pgroup, rplayer, self, oppo, min, max);
|
||||
}
|
||||
void field::xyz_overlay(card* target, card_set materials, bool send_materials_to_grave) {
|
||||
group* ng = pduel->new_group(std::move(materials));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(materials));
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::XyzOverlay>(target, ng, send_materials_to_grave);
|
||||
}
|
||||
void field::xyz_overlay(card* target, card* material, bool send_materials_to_grave) {
|
||||
xyz_overlay(target, card_set{ material }, send_materials_to_grave);
|
||||
}
|
||||
void field::get_control(card_set targets, effect* reason_effect, uint8_t chose_player, uint8_t playerid, uint16_t reset_phase, uint8_t reset_count, uint32_t zone) {
|
||||
group* ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::GetControl>(reason_effect, chose_player, ng, playerid, reset_phase, reset_count, zone);
|
||||
}
|
||||
void field::get_control(card* target, effect* reason_effect, uint8_t chose_player, uint8_t playerid, uint16_t reset_phase, uint8_t reset_count, uint32_t zone) {
|
||||
get_control(card_set{ target }, reason_effect, chose_player, playerid, reset_phase, reset_count, zone);
|
||||
}
|
||||
void field::swap_control(effect* reason_effect, uint32_t reason_player, card_set targets1, card_set targets2, uint32_t reset_phase, uint32_t reset_count) {
|
||||
group* ng1 = pduel->new_group(std::move(targets1));
|
||||
ng1->is_readonly = TRUE;
|
||||
group* ng2 = pduel->new_group(std::move(targets2));
|
||||
ng2->is_readonly = TRUE;
|
||||
auto ng1 = pduel->new_group(std::move(targets1));
|
||||
ng1->is_readonly = true;
|
||||
auto ng2 = pduel->new_group(std::move(targets2));
|
||||
ng2->is_readonly = true;
|
||||
emplace_process<Processors::SwapControl>(reason_effect, reason_player, ng1, ng2, reset_phase, reset_count);
|
||||
}
|
||||
void field::swap_control(effect* reason_effect, uint32_t reason_player, card* pcard1, card* pcard2, uint32_t reset_phase, uint32_t reset_count) {
|
||||
|
|
@ -206,8 +206,8 @@ void field::special_summon(card_set target, uint32_t sumtype, uint8_t sumplayer,
|
|||
}
|
||||
pcard->spsummon_param = (playerid << 24) + (nocheck << 16) + (nolimit << 8) + pos;
|
||||
}
|
||||
group* pgroup = pduel->new_group(std::move(target));
|
||||
pgroup->is_readonly = TRUE;
|
||||
auto pgroup = pduel->new_group(std::move(target));
|
||||
pgroup->is_readonly = true;
|
||||
emplace_process<Processors::SpSummon>(core.reason_effect, core.reason_player, pgroup, zone);
|
||||
}
|
||||
void field::special_summon_step(card* target, uint32_t sumtype, uint8_t sumplayer, uint8_t playerid, bool nocheck, bool nolimit, uint8_t positions, uint32_t zone) {
|
||||
|
|
@ -246,9 +246,9 @@ void field::special_summon_step(card* target, uint32_t sumtype, uint8_t sumplaye
|
|||
emplace_process<Processors::SpSummonStep>(nullptr, target, zone);
|
||||
}
|
||||
void field::special_summon_complete(effect* reason_effect, uint8_t reason_player) {
|
||||
group* ng = pduel->new_group();
|
||||
ng->container.swap(core.special_summoning);
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(core.special_summoning));
|
||||
core.special_summoning.clear();
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::SpSummon>(Step{ 1 }, reason_effect, reason_player, ng, 0);
|
||||
}
|
||||
void field::destroy(card_set targets, effect* reason_effect, uint32_t reason, uint8_t reason_player, uint8_t playerid, uint16_t destination, uint32_t sequence) {
|
||||
|
|
@ -279,8 +279,8 @@ void field::destroy(card_set targets, effect* reason_effect, uint32_t reason, ui
|
|||
pcard->sendto_param.set(p, POS_FACEUP, destination, sequence);
|
||||
++cit;
|
||||
}
|
||||
group* ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::Destroy>(ng, reason_effect, reason, reason_player);
|
||||
}
|
||||
void field::destroy(card* target, effect* reason_effect, uint32_t reason, uint8_t reason_player, uint8_t playerid, uint16_t destination, uint32_t sequence) {
|
||||
|
|
@ -296,8 +296,8 @@ void field::release(card_set targets, effect* reason_effect, uint32_t reason, ui
|
|||
pcard->current.reason_player = reason_player;
|
||||
pcard->sendto_param.set(pcard->owner, POS_FACEUP, LOCATION_GRAVE);
|
||||
}
|
||||
group* ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::Release>(ng, reason_effect, reason, reason_player);
|
||||
}
|
||||
void field::release(card* target, effect* reason_effect, uint32_t reason, uint8_t reason_player) {
|
||||
|
|
@ -330,8 +330,8 @@ void field::send_to(card_set targets, effect* reason_effect, uint32_t reason, ui
|
|||
pos = pcard->current.position;
|
||||
pcard->sendto_param.set(p, pos, destination, sequence);
|
||||
}
|
||||
group* ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::SendTo>(ng, reason_effect, reason, reason_player);
|
||||
}
|
||||
void field::send_to(card* target, effect* reason_effect, uint32_t reason, uint8_t reason_player, uint8_t playerid, uint16_t destination, uint32_t sequence, uint8_t position, bool ignore) {
|
||||
|
|
@ -369,8 +369,8 @@ void field::move_to_field(card* target, uint8_t move_player, uint8_t playerid, u
|
|||
emplace_process<Processors::MoveToField>(target, enable, ret, pzone, zone, rule, reason, confirm);
|
||||
}
|
||||
void field::change_position(card_set targets, effect* reason_effect, uint8_t reason_player, uint8_t au, uint8_t ad, uint8_t du, uint8_t dd, uint32_t flag, bool enable) {
|
||||
group* ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(std::move(targets));
|
||||
ng->is_readonly = true;
|
||||
for(auto& pcard : ng->container) {
|
||||
if(pcard->current.position == POS_FACEUP_ATTACK)
|
||||
pcard->position_param = au;
|
||||
|
|
@ -385,8 +385,8 @@ void field::change_position(card_set targets, effect* reason_effect, uint8_t rea
|
|||
emplace_process<Processors::ChangePos>(ng, reason_effect, reason_player, enable);
|
||||
}
|
||||
void field::change_position(card* target, effect* reason_effect, uint8_t reason_player, uint8_t npos, uint32_t flag, bool enable) {
|
||||
group* ng = pduel->new_group(target);
|
||||
ng->is_readonly = TRUE;
|
||||
auto ng = pduel->new_group(target);
|
||||
ng->is_readonly = true;
|
||||
target->position_param = npos;
|
||||
target->position_param |= flag;
|
||||
emplace_process<Processors::ChangePos>(ng, reason_effect, reason_player, enable);
|
||||
|
|
@ -1174,7 +1174,6 @@ bool field::process(Processors::GetControl& arg) {
|
|||
case 7: {
|
||||
core.operated_set = targets->container;
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(targets->container.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1327,15 +1326,11 @@ bool field::process(Processors::SwapControl& arg) {
|
|||
case 5: {
|
||||
core.operated_set = targets1->container;
|
||||
returns.set<int32_t>(0, 1);
|
||||
pduel->delete_group(targets1);
|
||||
pduel->delete_group(targets2);
|
||||
return TRUE;
|
||||
}
|
||||
case 10: {
|
||||
core.operated_set.clear();
|
||||
returns.set<int32_t>(0, 0);
|
||||
pduel->delete_group(targets1);
|
||||
pduel->delete_group(targets2);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -2999,8 +2994,8 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
switch(arg.step) {
|
||||
case 0: {
|
||||
effect_set eset;
|
||||
group* must_mats = core.must_use_mats;
|
||||
group* materials = core.only_use_mats;
|
||||
auto must_mats = core.must_use_mats;
|
||||
auto materials = core.only_use_mats;
|
||||
int32_t minc = core.forced_summon_minc;
|
||||
int32_t maxc = core.forced_summon_maxc;
|
||||
target->filter_spsummon_procedure(sumplayer, &eset, summon_type);
|
||||
|
|
@ -3077,14 +3072,8 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 4: {
|
||||
if(core.must_use_mats) {
|
||||
pduel->delete_group(core.must_use_mats);
|
||||
core.must_use_mats = nullptr;
|
||||
}
|
||||
if(core.only_use_mats) {
|
||||
pduel->delete_group(core.only_use_mats);
|
||||
core.only_use_mats = nullptr;
|
||||
}
|
||||
core.must_use_mats = nullptr;
|
||||
core.only_use_mats = nullptr;
|
||||
auto proc = arg.summon_proc_effect;
|
||||
uint8_t targetplayer = sumplayer;
|
||||
uint8_t positions = POS_FACEUP;
|
||||
|
|
@ -3275,7 +3264,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 21: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ) {
|
||||
card* pcard = *cit++;
|
||||
if(!(pcard->data.type & TYPE_MONSTER)
|
||||
|
|
@ -3297,7 +3286,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 22: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
if(pgroup->container.size() == 0)
|
||||
return TRUE;
|
||||
core.phase_action = true;
|
||||
|
|
@ -3306,7 +3295,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
}
|
||||
case 23: {
|
||||
auto proc = arg.summon_proc_effect;
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
card* pcard = *pgroup->it;
|
||||
pcard->enable_field_effect(false);
|
||||
pcard->current.reason = REASON_SPSUMMON;
|
||||
|
|
@ -3359,7 +3348,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 24: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
card* pcard = *pgroup->it++;
|
||||
auto message = pduel->new_message(MSG_SPSUMMONING);
|
||||
message->write<uint32_t>(pcard->data.code);
|
||||
|
|
@ -3371,7 +3360,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 25: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
if(is_flag(DUEL_CANNOT_SUMMON_OATH_OLD)) {
|
||||
set_spsummon_counter(sumplayer);
|
||||
}
|
||||
|
|
@ -3406,7 +3395,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 26: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
card_set cset;
|
||||
for(auto cit = pgroup->container.begin(); cit != pgroup->container.end(); ) {
|
||||
card* pcard = *cit++;
|
||||
|
|
@ -3436,7 +3425,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 27: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
release_oath_relation(arg.summon_proc_effect);
|
||||
for(const auto& peffect : arg.spsummon_cost_effects)
|
||||
release_oath_relation(peffect);
|
||||
|
|
@ -3450,7 +3439,7 @@ bool field::process(Processors::SpSummonRule& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 28: {
|
||||
group* pgroup = arg.cards_to_summon_g;
|
||||
auto pgroup = arg.cards_to_summon_g;
|
||||
pduel->new_message(MSG_SPSUMMONED);
|
||||
if(!is_flag(DUEL_CANNOT_SUMMON_OATH_OLD)) {
|
||||
set_spsummon_counter(sumplayer);
|
||||
|
|
@ -3685,7 +3674,6 @@ bool field::process(Processors::SpSummon& arg) {
|
|||
if(targets->container.size() == 0) {
|
||||
returns.set<int32_t>(0, 0);
|
||||
core.operated_set.clear();
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
bool tp = false, ntp = false;
|
||||
|
|
@ -3753,7 +3741,6 @@ bool field::process(Processors::SpSummon& arg) {
|
|||
core.operated_set.clear();
|
||||
core.operated_set = targets->container;
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(targets->container.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -3940,7 +3927,6 @@ bool field::process(Processors::Destroy& arg) {
|
|||
if(!targets->container.size()) {
|
||||
returns.set<int32_t>(0, 0);
|
||||
core.operated_set.clear();
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
card_vector cv(targets->container.begin(), targets->container.end());
|
||||
|
|
@ -3965,8 +3951,8 @@ bool field::process(Processors::Destroy& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 4: {
|
||||
group* sendtargets = pduel->new_group(targets->container);
|
||||
sendtargets->is_readonly = TRUE;
|
||||
auto sendtargets = pduel->new_group(targets->container);
|
||||
sendtargets->is_readonly = true;
|
||||
for(auto& pcard : sendtargets->container) {
|
||||
pcard->set_status(STATUS_DESTROY_CONFIRMED, FALSE);
|
||||
uint32_t dest = pcard->sendto_param.location;
|
||||
|
|
@ -3992,7 +3978,6 @@ bool field::process(Processors::Destroy& arg) {
|
|||
++cit;
|
||||
}
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(core.operated_set.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
case 10: {
|
||||
|
|
@ -4178,7 +4163,6 @@ bool field::process(Processors::Release& arg) {
|
|||
if(!targets->container.size()) {
|
||||
returns.set<int32_t>(0, 0);
|
||||
core.operated_set.clear();
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
card_vector cv(targets->container.begin(), targets->container.end());
|
||||
|
|
@ -4204,8 +4188,8 @@ bool field::process(Processors::Release& arg) {
|
|||
message->write<uint8_t>(0);
|
||||
message->write<uint64_t>(peffect->get_handler()->data.code);
|
||||
}
|
||||
group* sendtargets = pduel->new_group(targets->container);
|
||||
sendtargets->is_readonly = TRUE;
|
||||
auto sendtargets = pduel->new_group(targets->container);
|
||||
sendtargets->is_readonly = true;
|
||||
operation_replace(EFFECT_SEND_REPLACE, 5, sendtargets);
|
||||
emplace_process<Processors::SendTo>(Step{ 1 }, sendtargets, reason_effect, reason | REASON_RELEASE, reason_player);
|
||||
return FALSE;
|
||||
|
|
@ -4217,7 +4201,6 @@ bool field::process(Processors::Release& arg) {
|
|||
core.operated_set.clear();
|
||||
core.operated_set = targets->container;
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(targets->container.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -4287,7 +4270,6 @@ bool field::process(Processors::SendTo& arg) {
|
|||
if(!targets->container.size()) {
|
||||
returns.set<int32_t>(0, 0);
|
||||
core.operated_set.clear();
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
card_set leave_p, destroying;
|
||||
|
|
@ -4568,7 +4550,7 @@ bool field::process(Processors::SendTo& arg) {
|
|||
param->leave_field.insert(pcard);
|
||||
}
|
||||
if(param->predirect->operation) {
|
||||
tevent e;
|
||||
tevent e{};
|
||||
e.event_cards = targets;
|
||||
e.event_player = pcard->current.controler;
|
||||
e.event_value = 0;
|
||||
|
|
@ -4743,7 +4725,6 @@ bool field::process(Processors::SendTo& arg) {
|
|||
core.operated_set.clear();
|
||||
core.operated_set = targets->container;
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(targets->container.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -5360,7 +5341,6 @@ bool field::process(Processors::ChangePos& arg) {
|
|||
core.operated_set.clear();
|
||||
core.operated_set = targets->container;
|
||||
returns.set<int32_t>(0, static_cast<int32_t>(targets->container.size()));
|
||||
pduel->delete_group(targets);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -5426,12 +5406,6 @@ bool field::process(Processors::OperationReplace& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 3: {
|
||||
if(core.continuous_chain.back().target_cards)
|
||||
pduel->delete_group(core.continuous_chain.back().target_cards);
|
||||
for(auto& oit : core.continuous_chain.back().opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
core.continuous_chain.pop_back();
|
||||
core.solving_event.pop_front();
|
||||
return TRUE;
|
||||
|
|
@ -5492,12 +5466,6 @@ bool field::process(Processors::OperationReplace& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 8: {
|
||||
if(core.continuous_chain.back().target_cards)
|
||||
pduel->delete_group(core.continuous_chain.back().target_cards);
|
||||
for(auto& oit : core.continuous_chain.back().opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
core.continuous_chain.pop_back();
|
||||
core.solving_event.pop_front();
|
||||
return TRUE;
|
||||
|
|
@ -5606,12 +5574,6 @@ bool field::process(Processors::OperationReplace& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 16: {
|
||||
if(core.continuous_chain.back().target_cards)
|
||||
pduel->delete_group(core.continuous_chain.back().target_cards);
|
||||
for(auto& oit : core.continuous_chain.back().opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
core.continuous_chain.pop_back();
|
||||
arg.step = 14;
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
|
||||
* Copyright (c) 2016-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2016-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -197,8 +197,8 @@ void field::raise_event(card* event_card, uint32_t event_code, effect* reason_ef
|
|||
auto& new_event = core.queue_event.emplace_back();
|
||||
new_event.trigger_card = nullptr;
|
||||
if (event_card) {
|
||||
group* pgroup = pduel->new_group(event_card);
|
||||
pgroup->is_readonly = TRUE;
|
||||
auto pgroup = pduel->new_group(event_card);
|
||||
pgroup->is_readonly = true;
|
||||
new_event.event_cards = pgroup;
|
||||
} else
|
||||
new_event.event_cards = nullptr;
|
||||
|
|
@ -213,8 +213,8 @@ void field::raise_event(card* event_card, uint32_t event_code, effect* reason_ef
|
|||
void field::raise_event(card_set event_cards, uint32_t event_code, effect* reason_effect, uint32_t reason, uint8_t reason_player, uint8_t event_player, uint32_t event_value) {
|
||||
auto& new_event = core.queue_event.emplace_back();
|
||||
new_event.trigger_card = nullptr;
|
||||
group* pgroup = pduel->new_group(std::move(event_cards));
|
||||
pgroup->is_readonly = TRUE;
|
||||
auto pgroup = pduel->new_group(std::move(event_cards));
|
||||
pgroup->is_readonly = true;
|
||||
new_event.event_cards = pgroup;
|
||||
new_event.event_code = event_code;
|
||||
new_event.reason_effect = reason_effect;
|
||||
|
|
@ -228,8 +228,8 @@ void field::raise_single_event(card* trigger_card, card_set* event_cards, uint32
|
|||
auto& new_event = core.single_event.emplace_back();
|
||||
new_event.trigger_card = trigger_card;
|
||||
if (event_cards) {
|
||||
group* pgroup = pduel->new_group(*event_cards);
|
||||
pgroup->is_readonly = TRUE;
|
||||
auto pgroup = pduel->new_group(*event_cards);
|
||||
pgroup->is_readonly = true;
|
||||
new_event.event_cards = pgroup;
|
||||
} else
|
||||
new_event.event_cards = nullptr;
|
||||
|
|
@ -2554,9 +2554,9 @@ bool field::process(Processors::BattleCommand& arg) {
|
|||
core.battle_destroy_rep.clear();
|
||||
core.desrep_chain.clear();
|
||||
if(des.size()) {
|
||||
group* ng = pduel->new_group();
|
||||
auto ng = pduel->new_group();
|
||||
ng->container.swap(des);
|
||||
ng->is_readonly = TRUE;
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::Destroy>(Step{ 10 }, ng, nullptr, REASON_BATTLE, PLAYER_NONE);
|
||||
arg.cards_destroyed_by_battle = ng;
|
||||
}
|
||||
|
|
@ -2571,7 +2571,7 @@ bool field::process(Processors::BattleCommand& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 30: {
|
||||
group* des = arg.cards_destroyed_by_battle;
|
||||
auto des = arg.cards_destroyed_by_battle;
|
||||
if(des && des->container.size()) {
|
||||
for(auto& pcard : des->container) {
|
||||
pcard->set_status(STATUS_BATTLE_DESTROYED, TRUE);
|
||||
|
|
@ -2636,7 +2636,7 @@ bool field::process(Processors::BattleCommand& arg) {
|
|||
return FALSE;
|
||||
}
|
||||
case 33: {
|
||||
group* des = arg.cards_destroyed_by_battle;
|
||||
auto des = arg.cards_destroyed_by_battle;
|
||||
if(des) {
|
||||
for(auto cit = des->container.begin(); cit != des->container.end();) {
|
||||
auto rm = cit++;
|
||||
|
|
@ -3255,10 +3255,6 @@ bool field::process(Processors::Turn& arg) {
|
|||
switch(arg.step) {
|
||||
case 0: {
|
||||
//Pre Draw
|
||||
for(const auto& ev : core.used_event) {
|
||||
if(ev.event_cards)
|
||||
pduel->delete_group(ev.event_cards);
|
||||
}
|
||||
core.used_event.clear();
|
||||
for(auto& peffect : core.reseted_effects) {
|
||||
pduel->delete_effect(peffect);
|
||||
|
|
@ -4052,12 +4048,6 @@ bool field::process(Processors::SolveContinuous& arg) {
|
|||
effect* peffect = clit.triggering_effect;
|
||||
core.reason_effect = arg.reason_effect;
|
||||
core.reason_player = arg.reason_player;
|
||||
if(core.continuous_chain.back().target_cards)
|
||||
pduel->delete_group(core.continuous_chain.back().target_cards);
|
||||
for(auto& oit : core.continuous_chain.back().opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
core.continuous_chain.pop_back();
|
||||
core.solving_continuous.pop_front();
|
||||
if(peffect->is_flag(EFFECT_FLAG_DELAY) || (!(peffect->code & 0xfffff000u) && (peffect->code & (EVENT_PHASE | EVENT_PHASE_START)))) {
|
||||
|
|
@ -4308,12 +4298,6 @@ bool field::process(Processors::SolveChain& arg) {
|
|||
peffect->active_type = 0;
|
||||
peffect->active_handler = nullptr;
|
||||
pcard->release_relation(*cait);
|
||||
if(cait->target_cards)
|
||||
pduel->delete_group(cait->target_cards);
|
||||
for(auto& oit : cait->opinfos) {
|
||||
if(oit.second.op_cards)
|
||||
pduel->delete_group(oit.second.op_cards);
|
||||
}
|
||||
for(auto& cit : core.delayed_enable_set) {
|
||||
if(cit->current.location == LOCATION_MZONE)
|
||||
cit->enable_field_effect(true);
|
||||
|
|
@ -4899,9 +4883,9 @@ bool field::process(Processors::Adjust& arg) {
|
|||
}
|
||||
if(pos_adjust.size()) {
|
||||
core.re_adjust = true;
|
||||
group* ng = pduel->new_group();
|
||||
auto ng = pduel->new_group();
|
||||
ng->container.swap(pos_adjust);
|
||||
ng->is_readonly = TRUE;
|
||||
ng->is_readonly = true;
|
||||
emplace_process<Processors::ChangePos>(ng, nullptr, PLAYER_NONE, true);
|
||||
}
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <memory> //std::unique_ptr
|
||||
#include <type_traits> //std::false_type, std::true_type
|
||||
#include <variant>
|
||||
#include "lua_obj.h"
|
||||
#include "common.h"
|
||||
#include "containers_fwd.h"
|
||||
|
||||
|
|
@ -237,10 +238,10 @@ struct BattleCommand : public Process<false> {
|
|||
bool previous_point_event_had_any_trigger_to_resolve;
|
||||
uint8_t reason_player;
|
||||
effect* damage_change_effect;
|
||||
group* cards_destroyed_by_battle;
|
||||
owned_lua<group> cards_destroyed_by_battle;
|
||||
card* reason_card;
|
||||
std::multimap<effect*, card*> must_attack_map;
|
||||
BattleCommand(uint16_t step_, group* cards_destroyed_by_battle_ = nullptr, bool forced_attack_ = false) :
|
||||
BattleCommand(uint16_t step_, owned_lua<group> cards_destroyed_by_battle_ = nullptr, bool forced_attack_ = false) :
|
||||
Process(step_), phase_to_change_to(0), forced_attack(forced_attack_), forced_attack_done(false), is_replaying_attack(false), attack_announce_failed(false),
|
||||
repeat_battle_phase(false), second_battle_phase_is_optional(false),
|
||||
previous_point_event_had_any_trigger_to_resolve(false), reason_player(PLAYER_NONE), damage_change_effect(nullptr),
|
||||
|
|
@ -251,7 +252,7 @@ struct DamageStep : public Process<false> {
|
|||
bool new_attack;
|
||||
card* attacker;
|
||||
card* attack_target;
|
||||
group* cards_destroyed_by_battle;
|
||||
owned_lua<group> cards_destroyed_by_battle;
|
||||
DamageStep(uint16_t step_, card* attacker_, card* attack_target_, bool new_attack_) :
|
||||
Process(step_), backup_phase(0), new_attack(new_attack_), attacker(attacker_), attack_target(attack_target_), cards_destroyed_by_battle(nullptr) {}
|
||||
};
|
||||
|
|
@ -307,9 +308,9 @@ struct ExecuteTarget : public Process<false> {
|
|||
struct Destroy : public Process<false> {
|
||||
uint8_t reason_player;
|
||||
uint32_t reason;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
effect* reason_effect;
|
||||
Destroy(uint16_t step_, group* targets_, effect* reason_effect_, uint32_t reason_,
|
||||
Destroy(uint16_t step_, owned_lua<group> targets_, effect* reason_effect_, uint32_t reason_,
|
||||
uint8_t reason_player_) :
|
||||
Process(step_), reason_player(reason_player_), reason(reason_), targets(targets_),
|
||||
reason_effect(reason_effect_) {}
|
||||
|
|
@ -317,9 +318,9 @@ struct Destroy : public Process<false> {
|
|||
struct Release : public Process<false> {
|
||||
uint8_t reason_player;
|
||||
uint32_t reason;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
effect* reason_effect;
|
||||
Release(uint16_t step_, group* targets_, effect* reason_effect_, uint32_t reason_,
|
||||
Release(uint16_t step_, owned_lua<group> targets_, effect* reason_effect_, uint32_t reason_,
|
||||
uint8_t reason_player_) :
|
||||
Process(step_), reason_player(reason_player_), reason(reason_), targets(targets_),
|
||||
reason_effect(reason_effect_) {}
|
||||
|
|
@ -334,31 +335,31 @@ struct SendTo : public Process<false> {
|
|||
};
|
||||
uint8_t reason_player;
|
||||
uint32_t reason;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
effect* reason_effect;
|
||||
std::unique_ptr<exargs> extra_args;
|
||||
SendTo(uint16_t step_, group* targets_, effect* reason_effect_, uint32_t reason_,
|
||||
SendTo(uint16_t step_, owned_lua<group> targets_, effect* reason_effect_, uint32_t reason_,
|
||||
uint8_t reason_player_) :
|
||||
Process(step_), reason_player(reason_player_), reason(reason_), targets(targets_),
|
||||
reason_effect(reason_effect_), extra_args(nullptr) {}
|
||||
};
|
||||
struct DestroyReplace : public Process<false> {
|
||||
bool battle;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card* target;
|
||||
DestroyReplace(uint16_t step_, group* targets_, card* target_, bool battle_) :
|
||||
DestroyReplace(uint16_t step_, owned_lua<group> targets_, card* target_, bool battle_) :
|
||||
Process(step_), battle(battle_), targets(targets_), target(target_) {}
|
||||
};
|
||||
struct ReleaseReplace : public Process<false> {
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card* target;
|
||||
ReleaseReplace(uint16_t step_, group* targets_, card* target_) :
|
||||
ReleaseReplace(uint16_t step_, owned_lua<group> targets_, card* target_) :
|
||||
Process(step_), targets(targets_), target(target_) {}
|
||||
};
|
||||
struct SendToReplace : public Process<false> {
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card* target;
|
||||
SendToReplace(uint16_t step_, group* targets_, card* target_) :
|
||||
SendToReplace(uint16_t step_, owned_lua<group> targets_, card* target_) :
|
||||
Process(step_), targets(targets_), target(target_) {}
|
||||
};
|
||||
struct MoveToField : public Process<false> {
|
||||
|
|
@ -380,9 +381,9 @@ struct ChangePos : public Process<false> {
|
|||
bool enable;
|
||||
bool oppo_selection;
|
||||
effect* reason_effect;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card_set to_grave_set;
|
||||
ChangePos(uint16_t step_, group* targets_, effect* reason_effect_,
|
||||
ChangePos(uint16_t step_, owned_lua<group> targets_, effect* reason_effect_,
|
||||
uint8_t reason_player_, bool enable_) :
|
||||
Process(step_), reason_player(reason_player_), enable(enable_), oppo_selection(false),
|
||||
reason_effect(reason_effect_), targets(targets_) {}
|
||||
|
|
@ -390,9 +391,9 @@ struct ChangePos : public Process<false> {
|
|||
struct OperationReplace : public Process<false> {
|
||||
bool is_destroy;
|
||||
effect* replace_effect;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card* target;
|
||||
OperationReplace(uint16_t step_, effect* replace_effect_, group* targets_,
|
||||
OperationReplace(uint16_t step_, effect* replace_effect_, owned_lua<group> targets_,
|
||||
card* target_, bool is_destroy_) :
|
||||
Process(step_), is_destroy(is_destroy_), replace_effect(replace_effect_),
|
||||
targets(targets_), target(target_) {}
|
||||
|
|
@ -425,7 +426,7 @@ struct SpSummonRule : public Process<false> {
|
|||
uint32_t summon_type;
|
||||
card* target;
|
||||
effect* summon_proc_effect;
|
||||
group* cards_to_summon_g;
|
||||
owned_lua<group> cards_to_summon_g;
|
||||
effect_set spsummon_cost_effects;
|
||||
SpSummonRule(uint16_t step_, uint8_t sumplayer_, card* target_, uint32_t summon_type_,
|
||||
bool is_mid_chain_ = false, effect* summon_proc_effect_ = nullptr) :
|
||||
|
|
@ -436,9 +437,9 @@ struct SpSummon : public Process<false> {
|
|||
uint8_t reason_player;
|
||||
uint32_t zone;
|
||||
effect* reason_effect;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
SpSummon(uint16_t step_, effect* reason_effect_, uint8_t reason_player_,
|
||||
group* targets_, uint32_t zone_) :
|
||||
owned_lua<group> targets_, uint32_t zone_) :
|
||||
Process(step_), reason_player(reason_player_), zone(zone_), reason_effect(reason_effect_),
|
||||
targets(targets_) {}
|
||||
};
|
||||
|
|
@ -476,21 +477,21 @@ struct SpellSet : public Process<false> {
|
|||
};
|
||||
struct SpSummonStep : public Process<false> {
|
||||
uint32_t zone;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card* target;
|
||||
effect_set spsummon_cost_effects;
|
||||
SpSummonStep(uint16_t step_, group* targets_, card* target_, uint32_t zone_) :
|
||||
SpSummonStep(uint16_t step_, owned_lua<group> targets_, card* target_, uint32_t zone_) :
|
||||
Process(step_), zone(zone_), targets(targets_), target(target_) {}
|
||||
};
|
||||
struct SpellSetGroup : public Process<false> {
|
||||
uint8_t setplayer;
|
||||
uint8_t toplayer;
|
||||
bool confirm;
|
||||
group* ptarget;
|
||||
owned_lua<group> ptarget;
|
||||
effect* reason_effect;
|
||||
card_set set_cards;
|
||||
SpellSetGroup(uint16_t step_, uint8_t setplayer_, uint8_t toplayer_,
|
||||
group* ptarget_, bool confirm_, effect* reason_effect_) :
|
||||
owned_lua<group> ptarget_, bool confirm_, effect* reason_effect_) :
|
||||
Process(step_), setplayer(setplayer_), toplayer(toplayer_), confirm(confirm_),
|
||||
ptarget(ptarget_), reason_effect(reason_effect_) {}
|
||||
};
|
||||
|
|
@ -556,9 +557,9 @@ struct GetControl : public Process<false> {
|
|||
uint16_t reset_phase;
|
||||
uint32_t zone;
|
||||
effect* reason_effect;
|
||||
group* targets;
|
||||
owned_lua<group> targets;
|
||||
card_set destroy_set;
|
||||
GetControl(uint16_t step_, effect* reason_effect_, uint8_t chose_player_, group* targets_,
|
||||
GetControl(uint16_t step_, effect* reason_effect_, uint8_t chose_player_, owned_lua<group> targets_,
|
||||
uint8_t playerid_, uint16_t reset_phase_, uint8_t reset_count_, uint32_t zone_) :
|
||||
Process(step_), chose_player(chose_player_), playerid(playerid_), reset_count(reset_count_),
|
||||
reset_phase(reset_phase_), zone(zone_), reason_effect(reason_effect_), targets(targets_) {}
|
||||
|
|
@ -569,10 +570,10 @@ struct SwapControl : public Process<false> {
|
|||
uint8_t self_selected_sequence;
|
||||
uint16_t reset_phase;
|
||||
effect* reason_effect;
|
||||
group* targets1;
|
||||
group* targets2;
|
||||
owned_lua<group> targets1;
|
||||
owned_lua<group> targets2;
|
||||
SwapControl(uint16_t step_, effect* reason_effect_, uint8_t reason_player_,
|
||||
group* targets1_, group* targets2_, uint16_t reset_phase_, uint8_t reset_count_) :
|
||||
owned_lua<group> targets1_, owned_lua<group> targets2_, uint16_t reset_phase_, uint8_t reset_count_) :
|
||||
Process(step_), reset_count(reset_count_), reason_player(reason_player_), self_selected_sequence(0),
|
||||
reset_phase(reset_phase_), reason_effect(reason_effect_), targets1(targets1_), targets2(targets2_) {}
|
||||
};
|
||||
|
|
@ -680,11 +681,11 @@ struct RockPaperScissors : public Process<true> {
|
|||
struct SelectFusion : public Process<false> {
|
||||
uint8_t playerid;
|
||||
uint32_t chkf;
|
||||
group* fusion_materials;
|
||||
group* forced_materials;
|
||||
owned_lua<group> fusion_materials;
|
||||
owned_lua<group> forced_materials;
|
||||
card* pcard;
|
||||
SelectFusion(uint16_t step_, uint8_t playerid_, group* fusion_materials_, uint32_t chkf_,
|
||||
group* forced_materials_, card* pcard_) :
|
||||
SelectFusion(uint16_t step_, uint8_t playerid_, owned_lua<group> fusion_materials_, uint32_t chkf_,
|
||||
owned_lua<group> forced_materials_, card* pcard_) :
|
||||
Process(step_), playerid(playerid_), chkf(chkf_), fusion_materials(fusion_materials_),
|
||||
forced_materials(forced_materials_), pcard(pcard_) {}
|
||||
};
|
||||
|
|
@ -722,8 +723,8 @@ struct RemoveOverlay : public Process<false> {
|
|||
uint8_t self;
|
||||
uint8_t oppo;
|
||||
uint32_t reason;
|
||||
group* pgroup;
|
||||
RemoveOverlay(uint16_t step_, uint32_t reason_, group* pgroup_, uint8_t rplayer_,
|
||||
owned_lua<group> pgroup;
|
||||
RemoveOverlay(uint16_t step_, uint32_t reason_, owned_lua<group> pgroup_, uint8_t rplayer_,
|
||||
uint8_t self_, uint8_t oppo_, uint16_t min_, uint16_t max_) :
|
||||
Process(step_), min(min_), max(max_), replaced_amount(0),
|
||||
has_used_overlay_remove_replace_effect(false), rplayer(rplayer_), self(self_),
|
||||
|
|
@ -732,8 +733,8 @@ struct RemoveOverlay : public Process<false> {
|
|||
struct XyzOverlay : public Process<false> {
|
||||
bool send_materials_to_grave;
|
||||
card* target;
|
||||
group* materials;
|
||||
XyzOverlay(uint16_t step_, card* target_, group* materials_, bool send_materials_to_grave_) :
|
||||
owned_lua<group> materials;
|
||||
XyzOverlay(uint16_t step_, card* target_, owned_lua<group> materials_, bool send_materials_to_grave_) :
|
||||
Process(step_), send_materials_to_grave(send_materials_to_grave_), target(target_),
|
||||
materials(materials_) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2015, Argon Sun (Fluorohydride)
|
||||
* Copyright (c) 2018-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
* Copyright (c) 2018-2025, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -58,11 +58,11 @@ int32_t push_return_cards(lua_State* L, int32_t/* status*/, lua_KContext ctx) {
|
|||
if(cancelable) {
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
group* pgroup = pduel->new_group();
|
||||
auto pgroup = pduel->new_group();
|
||||
interpreter::pushobject(L, pgroup);
|
||||
}
|
||||
} else {
|
||||
group* pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
auto pgroup = pduel->new_group(pduel->game_field->return_cards.list);
|
||||
interpreter::pushobject(L, pgroup);
|
||||
}
|
||||
return 1;
|
||||
|
|
|
|||
11
scriptlib.h
11
scriptlib.h
|
|
@ -69,6 +69,9 @@ namespace scriptlib {
|
|||
template<typename T>
|
||||
inline constexpr bool IsFunction = std::is_same_v<T, function>;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool IsOwnedObject = std::is_same_v<T, owned_lua<group>>;
|
||||
|
||||
template<typename T>
|
||||
using EnableIfIntegral = std::enable_if_t<IsInteger<T> || IsBool<T>, T>;
|
||||
|
||||
|
|
@ -79,7 +82,9 @@ namespace scriptlib {
|
|||
|
||||
template<typename T>
|
||||
inline constexpr auto get_lua_param_type() {
|
||||
if constexpr(IsCard<T>)
|
||||
if constexpr(IsOwnedObject<T>)
|
||||
return get_lua_param_type<typename T::lua_type>();
|
||||
else if constexpr(IsCard<T>)
|
||||
return LuaParam::CARD;
|
||||
else if constexpr(IsGroup<T>)
|
||||
return LuaParam::GROUP;
|
||||
|
|
@ -187,7 +192,7 @@ namespace scriptlib {
|
|||
}
|
||||
|
||||
template<bool nil_allowed = false>
|
||||
inline std::pair<card*, group*> lua_get_card_or_group(lua_State* L, int idx) {
|
||||
inline std::pair<card*, owned_lua<group>> lua_get_card_or_group(lua_State* L, int idx) {
|
||||
if constexpr(nil_allowed) {
|
||||
if(lua_isnoneornil(L, idx))
|
||||
return { nullptr, nullptr };
|
||||
|
|
@ -198,7 +203,7 @@ namespace scriptlib {
|
|||
case LuaParam::CARD:
|
||||
return { reinterpret_cast<card*>(obj), nullptr };
|
||||
case LuaParam::GROUP:
|
||||
return{ nullptr, reinterpret_cast<group*>(obj) };
|
||||
return{ nullptr, owned_lua<group>{reinterpret_cast<group*>(obj)} };
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue