But eh, I've been recently rambling on IRC and whatnot about the scripting languages ZDoom has to offer and how they feel limited in a sort of way. I know this ZScript is coming up so I thought I'd give my input on the languages.
Anyway, I see the main things the scripting language should do are actor manipulation and environment manipulation. The former is done by the use of ACS and DECORATE, while the latter is mostly done with ACS. Thinking about the roots of these languages: ACS derives from Hexen. It was designed mainly for the environment manipulation part. Together with hubs it gave an RPGish feel on the game. DECORATE derives from a simple language that was meant to create simple decorations, now is a flowchart-like language for dynamic and powerful actor defining.
That's cool and all. But DECORATE's flow-chart design makes it clear it was mainly meant for animations and triggering events at certain positions and not a real scripting language while ACS is the inverse. This is why it feels sort of weird to see people do complex scripting on DECORATE. During my modding era here and on zandronum I've noticed that perhaps the most powerful way of making actors is to export the complex stuff to global ACS and using ACS_Execute on the key parts of the actor.
But ACS seems to be geared towards the environment part. There is no direct access to actors in the language, you haev to use a set of given functions to do things on the actor you want. Hexen tagged things with TIDs and used ACS on them to manipulate them. Teleporting them, spawning them on spots, and so on. For the complex things - like the boss monsters - it used native code and codepointers. It's not real actor control, though it does scratch the surface of it.
So what would be ideal? I'll go back to my previous paragraph: Hexen used native code for the complex actors. So what's in there? Pretty much the power to do anything on the actor. You have pointers to actors, custom fields, methods that execute every tic on the actor and when the actor starts, ability to iterate through actors and so on. Basically: you have access to pretty much any actor and pretty much any property on the said actor. ACS instead relies on actor tagging and falls short here. Because actors are tagged explicitly instead of implicitly, actors that aren't specially tagged just are not in the scope of any scripting whatsoever unless it is the calling actor.
Fine, so let's just tag everything? You'd think so at first, but risk of conflicts exist.. and you'd have to edit pretty much every single actor you're working with, add a hacky unique TID system.. instead of what could be easy access to any actor and their properties and flags.
So my ideology in a nutshell: global ACS should operate on a lower level, DECORATE should exist for the animations and that alone. Instead of TIDs, use unique actor IDs. One ID per actor, one actor per ID - and now you can emulate actor pointers in ACS. Through actor pointers, you could access their properties and flags.
Here's ACS:
Code: Select all
int t = UniqueTID (1000);
Spawn ("DoomImp", 1, 2, 3, t);
SetActorProperty (t, APROP_Health, GetActorProperty (t, APROP_Health) * 2);
Code: Select all
int t = 1000;
while (IsTIDUsed (t++)) {
if (!CheckActorClass (t, "DoomImp"))
continue;
SetActorProperty (t, APROP_RenderStyle, STYLE_Fuzzy);
t++;
}
Now imagine, if there was proper actor IDs:
Code: Select all
int mo = NextActor (0);
while (mo = NextActor (mo))
if (IsKindOf (mo, "DoomImp"))
SetProperty (mo, "renderstyle", "fuzzy");
More possibilities:
Killing every monster that targets the activator:
Spoiler:An imp with that pushes all actors (sorta) away if they get too close. Aside from the formalities, this is practically custom codepointers:
Spoiler:A_KoraxChase replicated in ACS:
Spoiler:This could all be done pretty painlessly if the scripting language had things like this. Even in the above code, TIDs remain only being used as actors tagged on the map.
Some more thoughts.. custom DoSpecialDamage() functions? Maybe a decorate property: SpecialDamageScript, takes an int parameter, calls NamedExecuteWithResult on it with one argument (the damage) and takes its result value for the mutated damage. Maybe the compiler (or an alternative one) could even integrate this GetProperty() and shorten it a little bit, like: imp->health *= 2.
Worried about abuse? Add limits and failsafes where necessary. Disallow parts that would cause bad things (for instance never allow deletion of used player bodies, don't add radius and height into SetProperty, (perhaps TryResize()?), etc)
TL;DR: If I were designing the scripting language I'd move away from TIDs for actor manipulation and use unique actor IDs and emulate pointers with them. Make DECORATE basic actor definitions and animations, complex stuff would be best off exported to ACS instead of attempted to be emulated - that only results in action functions with a ridiculous parameter count.
Also, I'd be grateful if my username could be changed to "Dusk" as that's what I use on pretty much every other Doom forum by now, thanks!

