Jump to content


Photo

Familiar conversation


  • Please log in to reply
14 replies to this topic

#1 Bookwyrme

Bookwyrme
  • Modder
  • 5804 posts

Posted 09 July 2007 - 10:20 AM

I've been working on coding up banters for the Trio, and I'm currently stuck at the Familiar Question. One of the mages can acquire a familiar in the course of the game, and I want it to have a handful of interjections, some comments inserted in other conversations, and of course PID's--ultimately, 3 sets depending on who it is talking to. Trouble is, I've no idea what sort of coding form these should take, nor can I think of a mod that has a comparable character. Would a familiar/ally have banter files? Or what? What would be the best way for it to comment on conversations?

Also, can anyone point me to a good tutorial on PID's?

Many thanks! (And many, many questions to come, I'm quite sure).

Mods: <a data-cke-saved-href="http://www.shsforums...-auroras-shoes/">Aurora's Shoes (released),

 


 

 


#2 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 09 July 2007 - 12:14 PM

I can point you to a good working tutorial on PIDs = The BG1 NPC Project code. All PIDs are simply a single line IsGabber(Player1) checked dialogue, set up as scarily as you want with responses. They come true when no other condition that IsGabber(Player1) is reached, which is why you want your PIDs to be the last things installed in your mod (and you want to force the component to be uninstalled when someone changes something before it, then reinstalled after it, so that it always goes last.)

Example of simple PID code:
D:\BaldursGateTutu\BG1NPC\Phase3\PID\X#PCINIT.D

APPEND ~VICONJ~

IF ~IsGabber(Player1)~ THEN BEGIN VICH
SAY @0
++ @1 EXIT
END

END

This gives you a Player-Initiated Dialogue on the J file. When you force-talk/click-talk Viconia, it fires if nothing else is available.

The extent of your singe talk is pretty huge. A "small" PID from The BG1 NPC Project has 30+ potential responses, all controlled by conditions to be met - Class of Player1, globals set by other mods or your own mod, gender, alignment, combinations - the sky is the limit. All of it takes place within the single dialogue. Berelinde will be alonng in a minute or so to make this simpler, but i will jump to the end and post a working sample and break some of it down:

/* PI DIALOGUES */

APPEND ~VICONJ~

IF ~IsGabber(Player1)~ THEN BEGIN VICH
SAY @0
++ @1 EXIT //Always allowed, like "Oh, nothing."

/* This set shows one of the four following random responses to a conversation completed in the game */
+ ~Global("VICHdone","GLOBAL",1) RandomNum(4,1)~ + @2 + VICHFailure1
+ ~Global("VICHdone","GLOBAL",1) RandomNum(4,2)~ + @2 + VICHFailure2
+ ~Global("VICHdone","GLOBAL",1) RandomNum(4,3)~ + @2 + VICHFailure3
+ ~Global("VICHdone","GLOBAL",1) RandomNum(4,4)~ + @2 + VICHFailure4

/* This set shows one of the five following random responses if that conversation has not happened yet in the game */
+ ~!Global("VICHdone","GLOBAL",1) RandomNum(5,1)~ + @3 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) RandomNum(5,2)~ + @3 + VICHFailure1
+ ~!Global("VICHdone","GLOBAL",1) RandomNum(5,3)~ + @3 + VICHFailure2
+ ~!Global("VICHdone","GLOBAL",1) RandomNum(5,4)~ + @3 + VICHFailure3
+ ~!Global("VICHdone","GLOBAL",1) RandomNum(5,5)~ + @3 + VICHFailure4

/* These show up only for highly intelligent PCs */
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,INT) RandomNum(2,1)~ + @4 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,INT) RandomNum(2,2)~ + @4 + VICHFailure1

/* These for dummies */
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,1)~ + @4 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,2)~ + @4 + VICHFailure1
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,3)~ + @4 + VICHFailure2
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,4)~ + @4 + VICHFailure3
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,5)~ + @4 + VICHFailure4

/* These for wise Player1s */
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,WIS) RandomNum(2,1)~ + @5 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,WIS) RandomNum(2,2)~ + @5 + VICHFailure2
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,1)~ + @5 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,2)~ + @5 + VICHFailure1
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,3)~ + @5 + VICHFailure2
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,4)~ + @5 + VICHFailure3
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,5)~ + @5 + VICHFailure4

/* These for charismatic */
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,CHR) RandomNum(2,1)~ + @6 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) CheckStatGT(Player1,15,CHR) RandomNum(2,2)~ + @6 + VICHFailure3

/* These for UGLY. UGLY. */
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,CHR) RandomNum(5,1)~ + @6 + VICHSuccess
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,CHR) RandomNum(5,2)~ + @6 + VICHFailure1
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,CHR) RandomNum(5,3)~ + @6 + VICHFailure3
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,CHR) RandomNum(5,4)~ + @6 + VICHFailure2
+ ~!Global("VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,CHR) RandomNum(5,5)~ + @6 + VICHFailure4

/* This is a set of standard responses. Only one of the eight will show up each time, randomly */
+ ~RandomNum(8,1)~ + @7 + ViconiaPID1.1
+ ~RandomNum(8,2)~ + @7 + ViconiaPID1.2
+ ~RandomNum(8,3)~ + @7 + ViconiaPID1.3
+ ~RandomNum(8,4)~ + @7 + ViconiaPID1.4
+ ~RandomNum(8,5)~ + @7 + ViconiaPID1.5
+ ~RandomNum(8,6)~ + @7 + ViconiaPID1.6
+ ~RandomNum(8,7)~ + @7 + ViconiaPID1.7
+ ~RandomNum(8,8)~ + @7 + ViconiaPID1.8

/* This is a second set of standard responses. Only one of the eight will show up each time, randomly */
+ ~RandomNum(8,1)~ + @8 + ViconiaPID2.1
+ ~RandomNum(8,2)~ + @8 + ViconiaPID2.2
+ ~RandomNum(8,3)~ + @8 + ViconiaPID2.3
+ ~RandomNum(8,4)~ + @8 + ViconiaPID2.4
+ ~RandomNum(8,5)~ + @8 + ViconiaPID2.5
+ ~RandomNum(8,6)~ + @8 + ViconiaPID2.6
+ ~RandomNum(8,7)~ + @8 + ViconiaPID2.7
+ ~RandomNum(8,8)~ + @8 + ViconiaPID2.8

/* You get it now - males only! */
+ ~RandomNum(8,1) Gender(Player1,MALE)~ + @9 + ViconiaPID3.1
+ ~RandomNum(8,2) Gender(Player1,MALE)~ + @9 + ViconiaPID3.2
+ ~RandomNum(8,3) Gender(Player1,MALE)~ + @9 + ViconiaPID3.3
+ ~RandomNum(8,4) Gender(Player1,MALE)~ + @9 + ViconiaPID3.4
+ ~RandomNum(8,5) Gender(Player1,MALE)~ + @9 + ViconiaPID3.5
+ ~RandomNum(8,6) Gender(Player1,MALE)~ + @9 + ViconiaPID3.6
+ ~RandomNum(8,7) Gender(Player1,MALE)~ + @9 + ViconiaPID3.7
+ ~RandomNum(8,8) Gender(Player1,MALE)~ + @9 + ViconiaPID3.8

/* This one shows up all the time and allows a stringfixer to run, resetting Viconia's soundset if it gets scrambled */
++ @10 + ViconiaVoice


The most extreme version is Ajantis - looking at those PID entries, off of one response are literally hundreds of carefully tailored, crafted responses, set up to closely mirror the progress of the game, alignmemts, reputation, gender, class, attributes, chapter, number in the party, you name it - a game within a game. All designed to make the NPC appear to have something directly on point to say about any subject available.

Domi's K & D mod has a similar setup; but the most extreme implementation of this idea so far is Ajantis.

As for the familiars, I will take a look, but I think either they can e set up as independent creatures with a D file (wolves, for example, can be assigned a D file and be engaged in conversation just like an NPC) or they can be scripted into a banter.

OK , I can't find it in either BanterPack or Flirtpack, but I know it is there - somewhere, someone handles Boo with SetName(). It has to be jcompton - we will have to search his mods. i just can't find the reference right now...

Edited by cmorgan, 09 July 2007 - 12:46 PM.


#3 Bookwyrme

Bookwyrme
  • Modder
  • 5804 posts

Posted 09 July 2007 - 12:25 PM

Super! Thanks!

Edited by Bookwyrme, 09 July 2007 - 09:21 PM.

Mods: <a data-cke-saved-href="http://www.shsforums...-auroras-shoes/">Aurora's Shoes (released),

 


 

 


#4 Bookwyrme

Bookwyrme
  • Modder
  • 5804 posts

Posted 12 July 2007 - 06:42 PM

So a familiar could use banter? BTM#Pic or would he have to be J?

Mods: <a data-cke-saved-href="http://www.shsforums...-auroras-shoes/">Aurora's Shoes (released),

 


 

 


#5 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 12 July 2007 - 07:21 PM

I believe it would be the same as any NPC.

A quick read of the .cre for familiar shows two versions of each, one for SoA, the other for oB. A quick example:

FAMPSD.cre Allegiance = Ally - 4 dv = fampsd dlg = FAMIL1.DLG

FAMPDS25.cre Allegiance = Ally - 4 dv = fampsd dlg = FAMIL125.DLG

The file FAMIL125.DLG decompiled:

// creator  : DLTCEP_enhanced_WeiDU (version 199)
// argument : FAMIL125.DLG
// game	 : .
// source   : ./DATA/25DIALOG.BIF
// dialog   : ./dialog.tlk
// dialogF  : (none)

BEGIN ~FAMIL125~

IF ~!InPartySlot(LastTalkedToBy,0)~ THEN BEGIN 0 // from:
  SAY #72066 /* ~The small dragon-like creature purrs quizzically with wide eyes. Nervously it backs away towards <CHARNAME>. Obviously it doesn't want to talk to you.~ */
  IF ~~ THEN DO ~MoveToObject(Player1)~ EXIT
END

IF ~InPartySlot(LastTalkedToBy,0)~ THEN BEGIN 1 // from:
  SAY #72067 /* ~The small dragon-like creature flutters its wings happily, looking at you with almost kaleidoscopic eyes. "You wish something?" It awaits your attention, tail flicking.~ */
  IF ~!InventoryFull(Player1)
OR(2)
Alignment(Player1,MASK_LAWFUL)
Alignment(Player1,MASK_LCNEUTRAL)
~ THEN REPLY #72068 /* ~Come here.  I want to pick you up and put you in my pack where it's a bit safer.~ */ GOTO 2
  IF ~~ THEN REPLY #72070 /* ~(pet and play with it)~ */ GOTO 3
  IF ~CombatCounter(0)
!HPPercentLT(Myself,100)~ THEN REPLY #73426 /* ~(feed the familiar)~ */ GOTO 17
  IF ~CombatCounter(0)
HPPercentLT(Myself,100)~ THEN REPLY #73432 /* ~(feed the familiar)~ */ GOTO 18
  IF ~~ THEN REPLY #72095 /* ~You wouldn't happen to have any advice, would you?~ */ GOTO 4
  IF ~~ THEN REPLY #72096 /* ~How are you?  Everything okay down there?~ */ GOTO 5
  IF ~!InventoryFull(Player1)
Alignment(Player1,MASK_CHAOTIC)
~ THEN REPLY #72098 /* ~Come here.  I want to pick you up and put you in my pack where it's a bit safer.~ */ GOTO 13
  IF ~~ THEN REPLY #72097 /* ~No, it's alright.  Let's just keep going.~ */ GOTO 12
END

IF ~~ THEN BEGIN 2 // from: 3.0 1.0
  SAY #72069 /* ~Its eyes brighten, and it practically leaps into your arms, ready to be stowed amongst your belongings where it can sleep and occasionally poke its head out.~ */
  IF ~~ THEN DO ~GiveItemCreate("FAMPSD25",Player1,0,0,0)
DestroySelf()
~ EXIT
END

IF ~~ THEN BEGIN 3 // from: 1.1
  SAY #72071 /* ~The dragon coos with delight, it's multicolored eyes whirling as you pat its warm, leathery hide.  "You are very kind to me, my <PRO_LADYLORD>," it purrs.~ */
  IF ~!InventoryFull(Player1)
OR(2)
Alignment(Player1,MASK_LAWFUL)
Alignment(Player1,MASK_LCNEUTRAL)
~ THEN REPLY #72072 /* ~Come here.  I want to pick you up and put you in my pack where it's a bit safer.~ */ GOTO 2
  IF ~~ THEN REPLY #72073 /* ~You wouldn't happen to have any advice, would you?~ */ GOTO 4
  IF ~~ THEN REPLY #72083 /* ~How are you?  Everything okay down there?~ */ GOTO 5
  IF ~~ THEN REPLY #72091 /* ~Let's just keep going, then.~ */ GOTO 12
  IF ~!InventoryFull(Player1)
Alignment(Player1,MASK_CHAOTIC)
~ THEN REPLY #72093 /* ~Come here.  I want to pick you up and put you in my pack where it's a bit safer.~ */ GOTO 13
END

IF ~~ THEN BEGIN 4 // from: 3.1 1.4
  SAY #72074 /* ~The familiar cranes its neck back and looks up at you with a slightly bewildered expression.  "You wish to ask *me* for advice, my <PRO_LADYLORD>?"~ */
  IF ~True()~ THEN EXIT
  IF ~Global("chapter","GLOBAL",8)~ THEN GOTO 14
  IF ~Global("chapter","GLOBAL",9)~ THEN GOTO 15
  IF ~Global("chapter","GLOBAL",10)~ THEN GOTO 16
END

IF ~~ THEN BEGIN 5 // from: 3.2 1.5
  SAY #72084 /* ~The dragon flicks its tail with pleasure and gazes up at you with colorful eyes.  "So long as you are well, my <PRO_LADYLORD>, then I am well."~ */
  IF ~HPLT("famil1",48)
!HPLT("famil1",24)~ THEN GOTO 6
  IF ~HPLT("famil1",24)~ THEN GOTO 7
  IF ~!HPLT("famil1",48)
RandomNum(4,1)~ THEN GOTO 8
  IF ~!HPLT("famil1",48)
RandomNum(4,2)~ THEN GOTO 9
  IF ~!HPLT("famil1",48)
RandomNum(4,3)~ THEN GOTO 10
  IF ~!HPLT("famil1",48)
RandomNum(4,4)~ THEN GOTO 11
END

IF ~~ THEN BEGIN 6 // from: 5.0
  SAY #72085 /* ~"I... I am a little hurt, though, my <PRO_LADYLORD>.  The cuts sting, and I am bleeding.  It... it is not pleasant."~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 7 // from: 5.1
  SAY #72086 /* ~"I...I am hurt badly, my <PRO_LADYLORD>. I don't want to die, my <PRO_LADYLORD>. I want to stay with you." The dragon whimpers a little and curls its tail around your leg.~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 8 // from: 5.2
  SAY #72087 /* ~"But since you are asking, I could use a snack.  Perhaps a nice gopher.  Or some pie... ooooh, yes, I *like* pie!"~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 9 // from: 5.3
  SAY #72088 /* ~"I do like traveling with you.  Very much, my <PRO_LADYLORD>.  Do you have an apple?  I could roast the apple a little and then eat it down.  Apples are good!"~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 10 // from: 5.4
  SAY #72089 /* ~I am amazed at all the new places I see with you.  Everything is so wonderful and so colorful!  Is all of the world like this, my <PRO_LADYLORD>?"~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 11 // from: 5.5
  SAY #72090 /* ~"I feel wonderful, myself, my <PRO_LADYLORD>.  My hide is clean and I stand ready to aid you against danger!"~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 12 // from: 3.3 1.7
  SAY #72092 /* ~The dragon flicks its tail contentedly and then turns its eyes back to the path before you.  "As you wish, my <PRO_LADYLORD>."~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 13 // from: 3.4 1.6
  SAY #72094 /* ~Its eyes brighten, and it practically leaps into your arms, ready to be stowed amongst your belongings where it can sleep and occasionally poke its head out.~ */
  IF ~~ THEN DO ~GiveItemCreate("FAMFAI25",Player1,0,0,0)
DestroySelf()
~ EXIT
END

IF ~~ THEN BEGIN 14 // from: 4.1
  SAY #72694 /* ~The little dragon looks up at you for a moment, its eyes shimmering.  "You must survive, my <PRO_LADYLORD>.  Your heritage places you in great danger!"  It whips its tail about agitatedly.~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 15 // from: 4.2
  SAY #72695 /* ~Its bright eyes look piercingly into yours.  "There has been so much death, my <LADYLORD>.  So much destruction.  But I trust you will find the way to do what is right."~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 16 // from: 4.3
  SAY #72696 /* ~For a moment, the dragon growls fiercely.  "The imposter must die, my <LADYLORD>!  You must somehow go into the Throne of Bhaal and confront her!"~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 17 // from: 1.2
  SAY #73428 /* ~You offer the little dragon some nuts and berries that you have stored, and the dragon nibbles on a few of them but doesn't really seem all that hungry.~ */
  IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN 18 // from: 1.3
  SAY #73430 /* ~The dragon's eyes swirl with pleasure as it noisily gulps down a large quantity of nuts and berries that you have collected.  It's wounds visibly start healing immediately.~ */
  IF ~~ THEN DO ~ApplySpell(Myself,CLERIC_CURE_MODERATE_WOUNDS)~ EXIT
END

so the banter would have to be different calls for the familiar assigned/game started, I think. It doesn't matter that the current file acts as a PID - the banter states are called directly, so basically they are just storhouses to be drawn directly in via indexed call (a fancy way of saying "this should work like any other NPC").

If you are creating your own, you only need one. A banter chain would just call on the familiar file, but you would have to test what happens if the familiar is in the backpack. I don't know if CD_STATE_NOTVALID or other dialogue checks would fail if the familiar is in inventoory or not...

there was a person awhile back (someone with some good skills, too, I think ) playing with rebuilding an alternate set of familiars. You might do a forum search on several sites to see if they have more concrete, tested information!

#6 Gort

Gort
  • Validating
  • 614 posts

Posted 04 September 2007 - 06:45 PM

interesting, but is it possible to use 2 RandomNum() of different dice as a condition for a reply?

#7 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 04 September 2007 - 07:06 PM

Good question. It is certainly possible to incorporate randomness based on number of entries:

from a PID (originally coded by Domi/Ashara)


/* PI DIALOGUES */

APPEND ~%VICONIA_JOINED%~

IF ~IsGabber(Player1) %BGT_VAR%~ THEN BEGIN VICH
SAY @0
++ @1 EXIT

+ ~Global("X#VICHdone","GLOBAL",1) RandomNum(4,1)~ + @2 + VICHFailure1
+ ~Global("X#VICHdone","GLOBAL",1) RandomNum(4,2)~ + @2 + VICHFailure2
+ ~Global("X#VICHdone","GLOBAL",1) RandomNum(4,3)~ + @2 + VICHFailure3
+ ~Global("X#VICHdone","GLOBAL",1) RandomNum(4,4)~ + @2 + VICHFailure4

+ ~!Global("X#VICHdone","GLOBAL",1) RandomNum(5,1)~ + @3 + VICHSuccess
+ ~!Global("X#VICHdone","GLOBAL",1) RandomNum(5,2)~ + @3 + VICHFailure1
+ ~!Global("X#VICHdone","GLOBAL",1) RandomNum(5,3)~ + @3 + VICHFailure2
+ ~!Global("X#VICHdone","GLOBAL",1) RandomNum(5,4)~ + @3 + VICHFailure3
+ ~!Global("X#VICHdone","GLOBAL",1) RandomNum(5,5)~ + @3 + VICHFailure4

+ ~!Global("X#VICHdone","GLOBAL",1) CheckStatGT(Player1,15,INT) RandomNum(2,1)~ + @4 + VICHSuccess
+ ~!Global("X#VICHdone","GLOBAL",1) CheckStatGT(Player1,15,INT) RandomNum(2,2)~ + @4 + VICHFailure1

+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,1)~ + @4 + VICHSuccess
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,2)~ + @4 + VICHFailure1
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,3)~ + @4 + VICHFailure2
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,4)~ + @4 + VICHFailure3
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,INT) RandomNum(5,5)~ + @4 + VICHFailure4

+ ~!Global("X#VICHdone","GLOBAL",1) CheckStatGT(Player1,15,WIS) RandomNum(2,1)~ + @5 + VICHSuccess
+ ~!Global("X#VICHdone","GLOBAL",1) CheckStatGT(Player1,15,WIS) RandomNum(2,2)~ + @5 + VICHFailure2

+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,1)~ + @5 + VICHSuccess
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,2)~ + @5 + VICHFailure1
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,3)~ + @5 + VICHFailure2
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,4)~ + @5 + VICHFailure3
+ ~!Global("X#VICHdone","GLOBAL",1) !CheckStatGT(Player1,15,WIS) RandomNum(5,5)~ + @5 + VICHFailure4


etc.


The PID goes on for a good long time. In each case, RandomNum(#totalstatespossible,#forrandomstate)

gives you a supposedly equal chance of the numbers. These allow several possible responses to the given initial condition. The most common way to get the condition is to set it via I_C_T into another state if it is responding to an existing encounter or condition, or by setting the "blocking" or "activating" variable in your own added banter or dialogue.Then you can code normally, and when the PID or banter is called it can reflect what has happened before, and do it (using the RandomNum() ) slightly differently each time.

For a full treatment of this, see BG1NPC Project SharTeel Romance D fles and all the Phase3 PIDs. Other code inproject uses this as well, but the most extensive use of RandomNum() is probably SharTeel and the PID responses of several of the NPCs.

Technically, this is close to setting 1d2, 1d3, 1d4, etc. I do not know how you would weight the statistical probabilities differently to match 1d6+1, or 1d6+1d4 - I wouldn't bother, myself.

Edited by cmorgan, 04 September 2007 - 07:08 PM.


#8 Gort

Gort
  • Validating
  • 614 posts

Posted 04 September 2007 - 07:48 PM

actually, I don't quite understand what did you want to say. I was talking about constructions like this:
CHAIN IF ~~ THEN TM#Larj
~blah-blah-blah~
END
+~RandomNum(4,1) RandomNum(2,1)~+ ~answer1~ EXIT
+~RandomNum(4,2) RandomNum(2,2)~+ ~answer2~ EXIT
+~RandomNum(4,3) RandomNum(2,1)~+ ~answer3~ EXIT
+~RandomNum(4,4) RandomNum(2,2)~+ ~answer4~ EXIT

You see, I need to code PID that looks like this:
NPC1: ~hello~
Player: ~hello yourself~

NPC1:
//random answers
~answer1~
~answer2~
~answer3~
//additional answers, if certain NPC is in party. Also random.
(If NPC2 in party) ~answer4~
(If NPC3 in party) ~answer5~
(If NPC4 in party) ~answer6~

If I understand right, to use RandomNum and make these answers truly random, I need a set of answers for every possible combination of NPC2-4 in party. That's not a problem, while there are 3 of them - it would result in 6 sets. But actually there are 6 of them, and amount of sets grows tremendously (720, if I'm right). Or am I missing something?

Edited by Gort, 04 September 2007 - 07:57 PM.


#9 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 05 September 2007 - 03:18 PM

CHAIN
//blah blah

END
/* Answer set 1 - always shown one possible */
+ ~RandomNum(4,1)~ + ~Answer1NPC1~ + NewNPC1State1
+ ~RandomNum(4,2)~ + ~Answer2NPC1~ + NewNPC1State2
+ ~RandomNum(4,3)~ + ~Answer3NPC1~ + NewNPC1State3
+ ~RandomNum(4,4)~ + ~Answer4NPC1~ + NewNPC1State4

/* Answer set 2 */
+ ~InParty("MyNPC1") RandomNum(4,1)~ + ~Answer1NPC1~ + NewNPC1State1
+ ~InParty("MyNPC1") RandomNum(4,2)~ + ~Answer2NPC1~ + NewNPC1State2
+ ~InParty("MyNPC1") RandomNum(4,3)~ + ~Answer3NPC1~ + NewNPC1State3
+ ~InParty("MyNPC1") RandomNum(4,4)~ + ~Answer4NPC1~ + NewNPC1State4

/* Answer set 3 */
+ ~InParty("MyNPC2") RandomNum(4,1)~ + ~Answer1NPC1~ + NewNPC2State1
+ ~InParty("MyNPC2") RandomNum(4,2)~ + ~Answer2NPC1~ + NewNPC2State2
+ ~InParty("MyNPC2") RandomNum(4,3)~ + ~Answer3NPC1~ + NewNPC2State3
+ ~InParty("MyNPC2") RandomNum(4,4)~ + ~Answer4NPC1~ + NewNPC2State4

/* Answer set 4 */
+ ~InParty("MyNPC3") RandomNum(4,1)~ + ~Answer1NPC3~ + NewNPC3State1
+ ~InParty("MyNPC3") RandomNum(4,2)~ + ~Answer2NPC3~ + NewNPC3State2
+ ~InParty("MyNPC3") RandomNum(4,3)~ + ~Answer3NPC3~ + NewNPC3State3
+ ~InParty("MyNPC3") RandomNum(4,4)~ + ~Answer4NPC3~ + NewNPC3State4

gives you one answer randomly determined per NPC in party (and would of course need other options if none of the NPCs were in the party.

You would want to add the checks to make sure they were ok to talk.

This CHAIN would display one option from answer set 1 (randomly chosen from the 4 available),
one from answer set 2 if the NPC1 was in party,
one from answer set 3 if the NPC2 was in party,
one from answer set 4 if the NPC3 was in party.

It sounds like you want something even more complicated, though; to get even more randomness, you would code each of these into subset CHAINS (though I don't see what it gains you from a stoyrtelling perspective) - simply apply the next level on the responses. For example, following the above code if you follow NewNPC1State1,

CHAIN ~banterfile~ NewNPC1State1
~wow, this is getting a little chaotic~
END
+ ~RandomNum(8,1)~ + ~Answer1NPC1~ + NewNPC1State1.1
+ ~RandomNum(8,2)~ + ~Answer2NPC1~ + NewNPC1State2.1
+ ~RandomNum(8,3)~ + ~Answer3NPC1~ + NewNPC1State3.1
+ ~RandomNum(8,4)~ + ~Answer4NPC1~ + NewNPC1State4.1
etc...

The engine is *supposed* to give an equal chance for each group set {#,firstInSeries to #,#} to fire. There are some older posts that throw soem statistical doubt on it, but I have not seen that anyone has really done an in-depth study - it works well enough for any storytelling purposes. I do not think that adding additional random number calls to the first random number call will get you what you want (if it even works; it might be that the first one would just get reset by the second one).

Edited by cmorgan, 05 September 2007 - 03:23 PM.


#10 Gort

Gort
  • Validating
  • 614 posts

Posted 05 September 2007 - 07:26 PM

what you suggest results in:
(NPC1 reply) > (several condition-dependent PC replies) > (random NPC1 reply)
But I need
(NPC1 reply) > (1 constant PC reply) > (random NPC1 answers, several of which are condition-dependent)

Edited by Gort, 05 September 2007 - 11:55 PM.


#11 Bookwyrme

Bookwyrme
  • Modder
  • 5804 posts

Posted 05 September 2007 - 08:34 PM

Could you mix them? Each set could have a combination of non-conditional & conditional replies. It means the non-conditional replies will fire more often, but wouldn't it still be random enough?

Mods: <a data-cke-saved-href="http://www.shsforums...-auroras-shoes/">Aurora's Shoes (released),

 


 

 


#12 berelinde

berelinde

    Troublemaker

  • Modder
  • 4916 posts

Posted 05 September 2007 - 11:02 PM

IF ~IsGabber("Player1") Global("PIDNotAllowed","GLOBAL",1)~ PIDDisabled
SAY ~I'm in no mood to talk to you now.~
IF ~~ THEN EXIT
END

IF ~IsGabber("Player1") !Global("PIDNotAllowed","GLOBAL",1)~ PIDEnabled
SAY ~You wanted to speak to me?~
+ ~Global("Chapter","GLOBAL",2) AreaType(OUTDOOR) RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State1
+ ~Global("Chapter","GLOBAL",2) AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State2
+ ~Global("Chapter","GLOBAL",2) AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State3
+ ~Global("Chapter","GLOBAL",2) AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State4
+ ~Global("Chapter","GLOBAL",3) AreaType(OUTDOOR)  RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State5
+ ~Global("Chapter","GLOBAL",3) AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State6
+ ~Global("Chapter","GLOBAL",3) AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State7
+ ~Global("Chapter","GLOBAL",3) AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State8
+ ~Global("Chapter","GLOBAL",4) AreaType(OUTDOOR)  RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State9
+ ~Global("Chapter","GLOBAL",4) AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State10
+ ~Global("Chapter","GLOBAL",4) AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State11
+ ~Global("Chapter","GLOBAL",4) AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State12
+ ~Global("Chapter","GLOBAL",2) !AreaType(OUTDOOR) RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State13
+ ~Global("Chapter","GLOBAL",2) !AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State14
+ ~Global("Chapter","GLOBAL",2) !AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State15
+ ~Global("Chapter","GLOBAL",2) !AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State16
+ ~Global("Chapter","GLOBAL",3) !AreaType(OUTDOOR)  RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State17
+ ~Global("Chapter","GLOBAL",3) !AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State18
+ ~Global("Chapter","GLOBAL",3) !AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State19
+ ~Global("Chapter","GLOBAL",3) !AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State20
+ ~Global("Chapter","GLOBAL",4) !AreaType(OUTDOOR)  RandomNum(4,1)~ + ~I wondered if you had any advice.~ + NewNPC1State21
+ ~Global("Chapter","GLOBAL",4) !AreaType(OUTDOOR)  RandomNum(4,2)~ + ~I wondered if you had any advice.~ + NewNPC1State22
+ ~Global("Chapter","GLOBAL",4) !AreaType(OUTDOOR)  RandomNum(4,3)~ + ~I wondered if you had any advice.~ + NewNPC1State23
+ ~Global("Chapter","GLOBAL",4) !AreaType(OUTDOOR)  RandomNum(4,4)~ + ~I wondered if you had any advice.~ + NewNPC1State24
//ETC.
END

In the example above, I've got one preemptive condition that will run if the NPC (or familiar) is annoyed and doesn't want to talk at the moment, followed by a PID that will run at all other times. It gets a bit long, because you're going to want to offer more than one PC response option, but it works. You could just as easily make this a CHAIN by adding an END after the SAY (and losing the SAY) and using EXTERN instead of +, but I was using cmorgan's code to save myself some typing and didn't want to have to change all of those +'s to EXTERN ~DLGfile~.

It gives you (NPC1 reply) > (1 constant PC reply) > (random NPC1 answers, several of which are condition-dependent)

"Imagination is given to man to console him for what he is not; a sense of humor, for what he is." - Oscar Wilde

berelinde's mods
TolkienAcrossTheWater website
TolkienAcrossTheWater Forum


#13 Gort

Gort
  • Validating
  • 614 posts

Posted 06 September 2007 - 12:22 AM

well, it's just the same way to the same 720 responses, isn't it? I guess it just impossible to do it simply.

#14 berelinde

berelinde

    Troublemaker

  • Modder
  • 4916 posts

Posted 06 September 2007 - 02:53 AM

Unfortunately, no. It still isn't possible to nest triggers.

"Imagination is given to man to console him for what he is not; a sense of humor, for what he is." - Oscar Wilde

berelinde's mods
TolkienAcrossTheWater website
TolkienAcrossTheWater Forum


#15 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 06 September 2007 - 04:02 AM

Thanks, berelinde - I guess I wasn't getting the Viconia stuff broken down enough to show the answer clearly enough - sorry :)