Jump to content

cmorgan

Recommended Posts

We have found out in other threads that some "awareness" of things presented in mod-added content can be scripted directly into your mod without any troubles. For example, Aran can reference any existing DV, so !Inparty("mynpc") checks will not fail on install, and the strings referenced will be available if the mod-added NPC shows up in-game later on, regardless of install order.

 

This works with globals, too, so in other threads progress to certain points in other mods allows "side talk" - not directly bantering with an NPC or using an item, but acknowledging their presence, either by use of <PLAYER3> tokens in dialog, or with direct checks for globals and DVs. Any way we cut this, we are still talking about having Aran (or your NPC) having some of his talks and paths refer to outside events created by other mods, and being able to install that content as part of Aran's mod. The presence of the global variable or DV being active in a game then "activates" that content passively - no need for messing about with other folk's files, etc.

 

We have taken this a step further with looking at player responses by mod-added kit, in the thread regarding "what happens when..."; here, we found that when Divine Remix was not installed and we wanted to reference the kits added, we had a problem. Compiling a reference to a non-pre-existing kit left the engine with only one choice, "0". Which caused all sorts of problems if DR was not installed, and even worse had no "repair" effect on installed files - unlike GTIMES.IDS or other "engine lookup by handle" things, KIT.IDS references have to be built *after* the kits have been placed on an install, because of the way the files are created and referenced.

 

We get around that by creating an independent "patch", ARAN_AWARE, which so far just swaps "dummy" variables that will compile at install but never be triggered (a very old idea in terms of shutting down content, the equivalent of adding False() to a trigger so a dialog will never play, except reversing a False() is a PITA, whereas setting a never-reached variable to 1 is a much more compatibility - friendly way of coding it - a SetGlobal, and the original block plays.) with the wanted content using good old fashioned REPLACE_TEXTUALLY operation:

/* HEARTWARDER OF SUNE - Sune Firehair, Lady Firehair : Global("c-heartwarder","GLOBAL",1) */
ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN  
ACTION_FOR_EACH ~dialog_file~ IN 	~c-aranj.dlg~
									~c-aranp.dlg~
									~c-arn25j.dlg~
						   			~c-arn25a.dlg~ BEGIN
	ACTION_IF FILE_EXISTS_IN_GAME ~%dialog_file%~ THEN BEGIN
		COPY_EXISTING ~%dialog_file%~ ~override~
			DECOMPILE_DLG_TO_D
				REPLACE_TEXTUALLY ~Global("c-heartwarder","GLOBAL",1)~ ~Kit(Player1,NMSUNE) OR(6) Class(Player1,CLERIC) Class(Player1,FIGHTER_CLERIC) Class(Player1,CLERIC_MAGE) Class(Player1,CLERIC_THIEF) Class(Player1,FIGHTER_MAGE_CLERIC) Class(Player1,CLERIC_RANGER)~
				REPLACE_TEXTUALLY ~Global("c-aranheartwarder","GLOBAL",1)~ ~Kit("c-aran",NMSUNE) OR(6) Class("c-aran",CLERIC) Class("c-aran",FIGHTER_CLERIC) Class("c-aran",CLERIC_MAGE) Class("c-aran",CLERIC_THIEF) Class("c-aran",FIGHTER_MAGE_CLERIC) Class("c-aran",CLERIC_RANGER)~					
			COMPILE_D_TO_DLG
		BUT_ONLY_IF_IT_CHANGES
	END
END	  
END					

 

So far so good. We know that using this after Divine Remix is installed means that the correct reference gets swapped into Aran's files. If a player installs the "patch" mod, the new content is activated. If they don't their game still works, and there is no problem.

 

So, what else would need this kind of handling?

Link to comment

I_C_T'ing into mod added content

 

One of the toughest things to work out is how to add dialog into a "floating" state. A mod's strings are not fixed, like the original game resources, so there is no way to do something like

 

I_C_T BANOMEN 1243
== C-ARANB IF ~InParty("c-aran") InMyArea("c-aran") !StateCheck("c-aran",CD_STATE_NOTVALID)~ THEN ~[ARAN] What in th' nine hells do you be blabberin' on about?~
== BANOMEN IF ~InParty("c-aran") InMyArea("c-aran") !StateCheck("c-aran",CD_STATE_NOTVALID)~ THEN ~[ANOMEN] I was not talking to you. Go sharpen your sword. At least that can be polished, unlike your poor manners and common speech.~
END

...because Laufey's Edwin vs. Anomen banters are in his Edwin Romance mod, and that could be put on several different types of install or in different orders, so that 1243 could be 967, or 3460, or 5890, or basically any state number higher than the original dialogs.

 

Crossmod handles this using STATE_WHICH_SAYS.

 

 

STATE_WHICH_SAYS

 

To see how this works, we go back to the beginning. Every state in a dialog file has a number, and a weight. All the original dialogs are set up and stable, as most folks want to be able to I_C_T into them, and such - it is the material added on top of the original states that "float" based on install order, what has been added to the base vanilla install by fixpacks/tweakpacks/"before all other mods" mods. So when trying to build content that actually interjects into other mods, instead of classical

 

I_C_T DIALOGFILE known_state added_state's_name

 

we now have

 

I_C_T DIALOGFILE unknown_state added_state's_name

 

What STATE_WHICH_SAYS does is work as a reverse lookup, checking a string against the existing states, and pulling the corresponding number from the local install.

 

 

Let's take an example, and play with it. In ERSoA107, Laufey's Edwin Romance for SoA, Edwin and Anomen have some... difficulties. Given the relative mutual distaste for eachother, all three being wildly different NPCs, it is likely that a sideplay between Edwin and Anomen might elicit a comment by Aran. Not much of one - no one with any brains at all is going to get in between two powerful potential rivals fighting it out and potentially ticking off <CHARNAME>. But a light one.

 

Here is Laufey's banter, as it plays in-game:

 

EDWIN ~Logically you couldn't have become anything else. There are only so many professions available for a man with a brain the size of a small pea and the social graces of a mollusc.~

ANOMEN ~*You* would lecture *me* on social graces? The man who spews insults wherever he goes, like a dragon breathes fire?~

EDWIN ~*My* insults are intelligent, purposeful and carefully considered. *Yours* are the random and clumsy mistakes of an oaf who puts his foot in his mouth often enough to have toe-fungus growing on his fat tongue.~

ANOMEN ~Speaking of feet...~

EDWIN ~OW! My *foot*! You *stepped* on it! You did that on *purpose*!~

ANOMEN ~I thought you wanted me to be more purposeful? And now my lady, let us return to our so sadly interrupted conversation. I was wondering if I had told you how I became a priest?~

[PLAYER_RESPONSE_1] ~No, but I'd like to hear the tale.~ GOTO 174

[PLAYER_RESPONSE_2] ~No, and I've no interest in hearing about it.~ GOTO 179

[PLAYER_RESPONSE_3] ~I thought you were trying to become a knight.~ GOTO 180

 

In code, it looks like this:

ERANOMEN.D

CHAIN BEDWIN ANO_EDWIN2
  @3
== BANOMEN
  @4
== BEDWIN
  @5
== BANOMEN
  @6
== BEDWIN
  @7
END BANOMEN 173_E

APPEND BANOMEN

IF ~~ THEN BEGIN 173_E
 SAY @16
 IF ~~ THEN REPLY #35254 /* ~No, but I'd like to hear the tale.~ */ GOTO 174
 IF ~~ THEN REPLY #35255 /* ~No, and I've no interest in hearing about it.~ */ GOTO 179
 IF ~~ THEN REPLY #35256 /* ~I thought you were trying to become a knight.~ */ GOTO 180
END

END

 

So Laufey here has done some smart coding, too - he has used stable existing strings #35254, #35255, #35256, saving his translators work, recreating the original choices, and reducing his addition to dialog.tlk. But more importantly, he has "TRA-IFIED" the mod (set up the mod to have a separate file of strings, referenced by weidu at install time, so that a line in code reads @3 and then weidu can look up @3 in the matching .tra file and swap in the string). That gives us a way of checking for a relatively stable resource, because one a mod has been traified and headed out to translators, it is unlikely to make big jumps in terms of code. It might... but it is highly unlikely. So we can look at the corresponding .tra file and see what this resolves to;

 

ERANOMEN.TRA

@3	= ~Logically you couldn't have become anything else. There are only so many professions available for a man with a brain the size of a small pea and the social graces of a mollusc.~
@4	= ~*You* would lecture *me* on social graces? The man who spews insults wherever he goes, like a dragon breathes fire?~
@5	= ~*My* insults are intelligent, purposeful and carefully considered. *Yours* are the random and clumsy mistakes of an oaf who puts his foot in his mouth often enough to have toe-fungus growing on his fat tongue.~
@6	= ~Speaking of feet...~
@7	= ~OW! My *foot*! You *stepped* on it! You did that on *purpose*!~

@16   = ~I thought you wanted me to be more purposeful? And now my lady, let us return to our so sadly interrupted conversation. I was wondering if I had told you how I became a priest?~

 

Insert Aran Here

OK, what if I wanted to add a byplay with Aran? It might look something like this:

 

 

EDWIN ~Logically you couldn't have become anything else. There are only so many professions available for a man with a brain the size of a small pea and the social graces of a mollusc.~

[ARAN] Do you be talkin' about th' size o' his brain, or his...

[EDWIN] Silence, moronic hireling. Even this pile of excrement's lack of sophistication and social manners is preferable to your clumsy common speech.~

ANOMEN ~*You* would lecture *me* on social graces? The man who spews insults wherever he goes, like a dragon breathes fire?~

EDWIN ~*My* insults are intelligent, purposeful and carefully considered. *Yours* are the random and clumsy mistakes of an oaf who puts his foot in his mouth often enough to have toe-fungus growing on his fat tongue.~

[ARAN] Sune's Left Hand, I am gettin' th' hells away from this before I go puttin' my foot in my mouth!

ANOMEN ~Speaking of feet...~

EDWIN ~OW! My *foot*! You *stepped* on it! You did that on *purpose*!~

ANOMEN ~I thought you wanted me to be more purposeful? And now my lady, let us return to our so sadly interrupted conversation. I was wondering if I had told you how I became a priest?~

[PLAYER_RESPONSE_1] ~No, but I'd like to hear the tale.~ GOTO 174

[PLAYER_RESPONSE_2] ~No, and I've no interest in hearing about it.~ GOTO 179

[PLAYER_RESPONSE_3] ~I thought you were trying to become a knight.~ GOTO 180

 

So, how do we do that?

 

First, we figure out what the .tra reference is, by checking in the .tra file and making a note of what file it is in. Then we set up STATE_WHICH_SAYS to look for it. Then we either create a dialog file on the fly, using "inlined' files or have a pre-existing I_C_T we want to use, with the state number variable-ized. In short, we have something that roughhly (pre-testing) looks like this:

 

/* in ERANOMEN.TRA, ERSoA107/edwin/tra/english/ERANOMEN.TRA 
@3	= ~Logically you couldn't have become anything else. There are only so many professions available for a man with a brain the size of a small pea and the social graces of a mollusc.~
*/

ACTION_IF FILE_EXISTS_IN_GAME ~<<LAUFLEY FILE PLACEHOLDER>>~ THEN BEGIN
 PRINT ~Defining Laufey's Edwin Romance Anomen Conflict State.~
 OUTER_SET actual_conflict_state = (STATE_WHICH_SAYS 3 IN ~ersoa107/edwin/tra/%s/eranomen.tra~ FROM ~BEDWIN~)
 PRINT ~Completed... moving on.~

 /* Aran interjection into Laufey's Edwin Romance */

<<<<<<<< aranw_aware/inlined/laufeysoa.d
I_C_T BEDWIN %actual_conflict_state% c-aranedwinanomen1
== C-ARANB IF ~InParty("c-aran") !StateCheck("c-aran",CD_STATE_NOTVALID)~ THEN ~[ARAN] Do you be talkin' about th' size o' his brain, or his....~
== BEDWIN IF ~InParty("c-aran") !StateCheck("c-aran",CD_STATE_NOTVALID)~ THEN ~[EDWIN] Silence, moronic hireling. Even this pile of excrement's lack of sophistication and social manners is preferable to your clumsy common speech.~
END
>>>>>>>>

 COMPILE EVALUATE_BUFFER ~aranw_aware/inlined/laufeysoa.d~
END

 

This thought experiment now needs some cleanup before we test it out. Let's recheck first -

 

ACTION_IF FILE_EXISTS_IN_GAME ~<<LAUFEY FILE PLACEHOLDER>>~ THEN BEGIN

 

....so we need a file unique to Laufey's mod, so that this acts only if the mod is installed before aran_aware runs.

 

PRINT ~Defining Laufey's Edwin Romance Anomen Conflict State.~

 

...so we have printed feedback

 

OUTER_SET actual_conflict_state = (STATE_WHICH_SAYS 3 IN ~ersoa107/edwin/tra/%s/eranomen.tra~ FROM ~BEDWIN~)

 

... so we check this against the weidu docs:

By the way, you can do this without .tra, but it is far riskier, as you then have to maintain every single typo repair, change, etc, and multilingual support within your own mod. Far better to link to the most up-to-date source using .tra. We are using usage #2, below, where strings have been traified already, rather than #1.

I.

STATE_WHICH_SAYS text FROM String String must be an in-game or in-override .dlg file. Returns:

 

1. Fails the installation if it can’t evaluate the text (an @x reference out of bounds)

2. -3 if the text is not currently in the tlk or in the list of strings to add

3. -2 if the text is spoken (= SAY ~Foo~) at least twice in the file String

4. -1 if the text is never spoken in the file String

 

Otherwise it returns the number of the state in which text is spoken in the file String. @x references are taken from the loaded TRA files (the ones defined in the Language part).

 

II.

STATE_WHICH_SAYS value IN String1 FROM String2 As above, except that @x references are taken from the String1 tra file. In particular, one %s in String1 is expanded to the list of directories; for example (as of Sola v102), solarom/%s/epilogue.tra would match

 

solarom/american/epilogue.tra

solarom/french/epilogue.tra

solarom/german/epilogue.tra

solarom/italian/epilogue.tra

solarom/polski/epilogue.tra

solarom/portuguese/epilogue.tra

solarom/russian/epilogue.tra

 

'String 2' is the resource being parsed, in this case BEDWIN. WeiDU looks up the sttref associated with the .tra reference, cross-references it with the dialog file, and spits out the state in 'String 2' ... so by BiggDU ninjary, using this .tra reference gets us the right state number for any language the mod would use, with one line of code. Way cool.

 

PRINT ~Completed... moving on.~

 

...ok, so we are getting talky with the player installing. Better that than them wondering whether there has been a problem, and clicking on that little red button in the corner of the command process.

 

Things to recheck before testing

 

Well for one thing, existing usage doesn't mess around with inlined files and variable substitution the same way. It uses stuff like this from Crossmod-v9 :

// INTERJECTIONS
// Note these files contain interjections into the respective mod, not from that mod

// Amber

ACTION_IF FILE_EXISTS_IN_GAME ~m#amber.dlg~
THEN BEGIN

 PRINT ~Defining Amber joining state~
 OUTER_SET actual_joining_state = (STATE_WHICH_SAYS 5023 IN ~amber/tra/%s/dialogs.tra~ FROM ~m#amber~)
 PRINT ~Defining Amber kidnapping state~
 OUTER_SET actual_kidnapping_state = (STATE_WHICH_SAYS 5207 IN ~amber/tra/%s/dialogs.tra~ FROM ~m#ambern~)
 PRINT ~Completed... moving on~

 // Auren interjections into Amber

 ACTION_IF FILE_EXISTS_IN_GAME ~k#aurenj.dlg~
 THEN BEGIN
PRINT ~Adding Auren injections into Amber's dialogues...~
COPY - ~CrossmodBG2/SoA/Interjections/Amber/Auren/Auren_Interjections.d~ ~CrossmodBG2/SoA/Interjections/Amber/Auren/Auren_Interjections.d~
  REPLACE_TEXTUALLY ~temp_joining_state~ ~%actual_joining_state%~
  REPLACE_TEXTUALLY ~temp_kidnapping_state~ ~%actual_kidnapping_state%~
COMPILE ~CrossmodBG2/SoA/Interjections/Amber/Auren/Auren_Interjections.d~
EXTEND_TOP ~k#auren.bcs~  ~CrossmodBG2/SoA/Interjections/Amber/Auren/Interject_k#auren.baf~
 END

 

This code uses "COPY - " to overwrite the unevaluated file with the evaluated file, doing a straight REPLACE_TEXTUALLY to set the value in the .d. Then it compiled the resulting .d. In the code we are playing with for Aran, we may or may not need the COMPILE EVALUATE_BUFFER; inlined files are parsed and created by the .tp2, which already knows that

 

%actual_conflict_state% = 245

 

or whatever value it really is on whatever local install it is being tossed on. We may not need to do anything but COMPILE.

 

We also need to revisit I_C_T behavior and make sure that the line is placed where we actually want it (after the target state plays, rather than before it) and tidy up any typos. hemn it is off to testiing-land, by installing

 

aranw

ersoa107

aran-aware

 

and seeing what the resulting dialog looks like in NI and DLTCEP - or just using BiggDU to create decompiled dialog files for the three gentlemen in question and crossreferencing to make sure everything works. (heh. If it works right the first time, it will be a miracle :) ).

 

 

Hey - you forgot a state - what about the other Aran line?

 

Forget it.

 

Seriously.

 

Looking at the dialog, it is already long enough. Aran's second line interrupts Laufey's flow to an extent I am not interested in pursuing. I don't want to rewrite/destroy/vandalize his work, I just want to make it feel more like a party of adventurers rather than a constantly changing set of one-on-one sideline comments. Using stuff like this is tricky from several standpoints:

  • Messing with Other People's Stuff.
    Philosophically, I am with Nythrun on this one. It seems very silly to have a double standard, where a modder can mess with BioWare without direct permission or dispensation, but not touch mod added content. BUT - there are reasons why this double standard exists, and just like US politics and Social Security, it is a well-known "third rail" of modding. Touch something without permission, and the volts passing through your body will power Chicagoland for a week. I have been on both sides of this. Coordinating BG1NPC meant accepting, supporting, and enforcing author's expressed wishes, regardless of any perceived need for repair or improvement. No problem - there was a policy in place, and it is little enough to ask for the hours of hard work the authors and coders originally put in. On the other hand, I clearly state everywhere that my own work is just a toy that anyone can play with however they want. Yes, that means that someone could read the tutorials and come up with horrible things that I feel are completely uncalled for, and dump the materials into Aran:
     
    [ARAN] Now then, there be a right fine sight...
    [NEW_NPC] SUXXOR. Take ywerre stoopid hands off my LUV you bastrd
    [ARAN] NO. I am L33T and Wub <CHRANAME>,. I fart in your general direction.
    [ARAN] Plus I am a louzy modd and U should be playing GAVINGAVINGAVIN you sttoooop.
    [ARAN] ...
     
    ...while I might not like it, I don't see having much emotional damage done to my psyche over a toy. And everything is fixable with some patching and install order. That potential brings up the only reason to really avoid messing with people's stuff when you can't get permission or find someone who acts on their behalf - the good old "Do Unto Others". If I care about how my mod is treated, then it probably is a good idea to treat other people's mods the same way. For this particular example, I chose the Edwin Romance as a fun thought experiment. If it gets permission from an author or representative, then after testing it can be submitted to G3's Crossmod for inclusion with other ideas that have been given permission. If no permission is available then I have to rely on "Do Unto others' and make a decision on whether or not the mod author wold be cool with it, or if they were folks who really did not want anything done to their work. That is easy enough to research - just look at the posts, the permissions they have given and not given, and see how they reacted to this sort of thing. Anyone who is still active is easy - I just ask if they are cool with it, and are interested in having some fun building some banters, and oila. Berelinde and i work together often, as do Jastey and I, so chances are good that Ajantis will be around to take Aran down a peg or two, and Gavin/Aran already have crossmod things built with more to come.
  • Not Bogging Down Dialog.
     
    This one needs no WOT. I will demonstrate.
     
     
    EDWIN ~Logically you couldn't have become anything else. There are only so many professions available for a man with a brain the size of a small pea and the social graces of a mollusc.~
    [ARAN] Do you be talkin' about th' size o' his brain, or his...
    [EDWIN] Silence, moronic hireling. Even this pile of excrement's lack of sophistication and social manners is preferable to your clumsy common speech.~
    ANOMEN ~*You* would lecture *me* on social graces? The man who spews insults wherever he goes, like a dragon breathes fire?~
    EDWIN ~*My* insults are intelligent, purposeful and carefully considered. *Yours* are the random and clumsy mistakes of an oaf who puts his foot in his mouth often enough to have toe-fungus growing on his fat tongue.~
    [ARAN] Sune's Left Hand, I am gettin' th' hells away from this before I go puttin' my foot in my mouth!
    EDWIN ~Silence, I said! (the baboon still insists on speaking when his betters are present.)~
    ANOMEN ~Go, run away, sellsword. You have no business here..~
    [ARAN] Th' hells I don't. She has made no mind, an' I am just as likely as th' next man to be th' one she chooses.
    [PLAYER_INTERJECT] ~boys...~
    ANOMEN ~Speaking of feet...~
    [ARAN]You thinkin' o' rammin' 'em up your own rear? I can volunteer my own for that job.
    EDWIN ~Finally, a use for the sellsword besides an overfed unpredictable meat shield. ~
    [ARAN] At least I don't flip to th' other team an' grow female parts. How's she supposed to be all interested in you when you keep changin' teams?
    EDWIN ~I am attractive in whatever form I choose!~
    ANOMEN ~Then why don't you choose to polymorph yourself into something more reflective of your personality, say, perhaps an Orog?~
    [ARAN] Good one, tin-can. Except at least he smells decent. You should get a bath. Mayhap two. (shoves Anomen.)
    EDWIN ~OW! My *foot*! You *stepped* on it! You did that on *purpose*!~
    [PLAYER-INTERJECT] ~BOYS! SHUT UP!~
    ANOMEN ~I thought you wanted me to be more purposeful? And now my lady, let us return to our so sadly interrupted conversation. I was wondering if I had told you how I became a priest?~
    [PLAYER_RESPONSE_1] ~The three of you are worse than apprentices. All three of you, strip off your gear and leave it in a pile in front of me. I have some scouting of the Shadow dragon I want done, and I expect you shall not return Next time, i am taking Gavin, kivan, and Ajantis, and you three will go on the "permanently uninstall and delete this mod" list..~

     
  • Keeping The Focus on PC.
    Adding more than a minor sprinkle of curry powder or nutmeg to the mix might be a fun idea, but since the primary interaction is supposed to be focused on the player, adding a huge dose has the same result as in cooking - way too hot, or way too bitter. I don't want players to say 'Hey, that was what - nutmeg with a little pumpkin? Turkey'd Curry?'. And while I am having fun with this, and having fun playing with reader's suggestions and ideas, introducing this kind of spice is taking something that is already someone else's 'recipe', and messing with it. Anyone who still loves their mother's lumpy slightly burned gravy because it tastes like home understands this concept well.

Link to comment
How usable is STATE_WHICH_SAYS for multi-language installs?

It prevents traification.

 

I tried traifying Crossmod Banter Pack. I thought it worked, until I tried installing it. During installation, all of the TRA refs from the S_W_S on down in the CBP tp2 were substituted with TRA refs from Amber... in German. I intend to try moving the parts that use S_W_S into separate TPH files, but I have yet to get around to it.

Link to comment

@Luridel - I bet you are right - I will try to confirm, and then edit my post accordingly!

 

@berelinde - Using it prevents automatic traification of a pre-existing multi-language .tp2, but not manual .tra-ification of that same .tp2 and not auto-tra of the rest of the mod, right?

Link to comment

I think berelinde means that a mod that uses S_W_S cannot be trayfied i.e. not translated into other languages as it would break upon installation.

 

But theoretically it should be possible to make S_W_S function with tras - if there is a fitting language install, it will be installed. If the mod in question doesn't have that language, or was installed with a different one [meaning, if the text line does not fit the one used for the S_W_S], it would just skip it. Request to bigg? (If it makes sense.)

Link to comment

WeiDU readme says that

STATE_WHICH_SAYS value IN String1 FROM String2

should take traified files fine.

 

If not, then I suppose direct DLG patching can be set with better precision, especially when it comes to uncertanties, like two states with the same text.

COPY_EXISTING - dialogue.dlg override
 SPRINT match @12345

 state= ~-2~
 CLEAR_ARRAY states GET_OFFSET_ARRAY states 0xc 4 0x8 0 0 0x10
 PHP_EACH states AS i => r BEGIN
READ_STRREF r text
PATCH_IF ~%text%~ STRING_EQUAL_CASE ~%match%~ BEGIN
  PATCH_IF state ! > ~-2~ BEGIN
	state=i
  END ELSE BEGIN
	state= ~-1~
	PATCH_PRINT ~The dialogue file contains more than one state with specified text. Do something about it.~
  END
END
 END

<<<<<<<<inlined.d
I_C_T dialogue %state% label
END
>>>>>>>>
COMPILE EVAL inlined.d

Link to comment

OK, I think I get it -

 

If I have a tra-ified .tp2, like this:

 

BEGIN @0 /* @0 = ~Install MyMod's First Component?~ */

COPY ~mymod/mymod.cre~ ~override~
 SAY NAME1 @1
 SAY NAME2 @1
 SAY INITIAL_MEETING @2 
 SAY MORALE  @3 
 SAY HAPPY   @4 
 SAY UNHAPPY_ANNOYED  @5 
 SAY UNHAPPY_SERIOUS  @6 
 SAY UNHAPPY_BREAKING  @7 
 SAY LEADER  @8 
 SAY TIRED  @9 
 SAY BORED  @10 
 SAY BATTLE_CRY1  @11 
 SAY BATTLE_CRY2  @12 
 SAY BATTLE_CRY3  @13 
 SAY BATTLE_CRY4  @14 
 SAY BATTLE_CRY5  @15 
 SAY DAMAGE  @16 
 SAY DYING  @17 
 SAY HURT  @18 
 SAY AREA_FOREST  @19 
 SAY AREA_CITY  @20 
 SAY AREA_DUNGEON  @21 
 SAY AREA_DAY  @22 
 SAY AREA_NIGHT  @23 
 SAY SELECT_COMMON1  @24 
 SAY SELECT_COMMON2  @25 
 SAY SELECT_COMMON3  @26 
 SAY SELECT_COMMON4  @27 
 SAY SELECT_COMMON5  @28 
 SAY SELECT_COMMON6  @29 
 SAY SELECT_ACTION1  @30 
 SAY SELECT_ACTION2  @31 
 SAY SELECT_ACTION3  @32 
 SAY SELECT_ACTION4  @33 
 SAY SELECT_ACTION5  @34 
 SAY SELECT_ACTION6  @35 
 SAY SELECT_ACTION7  @36 
 SAY REACT_TO_DIE_GENERAL @37 
 SAY SELECT_RARE1  @38 
 SAY SELECT_RARE2  @39 
 SAY CRITICAL_HIT  @40 
 SAY CRITICAL_MISS  @41 
 SAY TARGET_IMMUNE  @42 
 SAY INVENTORY_FULL  @43 
 SAY SPELL_DISRUPTED  @44 
 SAY SET_A_TRAP  @45 
 SAY HIDDEN_IN_SHADOWS  @46 
 SAY PICKED_POCKET  @47 
 SAY BIO @48

 PRINT @49

BEGIN @50 /* @50 = ~Install MyMod's Second Component?~

 COMPILE ~mymod/mydialog.d~

 

 

then using STATE_WHICH_SAYS has a potential hiccup. It looks for and parses out all the potential languages for the referenced file:

 

OUTER_SET actual_conflict_state = (STATE_WHICH_SAYS 3 IN ~ersoa107/edwin/tra/%s/eranomen.tra~ FROM ~BEDWIN~)

 

... and I bet it then makes WeiDU think that the last parsed /tra/%s/eranomen.tra is the .tra to reference for the rest of the time. For regular files, you can declare each file's tra manually, so it might not mess up anything els -

 

COMPILE ~c-arandialog.d~ USING ~awanw/tra/%s/master_tra_file_of_all_lines_in_game.tra

or something like that, instead of relying on AUTO_TRA. But I dont know how you could reset the .tp2 to go back to reading setup-tra or such. Perhaps putting it off into a .tpa or .tph with a resest of the master setup-mymod .tra reference?

 

 

(I will take a look at that code, Ardanis.)

Link to comment

OK, B - I did a full test, described below - but I think the problem you were running into with Crossmod was related to the complexity of the mod, not a bug in STATE_WHICH_SAYS. All those recursively nesting folders, and such, and something must have gone odd, because I can't confirm the switching of loaded .tra's during install. The "behavior test package" is available [>>state_which_says.rar<<] for replication or messing about with.

 

Testing This Out With A Dummy Mod or, how to kill an hour and a half for no good reason and make yourself nuttier than a fruitcake.

 

OK, so I want to test this out, and make sure that I am really checking on the behavior, without my lovely customary typos or oddities in RL mods cropping up and making my head hurt any more than it already does just trying this stuff. So, type A over-focus and OCD tendencies to the rescue...

 

create a sample mod.

 

Or in this case, two.

 

SWS wants an existing string from a mod folder, and then it uses that to look up where a state should be inserted, so, off to the races:

 

[in the package above, the first mod is "othermod".]

 

1. create a simple dummymod using AUTO_TRA, and the related files. The whole pack is in there, but here's the basics:

BACKUP ~othermod/backup~
AUTHOR ~cmorgan~

VERSION ~v1~

AUTO_TRA ~othermod/%s~

LANGUAGE ~english~ ~english~ ~othermod/english/setup.tra~

BEGIN @0

PRINT @3

COMPILE ~othermod/dialog/soa-other1.d~

PRINT @4

BEGIN @1

PRINT @5

COMPILE ~othermod/dialog/soa-other2.d~

PRINT @6

BEGIN @2

PRINT @7

COMPILE ~othermod/dialog/soa-other3.d~

PRINT @8

I didn't have to do all that PRINT @8 stuff, but I did it because I am going to copy/paste/modify into the second mod, so I might as well be able to do it. The related .tra, in othermod\english\setup.tra:

@0 = ~test string 0 of setup.tra: other~
@1 = ~test string 1 of setup.tra: other~
@2 = ~test string 2 of setup.tra: other~
@3 = ~test string 3 of setup.tra: other~
@4 = ~test string 4 of setup.tra: other~
@5 = ~test string 5 of setup.tra: other~
@6 = ~test string 6 of setup.tra: other~
@7 = ~test string 7 of setup.tra: other~
@8 = ~test string 8 of setup.tra: other~

The inner files look like copies of this, with the corrected references, set out with simple dialog construction, so something like this:

BEGIN other1
BEGIN other2
BEGIN other3

APPEND other1

IF ~~ testing1
 SAY @0 /* ~test string 0 of other1.tra: ~ */
 ++ @1 + testing2 /* ~test string 1 of other1.tra: ~ */
 ++ @2 + testing2 /* ~test string 2 of other1.tra: ~ */
 ++ @3 + testing2 /* ~test string 3 of other1.tra: ~ */
END

IF ~~ testing2
 SAY @4 /* ~test string 4 of other1.tra: ~ */
 ++ @5 EXIT /* ~test string 5 of other1.tra: ~ */
 ++ @6 EXIT /* ~test string 6 of other1.tra: ~ */
 ++ @7 EXIT /* ~test string 7 of other1.tra: ~ */
 ++ @8 EXIT /* ~test string 8 of other1.tra: ~ */
END

END

 

Most importantly, I needed to create a back-and-forth dialog to try to break into, so the final one to install became:

APPEND ~other3~

IF ~Global("startchain","GLOBAL",1)~ THEN BEGIN testing5
 SAY @8 
 IF ~~ GOTO starttalk
END

END

CHAIN ~other3~ starttalk
@0
== ~OTHER2~ @1
== ~OTHER3~ @2
== ~OTHER1~ @3
== ~OTHER2~ @4
END
++ @5 EXIT
++ @6 EXIT
++ @7 EXIT

 

And after we set it all up, run it out on the install:

 

post-844-1290207623_thumb.png

 

And open up DLTCEP to check each of the dummy dialogs. In this case, weidu-export out a "before" picture of OTHER3.DLG, because we are going to try to find a state inside of the CHAIN structure to I_C_T into.

{insert 15 minutes of typo correction, parse warnings, and other stupid things like doing COMPILE ~othermod/dialog/other3.d~ instead of COMPILE ~othermod/dialog/soa-other3.d~, and even sillier stuff like copying and pasting the COMPILE command but not updating the file, so I compile OTHER1 three times instead of getting all three. heh. i am not amused. But eventually...}

// creator  : DLTCEP_enhanced_WeiDU (version 22300)
// argument : OTHER3.DLG
// game		 : .
// source	 : ./override/OTHER3.DLG
// dialog	 : ./dialog.tlk
// dialogF  : (none)

BEGIN ~OTHER3~

IF ~Global("startchain","GLOBAL",1)
~ THEN BEGIN 0 // from:
 SAY #82595 /* ~test string 8 of other3.tra: ~ */
 IF ~~ THEN GOTO 1
END

IF ~~ THEN BEGIN 1 // from: 0.0
 SAY #82596 /* ~test string 0 of other3.tra: ~ */
 IF ~~ THEN EXTERN ~OTHER2~ 2
END

IF ~~ THEN BEGIN 2 // from:
 SAY #82598 /* ~test string 2 of other3.tra: ~ */
 IF ~~ THEN EXTERN ~OTHER1~ 2
END

 

Now we have a known, independent test mod to operate on, and everything is labled. If something gets scrambled, it will scream bloody murder at the top of its lungs, right away on the screen if the main mod screen starts pulling from another source, and in decompiled .d in the dialogs.

Link to comment

[in the package above, the second mod is "sws_test".]

 

2. create a STATE_WHICH_SAYS test dummymod using AUTO_TRA, and the related files to try to mess around with "othermod". The whole pack is in there, too but here's the basics:

 

a. basically, rework the othermod package to use MYTRA# references instead of OTHER# references, to save lots of time. "find in files" and "replace" makes this way easy, and fast - and then of course simplifying the dialog files because we don't want oddities getting in the way.

 

b. the real problem at hand - figure out how to try to force the .tra to fail.

 

BACKUP ~sws_test/backup~
AUTHOR ~cmorgan~

VERSION ~v1~

AUTO_TRA ~sws_test/%s~

LANGUAGE ~English~ ~English~ ~sws_test/english/setup.tra~

BEGIN @0

PRINT @3

COMPILE ~sws_test/dialog/mytra1.d~

PRINT @4

BEGIN @1

PRINT @5

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
<<INSERT TEST HERE >>
END 

COMPILE <<INSERT INLINED FILE TEST HERE >>

PRINT @6

COMPILE ~sws_test/dialog/mytra2.d~

PRINT @7

BEGIN @2

COMPILE ~sws_test/dialog/mytra3.d~

PRINT @8

This is where the PRINT and the COMPILE stuff makes a difference. The first component just installs a .tra'd .d; the second, though has both PRINT and COMPILE within the same component, after the attempt to use SWS; the third component is the a follow up to see if the (un)expected behavior continues in another component farther down the line.

 

So, the test itself... well, I will save you a hell of alot of stupid pointless reading, and save myself trying to type it all out. Basically, I found out some interesting things. Like

 

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... moving on.~
	<<<<<<<<sws_test\dialog\checkthis.d
	I_C_T OTHER3 %actual_state% other1mytra
	== MYTRA1 ~[MYTRA1] This is the most convoluted test... bleh.~
	END
	>>>>>>>>
END

sux.

 

I couldn't figure out why everything kept failing - tracking all sorts of things manually, fail, fail, fail... and more fail. Until I remembered Nythrun's (and several other folk's) use of PRINT and PATCH_PRINT can be very helpful, so I commented out stuff and reformed it to

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... state is %actual_state%  - moving on.~
END

 

... and voila...

 

it said I was getting a state of "-1", and of course then was doing the whole "weidu hates you and you teh suxxor email the file and go hang your newb head in shame or take up .html file "modding" for text games". A visit to the weidu docs reminded me that -1, -2, -3 results were great, and I was able to figure out that I was trying to look for a string that was in the dialog.tlk, but not in the file I was trying to sort through... so I fix that, and still...

 

post-844-1290208068_thumb.png

 

So, back to the drawing board - and this time I decided that if I can do a little ACTION_IF and PATCH_IF, I should be able to figure out some hideously hacky stupid newb way of making weidu happier on my epic fails - so i added a screen for the inlined file, skipping if it got -1, -2, or -3:

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... state is %actual_state%  - moving on.~
ACTION_IF (NOT (%actual_state% = 0 - 3) AND NOT (%actual_state% = 0 - 2) AND NOT (%actual_state% = 0 - 1)) THEN BEGIN
	<<<<<<<<sws_test\dialog\checkthis.d
	I_C_T OTHER3 %actual_state% other1mytra
	== MYTRA1 ~[MYTRA1] This is the most convoluted test... bleh.~
	END
	>>>>>>>>
END ELSE BEGIN
PRINT ~Not installing the reference because it was -3, -2, or -1~
END
END 
COMPILE ~sws_test\dialog\checkthis.d~

 

Ok, now it tells me when I fail, and what is failing. Cool. And I edited the file to look for something that was (golly gee, go figure ) actually IN the file to be found... But it is still failing - lots off stupid tries, all basically coming up with "unresolved state label". So now I look around, and try

 

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... state is %actual_state%  - moving on.~
ACTION_IF (NOT (%actual_state% = 0 - 3) AND NOT (%actual_state% = 0 - 2) AND NOT (%actual_state% = 0 - 1)) THEN BEGIN
	<<<<<<<<sws_test\dialog\checkthis.d
	I_C_T OTHER3 ~%actual_state%~ other1mytra
	== MYTRA1 ~[MYTRA1] This is the most convoluted test... bleh.~
	END
	>>>>>>>>
END ELSE BEGIN
PRINT ~Not installing the reference because it was -3, -2, or -1)~
END
END 
COMPILE ~sws_test\dialog\checkthis.d~

 

Changing %actual_state% to ~%actual_state%~.... No love. Then I remember that I thought inlined files might not need EVALUATE BUFFER, but perhaps I was wrong, so EVALUATE_BUFFER...

 

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... state is %actual_state%  - moving on.~
ACTION_IF (NOT (%actual_state% = 0 - 3) AND NOT (%actual_state% = 0 - 2) AND NOT (%actual_state% = 0 - 1)) THEN BEGIN
	<<<<<<<<sws_test\dialog\checkthis.d
	I_C_T OTHER3 ~%actual_state%~ other1mytra
	== MYTRA1 ~[MYTRA1] This is the most convoluted test... bleh.~
	END
	>>>>>>>>
END ELSE BEGIN
PRINT ~Not installing the reference because it was -3, -2, or -1)~
END
END 
COMPILE EVALUATE_BUFFER ~sws_test\dialog\checkthis.d~

VOILA!! EUREKA!! It works! (I then realize that I am still leaving a COMPILE EVALUATE_BUFFER outside of the ACTION_IF, so the mod will fail if the file doesn't exist, and am suitably ashamed. I repair it to)

ACTION_IF FILE_EXISTS_IN_GAME ~other3.dlg~ THEN BEGIN
 PRINT ~Defining Othermod's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS 0 IN ~othermod/%s/soa-other3.tra~ FROM ~other3~)
 PRINT ~Completed... state is %actual_state%  - moving on.~
ACTION_IF (NOT (%actual_state% = 0 - 3) AND NOT (%actual_state% = 0 - 2) AND NOT (%actual_state% = 0 - 1)) THEN BEGIN
	<<<<<<<<sws_test\dialog\checkthis.d
	I_C_T OTHER3 ~%actual_state%~ other1mytra
	== MYTRA1 ~[MYTRA1] This is the most convoluted test... bleh.~
	END
	>>>>>>>>
	COMPILE EVALUATE_BUFFER ~sws_test\dialog\checkthis.d~
END ELSE BEGIN
PRINT ~Not installing the reference because it was -3, -2, or -1)~
END
END

 

And test. Now we have something.

 

post-844-1290208131_thumb.png

 

First up, we look at the screens, and the logs - and the .tra references are all correct. The in-game strrefs point to appropriate ones. So perhaps something else was clobbering Crossmod on .tra references.

// creator  : DLTCEP_enhanced_WeiDU (version 22300)
// argument : OTHER3.DLG
// game		 : .
// source	 : ./override/OTHER3.DLG
// dialog	 : ./dialog.tlk
// dialogF  : (none)

BEGIN ~OTHER3~

IF ~Global("startchain","GLOBAL",1)
~ THEN BEGIN 0 // from:
 SAY #82595 /* ~test string 8 of other3.tra: ~ */
 IF ~~ THEN GOTO 1
END

IF ~~ THEN BEGIN 1 // from: 0.0
 SAY #82596 /* ~test string 0 of other3.tra: ~ */
 IF ~~ THEN EXTERN ~OTHER2~ 2
 IF ~Global("other1mytra","GLOBAL",0)~ THEN DO ~SetGlobal("other1mytra","GLOBAL",1)~ EXTERN ~MYTRA1~ 2
END

IF ~~ THEN BEGIN 2 // from:
 SAY #82598 /* ~test string 2 of other3.tra: ~ */
 IF ~~ THEN EXTERN ~OTHER1~ 2
END

 

and MYTRA2, the one right after the SWS:

// creator  : DLTCEP_enhanced_WeiDU (version 22300)
// argument : MYTRA2.DLG
// game		 : .
// source	 : ./override/MYTRA2.DLG
// dialog	 : ./dialog.tlk
// dialogF  : (none)

BEGIN ~MYTRA2~

IF ~Global("testing2","GLOBAL",1)
~ THEN BEGIN 0 // from:
 SAY #82605 /* ~test string 0 of mytra2.tra: ~ */
 IF ~~ THEN REPLY #82606 /* ~test string 1 of mytra2.tra: ~ */ GOTO 1
 IF ~~ THEN REPLY #82607 /* ~test string 2 of mytra2.tra: ~ */ GOTO 1
 IF ~~ THEN REPLY #82608 /* ~test string 3 of mytra2.tra: ~ */ GOTO 1
END

IF ~~ THEN BEGIN 1 // from: 0.2 0.1 0.0
 SAY #82609 /* ~test string 4 of mytra2.tra: ~ */
 IF ~~ THEN REPLY #82610 /* ~test string 5 of mytra2.tra: ~ */ EXIT
 IF ~~ THEN REPLY #82611 /* ~test string 6 of mytra2.tra: ~ */ EXIT
 IF ~~ THEN REPLY #82612 /* ~test string 7 of mytra2.tra: ~ */ EXIT
 IF ~~ THEN REPLY #82613 /* ~test string 8 of mytra2.tra: ~ */ EXIT
END

 

MYTRA1 and 3 look good, too. So, we have working code. plus we have set it up so that a note is put in DEBUG if the materials are not skipped, and we have figured out how to do it so that we don't get a bunch of errors from a .tra match that doesn't work. Cool.

 

Final code to use, in template format:

 

ACTION_IF FILE_EXISTS_IN_GAME ~THE_DIALOG_FILE_TO_ADD_TO.dlg~ THEN BEGIN
 PRINT ~Defining THE_OTHER_MOD's State.~
 OUTER_SET actual_state = (STATE_WHICH_SAYS # IN ~THE_OTHER_MOD/%s/THE_OTHER_MOD's_TRA.tra~ FROM ~THE_DIALOG_FILE_IT_IS_IN~) // replace # with the .tra number 
 PRINT ~Completed... state is %actual_state%  - moving on.~
ACTION_IF (NOT (%actual_state% = 0 - 3) AND NOT (%actual_state% = 0 - 2) AND NOT (%actual_state% = 0 - 1)) THEN BEGIN
	<<<<<<<<MY_MOD\dialog\checkthis.d
	I_C_T THE_DIALOG_FILE_TO_BE_ADDED_TO ~%actual_state%~ NEW_STATENAME
	== MYNPC ~[MYNPC] This is the text I am saying in the other mod's dialog file. ~
	END
	>>>>>>>>
	COMPILE EVALUATE_BUFFER ~MY_MOD\dialog\checkthis.d~
END ELSE BEGIN
PRINT ~Not installing the reference because it was -3, -2, or -1~
END
END

 

I guess the next logical step would be to try having a second language available, but I am out of time for tonight.

Link to comment

Archived

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

×
×
  • Create New...