Home arrow Tutorials arrow Romance Authoring Tutorial 13 October 2004  
HomeAllisonImproved AsylumPhaere's NPC PortraitsRPG Dungeon Item PackThe Unusual Oddities ShopSP Item PackSuper FirkraagRobe of Vecna Modification


Games
 Dragon Age

Main Menu
 Home
 Allison
 Improved Asylum
 Phaere's NPC Portraits
 RPG Dungeon Item Pack
 The Unusual Oddities Shop
 SP Item Pack
 Super Firkraag
 Robe of Vecna Modification

Mods Under Construction
 Heart of Vengeance
 Kitanya
 Darkness Beyond Light
 Sarevok Relationship
 Kit Pack

Services
 Tutorials
 Modding Tools

Misc.
 About Us
 Chat Room
 RPG Dungeon Forums
 Legal Information
 Related Sites
 Contact Us

Login Form
Username

Password

Remember me
Forgotten your password?

 
Romance Authoring Tutorial   PDF  Print  E-mail 
Written by Rastor  
Monday, 02 August 2004

Romance Authoring Tutorial
Author: Rastor

Download it

 

It has been brought to my attention recently that many people with great ideas for romanceable NPC mods don't know where to begin.  They try looking at already existing romanceable mods and are immediately innundated with a variety of variables and numerous dialogue files and don't know how to make any sense of it.  The seeming necessity to make flirtpacks in today's mods makes this all the more challenging and baffling.  If this sounds like you, read on!

 

Globals

Bioware's default romances are driven by a number of globals.  Essentially, these are the basic ones:

 

"XXXXXMatch","GLOBAL":  This global is set to 1 if the NPC will romance the player and set to 0 if the NPC and the player won't romance.
"XXXXXRomanceActive","GLOBAL":  This global is set to 0 if the romance hasn't started, 1 if the NPC is talking with the player but isn't in love with him/her yet, 2 if the NPC and the player are involved in an exclusive romance, and 3 if the romance has been killed for whatever reason.
"XXXXXRomance","GLOBAL":  This is a timer that controls when the NPC will next talk to the player.  Whenever it hits 0, the game checks for the necessary prerequisites for a talk and has the NPC talk to the player if appropriate.
"Lovetalk","LOCALS":  This simply controls which dialogue the NPC will say to the player whenever it is time to speak again.

 

There are a number of NPC specific variables present in each romance as well, but those control things like quest progression, whether the NPC and player have had sex or not, etc.  Those are not explicitly covered in this tutorial.  If you write your own scripts for your NPC, you can implement these things as necessary.

Flirt packs generally use similar but differently named variables to the ones described above.  They do not have to, however.

 

Writing Talks

WeiDU is by far the best tool to use for writing dialogues.  The reason for this is ensuring compatibility with other mods.  Now, you may be wondering how you go about coding your lovetalk.  Well, first I would strongly recommend having your entire dialogue tree (NPC statements and corresponding replies) sketched out on paper first.  This will make things much easier on you.

Having your NPC start a dialogue is very similar to any other dialogue initiated by an NPC.  What you'll need to do is to include a block in your NPC's override script that says something like:

 

IF
 Global("MynpcMatch","GLOBAL",1)
 Global("MynpcRomanceActive","GLOBAL",1)
 Global("Lovetalk","LOCALS",1)
 GlobalTimerExpired("MyRomance","GLOBAL")
 !AreaType(DUNGEON)  // None of the Bioware NPCs will banter in dungeons, and I suggest that modders keep this tradition.
 !StateCheck(Player1,STATE_SLEEPING)  // How's the PC going to talk if he can't do anything?
 InParty(Myself)  // Jaheira will actually fire lovetalks if she's not in the party.  You don't want your NPC to do that, do you?
 See(Player1)
THEN
 RESPONSE #100
  IncrementGlobal("Lovetalk","LOCALS",1)
  Interact(Player1)
END

 

Then in your NPC's B dialogue file (you can also use J, but that's quite unconventinal), you'll need to include the NPC's dialogue:

 

IF ~Global("MynpcRomanceActive","GLOBAL",1) Global("Lovetalk","LOCALS",2) Global("MynpcMatch","GLOBAL",1) GlobalTimerExpired("MyRomance","GLOBAL")~ THEN BEGIN RomanceTalk1
  SAY ~blah blah blah~ // You'll type whatever your NPC says into the dialogue
  IF ~~ THEN REPLY ~blah~ DO ~RealSetGlobalTimer("MyRomance","GLOBAL",30)~ /* You can actually set the timer to whatever you want. */ THEN GOTO NextLine
  IF ~~ THEN REPLY ~blah2~ DO ~RealSetGlobalTimer("MyRomance","GLOBAL",30)~ THEN GOTO NextLine2
END

 

That's the basic pattern to do lovetalks.  Anything that's not a top-level text (starts the conversation) is done using basic WeiDU techniques.  Simply change the variable names for conditionals as needed to get your romance coded.

 

Flirtpacks

While flirtpacks are by no means necessary for a romanceable NPC, many modders choose to include them most likely because every other NPC mod out there with a romance includes them.  So, how do you code them?  It is actually not much different than romances.

In the NPC's override script:

IF
 Global("MynpcRomanceActive","GLOBAL",1)
 GlobalTimerExpired("Flirt","LOCALS") // This can be a local or global variable.  It doesn't really matter.
 See(Player1)
 InParty(Myself)
 !StateCheck(Player1,STATE_SLEEPING)
THEN
 RESPONSE #100
  StartDialogue(Player1)
END

 

Many modders like to use a counter to measure the number of times that the player flirts with the NPC.  While you are certainly able to do this, it is not really necessary. The reason that this is done is if you want to keep track of how affectionate the player is to the NPC. This could be useful if you are trying to do something such as including special dialogues for more affectionate players.

Use the same techinique as you used to code the NPC's lines for the romance dialogue, only this time put the lines into the NPC's J file.  The flirtpacks and romance dialogues should go in different dialogue files.

For player initated flirts, all you need is a dialogue state in the NPC's J file (must be J file) that says IF ~IsGabber(Player1)~ THEN BEGIN FlirtSelection.

 

Weighting

To force the romance dialogues to fire exactly when you want them to, the romances should be weighted sequencally so that the first lovetalk gets the lowest weight, second one gets second lowest, etc.  The same applies to flirts.

Often, you'll want these to be the lowest weights in the dialogue file.  This will ensure that the game will check the romance talks first to attempt to find a banter to fire.  If you don't do this then your NPC might skip over lovetalks occasionally or whatnot.

Now you have all the basics needed to code a simple NPC romance.

 

Advanced Possibilities

By now you've realized that what's been covered so far is barely anything that can (and almost always) is done with NPC romances.  Flirts have random options, certain lovetalks only go off when the player rests and after the player wakes up, NPCs may have fights that spawn in at a certain stage of the romance, etc.  These involve trickier scripting, so if you have no idea how to do scripts, then I would not recommend trying this sort of thing.

 

Sleep Scripts

All NPCs have scripts which the game checks whenever the party rests.  These are set in the pdialog.2da file, but are generally XXXXXD.bcs, where XXXXX is the name of the NPC.  In order to fire a script at rest, you need merely to put the necessary code to fire a lovetalk into this script.  Use the script that I provided earlier as an example, changing the variables as needed.

In order to do the "Morning After" talks, include PartyRested() into the relevant block of the NPC's primary override script.

 

For example:

(morning after)

IF
 Global("MynpcRomanceActive","GLOBAL",2)
 Global("Lovetalk","LOCALS",19)
 GlobalTimerExpired("MyRomance","GLOBAL)
 PartyRested()
 InParty(Myself)
 See(Player1)
THEN
 RESPONSE #100
  IncrementGlobal("Lovetalk","LOCALS",1)
  Interact(Player1)
END

 

(on rest-add to XXXXXD.bcs)

IF
 Global("MynpcRomanceActive","GLOBAL",2)
 Global("Lovetalk","LOCALS",17)
 InParty(Myself)
 See(Player1)
THEN
 RESPONSE #100
  IncrementGlobal("Lovetalk","LOCALS",1)
  Interact(Player1)
END

 

Randomizing Flirts

To do this, you need to use the RandomNum(x,y) scripting trigger.  See IESDP for more information on this trigger.  You'll put this into the reply line of the Player initiated flirts, or into the GOTO section of the NPC initiated flirts.

An example for Cailean, graciously provided by Kismet:

 

APPEND FWCailej

//Cailean init flirts
IF ~Global("FWCaiDisableFlirts","GLOBAL",0)
See(Player1)
!StateCheck(Player1,STATE_SLEEPING)
CombatCounter(0)
Global("FWCaileanRomanceActive","GLOBAL",1)
Global("FWCaileanStartFlirt","GLOBAL",1)~ THEN BEGIN CaileanInitFlirts
SAY ~I'm going to start a flirt now.~
IF ~~ THEN DO ~IncrementGlobal("FWCaileanRandFlirt","LOCALS",1)~ GOTO CaileanInitHand
IF ~RandomNum(2,1)~ THEN DO ~IncrementGlobal("FWCaileanRandFlirt","LOCALS",1)~ GOTO CaileanInitKiss
IF ~RandomNum(2,2)~ THEN DO ~IncrementGlobal("FWCaileanRandFlirt","LOCALS",1)~ GOTO CaileanInitTickle
END

IF ~~ THEN BEGIN CaileanInitHand
SAY ~(Cailean takes a hold of your hand.)~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN CaileanInitKiss
SAY ~(Cailean gives you a kiss on the cheek.)~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN CaileanInitTickle
SAY ~(Cailean tickles your ribs.)~
IF ~~ THEN EXIT
END

//PC init flirts -- early
IF ~IsGabber(Player1)
CombatCounter(0)
GlobalGT("FWCaiInitLoveTalk","GLOBAL",6)
Global("FWCaileanQuestCompleted","GLOBAL",1)
Global("FWCaileanRomanceActive","GLOBAL",1)~ THEN BEGIN CaiFlirtBaseEarly
SAY ~(Cailean notices your approach.)~
+ ~RandomNum(4,1)~ + ~(Hold Cailean's hand.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + HandHold1
+ ~RandomNum(4,2)~ + ~(Hold Cailean's hand.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + HandHold2
+ ~RandomNum(4,3)~ + ~(Hold Cailean's hand.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + HandHold3
+ ~RandomNum(4,4)~ + ~(Hold Cailean's hand.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + HandHold1

+ ~RandomNum(4,1)~ + ~(Kiss Cailean.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + Kiss1
+ ~RandomNum(4,2)~ + ~(Kiss Cailean.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + Kiss2
+ ~RandomNum(4,3)~ + ~(Kiss Cailean.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + Kiss3
+ ~RandomNum(4,4)~ + ~(Kiss Cailean.)~ DO ~IncrementGlobal("FWCaileanFlirtCount","LOCALS",1)~ + Kiss4
++ ~Cailean, I like you very much, but please don't flirt with me anymore.~ DO ~SetGlobal("FWCaiDisableFlirts","GLOBAL",1)~ EXIT
++ ~(Say nothing.)~ EXIT
END

IF ~~ THEN BEGIN HandHold1
SAY ~Cailean holds your hand 1.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN HandHold2
SAY ~Cailean holds your hand 2.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN HandHold3
SAY ~Cailean holds your hand 3.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss1
SAY ~Cailean kisses you 1.~
= ~It's a really long kiss.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss2
SAY ~Cailean kisses you 2.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss3
SAY ~Cailean asks about the kiss~
++ ~Kiss answer 1.~ + Kiss3_1
++ ~Kiss answer 2.~ + Kiss3_2
++ ~Kiss answer 3.~ + Kiss3_3
END

IF ~~ THEN BEGIN Kiss3_1
SAY ~Cailean kisses you 3_1~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss3_2
SAY ~Cailean kisses you 3_2~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss3_3
SAY ~Cailean kisses you 3_3.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN Kiss4
SAY ~(Cailean kisses you 4.)~
IF ~~ THEN EXIT
END
END

 

Quests, Fights, and Other Miscellaneous Things

This guide is about writing romances.  For doing quests and fights, script them into the NPC's override file, but such things are subject for another time.


Top of Page