Tchos Posted August 25, 2016 Share Posted August 25, 2016 I've been tinkering around, and found some things that I haven't seen described here. During my work on my last module, I had occasion to write several utility scripts for my use in-game. One of them was to report the tags of the placeables around me for reference and later manipulation in areas that I couldn't easily open in the toolset. Something I noted, but did not confirm until my more recent experiments in making 0HP placeables functional again, was that static placeables were also reporting for duty. I had been told that static placeables aren't affected by script, and so for cases in which I wanted to make a static placeable usable in a module update, I had been planning on doing something I had earlier confirmed to work, which was to spawn a usable copy of that placeable on top of the original, scaled and/or offset to cover it up, so that it could be used. However, the scaling and imperfect covering of the static original will not be necessary, because DestroyObject() works just fine on static placeables. If the player is currently in the same area as the placeable when the DestroyObject command is fired, then the static placeable will only disappear after the area is reloaded, either by exiting and re-entering the area or by loading a saved game. Thus, when possible, static placeables should be destroyed when the player is in a different area. The usable copy can be spawned in its place at any time. Again, these experiments are mainly to increase the methods at hand to add to, change, or otherwise manipulate existing content in a module so that the changes take effect in a saved game in progress. As it stands, almost everything can be changed or expanded. Link to comment Share on other sites More sharing options...
Tchos Posted August 25, 2016 Author Share Posted August 25, 2016 I've never had much luck getting static placeables via tag in a script (probably because they don't have tags at all). Did you manage to pick them up indirectly, such as via a get nearest function, or within a spell shape loop? They do have tags. They reported their tags to me. I destroyed them using the tags they reported, using ga_destroy run from the console. Would it help to show a video? How does the script get hold of them as objects in the first place? Knowing a static placeable's tag wouldn't help in most instances, since the builder is unlikely to have changed the tags to be unique, and most static models tend to be used more than once in a module (houses, wall sections, etc). To report their tags? The script that reports the tags of the placeables around me uses GetNearestObject, with a loop to report the tags of the 3 nearest placeables to my current location. I first saw the static ones reporting their tags when I was trying to get the tag of a posted notice I had placed on a door, and found it reporting the tag of a nearby static pillar. In these recent cases I tested, I used a series of placeables, both static and non-static, usable and unusable, environmental and environmental-converted-to-placeable, to test various properties and actions, and gave them each unique tags. When I'm using these methods to affect actual module areas in scripts that are run within the module instead of conveniently-tagged test situations and scripts run from the console, when it is indeed as you describe, with placeables with default tags, I use GetNearestObjectByTag to get the ones closest to uniquely-tagged objects in known nearby locations, such as door waypoints. Knowing the tag is indeed useful in those cases to narrow down the selection, since I can say "get the 3rd nearest placeable whose tag is 'PLC_MC_STONEWALL' to waypoint x". As an added note unrelated to your query, I also checked to see if the "usable" property had any bearing on whether a placeable that is also marked as "static" could or could not be affected by script. It didn't matter. Interesting. It would seem that the GetObjectByTag() function deliberately filters out static placeables. It's good to know you can define them as objects in a script using alternate means. I assume their ghosts still haunt the walkmesh after they've been destroyed though. Do they no longer block line-of-sight, or is that also baked into the area somehow? I don't think I've tried the normal GetObjectByTag(). The scripts I've used have either used one of the GetNearest* scripts, or (in the case of the ga_destroy) GetTarget(), whose function uses a multitude of functions to try to return a valid object, which as I'm sure you know but which I include here for other readers, begins with special identifiers, and then moves to GetNearestObjectByTag() before it resorts to GetObjectByTag() if it still can't find anything. I'll try to confirm that GetObjectByTag() won't work for this. The cutting of the walkmesh certainly still stays in place unaltered, so I would use this in cases where I'd be replacing the static one with something else, and preferably not just removing it entirely, so characters wouldn't be taking a detour for no reason, unless the object is sufficiently small that such a detour wouldn't be distinguished from the sometimes bizarre pathfinding that the game uses normally (there's a spot in my module where characters always opt to veer sharply to the left through an alleyway and come back onto the path at an angle rather than run straight ahead, and NPCs always prefer to walk through the middle of the fountain area instead of around it, even when their destination is in the opposite direction). Line of sight bears testing. Link to comment Share on other sites More sharing options...
Tchos Posted August 25, 2016 Author Share Posted August 25, 2016 Why have the object as static anyway ? Just set it as plot put a description on it that says "nothing to see here" for any curious person with a z key habit ( like me ) and tick the dynamic collisions box, then when you destroy it you don't have to worry about the walkmesh. It's for things that were not anticipated to be needed later, which are being repurposed in modules that people are already playing. If I were preparing something ahead of time, I would simply do as I normally do and make it unusable until needed, which would make such a description unnecessary, as no one would be able to see it, and nor would it highlight. As a more concrete example, though I haven't yet tested this with static door objects -- imagine you have a static door on an unused building, on a campaign you've released. You want to make an update to the campaign, adding an interior to that building, so you add a script to the campaign to destroy the static door and replace it with an active door that leads to your new interior. Now, when someone applies that update to their campaign, no matter how far they've already played it, the new area is available to them. At least, that's my purpose. Others might find any number of uses for this ability. Sorry off topic but I believe have just got your post title ... very good, if I have read your intention correctly. "Life... is strength. That is not to be contested; it seems logical enough. You live; you affect your world." PJ Yes, I was tempted to answer Dann's "Interesting," with: "Yes, interesting -- this function has much untapped power," and reply to Tsongo: "You just don't understand what I'm doing, do you?" solely for the purpose of throwing in more Irenicus quotes, but I'd worry those words would be taken seriously! For others, Irenicus (not to be confused with the theologian Irenaeus, author of Adversus Haereses) is the antagonist of Baldur's Gate 2 -- one of the best villains in fiction that I know of, and very quotable. I think he was so effective because he was voiced by David Warner--it pays to have good voice acting talent.David Warner is brilliant and plays the part perfect! there's is something about hearing a voice you recognize in a game, audio book or drama, animated series or movie that just makes it special or pop. seth green - joker, liam neeson, ron perlman, Malcolm McDowell - fallout 3, Vincent price - multiple radio dramas, robin williams (RIP) - the Genie. to name a few. tim curry should do more voice acting. Link to comment Share on other sites More sharing options...
Tchos Posted August 25, 2016 Author Share Posted August 25, 2016 Something perhaps of interest. I'm playing around some more with on-the-fly environmental modifications, this time of interiors. Most of the time lately I've been using placeable construction materials rather than tilesets, but I saw a reference to something called "tile magic" in NWN1 that allowed them to dynamically change tilesets during the game for some cinematic purpose in one of the expansions, so I took a couple of hours to see how it might work in NWN2. The scripting they used relied on some constants in a 2DA, a model that doesn't exist in NWN2, and a different set of tiles, so I wrote a new function based on the same general idea to do it the NWN2 way (and without the use of a 2DA), and wrote a couple of utility scripts to do things like change to various standard sets and rotate them. Tinting is of course possible as well, and presumably texture swapping as well, but it would take more time and I just wanted to see this in action in a hurry. One limitation is that I can't seem to find a way to spawn an actual door object, aside from a door placeable which could be spawned as a non-usable cosmetic door positioned ajar in the doorway. However, since you likely don't want the player to walk through walls, you'd probably want to start the room out with some tiles already in it (I just started out with a blank room in this video to show how it was done), and pre-bake your walkmesh with the expected wall arrangement in place, so you could place real doors in there at that time. Basically, my purpose for a script like this would be to let me create new interiors as I need them without having to add actual new areas to my modules. Of course I'd spawn decorative placeables and NPCs into them as well. One other potential problem with such a system would be players dropping items in the area and expecting them to still be there later, which they wouldn't if I needed to change the area to something else, unless I really wanted to take the trouble to store the contents of the area for any future time they might enter it. Link to comment Share on other sites More sharing options...
Tchos Posted August 25, 2016 Author Share Posted August 25, 2016 I already see two interests in these scripts:Create secret doors/walls that can't be highlighted (except when they're actually discovered or known, when the corresponding tile is then changed)Make the results of a fight appear (with tiles showing fire marks, broken pillars, etc...)The only drawback being the walkmesh, triggers to prevent the party from crossing the walls need to be scripted (but that would have been necessary - at least for me - to hide/unhide the secret doors anyway). And slopes (changes in floor level) still need to be in a different area (or location in the same area), but good work all the same! As for secret doors, something like this could certainly be used to change a tile with a plain wall into a tile with a doorway with an appropriate skill check. Another method for doing that would be using a normal placeable wall, set to unusable so that it won't highlight, and either changed to usable upon a successful skill check (and using it would destroy it) or destroying it directly upon detection. Can you dynamically change the textures on the tiles, or tinted? Dynamically changing the tint/texture would be really cool. I haven't tried changing the textures yet, but I've done tints. I don't know if it's possible to specify colours directly by scripts, but I can use the scripts to select from prepared tint sets. I believe changing the textures to any of the standard variations for the tileset should be possible, since it works for other objects such as the paintings I did and the doors Bob did. Something else I hadn't noticed until I uploaded the video is that the UI circle isn't appearing on the ground. I'll have to test and see if it's because of the slight height offset I put in the script to account for spawning tiles over exterior terrain. Perhaps with no height offset the circles will appear. If the script were on a trigger then this could for the basis for a random dungeon level?PJ It would work fine on a trigger as long as some trigger-related lines were added to the script, and you could use it for a random dungeon layout, but you'd have to write a random generator that could intelligently pick tiles that logically go together (like making sure door openings are on both sides of a wall, for instance). Right now it's a ga_ script that expects parameters to be passed into it, so those parameters would have to be supplied in another way, like local variables or a random generator. Depending on how random you're talking about, such as whether you would want to have a wall in one random layout, where it's a doorway or a large open room in another layout, you'd probably also have to use push-back triggers, dynamic collision boxes, or something like that to deal with the walkmesh, and those aren't as good as real walkmeshes. I don't know if it's possible to generate a real walkmesh or swap to one of a bank of premade walkmeshes within the game engine. I tested to see if the CreateObject function would work for a door despite OBJECT_TYPE_DOOR not being listed as one of the options. I had found earlier that RemoveEffect works on placeables even though the function comments specify that it's to be used for creatures, so I thought this had a chance of working, too. In my test, I tried to spawn a door at the location of the PC. Unfortunately, no door appeared in my test. Either CreateObject does not work for OBJECT_TYPE_DOOR, as expected, or possibly doors cannot be spawned in a location currently occupied by a creature. Link to comment Share on other sites More sharing options...
Tchos Posted August 25, 2016 Author Share Posted August 25, 2016 Another experiment has borne fruit, so I'm putting it in this long-dormant thread. Some time ago, as some here may recall, I was experimenting with speakers and listeners as a means to make things happen when you type in the standard chat box in the game. The purpose would be for things like the player being able to enter passwords or speak magic words without the game having to prompt them to do so, as well as to be able to run my own debugging scripts without having to open the console or activate debug mode. Though that experiment was successful, and in fact remains in the BSoCC as a hidden feature, a commenter (I don't remember who, unfortunately, but it was a NWN1 player) mentioned that it could be done more easily without speakers and listeners by using the OnChat module event. I stopped experimenting with the speakers and listeners at that point, but it took several years for me to get around to trying the OnChat method. I did today, prompted by a NWN1 example, and although the syntax is different in the NWN2 version, it works just as simply and cleanly. There doesn't seem to be a template for the event in the toolset, but the NWN2 wiki had the necessary documentation and examples. I do wish I'd done this years ago, since it would have made my debugging tasks easier when testing my module, not having to use the console to access my debugging scripts and commands. That's what I'm primarily using it for, though Claudius has hinted that his current module uses something of this sort as a gameplay feature. I don't know whether it's through listeners or the OnChat event, though. Nothing related to the OnChat event, let alone speakers and listeners. It's just a set of scripts systematically included in all my campaigns folders which allows me to (relatively) easily direct a player if he's stuck because of a bug or an unanticipated behaviour. I also use them for debugging and test purposes. They require less memory efforts than standard scripts. For instance to update the journal, call sd_debug_quest("quest_tag", iStep). ga_journal would do the same thing but the syntax is more complex because of unecessary parameters.sd_debug_jump("WP_tag) moves the party to a specific waypoint, sd_debug_convo("locutor_tag", "convo_tag") fires a convo, etc... Ah, I thought you had said something about the player having to guess a password in one place. Just done through traditional search for clues and convos. Last of the Dana'an 2.0 has some functionality like that. The player can use the chat box to draw a crowd, then perform to raise money. Hm, I've played part of the original Last of the Dana'an, but not far enough to know whether that functionality was in the earlier version as well. No, it was added in the 2.0 WiP release. There may be other functions planned for access using the chat feature but that is the only one I'm aware of from playing it. You can always ping Lugaid' for more info. Link to comment Share on other sites More sharing options...
Recommended Posts