Jump to content

Inserting text into existing descriptions


Caedwyr

Recommended Posts

There's three infobit's you'll need to read out of the spell's header, which is the only part where offsets are fixed: the location in the file where the extended headers start (which you have, it's a long at 0x64), the number of extended headers present (which you have, it's a short at 0x68), and the location in the file where the effects begin (it's a long at 0x6a - you don't have this one). Note that there isn't a field in a spell that indicates how many total effects it has, as this would be redundant. The global effects/casting features I would probably recommend skipping: there's about half a dozen such spells in the unmodded game and in every case the global effects are spurious, broken, or both. Since there's almost never a reason to use these, modders very seldom do. (Ask if you want a list of the mostly inconsequential and recondite uses global effects are suited for - it's a short list :) )

 

With these three pieces of information, you can start the first of the two loops you'll need to sort through all the existing effects. The first loop is through the extended headers, and you have this one already:

FOR ( index = 0; index < abil_num; index = index + 1 ) BEGIN
WRITE_SHORT ("%abil_off%" + 0x02 + (0x28 * "%index%")) 1 // changes ability icon location to wizard (1)

. You'll need to add two more things. First, read the short at 0x1e bytes into the extended header you're on (and you'll want to do this inside of the loop, as you'll be doing this for each extended header that exists) which tells you how many effects are associated with this particular extended header. Right now you're reading this info out of the main header, and that won't return what you need. The other read you'll have to do is the short 0x20 bytes into the extended header you're on, which tells you how many 0x30-byte-long effects you skip before you get to the effects associated with this header. Thus far you're going to want something like this:

DEFINE_PATCH_MACRO ~divine_to_arcane~ BEGIN
 WRITE_SHORT 0x1c 0x01		  // sets spell type to wizard (1)
 WRITE_LONG  0x34 "spell_level" // sets spell level
 READ_LONG   0x64 "abil_off"
 READ_SHORT  0x68 "abil_num"
 READ_LONG   0x6a "eff_off"
 FOR ( index = 0x0; index < abil_num; index = index + 0x1 ) BEGIN
WRITE_SHORT ("abil_off" + 0x02 + (0x28 * "index")) 0x1	   // changes ability icon location to wizard (1)
READ_SHORT  ("abil_off" + 0x1e + (0x28 * "index")) "eff_num" // reads the number of feature blocks
READ_SHORT  ("abil_off" + 0x20 + (0x28 * "index")) "eff_idx" // reads the index to associated effects
 END
END

 

The last part you'll need to add is a second loop inside of the first loop, so you can get to the effects where the power levels are. The variable for this loop is going to begin with the effect index we've just read, and run until it reaches the effect index plus the effect count, so that we can patch each associated effect, but once only. It's defined like so:

FOR ( index2 = eff_idx; index2 < eff_idx + eff_num; index2 += 0x1)

This time you're going to be reading for the effect offset ("eff_off") rather than the abilities/extended header offset ("abil_off")...because you're looking at effects, not extended headers :)

 

Bleh, out of time :) I'm sure someone else can fill in the blanks; in the meantime,

DEFINE_PATCH_MACRO ~divine_to_arcane~ BEGIN
 WRITE_SHORT 0x1c 0x01		  // sets spell type to wizard (1)
 WRITE_LONG  0x34 "spell_level" // sets spell level
 READ_LONG   0x64 "abil_off"
 READ_SHORT  0x68 "abil_num"
 READ_LONG   0x6a "eff_off"
 FOR ( index = 0x0; index < abil_num; index = index + 0x1 ) BEGIN
WRITE_SHORT ("abil_off" + 0x02 + (0x28 * "index")) 0x1	   // changes ability icon location to wizard (1)
READ_SHORT  ("abil_off" + 0x1e + (0x28 * "index")) "eff_num" // reads the number of feature blocks
READ_SHORT  ("abil_off" + 0x20 + (0x28 * "index")) "eff_idx" // reads the index to associated effects
FOR ( index2 = eff_idx; index2 < eff_idx + eff_num; index2 = index2 + 0x1) BEGIN
  WRITE_BYTE ("eff_off" + 0x03 + (0x30 * "index2")) "spell_level"
END
 END
END

OUTER_SET "spell_level" = 5

COPY_STUFF

 

should do it.

Link to comment

Works like a charm, though I did need to change the following line:

 

WRITE_SHORT ("abil_off" + 0x02 + (0x28 * "index")) 0x1	   // changes ability icon location to wizard (1)

to

WRITE_SHORT ("abil_off" + 0x02 + (0x28 * "index")) 0x2	   // changes ability icon location to spell (2)

 

Looks like I got the location information wrong when I wrote it the first time. I guess my earlier patch macros weren't reading that line properly since the spells were still selectable under the spell tab. Cleaning up this section also has gotten rid of a CTD bug I was having a hard time tracking down. Next up, seeing if I can get the "LAUNCH_THE_DESCRIPTION_MACRO_FLEET_AND_LET_SLIP_THE_DOGS" section to work as I want it to.

Link to comment

GET_STRREF 0x50 ~description~

 

In the massive text patching macro, the section above seems to look up and apply the patches to a section of Haer'Dalis joining dialogue instead of the desired section of the spell description. Would READ_STRREF be more appropriate here?

 

 

Edit: Tested and READ_STRREF 0x50 ~description~ is what I wanted.

Link to comment

@cmorgan: Sure, I'll throw it up there fully commented and such.

 

Ok, the last macro I want to create, is one that will make sure the Level: # line in the spell description is changed correctly.

 

I currently have:

 

// Change the Level: # to the correct level number
DEFINE_PATCH_MACRO ~Level_number_english~ BEGIN

 REPLACE_TEXTUALLY ~^Level: +[0-9]$~ ~^Level: +"%spell_level%"

END


OUTER_SET "spell_level" = 1

COPY_EXISTING 	~foo123.spl~	~override/CA#DS123.spl~	/*foo spell name*/

 

I'd like to take the OUTER_SET "spell_level" value and stick whatever number I have there into the text, but I don't know if I can do this, or what the right syntax might be.

 

My current patching macro system, thanks to Nythun, works just fine, and I'd assume I'd launch this patch macro along with the other text changing ones

 

COPY_EXISTING 	~sppr103.spl~	~override/CA#DS103.spl~	/*cure light wounds*/
	~sppr104.spl~	~override/CA#DS104.spl~	/*detect evil*/
	~sppr105.spl~	~override/CA#DS105.spl~	/*entangle*/
	~sppr109.spl~	~override/CA#DS109.spl~	/*sanctuary*/
	~sppr110.spl~	~override/CA#DS110.spl~	/*shillelagh*/
 PATCH_IF SOURCE_SIZE > 0x71 THEN BEGIN
LAUNCH_PATCH_MACRO ~divine_to_arcane~		/*change to level 1 wizard spells*/
	READ_LONG 0x50 "strref"
	PATCH_IF ("strref" > 0x00 AND "strref" < 0x7fffffff) THEN BEGIN
	  READ_STRREF 0x50 ~description~
	  INNER_PATCH_SAVE ~description~ ~%description%~ BEGIN
		LAUNCH_PATCH_MACRO ~priest_druid_english~
		LAUNCH_PATCH_MACRO ~sphere_removal_english~
		LAUNCH_PATCH_MACRO ~Level_number_english~
	  END
	  SAY_EVALUATED 0x50 ~%description%~
	END
  END

 

At the moment, the multi-language support of the text patching macros isn't operational/existing, but I'll hold off on that section and all the assorted sub-loops and spaghetti code until I get everything working as I want in my native language.

 

So, the question. Can I use the OUTER_SET "spell_level" = # value in a section of text, inputing the # value as part of a patched text block?

Link to comment

There's some stuff on string concatenation I requested some versions of WeiDU ago. Dunno if that would help or if it ever made it in the latest WeiDUs but there's probably some hacky workaround - here's the link.

 

As for the multi-language text replacing stuff, as usual, Nythrun has some wacky code (probably also in the latest Level 1 NPC mod).

Link to comment

Ok, another thing I'm unclear on:

DEFINE_PATCH_MACRO ~sphere_removal_english~ BEGIN

 REPLACE_TEXTUALLY ~[ %lnl%%mnl%%wnl%]+Sphere: +[A-Za-z]+ *~ ~~

END

 

Is supposed to remove the entire line regarding spheres from the spell description. However, it seems to choke when the sphere description fits the following cases:

 

Sphere: Combat, Plant

Sphere: Elemental (Fire)

Sphere: Protection, Elemental (Fire)

 

So, this appears to fit the pattern of failure on

 

Sphere: Word1, Word2

Sphere: Word1 (Word2)

Sphere: Word1, Word2 (Word3)

 

Since the regexp doesn't seem to catch anything after the , or ( I'm guessing it would also choke on

 

Sphere: Guardian/ Creation

 

And miss anything after the /

 

I've tried using a $ to indicate end of line is where the section of text to be replaced should stop being read, but it doesn't seem to do anything:

REPLACE_TEXTUALLY ~[ %lnl%%mnl%%wnl%]+Sphere: +[A-Za-z]+ $~ ~~

 

Looking at the list of constructs for regexp, I also wonder where some of the %lnl%%mnl% etc type of language comes from, as it isn't shown on the weidu entry for regexp. Also, several constructs which from the explanation that is given should work, don't work. For example, I could also see using

 

. matches any character except newline
At the end of the sphere replacement section, since a newline is what I want to stop at.

 

From what you've said Miloch, it sounds like I'd be best off creating 9 patch macros for Level: 1 through to Level: 9. Something like:

 

DEFINE_PATCH_MACRO ~level_1_english~ BEGIN

 REPLACE_TEXTUALLY CASE_SENSITIVE ~[ %lnl%%mnl%%wnl%]+Level: +[0-9]+ *~ ~"Level: 1"~
END

 

Edit:

 

In the end, since I couldn't get it done elegantly, I just brute forced the Level: patch, and used the following:

 

// Change the Level: # to Level: 1
DEFINE_PATCH_MACRO ~level_1_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 1~

END


// Change the Level: # to Level: 2
DEFINE_PATCH_MACRO ~level_2_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 2~

END


// Change the Level: # to Level: 3
DEFINE_PATCH_MACRO ~level_3_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 3~

END


// Change the Level: # to Level: 4
DEFINE_PATCH_MACRO ~level_4_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 4~

END


// Change the Level: # to Level: 5
DEFINE_PATCH_MACRO ~level_5_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 5~

END


// Change the Level: # to Level: 6
DEFINE_PATCH_MACRO ~level_6_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 6~

END


// Change the Level: # to Level: 7
DEFINE_PATCH_MACRO ~level_7_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 7~

END


// Change the Level: # to Level: 8
DEFINE_PATCH_MACRO ~level_8_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 8~

END


// Change the Level: # to Level: 9
DEFINE_PATCH_MACRO ~level_9_english~ BEGIN

 REPLACE_TEXTUALLY ~Level: +[0-9]*~ ~Level: 9~

END

And just ran each patch macro at the appropriate time. Ugly, but it works.

Link to comment

If you need WeiDU to possibly match additional characters, you can just add them in. :)

 

DEFINE_PATCH_MACRO ~sphere_removal_english~ BEGIN

 REPLACE_TEXTUALLY ~[ %lnl%%mnl%%wnl%]+Sphere: +[A-Za-z ()/,]+ *~ ~~

END

 

I'd do the level replacement thusly:

 

DEFINE_PATCH_MACRO ~Level_number_english~ BEGIN

 REPLACE_TEXTUALLY ~^Level: +[0-9]~ ~Level: %spell_level%~

END

 

Remember that you won't be using regexp reserved characters on the right hand side of a regexp match: that text is exactly how you want it and doesn't need to match a range of possibilities.

 

Nice catch on GET_STRREF, I needs some coffee.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...