Placeable objects are non-moving models places into the game world. This may need a few subpages, there is a lot to talk about with them. If you're ever confused about flags, come here for more info!
Blueprints
Placeable blueprints are GFF files encoded as UTP. They contain all relevant information about a placeable and how it operates.
Usable Flag and Static Flag
There are two key flags for placeables: Usable and Static. These are important to learn about for toolset usage especially in a MP / persistent world module. This is a table of the 3 main possible states with these flags:
Usable Flag | Static Flag | Can have inventory/trap/be locked in toolset? | |
---|---|---|---|
On | Off | Yes | Usable placeables players are meant to touch softly with hands (or possibly hard with weapons and spells) |
Off | Off | No | Non-usable placeables which you still want to interact with explosions/scripts or be dynamically created using CreateObject |
Off | On | No | Static "terrain", baked into the mesh and pathfinding (note can still be created see below, just harder to set it up in the toolset). This has some optimisations but most importantly for players keyholing works correctly with them. |
Note that the fact the toolset disables fields is more to help module designers cotton on to what each one means. Usable can be toggled later after all.
Creating Placeables
See notes below but essentially:
- CreateObject() will strip the Static flag when using it to create what would be a blueprint of a static placeable
- This means it is unusable by default (usable flag is defaulted off) but retains other properties
- It also means it can be made usable so you can get a usable placeable from a static blueprint, weirdly
- CreateObject() otherwise respects the Usable flag, which can be also toggled via. scripts (see below)
GFF editing (JsonToObject) may make having a static placeable with a trap on it, for instance, more easily doable.
All placeables
At their basic level all placeables have these properties:
- Is findable with GetFirst/NextObjectInArea()/GetNearestObject() and GetObjectByTag() regardless of static or usable flag so be careful if you are looking for a particular object and you simply edit in the area a duplicate of other static ones
- They always run scripts and script actions at the lowest possible priority (VERY_LOW - see GetAILevel) in spite of player proximity, which can delay things such as AssignComment(ActionCastSpell()) used from them or responding to SignalEvent or even ExecuteScript().
- Remove all placeable heartbeat scripts if they're not needed! Just because it's not usable or is static doesn't mean the heartbeat doesn't fire.
- They have a valid HP, hardiness (damage resistance) and can be possible targets for VFX nodes (eg; cast a fireball in an area with placeables)
- Have the plot flag, which needs to be disabled if DestroyObject() is used on them
- Whether usable/static or not can have flags such as locked, and other aspects altered (then this might be applicable when using SetUsableFlag)
- Can have animations toggled (eg torch coming on/off) using ActionPlayAnimation() and ANIMATION_PLACEABLE_DEACTIVATE or ANIMATION_PLACEABLE_ACTIVATE. Note lighting may need to be recompiled.
Usable Placeable
The usable flag only alters one key thing - it makes the player able to see it using TAB and highlight it, and click on it. Without it some events are rendered near useless (eg; OnOpen, OnDisturbed, or OnUsed). Some that are more relevant however might be OnDamaged, OnDeath and OnSpellCastAt since AOE spells and abilities could affect them.
You can toggle if a placeable is usable using SetUsableFlag script command.
Some other relevant usable placeable specific notes:
- The toolset requires the usable flag to be ticked to allow an inventory and some other aspects such as locked status and trap. If you want a non-usable placeable with an inventory for some reason (maybe a chest that isn't accessible now, but will be later) you must make the blueprint be usable and set the usable flag to off in a script when it is spawned, or resort to GFF editing.
- NWN:EE now raises the AI priority if being interacted with so the scripts like OnUsed to signal starting a conversation run a lot more speedily on heavily used servers.
Static Placeables
On the server, static placeables are identical to dynamic ones. They can be found with scripts (such as GetFirst/NextObjectInArea, GetObjectByTag) and even run scripts/be affected by them to a degree, but because they're baked into a level cannot be created/destroyed easily (excepting NWNX see below).
On the client, static placeables are part of the tile. During area load, it will load the tile models, it will load the static placeable models, and it will merge them into a single optimal static geometry mesh. This super-mesh is never updated afterwards.
Static placeables have these specific properties, else they have the same properties of non-static placeables (see below):
- They default to Plot (invincible). Use SetPlot(FALSE) if using DestroyObject() on them. This renders it immune to spell AOE damage.
- Cannot play animations (eg; turning a flame on/off) since this requires it to be non-static
- However can be have permanent animations such as danglymesh on the model itself
- Cannot be created, sort of:
- In NWNX you can create static placeables but it will only appear if a player re-enters the area for it to be "baked in" and graphically load.
- Outside of NWNX CreateObject() will run a UTP file and strip the static flag off. This means it defaults to a non-usable placeable as per below properties. This means you don't necessarily have to have multiple blueprints for static versus non-static versions in a SP module.
- Can be destroyed (use DestroyObject() if the plot flag is removed) however it will not be removed from the geometry until the player re-enters an area. Outside of NWNX this is not recommended unless you want to make permanent level changes.
- They do not load LOD files and are always at maximum quality
- They cannot be visually scaled or transformed (although their location can be set to any arbitary one). To scale use a tool like CleanModelsEE to scale the MDL file and create a new placeables.2da line for it.
Choosing between using Dynamic vs Statics
While dynamics allow for more flexibility with visual transforms, etc., there's three things to consider in which static and non-static differ with regards to performance:
- On the client, the rendering of the static placeable is slightly more performant in some cases, because it gets baked into the giant mesh. This is a lot more noticeable when you have a lot of the same static placeables, so they can be combined into a single draw call.
- On the network (both client and server), static placeables have minimal overhead once during area load. Non-static ones have an overhead every time they enter or exit the view. This is where the visible distance comes into play. If something has the visibility distance set to 1000m, then it's effectively the same as a static placeable in this regard because it never leaves the view.
- On the server, non-static placeables are regularly checked for 'did anything change and should we send an update to clients?'. This is very CPU intensive. The very first thing that is checked is 'Is this placeable within visible distance of that client?' - if the answer is 'no' then no further checks are done.
Considerations: (1) is barely noticeable in general case. (2) happens virtually never for the individual thing. Even if you constantly move in/out of view, that's at most once per second, which is nothing. It also doesn't really matter what the actual visible distance is, you can have the same happen at 45m or 90m or 5m (3) can be massive when you have a lot of objects and lot of clients in the area. This can easily add up to 50% of all the CPU time ever done by a PW server. This is why the development team didn't recommend raising the visibility in general. If you raise it across the board from 45m to 60m, you've basically doubled (r*r*pi) the number of objects that a client sees and that need the complex checks now.
Another way to look at all this is to imagine two identical 8x8 areas with 1000 placeables stacked in there and the player at the center. In one case, placeables are static, in the other they're not. If playing in multiplayer, the client will probably not notice any difference in fps whatsoever.
If playing in singleplayer, the non-static version will have half the fps of the static one.
Moving Placeables
You can either clone the placeable (CopyObject) or use the effect EffectDisappearAppear on them. This won't change the facing but SetFacing works on placeables.
Placeables with Flare Lens
Most light source lens flares use the model fx_placeable01.mdl. If you override that with a version with the flare removed, you can kill the "hot spot" in the center of the light. Here's a version I did to solve the problem.
See also: placeables.2da ("https://nwn.wiki/display/NWN1/placeables.2da?preview=/38175210/38175586/fxpa_flare%20usage.txt")
Placeables and the Toolset
See this handy tutorial on the toolset pages for information about special ways placeables can be placed eg; outside the walkable area of the map. You can now in EE transform them to be bigger or smaller or rotate them (which can also be done in scripts on non-static placeables).
1 Comment
Pstemarie
Placeables also support Obscurring walkmesh material, but this needs to be edited directly in the PWK file with a text editor, changing the material value from 7 to 2. You'll also want to make the PWK mesh geometry 3D as opposed to a 2D plane.