Visual Effects using "programmed effects" can now be changed (outside of engine edits) using progfx.2da. This was added in patch 1.80.8193.14.
Note there is no "custom programming" this is a file of parameters for what the engine will understand when using a particular "type" of programmable FX (1 through 13).
You do not have to use the lines defined already to define your additions. Any line can be used for any progfx.2da type, just make sure the Type column is correctly set. For instance you could have all your custom ones start at line 2000 and not have to worry.
You use the visualeffects.2da columns ProgFX_Impact, ProgFX_Duration and ProgFX_Cessation to reference lines in this 2da:
- ProgFX_Impact - Run once when the VFX is applied
- ProgFX_Duration - Run continuously while VFX is active
- ProgFX_Cessation - Run once when VFX is removed
Previously, all the values for these columns were hardcoded. With 8193.14, a new 2DA, progfx.2da is added which contains the definitions for these values.
The progfx effects are grouped by Type. Each progfx Type has different handling within the engine, and the meaning of the parameters depends on the type. Note the Type ID by default is tied to a row number (eg; Type 3 starts at 300) but that no longer has to be the case.
Some Beamdog documentation available here: https://gist.github.com/mtijanic/97f309b8d9262f0cf4f7dfba6618ea6a mostly translated here.
progfx.2da Exceptions
progfx.2da only applies to visualeffects.2da. The problem with this is that vfx_persistent.2da cannot make use of it (this also defines models to use for visuals). There is one line that has a programmed effect - line 7 - blade barrier - applies environmental mapping as per id 2 below. No other lines can have this added, or any other progfx.2da changes.
2DA Contents
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Label | BeamLightning | This is just a name for the effect for readability. No effect. | |
Type | 1 | 1-13 | Type ID. Generally the TypeID is tied to the hundreth position in the 2da file itself, eg; Type 3 starts at line 300. |
Param1 | See below | Varies | See below |
Param2 | See below | Varies | See below |
Param3 | See below | Varies | See below |
Param4 | See below | Varies | See below |
Param5 | See below | Varies | See below |
Param6 | See below | Varies | See below |
Param7 | See below | Varies | See below |
Param8 | See below | Varies | None seem to use this one for some reason. |
Types Documentation
1: Skin Overlay (barkskin, stoneskin, etc)
This will set the texture of the creature to the given model texture, along with some altering of impact effects.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 1 | 1 | Set to 1 for this type. |
Param1 | vdu_tex_stone | Model name | Model Name with overlay (vdu_*) |
Param2 | stone, wood | name of entry in appearancesndset.2da ArmorType column value IE: stone, wood, scale, ethereal, leather, chitin, plate, chain, crystal | Tied to appearancesndset.2da ArmorType column (and possibly the counterpart weaponsounds.2da) which controls what noises weapons make when hitting it. Needs testing to see what happens if left blank, or set to an odd value. |
Param3 | 354 | visualeffects.2da line | The visualeffects.2da line played when the creature under this visual effect is damaged replacing usual "chunk" effects (and is "Medium" sized or larger). VFX_COM_CHUNK_STONE_MEDIUM for petrify. |
Param4 | 353 | visualeffects.2da line | The visualeffects.2da line played when the creature under this visual effect is damaged replacing the usual "chunk" effects (and is "Small" sized or smaller). VFX_COM_CHUNK_STONE_SMALL for petrify. |
Example progfx.2da lines:
2: Used for environment mapping
Sets an environment map file to be used by the VFX. The default lines do not actually seem to be used by the default game visual effects, and there doesn't actually appear to be any vdu_envmap_XXX files in the game files. Presumably the default lines are there just in case/show what the game would do by default.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 2 | 2 | Set to 2 for this type. |
Param1 | vdu_envmap_000 | Model name | Envmap Name |
Example progfx.2da lines:
3: Static Glow effects.
Sets a static glow effect to the model affected. This appears to be the same as the "hold tab" hilite (or "highlight") functionality. Of course tab overrides it.
Commonly used for VFX_DUR_AURA_XXX visualeffect lines as ProgFX_Duration, although can be used in ProgFX_Impact as well (eg: VFX_FNF_HIGHLIGHT_FLASH_WHITE)
The glow is constructed using image file fxpa_dot02, which is shared by the tab and mouse/over highlight. Any modification to that image will affect this type of glow. As an example, see Object Hilites
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 3 | 3 | Set to 3 for this type. |
Param1 | 0.25 | 0.0 - 1.0 | Amount of Red |
Param2 | 0.35 | 0.0 - 1.0 | Amount of Green |
Param3 | 0.5 | 0.0 - 1.0 | Amount of Blue |
Example progfx.2da lines:
4: Lighting addition or removal
Lighting models to provide lighting (or remove it - like if blinded!). There are likely a lot of hardcoded relations to these lines used by the game feats like Darkvision or certain effects like Ultra Vision.
Note that visualeffects.2da lines 153 to 180 are hardcoded in as to affect stealth/spot check and for use on the Item Property: Light. The effects are:
- At night:
- Without Darkvision or any 153 - 180 lines VFX applied on the spotter, they get -5 to their spot roll
- With 153 - 180 VFX the hider will get -10 on the the spot DC for creatures spotting them
You can't add more light lines that affect these so either:
- Remove all the above lines, and stop using Item Property: Light and code up an entirely new set of VFX lines and apply the penalty manually (without overlaps, fun!)
- Just edit lines 153 to 180 for alterations (eg more colours etc. by taking existing colours out).
- Add new lines but carefully add the correct penalties when that light will be "top" by searching them and checking the Param4 value since only the brightest tends to apply.
The normal ones appear to be used for ProgFX_Duration
The Fade ones appear to be used for ProgFX_Cessation
Note there are references to the default visions like Dark Vision here, therefore if you alter the progfx.2da or visualeffects.2da line references these effects can apparently be altered when loaded by the engine. May be worth testing.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 4 | 4 | Set to 4 for this type. |
Param1 | White_5m | Model animation name | Animation name of the Param7 model we are using. EG: "White_5M" is that animation node. Doesn't seem to be case sensitive (the model for fx_light_clr has it down as "white_5m") |
Param2 | 1 used for usual duration -0.31 used for the "cessation" (ie when a light source is removed) | Float | Animation speed. Fading is negative -0.31. |
Param3 | 0/1 | Boolean | Cast shadows or not (5M ones do not by default cast shadows). This overrides the model property of "shadow" set in fx_light_clr. |
Param4 | 13 (Area Blackout / Blind Vision) - When blinded with EffectBlindness or EffectDarkness (which detects Trueseeing or Ultravision, which can skip the blindness), applied using VFX_DUR_BLACKOUT (5) 20 (Lights) - Usual lights (eg; Torches, magical light rings) - various VFX lines, VFX_DUR_LIGHT_* 49 (Ultra Vision) - For countering Darkness (thus is higher), using EffectUltravision, applied using VFX_DUR_ULTRAVISION (244) 50 (Darkness) - applied using VFX_DUR_DARKNESS (1) but we don't think this is used by EFfectDarkness itself. 51 (Darkvision) - The racial feat FEAT_DARKVISION or item property "Darkvision", applied using VFX_DUR_DARKVISION (182) 52 (Low Light Vision) - The racial feat FEAT_LOW_LIGHT_VISION, applied using VFX_DUR_LOWLIGHTVISION (243) 53 (Blind Vision) - Blind Vision appears to be for those without any of the above effects applied. So default "humans" in otherwise dark areas get this. By default actually lights up the area a bit. TODO: Write a proper "Vision" page to explain the above, with pictures, and how to make alterations to each type. | Integer | 20 for the normal lights. It is the Priority of the light. No idea how it relates to other in-game lights (what priority are they by default - eg; a placeable?) Upon further testing, these values likely only apply to the player's client for determining which light should take priority when there's a light (or absence of) on the player, since only 1 can be shown on the player, and probably has nothing to do with inter-object interactions. In cases where the priorities are modified and racial vision supersedes other lights on the player, this is only local to the client; if you have 1 light and a racial vision active, the other players will see the light, whereas you'll only see the racial vision (since you had set racial vision priority as higher than the light). The priority is for what one will get applied if more than one exists on a player. EG: Equipping a torch turns off Darkvision, but a torch does not override Blindness. The special VFX for different "visions" probably are all used by hardcoded engine calls. |
Param5 | 1 for Darkness, Darkvision, Blindvision, Low Light Vision else 0 | Boolean | If this light source comes close enough to another light source, this light should be temporarily removed while in the vicinity. (This is why racial vision always "turns off" when coming into close contact with any other lights; note that this doesn't have anything to do with only 1 light being allowed to exist on the player at a time.) |
Param6 | 1 for LightAreaBlackout and FadeLAreaBlackout | Boolean | Beamdog documentation: "Attach to scene". If 1, removes all lights from the scene when under the Param1 effect. Typically, this means when blinded, remove all lights from the scene and apply Blind_Vision, but as an example, you could also make it so that when somebody has a Red_5m effect on themselves, they only see the red light around them and no other lights in the scene. Make sure the Non-fade and Fade versions of the light effect in question are the same values, otherwise the area lights won't come back when the effect is removed, or vice versa (likely reversed logic to what you want). |
Param7 | fx_light_clr | FX Model name | Model to load that relates to some of the above parameters, specifically Param1 and Param2. |
Example progfx.2da lines:
5: Alpha transparency modifiers.
These are used to apply VFX_DUR_INVISIBILITY, VFX_DUR_GHOSTLY_VISAGE, VFX_DUR_GLOW_ and a few others as ProgFX_Duration.
Since there is no model mentioned it's just a alpha and colour change.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 5 | 5 | Set to 5 for this type. |
Param1 | 0, 0.5, 0.001 | Float 0.0 - 1.0 | Amount of transparency (lower bound). Can be 0 as per cutscene invisibility or low values like 0.001 it seems 0.0 is a special value for Cutscene Invisibility and applies and removes some special states (ie the invisibility is "full on" the model removed even for the player if applied to them) - it might or might not remove the TAB popover however (is meant for cutscene mode where the player can't press this). |
Param2 | -1, 0.25, 0.5, 0, 1 etc. | Float -1 or 0.0 - 1.0 | Red value (if -1 then ignore colours and keep original?) |
Param3 | 0, 0.25, 0.4, 0.96 etc. | Float 0.0 - 1.0 | Green value |
Param4 | 1, 0.25, 0.5 etc. | Float 0.0 - 1.0 | Blue value |
Param5 | 0, 1000, 6000 | Milliseconds | Time between fades presumably, if 0 just does a permanent consistent visual effect. |
Param6 | 0, 1, 0.80 | Float 0.0 - 1.0 | Amount of transparency (upper bound). If we're fading (Param5) we go towards this value, then presumably back to Param1 value. EG: VFX_DUR_GHOSTLY_PULSE does 0.001 transparency (nearly not there) to 1 (entirely there) over 6 seconds then would do 6 seconds back again. |
Example progfx.2da lines:
6: Pulsing Aura glows - fades between 2 colors
Pulses two colours on the given model. This is used for VFX_DUR_BLUR and VFX_DUR_AURA_PULSE_XXX_YYY visualeffects.2da lines.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 6 | 6 | Set to 6 for this type. |
Param1 | 1, 0.25, 0 | Float 0.0 - 1.0 | First colour; Amount of Red |
Param2 | 1, 0.5, 0 | Float 0.0 - 1.0 | First colour; Amount of Green |
Param3 | 1, 0.17, 0 | Float 0.0 - 1.0 | First colour; Amount of Blue |
Param4 | 1, 0.82, 0 | Float 0.0 - 1.0 | Second colour; Amount of Red |
Param5 | 1, 0.1, 0 | Float 0.0 - 1.0 | Second colour; Amount of Green |
Param6 | 1, 0.83, 0 | Float 0.0 - 1.0 | Second colour; Amount of Blue |
Param7 | 1000 | Milliseconds amount | Presumably the amount of seconds to go from the first colour to the second colour. Once reached the second colour it takes the same amount of time to fade back to the first. |
Example progfx.2da lines:
7: Beams
Within original content, beams are used solely for EffectBeam which adds nwscript parameters for the "source" and "target" (so you can do a penagram on the ground if you wanted).
What this actually does is more useful than it sounds. One type of emitter is a point-to-point emitter (P2P) which moves a visual effect along a track from source to target point. There are three types of P2P emitter available within NWN.
1) Bezier
2) Gravity
3) Lightning
Beams within original content use the lighting emitter type in which a series of lightning decal graphics is placed along a line from source to target. The number of decals placed is dependent upon the builder, but the number must be a binary number (2, 4, 8. 16, 32, 64, etc.). Each decal is overlapped slightly, and options within the lighting type allow you to kink the lightning by skewing each decal in the line. No kink produces a straight beam appearance.
The other two P2P effects toss out emitted decals or chunks at the source, and they migrate toward the target point. Normally, the target point is defined by an AuroraRef dummy within the MDL file (the position of the dummy is often backward from where the emitted particles will go). However, with the Beam progFx, what you're doing is having the engine detach the beam target from that AuroraRef and place it on the location of the target object. This allows you to now use both Bezier and Gravity "beams" in P2P ways with the target object being the actual target. You're no longer confined to lightning type emitters.
Note: the AuroraRef node is NOT being moved to the target object. If you parent parts of the mesh to the AuroraRef dummy, they will remain where they were in the original MDL layout. What is actually happening is the target point is being removed from the dummy and placed on the target object.
The main thing here is the model is now unhardcoded - go mad adding your own (by editing the existing even).
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 7 | 7 | Set to 7 for this type. |
Param1 | vdu_beam000 vim_rayfire | Model resref name | Visual effect model resref name |
Param2 | cast01 | Animation name ? | This appears to be the animation name to play on the VFX - cast01 only ever appears in vim_lashfire so presumably used to activate the animation when the beam starts. Therefore have a look at vim_lashfire for an example of this usage. Question: does default to cast01 if nothing is specified/something invalid is used? If it is missing it presumably just does nothing. |
Example progfx.2da lines:
8: Stops models rendering
This would obviously remove the model from view, there appears to be no parameters so there is likely no reason to create duplicates of this line, but reference ID 700 to use it.
Used on visualeffects.2da line 120 - VFX_COM_UNLOAD_MODEL with the entry being tied to ProgFX_Impact. It's unknown if the game uses this VFX line or the 700 progfx.2da line at all (VFX_COM_ are instantly applied "combat" effects...but what would make a model disappear?).
Presumably a good one to use if you want another VFX to apply such as "blowing up a target" where if the model was still there it'd look weird.
The lexicon suggests this does nothing however. Possibly it only works in certain circumstances? Also how would you remove the fact the model is now gone? (possibly some SetAppearance calls may work but better be sure if using this!).
Example progfx.2da lines:
9: Chunk Model
VFX_COM_GIB uses this for it's ProgFX_Impact. This is likely the engines hardcoded high violence chunking - when like EffectDeath is used with bSpecacularDeath or similar (see notes here).
Since there are no parameters presumably we cannot force a particular chunk to be used. Using VFX_COM_GIB in EffectVisualEffect may also be buggy and it might be just only usable by the game engine itself not via. scripting or VFX lines.
Example progfx.2da lines:
10: MIRV (projectiles like Magic Missile)
Magic Missiles and Acid Arrows! The models can now be changed/new ones be added and the speed and projectile type can be changed. The MIRVs are randomised in direction if using certain projectile types.
This allows you to have fireballs throw from the ImpactScript for instance instead of being part of the spells.2da line definition or using wonky ActionCastSpellAtObject parameters (which miss a lot of projectile types).
Note: After testing even the slowest speeds here (log) tends to be much too fast - especially for "Spiral" (used for Hellball) where it messes up entirely. Needs more speeds to be effective for longer duration projectile types.
log nwscript code (magic missile, the slowest):
float fDist = GetDistanceBetween(OBJECT_SELF, oTarget); float fDelay = fDist/(3.0 * log(fDist) + 2.0); eg: fDist = 20.0f: 3.38 seconds
llnear nwscript code (will do a linear distance calculation. This is modified from acid arrow twice but is twice as fast):
float fDist = GetDistanceToObject(oTarget); float fDelay = (fDist/50.0);
linear2 nwscript code (acid arrow, linear half speed):
float fDist = GetDistanceToObject(oTarget); float fDelay = (fDist/25.0);
Note these are used in the ProgFX_Impact (eg; VFX_IMP_MIRV) it is an "instant" effect but with a visual that goes on. So you have to delay each hit by a certain amount to get the right "impact time" to, say, do damage.
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 10 | 10 | Set to 10 for this type. |
Param1 | vpr_magmisl | Model resref name | Visual effect model resref name |
Param2 | 340 | spells.2da line...for some reason | 340? It's line SHADES_Cone_of_Cold in spells.2da which is random. But confirmed by Beamdog it's the spells.2da line - which presumably is used to load spells.2da info of the projectile (although if EffectVisualEffect creates the projectile it probably already has that info loaded?) It is likely best to leave this as 340 to not have any issues, or set it to a line with no Projectile information (which 340 doesn't have). After testing setting it to a line with any projectile info doesn't do anything either. Probably unused by the game. |
Param3 | 0, 2 |
| Orientation - if needed. 0 if Magic Missile or Electric Magic Missile, 2 otherwise (arrows and darts). |
Param4 | 4, 1 |
| Seems to be PROJECTILE_PATH_HOMING (1) for Acid Arrow and PROJECTILE_PATH_ACCELERATING (4) for Magic Missiles. The values to the left are what the different options are. The travel time is controlled by Param5. |
Param5 | log, linear2 | log linear linear2 | The distance caluclation that you can then use in spell scripts to time impacts and damage. See above for nwscript info. "log" time to target scales logarithmically; "linear" scales linearly; "linear2" scales linearly, half speed; If left blank appears to use "log" as a default. |
Example progfx.2da lines:
11: Variant MIRV with sound and impact sound (Only used for moo cows / cheat)
Not sure how useful this is since it's used by the engine for the cheat command, and it doesn't have the same parameters as the MIRV options.
The most useful thing may be Param2 which is a one-off "source" sound (from when the projectile starts) so could be a crossbow going off or something for a bolt to appear.
I'm not sure what the distance / time calculations if using this is. Cows move in weird ways...!
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 11 | 11 | Set to 11 for this type. |
Param1 | vpr_kngpow | Model resref name | Visual effect model resref name |
Param2 | c_cow_atk1 | Sound resref name | One off sound when used, as an "Initial Sound". Sound itself doesn't repeat only fires once from source of VFX. |
Param3 | c_cow_dead | Sound resref name | Likely the same as "SoundImpact" column in visualeffects.2da entry. |
Param4 | 4 | Projectile Type:
| Since you can't specify a travel time this must be set, presumably to "log" but might be something slightly different - needs testing (cows are weird). |
Example progfx.2da lines:
12: Spell Casting Failures - model node attached VFX
By default these are used in the VFX lines VFX_FNF_SPELL_FAIL_HEAD and VFX_FNF_SPELL_FAIL_HAND. Those VFX lines are hardcoded so the default progfx.2da lines should usually remain unaltered.
For new lines you can add a VFX model to any node of the object being applied to. For instance if you have a "CatCollar" node you can have the VFX attach to it.
Obviously there are some limitations:
- Weapons are not part of the creatures model so the node names of them are unavailable (and sadly you can't apply a VFX to a weapon object easily - but iprp_visualfx.2da is a possible fix there - even if it's very cumbersome!)
- The node automatically moves with the model but does not adhere to OrientWithGround or OrientWithObject columns in visualeffects.2da - the VFX model itself must be coded to default to one of these modes if required
Examples of things that could be done:
- Flaming hands
- Head VFX (ghost rider style!)
- Better orientated/positioned lights for torches
- Any kind of attached items or hair or asscessories. You can adjust the location with the parameters in EffectVisualEffect script command.
See also:
Column Name | Example | Valid Values | Description and Notes |
---|---|---|---|
Type | 12 | 12 | Set to 12 for this type. |
Param1 | headconjure handconjure | Model target node name | A model node since these are listed in .mdl files for creatures so the source of where the VFX will go Note if **** then the VFX fails to display (but the game doesn't crash). |
Param2 | vimspellfail | MDL VFX resref | The VFX file to play |
Example progfx.2da lines:
13: Freeze Animations
This would obviously just freeze animations. There are no parameters so there is likely no reason to create duplicates of this line, but reference ID 1300 to use it. The VFX line used by default is VFX_DUR_FREEZE_ANIMATIONS.
Example progfx.2da lines: