squattingmonk / nwn-core-framework Goto Github PK
View Code? Open in Web Editor NEWAn extendable event management system for Neverwinter Nights
An extendable event management system for Neverwinter Nights
Not necessarily actual issues, just wanted document breaking changes in the framework when plugged into a module that currently uses it as a base. This is not a request to make any changes to the new version, just documentation.
RegisterEventScripts()
no longer exists and is replaced with RegisterEventScript()
. It's likely that multiple scripts were never assigned at the same time, anyway, so no big deal, but all plugins created until the old version will have to be updated with the new function name.
core_i_database
no longer exists and is not replaced. This breaks the administration system that used the database for player registration. Custom functions will have to be used to structure and populate the player database. Probably needed to be done anyway.
Several changes to the way plugins are handled, which is mostly internal to the framework, except SetPluginLibraries()
no longer exists and has been replaced by setting a local string on the plugin object during plugin creation (or call LoadLibraries()
during plugin creation. Also, GetPlugin()
no longer utilizes the creation shortcut if the plugin isn't found. Code must be modified to explicity create the plugin object using CreatePlugin()
.
GetCurrentEvent()
now returns a string instead of an object. Generally a simple fix since most GetCurrentEvent()
calls were used just to get the event name.
DelayLibraryScript()
has been removed and not replaced. The removes the ability to delay running library scripts. This was only used in a single test script, so easy fix.
GetEventTriggeredBy()
can no longer accept an object parameter.
[Get|Set|Clear]EventState()
can no longer accept an object parameter.
GetWasPC()
has been removed, but likely unused anyway, expect in hook_nwn
Line 308 needs to look for NCS instead of NSS, sumbit PR.
When testing some trigger-related code, I found that auto-hooking triggers can cause a behavior change for non-transition triggers. Once a script is added to the OnClick slot, the trigger automatically acts as a transition trigger, including highlighting on mouse-over and showing the enter
icon. Might need to add an exception for this event (might be other events that area affected by this behavior, but I haven't checked yet), to prevent a behavior change. To the best of my knowledge, this behavior change is hard-coded in the game, so it might have to be a work-around.
When registering a script, the debug statement displays the object's hex id, which may not be all that useful for identifying where it's actually coming from. Since we're generally not modifying plugin objects directly, it might be a better user experience to display the name of the plugin instead of the object id, or maybe the name and the object id in parenthesis, or some similar method. Or possibly even remove the "source" line since the debug system provides the plugin name at the beginning of the statement.
There's currently a switch in core_c_config.nss
that lets the user set an alternate debug level for heartbeat scripts. This helps cut down on extra noise. But there are other events that cause a lot of noise (e.g., OnCreaturePerception). It would be nice to allow builders to set module-level event debug levels and to allow those settings to be overridden on a per-object basis.
Toward the aim of reducing maintenance requirements, especially with the goal in mind of making plugins fully plug-and-play, explore the possibility of having libraries that define plugins automatically activate the plugin after libraries are finished loading, unless the user specifically sets the plugin to not activate.
A potential implementation would be to store the plugin name into a module-level list (much like INSTALLED_PLUGINS
in core_c_config
, but built dynamically as libraries are loaded, possibly through the CreatePlugin
function), and then running ActivatePlugin
against that list once libraries are loaded. This would require a function that would allow users to set this plugin as inactive during plugin definition to prevent automatic activation. Additionally, it would require a method for activating unscripted plugins defined by other means, such as bw_defaultsevents.uti
. It may be possible to find and activate unscripted plugins using glob syntax much like loading libraries by pattern.
In util_i_csvlists.nss, FindListItem is not carrying over the parsed item count when the item being searched for is also a substring of a previous item (i.e. the previous item count is not being carried through the recursion).
As you can see in this screenshot from a Debug() call, the system should find "emote" at index 7 in the passed list, but it finds it at index 2. This is because of the matching substring in "pc_emote" at index 4. During the recursion call, nOffset resets to zero and the item "server" is counted as index 0 with "emote" ending up at index 2.
Moving the "emote" item to a position before the "pc_emote" item fixes the problem, but it's not the best solution. Carrying the previous item count (number of items parsed before recursion) fixes the issue as you can see in the following screenshot.
Following are the code changes that fix the issue, however I don't know if any other functions in util_i_csvlists or util_i_lists work the same way. If so, they may need attention.
Prototype:
int FindListItem(string sList, string sListItem, int nParsed = 0);
Body:
int FindListItem(string sList, string sListItem, int nParsed = 0)
{
// Sanity check.
if (sList == "" || sListItem == "") return -1;
// Is the item even in the list?
int nOffset = FindSubString(sList, sListItem);
if (nOffset == -1) return -1;
// Quickest way to find it: count the commas that occur before the item.
int i = GetSubStringCount(GetStringLeft(sList, nOffset), ",");
// Make sure it's not a partial match.
if (GetListItem(sList, i) == sListItem)
return i + nParsed;
// Okay, so let's slim down the list and re-execute.
string sParsed = StringParse(sList, GetListItem(sList, ++i));
return FindListItem(StringRemoveParsed(sList, sParsed), sListItem, i + nParsed);
}
Haven't delved into this too far yet, so I'm putting this here as a marker for future investigation, but I noticed this today while doing some testing. I added a henchman by script to the area with CreateObject
. The correct events fired and the object was added as a script source as defined in OnAreaEnter:
However, when I removed the creature programmatically (DestroyObject), the OnAreaExit event triggered for the removed creature, but it doesn't appear that the creature object was available to the exit event script.
I have a feeling that it's because the object was destroyed and not just departed the area. Again, no action required, this is just a bookmark.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.