Mage Tome and Kaedrin

I can’t seem to get Kaedrin 1.42.1_override_dialoguetlk to work cohesively with MageTome. When I finally get all of the files where they belong, All of the classes from MageTome only show the icons for them. When I take the lines from the end of the dialog.tlk for MageTome and tack it on to the end of Kaedrin, it works in a limited way. The MageTome classes now show up correctly, but at least one third of the Kaedrin classes disappear, starting with Assassin and Avenger. Any thoughts? I am using the TlkEditor to access what I need.

UPDATE: This was under the wrong flag so I just put it in here hoping to get the help I am looking for.

I haven’t looked at MageTome but i imagine it’s gonna be a fairly extensive modification (like Tome of Battle – which i haven’t really looked at either) (unfortunately).

Once the kPrC Pack is installed, however, everything that you want in your /override needs to play nicely with it, just because it’s so huge/extensive. That is, you’ll need to merge the extra stuff into Kaedrin’s …

And if they don’t follow Reserved2daRanges, etc etc there will be conflicts, resulting in a nontrivial merge.

There can be only 1 Dialog.Tlk file (as you’re probably aware).* Each string-entry in the file is referenced by a strref → a string reference. The strref is an integer that points into Dialog.Tlk … so when merging the MageTome’s strings into the kPrC strings they (likely) can’t simply be tacked onto the end … because if the strrefs change the reference becomes borked.

The same holds true for merging any conflicting 2das (the row-ids must not be changed) etc.

If a strref or row-id changes, then you pretty much got to find all objects that use the old number and change them to the new number.

* do yourself a favor and backup the original Dialog.Tlk in your Nwn2 installation folder, and put your modified Dialog.Tlk there (this allows those extra strings to show up in the toolset as well as the game). And disable any other Dialog.Tlk that might be kicking around in eg. /override

1 Like

So, K’s dialog.tlk has StrRef starting at 0 and ending at 242804. Mage Tome’s dialog.tlk starts at 0 and ends at 246560. From what I can tell on a cursory examination, the new info for Mage Tome starts at 246000. It even says in the next column “Mage Tome PrC / Spell Kit starts here”. Are you saying that I couldn’t just copy lines 242805 through 246560 and paste them to the end of K’s dialog without consequences? Are there other files that would need to be combined?

UPDATE: I just looked at the 2 different classes.2da files from K and MT and they have some differences. Example: The Assassin class points to line 240541 in the dialog.tlk for the description in K’s pack, but the same class looks at line 9010 in MT pack. It would seem that I would need to merge the 2 classes files as well, and leave only one active. Just like I would need to do with the dialog files, correct? What other files could there be differences with? Feat.2da is the only other common file I can think of off the top of my noggin.

Am I at least close?

ok that sounds all good :)

(just copy the lines in the Tome file over to the same #s in Kaedrin’s)

idk I haven’t looked. But you should look at every file in the Tome and see if Kaedrin’s already uses that resource … if not then the file is good to go in your /override. But if K’s is already using that filename (aka resource) then they probably should be investigated and merged.

when I look at the entries for those 2 strrefs, I’d say that #9010 is the stock description for the Assassin, while #240541 is Kaedrin’s upgraded Assassin. The one you want depends on the characteristics/implementation of your active “Assassin” class … (probably K’s but i can’t sit here and say because I don’t know what’s on your system specifically)

absolutely. (note: Yata 2da editor has diff/merge functions)

yep. (I don’t know of a Tlk merge application, but if you find one that works for Nwn1/EE it should work well for Nwn2 also – the Tlk format/specification is the same for both games) Or just do it manually with a Tlk app like TlkEdit2 … idk how many Tlk entries need to be copied over …

idk … personally I’d upack both mods and use a duplicate file checking app to give an idea of what files are duplicated (ie conflict) and need to be merged.

again, my Yata 2da editor has diff/merge functions that should give a decent notion of what to do. Open both tables in Yata and rightclick their tabs … select diff1, select diff2, bam → fields with different values should become highlighted in darkish green …

it sounds like you understand the theory/concepts well enough to start. Keep things organized and make backups as things proceed

So, quick question: I see how I can compare the files with the diff1/diff2. How do I select what I want to replace? Does it ask me which file to take from and which file to write to? Will/can it create an entirely new file? Say take from classesK, write into classesMT, and/or create classesCOMBINED? What functions should I be using?

Here’s an example of using Yata to merge 2 Classes.2da files

open yata, open Kaedrin’s Classes.2da first (this will be diff1, your result). Then open Tome’s Classes.2da (diff2).

select diff1, select diff2

focus diff2, the Tome’s 2da

rightclick on a dark green cell (or use the goto button in the differ dialog that popped up)

on the contextmenu that appears (after rightclick) choose merge to other – Ce to copy the cell to Kaedrin’s. Or merge to other – Ro to copy the entire row to Kaedrin’s.

Alternately, for large merges, a path to Winmerge can be set in Yata’s Settings.Cfg file, such as →

diff=C:\Program Files (x86)\WinMerge\WinMergeU.exe

if you have Winmerge installed on your hardrive. (Yata’s Options file can be accessed under Help|Options file.)

note: There is no command to just do it all at once.

When things look good Save Kaedrin’s Classes.2da (and don’t forget to rename or remove the Tome’s Classes.2da later)

To recheck things you could run another diff on the 2 files after your merge is complete.


the context menu on a diffed cell can only send the text to the other file. (ie. you can never pull text from the other diffed file). So you look at the cell that you want the text of and rightclick → do merge to other

no sry. Edit a copy of Kaedrin’s 2da if you want to roll that way …

For example, have 2 copies of Kaedrin’s 2da on your hardrive
- classes.2da (diff1)
- classes_kprc.2da (backup)

and one of MageTome’s
- classes_mt.2da (diff2)

Then follow my instructions above, using classes.2da for diff1 and classes_mt.2da for diff2

1 Like

I found something odd. When comparing the 2 feat.2da files, I notice a number of lines in the MT feat.2da file that refer to a name and description that does not exist. For example: Line 2861 in the MT feat.2da file reads as follows - 2861 FEAT_SHAR_DARKNESS 16777216 16777217.
Those line numbers that are referenced, 16777216 and 16777217, do not exist. anywhere. Even when I look for the feat in the dialog.tlk file by using the find function to look for FEAT_SH, it tells me there is no match. Would I presume to simply not transfer those lines to K’s feat.2da file? I cannot even locate the icons referred to later in the line in any icon directory. The only additional info, in some of these feats, is a reference to an already existing spell within the framework of the OC/MotB/SoZ.

In my opinion, I just wouldn’t include these particular lines since I don’t see any description for them in any version of dialog.tlk.

a strref greater than 16,777,215 is a ref into a custom Tlk file

That is, Dialog.Tlk only goes up to 16,777,215. A custom Tlk file has to be created and associated with a Module.

Look for another .TLK file in the MageTome package. There should be one and if there isn’t there’s a mistake of some sort.

The lack of icons suggests that the feat is simply not used (the engine should/will handle it gracefully).

I’d keep the lines in until I was certain that it is an error and/or cannot be remedied … note that you can flag the feat REMOVED in Feat.2da col 60 (causing the engine to ignore it).

perhaps the author was going to create a custom.Tlk but never got around to it … idk really

1 Like

What is going to be the best way for me to compare 2 different dialog.tlk files? I can’t seem to figure out how to do it. The TlkEdit2 application will let me open the 2 different dialog.tlk files, but there doesn’t eem to be a way to compare them without doing it manually. all 220,000+ lines. From what I can tell, Yata doesn’t have the capability to open the dialog.tlk files into something coherent. Any suggestions?

yeah … persuade me to write a TLK editor JUST KIDDING

(its something id like to do but circumstances are a bit prohibitive) So, 2 ideas

  1. search around the Nwn vault for such an application (it ought work for nwn2 since the spec is the same, as far as im aware)
  2. assume Kaedrin’s entries are correct for 0…242804 and simply tack on the Tome’s entries for 242805+

FWIW Here is a list of tlk editors to try.


1 Like

So, I got K and MT combined and working together. Nearly seamless. No crashing issues yet, and I have used some new spells and feats so far. Having a problem with a spell that seems to be from the original install, but was not implemented in the game. Darkfire. It’s a 3rd level Cleric spell that adds fire damage to any weapon, yours or a companion’s. I can cast the spell all right, and the flaming effect appears on the weapon I cast it upon, but it does not show anywhere, item description or Character Sheet, that the additional damage was added. Wonder if someone could take a look? There are 2 or 3 different scripts pertaining to Darkfire. I just don’t know which is supposed to be the right one. The spell is not part of MageTome, it is simply activated in another line of the Spells.2da. If that line is needed for reference, please let me know.

if you’re talking about #548 Darkfire, the spellscript is x2_s0_darkfire

It puts an itemproperty onto a weapon … (that might be the reason it doesn’t show up on the character sheet) … unfortunately it seems to add

itemproperty ip = ItemPropertyOnHitCastSpell(127, iCasterlevel);
IPSafeAddItemProperty(oTarget, ip, fDur, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);

but #127 is actually SPELL_PHANTASMAL_KILLER

(another reason it might not show up on the character sheet)

personally I’d change the IP to

itemproperty ip = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iCasterlevel);

and rework the spellscript …

Caster Level(s): Cleric 3
Innate Level: 3
School: Evocation
Descriptor(s): Fire
Component(s): Verbal, Somatic
Range: Touch
Area of Effect / Target: Creature, Melee Weapon
Duration: 1 hr. / level
Save: None
Spell Resistance: No

This spell allows you to immolate a non-magical weapon. In addition to its
normal damage, the weapon inflicts 1d6 points of damage, +1 per two caster
levels (maximum of +10) of Fire damage. The caster can either target a specific
melee weapon in his inventory or a creature to enchant the weapon the creature
is wielding.

looking a bit further →

I think they intended to use #703 OnHitDarkfire … spellscript x2_s3_darkfire

So, the exact script I am seeing in x2_s0_darkfire that I believe you are referring to reads as such:

IPSafeAddItemProperty(oTarget, ItemPropertyOnHitCastSpell(127,nCasterLvl), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);

Am I to change the part of that line that starts “ItemPropertyOnHitCastSpell(127,nCasterLvl)” to

“ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iCasterlevel);” ?

So “IP_CONST_DAMAGETYPE_FIRE” is defined somewhere else as the damage type that is inflicted, correct? I don’t actually see where in the x2_s0_darkfire script it defines the damage amount. Is that in a different script that this one calls? Is the darkfire script simply telling the game what to do with the weapon and another script tells the game how much damage to inflict? I see the script where is says if the caster is greater than 20th level, so it only goes to a max of +10 dmg. I also see where the Extend Spell feat is taken into consideration. (Although, Persistent Spell would be cool to add to this one. I’ll find that one out for myself. I know just where to look for comparable script.) I am not actually seeing the damage amount that should be used. In the x2_s3_darkfire, I see references to how much damage to infllict, but I’m not certain how to incorporate that to the other darkfire script.

What does the following from the toolset mean?

cmi_ginc_spells.nss(1): ERROR: INVALID DECLARATION TYPE

All I did was open one of the spell scripts from Mage Tome called mt_s0_frostfingers.nss. This happens when I hit Save&Compile.
If I copy and paste the cmi.nss file from Kaedrin, then another cmi.nss file comes up in the Toolset with either the same error or something similar.
If I just bring up a spell script from Mage Tome, such as mt_s0_flamerage.nss, and then simply “x” off of it, nothing happens like that. Is there a problem that I need to resolve here? My original goal was to change the script in the mt_s0_snillocswarm.nss so that instead of the “level checker” would look for >= checks instead of <=. This affected the damage, which is supposed to start at 2d6 at 3rd level, then additional d6/2 levels to 5d6 at 9th level.

Compiler Error Messages - NWN Lexicon

But there is a better compiler available for NwN2 : Advanced Script Compiler for NWN2 | The Neverwinter Vault

that’s the idea, in practice it’s gonna be a bit more complicated

that’s an NwScript constant, defined in the NwScript.nss file

the Darkfire script applies an itemproperty to the weapon-item; that is ItemPropertyOnHitCastSpell(). So a spell is cast when the weapon strikes an opponent. The damage is determined in that 2nd spellscript : x2_s3_darkfire

    int nLevel = GetCasterLevel(OBJECT_SELF);
    int nDmg = d6() + (nLevel/2);
    effect eDmg = EffectDamage(nDmg,DAMAGE_TYPE_FIRE);

    object oTarget = GetSpellTargetObject();
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eDmg, oTarget);

(but as i said they seem to have wired up the wrong spellcast – #127 instead of #703) You could try just changing 127 to 703 then recompile and try it (the OnHit script isn’t flagged REMOVED in stock Spells.2da but check it …)

I haven’t played around with (itemproperty)OnHitCastSpell in a long time and forget what it takes to get them working exactly/properly.

you’ll need to add the Persistent bitflag to the MetaMagic col in Spells.2da (among other things)

since the script is poorly written (many are) here’s my refactor plus changing IP OnHitCastSpell to IP DamageBonus plus changing the duration to the spell-description in Dialog.Tlk →

//:: Darkfire
//:: 'x2_s0_darkfire'
//:: Copyright (c) 2001 Bioware Corp.
	Gives a melee weapon 1d6 fire damage +1 per two caster
	levels to a maximum of +10.
//:: Created By: Andrew Nobbs
//:: Created On: Dec 04, 2002
//:: Updated by Andrew Nobbs May 08, 2003
//:: 2003-07-29: Rewritten, Georg Zoeller
//:: kevL 2022.09.24 - rewritten and conformed to spell-description

#include "x2_inc_spellhook"
#include "x2_inc_itemprop"

void main()
	if (!X2PreSpellCastCode())

	object oTarget = IPGetTargetedOrEquippedMeleeWeapon();
	if (GetIsObjectValid(oTarget))
		object oPossessor = GetItemPossessor(oTarget);

		SignalEvent(oPossessor, EventSpellCastAt(OBJECT_SELF, GetSpellId(), FALSE));

		int iCasterlevel = GetCasterLevel(OBJECT_SELF);
		if (iCasterlevel > 0)
			int iDur = iCasterlevel;
			if (GetMetaMagicFeat() == METAMAGIC_EXTEND)
				iDur *= 2;

			float fDur = HoursToSeconds(iDur);

			effect eVis = EffectVisualEffect(VFX_IMP_PULSE_FIRE);
			eVis = EffectLinkEffects(EffectVisualEffect(VFX_IMP_FLAME_M), eVis);
			ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPossessor);

			effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, oPossessor, fDur);

			int iFire = iCasterlevel / 2;
			if (iFire > 10)
				iFire = 10;

			iFire += d6();

			itemproperty ipFire = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iFire);
			IPSafeAddItemProperty(oTarget, ipFire, fDur, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);

			itemproperty ipVis = ItemPropertyVisualEffect(ITEM_VISUAL_FIRE);
			IPSafeAddItemProperty(oTarget, ipVis, fDur, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
		FloatingTextStrRefOnCreature(83615, OBJECT_SELF);

bah. I see what’s to me a big problem with that: the d6 damage is not rerolled for each hit …

1 Like

When I change that part of line 27 to

ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iCasterlevel);

I get a compiler error saying “x2_s0_darkfire.nss(27): ERROR: VARIABLE DEFINED WITHOUT TYPE”

Does that mean that the IP_CONST part of that isn’t defined correctly or referred to correctly?

idk. Can’t tell without seeing the code in context

The compiler-plugin that i linked to above has much better error messages.

i can say that the script isn’t going to recognize iCasterlevel … since i changed that, was nCasterLvl – practice: choose a variable (varname) and follow it through the code to see where it’s declared/defined, how it’s used and what it’s doing

Side question: cmi_so_energywpn would be located where? This is the impact script for Weapon of Energy, which can then be declared for Fire, Acid, Air, Cold. Can’t seem to locate it. My thinking was to try and use the fire portion of that script for the darkfire spell.

Back on Darkfire - when I changed to the other spell id you gave me, 703 I think, same as before. No indication that anything changes other than the flame sfx showing up on the weapon.

UPDATE: Found it. was looking in the wrong place.

1 Like