2015-09-25 21:07:16 +08:00
|
|
|
/*
|
2024-01-03 01:21:08 +01:00
|
|
|
* Copyright (c) 2012-2015, Argon Sun (Fluorohydride)
|
|
|
|
|
* Copyright (c) 2017-2024, Edoardo Lolletti (edo9300) <edoardo762@gmail.com>
|
2015-09-25 21:07:16 +08:00
|
|
|
*
|
2024-01-03 01:21:08 +01:00
|
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
2015-09-25 21:07:16 +08:00
|
|
|
*/
|
2024-01-05 12:17:47 +01:00
|
|
|
#include "card.h"
|
2015-09-25 21:07:16 +08:00
|
|
|
#include "duel.h"
|
|
|
|
|
#include "field.h"
|
2024-01-05 12:17:47 +01:00
|
|
|
#include "scriptlib.h"
|
2015-09-25 21:07:16 +08:00
|
|
|
|
2022-05-14 19:54:07 +02:00
|
|
|
#define LUA_MODULE Debug
|
|
|
|
|
#include "function_array_helper.h"
|
|
|
|
|
|
2021-10-13 17:29:29 +02:00
|
|
|
namespace {
|
2025-07-05 19:50:36 +02:00
|
|
|
namespace LUA_NAMESPACE {
|
2021-10-13 17:29:29 +02:00
|
|
|
|
|
|
|
|
using namespace scriptlib;
|
|
|
|
|
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(Message) {
|
2022-10-24 18:16:28 +02:00
|
|
|
int top = lua_gettop(L);
|
|
|
|
|
if(top == 0)
|
2022-05-31 16:31:23 +02:00
|
|
|
return 0;
|
2022-10-24 18:16:28 +02:00
|
|
|
luaL_checkstack(L, 1, nullptr);
|
|
|
|
|
for(int i = 1; i <= top; ++i) {
|
2024-04-13 10:34:09 +02:00
|
|
|
const auto* str = ensure_luaL_stack(luaL_tolstring, L, i, nullptr);
|
2022-10-24 18:16:28 +02:00
|
|
|
if(str)
|
|
|
|
|
pduel->handle_message(str, OCG_LOG_TYPE_FROM_SCRIPT);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
}
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(AddCard) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 6);
|
2021-09-04 22:04:14 +02:00
|
|
|
auto code = lua_get<uint32_t>(L, 1);
|
|
|
|
|
auto owner = lua_get<uint8_t>(L, 2);
|
|
|
|
|
auto playerid = lua_get<uint8_t>(L, 3);
|
|
|
|
|
auto location = lua_get<uint16_t>(L, 4);
|
|
|
|
|
auto sequence = lua_get<uint16_t>(L, 5);
|
|
|
|
|
auto position = lua_get<uint8_t>(L, 6);
|
2020-07-23 23:50:09 +02:00
|
|
|
bool proc = lua_get<bool, false>(L, 7);
|
2015-09-25 21:07:16 +08:00
|
|
|
if(owner != 0 && owner != 1)
|
|
|
|
|
return 0;
|
|
|
|
|
if(playerid != 0 && playerid != 1)
|
|
|
|
|
return 0;
|
2021-10-12 22:59:25 +02:00
|
|
|
auto& field = pduel->game_field;
|
2025-06-28 18:10:02 +02:00
|
|
|
if(!field->is_field_location_valid(location, sequence))
|
|
|
|
|
lua_error(L, "Passed invalid location");
|
2021-10-12 22:59:25 +02:00
|
|
|
if(field->is_location_useable(playerid, location, sequence)) {
|
2015-09-25 21:07:16 +08:00
|
|
|
card* pcard = pduel->new_card(code);
|
|
|
|
|
pcard->owner = owner;
|
2020-05-12 20:26:07 +02:00
|
|
|
if(location == LOCATION_EXTRA && (position == 0 || (pcard->data.type & TYPE_PENDULUM) == 0))
|
2019-12-25 14:57:09 +08:00
|
|
|
position = POS_FACEDOWN_DEFENSE;
|
2017-08-06 17:14:03 +09:00
|
|
|
pcard->sendto_param.position = position;
|
2022-10-28 20:23:23 +02:00
|
|
|
bool pzone = false;
|
2017-07-24 11:08:54 +08:00
|
|
|
if(location == LOCATION_PZONE) {
|
2022-10-28 20:23:23 +02:00
|
|
|
location = LOCATION_SZONE;
|
|
|
|
|
sequence = field->get_pzone_index(sequence, playerid);
|
2022-12-08 10:50:29 +01:00
|
|
|
pzone = true;
|
2018-08-24 17:01:30 -03:00
|
|
|
} else if(location == LOCATION_FZONE) {
|
2022-10-28 20:23:23 +02:00
|
|
|
location = LOCATION_SZONE;
|
|
|
|
|
sequence = 5;
|
|
|
|
|
} else if(location == LOCATION_STZONE) {
|
|
|
|
|
location = LOCATION_SZONE;
|
|
|
|
|
sequence += 1 * pduel->game_field->is_flag(DUEL_3_COLUMNS_FIELD);
|
|
|
|
|
|
|
|
|
|
} else if(location == LOCATION_MMZONE) {
|
|
|
|
|
location = LOCATION_MZONE;
|
|
|
|
|
sequence += 1 * pduel->game_field->is_flag(DUEL_3_COLUMNS_FIELD);
|
|
|
|
|
|
|
|
|
|
} else if(location == LOCATION_EMZONE) {
|
|
|
|
|
location = LOCATION_MZONE;
|
|
|
|
|
sequence += 5;
|
|
|
|
|
}
|
|
|
|
|
field->add_card(playerid, pcard, location, sequence, pzone);
|
2015-09-25 21:07:16 +08:00
|
|
|
pcard->current.position = position;
|
2022-10-28 20:23:23 +02:00
|
|
|
if(!(location & LOCATION_ONFIELD) || (position & POS_FACEUP)) {
|
2016-04-08 19:38:51 +08:00
|
|
|
pcard->enable_field_effect(true);
|
2021-10-12 22:59:25 +02:00
|
|
|
field->adjust_instant();
|
2015-09-25 21:07:16 +08:00
|
|
|
}
|
|
|
|
|
if(proc)
|
|
|
|
|
pcard->set_status(STATUS_PROC_COMPLETE, TRUE);
|
2020-07-20 22:05:04 +02:00
|
|
|
interpreter::pushobject(L, pcard);
|
2015-09-25 21:07:16 +08:00
|
|
|
return 1;
|
2020-01-16 22:46:17 +01:00
|
|
|
} else if(location & LOCATION_ONFIELD) {
|
2015-09-25 21:07:16 +08:00
|
|
|
card* pcard = pduel->new_card(code);
|
|
|
|
|
pcard->owner = owner;
|
2021-10-12 22:59:25 +02:00
|
|
|
card* fcard = field->get_field_card(playerid, location, sequence);
|
2020-04-12 13:11:54 +02:00
|
|
|
fcard->xyz_add(pcard);
|
|
|
|
|
if(proc)
|
|
|
|
|
pcard->set_status(STATUS_PROC_COMPLETE, TRUE);
|
2020-07-20 22:05:04 +02:00
|
|
|
interpreter::pushobject(L, pcard);
|
2015-09-25 21:07:16 +08:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(SetPlayerInfo) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 4);
|
2021-09-04 22:04:14 +02:00
|
|
|
auto playerid = lua_get<uint8_t>(L, 1);
|
|
|
|
|
auto lp = lua_get<uint32_t>(L, 2);
|
|
|
|
|
auto startcount = lua_get<uint32_t>(L, 3);
|
|
|
|
|
auto drawcount = lua_get<uint32_t>(L, 4);
|
2015-09-25 21:07:16 +08:00
|
|
|
if(playerid != 0 && playerid != 1)
|
|
|
|
|
return 0;
|
2021-10-12 22:59:25 +02:00
|
|
|
auto& player = pduel->game_field->player[playerid];
|
|
|
|
|
player.lp = lp;
|
|
|
|
|
player.start_lp = lp;
|
|
|
|
|
player.start_count = startcount;
|
|
|
|
|
player.draw_count = drawcount;
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(PreSummon) {
|
2016-02-07 11:56:39 +08:00
|
|
|
check_param_count(L, 2);
|
2020-07-21 15:58:11 +02:00
|
|
|
auto pcard = lua_get<card*, true>(L, 1);
|
2021-09-04 22:04:14 +02:00
|
|
|
auto summon_type = lua_get<uint32_t>(L, 2);
|
|
|
|
|
auto summon_location = lua_get<uint8_t, 0>(L, 3);
|
2022-10-30 11:08:18 +01:00
|
|
|
auto summon_sequence = lua_get<uint8_t, 0>(L, 4);
|
|
|
|
|
auto summon_pzone = lua_get<bool, false>(L, 5);
|
|
|
|
|
pcard->summon.location = summon_location;
|
|
|
|
|
pcard->summon.type = summon_type;
|
|
|
|
|
pcard->summon.sequence = summon_sequence;
|
|
|
|
|
pcard->summon.pzone = summon_pzone;
|
2016-02-07 11:56:39 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(PreEquip) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 2);
|
2020-07-21 15:58:11 +02:00
|
|
|
auto equip_card = lua_get<card*, true>(L, 1);
|
|
|
|
|
auto target = lua_get<card*, true>(L, 2);
|
2015-09-25 21:07:16 +08:00
|
|
|
if((equip_card->current.location != LOCATION_SZONE)
|
2021-10-13 17:29:29 +02:00
|
|
|
|| (target->current.location != LOCATION_MZONE)
|
|
|
|
|
|| (target->current.position & POS_FACEDOWN))
|
2015-09-25 21:07:16 +08:00
|
|
|
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;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(PreSetTarget) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 2);
|
2020-07-21 15:58:11 +02:00
|
|
|
auto t_card = lua_get<card*, true>(L, 1);
|
|
|
|
|
auto target = lua_get<card*, true>(L, 2);
|
2015-09-25 21:07:16 +08:00
|
|
|
t_card->add_card_target(target);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(PreAddCounter) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 2);
|
2020-07-21 15:58:11 +02:00
|
|
|
auto pcard = lua_get<card*, true>(L, 1);
|
2021-09-04 22:04:14 +02:00
|
|
|
auto countertype = lua_get<uint16_t>(L, 2);
|
|
|
|
|
auto count = lua_get<uint16_t>(L, 3);
|
|
|
|
|
uint16_t cttype = countertype & ~COUNTER_NEED_ENABLE;
|
2025-02-25 18:23:41 +01:00
|
|
|
auto [cmit, was_constructed] = pcard->counters.try_emplace(cttype, card::counter_map::mapped_type());
|
|
|
|
|
if(was_constructed) {
|
2015-11-29 21:50:11 +09:00
|
|
|
cmit->second[0] = 0;
|
|
|
|
|
cmit->second[1] = 0;
|
|
|
|
|
}
|
2016-04-12 23:39:49 +08:00
|
|
|
if((countertype & COUNTER_WITHOUT_PERMIT) && !(countertype & COUNTER_NEED_ENABLE))
|
2015-11-29 21:50:11 +09:00
|
|
|
cmit->second[0] += count;
|
|
|
|
|
else
|
|
|
|
|
cmit->second[1] += count;
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(ReloadFieldBegin) {
|
2015-09-25 21:07:16 +08:00
|
|
|
check_param_count(L, 1);
|
2021-09-04 22:04:14 +02:00
|
|
|
auto flag = lua_get<uint64_t>(L, 1);
|
|
|
|
|
auto rule = lua_get<uint8_t, 3>(L, 2);
|
2020-07-23 23:50:09 +02:00
|
|
|
bool build = lua_get<bool, false>(L, 3);
|
2015-09-25 21:07:16 +08:00
|
|
|
pduel->clear();
|
2020-01-09 00:03:55 +01:00
|
|
|
#define CHECK(MR) case MR : { flag |= DUEL_MODE_MR##MR; break; }
|
2017-10-23 20:26:59 +02:00
|
|
|
if(rule && !build) {
|
|
|
|
|
switch (rule) {
|
2020-01-09 00:03:55 +01:00
|
|
|
CHECK(1)
|
|
|
|
|
CHECK(2)
|
|
|
|
|
CHECK(3)
|
|
|
|
|
CHECK(4)
|
|
|
|
|
CHECK(5)
|
2017-10-23 20:26:59 +02:00
|
|
|
}
|
2020-01-09 00:03:55 +01:00
|
|
|
#undef CHECK
|
2017-10-23 20:26:59 +02:00
|
|
|
}
|
|
|
|
|
pduel->game_field->core.duel_options = flag;
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(ReloadFieldEnd) {
|
2021-10-12 22:59:25 +02:00
|
|
|
auto& field = pduel->game_field;
|
|
|
|
|
auto& core = field->core;
|
2024-01-03 13:34:39 +01:00
|
|
|
core.shuffle_hand_check[0] = false;
|
|
|
|
|
core.shuffle_hand_check[1] = false;
|
|
|
|
|
core.shuffle_deck_check[0] = false;
|
|
|
|
|
core.shuffle_deck_check[1] = false;
|
2021-10-12 22:59:25 +02:00
|
|
|
field->reload_field_info();
|
2022-05-16 19:57:17 +02:00
|
|
|
if(lua_isyieldable(L))
|
2023-11-25 11:15:21 +01:00
|
|
|
return yield();
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2022-03-04 23:53:28 +01:00
|
|
|
template<int message_code, size_t max_len>
|
|
|
|
|
int32_t write_string_message(lua_State* L) {
|
2021-10-13 17:29:29 +02:00
|
|
|
check_param_count(L, 1);
|
2024-03-01 17:53:08 +01:00
|
|
|
check_param<LuaParam::STRING>(L, 1);
|
2020-11-06 22:40:01 +01:00
|
|
|
size_t len = 0;
|
|
|
|
|
const char* pstr = lua_tolstring(L, 1, &len);
|
2021-10-12 22:59:25 +02:00
|
|
|
if(len > max_len)
|
|
|
|
|
len = max_len;
|
2023-11-25 11:15:21 +01:00
|
|
|
auto message = lua_get<duel*>(L)->new_message(message_code);
|
2021-09-04 22:04:14 +02:00
|
|
|
message->write<uint16_t>(static_cast<uint16_t>(len));
|
2020-11-06 22:40:01 +01:00
|
|
|
message->write(pstr, len);
|
2021-09-04 22:04:14 +02:00
|
|
|
message->write<uint8_t>(0);
|
2015-09-25 21:07:16 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
2020-01-06 19:01:59 +01:00
|
|
|
|
2022-05-14 19:54:07 +02:00
|
|
|
LUA_FUNCTION_EXISTING(SetAIName, write_string_message<MSG_AI_NAME, 100>);
|
|
|
|
|
LUA_FUNCTION_EXISTING(ShowHint, write_string_message<MSG_SHOW_HINT, 1024>);
|
|
|
|
|
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(PrintStacktrace) {
|
2020-01-06 19:01:59 +01:00
|
|
|
interpreter::print_stacktrace(L);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2021-10-13 17:29:29 +02:00
|
|
|
|
2023-11-21 11:56:23 +01:00
|
|
|
LUA_STATIC_FUNCTION(CardToStringWrapper) {
|
2022-10-20 19:07:56 +02:00
|
|
|
const auto pcard = lua_get<card*>(L, 1);
|
|
|
|
|
if(pcard) {
|
|
|
|
|
luaL_checkstack(L, 4, nullptr);
|
|
|
|
|
lua_getglobal(L, "Debug");
|
|
|
|
|
lua_pushstring(L, "CardToString");
|
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
|
if(!lua_isnil(L, -1)) {
|
|
|
|
|
lua_pushvalue(L, 1);
|
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
lua_settop(L, 1);
|
|
|
|
|
}
|
2024-04-13 10:34:09 +02:00
|
|
|
const char* kind = ensure_luaL_stack(luaL_typename, L, 1);
|
2022-10-20 19:07:56 +02:00
|
|
|
lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, 1));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-05 19:50:36 +02:00
|
|
|
}
|
2021-10-13 17:29:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void scriptlib::push_debug_lib(lua_State* L) {
|
2022-05-14 19:54:07 +02:00
|
|
|
static constexpr auto debuglib = GET_LUA_FUNCTIONS_ARRAY();
|
2023-11-26 14:47:09 +01:00
|
|
|
static_assert(debuglib.back().name == nullptr);
|
2023-02-07 16:43:27 +01:00
|
|
|
lua_createtable(L, 0, static_cast<int>(debuglib.size() - 1));
|
2024-04-13 10:34:09 +02:00
|
|
|
ensure_luaL_stack(luaL_setfuncs, L, debuglib.data(), 0);
|
2021-10-13 17:29:29 +02:00
|
|
|
lua_setglobal(L, "Debug");
|
2023-02-07 16:43:27 +01:00
|
|
|
}
|