Jump to content

IDS Codes Help


grogerson

Recommended Posts

I'm working on a tweak for BG1, taken from BG1NPC. Zed Nocear's AreaCheck Emulator took care of one of my problems. I still have two to go. I'd like some input, especially from berelinde or cmorgan.

 

InMyArea - looking at the IESDP information, both Detect and InteractingWith could work. Detect looks to be the best option, since InteractingWith looks like the NPC has to be talking, not the PC.

 

DisplayStringHead - from the IESDP, "This action displays the specified string over the head on the specified object (on the game-screen). The string may also be shown in the message log, depending on options specified in baldur.ini." It's part of the BG1NPC component "Bardic Reputation Adjustment," but I'm wondering if it's needed (by the description)? If it is, is there a work-around or other IDS code that can be used?

Link to comment
InMyArea - looking at the IESDP information, both Detect and InteractingWith could work. Detect looks to be the best option, since InteractingWith looks like the NPC has to be talking, not the PC.
1) Range is imo better than Detect as it allows for greater distance and is unaffected by invisibility

2) Make a huge infotrigger covering all the map with the IsOverMe in it's script

Link to comment
InMyArea - looking at the IESDP information, both Detect and InteractingWith could work. Detect looks to be the best option, since InteractingWith looks like the NPC has to be talking, not the PC.
InteractingWith() only returns true if the passed character is involved in an Interact() (banter) with the calling character. It's pretty limited; Detect() would work fine, with the caveat that the character targeted must be within visual range (~30). You can always use Exists() (I think it was available in BG/TotSC) if the targeted characters have unique script names, which should pick up any loaded object (it might not be totally reliable with global actors, i.e., characters who can join the party, though).

 

DisplayStringHead - from the IESDP, "This action displays the specified string over the head on the specified object (on the game-screen). The string may also be shown in the message log, depending on options specified in baldur.ini." It's part of the BG1NPC component "Bardic Reputation Adjustment," but I'm wondering if it's needed (by the description)? If it is, is there a work-around or other IDS code that can be used?
BG/TotSC doesn't support floating strings; you can simply use DisplayString() to provide console feedback (the only thing to change will be no overhead text).
Link to comment

@ Ardanis - Thanks, but I've little skill in modding so your second option won't work for me. That's why I call myself a cobbler or a thief (but an honest one - I let 'em know I'm taking it). Your description of Range helped.

 

@devSin - Since I'm dealing with joinable NPCs, who should be visible to the bard, I'll go with Detect(). And thanks for the DisplayString info. It helped.

 

Now I've managed to get the install further along, I now have a new set of code problems to work with.

 

OR didn't appear in the trigger.ids until SoA. I'd like to keep the following check intact, but I need a substitute or workaround.

 

++ @2 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
+ ~OR(2) InParty("garrick") InParty("eldoth")~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard

 

PALADIN_ALL and THIEF_ALL in the class.ids were added by SoA. They would add a couple of dialog options, but aren't needed.

 

DestroyGold() was also added by SoA to the action.ids. Is there a similar function that can be used? I could remove it, but there's a possible exploit here I'd like to avoid.

 

I'll be looking for possibilities myself, but feedback and ideas from the more experienced is always desirable.

Link to comment
Now I've managed to get the install further along, I now have a new set of code problems to work with.

 

OR didn't appear in the trigger.ids until SoA. I'd like to keep the following check intact, but I need a substitute or workaround.

 

++ @2 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
+ ~OR(2) InParty("garrick") InParty("eldoth")~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard

http://forums.blackwyrmlair.net/index.php?showtopic=999 - this tutorial is mainly about scripts. You can probably use the first method for dialogues, though.

 

PALADIN_ALL and THIEF_ALL in the class.ids were added by SoA. They would add a couple of dialog options, but aren't needed.

If I'm not mistaken, you should be able to directly replace PALADIN_ALL with PALADIN (the _ALLs being used to detect multi-classes). Class(x,THIEF_ALL) could be replaced by Class(x,THIEF) or Class(x,FIGHTER_THIEF) or Class(x,FIGHTER_MAGE_THIEF) or Class(x,MAGE_THIEF) or CLERIC_THIEF - using that workaround for OR.

 

DestroyGold() was also added by SoA to the action.ids. Is there a similar function that can be used? I could remove it, but there's a possible exploit here I'd like to avoid.

Perhaps...

TakePartyGold(I:Amount*)

This action takes the specified amount of gold from the party. If performed by a party member, the gold is transferred to that characters gold stat (in the CRE file) and re-added to the party pot when the character re-joins the party.

Link to comment
DestroyGold() was also added by SoA to the action.ids. Is there a similar function that can be used? I could remove it, but there's a possible exploit here I'd like to avoid.
Gold may be taken by another actor, perhaps invisible to hide this technical workaround, who would disappear then.
Link to comment

For OR() in dialogues transitions, triple up (++ @2; + ~InParty("a") !InParty("b")~ + @3; + ~InParty("b") !InParty("a")~ + @3; + ~InParty("a") InParty("b")~ + @3). Obviously, this'd be a lot simpler with "pure" (GOTO) trans than exclusive replies, but what can you do.

Link to comment
For OR() in dialogues transitions, triple up (++ @2; + ~InParty("a") !InParty("b")~ + @3; + ~InParty("b") !InParty("a")~ + @3; + ~InParty("a") InParty("b")~ + @3). Obviously, this'd be a lot simpler with "pure" (GOTO) trans than exclusive replies, but what can you do.

Could this not simplify to 2 transitions? From the original 1 transition ~OR(2) InParty("a") InParty("b")~ to...

  1. ~InParty("a")~
  2. ~InParty("b")~

Link to comment

Or even, in this case, just a check to see if Player1,2,3,4,5,6 is a bard? the only reason for the line is to make sure there is an option that mentions that the party already has a bard around, so might not need bardic help (the "Yo, we don't kneed anything; but what is it you do that's different?" option).

 

The class exists in BG, right - so

 

+ ~Class(Player1,BARD)~ +

+ ~Class(Player2,BARD)~ +

+ ~Class(Player3,BARD)~ +

+ ~Class(Player4,BARD)~ +

+ ~Class(Player5,BARD)~ +

+ ~Class(Player6,BARD)~ +

 

 

or in devSin-approved "use the numbers",

 

+ ~Class(Player1,5)~ +

+ ~Class(Player2,5)~ +

+ ~Class(Player3,5)~ +

+ ~Class(Player4,5)~ +

+ ~Class(Player5,5)~ +

+ ~Class(Player6,5)~ +

 

the only oddity is the line would duplicate if more than one of the party were a bard.

(I should probably mess with something like this in the Tutu code, too, as teh line should play if a multiplayer or other bard character is in the party...)

 

I would skip the display string completely. The original idea was to highlight the new caharcter, but you could do that any number of ways, including a simple script addition that sends teh bard over to the PC once to let them know the bard exists.

Link to comment
Could this not simplify to 2 transitions? From the original 1 transition ~OR(2) InParty("a") InParty("b")~ to...

  1. ~InParty("a")~
  2. ~InParty("b")~

Because they're replies, this would cause @3 to show up twice when both are in the party; the extra stuff is needed to ensure that you only get the reply once if either or both are in the party. If there were no response (i.e., it was a simple GOTO/EXTERN transition), you'd only need the two (although BG/TotSC dialogue handling is slightly different IIRC, but I can't remember the details of what exactly was different).
Link to comment
Could this not simplify to 2 transitions? From the original 1 transition ~OR(2) InParty("a") InParty("b")~ to...

  1. ~InParty("a")~
  2. ~InParty("b")~

Because they're replies, this would cause @3 to show up twice when both are in the party; the extra stuff is needed to ensure that you only get the reply once if either or both are in the party. If there were no response (i.e., it was a simple GOTO/EXTERN transition), you'd only need the two (although BG/TotSC dialogue handling is slightly different IIRC, but I can't remember the details of what exactly was different).

Ah, okay. I thought I must have missed something obvious.

 

Or even, in this case, just a check to see if Player1,2,3,4,5,6 is a bard? the only reason for the line is to make sure there is an option that mentions that the party already has a bard around, so might not need bardic help (the "Yo, we don't kneed anything; but what is it you do that's different?" option).

 

The class exists in BG, right - so

 

+ ~Class(Player1,BARD)~ +

+ ~Class(Player2,BARD)~ +

+ ~Class(Player3,BARD)~ +

+ ~Class(Player4,BARD)~ +

+ ~Class(Player5,BARD)~ +

+ ~Class(Player6,BARD)~ +

 

 

or in devSin-approved "use the numbers",

 

+ ~Class(Player1,5)~ +

+ ~Class(Player2,5)~ +

+ ~Class(Player3,5)~ +

+ ~Class(Player4,5)~ +

+ ~Class(Player5,5)~ +

+ ~Class(Player6,5)~ +

 

the only oddity is the line would duplicate if more than one of the party were a bard.

(I should probably mess with something like this in the Tutu code, too, as teh line should play if a multiplayer or other bard character is in the party...)

 

I would skip the display string completely. The original idea was to highlight the new caharcter, but you could do that any number of ways, including a simple script addition that sends teh bard over to the PC once to let them know the bard exists.

Maybe one of his first reply-less transitions could turn into:

++ @1 + HasNoBard (alternately ~!Class(Player1,5) !Class(Player2,5) !Class(Player3,5) !Class(Player4,5) !Class(Player5,5) !Class(Player6,5)~)

+ ~Class(Player1,5)~ + @1 + HasBard

+ ~Class(Player2,5)~ + @1 + HasBard

+ ~Class(Player3,5)~ + @1 + HasBard

+ ~Class(Player4,5)~ + @1 + HasBard

+ ~Class(Player5,5)~ + @1 + HasBard

+ ~Class(Player6,5)~ + @1 + HasBard

 

That or his initiating dialogue state could be expanded into multiple ones with these terms.

Link to comment

I think that's a great idea. I'd have to look, but there weren't many reply-less transitions, but that wouldn'tt stop it; just put the original line and branch it there to two sets of replies. It might even be possible without writing and lines; there might be a recyclable line if a new one is needed (or you could rewrite them, grogerson, and add what you want :) ). I think at the time of writing, both berelinde and I were very much into the coolness of CHAIN and dialog options, and liked the "everyone comments" deal, so we stopped with the dialog option filters rather than doing EXTERN/GOTO filters. I bet the same basic structure could be created quite easily by following that devSin/Mike1072 combo idea, splitting at a GOTO for folks with a bard vs without a bard (and simply duplicating the other options available).

Link to comment

@Mike1072 - I thought about PALADIN last night...after I went to bed. :) As for THIEF_ALL, is this how it should run?

IF ~Class(Player1,THIEF) or Class(Player1,FIGHTER_THIEF) or Class(Player1,FIGHTER_MAGE_THIEF) or Class(Player1,MAGE_THIEF) or Class(Player1,CLERIC_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP1RepTalk","GLOBAL",1)~ EXIT

@devSin, cmorgan - I like the idea of checking each party slot instead of just checking for the two BioWare bards. Please remember, though, you are dealing with an old dog trying to learn new tricks (modding), and I have more energy than intelligence. That's why I'm trying to avoid messing with what's already there as much as possible. And that's why I'm saving the banter lines for last (yes, I had an error there too). I expect the banters will take a lot of work.

 

Would this work, and is it what you were thinking, cmorgan?

++ @2 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
+ ~Class(Player1,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard
+ ~Class(Player2,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard
+ ~Class(Player3,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard
+ ~Class(Player4,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard
+ ~Class(Player5,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard
+ ~Class(Player6,5)~ + @3 EXTERN ~X#LP1REP~ X#Troubador1OwnBard

Link to comment

IF ~Class(Player1,THIEF) or Class(Player1,FIGHTER_THIEF) or Class(Player1,FIGHTER_MAGE_THIEF) or Class(Player1,MAGE_THIEF) or Class(Player1,CLERIC_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP1RepTalk","GLOBAL",1)~ EXIT

 

would be

~OR(5) Class(Player1,THIEF) Class(Player1,FIGHTER_THIEF) Class(Player1,FIGHTER_MAGE_THIEF) Class(Player1,MAGE_THIEF) Class(Player1,CLERIC_THIEF)~

 

on the BG2 engine - for BG, it might be a bit more difficult.

 

I was thinking

/* SAM */
/* Initial Meeting */
CHAIN IF ~NumTimesTalkedTo(0) Global("X#LakeP1RepTalk","GLOBAL",0)~ THEN ~X#LP1REP~ X#Troubador1Start
@0
END
++ @1 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
++ @2 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
++ @4 EXTERN ~X#LP1REP~ X#Troubador1OfferHearMeOut
++ @5 EXTERN ~X#LP1REP~ X#Troubador1OfferDeclined
IF ~Class(Player1,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter
IF ~Class(Player2,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter
IF ~Class(Player3,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter
IF ~Class(Player4,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter
IF ~Class(Player5,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter
IF ~Class(Player6,5)~ THEN  EXTERN ~X#LP1REP~ X#Troubador1OwnBardfilter

/* Filter State for bards in the party */
APPEND ~X#LP1REP~

IF ~~ X#Troubador1OwnBardfilter
 SAY @3
 IF ~~ THEN GOTO X#Troubador1OwnBard
END

END // of APPEND

/* We've got our own bard */
CHAIN ~X#LP1REP~ X#Troubador1OwnBard
@14
END
++ @12 EXTERN ~X#LP1REP~ X#Troubador1OfferInterested
++ @15 EXTERN ~X#LP1REP~ X#Troubador1OfferDeclined

 

Actually, that last is a misuse of CHAIN on my part, like using an elephant gun to swat a mosquito. It should be

 

APPEND ~X#LP1REP~ 

/*SAM */
/* Initial Meeting */
IF ~NumTimesTalkedTo(0) Global("X#LakeP1RepTalk","GLOBAL",0)~ THEN  X#Troubador1Start
SAY @0
 ++ @1 + X#Troubador1OfferInterested
 ++ @2 + X#Troubador1OfferInterested
 ++ @4 + X#Troubador1OfferHearMeOut
 ++ @5 + X#Troubador1OfferDeclined
 IF ~Class(Player1,5)~ THEN  GOTO X#Troubador1OwnBardfilter
 IF ~Class(Player2,5)~ THEN  GOTO X#Troubador1OwnBardfilter
 IF ~Class(Player3,5)~ THEN  GOTO X#Troubador1OwnBardfilter
 IF ~Class(Player4,5)~ THEN  GOTO X#Troubador1OwnBardfilter
 IF ~Class(Player5,5)~ THEN  GOTO X#Troubador1OwnBardfilter
 IF ~Class(Player6,5)~ THEN  GOTO X#Troubador1OwnBardfilter
END

/* Filter State for bards in the party */
APPEND ~X#LP1REP~

IF ~~ X#Troubador1OwnBardfilter
 SAY @3
 IF ~~ THEN GOTO X#Troubador1OwnBard
END

/* We've got our own bard */

IF ~~ X#Troubador1OwnBard
 SAY @14
 ++ @4 + X#Troubador1OfferHearMeOut
 ++ @12 + X#Troubador1OfferInterested
 ++ @15 + X#Troubador1OfferDeclined
END

END // of APPEND

That way, any in-party bard kicks the dialog in that direction, but the player gets all the options the original had, too. And it avoids all the OR behaviors - it runs down each player, evaluates, and redirects if any of them come up as a bard, and the dialog replies from the original state show up if no one comes up all singingmaster/lutist/cornetto/chanteause/dancer.

 

Like I said, we were really getting massively excited by CHAIN, and I had just reread Zrayen's cool "Abuse of CHAIN" rescued on the old CoM boards, where he showed how (technically) you could code an entire mod, quests, banters, and all, in large groups of CHAIN. That component could probably use a recode to simplify. Simple is almost always better.

Link to comment
I think that's a great idea. I'd have to look, but there weren't many reply-less transitions, but that wouldn'tt stop it; just put the original line and branch it there to two sets of replies. It might even be possible without writing and lines; there might be a recyclable line if a new one is needed (or you could rewrite them, grogerson, and add what you want ;) ). I think at the time of writing, both berelinde and I were very much into the coolness of CHAIN and dialog options, and liked the "everyone comments" deal, so we stopped with the dialog option filters rather than doing EXTERN/GOTO filters. I bet the same basic structure could be created quite easily by following that devSin/Mike1072 combo idea, splitting at a GOTO for folks with a bard vs without a bard (and simply duplicating the other options available).

You replied in ahead of me here, so I'm not sure if my ideas will still be helpful, but oh well.

 

Let me reassure everyone that I still have no idea what I'm talking about with regards to dialogue, but hopefully I'll be able to get away with it. Yeah, I actually meant for those lines not to have a + @1... so the check would occur behind the scenes. I take it we're talking about x#lp[1-3]rep.d files from the BG1NPC component 'Bardic Reputation Adjustment' - it looks like they all simply speak one line and then you should immediately be able to reply that you already have a bard.

 

CHAIN IF ~NumTimesTalkedTo(0) Global("X#LakeP2RepTalk","GLOBAL",0)~ THEN ~X#LP2REP~ X#Troubador2Start
@0
END
++ @1 EXTERN ~X#LP2REP~ X#Troubador2OfferInterested
++ @2 EXTERN ~X#LP2REP~ X#Troubador2OfferInterested
+ ~OR (2) InParty("garrick") InParty("eldoth")~ + @3 EXTERN ~X#LP2REP~ X#Troubador2OwnBard
++ @4 EXTERN ~X#LP2REP~ X#Troubador2OfferHearMeOut
++ @5 EXTERN ~X#LP2REP~ X#Troubador2OfferDeclined

If leaving it the way it is with the Garrick/Eldoth checks, devSin's 3 replies would work handily in place of the OR line for BG1.

 

If you do change it to check all players to be bards, you'll probably also need to alter @14 (~...I most humbly submit that I might exceed his talents...~). It will also be less easy to make BG1 only display 1 reply instead of 6 (devSin's method would require 2^X - 1 transitions, or 63 in place of ~OR (6) ...~, if I'm not mistaken).

 

To make BG1 show only 1 reply with 'less' work, my ideas were:

 

Option 1: Find (or invent) a previously reply-less transition before the reply in question (in this case you'd have to invent one by changing the @0 response into 2 strings) and put 2 transitions in the first state, both of which lead to the second state (containing the original reply options quoted above). One transition would check that all players are not bards, and if true, set a variable such as "X#TroubadorHasOwnBard" to 2. If the check was false (ie. you have at least one bard), it would evaluate the transition above it (which will have no conditions) that sets "X#TroubadorHasOwnBard" to 1. Then, change the OR check in the second state to check the variable instead (~Global("X#TroubadorHasOwnBard",GLOBAL,1)~).

 

Option 2: Duplicate the entire state quoted above, adding conditions that each player is not a bard. Then remove its entire transition containing the OR check. Make sure it is weighted so that it is evaluated before the original state, and alter the original state's bard transition to have an empty trigger (always true).

 

Neither of these options function as generic solutions to ORs in dialogues, but should work in this case.

 

@Mike1072 - I thought about PALADIN last night...after I went to bed. :) As for THIEF_ALL, is this how it should run?

IF ~Class(Player1,THIEF) or Class(Player1,FIGHTER_THIEF) or Class(Player1,FIGHTER_MAGE_THIEF) or Class(Player1,MAGE_THIEF) or Class(Player1,CLERIC_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP1RepTalk","GLOBAL",1)~ EXIT

Sorry if I was unclear. You'd normally need to do the same thing with it as you would with the other ORs - try to convert it from ~OR (5) Class(Player1,THIEF) Class(Player1,FIGHTER_THIEF) Class(Player1,FIGHTER_MAGE_THIEF) Class(Player1,MAGE_THIEF) Class(Player1,CLERIC_THIEF)~. Taking a closer look at it, though, since Player1 couldn't be, for example, a CLERIC_THIEF at the same time as being a MAGE_THIEF or any of the others, you could simply duplicate the line for each class check:

Before:
IF ~Class(Player1,THIEF_ALL)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT

After:
IF ~Class(Player1,THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT
IF ~Class(Player1,FIGHTER_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT
IF ~Class(Player1,FIGHTER_MAGE_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT
IF ~Class(Player1,MAGE_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT
IF ~Class(Player1,CLERIC_THIEF)~ THEN REPLY @99 DO ~SetGlobal("X#TroubadorRep","GLOBAL",1) SetGlobal("X#LakeP2RepTalk","GLOBAL",1)~ EXIT

 

P.S. cmorgan: I randomly found what might be a typo: in state X#T2MB20.3 of x#lp2rep.d, the trigger condition is ~PartyGoldGT(2999)~ while it removes 2800 gold - from what he says, it sounds like 2800 is the right amount and the condition should be ~PartyGoldGT(2799)~.

 

P.P.S. cmorgan: I noticed the THIEF/PALADIN lines check Player1's class - wouldn't it be more logical to check LastTalkedToBy(Myself)'s class? I can recall noticing this in other parts of the game(s), and it's always bothered me when one of my NPCs noticeably has an option that's Player1-specific.

Link to comment

Archived

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

×
×
  • Create New...