Information on 2da files, which are essentially 2 dimensional array tables of information.
Note a lot of information on specific 2da files are on different pages, such as Spells and Abilities for spells.2da.
2da Format
The 2da format is relatively simple:
- The top line must be 2DA V2.0
- There may be one or more blank lines before the first line that contains characters, which is considered the header line
- The first column header must be blank, and that column is ignored (is usually a human readable number)
- The first column number IDs can be wrong - the game just reads each new line as a new entry (incremented from 0)
- The second and onwards columns must have the header match the in-game reference loaded, the order of columns doesn't matter. Label columns are generally ignored.
- The first column header must be blank, and that column is ignored (is usually a human readable number)
- Further lines are data rows:
- Column data - but not the header name - can be in quotes to include spaces. Whether or not the game understands that one being in quotes very much depends
- Column data is separated by one or more whitespace characters (tabs, spaces)
- Blank data is classified with 4 stars: ****
- Column data - but not the header name - can be in quotes to include spaces. Whether or not the game understands that one being in quotes very much depends
This all comes together to mean some very odd looking 2das can be completely valid.
Client and Serverside 2das
The game as a whole is made up of the client and the server. A singleplayer game essentially runs both at once for the local user - of course other players may still join if it is created as a network game. Therefore it is important to understand which is which, since some 2da files you don't need to include at all in hakpack or nwsync resource lists, and can be left in the .mod or override folder on a PW server perfectly fine.
The client ones tend to be based around levelling up, appeareances, visuals (icons, vfx, textures, etc.) and sounds (the latter 3 servers don't even load of course). Servers need to know about all the resources loaded by the game in regards to objects, spells, etc.
Client and Server
| 2da load reference | 2da Name | Notes |
|---|---|---|
| m_paIPRPCostTables // all of them | All cost tables in iprp_costtable.2da column "Name" | Example: iprp_bonuscost.2da |
| m_pAppearanceTable | appearance.2da | |
| m_pGenderTable | gender.2da | |
| m_pSurfaceMaterialTable | surfacemat.2da | |
| m_pVisualEffectTable | visualeffects.2da | |
| m_pPersistentVisualEffectTable | vfx_persistent.2da | |
| m_pCreatureSpeedTable | creaturespeed.2da | |
| m_pDoorTypesTable | doortypes.2da | |
| m_pGenericDoorsTable | genericdoors.2da | |
| m_pPlaceablesTable | placeables.2da | |
| m_pAreaTransitionTable | Not sure | |
| m_pIPRPSpells | iprp_spells.2da | |
| m_pIPRPLightTable | Not sure - probably iprp_lightcost.2da ? | |
| m_pIPRPColor | iprp_color.2da | |
| m_pIPRPMelee | iprp_meleecost.2da | |
| m_pItemPropDefTable | itempropdef.2da | |
| m_pItemPropsTable | itemprops.2da | |
| m_pCreatureSizeTable | creaturesize.2da | |
| m_pArmorTable | armor.2da | |
| m_pEncumbranceTable | encumbrance.2da | |
| m_pPortraitTable | portraits.2da | |
| m_pPartsChest | parts_chest.2da | |
| m_pSpellSchoolTable | spellschools.2da | |
| m_pTrapTable | traps.2da | |
| m_pLightColorTable | lightcolor.2da | |
| m_pIPRPDamageTable | iprp_damagecost.2da | May be others too |
| m_pPartsRobe | parts_robe.2da | |
| m_pItemValue | itemvalue.2da | |
| m_pPackages | packages.2da | Presumably also all the relevant class package 2das |
Client Only
While many of these are only loaded by the game client, the toolset would still make regular use of them, for instance, to be able to have a blueprint reference a particular wing model on a suitable NPC.
| 2da load reference | 2da Name | Notes |
|---|---|---|
| m_pPartTable | Not sure? | Model appearance related |
| m_pArmorTypesTable | armourtypes.2da | Sounds loading (cloth, leather, plate, chain) |
| m_pTileColorTable | tilecolor.2da | Texture loading |
| m_pReplaceTextureTable | replacetexture.2da | Texture loading |
| m_pTailModelTable | tailmodel.2da | Model appearance related |
| m_pWingModelTable | wingmodel.2da | Model appearance related |
| m_pCloakModelTable | cloakmodel.2da | Model appearance related |
| m_pCursorTable | cursors.2da | For the cursors for certain default game actions. |
| m_pActionsTable | actions.2da | For GUI icons list (player action list top left) |
| m_pAmbientMusicTable | ambientmusic.2da | Server tells client which line to load, which refers to this for the sound files |
| m_pAmbientSoundTable | ambientsound.2da | Server tells client which line to load, which refers to this for the sound files |
| m_pFootstepSoundsTable | footstepsounds.2da | Sounds loading |
| m_pAppearanceSoundsTable | appearancesndset.2da | Sounds loading |
| m_pWeaponSoundsTable | weaponsounds.2da | Sounds loading |
| m_pDefaultACSoundsTable | defaultacsounds.2da | Sounds loading |
| m_pAmmunitionTypesTable | ammunitiontypes.2da | Sounds loading |
| m_pKeymapTable | keymap.2da | Client GUI default keys/shortcuts |
| m_pPlaceableSoundsTable | placeableobjsnds.2da | Sounds loading |
| m_pDamageLevelTable | damagelevels.2da | GUI showing how damaged something is (Formats the text over creatures heads) |
| m_pEffectIconsTable | effecticons.2da | GUI effect icons (top right, inspect panel on items/characters, character sheet) |
| m_pLoadHintsTable | loadhints.2da | Loading string text loading |
| m_pSwearFilterTable | swearfilter.2da | It's funny how this is here. I presume it alters incoming messages not outgoing ones? Needs testing. Servers can implement changes to PC chat to implement a filter using OnPlayerChat event. |
| m_pPhenoTypeTable | phenotype.2da | Model appearance related |
| m_pIPRPVisualFxTable | iprp_visualfx.2da | Visual effects |
| m_pWeatherTypesTable | weathertypes.2da | Client is just told which line to load |
Server Only
| 2da load reference | 2da Name | Notes |
|---|---|---|
| Any custom 2da | eg: des_crft_aparts.2da | Loaded with Get2DAString so entirely script based access |
| m_pStateScriptsTable | statescripts.2da | Runs specific scripts |
| m_pPoisonTable | poison.2da | Applies effects / timings of effect changes |
| m_pDiseaseTable | disease.2da | Applies effects / scripts / timing of effect changes |
| m_pRepAdjustmentsTable | repadjust.2da | Engine changes to "reputation" ie; if they're hostile or not. |
| m_pFractionalCRTable | fractionalcr.2da | Works out how much a goblin with 1/4CR is "worth" in the engine XP system/"difficulty" tags (eg; "Easy" enemy when inspected) |
| m_pEncounterDifficultyTable | encdifficulty.2da | The "value" column is loaded when referenced from the encounters GFF |
| m_pCategoryTable | categories.2da | Used by the functions for talents. Some is hardcoded (eg; potion lines). So yeah. |
| m_pExcitedDurationTable | excitedduration.2da | Presumably amount of time in milliseconds (so 10 seconds) the thing is considered in combat after the events listed |
| m_pRestDurationTable | restduration.2da | Amount of milliseconds to sit on the ground for |
| m_pPartsBelt | parts_belt.2da | |
| m_pPartsBicep | parts_bicep.2da | |
| m_pPartsFoot | parts_foot.2da | |
| m_pPartsForearm | parts_forearm.2da | |
| m_pPartsHand | parts_hand.2da | |
| m_pPartsLegs | parts_legs.2da | |
| m_pPartsNeck | parts_neck.2da | |
| m_pPartsPelvis | parts_pelvis.2da | |
| m_pPartsShin | parts_shin.2da | |
| m_pPartsShoulder | parts_shoulder.2da | |
| m_pXpBase | exptable.2da | Levelling up chart |
| m_pAssociatesAnimalCompanionTable | hen_companion.2da | |
| m_pAssociatesFamiliarTable | hen_familiar.2da | |
| m_pSkillVsItemCostTable | skillvsitemcost.2da | |
| m_pRangesTable | ranges.2da | Note the "45.0M" range for streaming in placeables is hardcoded, and a maximum of visibility regardless of values here. |
| m_pPolymorphTable | polymorph.2da | |
| m_pDamageHitVisualTable | damagehitvisual.2da | Sends a relevant visualeffect.2da line number to the client |
| m_pBodyBagTable | bodybag.2da | References a placeables.2da line |
| m_pIPRPFeatsTable | iprp_feats.2da | |
| m_pIPRPMonsterDamageTable | iprp_monsterdam.2da | |
| m_pOnHitTable | iprp_onhit.2da | Note this pretty much is hardcoded |
| m_pOnHitSpellTable | iprp_onhitspell.2da | |
| m_pOnHitDurationTable | iprp_onhitdur.2da | |
| m_pIPRPACModTypeTable | iprp_acmodtype.2da | |
| m_pIPRPWeightIncTable | iprp_weightinc.2da | |
| m_pIPRPArcSpell | iprp_arcspell.2da | |
| m_pIPRPBonusCostTable | iprp_bonuscost.2da | |
| m_pIPRPSRCostTable | iprp_srcost.2da |
NWNX Reference
Source of what is referenced by the game engine. It relates to this file: https://github.com/nwnxee/unified/blob/master/NWNXLib/API/API/CTwoDimArrays.hpp