Rick Posted November 29, 2009 Share Posted November 29, 2009 So from what I know if you just make a variable and assign it a value it'll be global unless you put local in front of it. So in the fpscontroller.lua file (which seems to be the file that gets played when you run game from the editor) I make a variable and set it to true: runGame = true Then for the main game loop I do: while runGame do ... end Then I load the monster truck entity just to test this out. I just need an entity to have it's Update() method called each frame. I make a small change inside the Update() method of the monster truck: function Update(model) local model local entity for model,entity in pairs(entitytable) do entity:UpdateTires() end if KeyHit(KEY_ESCAPE) == 1 then runGame = false end end But when I press ESCAPE, the game doesn't end. What gives? Quote Link to comment Share on other sites More sharing options...
Josh Posted November 30, 2009 Share Posted November 30, 2009 Is KEY_ESCAPE defined anywhere? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 Is KEY_ESCAPE defined anywhere? I include base.lua which includes engine_const.lua which defines KEY_ESCAPE. I also tried the actual number instead of KEY_ESCAPE but that didn't work. I'd love to see if my Update() method is actually getting called. What would you recommend I do to see this. Normally I would use lua's print() but that doesn't seem to do anything. [EDIT] OK, using AppLog() I see it's getting inside the KeyHit(). So it must be setting runGame to false, but that's not being seen in the main game loop inside fpscontroller.lua. Quote Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 Global variables are bound to a lua state, not a specific script. So they should keep their values if you keep reusing the lua state. Is this what's happening the in editor? I assume only one lua_State* is being used to call all these scripts? Quote Link to comment Share on other sites More sharing options...
Josh Posted November 30, 2009 Share Posted November 30, 2009 Each model class uses its own Lua state. This allows one script to be edited at a time, but interstate communication is a little more difficult. You can use SetGlobalNumber() to communicate in this situation. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 Is there something like this for lua tables also? If not, then could there be because this seems like kind of a big limitation. For my coroutine system it needs to have global tables. I want this to be a "model" that users can just drag into their Sandbox scene and use instead of code files that they have to put into their custom main loop lua file. The "model" lua script would house the tables and the Update() method to run checks on entries in these tables. Another script would provide the methods to use like: DoWait() DoWait() would need access to these global tables to add entries. Quote Link to comment Share on other sites More sharing options...
Josh Posted November 30, 2009 Share Posted November 30, 2009 I don't know how that would be done. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 I don't know how that would be done. How is SetGlobalNumber() working currently? I would imagine you would have to loop through all the lua states you have and set a variable for each one and give it the value. Quote Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 So I assume giving all these scripts the same lua state isn't going to ever happen for the editor? Just wondering where this stands so I can try to figure out the best way to handle this. The best way that I see is to use the same state for all of these, but that would be up to you for the editor. Quote Link to comment Share on other sites More sharing options...
Josh Posted November 30, 2009 Share Posted November 30, 2009 SetGlobalNumber() sets a value in the engine. GetGlobalNumber() retrieves it. I don't have any plans to change the way the states are set up. It would require all the scripts to have their functions renamed like "light_directional_Update()" and who knows how else the scripts would interfere with one another. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted November 30, 2009 Author Share Posted November 30, 2009 OK, that really hurts the logical entities idea. Calling the community: How can we share variables between all entity scripts? Put on your thinking hats because you'll most likely run into a situation where you'll need this when making a game. I have a hard time believing a full game can be created without it. Quote Link to comment Share on other sites More sharing options...
Canardia Posted November 30, 2009 Share Posted November 30, 2009 You can use GetTarget(0) to get a target entity from another, and set a EntityKey in the target entity. I guess you could also use SendEntityMessage to send a message to the target, but that needs probably a bit more coding. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Josh Posted November 30, 2009 Share Posted November 30, 2009 Can you give an example of what you are trying to do? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted December 1, 2009 Author Share Posted December 1, 2009 Sure. This all revolves around my coroutine entity that I'm creating. So the thought process goes like this: 1. Create an entity that is like a light in that in the editor it has properties and has an Update() method that gets called each cycle but this entity isn't shown. It has no visual to it. It's just logical. 2. Ideally this entity would create some global tables. These tables are iterated through in it's Update() method. So far so good. 3. There is another .lua file that people include in their scripts. This file defines functions like RunScript(func) & DoWait(cr, interval). The DoWait() method adds entries to the global tables that the coroutine entity created when it was placed into the scene. So this is where the table would need to be global. Imagine you create a volume trigger. In the Collision() function you want to run a sequence of events. To make it simple let's say when the player collides with this trigger you want to wait 5 seconds and then end the game. In this volume trigger script you would include (dofile) this coroutine.lua file. This would give you access to the DoWait() function. To simplify in the volume trigger script you write a function that is your sequence of events. Then in the Collision() method you call RunScript() (also available because of coroutine.lua including) passing in your function to run. Inside RunScript() is where you first call DoWait(5000), then set some flag to kill the program. Here is some pseudo code of what I'm trying to get done: coroutine_coroutine.lua --- This is the entity you add in sandbox function Spawn() tblWait = {} -- Creates a global table end function Update() -- loop through tblWait looking to see if entries have their time up so we can resume the function for k, v in pairs(tblWait) do end end cr.lua -- gives access to some functions function DoWait(cr, interval) -- Create a timer of sorts that last for interval time and add it to tblWait global table coroutine.yield() -- this actually yields the function they are in. Looping through the tblWait let's us know when a time is up to resume end function RunScript(func) cr = coroutine.create(func) coroutine.resume(cr, cr) -- starts the function they passed in passing to it the coroutine created for it end trigger_volume.lua -- example of how a trigger volume would work function Spawn() end function Collisions(...) RunScript(MyScript) -- starts the script sequence end function MyScript(cr) DoWait(5000) endGame = true end Quote Link to comment Share on other sites More sharing options...
Josh Posted December 1, 2009 Share Posted December 1, 2009 1. Create an entity called "func_endgame". 2. When the player hits the trigger volume, send a message with a 5 second delay to the func_endgame entity. 3. When the func_endgame entity receives a message called "activate", it calls SetGlobalNumber("gameover",1). 4. Your main loop has this code: if GetGlobalNumber("gameover")==1 then return end Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Nilium Posted December 1, 2009 Share Posted December 1, 2009 How can we share variables between all entity scripts? If you put each entity in a separate Lua thread (bear in mind that I am only talking about having one actual Lua state) and then give that thread a separate environment while still retaining access to the globals table (fairly easy to do with metatables), then you should have the same effect without the wasted memory use, need for things like "SetGlobal*", etc. I don't think it's likely that you'll be able to do this without writing your own code to handle entities in Lua, however. 1 Quote MacBook Pro 15.4", Intel Core 2 Duo T9600 2.80GHz, 4GB 1066MHz DDR3, GeForce 9400M 256MB, GeForce 9600M GT 512MB - Mac OS 10.6.2, Vista32 Link to comment Share on other sites More sharing options...
Rick Posted December 1, 2009 Author Share Posted December 1, 2009 1. Create an entity called "func_endgame". 2. When the player hits the trigger volume, send a message with a 5 second delay to the func_endgame entity. 3. When the func_endgame entity receives a message called "activate", it calls SetGlobalNumber("gameover",1). 4. Your main loop has this code: if GetGlobalNumber("gameover")==1 then return end You are missing the point. The point wasn't to end the game. That was just an example. The point was to provide the functionality of DoWait() to the engine. And DoWait() is just the start. DoSound(), DoMove() will all act similar but their conditions to start the function back up will be when the sound is finished playing, and when the entity has reached a destiation. So a message delay isn't enough in these situations. Quote Link to comment Share on other sites More sharing options...
Rick Posted December 1, 2009 Author Share Posted December 1, 2009 You are missing the point. The point wasn't to end the game. That was just an example. The point was to provide the functionality of DoWait() to the engine. And DoWait() is just the start. DoSound(), DoMove() will all act similar but their conditions to start the function back up will be when the sound is finished playing, and when the entity has reached a destiation. So a message delay isn't enough in these situations. Your example and my example do the same thing but they do them very differently. That difference is the key because when the examples get more complex my example will work. Think of stepping out of the function completely only to return at another time. -- This is the coroutine way function MyScript() DoWait(5000) i = 5 DoWait(10000) i = 10 end -- This is the way you are talkinga bout function YourScript() SendMessage(x, y, z) i = 5 SendMessage(x, y, z) i = 10 end Let's imagine stepping through these functions. In YourScript() we would step right through it. First SendMessage(), then i = 5, then SendMessage() again. Stepping through YourScript() would take about a second and it would be finished. Stepping through my script would take 15 seconds minimum. Because when we hit the DoWait() function it actually leaves MyScript() and comes back into it 5 seconds later. So if we stepped through it when we ran the DoWait() function it would actually go back to whatever called MyScript() and continue on with the engine loop. This is where the global tables come in. DoWait() added an entry to this global table that says MyScript() is to run again in 5 seconds. Then that global table is iterated over inside the Update() of the coroutine model class to see if 5 seconds has past. Once it has, we call the function again, but because it was setup as a coroutine it will start up where it left off. So if we were stepping through the function it would come to the i = 5. So you see in my example i will = 5 for 10 seconds, but in your example i will = 5 for about a millisecond because it'll just continue on to SendMessage() which just continues. So you can think of DoWait() as blocking to the function it's in, but not to what called it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.