Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
YGOMobile
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fallenstardust
YGOMobile
Commits
db46908c
Commit
db46908c
authored
Nov 17, 2025
by
fallenstardust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
注释部分YGOPro相关类
parent
af960d55
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1453 additions
and
504 deletions
+1453
-504
Classes/gframe/drawing.cpp
Classes/gframe/drawing.cpp
+803
-369
Classes/gframe/duelclient.cpp
Classes/gframe/duelclient.cpp
+489
-54
Classes/gframe/netserver.cpp
Classes/gframe/netserver.cpp
+0
-1
Classes/ocgcore/libcard.cpp
Classes/ocgcore/libcard.cpp
+50
-16
Classes/ocgcore/libduel.cpp
Classes/ocgcore/libduel.cpp
+34
-10
Classes/ocgcore/processor.cpp
Classes/ocgcore/processor.cpp
+72
-50
mobile/src/main/res/layout/fragment_ex_card_list.xml
mobile/src/main/res/layout/fragment_ex_card_list.xml
+5
-4
No files found.
Classes/gframe/drawing.cpp
View file @
db46908c
This diff is collapsed.
Click to expand it.
Classes/gframe/duelclient.cpp
View file @
db46908c
This diff is collapsed.
Click to expand it.
Classes/gframe/netserver.cpp
View file @
db46908c
...
...
@@ -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 服务器监听的端口号
...
...
Classes/ocgcore/libcard.cpp
View file @
db46908c
...
...
@@ -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
);
...
...
Classes/ocgcore/libduel.cpp
View file @
db46908c
...
...
@@ -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
);
...
...
Classes/ocgcore/processor.cpp
View file @
db46908c
...
...
@@ -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
))
{
...
...
mobile/src/main/res/layout/fragment_ex_card_list.xml
View file @
db46908c
...
...
@@ -40,22 +40,23 @@ android:focusableInTouchMode="false"
android:layout_width=
"60dp"
android:layout_height=
"60dp"
android:layout_gravity=
"center"
android:layout_marginBottom=
"
5
dp"
android:layout_marginBottom=
"
10
dp"
android:background=
"@drawable/button_cube"
android:src=
"@drawable/downloadimages"
android:scaleType=
"fitCenter"
android:adjustViewBounds=
"true"
android:padding=
"1
2
dp"
android:padding=
"1
0
dp"
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>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment