怎么用cheat engine导入脚本里的lua脚本制作游戏修改器

馆藏&21919
TA的最新馆藏Lua脚本语言简明入门教程
作者:陈皓
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Lua脚本语言简明入门教程,本文简洁干练,可以让一个有编程基础的快速的学会Lua脚本语言,需要的朋友可以参考下
这几天系统地学习了一下Lua这个脚本语言,Lua脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到200k,这是多么地变态啊(/bin/sh都要1M,MacOS平台),而且能和C语言非常好的互动。我很好奇得浏览了一下Lua解释器的源码,这可能是我看过最干净的C的源码了。
我不想写一篇大而全的语言手册,一方面是因为已经有了(见本文后面的链接),重要的原因是,因为大篇幅的文章会挫败人的学习热情,我始终觉得好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽(这也是我为什么不想写书的原因)。所以,这必然又是一篇“入厕文章”,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。
相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧……
首先,我们需要知道,Lua是类C的,所以,他是大小写字符敏感的。
下面是Lua的Hello World。注意:Lua脚本的语句的分号是可选的,这个和GO语言很类似。
print("Hello World")
你可以像python一样,在命令行上运行lua命令后进入lua的shell中执行语句。
chenhao-air:lua chenhao$ lua
Lua 5.2.2& Copyright (C)
Lua.org, PUC-Rio
& print("Hello, World")
Hello, World
也可以把脚本存成一个文件,用如下命令行来运行。
&lua& file.lua
或是像shell一样运行:
chenhao-air:lua chenhao$ cat hello.lua
#!/usr/local/bin/lua
print("Hello, World")
chenhao-air:lua chenhao$ chmod +x hello.lua
chenhao-air:test chenhao$ ./hello.lua
Hello, World
-- 两个减号是行注释
&这是块注释
&这是块注释
Lua的数字只有double型,64bits,你不必担心Lua处理浮点数会慢(除非大于100,000,000,000,000),或是会有精度问题。
你可以以如下的方式表示数字,0x开头的16进制和C是很像的。
num = 1024
num = 3.1416
num = 314.16e-2
num = 0.31416E1
num = 0xff
num = 0x56
字符串你可以用单引号,也可以用双引号,还支持C类型的转义,比如: ‘\a' (响铃), ‘\b' (退格), ‘\f' (表单), ‘\n' (换行), ‘\r' (回车), ‘\t' (横向制表), ‘\v' (纵向制表), ‘\\' (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)
下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
C语言中的NULL在Lua中是nil,比如你访问一个没有声明过的变量,就是nil,比如下面的v的值就是nil
v = UndefinedVariable
布尔类型只有nil和false是 false,数字0啊,‘'空字符串('\0′)都是true!
另外,需要注意的是:lua中的变量如果没有特殊说明,全是全局变量,那怕是语句块或是函数里。变量前加local关键字的是局部变量。
theGlobalVar = 50
local theLocalVar = "local variable"
不多说了,直接看代码吧(注意:Lua没有++或是+=这样的操作)
while num &= 100 do
&&& sum = sum + num
&&& num = num + 1
print("sum =",sum)
if-else分支
if age == 40 and sex =="Male" then
&&& print("男人四十一枝花")
elseif age & 60 and sex ~="Female" then
&&& print("old man without country!")
elseif age & 20 then
&&& io.write("too young, too naive!\n")
&&& local age = io.read()
&&& print("Your age is "..age)
上面的语句不但展示了if-else语句,也展示了
1)“~=”是不等于,而不是!=
2)io库的分别从stdin和stdout读写的read和write函数
3)字符串的拼接操作符“..”
另外,条件表达式中的与或非为分是:and, or, not关键字。
从1加到100
for i = 1, 100 do
&&& sum = sum + i
从1到100的奇数和
for i = 1, 100, 2 do
&&& sum = sum + i
从100到1的偶数和
for i = 100, 1, -2 do
&&& sum = sum + i
&& sum = sum ^ 2 --幂操作
&& print(sum)
until sum &1000
Lua的函数和Javascript的很像
function fib(n)
& if n & 2 then return 1 end
& return fib(n - 2) + fib(n - 1)
同样,Javascript附体!
function newCounter()
&&& local i = 0
&&& return function()&&&& -- anonymous function
&&&&&& i = i + 1
&&&&&&& return i
c1 = newCounter()
print(c1())& --& 1
print(c1())& --& 2
function myPower(x)
&&& return function(y) return y^x end
power2 = myPower(2)
power3 = myPower(3)
print(power2(4)) --4的2次方
print(power3(5)) --5的3次方
函数的返回值
和Go语言一样,可以一条语句上赋多个值,如:
name, age, bGay = "haoel", 37, false, ""
上面的代码中,因为只有3个变量,所以第四个值被丢弃。
函数也可以返回多个值:
function getUserInfo(id)
&&& print(id)
&&& return "haoel", 37, "", "http://jb51.net"
name, age, email, website, bGay = getUserInfo()
注意:上面的示例中,因为没有传id,所以函数中的id输出为nil,因为没有返回bGay,所以bGay也是nil。
函数前面加上local就是局部函数,其实,Lua中的函数和Javascript中的一个德行。
比如:下面的两个函数是一样的:
function foo(x) return x^2 end
foo = function(x) return x^2 end
所谓Table其实就是一个Key Value的数据结构,它很像Javascript中的Object,或是PHP中的数组,在别的语言里叫Dict或Map,Table长成这个样子:
haoel = {name="ChenHao", age=37, handsome=True}
下面是table的CRUD操作:
haoel.website="http://jb51.net/"
local age = haoel.age
haoel.handsome = false
haoel.name=nil
上面看上去像C/C++中的结构体,但是name,age, handsome, website都是key。你还可以像下面这样写义Table:
t = {[20]=100, ['name']="ChenHao", [3.14]="PI"}
这样就更像Key Value了。于是你可以这样访问:t[20],t["name"], t[3.14]。
我们再来看看数组:
arr = {10,20,30,40,50}
这样看上去就像数组了。但其实其等价于:
arr = {[1]=10, [2]=20, [3]=30, [4]=40, [5]=50}
所以,你也可以定义成不同的类型的数组,比如:
arr = {"string", 100, "haoel", function() print("") end}
注:其中的函数可以这样调用:arr[4]()。
我们可以看到Lua的下标不是从0开始的,是从1开始的。
for i=1, #arr do
&&& print(arr[i])
注:上面的程序中:#arr的意思就是arr的长度。
注:前面说过,Lua中的变量,如果没有local关键字,全都是全局变量,Lua也是用Table来管理全局变量的,Lua把这些全局变量放在了一个叫“_G”的Table里。
我们可以用如下的方式来访问一个全局变量(假设我们这个全局变量名叫globalVar):
_G.globalVar
_G["globalVar"]
我们可以通过下面的方式来遍历一个Table。
for k, v in pairs(t) do
&&& print(k, v)
MetaTable 和 MetaMethod
MetaTable和MetaMethod是Lua中的重要的语法,MetaTable主要是用来做一些类似于C++重载操作符式的功能。
比如,我们有两个分数:
fraction_a = {numerator=2, denominator=3}
fraction_b = {numerator=4, denominator=7}
我们想实现分数间的相加:2/3 + 4/7,我们如果要执行: fraction_a + fraction_b,会报错的。
所以,我们可以动用MetaTable,如下所示:
fraction_op={}
function fraction_op.__add(f1, f2)
&&& ret = {}
&&& ret.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator
&&& ret.denominator = f1.denominator * f2.denominator
&&& return ret
为之前定义的两个table设置MetaTable:(其中的setmetatble是库函数)
setmetatable(fraction_a, fraction_op)
setmetatable(fraction_b, fraction_op)
于是你就可以这样干了:(调用的是fraction_op.__add()函数)
fraction_s = fraction_a + fraction_b
至于__add这是MetaMethod,这是Lua内建约定的,其它的还有如下的MetaMethod:
__add(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a + b
__sub(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a - b
__mul(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a * b
__div(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a / b
__mod(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a % b
__pow(a, b)&&&&&&&&&&&&&&&&&&&& 对应表达式 a ^ b
__unm(a)&&&&&&&&&&&&&&&&&&&&&&& 对应表达式 -a
__concat(a, b)&&&&&&&&&&&&&&&&& 对应表达式 a .. b
__len(a)&&&&&&&&&&&&&&&&&&&&&&& 对应表达式 #a
__eq(a, b)&&&&&&&&&&&&&&&&&&&&& 对应表达式 a == b
__lt(a, b)&&&&&&&&&&&&&&&&&&&&& 对应表达式 a & b
__le(a, b)&&&&&&&&&&&&&&&&&&&&& 对应表达式 a &= b
__index(a, b)&&&&&&&&&&&&&&&&&& 对应表达式 a.b
__newindex(a, b, c)&&&&&&&&&&&& 对应表达式 a.b = c
__call(a, ...)&&&&&&&&&&&&&&&&& 对应表达式 a(...)
“面向对象”
上面我们看到有__index这个重载,这个东西主要是重载了find key的操作。这操作可以让Lua变得有点面向对象的感觉,让其有点像Javascript的prototype。
所谓__index,说得明确一点,如果我们有两个对象a和b,我们想让b作为a的prototype只需要:
setmetatable(a, {__index = b})
例如下面的示例:你可以用一个Window_Prototype的模板加上__index的MetaMethod来创建另一个实例:
Window_Prototype = {x=0, y=0, width=100, height=100}
MyWin = {title="Hello"}
setmetatable(MyWin, {__index = Window_Prototype})
于是:MyWin中就可以访问x, y, width, height的东东了。(注:当表要索引一个值时如table[key], Lua会首先在table本身中查找key的值, 如果没有并且这个table存在一个带有__index属性的Metatable, 则Lua会按照__index所定义的函数逻辑查找)
有了以上的基础,我们可以来说说所谓的Lua的面向对象。
function Person:new(p)
&&& local obj = p
&&& if (obj == nil) then
&&&&&&& obj = {name="ChenHao", age=37, handsome=true}
&&& self.__index = self
&&& return setmetatable(obj, self)
function Person:toString()
&&& return self.name .." : ".. self.age .." : ".. (self.handsome and "handsome" or "ugly")
上面我们可以看到有一个new方法和一个toString的方法。其中:
1)self 就是 Person,Person:new(p),相当于Person.new(self, p)
2)new方法的self.__index = self 的意图是怕self被扩展后改写,所以,让其保持原样
3)setmetatable这个函数返回的是第一个参数的值。
于是:我们可以这样调用:
me = Person:new()
print(me:toString())
kf = Person:new{name="King's fucking", age=70, handsome=false}
print(kf:toString())
继承如下,我就不多说了,Lua和Javascript很相似,都是在Prototype的实例上改过来改过去的。
Student = Person:new()
function Student:new()
&&& newObj = {year = 2013}
&&& self.__index = self
&&& return setmetatable(newObj, self)
function Student:toString()
&&& return "Student : ".. self.year.." : " .. self.name
我们可以直接使用require(“model_name”)来载入别的lua文件,文件的后缀是.lua。载入的时候就直接执行那个文件了。比如:
我们有一个hello.lua的文件:
print("Hello, World!")
如果我们:require(“hello”),那么就直接输出Hello, World!了。
1)require函数,载入同样的lua文件时,只有第一次的时候会去执行,后面的相同的都不执行了。
2)如果你要让每一次文件都会执行的话,你可以使用dofile(“hello”)函数
3)如果你要玩载入后不执行,等你需要的时候执行时,你可以使用 loadfile()函数,如下所示:
local hello = loadfile("hello")
loadfile(“hello”)后,文件并不执行,我们把文件赋给一个变量hello,当hello()时,才真的执行。(我们多希望JavaScript也有这样的功能
当然,更为标准的玩法如下所示。
假设我们有一个文件叫mymod.lua,内容如下:
文件名:mymod.lua
local HaosModel = {}
local function getname()
&&& return "Hao Chen"
function HaosModel.Greeting()
&&& print("Hello, My name is "..getname())
return HaosModel
于是我们可以这样使用:
local hao_model = require("mymod")
hao_model.Greeting()
其实,require干的事就如下:(所以你知道为什么我们的模块文件要写成那样了)
local hao_model = (function ()
& --mymod.lua文件的内容--
我估计你差不多到擦屁股的时间了,所以,如果你还比较喜欢Lua的话,下面是几个在线文章你可以继续学习之:
lua在线手册
lua在线lua学习教程
Lua参考手册的中文翻译(云风翻译版本)
关于Lua的标库,你可以看看官方文档:,&, ,, 。
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具查看: 8178|回复: 7
使用Cheat Engine制作自己的游戏专用修改器
在线时间 小时
作者:wettuy
是一款非常强大的游戏修改器,甚至包括了内存的反汇编。不过他使用起来却很简单,即使你完全不懂编程,也可以用他做很多的修改。本文以命令与 征服3 1.09为例,简单的介绍一下CE的强大。所用的修改器是我自己汉化的Cheat Engine 5.3^_^
首先,开修改器,进游戏开始修改,这太简单了就不细说了。此时我们已经找到了游戏中钱的地址。不过要注意的是,C&C3的主程序是cnc3game.dat,而非你运行的cnc3.exe
双击搜索到的两个地址中的第一个,他会被自动添加到地址栏中。然后在地址栏中右击他,选择“Find out what writes to this address”(寻找是什么在写入此地址)。然后出现这个对话框
什么都不改,直接回游戏,建个电厂,然后出来,一般就能找到一个唯一的代码了,如图
现在我们已经知道是什么代码在让我们掉钱了。点击替换,把它改成nop(当然你也可以改成add,这样他就只增不减了^_^)
点击更多信息,可以看到这里已经成功修改了
回到游戏,看到了吗,我们成功了,此时钱已经不会减少了
不过此时还没有结束,因为我们下一步要开始制作专用修改器。回到CE的主界面,点击最下面的高级选项,这里可以看到我们修改的代码。点击上面的保存按钮
当然是创建新的修改器了
在制作修改器的窗口中选择添加,加入刚刚我们修改过的代码
然后对修改器的其他部分做一些修改,注意一定不要忘记选择进程
至此,我们的修改器就全部完成了
顺便附上做好的修改器成品:
怎么样,是不是很简单啊,这里我们完全没有用到任何编程的知识,更没有用到指针,就已经完成了一个专用修改器了,当然这主要是因为C&C3的地址比较容易,如果他每次都会变的话,就需要使用指针才能找到代码了。不过,那就是下次的事情了^_^
阅读权限150
在线时间 小时
命令与征服的....&&命令与征服的地址比红警要好找点&&红警地址很多隐藏了~~
阅读权限20
在线时间 小时
新人 对这类只是像白纸一样的白 牛奶一样的纯&&很想学习&&能拜三位为师吗
阅读权限60
在线时间 小时
!!!!!!!!
阅读权限55
在线时间 小时
图全挂了,老大
阅读权限55
在线时间 小时
一切都学习
阅读权限50
在线时间 小时
阅读权限50
在线时间 小时
顶起来…………
Powered by& 求一个制作游戏修改器的思路
查看: 1654|回复: 3
UID1387756主题阅读权限20帖子精华0积分60金钱1875 荣誉1 人气0 在线时间401 小时评议0
Lv.2游侠会员, 积分 60, 距离下一级还需 140 积分
帖子精华0积分60金钱1875 荣誉1 人气0 评议0
制作工具VS2010
游戏中的数据,我看总体货币数据是在初始化内存里,逻辑帧数据是在栈里,具体每个人物对象的数据是在堆里
初始化内存里的数据,可以根据进程地址,用指针算偏移找到内存地址,进行修改
那么请教在堆里的数据,如何找到地址,因为堆里每次的对象不是固定的,算内存地址偏移貌似不可行
UID1524672主题阅读权限40帖子精华0积分718金钱3094 荣誉0 人气34 在线时间2692 小时评议0
Lv.4游侠高级会员, 积分 718, 距离下一级还需 282 积分
帖子精华0积分718金钱3094 荣誉0 人气34 评议0
基本的原理很清楚 就是修改内存 既然看似有了程序基础咱就按照程序的角度来说
运转中的游戏的代码也一样是存在内存里的 直接定义和读取的部分也会在这里面 记得好像咱那会看得教程是叫模块地址还是啥 大致是0x004开始往后的很长一部分 这部分是无论你何时运行都不随运行环境变化的 如果你要修改的地址是在这个范围内的 那么你放心保存
还有一部分正如你说 是运行时确定数据或结构起始地址的 这部分你如果你想稳定的找到它的地址 那么就需要找到谁去引用它的 这部分可能是模块地址 那么你就能从这部分获取到它的运行时地址 那么这部分也可能是变化的 那么就要再去找引用这部分内存的是不是模块地址 以此类推
如果你是用CheatEngine来搜索地址 模块地址在搜索的时候就会被显示成绿色的 你找到的“堆里的数据”一种方法你可以再去查找有谁保存了它的地址(搜索16进制数)看是不是模块地址 或者可以先把它放到你的地址栏里 然后右键选择查看什么修改/访问了该地址 然后尝试通过程序指令寻找到引用它的地址 一步步推 层数多的话会是个挺艰苦的过程 但成功后的成就感可不止是翻倍的
另外有时修改并不一定要修改记录位置 你用上面提到的查找谁修改了该地址 一般情况下这部分指令会是在模块地址的 比如你是想锁血的话用你的程序直接把修改血量的指令的这段内存改成什么都不做的就行了 比修改数据存储的内存段更让人放心(比如不会出现敌人把你的血打到0的瞬间系统依旧判断你死亡的问题)
助人为乐,品格高尚~
总评分:&金钱 + 10&
UID1809794主题阅读权限60帖子精华0积分3481金钱7101 荣誉0 人气151 在线时间12553 小时评议0
Lv.6游侠黄金会员, 积分 3481, 距离下一级还需 2519 积分
帖子精华0积分3481金钱7101 荣誉0 人气151 评议0
我居然看懂了。。。。指针什么的。。。
幸福的家庭都是相似的,不幸的家庭各有各的不幸——托尔斯泰
& && && && && && && && & 先拯救自己吧
UID4564467主题阅读权限20帖子精华0积分2878金钱1636 荣誉0 人气150 在线时间5699 小时评议0
头像被屏蔽
帖子精华0积分2878金钱1636 荣誉0 人气150 评议0
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
Powered by

我要回帖

更多关于 cheat engine 的文章

 

随机推荐