There's also a 'Depth Fog' Option in the 'GL Options'. And if the fog is way too far away, you can use 'GL_DistFog' in the console to make it a bit more visible. There you go. It isn't the Doom Fog, though, but everything brights up the closer you get.bagheadspidey wrote:It's the lightning, too - can it be made to do the blocky lighting like the software renderer?
Lua
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
I haven't looked at it to be honest. I just want to get the website stuff out of the way without being distracted by Doom code. I've only been keeping a cursory track of what you've committed to SVN. I honestly hope I won't have too much trouble merging my current work-in-progress changes with all the commits you've done in the last four months.Graf Zahl wrote:He hasn't made a single comment so far. Well, there's always GZDoom, right?
That said, I still want the experience of writing my own scripting language. I tried eight years ago but didn't get too far, and I'd like to succeed this time around. I worry about the split that would occur if you added one thing to GZDoom and I added something else to ZDoom.
So here are the thoughts I had about what I want to see in the language before I got the notice from Lunarpages that I need to streamline my site or risk being kicked off. (Fortunately, they seem pretty lenient as long as I'm on this non-production server, but I do want to hurry up and get off, so I've not given the language much thought since then.):
- Object is a basic type for the language, as it is for Java and C#. New classes implicitly have it as an ancestor, and you are not limited to only subclassing actors.
- The language supports dynamic allocation of objects.
- An incremental garbage collector is used to reclaim dead objects. Not only does this free users from the burden of having to worry about freeing objects, but it also simplifies various implementation details. The pointer cleanup ZDoom already does is essentially a special-case mark-and-sweep single-pass garbage collector that can run as many as 35 times per second depending on the level activity. It's already known that this can cause slowdown in extreme maps. An incremental garbage collector should theoretically be able to perform better, since it can spread the collection out across multiple tics instead of doing it all at once. At worst, the performance should be about the same as what's in place now.
- Objects can also have arbitrary data associated with them by accessing them like an array:This provides an alternative path for extending objects without subclassing, in cases where subclassing is impractical. This is mostly for the benefit of using the language as a replacement for ACS. Right now, extra data about player state that modders want to maintain is commonly kept in arrays. Wouldn't it be better if that data could be kept directly with the player? It's cleaner and, more importantly, avoids the problem of assuming a fixed maximum number of players.
Code: Select all
someobj['mydata'] = foo;
Perhaps there can also be syntactic sugar for this so that the above example can also be written as:I'll have to see if that causes any conflicts with the grammar for labels first.Code: Select all
someobj:mydata = foo; - The parser is designed to be two-pass, so it collects type information in the first pass and compiles functions in the second pass. Then you don't have to worry about the order you define classes in.
- I'm not sure it's worth the trouble of trying to retrofit this into the existing DECORATE framework. I'd much rather start off with a new file format with a clean slate, with DECORATE support maintained as-is and give modders the option to use whichever format they prefer: DECORATE for everything possible now and script for everything else. New actors defined in script could even expose methods to be used for DECORATE parsing, so you could define an actor in script and then subclass that in DECORATE.
- The VM is register-based, so there are fewer hard-to-predict indirect branches needed for executing script code. For the purposes of serialization, the registers are tagged with types, although the instructions that act on the registers don't need to actually check those types, so long as the compiler produces correct code. I had started work on the VM before the Lunarpages business came up, so some work has been done.

- A debugger interface can be added later once everything else is working.
C++ is more of the exception than the rule as far as NOT having a single common superclass.randy wrote:Object is a basic type for the language, as it is for Java and C#. New classes implicitly have it as an ancestor, and you are not limited to only subclassing actors.
I like it. It sounds like my ECMAScript suggestion (the root standard in JavaScript, Flash). This suggests an implementation similar to JavaScript, where a class is really just a hash table.randy wrote:[*]Objects can also have arbitrary data associated with them by accessing them like an array:This provides an alternative path for extending objects without subclassing, in cases where subclassing is impractical. This is mostly for the benefit of using the language as a replacement for ACS. Right now, extra data about player state that modders want to maintain is commonly kept in arrays. Wouldn't it be better if that data could be kept directly with the player? It's cleaner and, more importantly, avoids the problem of assuming a fixed maximum number of players.Code: Select all
someobj['mydata'] = foo;
You'll want to stick with a balanced binary tree until there get to be quite a few class members. You can find the exact point where it makes sense to take on the additional overhead of hashtables by a little profiling, while also keeping in mind space and cache locality.
How do you intend to handle when someone tries to get the value of someobj['mydata'] when it is uninitialized? You can avoid a lot of messiness of ECMAScript by simply returning null and keeping 'undefined' out of the picture completely.
I think it would be best to try to stick with the model of ECMAScript, where you can access either using indexing or as member objects.randy wrote:Perhaps there can also be syntactic sugar for this so that the above example can also be written as:I'll have to see if that causes any conflicts with the grammar for labels first.Code: Select all
someobj:mydata = foo;
I agree. Layering on top of DECORATE is not the way to produce a clean language, not even if you did simply choose to accept that bad syntax that worked in the past will not anymore.randy wrote:[*]I'm not sure it's worth the trouble of trying to retrofit this into the existing DECORATE framework. I'd much rather start off with a new file format with a clean slate, with DECORATE support maintained as-is and give modders the option to use whichever format they prefer: DECORATE for everything possible now and script for everything else. New actors defined in script could even expose methods to be used for DECORATE parsing, so you could define an actor in script and then subclass that in DECORATE.
- bagheadspidey
- Posts: 1490
- Joined: Sat Oct 20, 2007 10:31 pm
- Contact:
You may be interested in the way the Vavoom source port handles this; DECORATE is preserved alongside a fully-functional scripting language. Have a look:randy wrote:I'm not sure it's worth the trouble of trying to retrofit this into the existing DECORATE framework. I'd much rather start off with a new file format with a clean slate, with DECORATE support maintained as-is and give modders the option to use whichever format they prefer: DECORATE for everything possible now and script for everything else. New actors defined in script could even expose methods to be used for DECORATE parsing, so you could define an actor in script and then subclass that in DECORATE.
Spoiler:edit: in case you are wondering, Actor::A_Fall calls NoBlockingSet.
- bagheadspidey
- Posts: 1490
- Joined: Sat Oct 20, 2007 10:31 pm
- Contact:
- Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Yes, that's how I implemented it. So far I haven't done any non-actor stuff though but it should work once I progress further.randy wrote: So here are the thoughts I had about what I want to see in the language before I got the notice from Lunarpages that I need to streamline my site or risk being kicked off. (Fortunately, they seem pretty lenient as long as I'm on this non-production server, but I do want to hurry up and get off, so I've not given the language much thought since then.):
[*]Object is a basic type for the language, as it is for Java and C#. New classes implicitly have it as an ancestor, and you are not limited to only subclassing actors.
I haven't implemented that yet but it's needed for the non-actor stuff later so it's somewhere down on my to-do list.[*]The language supports dynamic allocation of objects.
A question: How do you want to handle this? Like Java where all pointer assignments are tracked and an object is freed once all are gone or more like ZDoom where you tell an object to destroy itself and then the garbage collector takes over and gets rid of the object and all references to it? I've worked enough with Java that I really don't like its method. Especially in a situation with thousands of objects it's nearly impossible to keep track of everything and leaks are inevitable. ZDoom's method with a more performance-efficient cleanup code would also mean that less changes are needed to the code.[*]An incremental garbage collector is used to reclaim dead objects. Not only does this free users from the burden of having to worry about freeing objects, but it also simplifies various implementation details. The pointer cleanup ZDoom already does is essentially a special-case mark-and-sweep single-pass garbage collector that can run as many as 35 times per second depending on the level activity. It's already known that this can cause slowdown in extreme maps. An incremental garbage collector should theoretically be able to perform better, since it can spread the collection out across multiple tics instead of doing it all at once. At worst, the performance should be about the same as what's in place now.
Another issue is that right now I am very careful not to have a non-compilable version for more than a few hours so that I can test everything as quickly as possible and I have to stick closely to the way things are done in the C++ code. That also has the advantage for me that I can basically leave the code as it is and only make the necessary syntax adjustments.
That sounds like a cool idea but I haven't spent much thought about it yet because it's an extension to the existing functionality, not a replacement. But I see no reason why this can't be added.[*]Objects can also have arbitrary data associated with them by accessing them like an array:This provides an alternative path for extending objects without subclassing, in cases where subclassing is impractical. This is mostly for the benefit of using the language as a replacement for ACS. Right now, extra data about player state that modders want to maintain is commonly kept in arrays. Wouldn't it be better if that data could be kept directly with the player? It's cleaner and, more importantly, avoids the problem of assuming a fixed maximum number of players.Code: Select all
someobj['mydata'] = foo;
Grammar...Perhaps there can also be syntactic sugar for this so that the above example can also be written as:I'll have to see if that causes any conflicts with the grammar for labels first.Code: Select all
someobj:mydata = foo;
That's what I am doing, too. Although I made some restrictions regarding variable types so that the thing can still work within the existing DECORATE without causing conflicts. That means mostly that class and struct types have to be defined as 'class<name>' and 'struct<name>' to keep their namespace separate from DECORATE keywords. I have been thinking about relaxing this within function definitions but I havent done so yet.[*]The parser is designed to be two-pass, so it collects type information in the first pass and compiles functions in the second pass. Then you don't have to worry about the order you define classes in.
Mine is working within DECORATE and the problems so far are only minor. I have found only one WAD where I couldn't handle it at all due to its bad definitions which used integers where strings were needed. The old parser let these through without saying a word. Everything else prints out some warnings about unquoted strings or undefined actor classes at most and both cases can be handled without going into too much trouble.[*]I'm not sure it's worth the trouble of trying to retrofit this into the existing DECORATE framework. I'd much rather start off with a new file format with a clean slate, with DECORATE support maintained as-is and give modders the option to use whichever format they prefer: DECORATE for everything possible now and script for everything else. New actors defined in script could even expose methods to be used for DECORATE parsing, so you could define an actor in script and then subclass that in DECORATE.
Dehacked is working fine as well.
I have used a simple stack machine but so far I haven't done anything with code that has real performance impact so I can't say much about actual speed yet.[*]The VM is register-based, so there are fewer hard-to-predict indirect branches needed for executing script code. For the purposes of serialization, the registers are tagged with types, although the instructions that act on the registers don't need to actually check those types, so long as the compiler produces correct code. I had started work on the VM before the Lunarpages business came up, so some work has been done.![]()
Yes - but I fear that this will be more work than everything else combined...[*]A debugger interface can be added later once everything else is working.
That all said, I know fully well that much of my code is quite messy and will defintely need a complete cleanup including heavy rewrites once all the needed features are working.
A few things of interest:
- How strongly would you integrate the compiler into the engine. I resolve any class and sound names at compile time if possible because these operations are needed quite frequently and not having to look up this data should certainly save some time.
- Do you consider an external compiler an option? Because I think that would make things a lot more complicated because far less things can be done during compiling. My compile time tests show that it isn't really necessary. Ok, I have an extremely fast computer (Core Quad 2.4 GHz) but for me the compile time of all the data from the g_doom, g_heretic, g_hexen, g_raven and g_strife directories plus 10% of g_shared is only 0.1 seconds when launched after a reboot of the computer and the HD cache is empty. This should mean even on slower computers that it can be done under a second.
I noticed. He changed it for the latest version and his states syntax is a carbon copy of DECORATE. When converting all the Hexen stuff I could copy&paste most of his states definitions into my DECORATE files and it worked out of the box in most cases.bagheadspidey wrote: You may be interested in the way the Vavoom source port handles this; DECORATE is preserved alongside a fully-functional scripting language. Have a look:
Last edited by Graf Zahl on Fri Nov 02, 2007 2:49 am, edited 2 times in total.
- Graf Zahl
- Lead GZDoom+Raze Developer

- Posts: 49252
- Joined: Sat Jul 19, 2003 10:19 am
- Location: Germany
Jim wrote: How do you intend to handle when someone tries to get the value of someobj['mydata'] when it is uninitialized? You can avoid a lot of messiness of ECMAScript by simply returning null and keeping 'undefined' out of the picture completely.
I think 'undefined' needs to be properly defined.
Sometimes you can't just assume a certain value as the default. The existing DECORATE treats 0 as such and the issues were so much that when I started writing my compiler my first decision was to allow default parameter values like in C++ to avoid the problem.
I don't see any difference between function parameters and custom properties. If one isn't defined the code should be able to know (in the first case by not allowing to compile and in the second by reporting it properly.)
I was thinking of Lua, actually. It would be a hybrid of C-like structures and Lua-like tables, so it can integrate better with the existing code.Jim wrote:I like it. It sounds like my ECMAScript suggestion (the root standard in JavaScript, Flash). This suggests an implementation similar to JavaScript, where a class is really just a hash table.
Have you had a look at Lua's table algorithm? It tries to keep a hash table in a compact area of memory while also minimizing chain lengths. Seems to work pretty well to me, given Lua's ability to outperform pretty much every similar language.Jim wrote:You'll want to stick with a balanced binary tree until there get to be quite a few class members. You can find the exact point where it makes sense to take on the additional overhead of hashtables by a little profiling, while also keeping in mind space and cache locality.
Again, like Lua: Just return nil. Setting it to nil would also remove it from the table.Jim wrote:How do you intend to handle when someone tries to get the value of someobj['mydata'] when it is uninitialized?
Ultimately, the incremental garbage collector is responsible for reclaiming all memory. However, objects can be told to destroy themselves while references still remain. Doing so sets a flag on the object indicating it wants to be garbage. Code that uses object references needs to check that the object doesn't want to go garbage across function calls. If it does, then any references the function has need to be NULLed. (A template class ought to make all this transparent for C++, and script code would never need to know, since the VM would take care of it.) When the collector runs, either all references to the object have been NULLed, so it never encounters the object, or it sees the flag and NULLs the reference that brought it to the object without marking it as in-use. Either way, the object will be eliminated at the end of the next full collection cycle.Graf Zahl wrote:A question: How do you want to handle this [garbage collection]?
Another factor for this decision that I forgot to mention is that much of the compiler literature seems to be written with the assumption that a three-address machine is used for intermediate code, so it's easier to take algorithms from those books and apply them if that's what the VM is using.I wrote:The VM is register-based
I don't see any point in keeping them separate anymore.Graf Zahl wrote:How strongly would you integrate the compiler into the engine. ... Do you consider an external compiler an option?
There's a big difference between a state definition and DECORATE.bagheadspidey wrote:Right - "Vavoom actor states" are not exactly DECORATE but it's so damn close it might as well be.
- bagheadspidey
- Posts: 1490
- Joined: Sat Oct 20, 2007 10:31 pm
- Contact:
I admit there are probably many differences I am unaware of, but the code sure looks and feels similar.randy wrote:There's a big difference between a state definition and DECORATE.bagheadspidey wrote:Right - "Vavoom actor states" are not exactly DECORATE but it's so damn close it might as well be.
As for the js vs lua thing, my 0.02 USD (fwiw, etc): I think you should implement the underlying engine however you like, but I think that js has a friendlier syntax than lua. For example, the use of the : symbol to make static calls, the implied object-as-first-argument when making dynamic calls, functions returning multiple values, etc could be confusing to less experienced programmers. Also some operators are "weird" compared to other languages (~=). I have mixed feelings about "end" vs "}" type syntax: I personally favor the curly braces, but "end" might be friendlier for beginners
I'm not sure if it your intent to make the syntax lua-like or not, but imho js has a much friendlier syntax to learn.
- bagheadspidey
- Posts: 1490
- Joined: Sat Oct 20, 2007 10:31 pm
- Contact:
- TheDarkArchon
- Posts: 7656
- Joined: Sat Aug 07, 2004 5:14 am
- Location: Some cold place
