View previous topic :: View next topic |
Author |
Message |
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Tue Feb 01, 2005 1:11 Post subject: Run nwnScript from outside game - Proof of Concept |
|
|
Goodevening to all.
This day was another one good for me and as you probably noticed good for you too In my lone battle against dark forces of nwserver i've managed to find spell scroll which contain Spell of ExecScript. Here goes description:
What is?
RunNWNScript will be nwnx extension which allows you to run ingame script from outside. Any external application or dll (also nwnx plugins) can use it.
What for
Well... again your imagination is only limit. What i would use it for? First of all speech listening engine (talus or nwnx_speech) make call to database every second to check if there's new data for it. If no one speak for half hour it checks 60*30 times. Simple use of RunNWNScript would change that allowing only one check when someone speaks. Please post what you would use if for
How does it work
PostMessage to window named "nwnx_comm". MessageID is WM_USER+1010 and Params are scriptname and object_id (which script runs on). Window handle can be retrieved using FindWindow("nwnx_comm", NULL). When message is recieved nwnx calls ExecuteScript from memory and runs script
Implementation
Some technical part.
ExecuteScript is located on 0x05AF2C0. It takes three parameters on stack and one passed using ecx. Parameters are ExecuteScript(char ** ScriptName, int ObjectId, int Something = 1). Something is always 1 when running script, maybe that function is used for something else when something!=1 - i don't know. In EAX there's pointer to static variable which probably contains ScriptResult (or something like that). Can't tell you address right now cause i'm not at my computer.
Messagess - there's window class created by nwnx-module.dll and it's msg loop is execute on another thread. When it recived a WM_USER+1010 msg it calls ExecuteScript function. Message communication between plugins is something for own topic (which i'll post tonight or on morning)
What more
Because ExecuteScript is ran before nwnx_scripter hook it works with !scriptname trick. If you run !myscript it will be loaded from outside module (of course assuming you use nwnx_scripter)
Proof of Concept
Archive contains three files.
nwnx-module.dll - is to be placed in main directory (overwrite old one)
nwnx2.exe - like above
RunScriptPOC.mod file is to be placed in modules directory.
In module there's nothing but one script (named bigbadaboom). Cause it's only POC don't try to message script name to nwnx cause it'll only fire that script. After you run nwnx2.exe you'll see new button near About button. Log in to the game and press RunScript button. You should see visualeffect in game.
This PoC was tested only in my computer (xp+sp2) so i won't give my head for stability of this.
Have a good night.
Isilweo
ps. of course i forgot to put link here it is:
http://vdi.pl/isil/RunScriptPOC.rar |
|
Back to top |
|
|
Blacksting
Joined: 03 Jan 2005 Posts: 107
|
Posted: Tue Feb 01, 2005 1:54 Post subject: |
|
|
Excellent job. The ability to run a script from an external trigger and have that script not even be in the mod is something that was a pipe dream until your hard work. |
|
Back to top |
|
|
Papillon x-man
Joined: 28 Dec 2004 Posts: 1060 Location: Germany
|
Posted: Tue Feb 01, 2005 18:33 Post subject: |
|
|
Nice ! Do you plan to put this into a plugin sometime ? _________________ Papillon |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Wed Feb 02, 2005 0:05 Post subject: |
|
|
Few notes.
Amazing (well at least i was amazed) thing is that you can run script even whithout module loaded (of coruse as there are no resources loaded you must load it using scripter (resource manager as Pap call it now)).
The quite interesting use of RunNWNScript is to use script callbacks with it.
Ie. you run external process which do something with database, after it finishes you want it to call script ReloadQuestResources. I imagine you'll call it like this SetLocalString(GetModule(), "NWNX!MYDLL!DODBTHINGS", "ReloadQuestResources"). External process after it has done it's work runs ReloadQuestREsources script.
Papillon: sure i'll put it into plugin but i think nwnx base has to have few things added first. I'm working on them now, i wanted to talk to you about them but it seems you're rarely on icq. Maybe tomorow morning i'll make a post about them |
|
Back to top |
|
|
Blacksting
Joined: 03 Jan 2005 Posts: 107
|
Posted: Wed Feb 02, 2005 1:33 Post subject: |
|
|
Yes the obvious first use of the Call Back feature you describe is with the Talus Listening system. There will not be a need for a looping status check within NWN. I can not wait for this . |
|
Back to top |
|
|
Senalaya
Joined: 29 Dec 2004 Posts: 82 Location: Germany
|
Posted: Wed Feb 02, 2005 13:42 Post subject: |
|
|
Would it work, to also call 'spontaniously' SetLocalString() from an outside software?
It would allow to set parameters for the script, that is called externally.
i.e.:
SetNWNLocalString(iObjID, "New_Location", "AREATAG:TAVERN■POSITION_X12.00■POSITION_Y4.00 POSITION_Z0.00■FACING0.0")
RunNWNScript(iObjID, "walk_to_loc")
with "walk_to_loc" decoding the location string and running an ActionMoveToLocation().
The other way around would of course work, too. i.e. having "walk_to_loc" querying for the new location in the DB. But I somehow would prefer to set the variable directly, rather than having to run a SQL request from in-game. |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Wed Feb 02, 2005 23:34 Post subject: |
|
|
i'm working on that subject also. it's about posibility to pass data to nwn. but you can't do it with runscript cause it only runs script. all you can pass to it is object id which it is run on |
|
Back to top |
|
|
virusman
Joined: 30 Jan 2005 Posts: 1020 Location: Russia
|
Posted: Mon Feb 07, 2005 20:52 Post subject: |
|
|
Any chances to get a source? |
|
Back to top |
|
|
isilweo
Joined: 29 Dec 2004 Posts: 22 Location: poland
|
Posted: Mon Feb 07, 2005 22:47 Post subject: |
|
|
sure but not right now cause POC version was only slightly modified nwnx-module. now i'm making few changes to nwnx (inter plugin communication, firing up plugins from external soft, firing scripts in threads) and after that i'll make nwnx plugin with that. so stay tuned ;) |
|
Back to top |
|
|
Blacksting
Joined: 03 Jan 2005 Posts: 107
|
Posted: Fri May 06, 2005 22:41 Post subject: |
|
|
How is the development coming? |
|
Back to top |
|
|
Dazzle
Joined: 29 Dec 2004 Posts: 19
|
Posted: Mon Dec 26, 2005 17:13 Post subject: |
|
|
Whatever happend to this idea? Seems to me isilweo dropped off the planet, sadly. |
|
Back to top |
|
|
Themicles
Joined: 23 Jan 2005 Posts: 30 Location: Wolverine Lake, MI
|
Posted: Tue Dec 27, 2005 0:07 Post subject: |
|
|
Resource Manager plugin mentioned on the front page, and as described in a thread around here somewhere, does this. It allows you to not only run .nss files from an external folder, but also load some object types as well.
I've been using this for several months on my persistent world, Tairis'nadur. No more restarting the server to update scripts... and not having to open the toolset has been a big plus. I just use TextPad with the NWScript syntax plugin, and clcompile.exe to compile. _________________ World Leader of Tairis'nądur http://www.tairisnadur.com
Member World of CoPaP http://www.copap.org |
|
Back to top |
|
|
Dazzle
Joined: 29 Dec 2004 Posts: 19
|
Posted: Tue Dec 27, 2005 0:41 Post subject: |
|
|
Nono, it's not the same as the resource manager, this proof of concept lets you call ExecuteScript from outside the game. |
|
Back to top |
|
|
PlasmaJohn
Joined: 04 Mar 2005 Posts: 70 Location: The Garage
|
Posted: Thu Jan 05, 2006 14:53 Post subject: |
|
|
Does this still work with 1.66 or even 1.65? BTW, this should be usable via the following code:
Code: | int (*pExecuteScript)(char**,int,int) = 0x05af2c0;
int MyFunc( /* other args */, int obj ) {
...
(*pExecuteScript)("ext_event",obj,1);
...
} |
Basically, I'd write an NWNX plugin that had an NWNX command to set the object id from the OnLoad script. The above MyFunc should be in a seperate thread than the script VM. So once the object id is registerred, your external event (in my case a specific packet received by a UDP listener) will cause the ext_event script to be run. |
|
Back to top |
|
|
PlasmaJohn
Joined: 04 Mar 2005 Posts: 70 Location: The Garage
|
Posted: Sat Jan 07, 2006 0:00 Post subject: |
|
|
yes, yes it does on 1.65.
Need to figure out the function signature though, it's not at that address under 1.66. Will try to create the plugin I talked about. (NWNXspy which is the rough inverse of NWNXmnx). |
|
Back to top |
|
|
|