当前位置:首页 > 游戏资讯 > 正文

war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)

2.如何初始化一个lua脚本


war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第1张

通过 Cheat 函数来调用lua脚本
如图所示,执行地图中导入的 test.lua 脚本

已改为: execwar魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第2张lua:test      

  •       3.如何写lua脚本      

    有2种办法:用其他工具写好了导入到地图中/在编辑器里写          
    这里只介绍第二种          
             
             war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第3张          
             
    如图所示,在脚本的任意位置写下这样的格式遍可以自动往地图中导入名为"test.lua"的文件,文件内容即为 [[]] 括起来的部分

              应该是三种,1.27+的ydwe支持从本地硬盘上导入lua脚本文件。并且import本身就是一个lua函数,对lua熟悉的童靴可以编写自己的导入函数,比如导入一个文件夹内的所有lua脚本。        

  • 建议使用 <?import("文件名")[=====[脚本内容]=====]?> 的形式,等号数量前后一致就行,这样就可以和脚本中的 [[ ]] 进行区分以免冲突

                       

    4.建立第一个lua文件            
                war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第4张            
               
    在第一个文件中,我建议你只写以下代码            
               
               
    jass_ext.EnableConsole()            
               
    setmetatable(_G, {__index = getmetatable(jass).__index})            
               
               
    第一句的作用是打开一个cmd窗口,这样你的其他脚本有错误话会提示你            
               
               
    第二句代码如果不写的话你得用 jass.SetUnitState(jass.GetTriggerUnit(), jass.UNIT_STATE_LIFE, 0) 来写代码,写了以后"jass."就可以都省略掉了


               
             

                 _G是5.1的旧写法,有可能在未来lua版本中被移除,请使用_ENV代替            

    之后你可以在jass中用Cheat函数来运行其他lua脚本,你也可以在lua中通过              
    require "another.lua"              
    来运行其他lua脚本              
                 
                 
    注意这样运行的话每个脚本只能运行一次,如果你之前运行过"another.lua",那么之后的require "another.lua"就不会执行了


                 

    5.lua的基本介绍                
    lua是一个简单,高效,强大的脚本语言,其语法和jass有很多相似之处,因此有jass基础的话可以很快掌握lua                
                   
                   
    lua和jass最大的不同在于lua不需要写变量类型,例:                
                   
                   
    local a = 1                
    if a == 1 then                
    a = "等于1"                
    end                
                   
                   
    这个例子中a分别是数字(number)和字符串(string)                
                   
                   
    lua有以下几个类型                
    nil --空值,任何变量在复制前都是nil,类似于jass的null                
    boolean --布尔值,和jass一样包括true和false                
    number --数字,jass中的real和integer在lua中统一为number,因此在lua中 5/2 == 2.5                
    string --字符串,和jass中的string基本相同                
    function --函数,和jass不同的是lua中函数是一个变量,你随时可以把一个函数赋值给另一个变量,或传递给另一个函数做参数                
    userdata --自定义数据,你可以理解为jass中的handle,lua无法直接对其进行操作

    table类型呢……thread应该不能用。:table漏了...thread会和GetTriggerUnit什么不兼容所以不介绍了,acb正在写新的协同线程                

                                   

    lua有以下保留字                    
    and break do else elseif                    
    end false for function if                    
    in local nil not or                    
    repeat return then true until                    
    while                    
                       
                       

    6.变量                      
    lua对变量进行操作时不需要set 关键字                      
    lua使用全局变量无须事先声明,任何时候                      
    a = 10                      
    都是有效的.在a被复制前,如果去获取a的类型将返回"nil"                      
                         
                         
    局部变量的声明方式类似于jass:                      
    local a = 10                      
                         
                         
    记住,lua不需要写变量类型哦                      
                         
                         
    补充一下                      
    对于 if a then 这样的判定,当a为nil或false时不成立,其他包括0与""在内都是成立的                      
                         
                         
    lua中字符串连接符是 .. 而不是 + ,原因很简单:                      
    1 + 2 = 3                      
    1 .. 2 = "12"


                         

    7.表达式                        
    jass中的 != 在lua中写为 ~= ,其他加减乘除 括号 比较 and or 都一样                        
    此外lua还自带了取余(%)和幂(^)                        
    5%2 = 1                        
    2^3 = 8


                           

    8.关于数字和字符串的一些特殊写法                          
                             
                             
    lua和jass一样都支持 0x前缀的16进制数字,但是jass中 '' 表示的256进制数字符号在lua中要改为 || (注:这是acb加入的村规,lua并不自带256进制)                          
                             
                             
    lua的字符串符号有3个,分别是 "" '' 和 [[ ]]                          
    不过最后一个和YDWE有点冲突请不要使用(如果你是在外面写脚本然后导入地图可以无视)


                             

    9.数据结构                            
    抛弃掉jass的哈希表吧                            
                               
                               
    lua只有一种数据结构:table(表)                            
                               
                               
    t = {} --将一张新建的表赋值给变量t                            
    t[1] = 10                            
    t[2] = 20 --当数组用                            
                               
                               
    t.x = 50                            
    t.y = 100 --当哈希表用                            
                               
                               
    任何非nil的值都可以当做索引,例如                            
    t["呜喵"] = "wumiao"                            
    t[GetTriggerUnit()] = "厉害" --这里做索引的是一个单位,你可以抛弃GetHandleId了                            
                               
                               
    你可以在新建的时候直接定义数组内容,例:                            
    t = {                            
    10, --10赋值给t[1]                            
    x = 50, --50赋值给t.x                            
    y = 100, --100赋值给t.y                            
    20 --20赋值给t[2]                            
    }                            
                               
                               
    注意这样写的话,数据之间要加上一个逗号                            
                               
                               
    table可以进行多层嵌套,例如                            
    t = {}                            
    t[1] = {}                            
    t[1][2] = {}                            
    t[1][2][3] = "呜喵"                            
                               
                               
                                war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第5张                            


                               

    10.函数                              
    函数的内容比较多,我得分成好几段...                              
                                 
                                 
    函数声明:                              
    lua的函数声明有2种:                              
    function func(a, b, c)                              
    end                              
                                 
                                 
    func = function(a, b, c)                              
    end                              
                                 
                                 
    这2种方法是等价的,都是声明了一个名为"func",参数为a b c 的函数                              
    显然,参数不需要写类型,也不需要写返回类型.endfunction改为end即可                              
                                 
                                 
    在lua中函数是一个变量,这在第二种声明方式中得以显现.你可以随时将他赋值给另一个值,例如                              
    R2I = math.floor --后者是lua自带的取整函数                              
    这样你以后写 R2I(11.2) 就完全等价于 math.floor(11.2)                              
                                 
                                 
    既然是变量,那么他就可以局部化:                              
    local function func(a, b, c)                              
    end                              
                                 
                                 
    local func = function(a, b, c)                              
    end                              
                                 
                                 
    这样外部就调用不到这个func了


                                 
                               

                                   函数定义还有一种形式 function point:get_x() return self.x end,这也是一个语法糖。和function point.get_x(self) return self.x end的写法是完全等价的                                

                                                                   

    函数的调用                                    
                                       
                                       
    与jass不同,lua调用函数不需要写 call                                    
    以上面注册的函数为例,我只需要                                    
    func(1, 2, 3)                                    
    即可调用这个函数                                    
                                       
                                       
    lua调用函数没有顺序限制,只要func已经被赋值了函数就能调用,即使他赋值的函数是在之后定义的                                    
                                       
                                       
    lua也不限定你的参数,如果你写成                                    
    func(1, 2)                                    
    也依然可以正常调用func函数,只是该函数的参数c将为nil                                    
                                       
                                       
    lua也不限定你的返回值,你可以这样声明函数:                                    
    func = function(a)                                    
    if a == 1 then                                    
    return 1                                    
    elseif a == 2 then                                    
    return "呜喵"                                    
    elseif a == 3 then                                    
    return true                                    
    elseif a == 4 then                                    
    return {50, 100}                                    
    end                                    
    end                                    
                                       
                                       
    此时如果你                                    
    local r = func(0)                                    
    r的值就是nil                                    
                                       
                                       
    lua还支持多返回值:                                    
    GetXY = function(u)                                    
    return GetUnitX(u), GetUnitY(u)                                    
    end                                    
                                       
                                       
    local x, y, z = GetXY(u) → x = 0, y = 0, z = nil


                                     

    函数的特殊调用                                      
    当函数只有一个字符串或表参数,且不是变量时,可以省掉括号                                      
    例如之前的例子:                                      
    require "another.lua"                                      
    其实是                                      
    require("another.lua")                                      
    的缩写                                      
                                         
                                         
    还有个很常用的写法是                                      
    func = function(data)                                      
    SetUnitState(data.unit, data.state, GetUnitState(data.unit, data.state) + data.plus)                                      
    end                                      
                                         
                                         
    func{                                      
    unit = GetTriggerUnit(),                                      
    state = UNIT_STATE_LIFE,                                      
    plus = 100                                      
    }                                      
    这个例子中,我将参数全部保存在一个表中,然后将整个表作为一个参数传递给函数.


                                       

    闭包                                        
    当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。虽然这看起来很清楚,事实并非如此,词法定界加上第一类函数在编程语言里是一个功能强大的概念,很少语言提供这种支持。                                        
                                           
                                           
    ↑↑我反正是看着眼花,直接上演示:                                        
                                           
                                           
                                           war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第6张                                        
                                           
    很显然,这个函数的实现方式是开了个1秒的循环计时器                                        
    需要注意的是,我直接在本该传入code参数的位置写了个性的函数在上面(这个函数无需命名,称为匿名函数)                                        
    这个匿名函数可以正确调用到父函数"heal"的参数以及其声明的局部变量                                        
                                           
                                           
    嗯,这个就叫做闭包                                        
                                           
                                           
    看下面一个例子:                                        
                                           war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第7张                                        
                                           
    这里我将一个函数作为一个参数传递给了test,然后在1秒后运行了这个函数.思考一下,运行后,cmd窗口上将显示几呢?(print函数即为在cmd窗口上显示内容)


                                         
                                         

    11.条件与循环                                        
    嗯..应该在函数之前讲的说...                                        
                                           
                                           
    条件语句与jass基本相同,只需要将endif改成end即可,可以看16楼函数返回值的例子                                        
                                           
                                           
    lua中有3种循环方式                                        
    1.for 循环                                        
    最常用的循环方式                                        
                                           
                                           
    for i = 1, 10, 2 do                                        
    print(i)                                        
    end                                        
                                           
                                           
    cmd窗口中将显示"1 3 5 7 9"                                        
    例子中的 1 10 2 分别代表 开始 结束 步长                                        
    这里的 i 是自动声明的局部变量                                        
    如果步长是1,那么可以省略不写,例如                                        
                                           
                                           
    for i = 1, 5 do                                        
    print(i)                                        
    end                                        
                                           
                                           
    显示"1 2 3 4 5"                                        
                                           
                                           
    要注意的是,你不能通过修改i的值来临时更改循环,你可以理解为                                        
    forLoop(1, 5,                                        
    function(i)                                        
    print(i)                                        
    end                                        
    )                                        
                                           
                                           
    2.while 循环                                        
    当条件成立时进行循环                                        
                                           
                                           
    local i = 1                                        
    while i <= 5 do                                        
    print(i)                                        
    i = i + 1                                        
    end                                        
                                           
                                           
    如果你要手动修改i来控制循环,可以使用while                                        
                                           
                                           
    3.repeat 循环                                        
    至少我没用过                                        
                                           
                                           
    local i = 1                                        
    repeat                                        
    print(i)                                        
    i = i + 1                                        
    until i >= 5                                        
                                           
                                           
    你可以使用break来提前退出一个循环,常见的写法有                                        
    local i = 1                                        
    while true do                                        
    print(i)                                        
    i = i + 1                                        
    if i >= 5 then                                        
    break                                        
    end                                        
    end                                        
                                           
                                           
    需要注意的是,break与return必须写在一段代码的最后面,身后紧靠着end,elseif之类                                        
    如果你必须要在代码中间使用,请写成 do break end(do return end)


                                           

    12.对表的操作                                          
    通过前面的学习我们可以直到,与jass的"某个变量是数组"不同,lua中"某个变量的值是表".因此这个表可以重新赋值给别的变量或当做参数                                          
                                             
                                             
    lua自带了许多table相关的函数,你可以完全用table来取代group                                          
                                             
                                             
    例:                                          
    t = {10, 9, 8, 7, 6 , a = "呜喵", b = "喵呜", c = true}                                          
                                             
                                             
    这个表分为2个部分,数组与哈希表                                          
    我们可以通过 #t 来获取数组的长度(5)                                          
                                             
                                             
    for i = 1, #t do                                          
    print(i .. " = " .. t[i])                                          
    end                                          
                                             
                                             
    这是遍历数组的一个简单的方式                                          
    lua还提供了一种遍历数组的方式:                                          
                                             
                                             
    for i, v in ipairs(t) do                                          
    print(i .. " = " .. v)                                          
    end                                          
                                             
                                             
    这里的i 与 v都是局部变量                                          
                                             
                                             
    此外lua还提供一个遍历表中所有值的方式:                                          
                                             
                                             
    for i, v in pairs(t) do                                          
    print(i .. " = " .. v)                                          
    end                                          
                                             
                                             
    除了数组部分,可以将哈希表部分也都遍历出来,并将对应的索引放在i中,值放在v中                                          
    不过要注意的时,虽然这样遍历时依然会先按照顺序遍历出数组部分,但之后的哈希表部分的遍历顺序是随机的,与你储存时的顺序是没有关系的哦                                          
                                             
                                             
    lua还提供了2个常用的插入/拔出...好吧删除功能                                          
    table.insert(t, 3, 20)                                          
    将20插入到t[3]上,之前从[3]开始的数据都会被挤得往后挪一个位置                                          
                                             
                                             
    table.remove(t, 3)                                          
    将t[3]删除,同时之后的数据都会往前挪一个位置填补空缺                                          
                                             
                                             
    如果你不填位置,那么将默认在数组的尾端上操作:                                          
    table.insert(t, 20) == t[#t + 1] = 20                                          
    table.remove(t) == t[#t] = nil


                                             

    13.面向对象                                            
    面向对象是区别于面向过程的编程方式                                            
    jass使用者应该对面向过程很清楚-----你平时写的就是面向过程                                            
                                               
                                               
    一个简单的例子:                                            
                                                war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第8张                                            
                                               
    我使用了一张表保存了一个单位,以及其一些数据,此外还在里面保存了一个函数,这个函数的作用就是删除这个单位                                            
                                               
                                               
    之后,我只需要使用 hero:remove 即可调用到这个函数,从而删除hero里记录的单位                                            
                                               
                                               
    注意这个函数的调用的方式,hero与remove之间有一个冒号,代表调用hero的成员函数.如果你不能理解,你只要知道                                            
                                               
                                               
    hero:remove() 完全等价于 hero.remove(hero)                                            
                                               
                                               
    我们还可以在表的外面添加一个成员函数                                            
                                                war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第9张                                            
                                               
    这2种声明方式是等价的,当然你也可以使用                                            
    function hero:resethpmp(hp, mp)                                            
    来添加函数,效果是一样的                                            
                                               
                                               
    相对的,调用方式则为                                            
    hero.resethpmp(hero, 0, 0)                                            
    或者                                            
    hero:resethpmp(0, 0)                                            
                                               
                                               
    面向对象的好处在于,你可以把一系列的数据当做一个整体来处理,当你调用其中的一个函数时,这个函数可以获得这个整体的信息                                            
                                               
                                               
    看不懂的话看这句                                            
                                               
                                               
    如果说RemoveUnit(hero.unit)是找一把武器来杀死这个单位,那么hero:remove()就是按下这个单位身上的自爆按钮


                                               
                                             

    14.重载函数                                              
    重载函数这个名字很好听,但说白了就是给函数重新赋值罢了...                                              
                                                 
                                                 
    例子:                                              
                                                 war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第10张                                              
                                                 
    首先我将KillUnit保存在局部变量中,然后重新赋值了KillUnit:                                              
    如果单位不是"最萌小汐"才能执行杀死动作                                              
                                                 
                                                 
    由于lua的函数都是动态的,因此我们可以只在需要的时候进行重载.当你不再需要这个判断的时候,只需一句                                              
                                                 
                                                 
    KillUnit = oldKillUnit                                              
                                                 
                                                 
    即可取消重载                                              
                                                 
                                                 
    在lua中,不再使用的lua数据会被自动回收,这就包括的table                                              
    我们可以利用table来重载location相关的函数,例如:                                              
                                                 
                                                 
                                                 war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第11张                                              
                                                 
    这样你便可以放心大胆的使用location,完全无需担忧泄露问题


                                               


                                               

    15.重载操作符                                              
    我们定义2个三维向量                                              
                                                 
                                                 
    a = {10, 20, 0}                                              
    b = {20, 30, 90}                                              
                                                 
                                                 
    我们希望通过相加的方式来获得一个新的三维向量,但直接写 a + b 是错误的,因为lua并没有定义过表的相加方式                                              
                                                 
                                                 
    不过我们可以定义                                              
                                                 
                                                 
    我们可以使用setmetatable这个函数来为一个表添加一个元表,当table执行一些操作时,lua会去元表中寻找这个操作的定义方式                                              
                                                 
                                                 
                                                  war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第12张                                              
                                                 
                                                 
                                                 
    这里的mt就是一个a和b的元表                                              
    我们现在需要定义的是加法操作,其名称为: __add                                              
                                                 
                                                 
                                                  war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第13张                                              
                                                 
                                                 
                                                 
    之后我们可以通过                                              
    c = a + b                                              
    来获取a和b相加后的三维向量c                                              
                                                 
                                                 
    具体的流程如下:                                              
    当lua执行a + b时,检查出a的类型的table,于是打开它的元表mt,寻找加法操作__add.在这里lua很顺利的找到了mt.__add,于是执行了mt.__add(a, b),并将返回值赋值给了c.如果元表不存在,或原表中没有__add函数,lua将抛出错误                                              
                                                 
                                                 
    __add 加法 +                                              
    __sub 减法 -                                              
    __mul 乘法 *                                              
    __div 除法 /                                              
    __unm 负值 -(符号)                                              
    __pow 幂 ^                                              
    __mod 取模 %                                              
    __concat 链接 ..


                                                 

    16.表的继承                                                
    除了操作符外,读取与新建表不存在的数据也可以进行重载,其关键字分别为__index与__newindex,同样也是通过元表(setmetatable)来实现的                                                
                                                   
                                                   
    例子:                                                
                                                    war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第14张                                                
                                                   
    这里我定义了一个单位,他的数据包括hp和mp,然后我定义了一个英雄,既然是英雄那么他就要有三维,但同时他也要有单位的数据                                                
                                                   
                                                   
    在这里,我通过元表mt将__index赋值为了unit,这样当你获取hero.hp时将会返回100.流程如下:                                                
    试图获取hero.hp,但是hero里没有hp的定义,打开元表mt,成功找到了__index,他的值是另一张表unit,于是便到unit中寻找hp,成功找到了100,将其返回                                                
                                                   
                                                   
    在这个例子中,我将__index赋值为了一张表.不过他也可以赋值为函数,进行逻辑操作                                                
                                                   
                                                   
    例子:                                                
                                                    war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第15张                                                
                                                   
    此时print(t[10]) 的结果是89                                                
                                                   
                                                   
    __newindex的例子:                                                
                                                   
                                                   
                                                    war魔兽争霸3lua(lua在魔兽争霸编辑中的使用)  第16张                                                
                                                   
    如果你试图 unit.str = 15,那么就会赋值失败并显示错误                                                
                                                   
                                                   
    同样__newindex 也接受table做参数,例如前面的例子中我可以 hero.hp = 200,通过__newindex我可以实现让hero继承的unit来进行unit.hp = 200


                                                   

    嗯...想不到还有什么比较简单的东西能讲了...

    https://github.com/actboy168/jass2lua/blob/master/lua-engine.md


0