Jump to content

Creating the .bcs (script)


cmorgan

Recommended Posts

Starting the main SoA script for Aran, C-ARAN.BCS.

 

A quick reminder - the character's .BCS file is a script. It tells the game engine when it is time (and under what conditions) actions happen. There are all sorts of scripts; here, we are working with the "override script", the highest level. It runs when your NPC is going about his business, stops when he is dead, and generally controls anything you want it to.

 

Side Note: Variable Classes

 

I am using "GLOBAL", "LOCALS", and sometimes "AREA" as designated scripts. I am also using both RealSetGlobalTimer() and SetGlobalTimer(). BioWare was inconsistent in usage, and folks have different opinions on this topic (just like BioWare used LOCALS and Interact() to place lots of stuff on the banter file, while modern mods avoid putting anything that you really want to specifically fire at a precise moment on the J file and use Dialog/StartDialogNoSet() ), but I am using the following internal designations, which other folks may not agree with:

  • LOCALS = stored on the .cre; only use when nothing else is going to cross reference it. For example, if I have an interjection into a dialog I will not be using as a flag for further comment, or if I have a minor talk that I am not going to worry about follow up on, like the first time the party kills an Ettercap and he wants to comment on it.
  • GLOBAL = Lovetalks, Friendship talks, Quest variables, and anything I might want to crossreference later. For example, if I have Aran flirt while drunk, and I might want to reference it with another NPC or the PC. Most material fits this pattern of usage for me, and is really the default condition.
  • RealGlobalTimerExpired() || RealSetGlobalTimer() will always be GLOBAL and will be for anything used to space out dialog or actions in real time for players
  • GlobalTimerExpired() || SetGlobalTimer() will always be GLOBAL and will be for anything used to temporarily delay dialog or actions in game time for players
  • According to the IESDP, the only timer check that will evaluate true if it has EITHER never been set OR has expired is
    !GlobalTimerNotExpired("myVar","GLOBAL")
    So on the very vew things that start from 0 instead of being set to 1 by a 'kick-off" block, I will use this in conjunction with SetGlobalTimer(). Most things, though, will start with an initialization in either dialog or .bcs setting a timer, so most of the time RealGlobalTimerExpired() or GlobalTimerExpired() will do fine.
  • AREA = not if I can possibly help it.

 

edit: this stuff looks so pretty in the highlighter, and so plain without. But I am not messing up code with colorized bbcode for the rest of this. I am going to comment the code instead.

/* CONTENTS: */

/* Timers: 
* [REAL TIME] c-aranfriendtimer | c-aranromtimer
*
* [GAME TIME] c-aransmalltalk |
* 
* Variables: 
* [GLOBAL] c-aranfriendbg2 |  c-aranmatch | c-aranromance | c-aranbg2rom | c-aranvamped | c-silencearan | c-arandrunk
*
* [LOCALS] c-aranpckeep | c-aranlich | c-aranshadelord | c-arandragon | c-aranbasilisk | c-aranettercap | c-arangolem
* c-aranzombie | c-aranworkbod | c-aranworkaran | c-aranphaere | c-aranslaver | c-aranleader | c-aranpctired | c-aranoghma
* c-aranilmater | c-aranhelm | c-aranlath | c-aranumberlee | c-aranwaukeen | c-aranoldbat
* Resources:
* [SOUND] C-ARANFT | C-ARANLT | C-ARANH
*
*/

/* FRIEND TALKS */
* OK let's start with the Friend Talks. The idea here is to set the friendtalks up on a BCS <> DLG "bounce", so 
* 1. set the talk variable to 1 and set a timer.
* 2. set a block that sees that the timer has expired, and initiates dialog.
* 3. the game looks for the variable (1), and sees the dialog, and fires it.
* 4. The dialog line advances the variable to (2), and sets a new timer.
* 5. The BCS here looks for the timer to expire and the even variable (2), advancing to (3) when the timer expires
* Then when it sees the conditions are right, repeat sequence from 3. 
*/


/* Friend Talks Sequence */

/* Friend Talks Setup  */
IF 
Global("c-aranfriendbg2","GLOBAL",0)   // Not evaluated true yet
InParty(Myself)						// Aran is here
!StateCheck(Myself,CD_STATE_NOTVALID)  // Aran is ok
!StateCheck(Player1,CD_STATE_NOTVALID) // Player1 is ok
THEN
RESPONSE #100							  // 100% of the time
	SetGlobal("c-aranfriendbg2","GLOBAL",1)		 //  set up SoA_FT_1
	RealSetGlobalTimer("c-aranfriendtimer","GLOBAL",600)  // Minimum Real Time until SoA_FT_1
END

/* Aran's FriendTalks Aim, c-aranfriendbg2, ARAN_FTT */
/* This block takes the even variables set in dialog, and advances them to the odd */
IF
GlobalLT("c-aranfriendbg2","GLOBAL",32)  // shuts down sequence when finished
RealGlobalTimerExpired("c-aranfriendtimer","GLOBAL")  // Timer Expired
!Global("Chapter","GLOBAL",5) // Not in Underdark - specialized talks for that
OR(15)  
  Global("c-aranfriendbg2","GLOBAL",2)  // set up SoA_FT_2
  Global("c-aranfriendbg2","GLOBAL",4)  // set up SoA_FT_3
  Global("c-aranfriendbg2","GLOBAL",6)  // set up SoA_FT_4
  Global("c-aranfriendbg2","GLOBAL",8)  // set up SoA_FT_5
  Global("c-aranfriendbg2","GLOBAL",10) // set up SoA_FT_6
  Global("c-aranfriendbg2","GLOBAL",12) // set up SoA_FT_7
  Global("c-aranfriendbg2","GLOBAL",14) // set up SoA_FT_8
  Global("c-aranfriendbg2","GLOBAL",16) // set up SoA_FT_9
  Global("c-aranfriendbg2","GLOBAL",18) // set up SoA_FT_10
  Global("c-aranfriendbg2","GLOBAL",20) // set up SoA_FT_11
  Global("c-aranfriendbg2","GLOBAL",22) // set up SoA_FT_12
  Global("c-aranfriendbg2","GLOBAL",24) // set up SoA_FT_13
  Global("c-aranfriendbg2","GLOBAL",26) // set up SoA_FT_14
  Global("c-aranfriendbg2","GLOBAL",28) // set up SoA_FT_15
  Global("c-aranfriendbg2","GLOBAL",30) // set up SoA_FT_16
THEN
RESPONSE #100
	IncrementGlobal("c-aranfriendbg2","GLOBAL",1)  // move up from even to odd
END

/* Aran's FriendTalks Fire, c-aranfriendbg2, ARAN_FTT */
/* This block takes the odd variables set by the last block, and tries to fire them off.  */
IF
GlobalLT("c-aranfriendbg2","GLOBAL",32)  // shuts down sequence when finished
RealGlobalTimerExpired("c-aranfriendtimer","GLOBAL")  // Timer Expired
!Global("Chapter","GLOBAL",5) // Not in Underdark - specialized talks for that
InParty(Myself)						// Aran is here
!StateCheck(Myself,CD_STATE_NOTVALID)  // Aran is ok
!StateCheck(Player1,CD_STATE_NOTVALID) // Player1 is ok
CombatCounter(0)  // Not in combat
!See([ENEMY])  // Can't see any enemies
OR(16)  
  Global("c-aranfriendbg2","GLOBAL",1)   // fire SoA_FT_1
  Global("c-aranfriendbg2","GLOBAL",3)   // fire SoA_FT_2
  Global("c-aranfriendbg2","GLOBAL",5)   // fire SoA_FT_3
  Global("c-aranfriendbg2","GLOBAL",7)   // fire SoA_FT_4
  Global("c-aranfriendbg2","GLOBAL",9)   // fire SoA_FT_5
  Global("c-aranfriendbg2","GLOBAL",11)  // fire SoA_FT_6
  Global("c-aranfriendbg2","GLOBAL",13)  // fire SoA_FT_7
  Global("c-aranfriendbg2","GLOBAL",15)  // fire SoA_FT_8
  Global("c-aranfriendbg2","GLOBAL",17)  // fire SoA_FT_9
  Global("c-aranfriendbg2","GLOBAL",19)  // fire SoA_FT_10
  Global("c-aranfriendbg2","GLOBAL",21)  // fire SoA_FT_11
  Global("c-aranfriendbg2","GLOBAL",23)  // fire SoA_FT_12
  Global("c-aranfriendbg2","GLOBAL",25)  // fire SoA_FT_13
  Global("c-aranfriendbg2","GLOBAL",27)  // fire SoA_FT_14
  Global("c-aranfriendbg2","GLOBAL",29)  // fire SoA_FT_15
  Global("c-aranfriendbg2","GLOBAL",31)  // fire SoA_FT_16
THEN
RESPONSE #100
	PlaySong(0)  // play a blank reference, stoping the soundtrack
	PlaySound("C-ARANFT") // play a .wav or .wavc file
	StartDialogueNoSet(Player1)  // Yo, we are talkin', here...
END


/* ROMANCE TALKS */

/* Romance Match and Initiation (He is not picky...)
* One new thing here - Aran is ok if a friend switches genders -  
* but not so much on the romance side. So, we add a blocking variable
* to make sure nothing progresses while that silly Girdle is in place.
* He can have some special lines to play during the FT sequence on that.
*/

IF
Global("c-aranmatch","GLOBAL",0)	   // Not evaluated
InParty(Myself)						// Aran is here
!StateCheck(Myself,CD_STATE_NOTVALID)  // Aran is ok
!StateCheck(Player1,CD_STATE_NOTVALID) // Player1 is ok
Gender(Player1,FEMALE)				 // Player1 is female
!HasItemEquiped("belt05",Player1)	   // Girdle of sex change not on Player1
THEN
RESPONSE #100							  // 100% of the time
	SetGlobal("c-aranmatch","GLOBAL",1)	// Matched
	SetGlobal("c-aranromance","GLOBAL",1)  // Aran is interested
	RealSetGlobalTimer("c-aranromtimer","GLOBAL",1200)  // Minimum Real Time until first LT
	SetGlobal("c-aranbg2rom","GLOBAL",1)		 //  Tee up SoA_LT_1
END


/* LOVE TALKS */
/* Romance Talks Sequence */

/* Aran's Romance LoveTalks Aim, c-aranbg2rom, ARAN_LTT */
/* This block takes the even variables set in dialog, and advances them to the odd */
IF
GlobalLT("c-aranbg2rom","GLOBAL",32)  // shuts down sequence when finished
RealGlobalTimerExpired("c-aranromtimer","GLOBAL")  // Timer Expired
!Global("Chapter","GLOBAL",5) // Not in Underdark - specialized talks for that
!HasItemEquiped("belt05",Player1) // Not using Girdle of sex change
OR(15)  
  Global("c-aranbg2rom","GLOBAL",2)  // set up SoA_LT_2
  Global("c-aranbg2rom","GLOBAL",4)  // set up SoA_LT_3
  Global("c-aranbg2rom","GLOBAL",6)  // set up SoA_LT_4
  Global("c-aranbg2rom","GLOBAL",8)  // set up SoA_LT_5
  Global("c-aranbg2rom","GLOBAL",10) // set up SoA_LT_6
  Global("c-aranbg2rom","GLOBAL",12) // set up SoA_LT_7
  Global("c-aranbg2rom","GLOBAL",14) // set up SoA_LT_8
  Global("c-aranbg2rom","GLOBAL",16) // set up SoA_LT_9
  Global("c-aranbg2rom","GLOBAL",18) // set up SoA_LT_10
  Global("c-aranbg2rom","GLOBAL",20) // set up SoA_LT_11
  Global("c-aranbg2rom","GLOBAL",22) // set up SoA_LT_12
  Global("c-aranbg2rom","GLOBAL",24) // set up SoA_LT_13
  Global("c-aranbg2rom","GLOBAL",26) // set up SoA_LT_14
  Global("c-aranbg2rom","GLOBAL",28) // set up SoA_LT_15
  Global("c-aranbg2rom","GLOBAL",30) // set up SoA_LT_16
THEN
RESPONSE #100
	IncrementGlobal("c-aranbg2rom","GLOBAL",1)
END

/* Aran's Romance LoveTalks Fire, c-aranbg2rom, ARAN_LTT */
/* This block takes the odd variables set by the last block, and tries to fire them off.  */
IF
GlobalLT("c-aranbg2rom","GLOBAL",32)  // shuts down sequence when finished
RealGlobalTimerExpired("c-aranromtimer","GLOBAL")  // Timer Expired
!Global("Chapter","GLOBAL",5) // Not in Underdark - specialized talks for that
!HasItemEquiped("belt05",Player1) // Not using Girdle of sex change
CombatCounter(0)  // Not in combat
!See([ENEMY])  // Can't see any enemies
OR(16)  
  Global("c-aranbg2rom","GLOBAL",1)   // fire SoA_LT_1
  Global("c-aranbg2rom","GLOBAL",3)   // fire SoA_LT_2
  Global("c-aranbg2rom","GLOBAL",5)   // fire SoA_LT_3
  Global("c-aranbg2rom","GLOBAL",7)   // fire SoA_LT_4
  Global("c-aranbg2rom","GLOBAL",9)   // fire SoA_LT_5
  Global("c-aranbg2rom","GLOBAL",11)  // fire SoA_LT_6
  Global("c-aranbg2rom","GLOBAL",13)  // fire SoA_LT_7
  Global("c-aranbg2rom","GLOBAL",15)  // fire SoA_LT_8
  Global("c-aranbg2rom","GLOBAL",17)  // fire SoA_LT_9
  Global("c-aranbg2rom","GLOBAL",19)  // fire SoA_LT_10
  Global("c-aranbg2rom","GLOBAL",21)  // fire SoA_LT_11
  Global("c-aranbg2rom","GLOBAL",23)  // fire SoA_LT_12
  Global("c-aranbg2rom","GLOBAL",25)  // fire SoA_LT_13
  Global("c-aranbg2rom","GLOBAL",27)  // fire SoA_LT_14
  Global("c-aranbg2rom","GLOBAL",29)  // fire SoA_LT_15
  Global("c-aranbg2rom","GLOBAL",31)  // fire SoA_LT_16
THEN
RESPONSE #100
	PlaySong(0)
	PlaySound("C-ARANLT")
	StartDialogueNoSet(Player1)
END


/* OK, now on to some fun blocks to play with. These are things Aran can blather on about. */


/* TALKS, FLOATING AND SMALL */
/* Covers both specific reactions, floaters, and any smalltalk reactions (could also be
* called "after-the-fact interjections")
*/

/* After-Vampification Talk, Canonical, 2nd Class. */
IF
!InParty(Myself)
Global("c-aranvamped","GLOBAL",4)
THEN
RESPONSE #100
	SetGlobal("c-aranvamped","GLOBAL",5)
	StartDialogueNoSet(Player1)
END

/* Stronghold Commentary */

/* PC Owns Keep */
IF
Global("PCKeepOwner","GLOBAL",1)
Global("c-silencearan","GLOBAL",0) // PID - set silencer
Global("c-aranpckeep","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
CombatCounter(0)
!See([ENEMY])
THEN
RESPONSE #100
	SetGlobal("c-aranpckeep","LOCALS",1)
	StartDialogueNoSet(Player1)
END


/* Drunk Talks (incorporates Flirts if gender and romance variables set)  */
/* Using GLOBAL here so it can influence friendtalks */
IF
 GlobalLT("c-arandrunk","GLOBAL",6)  // shuts down sequence when finished
InParty(Myself)
CheckStatGT(Myself,50,INTOXICATION)  // Whoot - the room is moving about too much
OR(12)
	AreaCheck("AR0313") // Sea's Bounty
	AreaCheck("AR0406") // Copper Coronet
	AreaCheck("AR0509") // Five Flagons
	AreaCheck("AR0522") // Five Flagons (Stronghold)
	AreaCheck("AR0704") // Mithrest Inn
	AreaCheck("AR1105") // Umar Inn
	AreaCheck("AR1602") // The Vulgar Monkey
	AreaCheck("AR2010") // Vyatri's Pub, Trademeet
	AreaCheck("AR0709") // Den of the Seven Vales 1st Floor
	AreaCheck("AR0513") // Calbor's Inn at Bridge District 1st Floor
	AreaCheck("AR0021") // Crooked Crane 1st Floor
	AreaCheck("AR1602") // Brynnlaw's Inn
OR(3)
	Global("c-arandrunk","GLOBAL",0)
	Global("c-arandrunk","GLOBAL",2)
	Global("c-arandrunk","GLOBAL",4)
!StateCheck(Player1,CD_STATE_NOTVALID)
CombatCounter(0)
!See([ENEMY])
THEN
RESPONSE #100
	IncrementGlobal("c-arandrunk","GLOBAL",1)
END

IF
GlobalLT("c-arandrunk","GLOBAL",6)  // shuts down sequence when finished
!GlobalTimerNotExpired("c-aransmalltalk","GLOBAL") // Timer (game-time) has never been set or has expired
OR(12)
	AreaCheck("AR0313") // Sea's Bounty
	AreaCheck("AR0406") // Copper Coronet
	AreaCheck("AR0509") // Five Flagons
	AreaCheck("AR0522") // Five Flagons (Stronghold)
	AreaCheck("AR0704") // Mithrest Inn
	AreaCheck("AR1105") // Umar Inn
	AreaCheck("AR1602") // The Vulgar Monkey
	AreaCheck("AR2010") // Vyatri's Pub, Trademeet
	AreaCheck("AR0709") // Den of the Seven Vales 1st Floor
	AreaCheck("AR0513") // Calbor's Inn at Bridge District 1st Floor
	AreaCheck("AR0021") // Crooked Crane 1st Floor
	AreaCheck("AR1602") // Brynnlaw's Inn
CombatCounter(0)  // Not in combat
!See([ENEMY])  // Can't see any enemies
OR(3)  
  Global("c-arandrunk","GLOBAL",1)
  Global("c-arandrunk","GLOBAL",3)
  Global("c-arandrunk","GLOBAL",5)
THEN
RESPONSE #100
	PlaySong(0)
	PlaySound("C-ARANH")
	StartDialogueNoSet(Player1)
END

/* Monster Reactions */

/* Commenting on some Monster Encounters, Working for The Man/Undead */
IF 
!GlobalTimerNotExpired("c-aransmalltalk","GLOBAL") // Timer (game-time) has never been set or has expired
Global("c-silencearan","GLOBAL",0)  // a PID - set "silencer" for folks who hate unsolicited comments
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
OR(9)
	Global("c-aranlich","LOCALS",1)
	Global("c-aranshadelord","LOCALS",1)
	Global("c-arandragon","LOCALS",1)
	Global("c-aranbasilisk","LOCALS",1)
	Global("c-aranettercap","LOCALS",1)
	Global("c-arangolem","LOCALS",1)
	Global("c-aranzombie","LOCALS",1)
	Global("c-aranworkbod","LOCALS",1)
	Global("c-aranworkaran","LOCALS",1)
THEN
RESPONSE #100
	SetGlobalTimer("c-aransmalltalk","GLOBAL",300) // spaces comments
	StartDialogNoSet(Player1)
END


/* For catching general objects without regard to DVs, we can use a general catch all using the .ids entries - 
* [EA.GENERAL.RACE.CLASS]. An entry of 0 in a field will match any value. 
* For example: [ENEMY.0.0.MAGE] specifies all creatures that are enemies of the party, any general category, any race, mages.
* Amber uses these to good effect, so I started by borrowing from that code, then readjusting and extending - 
*/

/* Liches Are Scary  (Darios) */
IF
Global("c-silencearan","GLOBAL",0)
Global("c-aranlich","LOCALS",0)
OR(2)
  Killed([0.0.LICH]) 
  Killed([0.0.DEMILICH])
 InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranlich","LOCALS",1)
END

/* Shade Lord (Darios)  */
IF
Killed([0.UNDEAD.SHADOW.SHADOW.0.FEMALE]) // Shade Lord
	Global("c-silencearan","GLOBAL",0)
Global("c-aranshadelord","LOCALS",0)
OR(2)
  AreaCheck("AR1400") // Temple ruins
  AreaCheck("AR1404") // Temple ruins restored
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranshadelord","LOCALS",1)
END


/* Aran Dragon-Slayer (Darios) */
IF
Killed([0.0.DRAGON])
Global("c-silencearan","GLOBAL",0)
Global("c-arandragon","LOCALS",0)
!AreaCheck("AR2102") // Adalon's cave
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-arandragon","LOCALS",1)
END

/*  Basilisk Baiting */
IF
Killed([0.0.BASILISK]) 
Global("c-silencearan","GLOBAL",0)
Global("c-aranbasilisk","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranbasilisk","LOCALS",1)
END

/* Poisonous Cloakwood Ettercaps */
IF
Killed([0.0.ETTERCAP]) 
Global("c-silencearan","GLOBAL",0)
Global("c-aranettercap","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranettercap","LOCALS",1)
END

/* Golems are Big Boys */
IF
Killed([0.0.GOLEM])
Global("c-silencearan","GLOBAL",0)
Global("c-arangolem","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-arangolem","LOCALS",1)
END

/* Zombies: Looks Like Me After A Night On The Town */
IF
Killed([0.0.ZOMBIE])
Global("c-silencearan","GLOBAL",0)
Global("c-aranzombie","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranzombie","LOCALS",1)
END

/* Real Great Employer, buddy. Someone pass me the Daystar. */
IF
Global("WorkingForBodhi","GLOBAL",1)
Global("c-silencearan","GLOBAL",0)
Global("c-aranworkbod","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranworkbod","LOCALS",1)
END

/* Real Great Employer, buddy. But at least he's not undead. I think. */
IF
Global("WorkingForAran","GLOBAL",1)
Global("c-silencearan","GLOBAL",0)
Global("c-aranworkaran","LOCALS",1)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranworkaran","LOCALS",1)
END

/* Commenting on Phaerie, Leader, Slaver Procession, and a few more */
IF 
!GlobalTimerNotExpired("c-aransmalltalk","GLOBAL") // Timer (game-time) has never been set or has expired
Global("c-silencearan","GLOBAL",0)  // a PID - set "silencer" for folks who hate unsolicited comments
OR(4)
	Global("c-aranphaere","LOCALS",1)
	Global("c-aranslaver","LOCALS",1)
	Global("c-aranleader","LOCALS",1)
	Global("c-aranpctired","LOCALS",1)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobalTimer("c-aransmalltalk","GLOBAL",300) // spaces comments
	StartDialogNoSet(Player1)
END

/* Phaere is a hawt chick (male PC); is no good for you (female PC); better not have touched you (Romance) */  
IF
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
OR(2)
  Global("PhaereInnuendo","GLOBAL",2)
  Global("PhaereInnuendo","GLOBAL",3)
Global("c-aranphaere","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("c-aranphaere","LOCALS",1)
END

/* Slums Slavers (Darios, extended) */
IF
AreaCheck( <<HERE>> )
Global("c-aranslaver","LOCALS",0)
See("SlumsSlaver2")
See("SlumsSlaver3")
See("SlumsSlave1")
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranslaver","LOCALS",1)
END

/* Setting Aran as Leader */
IF
Global("c-aranleader","LOCALS",0)
Name("c-aran",Player1Fill)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
SetGlobal("c-aranleader","LOCALS",1)
END

/* You look dead on your feet */
IF
CheckStatGT(Player1,5,FATIGUE)
Global("c-aranpctired","LOCALS",0)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranpctired","LOCALS",1)
END


/* Temple Comments, Only If Not A Cleric (even minimal training would keep him from starting a holy fight) Firing */
IF 
!Class(Myself,CLERIC_ALL)
!GlobalTimerNotExpired("c-aransmalltalk","GLOBAL") // Timer (game-time) has never been set or has expired
Global("c-silencearan","GLOBAL",0)  // a PID - set "silencer" for folks who hate unsolicited comments
OR(4)
	Global("c-aranoghma","LOCALS",1)
	Global("c-aranilmater","LOCALS",1)
	Global("c-aranhelm","LOCALS",1)		
	Global("c-aranlath","LOCALS",1)		
	//	Global("c-arantalos","LOCALS",1)  // skipped because of quest
	Global("c-aranumberlee","LOCALS",1)
	Global("c-aranwaukeen","LOCALS",1)
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobalTimer("c-aransmalltalk","GLOBAL",300) // spaces comments
	StartDialogNoSet(Player1)
END

/* Temple Comments, Only If Not A Cleric (even minimal training would keep him from starting a holy fight)  */
IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranoghma","LOCALS",0)
AreaCheck("AR0319") //  Temple of Oghma
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranoghma","LOCALS",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranilmater","LOCALS",0)
OR(2)
	AreaCheck("AR0408") //  Temple of Ilmater
	AreaCheck("AR0703") //  Temple of Ilmater
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
SetGlobal("c-aranilmater","LOCALS",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranhelm","LOCALS",0)
OR(2)
	AreaCheck("AR0512") //  Temple of Helm
	AreaCheck("AR0901") //  Temple of Helm
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranhelm","LOCALS",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranlath","LOCALS",0)
AreaCheck("AR0902") //  Temple of Lathander
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranlath","LOCALS",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-arantalos","LOCALS",0)
AreaCheck("AR0904") //  Temple of Talos
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-arantalos","GLOBAL",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranumberlee","LOCALS",0)
AreaCheck("AR1604") //  Temple of Umberlee
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranumberlee","LOCALS",1)
END

IF
!Class(Myself,CLERIC_ALL)
Global("c-silencearan","GLOBAL",0)
Global("c-aranwaukeen","LOCALS",0)
OR(2)
	AreaCheck("AR1010") //  Temple of Waukeen
	AreaCheck("AR2008") //  Temple of Waukeen
InParty(Myself)
!StateCheck(Myself,CD_STATE_NOTVALID)
!StateCheck(Player1,CD_STATE_NOTVALID)
THEN
RESPONSE #100
	SetGlobal("c-aranwaukeen","LOCALS",1)
END

 

Posting the related dialogs in Interjections for Aran

Link to comment

Oh, darn, good catch - will edit to 7, as I want it to fire when the in-game fatigue comes in. I lifted this idea directly from Darios, and I expect his (and Miera's) intention was to have a little bit of "sixth sense" with a Tiefling, but Aran shouldn't be that sensitive. Thanks!

Link to comment

OK, that's nice and all, but can you tell me what's the difference of all the script attached to the creature file... you used the "override script" and told what it basically does, but what the other do?

 

PS: the whole thing won't work cause of the end of this line:

FRIEND TALKS */
:blush:
Link to comment

Whoa, missed that - thanks - I'll take that end-block-comment out so it works!

 

As for the scripts, well, there are two things - scripts and "scope of variables sorting" (there has got to be a better way of describing this). Variables, as reported in the IESDP, are sorted into

global (between-creature communication) locals ("This allows for several creatures to use the same script (with the same variable names) as the value assigned to variables are for each creature." - i.e., I can set Aran to have "HaveKissedPCThisManyTimes" and also have the same variable assigned to another NPC, say Ilyos, and they can track different numbers)

and area (which is seen by everything, but can be set to different values in each area).

 

The use of LOCALS is the pat that gets folks dividing up over what is "good coding". In BG1, the LOCALS variable is stored in the game session, and at no other time. So for BG1, LOCALS means "one shot, and if you hit ctr-r it probably goes away". In BG2, the LOCALS are stored better, so that problem goes away, but the creature who sets the variable is the ony one who can reference it -

 

if I set c-arankissedthepc = 1 and store it as a LOCALS, no one but Aran can "see" that variable, so if I want it to triger someone else to comment if he has kissed her 5 times, nope - can't do it by referecing. BioWare coded all the BG2 LTs I have seen this way, I am assuming because they felt LTs were private one-on-one conversations nop-one else in the party wuld ever need to reference (a wild and unsupported guess on my part).

 

I have no data on whether it makes any difference to the game processing speed if you set hundreds of GLOBAL vs hundreds of LOCAL vs hundreds of AREA. I have always used GLOBAL almost exclusively. But my "better safe than sorry" on Aran is to move closer to BioWare and follow SConrad's notes on use of LOCALS, spreading out the number of times I use each a bit more. Not a particularly scholarly /tested approach on my part, but it sounds good, so why not?

 

As for the scripts, there are several that work at different levels. This entry has the data, but you really wan to hop over to PPG and take a look at the big "how scripts work' tutorial post - I'll try to look it up when I get home. The summary (as I understand it) is that it works kind of like a decision tree -

 

override script is checked for smething that is valid, and if nothing fires, the engine moves on to the next on down the line to check. So

 

0 OVERRIDE

1 AREA

2 SPECIFICS

4 CLASS

5 RACE

6 GENERAL

7 DEFAULT

 

where c-aran.bs is the "override" that will have all the custom stuff. Other scripts, like WTASIGHT.BCS, etc., fill in the remaining scripts and provide actions specific to those functions.

 

I guess technically that means you could create custom scripts for all of these levels. In practice, everyone seems to dump everything (including combat scrip materials) into both Joinable and Non-Joinable NPCs "override" scripts.

Link to comment

!GlobalTimerNotExpired() - it's generally used in combat scripts, where you can have multiple

IF
!GlobalTimerNotExpired("one_round","locals")
HaveSpell(WIZARD_SPELL)
THEN
RESPONSE #100
SetGlobalTimer("one_round","locals",6)
Spell(Target,WIZARD_SPELL)
END

blocks, instead of doubling their amount due to uncertainty whether or not the timer had been already set. So, basically there's no much benefit from using it in normal scripts, it will save few blocks at most. Still better, but probably not enough to compensate the confusion of novice modder, should they be reading this.

 

In practice, everyone seems to dump everything (including combat scrip materials) into both Joinable and Non-Joinable NPCs "override" scripts.
That's very bad to do, and it was a case in Xulaye. First, combat usually weights quite a bit, second, it can mess with player's directions. The best way is to have a trigger in normal script with checks for a need to go hostile, then switch to a pure combat one, should such a need occur.
Link to comment

Good points - at most, it will save perhaps 4 blocks total, since I am using medium blocks of OR(#) to trigger dialog instead of a long list of small follow-up SDNS() blocks. I am not convinced I am saving much by doing that, either.

 

The combat script is a point I think I'd better make pretty clearly when we get to that. It also leads us to the side note that somewhere in here we might want to poke at stuff like

 

ANOMEN.BCS

vs

ANOM25.BCS

vs.

ANOMEND.BCS

vs.

ANOMX.BCS

 

[when we get to it, the reminder it is set manually

IF
Global("AnomenFinalFight","GLOBAL",1)
Global("HopToItAnomen","LOCALS",0)
THEN
RESPONSE #100
	SetGlobal("HopToItAnomen","LOCALS",1)
	SetDialog("")
	ChangeAIScript("anomx",SPECIFICS)
	ChangeAIScript("",DEFAULT)
	ChangeAIScript("useitem",GENERAL)
	ChangeEnemyAlly(Myself,GOODBUTBLUE)
END

vs.

PRIEST1.BCS

vs.

WDASIGHT.BCS

 

 

as I note some mods like Saerileth copy this "out of party combat/cutscene script" and others don't.

Link to comment

Archived

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

×
×
  • Create New...