Scenario: In a large module (hundreds of areas, many thousands of objects), I want to run a pseudo heartbeat in several of the areas, when PCs are in them. That’s easy enough to set up. But, in each of those areas there are between 15 - 30 special waypoints with the same tag and I want to pick one of them randomly in the HB for some activity.
One option is to set things up so that all of those waypoints in the several areas have the same tag and then use GetNearestObjectByTag() along with some object in the area to make sure I am getting a WP in the current area.
Another option is to set up each area so that its waypoints have the same tag, but that tag is different for each area and then use GetObjectByTag(), which searches over the whole module.
Which is more efficient, in terms of CPU use (e.g. potential lag)? The lexicon page for GetObjectByTag() suggests that it is more efficient because the game maintains a hash of objects by tag and it can do a quick search of them. But, the first approach has the advantage of searching through the smaller number of objects that are in one area, rather than through all the tags in the module.
Well, because of a critical bug in Enhanced Edition (that exists from release and that still wasn’t fixed), where GetNearest* functions randomly misfire and returns OBJECT_INVALID despite the seeking object exists, I think the answer to this is pretty obvious, isn’t it?
I was not aware of that bug. Thanks for the heads up. Is there a pointer to a more complete description of the issue, so that I can know more specifically what to look out for? There are hundreds of calls to GetNearest* in the module code.
Do you have a link to the report to Beamdog so that I can keep an eye on it and possibly upvote it or make sure Beamdog knows this is a big deal?
https://github.com/Beamdog/nwn-issues/issues/52 - this is last bug report for this issue, the previous reports by me were deleted when Beamdog decide to reset the bug tracker and start from scratch. There are also several (at least three, possibly more) forum posts in Beamdog forum related to this issue (spells not finding targets etc.). There was a forum post here related to this bug too (missile storm spells not finding targets), but I can’t find it.
BTW If that bug was not the case, I would went for GetNearest. CPU use is meaningless, in terms of the actual speed, GetObjectByTag will be faster indeed, however that has basically no meaning. The only slow scripts are those using database. Other than that, you cannot really make a script that would seriously lagged server even if you wanted to because TMI exists (*not saying it isn’t possible, pseudo-heartbeats and delaycommands are able to do this, if used badly). TMI - instruction limit will stop your script prematurely in order to avoid endless loop scripts halting the server. And this instruction limit counts each variable declaration, assignment, function usage, parameter usage and more. Which means, that with GetObjectByTag you have bigger chance to hit this limit, especially if there are numerous such waypoints in each area and there are hundreds of areas, which can break your script.
Wow! Thanks for that link. We have also had issues with spells like I[GL]MS and Firebrand not finding targets. It seemed to be connected somehow to the presence of AoEs in the area (e.g. if the target was a dragon or an Ogre High Mage with an aura active). I wish I knew if that connection is legit and how it’s related.
Has this been added to the Atlassian-hosted NWN bug reports? I see you wrote a module to reproduce the bug and an alternate GetNearestObjectByTag() script. Awesome work.
Also, thanks for the advice on the efficiency aspect of this. If there weren’t an outstanding issue with GetNearestObjectByTag(), then that would be the way I would go. In this particular case, it would allow slightly more modular scripting and less care required in the area setup. It is still tempting to go that way, since this heartbeat is not a game- or quest-breaking deal.
I have reported (or re-reported) this to Beamdog using its Atlassian bug reporting feature. The link to the report is https://beamdog.atlassian.net/servicedesk/customer/portal/1/NWNS-7345, though I don’t know whether one has to be logged in as me to see it.
FWIW, this is what I filed.
No, spells weren’t reported by me again because in my understandment it is the same bug, it just affects more functions than GetNearestObject. GetFirst/NextObjectInShape are affected too and reason why spells are missing targets sometimes. The spells related issue is fixed in Community Patch, or rather workarounded.
I saw right after I posted the bug report that I was too specific. I have appended a comment to the report that the issue is not limited to that one function and seems to affect several functions that are supposed to return objects in areas.
BTW, I mentioned the spells in the bug report to make it clear that this isn’t just something that only affects custom modules and custom scripting. I think these bugs get more attention when it’s clear that this is a bug that someone will see when playing something that Beamdog is supposed to be supporting out of the box, like the OC, HotU, etc.