Doc2 (#90)
又写了一堆文档呢(乐 --------- Co-authored-by: deepskybird <32931830+deepskybird@users.noreply.github.com>
This commit is contained in:
parent
73de569110
commit
e4c806ff09
|
@ -1,2 +1,7 @@
|
|||
Server
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
server/room.rst
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Room
|
||||
=============
|
||||
|
||||
.. lua:autoclass:: Room
|
22
docs/conf.py
22
docs/conf.py
|
@ -34,7 +34,6 @@ extensions = [
|
|||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.githubpages',
|
||||
'sphinxcontrib.luadomain',
|
||||
'sphinx_lua',
|
||||
|
@ -71,9 +70,28 @@ exclude_patterns = []
|
|||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'sphinx_book_theme'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# PDF option
|
||||
latex_engine = 'xelatex'
|
||||
latex_elements = {
|
||||
'papersize': 'a4paper',
|
||||
'pointsize': '12pt',
|
||||
'fontpkg': r'''
|
||||
''',
|
||||
'fncychap': r'\usepackage[Sonny]{fncychap}',
|
||||
'preamble': r'''
|
||||
''',
|
||||
'figure_align': 'H',
|
||||
}
|
||||
|
||||
latex_documents = [
|
||||
('index', 'manual.tex', 'FreeKill Handbook',
|
||||
'Notify', 'manual', False),
|
||||
]
|
||||
|
||||
|
|
|
@ -8,10 +8,15 @@ FreeKill采用最新的Qt进行构建,因此需要先安装Qt6的开发环境
|
|||
|
||||
无论是Win还是Linux,都建议用\ `Qt官方的下载器 <https://download.qt.io/official_releases/online_installers/>`__\ 进行安装。当然了,在一些软件更新很频繁的Linux发行版里面,可能已经能从包管理器安装Qt6,对此后文细说。这个环节介绍用Qt安装器安装的步骤。
|
||||
|
||||
Qt安装的流程不赘述。为了编译FreeKill,至少需要安装以下的组件: - Qt 6:
|
||||
MinGW 11.2.0 64-bit (不支持MSVC) - Qt 6: Qt5 Compat - Qt 6: Shader
|
||||
Tools (为了使用GraphicalEffects) - Qt 6: Multimedia -
|
||||
QtCreator(这个是安装器强制要你安装的) - CMake、Ninja - OpenSSL 1.1.1
|
||||
Qt安装的流程不赘述。为了编译FreeKill,至少需要安装以下的组件:
|
||||
|
||||
- Qt 6: MinGW 11.2.0 64-bit (不支持MSVC)
|
||||
- Qt 6: Qt5 Compat
|
||||
- Qt 6: Shader Tools (为了使用GraphicalEffects)
|
||||
- Qt 6: Multimedia
|
||||
- QtCreator(这个是安装器强制要你安装的)
|
||||
- CMake、Ninja
|
||||
- OpenSSL 1.1.1
|
||||
|
||||
接下来根据平台的不同,步骤也稍有区别。
|
||||
|
||||
|
@ -26,15 +31,9 @@ Windows
|
|||
|
||||
接下来使用QtCreator打开项目,然后尝试编译。
|
||||
|
||||
这时遇到cmake报错:OpenSSL:Crypto not found.
|
||||
这是因为我们还没有告诉编译器OpenSSL的位置,点左侧“项目”,查看构建选项,在CMake的Initial
|
||||
Configuration中,点击添加按钮,新增String型环境变量OPENSSL_ROOT_DIR,将其值设为跟Qt一同安装的OpenSSL的位置(如C:/Qt/Tools/OpenSSL/Win_x64)。然后点下方的Re-configure
|
||||
with Initial Parameters,这样就能正常编译了。
|
||||
这时遇到cmake报错:OpenSSL:Crypto not found. 这是因为我们还没有告诉编译器OpenSSL的位置,点左侧“项目”,查看构建选项,在CMake的Initial Configuration中,点击添加按钮,新增String型环境变量OPENSSL_ROOT_DIR,将其值设为跟Qt一同安装的OpenSSL的位置(如C:/Qt/Tools/OpenSSL/Win_x64)。然后点下方的Re-configure with Initial Parameters,这样就能正常编译了。
|
||||
|
||||
运行的话,在Qt
|
||||
Creator的项目选项->运行中,先将工作目录改为项目所在的目录(git仓库的目录)。然后先将编译好了的FreeKill.exe放到项目目录中,在目录下打开CMD,执行windeployqt
|
||||
FreeKill.exe。调整目录下的dll文件直到能运行起来为止,之后就可以在Qt
|
||||
Creator中正常运行和调试了。
|
||||
运行的话,在Qt Creator的项目选项->运行中,先将工作目录改为项目所在的目录(git仓库的目录)。然后先将编译好了的FreeKill.exe放到项目目录中,在目录下打开CMD,执行windeployqt FreeKill.exe。调整目录下的dll文件直到能运行起来为止,之后就可以在Qt Creator中正常运行和调试了。
|
||||
|
||||
--------------
|
||||
|
||||
|
|
|
@ -31,15 +31,14 @@ Fk是游戏本身,也是拓展包运行的平台。事实上这份文档应该
|
|||
- 需要有EmmyLua插件的支持
|
||||
- 需要默认UTF-8格式保存代码文件
|
||||
|
||||
..
|
||||
.. note::
|
||||
|
||||
EmmyLua是一种特别的Lua注释方式,可以为本来弱类型的Lua语言提供类型支持,这对于像FreeKill这种稍有规模的Lua项目是十分必要的。目前能提供开箱即用的EmmyLua插件编辑器主要有IntelliJ
|
||||
IDEA和Visual Studio
|
||||
Code。EmmyLua也能以LSP的方式运行,因此支持LSP的编辑器(这种就多了,比如vim,
|
||||
sublime)也能符合条件。
|
||||
EmmyLua是一种特别的Lua注释方式,可以为本来弱类型的Lua语言提供类型支持,这对于像FreeKill这种稍有规模的Lua项目是十分必要的。目前能提供开箱即用的EmmyLua插件编辑器主要有IntelliJ IDEA和Visual Studio Code。EmmyLua也能以LSP的方式运行,因此支持LSP的编辑器(这种就多了,比如vim, sublime)也能符合条件。
|
||||
|
||||
编辑器的具体安装以及插件配置不在此赘述。
|
||||
|
||||
.. hint::
|
||||
|
||||
出于易用性和免费的考虑,推荐用VSCode进行拓展。下文将以VSCode为编辑器进行进一步说明。
|
||||
|
||||
git
|
||||
|
@ -47,6 +46,8 @@ git
|
|||
|
||||
git就不必多介绍了吧,这里说说为什么需要配置git。这是因为在Fk中,拓展包拥有在线安装/在线更新的功能,这种功能都是依托于git进行的,因此如果你打算将自己的拓展包发布出去的话,就需要将其创建git仓库,并托管到git托管网站去。
|
||||
|
||||
.. hint::
|
||||
|
||||
考虑到国内绝大部分人的访问速度,综合国内几家git托管平台,建议使用gitee。
|
||||
|
||||
大多数人可能从未用过git,并且git上手的门槛并不低,因此以下会对涉及git的操作进行详尽的解说。
|
||||
|
@ -99,6 +100,8 @@ cmd弹出命令行窗口,输入git命令,如果出来一长串英文说明
|
|||
|
||||
一种最常见的发布mod方式是把mod打包成zip,发到公共平台上供玩家下载。这种办法虽然可行,但并不是fk推荐的做法。
|
||||
|
||||
.. hint::
|
||||
|
||||
以下介绍的其实就是新建仓库并推送到gitee的办法,熟悉git者请跳过。
|
||||
|
||||
下面着重介绍用git发布mod的办法。使用git进行发布的话,就可以让用户体验在线安装、在线更新等便捷之处。
|
||||
|
|
|
@ -22,7 +22,7 @@ fk的技能分为两大类,这两大类又各自细分为更小的分类:
|
|||
- 卡牌增强技(TargetModSkill):影响卡牌使用次数上限、目标上限、距离限制等等的技能
|
||||
- 锁定视为技(FilterSkill):让一张牌强制视为另一张牌的技能
|
||||
|
||||
其中,触发技的逻辑最为复杂,但是\ `已经在这里分析过了 <../dev/gamelogic.rst>`__\ ,故不再赘述。
|
||||
其中,触发技的逻辑最为复杂,但是\ :doc:`已经在这里分析过了 <../dev/gamelogic>`\ ,故不再赘述。
|
||||
|
||||
主动技和状态技应该不算难,先按下不表。视为技与神杀有所区别,区别如下:
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@ fk中的游戏事件
|
|||
|
||||
在进行DIY时,需要对三国杀的规则有一定了解;在编写技能时,也要熟悉游戏提供的各种事件,他的触发方式、触发时机、相关数据。必须要知道这些才能写出正确的代码。
|
||||
|
||||
下面的内容介绍的Fk涉及的诸多游戏事件。对于事件具体流程的描述仅限于如何触发各种时机而已。也有可能稍微多聊一些其他方面的事情。
|
||||
|
||||
描述触发时机以及事件详细流程的时候,使用的直接就是类似Lua的伪代码,其实你直接看源码都能得到差不多的效果。
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: 事件列表
|
||||
|
|
|
@ -107,7 +107,7 @@ fk本身不内置多少技能,但玩家还是可以给武将添加已有的技
|
|||
|
||||
保存一下,进游戏就能发现多了个技能。
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-da0d53b6996941de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
.. figure:: ../pic/diy3-pic1.webp
|
||||
:alt: 添加已有技能
|
||||
|
||||
添加已有技能
|
||||
|
@ -123,23 +123,13 @@ fk本身不内置多少技能,但玩家还是可以给武将添加已有的技
|
|||
|
||||
fk中,武将的图片应该为250x292分辨率,并且是jpg格式。为了观感舒适,武将的人脸应该位于图片的中上方。
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-7b08fd53820d4160.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
.. figure:: ../pic/diy3-pic2.webp
|
||||
:alt: 使用GIMP切图。我倾向于开5x5参考线,并让人脸位于2行3列的格子里面
|
||||
|
||||
使用GIMP切图。我倾向于开5x5参考线,并让人脸位于2行3列的格子里面
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-a629150ce8a4eac8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
:alt: 使用GIMP切图后,将尺寸缩到需要的分辨率
|
||||
|
||||
使用GIMP切图后,将尺寸缩到需要的分辨率
|
||||
|
||||
最后用jpg格式导出图片,图片的名字是武将的内部名称,在这里就是study_sunce。
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-7093b57e9cb53118.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
:alt: 导出JPG
|
||||
|
||||
导出JPG
|
||||
|
||||
注意了,JPG图片的质量不能拉到100%,不然图片体积会很大,给他人下载你的拓展包带来不便。一般质量为90为好,此时图片大约三四十KB大小。这里图像质量只调了60,这样看起来不至于完全失真,图片的体积也相当较小。
|
||||
|
||||
至此我们做好了图片,接下来就是把图片放到游戏去。
|
||||
|
@ -154,12 +144,7 @@ fk中,武将的图片应该为250x292分辨率,并且是jpg格式。为了
|
|||
│ └── study_sunce.jpg
|
||||
└── init.lua
|
||||
|
||||
然后打开游戏就能看到武将的图片了:
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-faafcd3e899f241b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
:alt: 效果还不错吧
|
||||
|
||||
效果还不错吧
|
||||
然后打开游戏,进入武将一览,就能看到武将的图片了。
|
||||
|
||||
--------------
|
||||
|
||||
|
@ -170,12 +155,7 @@ fk中,武将的图片应该为250x292分辨率,并且是jpg格式。为了
|
|||
|
||||
怎么处理mp3音频就不叙述了,可以考虑用audacity这款软件调节mp3的音量、去掉首尾的延迟等等。但是依然需要注意一点——mp3语音的体积不能太大了。为此我的建议是使用格式工厂对mp3文件再进行一次格式转换,将转换后mp3文件的码率设为128kbps,这样一来一句语音差不多就是三四十KB的感觉,而音质却不至于非常模糊。
|
||||
|
||||
阵亡语音放到拓展包文件夹下的audio/death里面,命名规则是武将的内部名称。如图所示:
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-1ce5c371b425638e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
:alt: 阵亡语音的命名,以及存放位置
|
||||
|
||||
阵亡语音的命名,以及存放位置
|
||||
阵亡语音放到拓展包文件夹下的audio/death里面,命名规则是武将的内部名称。
|
||||
|
||||
--------------
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ fk体量实在太小,只有标包,欲玩到更多技能,还是得自己亲
|
|||
|
||||
启动游戏试试看,却给我们甩了个报错:
|
||||
|
||||
.. image:: https://upload-images.jianshu.io/upload_images/21666547-b032b4f43ad13b58.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
.. image:: ../pic/diy4-pic1.webp
|
||||
|
||||
原来是这个复制粘贴的技能和已有的英姿重复了。解法很简单,换个名字就行了,这里改名为“激姿”好了。按照命名习惯,为他起一个内部名称”study_jizi”。然后把所有的yingzi都改成这个名,改名后如下:
|
||||
|
||||
|
@ -78,11 +78,6 @@ fk体量实在太小,只有标包,欲玩到更多技能,还是得自己亲
|
|||
|
||||
至此完事了。别忘了更新一下git,后面不赘述关于git的事情了。
|
||||
|
||||
.. figure:: https://upload-images.jianshu.io/upload_images/21666547-f4c76ee91f8c15ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240
|
||||
:alt: 搞定,一摸就是6张,薄纱神郭嘉
|
||||
|
||||
搞定,一摸就是6张,薄纱神郭嘉
|
||||
|
||||
--------------
|
||||
|
||||
稍微解说一下创建技能的语法
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
技能解析:触发技
|
||||
======================
|
||||
|
||||
在上回中,我们创造了第一个技能“激姿”,就是一个改造版的英姿,它的作用是摸牌阶段摸牌时候让摸牌数+4。
|
||||
|
||||
像这种在游戏特定时机被触发的技能,就称为触发技,它们通常都是形如“当xxx时,你可以xxx”的技能。
|
||||
|
||||
下面来介绍触发技。首先介绍触发技的几个基本函数,再说明触发技的执行流程,最后说明怎么创建触发技。这篇文章大多为比较无聊的概念解析,也没有实操,建议自己对着已经写好的触发技实操。
|
||||
|
||||
触发技的基本函数
|
||||
--------------------
|
||||
|
||||
触发技中涉及这些函数:
|
||||
|
||||
- ``can_trigger`` :技能能否被触发?
|
||||
- ``on_trigger`` :技能是如何执行的?
|
||||
- ``on_cost`` :技能的执行消耗是什么?
|
||||
- ``on_use`` :技能正式发动后,执行什么代码?
|
||||
|
||||
所有这些函数的函数原型全都是一样的:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
---@param self TriggerSkill
|
||||
---@param event Event
|
||||
---@param target ServerPlayer
|
||||
---@param player ServerPlayer
|
||||
---@param data any
|
||||
function(self, event, target, player, data)
|
||||
end
|
||||
|
||||
这个函数原型还是稍微有些难以理解,得结合触发技的具体执行流程来看。
|
||||
|
||||
触发技的执行流程
|
||||
--------------------
|
||||
|
||||
第一步 触发一个时机
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
触发技若是想要被发动,那么肯定就先要有时机被触发了。而用来触发事件的函数就是如下这位:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
---@param event Event
|
||||
---@param target ServerPlayer
|
||||
---@param data any
|
||||
function GameLogic:trigger(event, target, data) end
|
||||
|
||||
直接调查这个函数的代码就能知道触发技执行的所有细节了。但这个函数并没有那么好懂,故在此进行说明。
|
||||
|
||||
首先,从这个函数可以看出,某一个触发时机一共有三要素:
|
||||
|
||||
- ``event`` :具体是哪个触发时机。
|
||||
- ``target`` :这个触发时机涉及的玩家,这名玩家在后面会称为“时机的承担者”。
|
||||
- ``data`` :可以是任何值,视具体时机而定。
|
||||
|
||||
首先,event是这个时机具体是什么,比如“受到伤害后”( ``fk.Damaged`` );target则是时机的承担者,比如“受到伤害后”这个时机,承担者就是此次伤害的目标;data就完完全全是根据时机而定了。
|
||||
|
||||
想要知道某个时机具体对应着哪个target和data,最直接的办法就是直接从源码中找到trigger函数调用的点了,这样一下子就知道这个时机的相关数据了。不过呢,文档后面也是会一一列出的,毕竟有些时机的data还是多少复杂了点。
|
||||
|
||||
第一步(续) 假设出一个例子情景
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
在开始接下来的解说之前,还是想象一下有这么一桌军五吧:
|
||||
|
||||
::
|
||||
|
||||
郭嘉 司马懿
|
||||
|
||||
*关羽 -------杀------> 郭嘉 -1
|
||||
|
||||
周瑜(一号位)
|
||||
|
||||
如图所示,关羽杀郭嘉(二号位),郭嘉掉血,此时执行到了伤害流程的“受到伤害后”时机。
|
||||
|
||||
假设当前回合的角色是关羽。
|
||||
|
||||
假设郭嘉拥有在这个时机可以发动的技能“遗计”,其代码如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local easy_yiji = fk.CreateTriggerSkill{
|
||||
name = "easy_yiji",
|
||||
events = {fk.Damaged},
|
||||
on_use = function(self, event, target, player, data)
|
||||
player:drawCards(2)
|
||||
end,
|
||||
}
|
||||
|
||||
为了简化说明,这是是一段简化版的遗计代码。其作用是受到伤害后,可以摸两张牌。
|
||||
|
||||
前面说到一个触发技得有4种函数,而这里却只有个 ``on_use`` 啊。这是因为其他三个函数此处可以取默认值,所以实际写Lua的时候省略掉了。为了便于说明,现在将这4个函数补全(包括默认情况):
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local easy_yiji = fk.CreateTriggerSkill{
|
||||
name = "easy_yiji",
|
||||
events = {fk.Damaged},
|
||||
can_trigger = function(self, event, target, player, data)
|
||||
return target == player and target:hasSkill(self.name)
|
||||
end,
|
||||
on_trigger = function(self, event, target, player, data)
|
||||
return self:doCost(event, target, player, data)
|
||||
end,
|
||||
on_cost = function(self, event, target, player, data)
|
||||
return player.room:askForSkillInvoke(player, self.name)
|
||||
end,
|
||||
on_use = function(self, event, target, player, data)
|
||||
player:drawCards(2)
|
||||
end,
|
||||
}
|
||||
|
||||
这里假设出来的情景是“受到伤害后”时机,写成代码就是
|
||||
|
||||
.. code:: lua
|
||||
|
||||
logic:trigger(fk.Damaged, guojia, data)
|
||||
|
||||
这里不关心data。第二个参数guojia表示受到伤害后的那个郭嘉。注意场上有两个郭嘉,这是为了后面详细解释而安排的。
|
||||
|
||||
第二步 遍历场上玩家
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
现在的时机是fk.Damaged,刚好遗计的时机也是fk.Damaged,所以遗计就能在这个时机发动了。隔壁司马懿也有个反馈能在这个时机发动。所以现在能够在该时机发动的技能有:遗计、反馈。
|
||||
|
||||
假设反馈的代码和上文的遗计一模一样,只是技能名不同罢了。
|
||||
|
||||
确定了可能可以发动的技能后,Fk就会从当前回合角色开始,对所有角色进行遍历。每一趟遍历的步骤如下:
|
||||
|
||||
1. 把当前正在遍历到的玩家称为player。
|
||||
2. 执行 ``can_trigger(self, event, target, player, data)``
|
||||
3. 如果第二步的执行返回了true,就执行 ``on_trigger`` 。
|
||||
|
||||
事已至此,触发技函数中的参数也基本明朗了:
|
||||
|
||||
- ``self`` :这个技能本身。
|
||||
- ``event`` :当前的触发时机。
|
||||
- ``target`` :时机的承担者。
|
||||
- ``player`` :当前被遍历到的玩家。
|
||||
- ``data`` : ``logic:trigger`` 函数中传入的那个额外的data参数。
|
||||
|
||||
下面进行针对前面那桌军五,模拟一下这么个遍历流程。
|
||||
|
||||
::
|
||||
|
||||
可能可以发动的技能: 遗计,反馈
|
||||
当前回合角色:关羽
|
||||
当前时机:受到伤害后
|
||||
时机的承担者(target):郭嘉 - 二号位
|
||||
当前的data:没人在意data
|
||||
|
||||
对 关羽 进行遍历,令 player 为 关羽
|
||||
-> 遗计的can_trigger:失败,target ~= player
|
||||
-> 反馈的can_trigger:失败,target ~= player
|
||||
|
||||
对 周瑜 进行遍历,令 player 为 周瑜
|
||||
-> 遗计的can_trigger:失败,target ~= player
|
||||
-> 反馈的can_trigger:失败,target ~= player
|
||||
|
||||
对 郭嘉二号位 进行遍历,令 player 为 郭嘉二号位
|
||||
-> 遗计的can_trigger:通过,target == player and player:hasSkill(self.name)
|
||||
-> 遗计的 on_trigger 开始执行
|
||||
-> 执行 TriggerSkill:doCost
|
||||
-> 反馈的can_trigger:失败,target == player,但是player:hasSkill(反馈)为false,郭嘉不会反馈
|
||||
|
||||
对 司马懿 进行遍历,令 player 为 司马懿
|
||||
-> 遗计的can_trigger:失败,target ~= player
|
||||
-> 反馈的can_trigger:失败,target ~= player,虽然player拥有技能反馈
|
||||
|
||||
对 郭嘉四号位 进行遍历,令 player 为 郭嘉四号位
|
||||
-> 遗计的can_trigger:失败,target ~= player
|
||||
-> 反馈的can_trigger:失败,target ~= player
|
||||
|
||||
遍历结束了,本次触发时机也随之结束了。
|
||||
|
||||
从上面的实机演练中我们差不多能明白 ``can_trigger`` 和 ``on_trigger`` 的执行流程。
|
||||
|
||||
.. note::
|
||||
|
||||
在实际的执行中,其实是先都执行 ``can_trigger`` ,然后将所有通过的技能暂存在表中,玩家可以从这里面选出自己想要先发动的技能,然后再去执行那个技能的 ``on_trigger`` 。
|
||||
|
||||
第三步 询问消耗执行,以及正式发动技能
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
而 ``on_cost`` 和 ``on_use`` ,则是在on_trigger中调用doCost函数时候调用的。doCost的内容如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
-- do cost and skill effect.
|
||||
-- DO NOT modify this function
|
||||
function TriggerSkill:doCost(event, target, player, data)
|
||||
local ret = self:cost(event, target, player, data)
|
||||
if ret then
|
||||
return player.room:useSkill(player, self, function()
|
||||
return self:use(event, target, player, data)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
在这段代码中,首先执行一下cost函数(也就是这里聊的on_use),如果返回true,那么调用useSkill函数正式发动技能。useSkill函数先播放技能发动的特效、增加技能发动次数,再去调用传入的第三个函数(这里就是on_use了)。
|
||||
|
||||
这也就是说,on_cost函数掌握的是技能是否确实要发动,用户得在这里做出自己的选择。如果用户作出了肯定的答复,那么on_cost就返回true,这之后技能发动次数的历史记录便加一,然后开始真正执行技能的效果。
|
||||
|
||||
创建触发技的办法
|
||||
------------------
|
||||
|
||||
要创建一个触发技,我们使用 ``fk.CreateTriggerSkill`` 函数。该函数接收一个表作为参数,表中各种键值的含义如下:
|
||||
|
||||
- ``name`` :技能名。别和其他技能重名了。
|
||||
- ``frequency`` :技能的发动频率,可能是锁定技。
|
||||
- ``anim_type`` :技能的动画类型。上一篇好像已经聊过了。
|
||||
- ``mute`` :技能是否静默。
|
||||
|
||||
.. tip::
|
||||
|
||||
静默的技能不会播放配音、动画、发log,如果你想播放配音,就得自己手动做这些工作。
|
||||
有些需要根据情况手动播放相应配音的技能,比如自书、英魂等,就得先设为静默,然后自己去技能发动的环节添加这些跟播放特效有关的代码。
|
||||
|
||||
上面这4项其实是对所有技能都通用的。下面是一些触发技专用的:
|
||||
|
||||
- ``global`` :是否是全局技能。全局技能必定会参与到遍历中。
|
||||
- ``events`` :一个数组,保存着可能可以触发这个技能的所有时机。
|
||||
- ``can_trigger`` :触发该技能的条件。
|
||||
- ``on_trigger`` :技能触发的内容。这个函数一般是自定义如何去询问发动、发动几次的。总之自定义的话,记得在里面调用doCost进行实际的询问和生效就行了。
|
||||
- ``on_cost`` :技能生效前要对玩家进行询问的内容,或者说是“消耗”。
|
||||
- ``on_use`` :技能生效环节。
|
||||
|
||||
.. danger::
|
||||
|
||||
除非万不得已,不要把技能的global设为true!global技能在任何情况下都会被纳入游戏的处理范围,随着global的增多,遍历的技能也会变多,这会使游戏的性能下降!
|
||||
|
||||
有些时候我们不希望增加技能发动的次数,只想执行一些代码而已,比如说清理掉某些不可见标记等等。为了实现这个效果,触发技中还有一种称为“refresh”的行为(相对于发动技能的“use”),创建触发技的时候可以用这些来指定:
|
||||
|
||||
- ``refresh_events`` :可能触发refresh的所有时机。
|
||||
- ``can_refresh`` :类似 ``can_trigger`` ,只不过是针对refresh的。注意这个函数没有默认值。
|
||||
- ``on_refresh`` :类似 ``on_trigger`` ,但是是针对refresh。
|
||||
|
||||
refresh和实际发动技能也差不多,一样的遍历,判断can_refresh,执行on_refresh。在实际trigger中,是 **先执行refresh,再执行use** 。
|
|
@ -0,0 +1,35 @@
|
|||
技能解析:主动技
|
||||
================
|
||||
|
||||
上篇说到的触发技是在满足某个时机之后“被动”发动的,而本文将要阐述的技能则是在出牌阶段空闲的时候主动发动的。
|
||||
|
||||
在技能显示页面中,主动技是有一个按钮可以按下去的,其他技能就只是文字而已。
|
||||
|
||||
接下先看看如何创建主动技,再来简述一下主动技是如何发挥效果的。
|
||||
|
||||
创建主动技
|
||||
----------
|
||||
|
||||
创建主动技使用的是 ``fk.CreateActiveSkill`` 函数。这个函数和创建触发技一样,接收的参数也是一个表,表中可以指定 ``name`` 、 ``frequency`` 、 ``anim_type`` 、 ``mute`` 这四个属性,以及这些主动技特有的函数/属性:
|
||||
|
||||
- ``can_use`` :函数原型为 ``fun(self, player)`` ,用来判断当前空闲时间点能不能使用该技能。
|
||||
- ``card_filter`` :函数原型为 ``fun(self, to_select, selected, selected_targets)`` ,用来判断某张卡牌能不能被这个技能选择。
|
||||
- ``target_filter`` :函数原型为 ``fun(self, to_select, selected, selected_cards)`` ,用来判断某名角色能不能被技能选择。
|
||||
- ``target_num`` :为了能点击确定键,需要选择的角色数量。
|
||||
- ``card_num`` :为了能点击确定键,需要选择的卡牌数量。
|
||||
- ``max_target_num`` :能点击确定键的最大选择角色数量,默认999
|
||||
- ``min_target_num`` :能点击确定键的最小选择角色数量,默认0
|
||||
- ``max_card_num`` :能点击确定键的最大选牌数量,默认999
|
||||
- ``min_card_num`` :能点击确定键的最小选牌数量,默认0
|
||||
- ``on_use`` :主动技生效部分,后面再说
|
||||
|
||||
主动技生效之前的流程
|
||||
--------------------
|
||||
|
||||
首先,每当玩家即将进行出牌阶段的一次出牌之前,游戏会先做出判断,来确定按钮是否能被按下。
|
||||
|
||||
对于某个技能而言,判断按钮是否被点亮就是通过 ``can_use`` 。返回true的话就能点亮。
|
||||
|
||||
然后,当技能按钮被按下后,就需要对手牌/装备含有的所有卡牌,以及场上所有角色,都判断能不能点亮。
|
||||
|
||||
TODO!
|
|
@ -1,14 +1,117 @@
|
|||
与体力值相关的事件
|
||||
==================
|
||||
|
||||
以下列出了一些和体力值改变有关的事件。
|
||||
|
||||
改变体力
|
||||
--------
|
||||
|
||||
涉及的类如下:
|
||||
|
||||
.. lua:autoclass:: HpChangedData
|
||||
|
||||
事件流程如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local data = HpChangedData
|
||||
local player = xxx -- 体力变动的那位角色
|
||||
|
||||
-- 先触发“体力变化前”时机 ** 可中断 **
|
||||
logic:trigger(fk.BeforeHpChanged, player, data)
|
||||
|
||||
-- 然后对player的hp作出修改
|
||||
|
||||
-- 最后触发“体力变化后”时机
|
||||
logic:trigger(fk.HpChanged, player, data)
|
||||
|
||||
-- 如果体力变化之后,玩家的hp < 1
|
||||
-- 并且这次体力变化的变化量是负数,那么进入濒死阶段
|
||||
|
||||
伤害
|
||||
----
|
||||
|
||||
失去体力/体力上限
|
||||
-----------------
|
||||
涉及的类如下:
|
||||
|
||||
.. lua:autoclass:: DamageStruct
|
||||
|
||||
在整个伤害事件中,触发时机时候传递的data都是DamageStruct类型。
|
||||
|
||||
事件的流程如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local data = DamageStruct
|
||||
-- 下面的data.from是伤害来源,data.to是伤害目标
|
||||
|
||||
-- 在处理过程中,如果伤害目标死了,事件就结束。
|
||||
|
||||
-- 触发时机“伤害结算开始前” ** 可中断 **
|
||||
logic:trigger(fk.PreDamage, data.from, data)
|
||||
|
||||
-- 触发时机“造成伤害时” ** 可中断 **
|
||||
logic:trigger(fk.DamageCaused, data.from, data)
|
||||
|
||||
-- 触发时机“受到伤害时” ** 可中断 **
|
||||
logic:trigger(fk.DamageInflicted, data.to, data)
|
||||
|
||||
-- 进行一个“改变体力”事件,以修改伤害目标的体力
|
||||
|
||||
-- 触发时机“造成伤害后”
|
||||
logic:trigger(fk.Damage, data.from, data)
|
||||
|
||||
-- 触发时机“受到伤害后”
|
||||
logic:trigger(fk.Damaged, data.to, data)
|
||||
|
||||
-- 触发时机“伤害结算完成后”
|
||||
logic:trigger(fk.DamageFinished, data.from, data)
|
||||
|
||||
|
||||
失去体力
|
||||
--------
|
||||
|
||||
涉及的类如下:
|
||||
|
||||
.. lua:autoclass:: HpLostData
|
||||
|
||||
流程如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local data = HpLostData
|
||||
local player = xxx -- 失去体力的那位角色
|
||||
|
||||
-- 触发时机“失去体力前” ** 可中断 **
|
||||
logic:trigger(fk.PreHpLost, player, data)
|
||||
|
||||
-- 进行一次“改变体力”事件,以更新受害者的hp
|
||||
|
||||
-- 触发时机“失去体力后”
|
||||
logic:trigger(fk.HpLost, player, data)
|
||||
|
||||
回复体力
|
||||
--------
|
||||
|
||||
濒死和死亡
|
||||
----------
|
||||
涉及的类如下:
|
||||
|
||||
.. lua:autoclass:: RecoverStruct
|
||||
|
||||
流程如下:
|
||||
|
||||
.. code:: lua
|
||||
|
||||
local data = HpLostData
|
||||
local player = xxx -- 失去体力的那位角色
|
||||
|
||||
-- 触发时机“回复体力前” ** 可中断 **
|
||||
logic:trigger(fk.PreHpRecover, player, data)
|
||||
|
||||
-- 进行一次“改变体力”事件,以更新回复者的hp
|
||||
|
||||
-- 触发时机“回复体力后”
|
||||
logic:trigger(fk.HpRecover, player, data)
|
||||
|
||||
改变体力上限
|
||||
-------------
|
||||
|
||||
TODO
|
||||
|
|
|
@ -8,4 +8,5 @@ Diy文档
|
|||
02-skilltype.rst
|
||||
03-newgeneral.rst
|
||||
04-newskill.rst
|
||||
05-trigger.rst
|
||||
03-events.rst
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usr/index.rst
|
||||
diy/index.rst
|
||||
dev/index.rst
|
||||
api/index.rst
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
TEX_FILE=manual.tex
|
||||
cd build/latex
|
||||
|
||||
# 给所有的标题加一个层级
|
||||
|
||||
if ! grep '\\part' $TEX_FILE; then
|
||||
sed -i 's/\\chapter/\\part/g' $TEX_FILE
|
||||
sed -i 's/\\section/\\chapter/g' $TEX_FILE
|
||||
sed -i 's/\\subsection/\\section/g' $TEX_FILE
|
||||
sed -i 's/\\subsubsection/\\subsection/g' $TEX_FILE
|
||||
sed -i 's/\\paragraph/\\subsubsection/g' $TEX_FILE
|
||||
sed -i 's/\\subparagraph/\\paragraph/g' $TEX_FILE
|
||||
fi
|
||||
|
||||
# webp转jpg
|
||||
sed -i 's/webp/jpg/g' $TEX_FILE
|
||||
for webp in *.webp; do
|
||||
convert $webp -background white -alpha remove ${webp%%webp}jpg
|
||||
done
|
||||
|
||||
# 好了,开始做pdf
|
||||
make
|
||||
|
||||
cd ../..
|
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -1,2 +1,2 @@
|
|||
sphinx-lua
|
||||
sphinx-rtd-theme
|
||||
sphinx-book-theme
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
下载FK
|
||||
========
|
||||
|
||||
FreeKill目前提供Windows版和安卓版下载。
|
||||
|
||||
下载链接:
|
||||
|
||||
https://github.com/Notify-ctrl/FreeKill/release
|
||||
|
||||
https://gitee.com/notify-ctrl/FreeKill/release
|
||||
|
||||
其中,apk文件就是安卓版,直接下载安装;7z文件是windows版,下载并解压缩后即可运行。
|
|
@ -0,0 +1,12 @@
|
|||
游玩FK
|
||||
========
|
||||
|
||||
进入FK之后首先是登录界面。先随意输入用户名和密码,然后单机启动,就能进入游戏大厅。
|
||||
|
||||
在大厅中,可以查看武将、卡牌等,或者对游戏进行配置。
|
||||
|
||||
点击“创建房间”,就会弹出创房对话框,然后做好配置后创建房间就行了。
|
||||
|
||||
进入房间后,就进入了游戏画面。此时点击屏幕中间的添加机器人按钮即可添加机器人,人满之后游戏开始。
|
||||
|
||||
在游戏中,随着流程的推进你将会面临各种交互,比如做出选项、思考如何出牌等等。运用手中的各种卡牌和技能,击败敌人,获取胜利吧。
|
|
@ -0,0 +1,16 @@
|
|||
联机游玩FK
|
||||
===========
|
||||
|
||||
在登录界面输入服务器IP,再输入自己的用户名、密码即可连接到服务器中。
|
||||
|
||||
请记住自己的密码!当然了,FK也带有记住密码的功能。
|
||||
|
||||
在游戏大厅中,你可以自己创建房间,也可以加入已有房间游戏。
|
||||
|
||||
其他人也可以加入这个服务器,这样就是多人游玩了。
|
||||
|
||||
想要自己开服联机的话,先在自己的电脑上单机启动,然后用内网穿透等手段获取公网IP,然后别人就能通过这个IP连接到你的服务器中。
|
||||
|
||||
或者,在命令行中使用 ``./FreeKill -s`` 或者 ``.\FreeKill.exe -s`` ,前者是针对Linux服务器的命令。
|
||||
|
||||
Linux服务器开服的话需要自己编译。
|
|
@ -0,0 +1,12 @@
|
|||
拓展包管理
|
||||
===========
|
||||
|
||||
在登录界面中有一个拓展包管理按钮。
|
||||
|
||||
在拓展包管理中,你可以安装、卸载、禁用、启动拓展包。
|
||||
|
||||
当获知拓展包的URL后,就可以自己安装它。
|
||||
|
||||
在连接到服务器的时候,会自动同步所有拓展包。
|
||||
|
||||
想要自己做拓展包的话,还请继续阅读后文。
|
|
@ -0,0 +1,12 @@
|
|||
入门FK
|
||||
========
|
||||
|
||||
本章讲述了如何下载、游玩FK等等。
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
00-download.rst
|
||||
01-play.rst
|
||||
02-connect.rst
|
||||
03-package.rst
|
|
@ -1,14 +1,18 @@
|
|||
--- Card记录了FreeKill所有卡牌的基础信息。
|
||||
---
|
||||
--- 它包含了ID、所属包、牌名、花色、点数等等
|
||||
---
|
||||
---@class Card : Object
|
||||
---@field public id integer
|
||||
---@field public package Package
|
||||
---@field public name string
|
||||
---@field public suit Suit
|
||||
---@field public number integer
|
||||
---@field public trueName string
|
||||
---@field public color Color
|
||||
---@field public type CardType
|
||||
---@field public sub_type CardSubtype
|
||||
---@field public area CardArea
|
||||
---@field public id integer @ 标志某一张卡牌唯一的数字,从1开始。若此牌是虚拟牌,则其id为0。服务器启动时为卡牌赋予ID。
|
||||
---@field public package Package @ 卡牌所属的扩展包
|
||||
---@field public name string @ 卡牌的名字
|
||||
---@field public suit Suit @ 卡牌的花色(四色及无花色)
|
||||
---@field public number integer @ 卡牌的点数(0到K)
|
||||
---@field public trueName string @ 卡牌的真名,一般用于分辨杀。
|
||||
---@field public color Color @ 卡牌的颜色(分为黑色、红色、无色)
|
||||
---@field public type CardType @ 卡牌的种类(基本牌、锦囊牌、装备牌)
|
||||
---@field public sub_type CardSubtype @ 卡牌的子种类(例如延时锦囊牌、武器、防具等)
|
||||
---@field public area CardArea @ 卡牌所在区域(例如手牌区,判定区,装备区,牌堆,弃牌堆···)
|
||||
---@field public subcards integer[]
|
||||
---@field public skillName string @ for virtual cards
|
||||
---@field public skill Skill
|
||||
|
@ -57,6 +61,7 @@ Card.DrawPile = 6
|
|||
Card.DiscardPile = 7
|
||||
Card.Void = 8
|
||||
|
||||
--- Card的构造函数。具体负责构建Card实例的函数,请参见fk_ex部分。
|
||||
function Card:initialize(name, suit, number, color)
|
||||
self.name = name
|
||||
self.suit = suit or Card.NoSuit
|
||||
|
@ -84,9 +89,12 @@ function Card:initialize(name, suit, number, color)
|
|||
self.skillName = ""
|
||||
end
|
||||
|
||||
---@param suit Suit
|
||||
---@param number integer
|
||||
---@return Card
|
||||
--- 克隆特定卡牌并赋予花色与点数。
|
||||
---
|
||||
--- 会将skill/special_skills/equip_skill继承到克隆牌中。
|
||||
---@param suit Suit @ 克隆后的牌的花色
|
||||
---@param number integer @ 克隆后的牌的点数
|
||||
---@return Card @ 产品
|
||||
function Card:clone(suit, number)
|
||||
local newCard = self.class:new(self.name, suit, number)
|
||||
newCard.skill = self.skill
|
||||
|
@ -95,10 +103,15 @@ function Card:clone(suit, number)
|
|||
return newCard
|
||||
end
|
||||
|
||||
--- 检测是否为虚拟卡牌,如果其ID为0及以下,则为虚拟卡牌。
|
||||
function Card:isVirtual()
|
||||
return self.id <= 0
|
||||
end
|
||||
|
||||
--- 获取卡牌的ID。
|
||||
---
|
||||
--- 如果牌是虚拟牌,则返回其第一张子卡的id,没有子卡就返回nil
|
||||
---@return integer | nil
|
||||
function Card:getEffectiveId()
|
||||
if self:isVirtual() then
|
||||
return #self.subcards > 0 and self.subcards[1] or nil
|
||||
|
@ -129,7 +142,8 @@ local function updateColorAndNumber(card)
|
|||
card.number = number
|
||||
end
|
||||
|
||||
---@param card integer|Card
|
||||
--- 将一张子卡牌加入某张牌中(是addSubcards的基础函数,常用addSubcards)。
|
||||
---@param card integer|Card @ 要加入的子卡
|
||||
function Card:addSubcard(card)
|
||||
if type(card) == "number" then
|
||||
table.insert(self.subcards, card)
|
||||
|
@ -142,21 +156,27 @@ function Card:addSubcard(card)
|
|||
updateColorAndNumber(self)
|
||||
end
|
||||
|
||||
--- 将一批子卡牌加入某张牌中(常用于将这批牌弃置/交给某个角色···)。
|
||||
---@param cards integer[] | Card[] @ 要加入的子卡列表
|
||||
function Card:addSubcards(cards)
|
||||
for _, c in ipairs(cards) do
|
||||
self:addSubcard(c)
|
||||
end
|
||||
end
|
||||
|
||||
--- 清空加入某张牌中的子卡牌。
|
||||
function Card:clearSubcards()
|
||||
self.subcards = {}
|
||||
updateColorAndNumber(self)
|
||||
end
|
||||
|
||||
--- 判断此牌能否符合一个卡牌规则。
|
||||
function Card:matchPattern(pattern)
|
||||
return Exppattern:Parse(pattern):match(self)
|
||||
end
|
||||
|
||||
--- 获取卡牌花色并返回花色文字描述(如 黑桃、红桃、梅花、方块)。
|
||||
---@return string @ 描述花色的字符串
|
||||
function Card:getSuitString()
|
||||
local suit = self.suit
|
||||
if suit == Card.Spade then
|
||||
|
@ -172,6 +192,8 @@ function Card:getSuitString()
|
|||
end
|
||||
end
|
||||
|
||||
--- 获取卡牌颜色并返回点数颜色描述(例如黑色/红色/无色)。
|
||||
---@return string @ 描述颜色的字符串
|
||||
function Card:getColorString()
|
||||
local color = self.color
|
||||
if color == Card.Black then
|
||||
|
@ -182,6 +204,7 @@ function Card:getColorString()
|
|||
return "nocolor"
|
||||
end
|
||||
|
||||
--- 获取卡牌类型并返回点数类型描述(例如基本牌/锦囊牌/装备牌)。
|
||||
function Card:getTypeString()
|
||||
local t = self.type
|
||||
if t == Card.TypeBasic then
|
||||
|
@ -194,6 +217,7 @@ function Card:getTypeString()
|
|||
return "notype"
|
||||
end
|
||||
|
||||
--- 获取卡牌点数并返回点数文字描述(仅限A/J/Q/K)。
|
||||
local function getNumberStr(num)
|
||||
if num == 1 then
|
||||
return "A"
|
||||
|
@ -208,6 +232,7 @@ local function getNumberStr(num)
|
|||
end
|
||||
|
||||
-- for sendLog
|
||||
--- 获取卡牌的文字信息并准备作为log发送。
|
||||
function Card:toLogString()
|
||||
local ret = string.format('<font color="#0598BC"><b>%s</b></font>', Fk:translate(self.name) .. "[")
|
||||
if self:isVirtual() then
|
||||
|
@ -222,6 +247,7 @@ function Card:toLogString()
|
|||
return ret
|
||||
end
|
||||
|
||||
--- 静态方法。传入下列类型之一的参数,返回id列表。
|
||||
---@param c integer|integer[]|Card|Card[]
|
||||
---@return integer[]
|
||||
function Card:getIdList(c)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,15 +31,17 @@
|
|||
---@field public toCard Card
|
||||
---@field public winner ServerPlayer|null
|
||||
|
||||
--- 描述和一次体力变化有关的数据
|
||||
---@class HpChangedData
|
||||
---@field public num integer
|
||||
---@field public reason string
|
||||
---@field public skillName string
|
||||
---@field public damageEvent DamageStruct|null
|
||||
---@field public num integer @ 体力变化量,可能是正数或者负数
|
||||
---@field public reason string @ 体力变化原因
|
||||
---@field public skillName string @ 引起体力变化的技能名
|
||||
---@field public damageEvent DamageStruct|nil @ 引起这次体力变化的伤害数据
|
||||
|
||||
--- 描述跟失去体力有关的数据
|
||||
---@class HpLostData
|
||||
---@field public num integer
|
||||
---@field public skillName string
|
||||
---@field public num integer @ 失去体力的数值
|
||||
---@field public skillName string @ 导致这次失去的技能名
|
||||
|
||||
---@alias DamageType integer
|
||||
|
||||
|
@ -47,22 +49,24 @@ fk.NormalDamage = 1
|
|||
fk.ThunderDamage = 2
|
||||
fk.FireDamage = 3
|
||||
|
||||
--- DamageStruct 用来描述和伤害事件有关的数据。
|
||||
---@class DamageStruct
|
||||
---@field public from ServerPlayer|null
|
||||
---@field public to ServerPlayer
|
||||
---@field public damage integer
|
||||
---@field public card Card
|
||||
---@field public chain boolean
|
||||
---@field public damageType DamageType
|
||||
---@field public skillName string
|
||||
---@field public beginnerOfTheDamage boolean|null
|
||||
---@field public from ServerPlayer|null @ 伤害来源
|
||||
---@field public to ServerPlayer @ 伤害目标
|
||||
---@field public damage integer @ 伤害值
|
||||
---@field public card Card | nil @ 造成伤害的牌
|
||||
---@field public chain boolean @ 伤害是否是铁索传导的伤害
|
||||
---@field public damageType DamageType @ 伤害的属性
|
||||
---@field public skillName string @ 造成本次伤害的技能名
|
||||
---@field public beginnerOfTheDamage boolean @ 是否是本次铁索传导的起点
|
||||
|
||||
--- 用来描述和回复体力有关的数据。
|
||||
---@class RecoverStruct
|
||||
---@field public who ServerPlayer
|
||||
---@field public num integer
|
||||
---@field public recoverBy ServerPlayer|null
|
||||
---@field public skillName string|null
|
||||
---@field public card Card|null
|
||||
---@field public who ServerPlayer @ 回复体力的角色
|
||||
---@field public num integer @ 回复值
|
||||
---@field public recoverBy ServerPlayer|nil @ 此次回复的回复来源
|
||||
---@field public skillName string|nil @ 因何种技能而回复
|
||||
---@field public card Card|nil @ 造成此次回复的卡牌
|
||||
|
||||
---@class DyingStruct
|
||||
---@field public who integer
|
||||
|
|
Loading…
Reference in New Issue