Im at work right now so cant check them out, but will respond nonetheless.
Please forgive my audacity
The nwn2 script functions are extremely robust in their current iteration, and allow literally any game to be made with a small amount of simple functions.
For example, NWN2's default combat system is turn based/round based and relies on an auto attack and ability cast system.
Using the NWscript I was able to completely override this into a twitch based real time rock/paper/scissors influenced combat system with a very small amount of code.
I would like to help out with the scripting you chose in esenthel.
Many of the people who have used the nwnscript syntax/functions have praised its simplicity and its great power.
While I am extremely happy with the nwscript functions/system its not perfect for everyone, and I understand you have your own ideas how you want your engine to work
In my opinion, the most important thing in scripting has to do with getting targets properly and re-using them, in addition to setting variables on objects.
Allow me to lay out some function requests (names and syntaxes are up to you) that I personally couldnt live without.
This would return the object that the script was fired by. Pretty simple.
Would return the type of object - player, npc, item, etc. Useful for determining if a object is valid or not, based on the scripters own rules.
This would get the target currently selected by targetter. Generally targetter would be the object that fire the script, but can also be used to determine NPC's current target for example.
Could be a clicked target or something under a reticule, or whatever.
4: AffectObject(effecttype, object, effecter, "NameOfEffect"); / AffectLocation(effecttype, location, effector, "NameOfEffect")
This one is really a combination of a few functions, but allow me to explain.
effecttype could be an animation, a visual effect, damage, or even a script (and the script could optionally self-loop for "X over time" effects).
The name of the effect should be unique for referencing the effect (ending, overwriting, etc).
Each effect would have its own params (discussed below) so the command to animate a character would potentially look like "AffectObject(Animate("animationname", Duration, Speed, StartTime), animatedcharacter);"
Object would naturally be the target to 'effect'.
Affector would be the originator of the effect for purposes of spells, etc, and to determine the damager or the person to give xp to. Im not sure the best way to store this value on the object, but up to you. I think generally a single instance pointing to an object that is overriden each time would be most efficient.
The below are suggestions for types of effects for "AffectObject" and "AffectLocation"
4a: Animate("animation name", Duration, Speed, StartTime);
Animation name would be a simple string referring to the name of the animation.
Duration would be a float for the duration. A -1.0 here or similar could indicate it to be looping.
Speed would be a float for animation speed. 1.0 would be default.
StartTime (could also be StartFrame) would be an int referring the start point in the animation, if wanted. A 0 would be the 'start'.
If wanting to end an animation prematurely use a shorter duration than the animation.
4b: VisualEffect("Name of Visual Effect", Params, For, Visual, Effect);
I dont know how esenthel does visual effects, but the parameters for such would go here.
Pretty self explanatory. Float or Int? Also, negative values could be used to heal? If not, have a specified heal function.
DamageAmount would be able to be changed by the scripter on various things like resists, etc.
4c: Whatever anyone suggests.
No longer in reference to AffectObject from here on.
5: GetVar(object, "varname");
Yup. Get a variable. Could be string/int/whatever. If the case/if statements used to make this function are too intensive, split into int/string/float forms.
6: SetVar(object, "varname");
Sets a var to an object. This var would be written to database with lazy cpu cycles or whatnot, and the cached var on the object would be referred to for speed. This is probably already used, and im probably just being pedantic.
This should be persistant.
Get the location of object as an mapname/X/Y/Z value. Additionally, a matching function to "set" the location (e.g., teleport, jump, etc)
8: SaveLocation(Object, ObjectToSaveTo, "NameOfLocation");
Saves a location for later usage/retrieval. Say, you want a mob to respawn after being killed. When it dies, run a script to find its original location (saved on spawn) and create a new one there, or near it.
9: GetSavedLocation(Object, "NameOfLocation");
This is the get function for SaveLocation. I suppose these two functions could be included in Set/GetVar, but not sure how esenthel handles these.
10: SaveObjectRef(ObjectToReference, ObjectToSaveTo, "NameOfReference");
This would be used to save a shortcut to an object on another object. Say you want to jump to the party leader, when you joined the party this function would have saved the party leader's shortcut to your character, and you could then use setlocation, getlocation, and GetSavedObjectRef to jump there.
11: GetSavedObjectRef(ObjectToGetFrom, "NameOfReference");
Retrieves the shortcut of an object from another object by string name.
12: Random(MinimumInclusiveNumber, MaxiumumInclusiveNumber);
Returns a random number between the minimum and max, including both. Thus, a random of Random(1,10) would return a number between 1 and 10, including 1 and 10 as possible returns.
13: IntToFloat, FloatToInt, StringToInt, StringToFloat, etc
These are probably already there, but just saying.
14: PlaySoundAtLocation("soundfile", Location, Duration, Radius)
Pretty self explanatory. A negative value for duration is looping.
15: AttachSoundToObject("soundfile", Object, Duration, Radius)
Same as above, but the sound follows the object.
16: RemoveEffectFromObject(object, "NameOfEffect"); / RemoveEffectFromLocation(Location, "NameOfEffect", RadiusFromLocation)
Removes an effect from an object/location, finished or not. For example an animation, or a looping sound.
I cant think of any other functions I have used in the last 10 years or so I have been scripting that arent inclusive of the above (off the top of my head) but if I do, I will post back.
If anyone has any requests or suggestions, please post here.
Also, if anyone wants to save Esenthel some work and actually write and include the code for the function or any of the ones I have listed, that is also welcomed.
From what I have read around these forums, this kind of customer support supplied by Esenthel is hilariously good - I am genuinely excited
Forgot about GUI manipulation. These are even looser suggestions, but I suppose something along the lines of:
MoveGuiObject("GUIObjectName", XPos, YPos);
Moves the GUI object to the X/Y position.
Enables/Disables the GUI object.
Changes the texture used for the GUI object.
Set the progress bar position of the GUI object (if they indeed exist).
DisableGuiObject("GUIObjectName", BOOLEAN, Duration);
Sets the GUI object to unclickable/unusable, and if the object has a 'disabled state' texture, apply it.
Sets a cooldown animation (brightness scaling up from bottom, or around in a circle?) on the gui object for the duration, also disabling it.
Get the string parsed to the object from the GUI function (below).
Get the GUI object that caused this script to run.
These would be the actions to fire when the gui is interected with.
RunScript(object, "scriptname", "StringToParseToScript");
This is for running a script and sending a var to the script. Object is what the script runs on.
Dont actually particularly need any more, as all the other functions can be run from the RunScript function, inside a script.
GENERAL STRING PARSING:
Return all the characters in a string left of the substring. For example, lets look at the string Esenthelrocks.
If we had GetSubstringLeft("rocks","Esenthelrocks"); it would return "Esenthel".
Return all the characters in a string right of the substring. For example, lets look at the string Esenthelrocks.
If we had GetSubstringRight("Esenthel","Esenthelrocks"); it would return "rocks".
GetSubstringBetween("substringFirst", "substringLast", "string");
Similar to the above two, but gets the string between substringFirst and substringLast.
If we had GetSubstringBetween("Esen", "rocks", "Esenthelrocks"); it would return "thel".
If we combine the above with IntToString and IntToFloat, then use it with the GUI command RunScript, we can parse quite a lot of GUI information back to the script, allowing complex UI's and complex character leveling/progression systems.