Jump to content


Photo

Help with first mod ideas


  • Please log in to reply
40 replies to this topic

#21 Gwendolyne

Gwendolyne
  • Administrator
  • 1016 posts

Posted 21 May 2019 - 02:44 PM

Here is the routine. All you have to do is replace the following line

 

ACTION_FOR_EACH spell IN sppr101 sppr102 sppr103 BEGIN

 

with the spells you are interested in.

Attached Files


Edited by Gwendolyne, 21 May 2019 - 02:45 PM.

CARPE DIEM ....
 

In progress : Menace sur le Royaume de Diamant Éternel there.


#22 Alonso

Alonso
  • Member
  • 35 posts

Posted 22 May 2019 - 08:12 AM

Thank you, Gwendolyne, that worked like a charm! :new_thumbs:
 
In order to streamline my workflow I modified a bit that routine to make it generate also the spell file name, apart from the spell name and the spell description. I attach the generated file to illustrate what I'm doing. My goal is to use just string references, rather than string literals, in my tp2 file. This is what I want to do:

 

COPY_EXISTING @100001 ~override~
SAY NAME1 @100002
SAY UNIDENTIFIED_DESC @100003

 

Here, @100001 would be something like SPWI201.spl. However, it looks like doing this breaks some syntax rule, WeiDU complains about that @100001 reference. I attach the debug file with the error. What am I doing wrong?

Attached Files


Edited by Alonso, 22 May 2019 - 08:12 AM.


#23 Mike1072

Mike1072
  • Modder
  • 539 posts

Posted 22 May 2019 - 04:48 PM

You should only use .tra references for strings that need to be translated to different languages.  Filenames don't need to be translated.



#24 Gwendolyne

Gwendolyne
  • Administrator
  • 1016 posts

Posted 22 May 2019 - 05:12 PM

Furthermore I really think it would be a waste of time.

Anyway, try this

 

 

OUTER_FOR (i = 100001 ; i < 102432 ; ++i) BEGIN
    OUTER_SPRINT spell (AT i)
    OUTER_SET name = i + 1
    OUTER_SET desc = i + 2
    ACTION_IF (FILE_EXISTS_IN_GAME ~%spell%~) BEGIN
        COPY_EXISTING ~%spell%~ ~override~
        SAY NAME1 (AT name)
        SAY UNIDENTIFIED_DESC (AT desc)
        BUT_ONLY
    END
END

One again, I never did that before and I did not test it. ;)


Edited by Gwendolyne, 22 May 2019 - 05:13 PM.

CARPE DIEM ....
 

In progress : Menace sur le Royaume de Diamant Éternel there.


#25 Alonso

Alonso
  • Member
  • 35 posts

Posted 27 May 2019 - 10:24 AM

Thanks again, Gwendolyne, that worked very well and the mod is essentially finished now. I ran into a minor issue, though: I removed some of the entries in my list of spells, which means that there is no longer a string for every single reference checked in the loop. Now WeiDU complains that it expected a string for one of the empty references. I guess fixing the code to deal with that should be very straightforward, a simple case of skipping the loop when the text references are empty. But with my almost non existent knowledge of WeiDU I can't figure out how to do it. Can you give me a clue?

Attached Files



#26 Gwendolyne

Gwendolyne
  • Administrator
  • 1016 posts

Posted 30 May 2019 - 01:34 AM

One again, I never used this WeiDU command, but try this:

 

OUTER_FOR (i = 100001 ; i < 102432 ; ++i) BEGIN
    ACTION_IF (TRA_ENTRY_EXISTS("i")) BEGIN
        OUTER_SPRINT spell (AT %i%)
        OUTER_SET name = i + 1
        OUTER_SET desc = i + 2
        ACTION_IF (FILE_EXISTS_IN_GAME ~%spell%~) BEGIN
            COPY_EXISTING ~%spell%~ ~override~
            SAY NAME1 (AT name)
            SAY UNIDENTIFIED_DESC (AT desc)
            BUT_ONLY
        END
    END
END

 

Of course, I assume you have loaded the tra file. ;)

 

Edited by Gwendolyne, 30 May 2019 - 01:34 AM.

CARPE DIEM ....
 

In progress : Menace sur le Royaume de Diamant Éternel there.


#27 Alonso

Alonso
  • Member
  • 35 posts

Posted 03 June 2019 - 03:43 PM

Your intuition is very good, Gwendolyne, that also worked :)

 

Looks like I have a fully functional mod now. I attach it to this post in case someone wants to try it. If you do try it, though, bear in mind that I'm still changing some descriptions. In that regard the mod is still incomplete, so you'll find mistakes and inconsistencies in the text.

 

As I work with spell descriptions I've realized that many of them are repeated. For instances, the files cdstaf12.spl, OHBWI308.spl, SPCL722.spl, SPDR301.spl, SPIN579.spl, SPIN714.spl, SPWI002.spl, SPWI308.spl, SPWI399.spl and SPWI997.spl are all copies of Lightning Bolt. That means that every time I change a bit of the description of Lightning Bolt I have to repeat that change ten times. That happens with hundreds of spells. Given the amount of changes I'm doing, that means an awful lot of repeated work. Therefore, even though the mod is perfectly functional as it is, I'd like to modify it to remove the repeated descriptions, so that when I change a description I only have to do it once.

 

That would be almost trivial in a language I'm familiar with, like Java, but in WeiDU I've no idea of how to do it. It would involve two steps:

 

1. Modify setup.tra: For each set of duplicated name/description pairs remove all the duplication and leave only one unique name/description pair. Associate each of these pairs with the names of the files to which they belong. This association can be done in several ways. I think the easiest would be to use some sort of numeric pattern in the string ids. I would do this manually.

 

2. Modify the tp2 file: Adapt the code to the modifications done in setup.tra in the previous step. This probably involves using arrays of strings (or the equivalent data structure in WeiDU) to handle the group of file names associated to each name/description pair.

 

I'm pretty sure it should be quite easy to do, 10-12 lines of code max. Any tips on how to go about this?

Attached Files


Edited by Alonso, 03 June 2019 - 03:44 PM.


#28 Mike1072

Mike1072
  • Modder
  • 539 posts

Posted 03 June 2019 - 04:27 PM

Storing filenames in .tra files is a strange way of doing things.

To match filenames with spell names and spell descriptions, I'd recommend either an associative array in your .tp2 code or a separate .2da file.  I'd probably go with a .2da file.
 
AlonsosMod/spells.2da:
         NAME    DESC
BALSHLD  100002  100003
BALSHLD2 100005  100006
 
AlonsosMod.tp2:
COPY - ~AlonsosMod/spells.2da~ ~AlonsosMod/spells.2da~
  READ_2DA_ENTRIES_NOW ~r2en_spells~ 3
  FOR (row = 0; row < r2en_spells; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 0 resource
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 1 name
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 2 desc
    
    INNER_ACTION BEGIN
      ACTION_IF (FILE_EXISTS_IN_GAME ~%resource%.spl~) BEGIN
        COPY_EXISTING ~%resource%.spl~ ~override~
          SAY NAME1 (AT name)
          SAY UNIDENTIFIED_DESC (AT desc)
          BUT_ONLY
      END
    END
  END

Edited by Mike1072, 03 June 2019 - 04:28 PM.


#29 Gwendolyne

Gwendolyne
  • Administrator
  • 1016 posts

Posted 03 June 2019 - 11:14 PM

I second Mike's advice at 200 %. That's what I had in mind since the beginning (an array, not a 2da file, but nevermind).

 

But as you wanted to experiment this way of coding, I found interesting to write stuff I never did before. ;)


CARPE DIEM ....
 

In progress : Menace sur le Royaume de Diamant Éternel there.


#30 Alonso

Alonso
  • Member
  • 35 posts

Posted 07 June 2019 - 02:51 PM

Thank you, Mike and Gwendolyne. I've revamped the whole mod following your suggestions. However, for some reason the tp2 code doesn't work. I guess it must be some very basic syntax problem, but in this case I just cannot figure out what it might be. I attach the mod again so you can check it.

 

I feel a bit silly asking basic syntax questions like this one, but so far I haven't managed to find any documentation that I can understand. I've tried the WeiDU readme several times, but it looks like it assumes that the reader is a BG modding veteran and it gives for granted many concepts that are unknown for me.

Attached Files


Edited by Alonso, 07 June 2019 - 02:52 PM.


#31 Mike1072

Mike1072
  • Modder
  • 539 posts

Posted 07 June 2019 - 04:01 PM

You need to include a component declaration (e.g. BEGIN ~Name of Component~), after your LANGUAGE statement.

There are also several errors in your .tra file. You are missing the equals sign between the reference and string (e.g. @100650 = ~Abazigal Shockwave~) and there is one .tra reference with no associated string (@100350).

#32 Alonso

Alonso
  • Member
  • 35 posts

Posted 08 June 2019 - 02:01 PM

Thank you, Mike, I corrected that and the mod works again (and it's much easier to maintain now).

 

Once again the mod is fully functional, but it is still incomplete: It changes the spell descriptions for spells, but not for the scrolls used to learn those spells. In order to update the scroll descriptions the first step is to extract the descriptions of the scrolls, just like we did before with spells. For that we used Gwendolyne's description extractor routine. In order to do so I'm modifying Gwendolyne's routine, editing the block that processes spells to make it process scrolls instead.

 

In this block I want to start by checking what kind of item is in each item file. If it is not a scroll, I ignore it and move on to the next item. Apparently item files store their item types in the "General name" field, so I need to read that field and check its contents. I'm stuck there because I don't know the syntax. This is my rough attempt, which WeiDU doesn't like, of course:

 

ACTION_FOR_EACH item IN ABAZRING ABISRED1 ACIDBL ACIDMIST ACIDOOZ1 ACIDOOZ2 ACIDOOZ3 BEGIN

    ACTION_IF (FILE_EXISTS_IN_GAME ~%item%.itm~) BEGIN

        COPY_EXISTING ~%item%.itm~ ~override~
            READ_LONG 0x08 item_type
            READ_LONG 0x50 scroll_description
            READ_LONG 0x?? scroll_name  // How do I figure out the offset for the scroll name (identified name)?
            PATCH_IF (scroll_description > 0 AND item_type > 0 AND scroll_name > 0) BEGIN   // Syntax?
                GET_STRREF %item_type% str_item_type
                PATCH_IF (str_item_type == "Scroll") BEGIN // Syntax?
                    GET_STRREF %scroll_name% str_name
                    SPRINT str_name EVAL "@%iter% = ~%str_name%~%WNL%"
                    SET iter = iter + 1
                    GET_STRREF %scroll_description% str_desc
                    SPRINT str_desc EVAL "@%iter% = ~%str_desc%~%WNL%"
                    SPRINT output EVAL "%output%%WNL%%item%%WNL%%str_name%%str_desc%"
                    SET iter = iter + 1
                END
            END
        BUT_ONLY
    END
END

 

The comments mark the problematic lines, the lines where I'm obviously doing something wrong. Any tips on how to make this work?


Edited by Alonso, 08 June 2019 - 02:06 PM.


#33 Mike1072

Mike1072
  • Modder
  • 539 posts

Posted 08 June 2019 - 11:24 PM

You can check the IESDP for file offsets.  You can also enable the setting 'View Hex Offets' in Near Infinity, which will display the offset next to each field on the Edit tab.

 

The unidentified name is at offset 0x08.

 

If you want to read the string directly, you can use READ_STRREF.  It's equivalent to READ_LONG plus GET_STRREF.

 

To do a string comparison, you can't use ==.  You have to use one of the string comparison operators, like STRING_EQUAL or STRING_COMPARE.  You also have to wrap your variable name in quotes and use percent signs to evaluate it, to ensure you are comparing the variable's value and not the variable's name.

 

Be warned that STRING_EQUAL (sensibly) returns 1 when there is a match, but the STRING_COMPARE and STRING_MATCHES_REGEXP variants return 0 when there is a match. These two expressions are equivalent:

(~%str_item_type%~ STRING_COMPARE ~Scroll~ == 0)
(~%str_item_type%~ STRING_EQUAL ~Scroll~)

Edited by Mike1072, 08 June 2019 - 11:28 PM.


#34 Alonso

Alonso
  • Member
  • 35 posts

Posted 13 June 2019 - 04:56 PM

Thank you, Mike, that worked. It took me hours of editing, but I finally have my tra and 2da files updated with the info about scrolls. I could use two 2da tables for this, but I thought it would be more sensible and easier to maintain to keep everything in a single table. In order to do this, though, I had to include the file extensions (spl or itm) in the 2da file, for otherwise there would be name conflicts. So I added some logic to my tp2 file to distinguish between scrolls and spells:

 

COPY - ~AlonsosMod/spells.2da~ ~AlonsosMod/spells.2da~
READ_2DA_ENTRIES_NOW ~r2en_spells~ 3
FOR (row = 0; row < r2en_spells; row += 1) BEGIN
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 0 resource
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 1 name
    READ_2DA_ENTRY_FORMER ~r2en_spells~ row 2 description
    
    INNER_ACTION BEGIN
        ACTION_IF (FILE_EXISTS_IN_GAME ~%resource%~) BEGIN
            COPY_EXISTING ~%resource%~ ~override~
            ACTION_IF (~%resource%~ STRING_CONTAINS_REGEXP ~spl~) BEGIN
                SAY NAME1 (AT name)
                SAY UNIDENTIFIED_DESC (AT description)
            END
            ACTION_IF (~%resource%~ STRING_CONTAINS_REGEXP ~itm~) BEGIN
                SAY NAME1 (AT name)
                SAY DESC (AT description)
            END
        BUT_ONLY
    END
END

 

WeiDU complained about that, though, so I must have broken some syntax rule there. Can you tell what the problem is?


Edited by Alonso, 13 June 2019 - 05:10 PM.


#35 Mike1072

Mike1072
  • Modder
  • 539 posts

Posted 13 June 2019 - 06:22 PM

Your patches for the COPY_EXISTING (SAY and BUT_ONLY) aren't executing on it because ACTION_IF starts a new action.

 

You need to use PATCH_IF there instead.

 

I'd also update the regexp check to be a little more robust and to toss in the comparison with its matching return value, as mentioned previously:

(~%resource%~ STRING_MATCHES_REGEXP ~.+\.spl~ == 0)


#36 Alonso

Alonso
  • Member
  • 35 posts

Posted 16 June 2019 - 07:53 PM

Thanks, Mike, that fixed it.

 

And my mod is finished now!  :cheers:

 

Who wants to be my guinea pig and try it in their computer?

Attached Files



#37 Alonso

Alonso
  • Member
  • 35 posts

Posted 26 June 2019 - 04:00 PM

OK, not many candidates to be my guinea pig here :P. Maybe I need a bigger audience. I'd like to publish this mod and make it available for the community, but I'm not sure of what is the best place to publish it. Any suggestions?



#38 jastey

jastey
  • Administrator
  • 3218 posts

Posted 26 June 2019 - 09:04 PM

You can always open a thread in the general modding forums first. The greatest audience is probably at BeamDog's, the mod is best also compatible with the EE games then, though.



#39 Alonso

Alonso
  • Member
  • 35 posts

Posted 27 June 2019 - 01:33 AM

That sounds good. Quick silly question: So far I've only tried the mod in BG2, right now I don't even have BG1 installed, so I guess I should publish it in the BG2 modding subforum of Beamdog rather than in the general modding subforum, right?



#40 jastey

jastey
  • Administrator
  • 3218 posts

Posted 27 June 2019 - 01:36 AM

Would it be compatible with BG:EE, as well?

It's a good question. I'd say if it's meant to be compatible with both BG1 and BGII, the General Modding forum is probably more appropriate since otherwise you'd exclude one of the games, and opening two threads is not an option.