CELua控件、界面设计系列基础教程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

CE修改器界面设计系列1:建议的生成修改器流程
前言
本系列教程基于CE6.5.1制作,建议大家使用相同版本或更高版本的CE进行学习。

系列中的作为示例的修改器均为楼主从零学起,各种查资料,各种探索,各种实验研究出来的成果。

在这个过程中,楼主体会到了什么叫做大海捞针般的找资料,为方便大家查阅学习,特此把楼主学习所得制作一个合集,以飨同好。

楼主初学界面设计,技术有限,教程中疏漏之处在所难免。

本系列教程中的代码不一定是最优,但绝对是可以使用的,因为都是经过实践检验过的。

两款示例修改器分别为“极品飞车17v1.5战刀修改器v5.1”和“极品飞车17v1.5超级替换车辆修改器v1.0”,修改器源CT下载/thread-119338-1-1.html。

本文版权归百度“银河战刀”所有,转载请署名!
1.流程:
建议通过“修改器生成器”工具设计界面,这样CE可以自动编写抓取游戏进程的代码,方便省事。

(1)先运行游戏,然后在CE中打开游戏进程,如下图:
(2)进入修改器生成器工具
(3)设置好其他选项后,点击“使用者手动设计界面”按钮,
然后就会进入如下界面,从Object Inspetor或修过器界面选择不需要的控件,然后按键盘delete键即可删除。

“Properties”是基本属性栏,“Events”是事件栏,具体看后面的教程。

注意:热键依附的PANEL面板控件不能删除,要保持热键的原路径/层级关系不变,否则先前设置的热键声音等相关属性将会不正常。

热键描述乱码可以这样解决,。

此处省略1万字。

(4)设计好界面后↓。

(5)生成修改器
成功!(exe文件名只能由字母和数字组成)
CE修改器界面设计系列2:复选框(CECheckbox)的使用1.创建复选框控件:
在Form Designer工具栏中,单击选择复选框控件,然后在修改器界面中任意位置单击即可创建。

图1-1
拖动控件周边的8个白色控制控制点可以控制控件大小(这一点用办公软件编辑过图片的绝对知道),鼠标左键按住控件内部可以移动控件。

“Caption”选项后面可以编辑控件的说明文字。

图1-2
“Font”用于调整控件文字的字体;
“Hight”用于调整控件的高度;
“Left”用于调整控件在界面中的横向位置;
“Top”用于调整控件在界面中的竖直位置;
“Width”用于调整控件的宽度;
这些基本属性对于其他的控件同样适用,后续教程不再赘述。

不过有些控件的高度和宽度是根据文字的大小改变的,比如“复选框”控件。

至于其他选项不是影响功能的关键,想更改的可以自己去研究,楼主就不多说了。

2.给复选框添加功能(以控制CEAA为例):
上一节已经做出了复选框大致外观,然而这样的复选框在使用中是不会产生任何效果的(除了报错)
,所以在这一节我们就研究研究如何让复选框实现自己想要的功能。

图1-3
点击“Events”选项卡,找到“OnChange”选项,然后点击选项后面的小按钮,如图1-3。

这时,CE
会自动弹出一个窗口如下图,
图1-4
其中
function CECheckbox5Change(sender)
end
是CE自动创建的“改变时触发事件的框架代码”,这个保持默认即可。

里面的“CECheckbox5”是复选框的“Name”名,见图1-2。

在单个修改器中,每个控件的Name名都是唯一的。

Name名支持自定义,但我还是建议大家直接使用默认值。

接下来,我们需要做的就只剩在框架代码的空行中写入自己想要的功能了。

这里我以用复选框控制一个CEAA脚本即“CE自动汇编”脚本的开、关为例(不清楚CEAA的请自行百度):
function CECheckbox5Change(sender)
if(checkbox_getState(CETrainer.CECheckbox5)==1)then
autoAssemble(
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
newmem:
originalcode:
mov eax,00000002
ret
exit:
jmp returnhere
“checkbox_getState()”函数可获取复选框的勾选状态,
数字1代表勾选,0代表未勾选。

其中“CETrainer”是修改
器窗体的Name名,后面用“.”或“_”(见系列2第2小点)
连接所需复选框的Name名。

“autoAssemble()”函数用于调用汇编代码,汇编代码
写在(括号里面)即可。

第一个“autoAssemble()”我写入的是CEAA“[ENABLE]”开的内容,第二个“autoAssemble()”我写入的是CEAA“[DISABLE]”关的内容。

最后用if函数把这几个函数组织起来,形成一个完整的判断和功能。

综上,整个if语句的意思就是:
如果CECheckbox5处于勾选状态,那么
执行第一个“autoAssemble()”(勾选时执行的功能)
否则
执行第二个“autoAssemble()”(取消勾选时执行的功能)
结束
“OnChange”即当状态改变
时触发的事件。

"NFS13.exe"+4F5339:
jmp newmem
returnhere:
)
else
autoAssemble(
dealloc(newmem)
"NFS13.exe"+4F5339:
je NFS13.exe+4F534A
dec eax
je NFS13.exe+4F5344
)
end
end
3.脚本变量的使用:
大家仔细看看上面的代码,有没有发现插入汇编后if函数突然“一口吃成了个大胖纸”。

假如修改器中只需要几个复选框,那么查阅起来还可以接受,而如果有十几个复选框,你还能内心安定地一行行读下去吗。

所以这里有必要引入“变量/标识符”来解决这个问题,这个变量的作用与C语言中的变量大致相同,不仅省空间,而还方便查阅修改以及多次引用。

举个例子:
onLightON=[[
alloc(newmem,2048)
label(returnhere) label(originalcode) label(exit)
newmem:
originalcode:
mov eax,00000002 ret
exit:
jmp returnhere
"NFS13.exe"+4F5339: jmp newmem returnhere:
]]
onLightOFF=[[ dealloc(newmem) "NFS13.exe"+4F5339:
将汇编代码分别写在“[[两个中括号里面]]”

用变量名“onLightON”代表开灯AA脚本“[ENABLE]”的汇编代码,
用变量名“onLightOFF”代表开灯AA脚本“[DISABLE]”的汇编代码。

onLightON和onLightOFF都可以自定义,比
如AA1和AA2,只要保证自己看得懂就行。

脚本变量的总体格式是:
变量名=[[汇编代码]]
更多if函数格式请参考:
CE6.2lua脚本入门教学[第三课]自动汇编(一)指令修改/forum.php?mod=viewthread&tid=75394 (出处:我爱秘籍论坛@lyzzb)
je NFS13.exe+4F534A dec eax
je NFS13.exe+4F5344]]
function CECheckbox5Change(sender)
if (checkbox_getState(CETrainer.CECheckbox5)==1)then
autoAssemble(onLightON)
else
autoAssemble(onLightOFF)
end
end
当然,本例中变量和function 函数挨着写并不意味者大家也要这样写,当有多个变量时,建议大家把所有变量和function 函数分别写在“Lua 脚本:CT 表”的不同位置,如下:AA1=[[...]]AA2=[[...]]AA3=[[...]]...
AAX=[[...]]function...function......
function...
4.复选框互锁:
在本例中(图1-1),“开灯”和“关灯”是两个互相关联的修改,假如想在勾选了开灯的情况下,勾选关灯时让修改器自动取消勾选开灯该如何实现呢?答:
--开灯
function CECheckbox5Change(sender)
if (checkbox_getState(CETrainer.CECheckbox6)==1)then
checkbox_setState(CETrainer.CECheckbox6,0)
autoAssemble(offLightOFF)
else
end
if (checkbox_getState(CETrainer.CECheckbox5)==1)then
autoAssemble(onLightON)
else
autoAssemble(onLightOFF)end end
引用时将所需变量名写在
“autoAssemble(括号里)”即可。

有没有发现这样不仅简洁了许多,而
且一眼就能看出函数结构。

连续键入2个“-”用于在Lua 中添加单行注释“CECheckbox6”是“关灯”复选框的Name 名。

“checkbox_setState(CETrainer.CECheckbox6,0)”函数用于将CECheckbox6的状态码设置为0,即设置为未勾选。

然后在这个函数的下一行写上CECheckbox6取消勾选时执行的功能即可。

整个语句的意思我就不说了,大家自己试着理解。

变量名“offLightON ”代表关灯
AA 脚本“[ENABLE]”的汇编代码,
变量名“offLightOFF ”代表关灯AA 脚本“[DISABLE]”的汇编代码。

--关灯
function CECheckbox6Change(sender)
if(checkbox_getState(CETrainer.CECheckbox5)==1)then checkbox_setState(CETrainer.CECheckbox5,0)
autoAssemble(onLightOFF)
else
end
if(checkbox_getState(CETrainer.CECheckbox6)==1)then autoAssemble(offLightON)
else
autoAssemble(offLightOFF)
end
end
CE 修改器界面设计系列3:编辑框(CEEdit )
1.创建编辑框控件:
在Form Designer 工具栏中,选择编辑框控件,然后在修改器界面中任意位置单击即可创建。

“Text ”选项可以更改编辑框的默认数值,这个数值在修改器打开后会显示出来,所见即所得。

Text 后面不填任何字符即是空白编辑框。

2.给编辑框添加功能:
这里只讲这个修改器中用到的功能,这个功能非常重要,那就是在鼠标点击编辑框时,使编辑框可用,不然妥妥的报错,具体如下图:
function CEEdit1Click(sender)
control_setEnabled(CETrainer_CEEdit1,true)end
"control_setEnabled(CETrainer_CEEdit1,true)"就是设置编辑框1为可用的。

“OnClick ”就是当单击时触发的事件。

CE修改器界面设计系列4:内存操作
1.内存写入
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") memoryrecord_setValue(Subpolishing1address,100)
上面第一行的语句可以获取CE地址列表里自己添加的“内存地址的‘地址’”,只需将内存地址的描述如Subpolishing1(见下图)添加到"双引号里面"(注意是英文状态的双引号)
即可。

“Subpolishing1address”是我自定义的用于表示“内存地址的‘地址’”的标识符,大
家可以改成其他的,只要是由字母或数字组成即可。

第二行凭感觉就可以猜到语义是将数值100写入Subpolishing1address地址中。

数值类型(整型,浮点型等等)是直接套用的地址列表上的设置。

可以选中下图中Subpolishing1
地址后按“Alt+Enter”更改。

大家看,代码里面有一个大大的“set”,是不是似曾相识呢?
2.内存读取
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") memoryrecord_getValue(Subpolishing1address)
第一行还需要解释吗?第二行看“get”,getValue,获取值,是不是很简单呢。

注意Lua 语言是区分大小写的,所以Value首字母是大写的,具体看CE安装根目录下面“main.lua”
文件的定义,这个文件可以用记事本打开(推荐用“Notepad++”这款软件,能支持相关的
编码)。

3.内存锁定(超简单)
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") memoryrecord_freeze(Subpolishing1address)
下面进入学英语时间,freeze:冻结...
4.内存解锁(超简单)
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") memoryrecord_unfreeze(Subpolishing1address)
CE修改器界面设计系列5:按钮(CEButton)
1.创建按钮控件:
在Form Designer工具栏中,选择按钮控件,然后在修改器界面中任意位置单击即可创
建。

2.给按钮添加功能:
这里以单击触发事件为例,具体操作如下图:
function CEButton1Click(sender) end
功能实现详见系列6。

按钮单击“框架代码”
CE修改器界面设计系列6:编辑框、内存操作、按钮的综合
使用
1.按按钮获取编辑框中的数值然后写入内存
例:
function CEButton1Click(sender)
control_setEnabled(CETrainer_CEEdit1,true)
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") memoryrecord_setValue(Subpolishing1address,control_getCaption(CETrainer_CEEdit1))
end
结合已学内容,这个例子应该很好理解吧,如果看不懂就多看几遍。

“control_getCaption(CETrainer_CEEdit1)”用来获取CETrainer编辑框CEEdit1中的数值或字符。

2.按按钮获取内存中的数值然后写入编辑框
例:
function CEButton1Click(sender)
control_setEnabled(CETrainer_CEEdit1,true)
local Subpolishing1address=addresslist_getMemoryRecordByDescription(getAddressList(),"Subpolishing1") Subpolishing1value=memoryrecord_getValue(Subpolishing1address)
control_setCaption(CETrainer_CEEdit1,Subpolishing1value)
end
“Subpolishing1value”是我自定义的一个标识符,用来表示从Subpolishing1address获取的值。

至于“control_setCaption(CETrainer_CEEdit1,Subpolishing1value)”大家可以看到setCaption,set,set,又是set,这句啥意思马上就出来了,就是将Subpolishing1value所代
表的字符写入编辑框CEEdit1中,这样我们就可以在编辑框中看到字符了。

CE修改器界面设计系列7:组合框(CEComboBox)
1.创建组合框控件:
在Form Designer工具栏中,选择组合框控件,然后在修改器界面中任意位置单击即可创建。

组合框的基础使用,其实并没有想象中的那么难,那么高深莫测,只是一张“Paper-Tiger”而已。

“ItemIndex”选项用来标识组合框选择的是第几项,
如果后面的数值是-1,就代表啥也没选;
如果是0,就代表选择了第1项;
如果是1,就代表选择了第2项;
如果是2,就代表选择了第3项;以此类推。

如果这里选择第几项,修改器打开后就默认显示第几项。

“Items”选项用来编辑各个选项显示在组合框上的说明字符,点击Items后面的“...”小按钮,会弹出以下内容
,然后我们将各项需要显示的内容写进去即可,
就像在记事本中打字那样,写完1项后回车进入下一项,1项只能占1行。

如下图:
编辑好后双击界面中的组合框马上
见效!

“ReadOnly”勾选用于将组合框设置成只读,这个一般要设置成只读,大家根据需要来,可以自己试试不勾选是什么效果。

2.结合按钮给组合框添加功能:
先创建一个按钮,然后给按钮添加OnClick事件,具体代码如下:
function CEButton1Click(sender)
MyCarID=combobox_getItemIndex(CETrainer.CEComboBox1)
if MyCarID==-1then return end--如果没选,if判断直接结束。

if MyCarID==0then--如果选择了第1项,那么
local MyCarAddr=addresslist_getMemoryRecordByDescription(getAddressList(),"mycarNV")
memoryrecord_setValue(MyCarAddr,1085698)
elseif MyCarID==1then--否则,如果选择了第2项,那么local MyCarAddr=addresslist_getMemoryRecordByDescription(getAddressList(),"mycarNV")
memoryrecord_setValue(MyCarAddr,2196263)
elseif MyCarID==2then--否则,如果选择了第3项,那么local MyCarAddr=addresslist_getMemoryRecordByDescription(getAddressList(),"mycarNV")
memoryrecord_setValue(MyCarAddr,1160082)
elseif MyCarID==3then
local MyCarAddr=addresslist_getMemoryRecordByDescription(getAddressList(),"mycarNV")
memoryrecord_setValue(MyCarAddr,2196529)
end
end
“MyCarID=combobox_getItemIndex(CETrainer.CEComboBox1)”这句用来获取组合框的ItemIndex值,并用MycarID标识符标识,方便后续使用。

“mycarNV”跟前面的例子一样,是引用的地址列表里一个内存地址描述。

综上,相信这个例子还是很好理解的。

CE修改器界面设计系列8:总结
前面的介绍的几个控件使用、内存操作方法,已经足够应付大多数修改了。

而且,总结以上的教程,我们发现,控件使用思路无非就是

通过一个事件获取或改变控件的状态

根据控件的状态执行相应的操作
”。

有了这个思路,我们就可以根据CE帮助文件和根目录中的“main.lua”提供的各控件相关函数自己研究新控件新功能了。

一句话“勤动手,勤动脑,实践出真知”。

祝大家学习愉快,做出更高逼格的修改器!。

相关文档
最新文档