Ok so I've been messing around with lua because I need to implement it in one of my projects.
I understand that Xlua is considered the best variation of the lua extension, but I have yet to be able to do anything with it. The regular lua extension seems a bit easier to use as well.
Anyways a couple of questions:
-Is it possible to load all of the scripts that will be used into memory from files at runtime?
-Can multiple scripts be ran at once in a loop?
-Can variables inside lua be changed by mmf? (ex. have a command like this: "print ($text)" and have mmf change the variable $text)
-Can a function be made that allows lua to gather data about anything inside mmf, like: getplayerx()
-Can someone make an example of a script reader with custom functions that uses the Xlua objects?
To answer your questions;
-Is it possible to load all of the scripts that will be used into memory from files at runtime?
YES. dofile("name.lua") is the function you call in your script
-Can multiple scripts be ran at once in a loop?
Im not sure what you mean. When you execute a script it will read it from top down and do any events that are within that. Same as when you call a function.
-Can variables inside lua be changed by mmf? (ex. have a command like this: "print ($text)" and have mmf change the variable $text)
You need to pass values and variables into LUA and vice versa. Lua can also read and write to objects in MMF if you have MMF interface selected.
-Can a function be made that allows lua to gather data about anything inside mmf, like: getplayerx()
Yes, see above. Turn on MMF interface. I suggest you read the help file.
When you say "dofile("name.lue")" does that mean It'll grab that file and load it into memory so that the original file can be deleted off the machine, but still run?
I want to run multiple scripts that apply to the same active objects, but at the same time change the varibles in that script to the Alterable Variables of that object. Like so:
MoveObject(getA()+5,getB()-3)
and getA() gets the Alterable Value A of whatever object it is that the script is manipulating.
I'm having a hard time explaining. Thanks for the help though. I'll go read the documentation, but the examples didn't help me much.
I see you are using Zephni's coroutine example.
Coroutines I dont really know much about and I wouldnt suggest you even bother looking at this unless you want to make a scripting engine. Coroutines pause your application which is what is needed for scripting.
To interface with objects directly you need to tick the box under xlua properties which says 'enable MMF interface'.
Look at the example file that is supplied with the xlua zip file. One of them shows how to interface with MMF directly.
What you need to do is export all your objects into a LUA table so that it can reference them later. This can be the fixedvalue of the object or a custom ID value, it doesnt matter as long as you can select the right object.
Once you have the IDs stored in a LUA table you can then do commands such as mmf.Object.GetValue(ID,1) which will return Alt value A for the unit exported with that ID. You can also write to the Alterable Value by using mmf.Object.SetValue(ID,1,999) which will set Alterable Value A of object with ID to 999.
Take a look at the help file under 'MMF interface' which lists all the different interface functions. You can also change objects positions, order and many other things.
In regards to dofile("file.lua") command, this simply includes that script into memory exactly how 'include' works with C/C++.
Wether you can delete this once it has been loaded into memory is something you will have to test but if you were worried about people having access to your file include them in string objects instead within MMF or use the binary object to pack/unpack them only when you are loading (this is what I do)
You should also post in Clickteam forums which have a dedicated LUA section. Retriever2 always answers any questions you have, he made the xlua extension.
Alright I might just head over to the clickteam forums. However I think I'll just stick with the regular lua extension since it seems easier, and I don't really want to do a super complex system. Just for character dialog and such.
I'll most likely make a custom setup that uses lua and a custom scripting engine combined.
Also I have to store the files externally because, you see they need to be updated periodically over the internet. That's why I need to load them into memory at runtime somehow and then delete them, or in the very least make them virtually inaccessible. I think I'll just blowfish encrypt them or something.
I would strongly advise to use xlua extension.
One of the LUA extensions is no longer being updated (Jamie's one) and the other one is very basic. XLua is only complex if you need it to be. Its continuously being updated too and the author is there to answer all your questions as I mentioned in my last post.
Its up to you though
i don't think xlua can call mmf functions through coroutines; i asked rii about and he didn't say anything about it being intentional (specifically he said it could be due to how xlua handles its call stack or luajit's way of handling coroutines)
for now you'll probably have to use the regular lua object, but if this can be fixed you will definitely want to look into using xlua instead
I dont see how xlua would not be able to handle the coroutines, its part of the LUA code...
All these extensions do is allow MMF to link in with LUA scripting. I will play with the example and see if I can get it to work later.
EDIT: ok you are right, for some reason coroutines dont seem to work with xlua. Well they might work, just not the way that Zephni's example works. Actually now that I think about it I did try to get coroutines working before but couldn't get it working, I wonder if thats why...
Originally Posted by bigredron I dont see how xlua would not be able to handle the coroutines, its part of the LUA code...
All these extensions do is allow MMF to link in with LUA scripting. I will play with the example and see if I can get it to work later.
if it were due to the c function stack that would be why; apparently it can be quite difficult to communicate with mmf without crashing it, and calling c functions when it doesn't expect them is one way to blow it up (which is why there's two different calling modes for the print and error queues: "Queued" is far less likely to crash mmf but is limited to the size of the event queue [which is only like 20 or something], and "Immediate" isn't limited to the queue size but can desync with mmf and crash it)
luajit itself apparently makes changes to how coroutines work with c functions, to make them more efficient for the compiler and to also remove some restrictions that are normally there (specifically with coroutine.yield()). this could also be another factor if it's not playing well with mmf
the original lua object is probably just a straight-up embedding of lua into an extension so it doesn't have this problem as it doesn't have the features that could cause it
anyway, coroutines do work in xlua, but only inside lua code; if you try to call functions inside mmf from inside a coroutine, nothing will happen in mmf and the coroutine will just continue on its way
Xgoff:
You are right about some sort of C error.
I did an OnError function in MMf events and printed the result to the popup box.
See this link: http://img511.imageshack.us/img511/9712/xlua.jpg
Not too sure what it means though, i dont have C experience.
UrbanMonk:
You can probably do a dirty workaround by storing your script in a lua table.
Then you would have some sort of counter to keep track of the line number and pull the appropriate string from the table. You would call the function 'say' every time the user presses key to continue.
Similar to this:
** IN LUA **
script={"first sentence","second sentence","third!","and last but not least, four!"}
LineNumber = 1
function say()
print(script[LineNumber])
LineNumber=LineNumber+1
end
** IN MMF **
+ Upon pressing enter
-> Call function "say"
I'm sure there are other ways too, you just need to be creative
Originally Posted by bigredron Xgoff:
You are right about some sort of C error.
I did an OnError function in MMf events and printed the result to the popup box.
See this link: http://img511.imageshack.us/img511/9712/xlua.jpg
Not too sure what it means though, i dont have C experience.
Those are Lua errors, coming from lines 7, 12, 43, and 61 of data.lua. The first three errors are within functions, the last one is not. I can only guess that these errors are because you're calling the yield function wrong.
Originally Posted by UrbanMonk This kinda ruins the whole idea behind using lua. I was gonna use it to make dialog easier.
Do you think I could perhaps store the lines inside of a text array, and call each line from there?
I could just make my own pause command. hmmm.
Since I'm not using c code for anything I'll most likely just use the regular lua object for simplicity sake.
Thanks so much guys. If you think of another way around this let me know! I'm curious about this now.
"c" in this case just means mmf, since that's what it is on the level lua is working with
and yeah that error is resulting from trying to yield from a c function which is not allowed... why that works in lua' but not xlua i'm not sure, unless it's due to differences in communication. apparently this is one of the things being looked at for lua 5.2 but no telling when that will be released
as an alternative to coroutines i would do something along the lines of what bigredron suggested; this sort of system could actually be done easily without coroutines... i may come up with some system later that's pretty much equivalent to this
ah, I see. What I originally thought was kinda weird anyways!
Ok, so forgetting coroutines for a second. Is it still possible to create a custom scripting engine with my own functions that call functions from within mmf?
If so, how would I load my custom functions into mmf? Do I have to load the functions after the main script that calls them, or could I load them before hand?
If I made my own engine to stop and start lua scripts doesn't this just add extra overhead that lua was supposed to remove in the first place?
When running a lua script does the whole script run through completely when it is called in an action, or after the mmf loop is complete? Because as far as I know when a mmf function is called from within a lua script mmf has to search for the function in the regular mmf loop code in order to execute the actions it contains.
Sorry for all the questions! Hope this all makes sense to you all!
Ok, so forgetting coroutines for a second. Is it still possible to create a custom scripting engine with my own functions that call functions from within mmf?
yes, although without coroutines you have to handle the "pausing" between lines yourself. manually going through lines in a table is easy and does this, but then you can't use functions as you normally would, because they'll automatically execute during the table construction (which you don't want). in this case you'd have to use string commands mixed in with your text strings, but then you'd also make it automatically jump through a set of consecutive commands (while executing them) without stopping... it's not hard it's just annoying and error-prone
If so, how would I load my custom functions into mmf? Do I have to load the functions after the main script that calls them, or could I load them before hand?
your custom functions (if they're lua ones) can just stay inside the same lua script as the rest of the engine
If I made my own engine to stop and start lua scripts doesn't this just add extra overhead that lua was supposed to remove in the first place?
technically, though with this kind of script system the overhead is pretty much negligible; you don't start seeing the difference between lua<->mmf and lua alone until you start calling a ton of functions per second (in the thousands)... a simple script system shouldn't be doing this
When running a lua script does the whole script run through completely when it is called in an action, or after the mmf loop is complete? Because as far as I know when a mmf function is called from within a lua script mmf has to search for the function in the regular mmf loop code in order to execute the actions it contains.
that's just a design issue in mmf. everything in lua is stored in a table (including the global environment, in a table called '_G'). when you call a function, lua just does a table index like _G["function_name"](param1, param2, ...). since it uses hash tables this is pretty much an immediate effect: it KNOWS where the function is (or it has a really good general idea), it doesn't have to search every index for it
it's probably overboard compared to what you want but it works fine (at least as far as my limited bug testing went). there's a few things i don't like code-wise (related to passing), but oh well. it makes a decent example at least
it uses the "table full of strings" approach including the aforementioned text commands
You even have a method of storing dialog outside of the script!
So from a normal users point of view would it be possible to simplify the scripts for creating dialog in such a way that it would be extremely easy for someone who's never scripted before to pick up.
I was thinking of something along the lines of the original example. Except I didn't want to encounter the bugs that the original lua extension had. (not that I even knew what they were! ) That's why I was trying to "convert" it.
I wanted to have more commands than just dialog however. (ex: open door (1) or saveplayerstate("Dark Caves",3,"blah") )
My initial plan was to be able to pass variables into the script itself (without having to parse anything, direct variable injection!) This is so I could create one script that could apply to many objects. Like a spring script that allows one to change the bounce height, but at the same time be editable on the script level.
Another reason to do this the lua way instead of making a custom scripting engine is the fact that it's able to do math within the script itself. Which is a big problem with my current setup. (I overlooked it)
Anyways Thanks Sooo much, I'm gonna examine this and see if I can figure it all out!
Hopefully I can figure out how to do what I want without too much hassle!
EDIT: I like how you made your script easy to edit! Awesome! All those little comments!
yeah my example isn't as transparent as it could be, but other ways to do it would look ugly without having to use an entirely new system. bringing up that problem with table constructors calling functions, you'd instead need something like:
person = Dialogue {
"hi",
"calling a function",
function () saveplayerstate("Dark Caves", 3, "blah") end, -- bleh
}
and make appropriate changes in the line reader to check the type of the line to see if it's a function, then run that instead of the parser (which would probably be removed entirely)
it's not entirely impossible to implement a pseudo-variable system inside text strings, but it's not clean either. you could have something like:
replacing anything starting with '$' with the value of whatever is stored in the variable with the same name. however that still makes math messier since you have to use temporary variables for some things
adding more commands would be easy since there's that section where they're all defined, so you'd just have to implement the functionality of that command in mmf and call it through that command
Hmm, soooo, would I have to attach all those functions to whatever script I'd want to run, or could I have separate scripts that could piggy back off the functions already defined in the main script? EDIT: wait, I think this is somehow linked to coroutines which you said wasn't possible in Xlua, right?
Sorry for bothering you, it's just that this seems so difficult to implement in a clean way.
I don't want users to have to bother with all the extra syntax needed to make a script function properly, but at the same time I want to keep it clean on the mmf side of things. Perhaps what I want to do is impossible with lua alone...
Thanks for your great work again! I'm gonna have to go read up on some lua documentation this weekend!
after that you could use it in other scripts simply by using the 'require' function:
talk = require("textengine") -- "textengine" being the filename of the dialogue engine. note that you don't include the '.lua'!
talk.Dialogue {
"blah",
}:begin()
you'll probably have to make a global alias for 'MMF_Next' since it will now be inside the module, so you could just do 'MMF_Next = text.MMF_Next' inside your scripts
Interesting. Would it be possible to get rid of the "talk.Dialogue {" bit in user made scripts on a lua level? (by that I mean by not adding it later from within mmf) So that it would be easier to edit for the less experienced.
Also would there be a way to add modules at run time. Like calling scripts when the objects that they represent are interacted with, or "called" if you will.
Interesting. Would it be possible to get rid of the "talk.Dialogue {" bit in user made scripts on a lua level? (by that I mean by not adding it later from within mmf) So that it would be easier to edit for the less experienced.
off the top of my head i can't think of a way, at least not a way that would be any cleaner. it is in fact just a normal function. it'll have to be used at some point
however, if you've checked the 'external_dia.txt' file you'll see it's just the dialogue (and commands) only, not even requiring the quotation marks, so as long as your main script somehow has a way of making text.Dialogue{}:load("whatever.txt"):begin() hidden from the user it may work out. imo the way it is now isn't all that confusing (it could be worse!), and newcomers shouldn't have a problem if they were given a couple of examples
Also would there be a way to add modules at run time. Like calling scripts when the objects that they represent are interacted with, or "called" if you will.
i'm not totally sure what you mean with this... you want scriptable objects that are their own separate modules?
Also would there be a way to add modules at run time. Like calling scripts when the objects that they represent are interacted with, or "called" if you will.
i'm not totally sure what you mean with this... you want scriptable objects that are their own separate modules?
Exactly. I want to have different types of "objects" as well, but this would be handled mmf side. Most of the scripts would just be checking variables and changing the animation/interactions of the object when a change occurs.
Actually come to think of it all I'd need is for the script to activate once the object is touched (for the most part)
But I'd also like to be able to make objects that can be changed by other objects, or objects that can retrieve outside information and use it within itself. Like $name = getplayername() (if that's even how lua works with setting variables)
Or:
$door = getunlockedstate()
if ($door > 0) then
setframe(2,4)
end
But in this case the script would have to run at the beginning of the frame, or at least when it becomes visible on screen.
If it were run at the beginning it would have to iliterate through all the scripts that are supposed to run at the beginning.
I also considered doing a system that is part lua and part mmf, where mmf handles the variables and the object setup, but this would be less seamless.
This may just be too much to ask, but it would be awesome if it were possible.
With xlua you can do what you want as you can modify objects position/values etc if you have MMF interact selected.
I guess what you would have to do is give each objects an alterable string with a unique ID or something and then export that object to LUA so you can load it into your custom script and do your checks there. You would need to store your IDs into a table in LUA so you can loop through it and do checks etc.
Yes that's what I meant, but I think I'll just use the regular lua object and make a system that selects which script to run based on variables that mmf retrieves externally, and just make a special editor for it or something.
Although it's a more complicated solution it would be easier my users in the long run.
not to plug xlua more or anything but rii just fixed the coroutines thing
also that one xlua'd coroutine example you were using was in fact not ported entirely correctly; the first LF_StringReturn$() should be replaced with MF_StringParam$() and the Val(LF_StringReturn$()) is better replaced with MF_NumericParam()
Originally Posted by UrbanMonk Oh, whoops. I hate capital sensitive languages. I thought that was just a linux thing. Guess not.
What's the benefits of a capital sensitive language anyways?
most programming languages are case-sensitive, actually
i doubt there's really any benefits to a language being case-sensitive as opposed to not, though on a lower level it's easier to implement them as CS, since you only have one character meaning something instead of two
CS does allow you to have two or more variables with the "same" name, and in cases where those variables are very closely related, it can be convenient for them to share the "same" name as opposed to cluttering them up with underscores or something. for example, in that dialogue script i posted, 'Dialogue' objects use the 'dialogue' table. of course abusing this ability can cause confusion, but then again so can the lexical scoping lua uses:
function doSomething (table)
return table.sort(table)
end
it's very likely you'll get an error when running that, because the 'table' variable in the parameter list overrides the global 'table' when you try accessing it. that's bitten me a couple of times when i haven't paid attention
mmf is semi-case sensitive; you can type something like 'val()' or 'VAL()' or 'vAl()' and it'll take it, but it'll automatically convert it to the "correct" form by the time you view that expression again
Yeah, well on a lower level it would of course make sense, but I still don't see the point in doing it that way.
I don't want people to be confused by it, so I'll most likely make a parse table to convert everything to the correct cases, and for the rest make it lowercase.
I understand that I can get data about mmf objects directly, but I was wondering if mmf can pass information to Xlua from actions. I asked about this already, but I didn't get the answer I was looking for.
So.. Is it possible to create a function that returns data instead of actually carrying out an action. Such as.
GetPlayerName() could return the players name in the form of a string. So
Print(GetPlayerName()) Would print the players name?
Also how do I combine data types in a single input line. OR more specifically how can I include varibles in, say, strings. like:
Print("Hello "+GetPlayerName()+" How do you do?")
But I know that's not how it works, so how would I accomplish this?
if GetPlayerName() is something you'd use in an 'On Function' event, then look under the 'MMF Functions' menu for 'Push String Return'
then you'd do something like this:
On Function "GetPlayerName"
--> XLua - Push String Return: player_name [or whatever GV/AV/array/whatever it's in]
lua does automatic conversions (except in a couple of cases irrelevant here) when possible; right here you don't even have to worry about it, since that function already returns a string. however, lua uses '..' and not '+' to concatenate strings. if you wanted to force a conversion, you could use the tostring() function around whichever function or value you wanted to convert
so as it is, you'd use: Print("Hello " .. GetPlayerName() .. " How do you do?")
Hello, I'm the author of XLua, and I just wanted to throw in that the real reason you should not use the original Lua Object, or the LuaPlus object, is because they are both unstable and crash under larger scripts, and are no longer maintained. That is why XLua came into existence.
XLua is really based on the LuaPlus way of doing things, but you can also do things the old Lua-Object way too. The action "Lua Functions->Inline Parameters->Call With Delimited String" is the same as the Lua-Object "Call Function" action. You can also use DoCall() in your lua scripts to call On Function conditions, like you do in the Lua-Object. Sometimes this is the best way to do things, but it's worth taking the time to learn the other actions because they preserve type information and make some tasks easier.
Originally Posted by Xgoff however, lua uses '..' and not '+' to concatenate strings. if you wanted to force a conversion, you could use the tostring() function around whichever function or value you wanted to convert
so as it is, you'd use: Print("Hello " .. GetPlayerName() .. " How do you do?")
Great! That's the info I was looking for. That's pretty similar to php, I was trying to use "blah " . " Blah" but I see I need two periods now. Nice.
Originally Posted by Retriever2 XLua is really based on the LuaPlus way of doing things, but you can also do things the old Lua-Object way too. The action "Lua Functions->Inline Parameters->Call With Delimited String" is the same as the Lua-Object "Call Function" action. You can also use DoCall() in your lua scripts to call On Function conditions, like you do in the Lua-Object. Sometimes this is the best way to do things, but it's worth taking the time to learn the other actions because they preserve type information and make some tasks easier.
I'm going to take a look at all the new commands too. Some of my functions need to be called from within mmf2 because I want to hide what they are doing. Mostly communicating with the get object to get info from a php script.