• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] LUA_FILE_HEADER

Level 31
Joined
Jul 10, 2007
Messages
6,306
Quickstart Guide to Lua Framework

Lua Tutorial w/ Lua Framework

JASS:
//Writes map header to map (run once, but multiple times won't hurt)
//------------------------------------------------------------------------
    //function initmap()
    
    //comment after initialization
    ///*
    //! externalblock extension=lua FileExporter $FILENAME$
        //! runtextmacro LUA_FILE_HEADER()
        //! i initmap()
    //! endexternalblock
    //*/

    //uncomment after initialization
    ///! import "luajass.FILE_NAME.j"
//------------------------------------------------------------------------


//import and run lua script to current script (all do same thing)
//------------------------
    //function dofile(name)
    //function require(name)
    //function loadfile(name)

//lua scripts are shared across all maps
//jass scripts are local to a map

//returns code inside of file
//------------------------
    //function readlua(name)
    //function readjass(name)

//writes code to file
//------------------------
    //function writelua(name, code)
    //function writejass(name, code)

//deletes file
//------------------------
    //function deletelua(name)
    //function deletejass(name)

//! textmacro LUA_FILE_HEADER
    //! i do
        //replace "FILE_NAME" with the name of the map
        //must be valid directory name
        //! i local FILENAME = "FILE_NAME"
        
        //! i function getfilename() 
            //! i return FILENAME 
        //! i end
        
        //Initialization
        ///////////////////////////////////////////////////////////////////////
        //! i local PATH_LUA_p = "grimext\\luadir"
        //! i local PATH_JASS_p = PATH_LUA_p .. "\\" .. FILENAME .. "_dir"
        
        //! i local PATH_LUA = PATH_LUA_p .. "\\"
        //! i local PATH_JASS = PATH_JASS_p .. "\\"
        //! i local JASS_HUB = "jass\\luajass." .. FILENAME .. ".j"
        //! i function initmap()
            //! i os.execute("if not exist " .. PATH_LUA .. " (mkdir " .. PATH_LUA .. ")")
            //! i os.execute("if not exist " .. PATH_JASS .. " (mkdir " .. PATH_JASS .. ")")
            //! i local file = io.open(JASS_HUB, "r")
            //! i if (file == nil) then
                //! i file = io.open(JASS_HUB, "w")
                //! i file:write("")
                //! i file:close()
            //! i else
                //! i file:close()
            //! i end
            
            //! i os.execute("if not exist grimext\\luadir\\" .. FILENAME .. "_dir (mkdir grimext\\luadir\\" .. FILENAME .. "_dir)")
        //! i end
        ///////////////////////////////////////////////////////////////////////
        
        //! i local olddofile = dofile
        //! i local oldrequire = require
        //! i local oldloadfile = loadfile
        //! i function dofile(name)
            //! i oldrequire("luadir\\" .. name)
        //! i end
        //! i function require(name)
            //! i dofile(name)
        //! i end
        //! i function loadfile(name)
            //! i dofile(name)
        //! i end
        
        //! i local function getluapath(name)
            //! i return (PATH_LUA .. name .. ".lua")
        //! i end
        //! i local function getjasspath(name)
            //! i return (PATH_JASS .. name .. ".luajass.j")
        //! i end
        //! i local function getjassimport(name)
            //! i return ("\/\/! import \"..\\" .. getjasspath(name) .. "\"")
        //! i end
        
        //! i local function del(name)
            //! i os.remove(name)
        //! i end
        //! i local function read(path)
            //! i local file = io.open(path, "r")
            //! i code = nil
            //! i if (file ~= nil) then
                //! i code = file:read("*all")
                //! i file:close()
            //! i end
            //! i return code
        //! i end
        //! i local function write(path, code)
            //! i file = io.open(path, "w")
            //! i file:write(code)
            //! i file:close()
        //! i end
        //! i local function import(name)
            //! i local code = read(JASS_HUB)
            //! i local line = getjassimport(name) .. "\n"
            //! i local s,k = code:find(line)
            //! i if (s == nil) then
                //! i write(JASS_HUB, code .. line)
            //! i end
        //! i end
        
        //! i function readlua(name)
            //! i return read(getluapath(name))
        //! i end
        //! i function writelua(name, code)
            //! i write(getluapath(name), code)
        //! i end
        //! i function readjass(name)
            //! i return read(getjasspath(name))
        //! i end
        //! i function writejass(name, code)
            //! i write(getjasspath(name), code)
            //! i import(name)
        //! i end
        //! i function deletelua(name)
            //! i del(getluapath(name))
        //! i end
        //! i function deletejass(name)
            //! i del(getjasspath(name))
            //! i local line = getjassimport(name) .. "\n"
            //! i local code = read(JASS_HUB)
            //! i local s,k = code:find(line)
            //! i if (s ~= nil) then
                //! i write(JASS_HUB, code:sub(1,s-1) .. code:sub(k+1))
            //! i end
        //! i end
    //! i end
//! endtextmacro

Demo
JASS:
//! externalblock extension=lua FileExporter $FILENAME$
    //run the header first
    //! runtextmacro LUA_FILE_HEADER()
    
    //writing an lua script to a follow
    //! i writelua("MyScript", [[
        //! i function Hello() 
            //! i logf("hi") 
        //! i end
    //! i ]])
    
    //using the lua script just written
    //! i dofile("MyScript")
    
    //calling a function inside of written lua script
    //! i Hello()
    
    //writing 3 jass scripts that are imported into the map automatically
    //-----------------------------------------------------------
        //! i writejass("MyScript", [[
            //! i struct Tester1 extends array
                //! i private static method onInit takes nothing returns nothing
                    //! i call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "hello world")
                //! i endmethod
            //! i endstruct
        //! i ]])
        
        //! i writejass("MyScript2", [[
            //! i struct Tester2 extends array
                //! i private static method onInit takes nothing returns nothing
                    //! i call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "hello world")
                //! i endmethod
            //! i endstruct
        //! i ]])
        
        //! i writejass("MyScript3", [[
            //! i struct Tester3 extends array
                //! i private static method onInit takes nothing returns nothing
                    //! i call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "hello world")
                //! i endmethod
            //! i endstruct
        //! i ]])
    //-----------------------------------------------------------
    
    //delete the second jass script
    //! i deletejass("MyScript2")
    
    //write jass script 1 and lua script to grimext logs
    //! i logf(readjass("MyScript"))
    //! i logf(readlua("MyScript"))
    
    //clear out so that you don't have to delete this demo from your directory : D
    //! i deletelua("MyScript")
    //! i deletejass("MyScript")
    //! i deletejass("MyScript3")
//! endexternalblock

Lua installation script template

http://www.hiveworkshop.com/forums/submissions-414/snippet-lua_file_header-186775/
JASS:
//MyScript v1.0.0.0
//! externalblock extension=lua FileExporter $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i writelua("MyScript", [[
    //////////////////////////////////////////////////////////////////
    //code



    //end code
    //////////////////////////////////////////////////////////////////
    //! i ]])
//! endexternalblock
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Next update done >: o

I don't think this can be improved anymore, honestly.

Code is now so easy to read it makes me a little bitter...

Got rid of version control as that was a stupid idea : P

Changed API (aren't I wonderful?)


Want to clear out the old version before installing this?

Navigate to your Warcraft 3 directory-

You should see a directory in there called luadir. Delete it.

Go into grimext. You should see a directory called luadir. Delete it.

Go back to Warcraft 3 directory and then go inside of the jass directory
In the jass directory you will see a file like this ->luajass.FILE_NAME.j

Delete it : P

Now put in the new FILE_HEADER, run mapinit, and you are ready to go : D.

You will have to reinstall all of the scripts /sad face.

This includes any JASS scripts that used these scripts to generate objects (delete the objects and reinstall).

The reason you have to delete everything is because object generation depends both on the dynamic jass scripts generated by this lua stuff and the objects. If you don't have the scripts to back up the object ids, it'll remake the objects with a new id. This only becomes a problem if the jass scripts that support the objects get deleted ; P, which in this case is what happened : D.

To save people from having to go through all of this nonsense to delete scripts, I added two new functions to the new LUA_FILE_HEADER

JASS:
//deletes file
//------------------------
    //function deletelua(name)
    //function deletejass(name)

Happily, these functions don't work on the old LUA_FILE_HEADER =P. If I'm ever a tyrant again about updating my stuff, you can just run deletelua(name) and deletejass(name) rather than going through all of these directories on a file hunt ; P.
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,097
So when I wanted to generate jass lines from lua in vJass, how would I go about it using textmacros?

JASS:
//! textmacro blub takes name
    generate jass lines from lua "call BJDebugMsg(\"this is function $name$\")"
//! endtextmacro

function A takes nothing returns nothing
    //! runtextmacro blub("A")
endfunction

function B takes nothing returns nothing
    //! runtextmacro blub("B")
endfunction

Problem is that //! import is done before the external script and even before textmacros. Your method collects the code to import in a single file and therefore also unloads everything at one point.

JASS:
//! textmacro blub takes name
    //! import hub
//! endtextmacro

-->

JASS:
//! textmacro blub takes name
    //! import call BJDebugMsg("this is function "A")
    //! import call BJDebugMsg("this is function "B")
//! endtextmacro

-->

JASS:
function A takes nothing returns nothing
    call BJDebugMsg("this is function A")
    call BJDebugMsg("this is function B")
endfunction

function B takes nothing returns nothing
    call BJDebugMsg("this is function A")
    call BJDebugMsg("this is function B")
endfunction

Am I only able to filter the right parts through passing an identifier to the textmacro that is used in a static if (which are very limited)? And yeah, the double saving is kind of annoying too.

My target would be to effectively combine object editor object creation with mirroring the values in jass. Inputs of this style would be nice:

JASS:
//! runtextmacro UnitType_Create("h000", "name=peasant model=units\\human\\Peasant\\Peasant.mdl shadow=[Shadow, 100, 100, 40, 40] color=[255, 255, 255]")

parsing it to

JASS:
set this.name = "peasant"
set this.model = "units\\human\\Peasant\\Peasant.mdl"
set this.shadowTexture = "Shadow"
set this.shadowSizeV = 100
...
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Yeah, but how could I approach it in general? External tools cannot return values to jass,
JASS:
//! import
is the only option to get things from outside. As portrayed, however, this command cannot be spread throughout code using textmacros.

I could export complete textmacros in the external file and import them again to only collect pastable templates at the hub but had to call them too, differing from the creation textmacro. That's kind of shitty and error-prone:

JASS:
//! runtextmacro UnitType_Create("h000", "name=peasant model=units\\human\\Peasant\\Peasant.mdl shadow=[Shadow, 100, 100, 40, 40] color=[255, 255, 255]")
//! runtextmacro UnitType_Create_h000()

or leave out the central import and do it manually here

JASS:
//! runtextmacro UnitType_Create("h000", "name=peasant model=units\\human\\Peasant\\Peasant.mdl shadow=[Shadow, 100, 100, 40, 40] color=[255, 255, 255]")
//! import "h000.j"
 
Okay, I'm kind of stuck. I've installed a few scripts:
96994d1296274328t-snippet-lua_file_header-hm.jpg


But now what do I do to use them exactly? I've tried a combination of things, and I am not really clear on it because it always ends up giving me some sort of error. After a while, I used it in a testing map and the save kept giving me an error saying that "The File Exists". There is no more lua in it though. Now it does it for every map that I open, so yeah. :p I need some more info.

After Restarting my computer, it saves and then takes like 1 minute before popping up the error. :p I'll probably reinstall. I just want to know the proper method so I don't have this happen ever again.
 

Attachments

  • hm.jpg
    hm.jpg
    26.9 KB · Views: 311
Level 31
Joined
Jul 10, 2007
Messages
6,306
You made sure to update the header right?
JASS:
    //comment after initialization
    /*
    //! externalblock extension=lua FileExporter $FILENAME$
        //! runtextmacro LUA_FILE_HEADER()
        //! i initmap()
    //! endexternalblock
    */

    //uncomment after initialization
    //! import "luajass.FILE_NAME.j"

And a map with absolutely 0 lua code popping the error... now that's funky..

I haven't run into the same issue, hm.. let me know if you did the map header fine.

Could you please zip up the grimext directory in your wc3 directory and upload it so I can take a look and see what's going on? If there's nothing wrong with your directory, then it's a direct map issue. Can you upload your map too please, tx. And please include any lua code you used.

Zip up your jass directory too while you're at it.



Also remember that if you had any old versions of like var object and this one, you had to delete them. I'll check and see what's wrong though, np.
 
Hmm.. I did this:
JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")
//! endexternalblock

Saved that, just to see if it parsed. Then I changed it to this:
JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")

    //! i local rez = getvarobject("AHre", "abilities", "ABILITIES_REVIVE_UNIT_RESURRECTION", true)
        //! i createobject("AHre",rez)
        //! i makechange(current,"anam","DumResurrection")
        //! i makechange(current,"aher","0")
        //! i makechange(current,"acat","")
        //! i makechange(current,"atat","")
        //! i makechange(current,"Hre1","1","1")
        //! i makechange(current,"aare","1","0")
        //! i makechange(current,"aran","1","0")
        //! i makechange(current,"acdn","1","0")
        //! i makechange(current,"amcs","1","0")
        //! i makechange(current,"atar","1","Air,Dead,Enemy,Friend,Ground,Neutral")

    //! i local dummy = getvarobject("ushd", "units", "UNITS_REVIVE_UNIT_DUMMY", true)
        //! i createobject("ushd",dummy)
        //! i makechange(current,"unam","Dummy")
        //! i makechange(current,"uabi","'" .. rez .. "',Aloc,Avul")
        //! i makechange(current,"ucbs","0")
        //! i makechange(current,"ucpt","0")
        //! i makechange(current,"umdl","none.mdl")
        //! i makechange(current,"usca","0.01")
        //! i makechange(current,"ushu","None")
        //! i makechange(current,"umvh","0")
        //! i makechange(current,"umvs","0")
        //! i makechange(current,"ufoo","0")
        //! i makechange(current,"umpi","100000")
        //! i makechange(current,"umpm","100000")
        //! i makechange(current,"umpr","1000")

        //! i updateobjects()
//! endexternalblock

Afterward. Then it brought up an error on saving. So I removed that. Then I took it down to:
JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")
    //! i local rez = getvarobject("AHre", "abilities", "ABILITIES_REVIVE_UNIT_RESURRECTION", true)
//! endexternalblock

I think it brought up an error as well. Then I deleted the directory TestingMapZ_dir and then tried to do the init again. After that it just kept saying "The File Exists". I can't upload my jass folder because I already am in the process of reinstalling. It is probably some really weird error though, because I do not remember exactly what I did.

I just need to know the proper way so I can prevent myself from experimenting. xP

EDIT: Lol, I think I have to reinstall wc3 in general. It still shows the error after reinstalling newgen. Even on new maps.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok this does absolutely nothing
JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i dofile("GetVarObject")
//! endexternalblock

Well, it does do something, but it doesn't actually write anything. All of the updating is done in the updateobjects() call, so that first thing shouldn't have changed anything in your map.

After running your code, I have gotten 0 errors.

You did remember to disable the installation code for the lua scripts right? The lua scripts on the site are installed, meaning you install them into your computer by saving them in WE one time. After saving them, you can delete the trigger, disable the trigger, or w/e, but having it enabled installs it over and over again ;P.

I don't know what you did w/o seeing your directory, but I ran into 0 problems following all of the steps you said you took ;P.

You can experiment and etc just fine as long as you know how the lua framework works (where stuff is written). When writing resources, knowing where stuff is written can be helpful so you can do clean installs of your scripts for testing =). Really, it's pretty simple.

It writes a single file into the jass directory for importing.
It writes a new directory called luadir into the grimext directory
Inside of the grimext directory, it creates a new working map directory for your map and treats the parent directory as a directory for lua scripts. Plain lua scripts go into the parent while map specific scripts go into the map directory. Currently, all lua scripts are auto global (non map specific, which is why I add the map name to the file), but there should be a flag for determining whether the lua script should be global or local.

You must have done something more than what you stated in those steps because I ran into 0 errors ;P.



This is in my JASS import file
JASS:
//! import "..\grimext\luadir\dummy_map_dir\JassGlobals.luajass.j"

This is the file output for objects running your script

return {['ABILITIES_REVIVE_UNIT_RESURRECTION']='A!!!',['1A!!!']='ABILITIES_REVIVE_UNIT_RESURRECTION',['UNITS_REVIVE_UNIT_DUMMY']='u!!!',['1u!!!']='UNITS_REVIVE_UNIT_DUMMY'}

And this is the directory generated (not same name, but w/e)
dummy_map_dir

And here are imported globals inside of the JassGlobals.luajass.j file.
JASS:
globals
constant integer ABILITIES_REVIVE_UNIT_RESURRECTION='A!!!'
constant integer UNITS_REVIVE_UNIT_DUMMY='u!!!'
endglobals

All ran pretty dern smoothly ;P.
 
Oh well, whatever it was, it is fixed now. In another thread (someone actually had a similar problem a long time ago) phyrex just said to delete the temp folder. So I did and it worked like a charm.

Which probably means it isn't your LUA or anything that you can fix, it is probably some fluke I did that messed up jasshelper. :p

EDIT: Btw, it works perfectly now.
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
Read the quickstart guide

Comment out this portion from demo-
JASS:
    //clear out so that you don't have to delete this demo from your directory : D
    //! i deletelua("MyScript")
    //! i deletejass("MyScript")
    //! i deletejass("MyScript3")

Save map, disable demo trigger, save map again, hit test map. You should see hello world. Uncomment the above to delete the demo out of the map = ).
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
The framework is primarily used for dynamic object generator (Object Editor in WE).


Some JASS resources, like Unit Indexers, Unit Event libs, and Bonus libs, require certain objects with certain properties be created. These resources can use Lua to generate those objects (in this case units/abilities) and then store them into a dynamically generated JASS script so that they can be accessed via JASS.


I've also seen the Lua Framework used for generating masses of destructables (rotated barrels).


If you have no clue what it's even useful for, chances are that you don't need it ; ).


Here is an in-depth tutorial written by Purge
http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/lua-object-generation-191740/
 
Top