Jump to content

Photo

What happens when a kit is called in .d, but is not installed?

modder discussion troubleshooting mod development dialog coding aran whitehand

28 replies to this topic

#1 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 04:18 PM

So, the idea was to get detailed, and see what happened in WeiDU with two ideas that have been coded into Aran.

1. - is it really really true that WeiDU does not care if you code things like this:

IF ~~ a101
	SAY ~[ARAN] Well, I have seen precious little o' th' Tel' Quessirim, truth be told. Those ears be a right interestin' sight on a lad. No harm meant, eh?~
	IF ~~ THEN EXIT
END

or this, run all into a single line:

IF ~~ a101 SAY ~[ARAN] Well, I have seen precious little o' th' Tel' Quessirim, truth be told. Those ears be a right interestin' sight on a lad. No harm meant, eh?~ IF ~~ THEN EXIT END

(We know the answer to this - WeiDU does not care, but the human does. Nothing harder to troubleshoot than unindented stuff. If there is not a decent pattern, then you can't catch the silly things, like a missing tilde, or an IF ~~ THEN EXIT with no END. We are just having some fun with this as a control).

So, first off, we create a folder called test1 in the BG2 directory. NOT THAT ONE!!!!!

Nope, not the clean, nice, pristine, untouched one you have on your main hard drive. Trust me. Bad idea. Copy the whole BG2 clean version onto another drive, remap the baldur.ini in your copied one to your new one in the nice folder X:\TESTING\BG2, because you might want to get fancy someday and do things like edit creatures, or build macros that are supposed to manipulate values, or something fancier than what we are doing today. And when you do that, you will need to compare the original game structures to the modded ones, so that even before you test in-game, you can see if it is doing basically what you want, or have you accidentally done something like edit every single item in the game to have an extra couple of bytes, thus corrupting everything...

believe, or suffer the consequences. I certainly hope you believe, because if you think it is tough to troubleshoot your installation now, just wait until you have been playing around trying to learn modding, and forget to uninstall a test - or worse.

OK, on the testing install, I have that folder, and now I grab a copy of another mod's setup-mymod.exe (or just a regular old weidu.exe from its package), and name it setup-test1.exe.

I whip up a quick .tp2 (unless I have a test one already created and are just editing it, like I do):

setup-test1.tp2
BACKUP ~test1/BACKUP~
AUTHOR ~Me.~	  
VERSION ~v1~  

BEGIN ~Check Dialog format~

COMPILE ~test1/test1.d~

And I grab the dialog thought I want to play with, and toss it in the folder with the .tp2:

test1.d
BEGIN ~test1~

APPEND ~test1~

IF ~Global("test1","GLOBAL",1)~ THEN BEGIN a100
  SAY ~[ARAN] What a blighted great place to be fightin' for our lives at every turn. So do you come here often? How's the food? Know any available converts o' Sune? You thinkin' o' convertin'?~
  IF ~!Kit(Player1,NMSUNE)~ THEN DO ~IncrementGlobal("c-aranflirt","GLOBAL",1) SetGlobal("c-aranlightflirt","GLOBAL",0) RealSetGlobalTimer("c-aranflirttimer","GLOBAL",ARAN_FLIRT)~ EXIT
  IF ~Kit(Player1,NMSUNE)~ THEN GOTO a101
END

IF ~NumTimesTalkedTo(0)~ THEN BEGIN a105
SAY ~[ARAN] Yup, a stupid test~
++ ~[PC] heya, 101~ + a101
++ ~[PC] heya, 102~ + a102
++ ~[PC] heya, 103~ + a103
++ ~[PC] heya, 104~ + a104
END

IF ~~ a101 SAY ~[ARAN] Well, I have seen precious little o' th' Tel' Quessirim, truth be told. Those ears be a right interestin' sight on a lad. No harm meant, eh?~ IF ~~ THEN EXIT END
/* c-aranpidhum */
IF ~~ a102 SAY ~[ARAN] No, naught but tryin' to figure out if you be a native Chondathan, Luskan, or mayhap Rashemi speaker. Must be all that book learnin'. I just can't bloody well place your accent, is all.~ IF ~~ THEN EXIT END
/* c-aranpiddwarf */
IF ~~ a103 SAY ~[ARAN] Nothin' wrong. Just tryin' not to trip over your short little sorry arse, eh?~ IF ~~ THEN EXIT END
/* c-aranpidorc */
IF ~~ a104 SAY ~[ARAN] Just tryin' to figure out how to avoid tellin' you that you be the ugliest son o' a bitch I ever did lay eyes on. No harm meant, o' course.~ IF ~~ THEN EXIT END

END

and double-click the file setup-test1.exe.

Now, I have weidu showing me a command box, and before I go further, I want to make sure I get all the data I can. In Windows (I am using Win7 pro x64, but it is all variations on a theme), I right click on the top bar of the command prompt (command box, terminal, whatever you want to call it), and I change the properties. First, I set the screen buffer size to something appropriate for my screen resolution. Since I work at 1280 x 1024, it ends up being something huge, like width = 150, height = 300. I make the window size width = 150 and height = 60. And most of all, I toggle options, and put a buffer size of 500, 4 buffers, QuickEdit mode, and Insert mode.

Now, the command box will save lots of cool information - and I can cut and paste out of it. It looks pretty silly right now,

first_window.PNG


but on troubleshooting a big install, I have a big wide net cast to discover troubles, and I can either screenshot or copy/paste the errors for forum posting, to bug and annoy share with friendly fellow modders.

OK, now I go ahead and press i, installing the mod. Success! If there wasn't, I could do that snipping tool, giving you a cute picture of a black box with text, or just copy the contents and post here, like this:

[D:\Black Isle\BGII - SoA\setup-test1.exe] WeiDU version 21200
[D:\Black Isle\BGII - SoA\setup-test1.exe] Using scripting style "BG2"

Install Component [Check Dialog format]?
[I]nstall, or [N]ot Install or [Q]uit? i

Installing [Check Dialog format]
Compiling 1 dialogue file ...

[trigger list near line 9, column 28 of test1/test1.d] PARSE WARNING at line 9 column 1-20
Near Text: )
[Kit] argument [NMSUNE] not found in [KIT.IDS]

[action list near line 9, column 180 of test1/test1.d] PARSE WARNING at line 9 column 1-141
Near Text: )
[RealSetGlobalTimer] argument [ARAN_FLIRT] not found in [GTimes.IDS]

[trigger list near line 10, column 27 of test1/test1.d] PARSE WARNING at line 10 column 1-19
Near Text: )
[Kit] argument [NMSUNE] not found in [KIT.IDS]



SUCCESSFULLY INSTALLED Check Dialog format

Press ENTER to exit.


OK, now we have our answers to both questions. It installs, allowing single-line code, and if Divine Remix is not installed before Aran is installed, there will be some parse warnings that show up in the black box and will lead to people checking in and reporting this as an error. Useful information.

Side Note: what we just found out was that weidu will allow an install to happen, and will show a successful install in the DEBUG. It will not throw a "Installed with Warnings", or fail outright. In other words, it found the correct structures, and did not choke/scream bloody murder/spit up on us. WE HAVE NOT FOUND OUT IF IT WORKS. WeiDU was designed by trial and error, and is rebuilt and maintained by serious moddarz, not folks who have 14 safety nets for every conceivable situation and way in which the average idiot like me will throw weidu's way. If you tell it politely to do something that sounds reasonable, using the correct language, and in the correct form, it will do it. But, as we are about to find out, what a modder *thinks* they want and what the game engine *actually* wants is not always... err... make that almost never... the same thing.

SO,

Now we check the files. Lots of ways of doing this, but since many folks starting out do not actually use weidu to look at dialog, let's use DLTCEP and go through the process. (Heh. That is a little joke, because when you are using DLTCEP, you are using a cool, powerful, hardworking tool that acts as a front-end GUI for weidu. It does other stuff, but in this instance, we are just letting DLTCEP form the weidu commands).

First off, we point DLTCEP to our new test install, because if you leave it where it is, you will keep going back to the same original installation over and over, scratching your head, trying to figure out why the mod *says* it is installed, but DLTCEP just can't seem to find TEST1.DLG...

That's always fun.

Now, I choose the EDIT > DLG > Load Dialog, and find TEST1. Yup, it is there, and looks good. But I want to see it all laid out nicely like when I wrote it, instead of hunting down triggers and actions and text strings, all jumbled up - so I do FILE > Export WeiDU.

Now I toddle over to my testing directory> script compiler > decompiled, and voila - a TEST1.D is all ready for me. Let's see what it looks like, opened up in Notepad++:

window_d.PNG

OK. Now, there is something interesting to investigate next, another day, by either asking on the forums or trying it out in game. If we look at the decompiled dialog reply states, we has set up the logic

"If the player has the kit NMSUNE, then go in this direction. If the player does not have the kit NMSUNE, then go in another direction."

But with no entry for NMSUNE, because DR is not installed, the script now says

"If the player has the kit 0, then go in this direction. If the player does not have the kit 0, then go in another direction."

IF ~!Kit(Player1,0)~ THEN EXIT
IF ~Kit(Player1,0)~ THEN GOTO 2


Before we experiment, of course, we can research. What is Kit=0?

IESDP, http://iesdp.gibberl...ids/bg2/kit.htm, and we find... nothing.

Nothing matching 0 in the old, incorrect .ids, nothiing in the new one... are we safe?

Maybe. But logic tells us we might just have a problem. Because what that lovely piece of code is saying is

IF NOT no_kit
IF no_kit

and there is no entry no_kit (and even un-kitted folks have 0x4000 TRUECLASS as their "kit") -


I think we will have a dreaded NVROL "No Valid Replies Or Links" popping up.

Lots of ways to solve this, by the way - everything from requiring Divine Remix to be installed before Aran [bad idea to create unneeded dependencies, so not my idea of a good solution] to rejiggering the dialog code to allow a valid link that allows folks who want to play without DR installed, by simply making that ~!Kit(Player1,0)~ into a very simple default condition always available, by using IF ~~ THEN REPLY or its shortcut ++.

Edited by cmorgan, 19 November 2011 - 04:28 AM.

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#2 the bigg

the bigg

    The Avatar of F/Ts

  • Modders
  • 2337 posts
  • Gender:Male
  • Location:Modena (Italy)

Posted 05 February 2010 - 04:25 PM

Domi's Kivan&Deheriana is in a similar situation with a kit from Refinements. I can't recall if/how the situation was handled, though.
Italian users: help test the Stivan NPC!

Author or Co-Author: WeiDU - Widescreen - Generalized Biffing - Refinements - TB#Tweaks - IWD2Tweaks - TB#Characters - Traify Tool - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics - Nalia Mod - Nvidia Fix
Code dumps: Detect custom secondary types - Stutter Investigator

If possible, send diffs, translations and other contributions using Git.

#3 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 04:34 PM

I'll go take a look!

EDIT> Hmmm. looks like she resolved it by reworking it completely - she does the standard "rebuild the kit.ids to fixed status just in case the player has not used the BG2 Fixpack", but there are only references to Class( and all of those are standard. No reference to Kit( . I bet she chose to simply reword it so it was applicable to more than the one kit.

Edited by cmorgan, 05 February 2010 - 04:51 PM.

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#4 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 05:10 PM

Hmmm. Curiouser and curiouser, on the research front. Check The Bodies v1.11 actually uses the 0 as a check for no kit... I wonder if it works? Sample

IF ~OR(5)
GlobalGT("CbMasterBardWantsHarp","GLOBAL",0)
GlobalGT("CbRangerDeadDear","GLOBAL",0)
GlobalGT("CbDruidTeachingSeeds","GLOBAL",0)
GlobalGT("CbTumblingWizardWantsResearch","GLOBAL",0)
GlobalGT("CbElvenSorceressWantsSeeds","GLOBAL",0)
IsGabber(Player1)
Class(Player1,FIGHTER)
Kit(Player1,0)~ THEN BEGIN 43
  SAY @55
  IF ~~ THEN EXIT
END
The mod uses it 38 times, almost always in conjunction with Class(Player1,FIGHTER).

A full search of a huge pile-o-mods seems to indicate most folks skip this by not specializing down to Kit, sticking with Class as a covering trigger, or they are responding to thier own added kit guaranteed to be there (Zraen's Reaver, SConrad's Hubelpot and his two potntial kits, etc.)
I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#5 the bigg

the bigg

    The Avatar of F/Ts

  • Modders
  • 2337 posts
  • Gender:Male
  • Location:Modena (Italy)

Posted 05 February 2010 - 05:33 PM

CtB used to be a non-WeiDU mod. I won't bore you with an history lesson in outdated tools and broken files, but it's likely that the Kit(Player1,0) thing is a result of the conversion process and the thing was never noticed during the rigorous testing big mods usually undergo.
Italian users: help test the Stivan NPC!

Author or Co-Author: WeiDU - Widescreen - Generalized Biffing - Refinements - TB#Tweaks - IWD2Tweaks - TB#Characters - Traify Tool - Some mods that I won't mention in public
Maintainer: Semi-Multi Clerics - Nalia Mod - Nvidia Fix
Code dumps: Detect custom secondary types - Stutter Investigator

If possible, send diffs, translations and other contributions using Git.

#6 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 07:37 PM

That makes sense. None of those references are for reply states, just for dialog triggers or so if the check failed, something would never play in-game, and many of the CtB quests appear to have multiple ways of triggering.


Well, this makes the case for us nicely - the only thing left after planning, logic-check, researching, and checking how other mods have handled it, is to run it out and test.

To test it out, I am adding a new line to IMOENJ.DLG, the initially joined dialog in Irenicus' dungeon, for a quick vanilla test.

Same .tp2, but now the contents of the test1.d are

APPEND ~IMOENJ~

IF WEIGHT #-1 ~Global("test1","GLOBAL",1)~ THEN BEGIN a100
  SAY ~[ARAN] What a blighted great place to be fightin' for our lives at every turn. So do you come here often? How's the food? Know any available converts o' Sune? You thinkin' o' convertin'?~
  IF ~!Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, does not have a kit .ids reference of 0.~ EXIT
  IF ~Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, has a kit .ids reference of 0.~ EXIT
END

END

Let's put this ingame, and see what happens...

(The WEIGHT thing is to make the dialog jump to the top of the stack that the game engine sees.)

step 1, install, and of course the same as above, weidu tells us gently "I do not think that word means what you think it means", but since it has not started chanting "Hello. My name in Indigo Montoya. You killed my father. Prepare to die." we are all good. Next up, a check using DLTCEP...

Yep. It look like I wanted it to. So the export using WeiDU...

IF WEIGHT #0 ~Global("test1","GLOBAL",1)
~ THEN BEGIN 71 // from:
  SAY #74112 /* ~[ARAN] What a blighted great place to be fightin' for our lives at every turn. So do you come here often? How's the food? Know any available converts o' Sune? You thinkin' o' convertin'?~ */
  IF ~!Kit(Player1,0)
~ THEN REPLY #74122 /* ~Hah. I have detected that Player 1, <CHARNAME>, does not have a kit .ids reference of 0.~ */ EXIT
  IF ~Kit(Player1,0)
~ THEN REPLY #74123 /* ~Hah. I have detected that Player 1, <CHARNAME>, has a kit .ids reference of 0.~ */ EXIT
END

Yep, a new state has been added to the bottom of the stack that the palyer sees, but though its state number is 71, it is feather light, weighing in at an engine-decision-making weight of #0 - top priority, the absolute first highest and Grand Exalted state. Assuming, of course, we have set the global "test1" to 1... I did remember to enable CluaConsole on that test install, right? A doublecheck before we take the time to load up and watch the blasted beginning cutscene for the ten-thousandth time (yes, there are shortcust to this. Bit right now, I am on a clean install, no mods, so you can always replicate if you are one of the N-1 people who are using Aran to experiment with to learn new stuff/bounce ideas off of.)

Edited by cmorgan, 05 February 2010 - 07:47 PM.

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#7 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 07:55 PM

And of course, I forgot to set a trigger state and close it up. Typical.
I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#8 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 08:07 PM

OK, trial 2, after a quick uninstall: this time, I have a new .tp2 line.

EXTEND_BOTTOM ~IMOEN.BCS~ ~test1/test1.baf~

with file

test1.baf
IF
Global("test1","GLOBAL",1)
THEN RESPONSE #100
Wait(8)
StartDialogNoSet(Player1)
END

and a modified test1.d, since now we are checking on a global via .bcs...

APPEND ~IMOENJ~

IF WEIGHT #-1 ~Global("test1","GLOBAL",1)~ THEN BEGIN a100
  SAY ~[ARAN] What a blighted great place to be fightin' for our lives at every turn. So do you come here often? How's the food? Know any available converts o' Sune? You thinkin' o' convertin'?~
  IF ~~ THEN REPLY ~This state shows up all the time no matter what, so that if everything else fails I don't get stuck in an infinite script stutter...~ DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
  IF ~!Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, does not have a kit .ids reference of 0.~ DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
  IF ~Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, has a kit .ids reference of 0.~  DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
END

END

Edited by cmorgan, 05 February 2010 - 08:08 PM.

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#9 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 05 February 2010 - 08:17 PM

AAAND - this is why it is fun to play with this stuff, folks - you learn new things every day!

With our dear friend Imported Abdel, a single class fighter, both option 1 and option 2 show up. 3 does not show up.

Well, let's check that it still works that way if the player has a kit assigned. Let's start a new fighter character, and give them a kit, and try the same thing.

EDIT>

Well, this is completely unexpected - Ellie the Test Girl, a true neutral Kensai, also has option 1 { always true } and option 2 { !Kit(Player1,NMSUNE) evaluated to !Kit(Player1,0) }.

So this Kit(Player1,0) returns false. !Kit(Player1,0) returns true.

Interesting.

What this appears to show is that I could play around using kit references that are not installed, knowing that they will evaluate to false if the kit is not there.

For tomorrows test, will installing this and then installing DR result in what I expect (that the NMSUNE kit.ids reference needs to be in place before Aran is installed - it seems only logical, because if an undefined .ids reference = 0, then how could the 0's get magically remapped to different values).

Edited by cmorgan, 05 February 2010 - 08:33 PM.

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#10 devSin

devSin
  • Modders
  • 3017 posts
  • Gender:Male

Posted 05 February 2010 - 09:00 PM

When an IDS value is resolved by the compiler, invalid values get turned into zero (BCS is a fixed format, so everything is already defaulted to '0' and "" empty strings--you can't *add* data to BCS code, merely change the value of what's already there--and WeiDU compiles BCS code when compiling dialogues and then outputs the decompiled compiled code in the actual dialogue, instead of trusting the modder and simply using what you wrote in the D). (You can also chomp off parameters and such with bad IDS files because our compilers are so dumb.)

If the engine sees your NMSUNE and can't find it, it's just invalid (and false). If it encounters Kit(0), it should just be a literal compare with the CRE kit value. No PC should ever have this, because the engine defaults to 0x4000 at character creation. If the engine is checking only part of the word, though, then this might trigger for barbarians and wild mages who don't have any of their kit value in the right word IIRC (if you could get WeiDU to leave NMSUNE alone and not try to compile it, though, it should fail gracefully everywhere). When the value is already compiled to 0, decompiling and recompiling with WeiDU can change the value if there's a "0" symbol in the local IDS, and NI will also show you resolved code (in some versions) in the View mode for the dialogue (if you select the trigger or action in the Edit list, you'll get what's actually in the DLG, but in the View pane, the code is compile/decompile-checked, and we cache the IDS top-down, opposite from WeiDU, and return the first match, so you could get your NumTimesTalkedTo() mysteriously appearing to be NumberOfTimesTalkedTo() and such in the View pane, depending on what symbol we find first in the IDS).

Object ID values (general, race, class, etc.) and their triggers treat '0' as a "wildcard" and match anything, but they're special (kit isn't part of the object spec).

I'd recommend only bothering to test Kit(0) with a barb or wm, and Kit(NMSUNE) (always fail) and !Kit(NMSUNE) (hopefully always true) with any character when NMSUNE isn't in Kit.ids (I believe the script engine fails gracefully enough to have Kit(error) return false and !Kit(error) return true instead of discarding the entire trigger, but best to check). You can add NMSUNE to the IDS and then delete it after WeiDU has compiled the dialogue if you can't get it to not compile to 0.

Edited by devSin, 05 February 2010 - 09:18 PM.


#11 Nythrun

Nythrun

    Long since out to pasture

  • Modders
  • 1761 posts
  • Gender:Female

Posted 06 February 2010 - 02:10 AM

this might trigger for barbarians and wild mages who don't have any of their kit value in the right word


Yeah :thumbsup: Their kit values are handled entirely in hardcode; mods that try to assign nonzero values in kit.ids just end up breaking kit checks for these two. But Heartwarder of Sune is a cleric kit, so no fuss.

I suppose if you really wanted to be showoffy about it, you could compile the dialogue with False() standing in for the nmsune kit, then
ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~False()~ ~Kit(Player1,nmsune)~  
  >>>>>>>>
  COMPILE blahblah.d
END
would be a low effort way to do things.
"You tell lies, too."
"Not I." The witch laughed; her laughter was clear and yet unpleasant. "I used to as a child, I confess. But I soon found the truth more disconcerting."

#12 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 07 February 2010 - 10:04 AM

Cool feedback, thanks!

I'd recommend only bothering to test Kit(0) with a barb or wm, and Kit(NMSUNE) (always fail) and !Kit(NMSUNE) (hopefully always true) with any character when NMSUNE isn't in Kit.ids (I believe the script engine fails gracefully enough to have Kit(error) return false and !Kit(error) return true instead of discarding the entire trigger, but best to check). You can add NMSUNE to the IDS and then delete it after WeiDU has compiled the dialogue if you can't get it to not compile to 0.


That's what I shall do!

This feedback, and Nythrun's idea about
ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~False()~ ~Kit(Player1,nmsune)~  
  >>>>>>>>
  COMPILE blahblah.d
END

already give us some potential solutions, even before testing the full idea out to find out if Barbs and Wild Mages garbage us out of working code. We will test out the rest of this in a bit, but first, some escape-the-problem thinking.

Our best-case scenario is that
A. the player who wants kit content to play and does not follow install order can still play without getting garbage that does not make sense (or worse doesn't work).
B. the player who does not care is not slapped with troubles for not having DR ionstalled.
C. the player who changes their mind or screws up install order putting DR afterwards still can fix this without undoing the whole install.

Ambitious? Yes. Possible? Perhaps.


Possible solutions.

1. Require Divine Remix be installed beforehand.
The NMSUNE will be a valid kit, and as a result of this testing we have a note for the workroom; if a player reporst that this is broken, scanning the decompiled .dlg for Kit(Player1,0) will pop up and identify that they have put things in the wrong order. This, by the way, has historically been the way to fix things - make things install order dependent, or work with another modder to fix things like this by cross-pollination.

Advantage: we can play with all the DR kits for replies.

Disadvantage: requiring a mod other than a foundational one like BG2 Fixpack curtails player choice at a core level. Not every player wants those kist - even with the way-cool ToB-EX and the new .exe tweaks to allow lots of kits to be present and visible and valid for PCs, we are headed away from the basic idea behind Aran. So, this is a last resort option. It basically says "do it my way or suffer the consequences".

What else could we do?

2. We could add the full NMSUNE kit ourselves, in our mod.
G3 mods tend to be of the "hey, if it works, use it" variety - taking that kit and adding it via Aran, with an escape if DR is not already installed might be a fine idea. 1 PP and the new Infinity Animations materials in Aroura's Shoes, the cross-mod duplicated fixes (and not-installed-if-the-other-modder-already-fixes-it) found in UB/BG1NPC/SCS/SCSII [and the list goes on...]

Advantage: logical fix, and it makes Aran self-sustaining, self-referential, and completely independent.

Disadvantage: many.

Looking at Detectable Stats, or the pains suffered by BiG world folks working through things, or even just keeping stuff between BG1NPC and BG1 UB involves joint update of code, or you get a mess. DR gets an update, the fixes don't transfer magically to the other mods. And even when modders work hard to do the right thing by eachother, RL release timings are always off, and a bunch of folks will not upgrade or will find an old copy on a mirror somewhere...
With DR, I might get lucky. The coders probably put some sanity checks to make sure that the kit isn't installed twice, and probably did not leave things so that if one kit were installed the whole mod could not be installed again. But if I were expecting to work with another mod, I would expect that adding the kit might pose some challenges. So I would need alot of testing to make sure that I don't break another mod. Plus, I would need to really understand all of the DR code to bring over what I need. I might be able to get away with the kit and CLAB stuff. Err... no, on second thought, looking at the DR code, this rebuilds clabs and adds specialty spells for the kits and so much more... and the whole idea off adding in all the resources to be potentially called is not a strong enough to cover other mod added kits in other situations, unless a modder pulls more and more of other folk's work into their mod, making it bloated and more and more likely to mess other people up.

Possible to do, but tons of work to learn what needs to be done, with a high probability of abject failure, or at best code I don't understand how to troubleshoot effectively in my own mod. What else do we have?

3. We could fake an NMSUNE in the IDS, and see if it fails the way devSin expects it does.

This is easy to do, as we have the good old .tp2 to help us out, using APPEND <> UNLESS, the same way we add to other .2da / .ids files. We need to figure out how to capitalize on the materials devSin just mentioned about different .ids evaluation order, because it might be a problem if we entered a fake value to an invalid kit and then DR comes along and adds the real value but the .ids map keeps using the fake value... or if the modder has protected against double-installation by looking at the .ids file to see if the mod has already been installed and fids the false entry, and does not add needed patching. Basically, a variation on the problem misuse/incomplete understanding of how to use ALLOW_MISSING might cause troubles.

that is an interesting idea to try! This has the potential to allow as many mod-added kits to be referenced, and if we can figure it out, leaves very little impact on code. The goal for this experiment would be to find a way to assign a kit.ids with a faked entry, and if the player installs the kit before or after Aran, the real entry mapping be set to either replace the false one or be evaluated first. Something to play with.

4. We could use Nythrun's idea in a few ways. We could take it directly, doing
ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~False()~ ~Kit(Player1,nmsune)~  
  >>>>>>>>
  COMPILE blahblah.d
END
so that when Aran is installed but nmsune isn't, the reply states are false and not triggered, but when the mod is present the kit reference gets placed as the trigger. We could extend that to all sorts of stuff - right after the PID is installed, force a final component that "patches" Aran to fit his environment by replacing some of the triggers in .bcs or .dlg to fit his environment.
We could also do this at the .tp2 level, where we variable-ize the dialog, and run it through the COMPILE EVALUATE_BUFFER routine, so that

.d
+ ~%nmsunekit%~ + ~[ARAN] You are a Sunite Cleric, a HeartWarder!~ + a690
.tp2
ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN
  OUTER_SET ~nmsunekit~ ~NMSUNE~
  END ELSE BEGIN 
  OUTER_SET ~nmsunekit~ ~False()~
END

COMPILE EVALUATE_BUFFER blahblah.d

Either way, this makes things pretty flexible. The .tp2 usage with C E_B does lock the install order, though. Since the variables are set and evaluated at install time, any mod already installed before Aran gets looked at, and anything that installs after him, of course, gets set to False(). No way out of that.

ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN  // DR's Sune
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~False()~ ~Kit(Player1,nmsune)~  
  >>>>>>>>
  COMPILE blahblah.d
END
ACTION_IF FILE_EXISTS_IN_GAME morituri.2da BEGIN  // Aroc's morituri kit
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~False()~ ~Kit(Player1,morituri)~  
  >>>>>>>>
  COMPILE blahblah.d
END
or SC#VDrd.2da if someone has managed to assign SConrad's Hubelpot kits to their PC looks like the most flexible option out there, because it means that we can create a patch or macro to be separately downloaded at the end of an install routine, to fix the mod if DR is out of sequence. The idea here is that the same file can be used in the mod, to account for materials already in the install, and then distributed as a separate patch that can be run at any time to take any other mods added after him into consideration. One file to update, and sevring both functions without any fuss.

We would need to make one change to this code to make it possible to mix and match mod-added kits within the same dialog - we swap the ~false()~ to a custom global trigger that we know will always be false, because we have not set it anywhere:

ACTION_IF FILE_EXISTS_IN_GAME nmsune.2da BEGIN  // DR's Sune
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~Global("c-kitSune","LOCALS",1)~ ~Kit(Player1,nmsune)~  
  >>>>>>>>
  COMPILE blahblah.d
END
ACTION_IF FILE_EXISTS_IN_GAME morituri.2da BEGIN  // Aroc's morituri kit
  <<<<<<<<blahblah.d  
  REPLACE_TRANS_TRIGGER whatever_aran BEGIN 0 1 2 END BEGIN 0 1 2 END
  ~Global("c-kitMori","LOCALS",1)~ ~Kit(Player1,morituri)~  
  >>>>>>>>
  COMPILE blahblah.d
END

so that the target is easily found. By extending this, we could concieveably run out independent reply lines that are directly tailored to an install's kits and additions -

+ ~Global("c-kitMori","LOCALS",1)~ +  ~[ARAN] You are one o' them death-kensai folks, eh? Big sword.~ + a690
+ ~Global("c-kitReaver","LOCALS",1)~ +  ~[ARAN] You don't bloody well need me, eh? Hey, just for kicks, tear through that wall wi' your bare hands.~ + a690
+ ~Global("c-kitGeoSorc","LOCALS",1)~ +  ~[ARAN] Got it. Step on a plant, an' you call nature's own wrath down on my sorry arse. I'll be stickin' to th' pathe, eh?~ + a690
+ ~Global("c-AbbyStore","LOCALS",10)~ +  ~[ARAN] I heard we could get some right quaint items from this lass named Abysima, down docks-way, if that helps. But go see her wi' a ton o' gold an' trade bars.~DO ~SetGlobal("c-AbbyStore","LOCALS",11)~ + a690
+ ~Global("c-Jasper","LOCALS",10)~ +  ~[ARAN] You keep mutterin' about some lad named St. Baird. What did he do to you, anyways?~  DO ~SetGlobal("c-Jasper","LOCALS",11)~ + a690
+ ~Global("c-KingDutkasThief","LOCALS",10)~ +  ~[ARAN] I just got to get me one o' them thier-summonin' rings. Where did you find that, anyhow? Can I buy it off o' you?~ DO ~SetGlobal("c-KingDutkasThief","LOCALS",10)~ + a690

We could even mix and match for install order, so that Aran is installed with content that fits what has been installed before him, and then patched at the end of an install to enable reply states that account for things installed afterwards, in his own miniature simplified version of an item/kit/class/game-changing-additional-set-of-quests-added crossmod.

Pros: easy to code, and takes the guesswork out of things.

Cons: bloated reply states, where we need to make sure that we don't end up with 14 replies instead of 3 to 7 with an average of 6, and more work to add them in. Plus, in the best case scenario, adding a mod to exted potential replies that may never be seen in-game - though this last can be adjusted by careful loop integration with the first dialog state in each tree.

NOTE: The only reason to have fun extending the replacements for other mods using the "replace 10 with 0, 11 with 1" approach above is that it might be a fun way of reducing the number of .bcs blocks needed. WeiDU will happily let you have variables added that have no referent or have no way of getting set, as we did above in the testing. The difference here is that instead of looking for a specific added item being in the party, we can spam out mod-specific dialog without having to have a triggering .bcs block.
In the case of kits, that "0" evaluation is the problem. On variables, anything goes - it is all in how you set the LOCALS or GLOBAL, or leave it impossible to rtrigger without CLUA, thus creating a "blocking variable', or an individually tailored and manipulatable "False()".



Not that I want to do this last thought, as I really would prefer to be as directly targeted as possible - but taken one step further, we can even just make the patch a REPLACE_TEXTUALLY, so that the dialog files get evaluated all in one pass:

My_Patch_to_customize_ARAN_to_your_install_because_I_am_just_that_OCD.tph
COPY_EXISTING ~c-aranj.dlg~ ~override~
  DECOMPILE_DLG_TO_D
	  REPLACE_TEXTUALLY ~Global("c-kitSune","LOCALS",1)~ ~Kit(Player1,NMSUNE)~
	  REPLACE_TEXTUALLY ~Global("c-kitMori","LOCALS",1)~ ~Kit(Player1,MORITURI)~
	  REPLACE_TEXTUALLY ~Global("c-AbbyStore","LOCALS",10)~ ~Global("c-AbbyStore","LOCALS",0)~
	  REPLACE_TEXTUALLY ~Global("c-AbbyStore","LOCALS",11)~ ~Global("c-AbbyStore","LOCALS",1)~
	COMPILE_D_TO_DLG
	BUT_ONLY_IF_IT_CHANGES

I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#13 cmorgan

cmorgan

    journeyman investigator

  • Gibberlings
  • 7097 posts
  • Gender:Male
  • Location:Glencoe, IL, USA

Posted 07 February 2010 - 12:18 PM

OK, some tests.

test1.d
APPEND ~IMOENJ~

IF WEIGHT #-1 ~Global("test1","GLOBAL",1)~ THEN BEGIN a100
  SAY ~[ARAN] What a blighted great place to be fightin' for our lives at every turn. So do you come here often? How's the food? Know any available converts o' Sune? You thinkin' o' convertin'?~
  IF ~~ THEN REPLY ~This state shows up all the time no matter what, so that if everything else fails I don't get stuck in an infinite script stutter...~ DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
  IF ~!Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, does not have a kit .ids reference of 0, so !Kit(Player1,NMSUNE) returns true.~ DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
  IF ~Kit(Player1,NMSUNE)~ THEN REPLY ~Hah. I have detected that Player 1, <CHARNAME>, has a kit .ids reference of 0, so Kit(Player1,NMSUNE) returns true.~  DO ~SetGlobal("test1","GLOBAL",2)~ EXIT
END

END

And our cast of characters, each on a brand new game, initial load, cutscene, and then the first Imoen dialog completed, CLUA to test1=1, and see what pops up. The results:

Freddie Freemason's (Wild Mage) PC reply says "Hah. I have detected that Player 1, Freddie Freemason, has a kit .ids reference of 0, so Kit(Player1,NMSUNE) returns true."

Boris BigBarbie's (Barbarian) PC Reply says "Hah. I have detected that Player 1, Boris BigBarbie, has a kit .ids reference of 0, so Kit(Player1,NMSUNE) returns true."

Clara Cleric's (Trueclass Cleric) PC Reply says "Hah. I have detected that Player 1, Clara Cleric, does not have a kit .ids reference of 0, so !Kit(Player1,NMSUNE) returns true."

Harriet HotHelmite's (Cleric kitted to Kit=GODHELM) PC Reply says "Hah. I have detected that Player 1, Harriet HotHelmite, does not have a kit .ids reference of 0, so !Kit(Player1,NMSUNE) returns true."

As we suspected, devSin and Nythrun know their stuff inside and out, and told us this would happen, because the Kit() call checks only a section of the storage that holds information, and both Barbarian and WildMage use a different part of the staorage area. So, what we have found out is that leaving it in and compiled the way we currently have it will result in unwanted behavior - without DR installed prior to Aran, we get the following:

IF Player1 is {Barbarian or WildMage}, Aran thinks PC is a HeartWarder and shows up inappropriate responses.

IF Player1 is a Heartwarder, Aran thinks PC is not a HeartWarder and hides the responses.

IF Player1 is anything else, Aran thinks PC is not a HeartWarder and hides the responses.


Now we just have to figure out the "fake a kit in the .ids" routine.
I love deadlines. I love the whooshing noise they make as they go by. - Douglas Adams

#14 Mike1072

Mike1072
  • Gibberling Poobah
  • 2526 posts
  • Gender:Male
  • Location:Canada

Posted 07 February 2010 - 03:22 PM

As we suspected, devSin and Nythrun know their stuff inside and out, and told us this would happen, because the Kit() call checks only a section of the storage that holds information, and both Barbarian and WildMage use a different part of the staorage area. So, what we have found out is that leaving it in and compiled the way we currently have it will result in unwanted behavior - without DR installed prior to Aran, we get the following:

IF Player1 is {Barbarian or WildMage}, Aran thinks PC is a HeartWarder and shows up inappropriate responses.

IF Player1 is a Heartwarder, Aran thinks PC is not a HeartWarder and hides the responses.

IF Player1 is anything else, Aran thinks PC is not a HeartWarder and hides the responses.

So, if you are trying to detect a Mage or Fighter kit, this won't be usable, as you might get a false positive. If you are trying to detect a kit for another class, like clerics, you can slap on a Class(Player1,CLERIC) to the kit check, and it will no longer return true for Wild Mages or Barbarians. This solution remains install-order dependent, though, so you may as well do the more cumbersome "check if kit is installed before enabling trigger" method so you have the option of detecting kits for any class.

#15 erik

erik

    Kobold sorcerer

  • Modders
  • 443 posts
  • Gender:Male
  • Location:fjords nearby

Posted 08 February 2010 - 10:38 AM

If you are trying to detect a kit for another class, like clerics, you can slap on a Class(Player1,CLERIC) to the kit check, and it will no longer return true for Wild Mages or Barbarians.


CLERIC_ALL, rather. (Kitted dualclasses & level1npc kitted multis. Who knows what a geomantic sorcerer will show up like on the radar.)

I really like the check if kit is installed before enabling trigger method. Elegant.



Reply to this topic



  



Also tagged with one or more of these keywords: modder discussion, troubleshooting, mod development, dialog coding, aran whitehand

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users