Gort Posted October 19, 2007 Share Posted October 19, 2007 Do I need the repeated COPY_EXISTING blocks for each time I want to make a batch of changes to the spells.. no. As for the rest - it's getting complicated, I'd just ry it first and see the results=) Link to comment
Caedwyr Posted October 19, 2007 Author Share Posted October 19, 2007 I did. It didn't work (I don't have all the code I need to make it work, and wasn't able to figure out those last bits from the existing code). Hence my call for help Link to comment
Nythrun Posted October 23, 2007 Share Posted October 23, 2007 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
Caedwyr Posted October 27, 2007 Author Share Posted October 27, 2007 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
cmorgan Posted October 27, 2007 Share Posted October 27, 2007 Hey, when you get this rockin', can you please post the final working code up on the Wikki, updating that Code Bank? I think the materials I clipped are the "in progress", not the "working code" Link to comment
Caedwyr Posted October 27, 2007 Author Share Posted October 27, 2007 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
Caedwyr Posted October 27, 2007 Author Share Posted October 27, 2007 @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
Miloch Posted October 27, 2007 Share Posted October 27, 2007 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
Caedwyr Posted October 28, 2007 Author Share Posted October 28, 2007 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, PlantSphere: Elemental (Fire) Sphere: Protection, Elemental (Fire) So, this appears to fit the pattern of failure on Sphere: Word1, Word2Sphere: 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
Nythrun Posted October 28, 2007 Share Posted October 28, 2007 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
Caedwyr Posted October 28, 2007 Author Share Posted October 28, 2007 Yay, it all works perfectly. Thanks for the coding help. Is there a spot I can look up additional values to be used in regexp like the %lnl% or %mnl% or %wnl% that is used in the above code? Link to comment
Guest erik Posted October 28, 2007 Share Posted October 28, 2007 Sure. Look in that nice lib/extra_regexp_vars.tpa file you grabbed earlier . And http://www.regular-expressions.info/tutorial.html has far more info than you can digest easily, if you feel like doing crazy things. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.