Commit db46908c authored by fallenstardust's avatar fallenstardust

注释部分YGOPro相关类

parent af960d55
This diff is collapsed.
This diff is collapsed.
......@@ -15,7 +15,6 @@ DuelMode* NetServer::duel_mode = 0;
unsigned char NetServer::net_server_write[SIZE_NETWORK_BUFFER];
size_t NetServer::last_sent = 0;
/c++
/**
* @brief 启动网络服务器
* @param port 服务器监听的端口号
......
......@@ -3188,46 +3188,80 @@ int32_t scriptlib::card_is_can_be_battle_target(lua_State *L) {
lua_pushboolean(L, pcard->is_capable_be_battle_target(bcard));
return 1;
}
/**
* @brief 为卡片添加怪物属性(如类型、种族、等级、攻击力、守备力等)
*
* 此函数用于动态地给一张卡牌设置其作为怪兽的基本属性。这些属性包括但不限于:
* 怪兽类型(通常由 type 参数指定)、属性、种族、等级以及攻防数值。
* 所有修改通过临时效果实现,并在特定事件时重置。
*/
int32_t scriptlib::card_add_monster_attribute(lua_State *L) {
check_param_count(L, 2);
check_param(L, PARAM_TYPE_CARD, 1);
int32_t type = (int32_t)lua_tointeger(L, 2);
int32_t attribute = (int32_t)lua_tointeger(L, 3);
int32_t race = (int32_t)lua_tointeger(L, 4);
int32_t level = (int32_t)lua_tointeger(L, 5);
int32_t atk = (int32_t)lua_tointeger(L, 6);
int32_t def = (int32_t)lua_tointeger(L, 7);
check_param_count(L, 2); // 检查至少传入两个参数
check_param(L, PARAM_TYPE_CARD, 1); // 确保第一个参数是有效的 card 类型
// 从 Lua 栈中提取各个参数值
int32_t type = (int32_t)lua_tointeger(L, 2); // 怪兽类型(如 EFFECT_TYPE_MONSTER)
int32_t attribute = (int32_t)lua_tointeger(L, 3); // 属性值(可选)
int32_t race = (int32_t)lua_tointeger(L, 4); // 种族值(可选)
int32_t level = (int32_t)lua_tointeger(L, 5); // 等级值(可选)
int32_t atk = (int32_t)lua_tointeger(L, 6); // 攻击力值(可选)
int32_t def = (int32_t)lua_tointeger(L, 7); // 防御力值(可选)
// 获取目标卡片对象和决斗对象
card* pcard = *(card**) lua_touserdata(L, 1);
duel* pduel = pcard->pduel;
// 清除"无等级"状态标志,允许设置等级相关属性
pcard->set_status(STATUS_NO_LEVEL, FALSE);
// 声明一个效果指针,用于创建各种临时效果
effect* peffect;
// 定义一个 Lambda 函数,用于创建并添加临时效果到卡片上
// code: 效果代码
// value: 效果值
// extra_reset_flag: 额外的重置标志(可选)
auto add_temp_effect = [&](uint32_t code, int32_t value, uint32_t extra_reset_flag = 0) {
peffect = pduel->new_effect();
peffect->owner = pcard;
peffect->type = EFFECT_TYPE_SINGLE;
peffect->code = code;
peffect->flag[0] = EFFECT_FLAG_CANNOT_DISABLE;
peffect = pduel->new_effect(); // 创建新效果
peffect->owner = pcard; // 设置效果所有者为当前卡片
peffect->type = EFFECT_TYPE_SINGLE; // 设置为单体效果类型
peffect->code = code; // 设置效果代码
peffect->flag[0] = EFFECT_FLAG_CANNOT_DISABLE; // 设置效果不可被无效化
// 设置重置条件:在特定事件或0x47e0000指定的条件下重置,可添加额外重置标志
peffect->reset_flag = RESET_EVENT | 0x47e0000 | extra_reset_flag;
peffect->value = value;
pcard->add_effect(peffect);
peffect->value = value; // 设置效果值
pcard->add_effect(peffect); // 将效果添加到卡片上
};
// 添加预设怪物类型的临时效果,并设置在连锁重置
add_temp_effect(EFFECT_PRE_MONSTER, type, RESET_CHAIN);
// 如果提供了属性值,则添加更改属性的临时效果
if(attribute) {
add_temp_effect(EFFECT_CHANGE_ATTRIBUTE, attribute);
}
// 如果提供了种族值,则添加更改种族的临时效果
if(race) {
add_temp_effect(EFFECT_CHANGE_RACE, race);
}
// 如果提供了等级值,则添加更改等级的临时效果
if(level) {
add_temp_effect(EFFECT_CHANGE_LEVEL, level);
}
// 如果提供了攻击力值,则添加设置基础攻击力的临时效果
if(atk) {
add_temp_effect(EFFECT_SET_BASE_ATTACK, atk);
}
// 如果提供了防御力值,则添加设置基础防御力的临时效果
if(def) {
add_temp_effect(EFFECT_SET_BASE_DEFENSE, def);
}
return 0;
return 0; // 返回0表示函数执行成功(Lua C API 规范)
}
int32_t scriptlib::card_cancel_to_grave(lua_State *L) {
check_param_count(L, 1);
......
......@@ -1094,21 +1094,45 @@ int32_t scriptlib::duel_confirm_cards(lua_State *L) {
pduel->game_field->add_process(PROCESSOR_WAIT, 0, 0, 0, 0, 0);
return lua_yield(L, 0);
}
/**
* @brief 让玩家重新排列自己卡组顶部的指定数量卡片
*
* 此函数用于启动一个卡组顶部卡片排序流程,允许指定的玩家重新排列目标玩家卡组顶部的若干张卡。
* 通常用于需要查看并重新排列卡组顶部卡片的效果处理。
*
* @param L Lua状态机指针,包含调用该函数所需的参数
* - 参数1:sort_player(整数),执行排序操作的玩家ID(0或1)
* - 参数2:target_player(整数),目标玩家ID,即其卡组将被排序(0或1)
* - 参数3:count(整数),需要排序的卡片数量
*
* @return 返回lua_yield()的结果,表示这是一个异步操作
*/
int32_t scriptlib::duel_sort_decktop(lua_State *L) {
check_action_permission(L);
check_param_count(L, 3);
int32_t sort_player = (int32_t)lua_tointeger(L, 1);
int32_t target_player = (int32_t)lua_tointeger(L, 2);
int32_t count = (int32_t)lua_tointeger(L, 3);
if (!check_playerid(sort_player))
check_action_permission(L); // 检查当前是否允许执行操作(如是否在正确的时点)
check_param_count(L, 3); // 检查是否提供了足够的参数(至少3个)
// 从Lua栈中获取参数并转换为整数类型
int32_t sort_player = (int32_t)lua_tointeger(L, 1); // 获取执行排序的玩家ID
int32_t target_player = (int32_t)lua_tointeger(L, 2); // 获取目标玩家ID
int32_t count = (int32_t)lua_tointeger(L, 3); // 获取需要排序的卡片数量
// 验证玩家ID的有效性
if (!check_playerid(sort_player)) // 检查执行排序的玩家ID是否有效(0或1)
return 0;
if (!check_playerid(target_player))
if (!check_playerid(target_player)) // 检查目标玩家ID是否有效(0或1)
return 0;
if (count < 1)
if (count < 1) // 检查排序数量是否至少为1
return 0;
duel* pduel = interpreter::get_duel_info(L);
duel* pduel = interpreter::get_duel_info(L); // 获取当前决斗对象的指针
// 添加一个处理流程到游戏字段处理队列中
// PROCESSOR_SORT_DECK: 使用卡组排序处理器
// sort_player + (target_player << 16): 将两个玩家ID打包成一个整数传递
// count: 排序的卡片数量
pduel->game_field->add_process(PROCESSOR_SORT_DECK, 0, 0, 0, sort_player + (target_player << 16), count);
return lua_yield(L, 0);
return lua_yield(L, 0); // 挂起当前Lua线程,等待排序操作完成
}
int32_t scriptlib::duel_check_event(lua_State *L) {
check_param_count(L, 1);
......
......@@ -662,56 +662,78 @@ uint32_t field::process() {
return pduel->buffer_size();
}
case PROCESSOR_SORT_DECK: {
uint8_t sort_player = it->arg1 & 0xffff;
uint8_t target_player = it->arg1 >> 16;
uint8_t count = it->arg2, i = 0;
if(count > player[target_player].list_main.size())
count = (uint8_t)player[target_player].list_main.size();
if(it->step == 0) {
core.select_cards.clear();
for(auto clit = player[target_player].list_main.rbegin(); i < count; ++i, ++clit)
core.select_cards.push_back(*clit);
add_process(PROCESSOR_SORT_CARD, 0, 0, 0, sort_player, 0);
++it->step;
} else {
if(returns.bvalue[0] != 0xff) {
card* tc[256];
for(i = 0; i < count; ++i)
player[target_player].list_main.pop_back();
for(i = 0; i < count; ++i)
tc[returns.bvalue[i]] = core.select_cards[i];
for(i = 0; i < count; ++i) {
player[target_player].list_main.push_back(tc[count - 1 - i]);
}
reset_sequence(target_player, LOCATION_DECK);
auto clit = player[target_player].list_main.rbegin();
for(i = 0; i < count; ++i, ++clit) {
card* pcard = *clit;
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(0);
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(pcard->get_info_location());
pduel->write_buffer32(REASON_EFFECT);
}
}
if(core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) {
if(count > 0) {
card* ptop = player[target_player].list_main.back();
if(core.deck_reversed || (ptop->current.position == POS_FACEUP_DEFENSE)) {
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(target_player);
pduel->write_buffer8(0);
if(ptop->current.position != POS_FACEUP_DEFENSE)
pduel->write_buffer32(ptop->data.code);
else
pduel->write_buffer32(ptop->data.code | 0x80000000);
}
}
}
core.units.pop_front();
}
return pduel->buffer_size();
}
// 从参数中提取排序玩家、目标玩家和卡片数量
uint8_t sort_player = it->arg1 & 0xffff; // 执行排序的玩家
uint8_t target_player = it->arg1 >> 16; // 被排序卡组的玩家
uint8_t count = it->arg2, i = 0; // 需要排序的卡片数量,循环变量初始化
// 如果要求排序的数量超过目标玩家主卡组的实际数量,则调整为实际数量
if(count > player[target_player].list_main.size())
count = (uint8_t)player[target_player].list_main.size();
// 第一步:准备需要排序的卡片并启动排序处理器
if(it->step == 0) {
core.select_cards.clear(); // 清空选择卡片列表
// 从目标玩家主卡组末尾开始,取count张卡片加入选择列表
for(auto clit = player[target_player].list_main.rbegin(); i < count; ++i, ++clit)
core.select_cards.push_back(*clit);
// 添加卡片排序处理器,让sort_player对这些卡片进行排序
add_process(PROCESSOR_SORT_CARD, 0, 0, 0, sort_player, 0);
++it->step; // 进入下一步
} else {
// 第二步:处理排序结果
// 如果返回值不是0xff(表示排序未被取消)
if(returns.bvalue[0] != 0xff) {
card* tc[256]; // 临时卡片数组,用于存储重新排序后的卡片
// 从目标玩家主卡组中移除之前取出的count张卡片
for(i = 0; i < count; ++i)
player[target_player].list_main.pop_back();
// 根据玩家的排序结果,将卡片放入临时数组的正确位置
for(i = 0; i < count; ++i)
tc[returns.bvalue[i]] = core.select_cards[i];
// 按照新的顺序将卡片重新放入目标玩家的主卡组
for(i = 0; i < count; ++i) {
player[target_player].list_main.push_back(tc[count - 1 - i]);
}
// 重置目标玩家主卡组中所有卡片的序列号
reset_sequence(target_player, LOCATION_DECK);
// 从卡组末尾开始遍历刚重新排序的卡片
auto clit = player[target_player].list_main.rbegin();
for(i = 0; i < count; ++i, ++clit) {
card* pcard = *clit;
// 向客户端发送卡片移动消息(虽然位置未变,但用于同步排序结果)
pduel->write_buffer8(MSG_MOVE);
pduel->write_buffer32(0); // 原位置(这里用0表示无来源)
pduel->write_buffer32(pcard->get_info_location()); // 当前位置
pduel->write_buffer32(pcard->get_info_location()); // 目标位置
pduel->write_buffer32(REASON_EFFECT); // 移动原因
}
}
// 如果启用了卡组顶部检查的全局标志
if(core.global_flag & GLOBALFLAG_DECK_REVERSE_CHECK) {
// 如果有卡片被排序
if(count > 0) {
// 获取目标玩家主卡组最上面的卡片
card* ptop = player[target_player].list_main.back();
// 如果卡组是翻转状态或者最上面的卡片是表侧守备表示
if(core.deck_reversed || (ptop->current.position == POS_FACEUP_DEFENSE)) {
// 向客户端发送卡组顶部卡片信息
pduel->write_buffer8(MSG_DECK_TOP);
pduel->write_buffer8(target_player); // 玩家
pduel->write_buffer8(0); // 序号(0表示最上面)
// 根据卡片位置发送卡片密码
if(ptop->current.position != POS_FACEUP_DEFENSE)
pduel->write_buffer32(ptop->data.code); // 里侧表示
else
pduel->write_buffer32(ptop->data.code | 0x80000000); // 表侧表示
}
}
}
core.units.pop_front(); // 移除当前处理单元
}
return pduel->buffer_size(); // 返回缓冲区大小
}
case PROCESSOR_REMOVE_OVERLAY: {
if(remove_overlay_card(it->step, it->arg3, (card*)(it->ptarget), it->arg1 >> 16,
(it->arg1 >> 8) & 0xff, it->arg1 & 0xff, it->arg2 & 0xffff, it->arg2 >> 16)) {
......
......@@ -40,22 +40,23 @@ android:focusableInTouchMode="false"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_marginBottom="10dp"
android:background="@drawable/button_cube"
android:src="@drawable/downloadimages"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:padding="12dp"
android:padding="10dp"
android:clickable="false" />
<TextView
android:id="@+id/text_download_precard"
android:layout_width="60dp"
android:layout_height="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ic_radius_bg"
android:clickable="false"
android:gravity="center"
android:textAlignment="center"
android:text="0"
android:textColor="@color/gold"
android:textSize="10sp" />
</LinearLayout>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment