Version 6, by jastey.
This tutorial deals with giving your NPC some general script additions like XP adjustment upon joining, removing of Story Mode upon leaving the group, letting the NPC move in cutscenes if not in party, and inclusion into general NPC reaction points to the main game events.
The listed situations in this tutorial are the ones where general reactions depending on class, race, or alignment of all or several NPCs in group are included in the game and where a mod NPC should not be missing. It does not give examples of possible interjection points depending on individual NPCs' character or personal reactions to game events etc.
The tutorial now includes all instances I could find by browsing the game files. Let me know if I missed anything or if you have general critique. The tutorial might change after I finished my own NPC mods for SoD.
Some nomenclature:
xx | used as a modding prefix in this tutorial. If you don't have a prefix, check the IE Community Filename Prefix Reservations List and register one at Black Wyrm Lair Forums. | xxBiff | Biff's scriptname (death variable) |
xxBiffs.bcs | Biff's SoD override script |
xxBiffJ.dlg | Biff's joined dialogue |
This chapter presents script additions every NPC in SoD has in their OVERRIDE script. They are for XP adjustment upon joining in SoD, total healing and dispell of effects after leaving the Ducal Palace, and removing of Story Mode if leaving the party.
The first eight script blocks deal with levelling the NPC up to match the XP the PC has in SoD. This is especially interesting if your NPC was left standing in BG:EE and is supposed to rejoin the group now, or for a new SoD game if they will join later in SoD where the PC had time to level up. It also gives the possibility to use one cre file for both new BG:EE and SoD games without having to think about how to distribute weapon pips etc. (Maybe not as smart for a mage or cleric etc. who need to know higher level spells in SoD, though.)
The next script block contains full healing and dispelling of any spell effects, deafness, feeblemindedness etc. after Korlasz' Crypt is cleared.
The last script block will remove the Story Mode from your NPC if they leave the party.
You could put these into an own .baf-file and EXTEND_BOTTOM it to your NPC's SoD OVERRIDE script.
/* This file contains no NPC specific variables or names. You can use it to patch it to your NPC's SoD Override script without changes. */ /* in the tutorial mod package, it is called general_script_additions.baf */ /* make NPC level up to PC's level upon first joining. You can always reactivate this by resetting SetGlobal("BDSODXP","LOCALS",0). There is a similar thing for the BG:EE part in the according NPC scripts. */ IF Global("BD_JOINXP","LOCALS",1) Global("BD_SAFEHOUSE_DONE","GLOBAL",1) // gets set in bdcut00z.bcs (transition to bd0103.are after Korlaz's crypt is cleared) Global("BDSODXP","LOCALS",0) InParty(Myself) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BDSODXP","LOCALS",1) SetGlobal("BD_JOINXP","LOCALS",0) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,249999) XPLT(Myself,250000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,250000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,199999) XPLT(Myself,200000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,200000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,160999) XPLT(Myself,161000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,161000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,134999) XPLT(Player1,161000) XPLT(Myself,135000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,135000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,109999) XPLT(Player1,135000) XPLT(Myself,110000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,110000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPGT(Player1,89999) XPLT(Player1,110000) XPLT(Myself,90000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) ChangeStat(Myself,XP,90000,SET) SetInterrupt(TRUE) END IF Global("BD_JOINXP","LOCALS",0) InParty(Myself) XPLT(Player1,90000) THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_JOINXP","LOCALS",1) SetInterrupt(TRUE) END /* after transition to Ducal Palace: remove all spell effects, cure all deseases & feablemindedness, reset HP to 100% (this is for "better safe than sorry", since we do this again when we spawn the NPC in their meeting place after the PC left the Ducal Palace) */ IF !InParty(Myself) Global("BD_SAFEHOUSE_DONE","GLOBAL",1) Global("BD_POST_SAFEHOUSE_HEAL","LOCALS",0) THEN RESPONSE #100 SetGlobal("BD_POST_SAFEHOUSE_HEAL","LOCALS",1) ReallyForceSpellDeadRES("BDREJUVE",Myself) // cures all deseases, dispelles all spell effects and resets HP to 100% Continue() END /* In case player plays in story mode: deactivate it in case NPC is not in party */ IF !InParty(Myself) CheckSpellState(Myself,STORY_MODE) THEN RESPONSE #100 ReallyForceSpellDeadRES("OHSMODE3",Myself) Continue() END
In the tutorial mod package, these scriptblocks are in a file called general_script_additions.baf. The according tp2 patching for adding it to Biff's OVERRIDE script would be:
/* patching general script additions to Biff's OVERRIDE script */ EXTEND_BOTTOM ~xxBiffs.bcs~ ~%MOD_FOLDER%/baf/general_script_additions.baf~ EVALUATE_BUFFER
In bd0120.are and also bd0130.are, the two areas of Korlaz's crypt, the NPCs have DisplayStringHeads about what they are planning to do after the dungeon is cleared.
The first script block is before Korlasz is defeated, the NPCs mention that the time together with the PC will come to an end. The second script block is after Korlasz is defeated, the NPCs state their specific plans of leaving and / or congratulate the PC for their victory.
The script blocks shown here are compatible with EndlessBG1 and Transition Mods where the farewell blurbs will be prevented. Apart from that, please also refer to Tutorial Part 1 Chapter 1 regarding my recommendation how to chose the NPC's joined and banter files in Korlasz' Crypt.
For Biff, we patch the following to both bd0120.bcs and bd0130.bcs so it can play in either area:
/* bd0120_commenting.baf In Korlasz' Crypt: NPC state their plans after the last follower of Sarevok will be defeated. This will be patched to both bd0120.bcs and bd0130.bcs. */ /* First comment: before Korlasz will be defeated. */ IF Global("xxBiff_SoDleavingcomment","global",0) CombatCounter(0) GlobalGT("bd_leaving_ot","GLOBAL",0) GlobalLT("bd_leaving_ot","GLOBAL",7) IsValidForPartyDialogue("xxBiff") GlobalTimerExpired("bd_leaving_ot_timer","global") !Dead("bdkorlas") // Korlasz !Global("BD_KORLASZ_SURRENDER","GLOBAL",1) THEN RESPONSE #200 Continue() RESPONSE #100 IncrementGlobal("bd_leaving_ot","global",1) SetGlobal("xxBiff_SoDleavingcomment","global",1) SetGlobalTimerRandom("bd_leaving_ot_timer","global",TWENTY_MINUTES,THIRTY_MINUTES) DisplayStringHead("xxBiff",~When we are finished here, I'll go and see whether I'll find a real theatre to perform... ah, no, it's too early to say this.~) END /* Second comment: after Korlasz defeated */ IF GlobalLT("xxBiff_SoDleavingcomment","global",2) CombatCounter(0) GlobalGT("bd_leaving2_ot","GLOBAL",0) GlobalLT("bd_leaving2_ot","GLOBAL",7) IsValidForPartyDialogue("xxBiff") GlobalTimerExpired("bd_leaving2_ot_timer","global") OR(2) Dead("bdkorlas") // Korlasz Global("BD_KORLASZ_SURRENDER","GLOBAL",1) THEN RESPONSE #200 Continue() RESPONSE #100 BanterBlockTime(100) IncrementGlobal("bd_leaving2_ot","global",1) SetGlobal("xxBiff_SoDleavingcomment","global",2) SetGlobalTimerRandom("bd_leaving2_ot_timer","global",EIGHT_MINUTES,THIRTEEN_MINUTES) DisplayStringWait("xxBiff",~Well done, everyone.~) END
And the according tp2 patching:
/* after Korlasz is defeated: DisplayStringHead of his further plans. Same script blocks get patched to both area scripts of Korlasz' Crypt */ EXTEND_BOTTOM ~bd0120.bcs~ ~%MOD_FOLDER%/baf/bd0120_commenting.baf~ EVALUATE_BUFFER EXTEND_BOTTOM ~bd0130.bcs~ ~%MOD_FOLDER%/baf/bd0120_commenting.baf~ EVALUATE_BUFFER
After the first group of enemies in bd0120.are are defeated, up to three NPCs have a DisplayStringHead. Some comment the fight, some the dungeon. Since I like it if the NPCs talk, Biff will comment in addition to the maximum of three other NPCs. Even if some day there will be more mod NPCs no incrementing the variable ("bd_mdd000te_ot"), I didn't see any problems in the game since it's only used to restrict NPC comments to a maximum of three.
Unless this will be fixed at some point, these comments and thus also your NPC's will only show for game difficulties harder than EASY, because only for these the number of available opponents will match the needed for triggering.
For Biff, we patch this to bd0120.bcs via EXTEND_TOP:
/* bd0120_commenting_et.baf This is a comment in bd0120.are (Korlasz' Crypt) after defeating the first enemies. Some NPCs commment on the fight, some on the dungeon. This will be patched to bd0120.bcs via EXTEND_TOP. Originally, only three NPCs will comment. Biff will comment in addition. */ IF Global("bd_plot","global",10) GlobalGT("bd_mdd000te_ot","bd0120",0) Global("xxBiff_bd_mdd000te_ot","bd0120",0) //this variable is similar to the ones used in SoD. I don't know what it means! :-) IsValidForPartyDialogue("xxBiff") THEN RESPONSE #200 Continue() RESPONSE #100 SetGlobal("xxBiff_bd_mdd000te_ot","bd0120",1) DisplayStringHead("xxBiff",~I didn't imagine this crypt to be so huge.~) Wait(5) Continue() END
And the according tp2 patching:
/* comment after defeating the first enemies in Korlasz' Crypt */ EXTEND_TOP ~bd0120.bcs~ ~%MOD_FOLDER%/baf/bd0120_commenting_et.baf~ EVALUATE_BUFFER
This is for NPCs the player takes into the group before leaving for the crusade. In the game, all original NPCs recruitable in BG city, i.e. Minsc, Dynaheir, and Safana, have a comment in the morning after the last night in the Ducal Palace, after Skie woke up the PC. For this, those three NPCs are moved into the PC's bed chamber by bdcut05.bcs which is triggered by Skie's dialgogue bdskie.dlg. Multiplayer NPCs (or mod NPCs without an addition) will be standing in the hall between the PC's and Imoen's chambers.
The actual moving of the party NPCs is done by bdcut05.bcs, but it is scripted in a way that patching it neither at top nor bottom will move mod NPCs in time. If we want Biff to be in the room, too, we need to patch the JumpToPoint to his OVERRIDE script. His morning comment needs to be patched to bd0103.bcs via EXTEND_TOP.
This is only needed for your NPC if they are already available inside the Baldur's Gate city areas of SoD.
The following goes into Biff's OVERRIDE script xxBiffs.baf:
/* Move Biff to the table in the morning after the last night in the Ducal Palace (before heading out against the Crusade) */ IF Global("bd_plot","global",55) Global("xxBiff_bd_55","bd0103",0) InParty("xxBiff") AreaCheck("bd0103") THEN RESPONSE #100 CutSceneId(Player1) ActionOverride("xxBiff",JumpToPoint([xxx.yyy])) //Somewhere near the small table by the stairs. For example Minsc: [568.270] ActionOverride("xxBiff",Face(S)) SetGlobal("xxBiff_bd_55","bd0103",1) END
The following goes into a .baf file, we will call it bd0103_commenting_et.baf:
/* bd0103_commenting_et.baf after Skie woke the PC up on the day of departure */ IF Global("bd_plot","global",55) Global("xxBiff_BD_PLAY_ONCE","BD0103",0) Global("BD_OT_DELAY","BD0103",0) IsValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetInterrupt(FALSE) SetGlobal("BD_OT_DELAY","BD0103",1) SetGlobal("xxBiff_BD_PLAY_ONCE","BD0103",1) Wait(1) DisplayStringWait("xxBiff",~This is the big day!~) SetGlobal("BD_OT_DELAY","BD0103",0) SetInterrupt(TRUE) Continue() END
And the according tp2 patching:
/* In case Biff is in party the last night the PC slept in Ducal Palace - comment after Skie is gone */ EXTEND_TOP ~bd0103.bcs~ ~%MOD_FOLDER%/baf/bd0103_commenting_et.baf~ EVALUATE_BUFFER
When the PC leaves the Ducal Palace, ready to march against the crusade, all NPCs and relevant coalition leaders (from BG) are gathered in front of the Entrance, along with a cheerful crowd. The area is now bd0101.are.
The NPCs not in the group have random DisplaystringHeads while they are waiting for the PC either to talk to them or to Corwin and start the march. We give Biff the Understudy, our example NPC, the following lines which need to be patched to bd0101.bcs with EXTEND_TOP. Note: we already used the name "bd0101_patch.baf" for Biff's spawning as described in Tutorial Part 1, so we will name this file "bd0101_commenting_et.baf", with "_et" for "EXTEND_TOP".
Of course, you could put all script blocks for bd0101.bcs into one file and patch them via EXTEND_TOP. But: if you do that, each script block from Tutorial Part 1 needs to have Continue() at the end.
/* bd0101_commenting_et.baf; this goes into bd0101.bcs */ /* Waiting to march out of BG city: make Biff comment while waiting to leave */ IF Global("bd_mdd010z_ot","bd0101",1) !GlobalTimerNotExpired("bd_mdd010z_ot_timer","bd0101") InMyArea("xxBiff") !InParty("xxBiff") THEN RESPONSE #10 SetGlobalTimer("bd_mdd010z_ot_timer","bd0101",ONE_ROUND) SetGlobal("bd_mdd010z_ot","bd0101",0) DisplayStringHead("xxBiff",~Wow, this is really exciting.~) Continue() RESPONSE #10 SetGlobalTimer("bd_mdd010z_ot_timer","bd0101",ONE_ROUND) SetGlobal("bd_mdd010z_ot","bd0101",0) DisplayStringHead("xxBiff",~That is really a huge crowd.~) Continue() RESPONSE #10 SetGlobalTimer("bd_mdd010z_ot_timer","bd0101",ONE_ROUND) SetGlobal("bd_mdd010z_ot","bd0101",0) DisplayStringHead("xxBiff",~Wait... do I have all the scripts? (murmurs) Corwin, Dunkan, Glint... Yes, all here. (phew)~) Continue() RESPONSE #160 Continue() END
And the according tp2 patching:
/* Waiting to march out of BG city: make Biff comment while waiting to leave */ EXTEND_TOP ~bd0101.bcs~ ~%MOD_FOLDER%/baf/bd0101_commenting_et.baf~ EVALUATE_BUFFER
When everyone starts marching out of the city to face the crusade, all NPCs not in the group start moving towards the southeast area exit until the scene fades to black.
We patch this to bdcut08.bcs so Biff will move, too:
/* bdcut08_patch.baf march out of BG city: make Biff move when the coalition start marching out of BG city */ IF True() THEN RESPONSE #100 CutSceneId("xxBiff") ApplySpellRES("BDSLOW",Myself) // sets the movement rate to "6" for 15 realtime seconds Wait(2) SmallWait(109) MoveToPoint([1090.1100]) //leave these in or chose a point in direction of the southeast area exit of bd0010.are, depending on where your NPC is waiting. END
And the according tp2 patching (note the EXTEND_TOP):
/* March out of BG city: make Biff move when the coalition start marching out of BG city */ EXTEND_TOP ~bdcut08.bcs~ ~%MOD_FOLDER%/baf/bdcut08_patch.baf~ EVALUATE_BUFFER
The actual commenting on the destruction of the bridge is in bdcut14.bcs, but the cutscene is such that it either needs to be patched using REPLACE_TEXTUALLY or somesuch to bring NPC reactions in the middle, or the NPC reactions need to be put elsewhere. I decided to put them into the NPC's OVERRIDE script so they trigger after the cutscene, when the intermediate fight with the crusaders trapped on the PC's side of the bridge starts. This is also why this time, the trigger does not contain a "CombatCounter(0)". This might delay NPC's ai fighting reactions since there is enemies right in front of them, but I couldn't detect any measurable effect while playing:
/* This goes into Biff's SoD OVERRIDE script */ /* bd1000: Biff comments on the explosion on the bridge */ IF GlobalTimerNotExpired("bd_caelar_timer","bd1000") AreaCheck("bd1000") IsValidForPartyDialog(Myself) Detect(Player1) Global("xxBiff_SoDbridge","bd1000",0) THEN RESPONSE #100 SetGlobal("xxBiff_SoDbridge","bd1000",1) DisplayStringHead(Myself,~What an explosion!~) END
After meeting Caelar across the Coastway Crossing Bridge, the NPCs have a comment on her via bd1000.bcs.
These comments will only show before the Flaming Fist soldiers and Bence Duncan attracted by the explosion will initiate dialogue which will happen if any party member comes near the exit by the tent at the bridge. Depending on how the group fight the trapped crusaders, this could be directly after the meeting happened, and no comments on Caelar will show. If you want your NPC comment on Caelar independent to this, you need to broaden the trigger a bit.
This will be patched to bd1000.bcs:
/* bd1000_commenting.baf: Reaction to Caelar */ IF Global("bd_plot","global",170) //after talking to Bence, this will be at Global("bd_plot","global",175) Global("xxBiff_bd_mdd016b","bd1000",0) !GlobalTimerNotExpired("bd_mdd016b_timer","bd1000") //timer to space the NPC comments IsValidForPartyDialog("xxBiff") TriggerOverride("xxBiff",Detect(Player1)) THEN RESPONSE #100 SetGlobal("xxBiff_bd_mdd016b","bd1000",1) SetGlobalTimer("bd_mdd016b_timer","bd1000",ONE_ROUND) DisplayStringHead("xxBiff",~Intimidating, that woman.~) END
And the tp2 patching:
/* (T3) Reaction to Caelar's first appearance on bridge */ EXTEND_BOTTOM ~bd1000.bcs~ ~%MOD_FOLDER%/baf/bd1000_commenting.baf~ EVALUATE_BUFFER
Inside the old temple of Bhaal (bd7230.are) there are three crusaders trapped in cages. A lever to the left will activate a spike trap in those cages, killing the three crusaders inside. The PC can either activate the trap by clicking on the lever twice. Before doing that, the PC can also threaten the crusaders with doing this.
If the lever is pulled twice and the crusaders killed that way, a PC being PALADIN or RANGER will fall. Please note: because of how it is scripted, clicking on the lever while having more than one group member selected is counted by the engine as more than one click - and the spike trapp will be activated even if the player clicked only once!
If the PC choses the threatening reply option it is only Rasaad who will react to the threat (and Dorn replying to Rasaad if present). But seeing how using the lever to kill the crusaders will lead to a fall of paladin- and rangerhood of the PC tells me that this is a situation where good aligned NPCs should react, and strongly.
So, Biff will do three things to serve as an example for other mod NPCs:
The comment into the dialogue is a simple I_C_T that needs to be put into a .d-file. In the tutorial mod package it is called sod_event_comments.d:
/* PC threatens to kill the crusaders with the spikes in bd7230.are */ I_C_T bdkharmy 6 xxBiff_bdkharmy_6 == xxBiffJ IF ~IsValidForPartyDialogue("xxBiff")~ THEN ~Wow, eeeevil.~ END
For the reaction to the usage of the spike trap, we need to patch the script bdlever2.bcs so it sets variables we can use for detection. For this, we add to the tp2:
/* React in case crusaders in cages are killed by spikes (bd7230.are) */ /* Patch bdlever2.bcs */ COPY_EXISTING ~bdlever2.BCS~ ~override~ DECOMPILE_AND_PATCH BEGIN SPRINT textToReplace ~\(Kill("bdkharmy")\)~ COUNT_REGEXP_INSTANCES ~%textToReplace%~ num_matches PATCH_IF (num_matches > 0) BEGIN REPLACE_TEXTUALLY ~%textToReplace%~ ~SetGlobal("xxBiff_UsedSpikes","GLOBAL",1) \1~ PATCH_PRINT ~Patching: %num_matches% matches found in %SOURCE_FILESPEC% for REPLACE_TEXTUALLY: %textToReplace%~ END ELSE BEGIN PATCH_WARN ~WARNING: could not find %textToReplace% in %SOURCE_FILESPEC%~ END SPRINT textToReplace ~\(ActionOverride(Player1,RemovePaladinHood())\)~ COUNT_REGEXP_INSTANCES ~%textToReplace%~ num_matches PATCH_IF (num_matches > 0) BEGIN REPLACE_TEXTUALLY ~%textToReplace%~ ~SetGlobal("xxBiff_SpikeTrapFall","GLOBAL",1) \1~ PATCH_PRINT ~Patching: %num_matches% matches found in %SOURCE_FILESPEC% for REPLACE_TEXTUALLY: %textToReplace%~ END ELSE BEGIN PATCH_WARN ~WARNING: could not find %textToReplace% in %SOURCE_FILESPEC%~ END SPRINT textToReplace ~\(ActionOverride(Player1,RemoveRangerHood())\)~ COUNT_REGEXP_INSTANCES ~%textToReplace%~ num_matches PATCH_IF (num_matches > 0) BEGIN REPLACE_TEXTUALLY ~%textToReplace%~ ~SetGlobal("xxBiff_SpikeTrapFall","GLOBAL",1) \1~ PATCH_PRINT ~Patching: %num_matches% matches found in %SOURCE_FILESPEC% for REPLACE_TEXTUALLY: %textToReplace%~ END ELSE BEGIN PATCH_WARN ~WARNING: could not find %textToReplace% in %SOURCE_FILESPEC%~ END END BUT_ONLY
And this goes into Biff's OVERRIDE script. For each reaction, there is a script block that will prevent Biff's reaction in case he wasn't around when it happened.
/* (T3) Biff should not react to spike trap if he wasn't around */ IF !InParty(Myself) OR(2) !AreaCheck("bd7230") !Range("Lever",30) Global("xxBiff_UsedSpikes","GLOBAL",1) //this variable is set by patching bdlever2.BCS via tp2 CombatCounter(0) THEN RESPONSE #100 SetGlobal("xxBiff_UsedSpikes","GLOBAL",3) END /* (T3) PC killed crusaders with the spikes */ IF InParty(Myself) IsValidForPartyDialog(Myself) See(Player1) AreaCheck("bd7230") Global("xxBiff_UsedSpikes","GLOBAL",1) //this variable is set by patching bdlever2.BCS via tp2 CombatCounter(0) THEN RESPONSE #100 SetGlobal("xxBiff_UsedSpikes","GLOBAL",2) DisplayStringHead(Myself,~If I'd be Lawful Good, I could also initiate dialogue and react by leaving the group or somesuch.~) END /* PC lost Paladinhood / Rangerhood due to spiketraps */ /* (T3) Biff should not react if he wasn't around */ IF !InParty(Myself) !AreaCheck("bd7230") Global("xxBiff_SpikeTrapFall","GLOBAL",1) //this variable is set by patching bdlever2.BCS via tp2 CombatCounter(0) THEN RESPONSE #100 SetGlobal("xxBiff_SpikeTrapFall","GLOBAL",4) END /* (T3) Biff was around: PC lost Paladinhood / Rangerhood due to spiketraps */ IF InParty(Myself) IsValidForPartyDialog(Myself) See(Player1) AreaCheck("bd7230") Global("xxBiff_SpikeTrapFall","GLOBAL",1) //this variable is set by patching bdlever2.BCS via tp2 CombatCounter(0) THEN RESPONSE #100 SetGlobal("xxBiff_SpikeTrapFall","GLOBAL",2) END /* trigger */ IF See(Player1) CombatCounter(0) !See([ENEMY]) !StateCheck(Myself,CD_STATE_NOTVALID) !StateCheck(PLAYER1,CD_STATE_NOTVALID) Global("xxBiff_SpikeTrapFall","GLOBAL",2) THEN RESPONSE #100 StartDialogNoSet(Player1) END
The comment about the fallen PC goes into the .d-file. In the tutorial mod package it is called sod_event_comments.d:
APPEND xxBiffJ /* (T3) PC lost paladinhood / rangerhood due to the spike trap */ IF ~Global("xxBiff_SpikeTrapFall","GLOBAL",2)~ THEN spiketrap_fall SAY ~Whoa, <CHARNAME>. As a paladin or ranger, I would totally go nuts right now!~ IF ~~ THEN DO ~SetGlobal("xxBiff_SpikeTrapFall","GLOBAL",3) /* uncomment the following line if it makes sense for your NPC */ //SetLeavePartyDialogFile() LeaveParty() Enemy() Attack(Player1) ~ EXIT END END //APPEND
In chapter 9, the PC has the opportunity to hand over Bridgefort to the crusaders without a fight. Good aligned NPCs in the party will call this a betrayal. First, Corwin will speak up, then Khalid. Neera, Rasaad, Dynaheir, and Minsc will chime in depending on the PC's replies, and finally Jaheira.
If Corwin is not in the party, the dialogue will be started by Khalid and the other NPCs will chime in as described. If Khalid is not in the party, then Jaheira, Minsc, and Rasaad will have their dialogue lines as DisplayStringHeads, instead.
So, we want two things for Biff: if Khalid is in the group and able to talk, we want Biff to say his comment after Khalid's first line. If Khalid is not able to talk, Biff should have his comment as a floating text above his head - but after Corwin spoke her line if she is in party and able to talk.
To achieve this, we need to consider the following:
This is what we put into a .d file. In the tutorial mod package it is called sod_event_comments.d:
/* PC handed over the Bridgefort Castle to the crusaders */ I_C_T BDKHALIJ 33 xxBiff_betrayal_discussion //"xxBiff_betrayal_discussion" is the name of the global variable == xxBiffJ IF ~IsValidForPartyDialogue("xxBiff")~ THEN ~Well, this was definitely faster.~ END
This is what we will patch to bd2000.bcs via EXTEND_TOP:
/* bd2000_commenting_et.baf */ /* PC surrendered Bridgefort to the Crusaders */ IF Global("bd_plot","global",260) Global("xxBiff_betrayal_discussion","GLOBAL",0) //same variable as in the I_C_T so this doesn't fire if the dialogue happened !GlobalTimerNotExpired("bd_betrayal_discuss_timer","bd2000") //in case there are more mod NPCs commenting !IsValidForPartyDialogue("KHALID") //only if Khalid cannot start his dialogue IsValidForPartyDialogue("xxBiff") OR(2) !IsValidForPartyDialogue("CORWIN") //Corwin is either not here Global("bd_betrayal_discussion","bd2000",1) //or Corwin's dialogue fired already THEN RESPONSE #100 SetGlobal("xxBiff_betrayal_discussion","GLOBAL",1) SetGlobalTimer("bd_betrayal_discuss_timer","bd2000",ONE_MINUTE) //to space all the other NPC comments DisplayStringHead("xxBiff",~Well, this was definitely faster.~) Continue() END
And the tp2 patching:
/* (T3) PC gave Bridgefort Castle to the crusaders */ EXTEND_TOP ~bd2000.bcs~ ~%MOD_FOLDER%/baf/bd2000_commenting_et.baf~ EVALUATE_BUFFER
The random encounter area bd0063.are features an ambush inside a canyon. Some of the NPCs have a comment here: Minsc or Corwin will state the possibility of an ambush, and either Edwin, Baeloth, Dynaheir, or Neera will inform the PC that it's a dead magic zone. This is done in a way that either one NPC of each of the two groups will speak randomly, and only if this didn't happen (because the NPC in question is not in party), each one of the NPCs are called in extra script blocks directly in case the random script blocks didn't trigger.
We will not touch the random script blocks as patching them will not be possible in a compatible manner for more than one NPC mod, but we will add a script block so that our NPC can state the obvious in case the original NPCs are not present.
In case you want your NPC to steal the show, you could patch the script addition via EXTEND_TOP - then your NPC will be the one stating the warning, unless another mod NPC installed after yours did the same. I decided to play nice and add Biff's comments at the end, so they will only show if none of the 6 mentioned NPCs of the two groups are present.
Of course you can make your NPC say something in addition to the other ones. In this case you need to use own trigger variables for the commenting script blocks and using EXTEND_BOTTOM is sufficient.
This is what we will patch to bd0063.bcs. It contains both script blocks, one for a fighter who would warn about the place being a good ambush point and the second for a mage who would warn about the place being a dead magic zone:
/* bd0063_commenting.baf */ /* Warn about the place being a good ambush point: */ IF Global("BD_NPC02","MYAREA",0) //neither Minsc nor Corwin gave a warning about a possible ambush IfValidForPartyDialog("xxBiff") Delay(3) THEN RESPONSE #100 SetGlobal("BD_NPC02","MYAREA",1) DisplayStringHead("xxBiff",~This looks like the ambush site we are supposed to encounter~) END /* Warn about the place being a dead magic zone (mages only): */ IF Global("BD_NPC01","MYAREA",0) //neither Edwin, Baeloth, Dynaheir, nor Neera gave a warning about dead magic zone IfValidForPartyDialog("xxBiff") Delay(3) THEN RESPONSE #100 SetGlobal("BD_NPC01","MYAREA",1) DisplayStringHead("xxBiff",~By the way, this is a dead magic zone.~) END
And the tp2 patching:
/* (T3) Comment in random area (Canyon Ambush) bd0063.are */ EXTEND_BOTTOM ~bd0063.bcs~ ~%MOD_FOLDER%/baf/bd0063_commenting.baf~ EVALUATE_BUFFER
In the spider cave (bd0114.are) a giant beetle will appear. After killing it, all party members will comment. A timer helps to space the comments appropriately.
This is what we will patch to bd0114.bcs:
/* bd0114_commenting.baf */ IF Global("BD_POINT6","BD0114",4) // Spider Cave: Rhinoceros Beetle appeared StateCheck("BDBEETRH",STATE_REALLY_DEAD) // Rhinoceros Beetle Global("xxBiff_BD_BEETLE","BD0114",0) !GlobalTimerNotExpired("BD_TIMER_RHINOTALK","BD0114") IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 DisplayStringHead("xxBiff",~Wow. This thing always makes me a bit nervous.~) SetGlobal("xxBiff_BD_BEETLE","BD0114",1) END
And the tp2 patching:
/* (T3) Comment after killing the Rhinoceros Beetle in bd0114.are */ EXTEND_BOTTOM ~bd0114.bcs~ ~%MOD_FOLDER%/baf/bd0114_commenting.baf~ EVALUATE_BUFFER
When the battle for Bridgefot starts, all NPC will have a comment.
This is what we will patch to bd2000.bcs:
/* bd2000_commenting.baf */ /* Battle at Bridgefort starts */ IF Global("bd_plot","global",250) !GlobalTimerNotExpired("bd_mdd410z_ot_timer","bd2000") Global("xxBiff_bd_ot","bd2000",0) IfValidForPartyDialog("xxBiff") TriggerOverride("xxBiff",Range([ENEMY.0.0.0.CRUSADERS],30)) THEN RESPONSE #100 SetGlobalTimer("bd_mdd410z_ot_timer","bd2000",THREE_MINUTES) // Boareskyr Bridge & Bridgefort SetGlobal("xxBiff_bd_ot","bd2000",1) DisplayStringHead("xxBiff",~Alright, you know what to do! Noone fall into their weapons, please!~) END
And the tp2 patching:
/* Battle at Bridgefort starts */ EXTEND_BOTTOM ~bd2000.bcs~ ~%MOD_FOLDER%/baf/bd2000_commenting.baf~ EVALUATE_BUFFER
In bd4300.bcs happen several things so I decided to put them into the same baf file.
This is what we will patch to bd4300.bcs:
/* bd4300_commenting_et.baf */ /* 1 Hephernaan discovered the group inside the castle */ IF Global("bd_plot","global",370) !GlobalTimerNotExpired("bd_mdd905a_ot_timer","bd4300") Global("xxBiff_bd_ot","bd4300",0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobalTimer("bd_mdd905a_ot_timer","bd4300",THREE_MINUTES) SetGlobal("xxBiff_bd_ot","bd4300",1) DisplayStringHead("xxBiff",~We should leave, like, now.~) SmallWait(8) Continue() END /* 2 Portal is opened after Hephernaan's scheme */ IF AreaCheck("BD4300") Global("bd_plot","global",495) Global("xxBiff_SoDPortalComment","bd4300",0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobal("xxBiff_SoDPortalComment","bd4300",1) DisplayStringHead("xxBiff",~Ouch, I don't like this part. Does it hurt, <CHARNAME>?~) SmallWait(8) Continue() END /* 3 PC killed the crusaders at the portal */ IF Global("xxBiff_bd_MDD892a_ot","bd4300",0) Global("bd_poison_dsc_supplies","global",0) Dead("bdbelben") // Belben CombatCounter(0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobal("xxBiff_bd_MDD892a_ot","bd4300",1) SetGlobalTimer("bd_MDD892a_ot_timer","bd4300",ONE_MINUTE) //timer will be checked for Corwin DisplayStringHead("xxBiff",~Never a good idea, fighting us.~) Continue() END /* 4 Comment after first wave of demons if PC lingers */ IF GlobalLT("bd_plot","global",499) Global("bd_mdd1290d_ot","bd4300",1) Global("xxBiff_bd_mdd1290d_ot","bd4300",0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 DisplayStringHead("xxBiff",~So many demons! Well, I guess that's no wonder considering there is an open portal to Avernus.~) SetGlobal("xxBiff_bd_mdd1290d_ot","bd4300",1) SmallWait(8) Continue() END /* 5 Comment after return from Avernus: portal is closed */ IF Global("bd_plot","global",586) !GlobalTimerNotExpired("bd_mdd1341a_ot_timer","bd4300") Global("xxBiff_bd_ot2","bd4300",0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobalTimer("bd_mdd1341a_ot_timer","bd4300",2) // Dragonspear Castle Basement SetGlobal("xxBiff_bd_ot2","bd4300",1) DisplayStringHead("xxBiff",~We are back!~) Continue() END
And the tp2 patching via EXTEND_TOP:
/* Comments in bd4300.are (Bridgefort Castle interior and Avernus portal) */ EXTEND_TOP ~bd4300.bcs~ ~%MOD_FOLDER%/baf/bd4300_commenting_et.baf~ EVALUATE_BUFFER
Upon entering the portal and reaching Avernus, up to three NPCs will give a comment. The chances of original NPCs talking is reduced to 50% by giving two RESPONSE #50 action blocks.
Our NPC will say their piece in addition, but also only with a 50% chance. If you want your NPC to give their comment always, you need to remove one of the #50 action blocks and change the percetage to #100 as indicated below.
This is what we will patch to bd4400.bcs:
/* bd4400_commenting.baf */ /* Comment upon entering Avernus */ IF GlobalLT("bd_plot","global",505) IfValidForPartyDialog("xxBiff") Global("xxBiff_bd_avernus_bark","bd4400",0) THEN RESPONSE #50 //Remove this if your NPC should say their line always Continue() //Remove this if your NPC should say their line always RESPONSE #50 //change this to #100 if your NPC should say their line always DisplayStringWait("xxBiff",~It's hot in here!~) SetGlobal("xxBiff_bd_avernus_bark","bd4400",1) SmallWait(8) END
And the tp2 patching:
/* Comment upon entering Avernus */ EXTEND_BOTTOM ~bd4400.bcs~ ~%MOD_FOLDER%/baf/bd4400_commenting.baf~ EVALUATE_BUFFER
Inside Avernus, the group has to use an elevator. Between the demon showers, the NPCs comment on it.
This is what we will patch to bd4601.bcs:
/* bd4601_commenting.baf */ /* Comment in the Avernus Elevator */ IF GlobalGT("bd_plot","global",554) Global("xxBiff_bd_hellevator_ot","bd4601",0) IfValidForPartyDialog("xxBiff") !GlobalTimerNotExpired("bd_hellevator_timer","bd4601") !ActuallyInCombat() THEN RESPONSE #100 SetGlobal("xxBiff_bd_hellevator_ot","bd4601",1) // Avernus Elevator SetGlobalTimer("bd_hellevator_timer","bd4601",7) DisplayStringHead("xxBiff",~Better not be afraid of heights! ... And demons.~) END
And the tp2 patching:
/* Comment in the Avernus Elevator */ EXTEND_BOTTOM ~bd4601.bcs~ ~%MOD_FOLDER%/baf/bd4601_commenting.baf~ EVALUATE_BUFFER
In the Underground River area (bd5100.are) there is a cave with three blind wyrmlings inside. Either Jaheira, Dynaheir, Minsc, or M'Khiin will give a comment upon reaching the entrance to the cave about "Pain and sorrow knot together" (Dynaheir), "a powerful anger" (Jaheira), "Boo is restless" (Minsc), or "So much rage in the air" (M'Khiin). How the NPCs got their 6th sense I don't know, neither why it is this choice of NPCs. Nevertheless, if your NPC should give a warning too, here is a way to script it so that your NPC speaks if none of the other does.
If your NPC should speak up in addition to one of the original ones you need to remove the original variable Global("BD_SDD317_WYRMS","BD5100",0) out of the script block. Also, the comment could be done via DisplayStringHead instead of calling a real dialogue line.
This is what we will patch to bd5100aw.bcs:
/* bd5100aw_commenting.baf */ /* Comment before entering the Cave with the blind Wyrmlings (bd5100aw.bcs). Will only fire if no original NPC gives their line. */ IF OR(3) Entered([GOODCUTOFF]) IsOverMe([GOODCUTOFF]) WalkedToTrigger([GOODCUTOFF]) Range([PC],20) Global("BD_SDD317_WYRMS","BD5100",0) //this is the original trigger variable which makes sure your NPC only speaks up if none of the original did. Remove if you want your NPC to speak up always. Global("xxBiff_BD_SDD317_WYRMS","BD5100",0) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobal("xxBiff_BD_SDD317_WYRMS","BD5100",1) ActionOverride("xxBiff",StartDialogNoSet(Player1)) END
And the tp2 patching:
/* Comment before entering the Cave with the blind Wyrmlings (bd5100aw.bcs) */ EXTEND_BOTTOM ~bd5100aw.bcs~ ~%MOD_FOLDER%/baf/bd5100aw_commenting.baf~ EVALUATE_BUFFER
The comment is an actual dialogue pop up. The following goes into the NPC's joined dialogue file:
/* Comment before entering the Cave with the blind Wyrmlings (bd5100aw.bcs) */ APPEND xxBiffJ IF ~Global("xxBiff_BD_SDD317_WYRMS","BD5100",1)~ THEN blind_wyrm_comment SAY ~There is something weird and dangerous in the cave in front of us.~ IF ~~ THEN DO ~SetGlobal("xxBiff_BD_SDD317_WYRMS","BD5100",2)~ EXIT END END //APPEND
After the three blind wyrmlings in the cave (bd0113.are) are killed, Jaheira or Corwin will have a remark. I put the according trigger here in case you want your NPC to comment, too.
This is what we will patch to bd0113.bcs to trigger the dialogue:
/* bd0113_commenting.baf */ /* Comment after killing the blind Wyrmlings in Cave (bd0113.bcs) */ IF StateCheck("BDWYRMLI",STATE_REALLY_DEAD) // Blind Albino Wyrmling NumDeadGT("BDWYRML1",2) // Blind Albino Wyrmling GlobalGT("BD_SDD317_WYRMS","BD5100",2) //remove this if your NPC should talk in addition to Jaheira or Corwin !IfValidForPartyDialog("JAHEIRA") //remove this if your NPC should talk in addition to Jaheira or Corwin !IfValidForPartyDialog("CORWIN") //remove this if your NPC should talk in addition to Jaheira or Corwin GlobalLT("xxBiff_BD_SDD317_WYRMS","BD5100",3) CombatCounter(0) THEN RESPONSE #100 SetGlobal("xxBiff_BD_SDD317_WYRMS","BD5100",3) ActionOverride("xxBiff",StartDialogNoSet(Player1)) END
And the tp2 patching:
/* Comment after killing the blind Wyrmlings in Cave (bd0113.bcs) */ EXTEND_BOTTOM ~bd0113.bcs~ ~%MOD_FOLDER%/baf/bd0113_commenting.baf~ EVALUATE_BUFFER
The comment is an actual dialogue pop up. The following goes into the NPC's joined dialogue file:
/* Comment after killing the blind Wyrmlings in Cave (bd0113.bcs) */ APPEND xxBiffJ IF ~Global("xxBiff_BD_SDD317_WYRMS","BD5100",3)~ THEN blind_wyrm_comment SAY ~Now they are dead.~ IF ~~ THEN DO ~SetGlobal("xxBiff_BD_SDD317_WYRMS","BD5100",4)~ EXIT END END //APPEND
In one of the areas in the Underground River, Kanaglym (bd5300.are) the group has to fight a necromancer and his ghost dragon. The NPCs give a shout when the fight starts.
This is what we will patch to bd5300.bcs:
/* bd5300_commenting.baf */ /* Comment when battle starts in Kanaglym (bd5300.are, Underground River) */ IF Global("BD_AREA_HOSTILE","BD5300",1) // Kanaglym !GlobalTimerNotExpired("bd_sdd350b_ot_timer","bd5300") // The original timer has the area code from Boareskyr Bridge & Bridgefort - I *think* this is a bug so I corrected it Global("xxBiff_bd_ot","bd5300",0) IfValidForPartyDialog("xxBiff") TriggerOverride("xxBiff",Range([ENEMY.0.0.0.HOSTILES3],30)) THEN RESPONSE #100 SetGlobalTimer("bd_sdd350b_ot_timer","bd5300",THREE_MINUTES) // The original timer has the area code from Boareskyr Bridge & Bridgefort - I *think* this is a bug so I corrected it SetGlobal("xxBiff_bd_ot","bd5300",1) DisplayStringHead("xxBiff",~Here we go!~) END
And the tp2 patching:
/* Comment when battle starts in Kanaglym (bd5300.are, Underground River) */ EXTEND_BOTTOM ~bd5300.bcs~ ~%MOD_FOLDER%/baf/bd5300_commenting.baf~ EVALUATE_BUFFER
This section is deprecated alongside the according components to move the NPC at the end of SoD described in Tutorial 2 ("Make Your NPC Comment and Move Along at the End of SoD"). I'll leave it in so anyone interested can try to make this work without having to search for the involved scripts anew.
SoD comes with an abduction cutscene at the end which is disabled for the original product. EET restores this cutscene, as does one component of my Jastey's SoD Tweak Pack.
The group in the last game area is attacked by hooded figures, and two comments can be said by three NPCs each depending on the moment (one for being attacked, one when they lose consciousness). The following code will add comments for our NPC in addition to the three original group members if the NPC is in the group.
Both script blocks make the NPC comment with a 33% chance. If you want your NPC to comment always, you need to remove the extra RESPONSE #200 Continue() action block.
This is what we will patch to bd6100.bcs:
/* bd6100_commenting_et.baf */ /* Last area bd6100.are: comment in abduction scene (for EET or SoD with Jastey's SoD Tweak Pack) */ /* makes the NPC comment with a 33% chance during the rush of the attack */ IF !RealGlobalTimerExpired("bd_stop_alertbark","bd6100") GlobalTimerExpired("bd_second_alertbark","BD6100") GlobalGT("bd_Mdd1735a_ot","bd6100",0) Global("xxBiff_alert","bd6100",0) Global("bd_finale","bd6100",4) IfValidForPartyDialog("xxBiff") TriggerOverride("xxBiff",Detect([ENEMY])) THEN RESPONSE #200 //remove this if your NPC should comment always Continue() //remove this if your NPC should comment always RESPONSE #100 SetGlobal("xxBiff_alert","bd6100",1) DisplayStringHead("xxBiff",~An ambush! They are attacking us!~) SetGlobalTimerRandom("bd_second_alertbark","BD6100",2,4) Continue() END /* makes the NPC comment with a 33% chance to fog before the black out */ IF GlobalTimerExpired("bd_effectbark","BD6100") Global("xxBiff_bd_effect","bd6100",0) THEN RESPONSE #200 //remove this if your NPC should comment always Continue() //remove this if your NPC should comment always RESPONSE #100 SetGlobal("xxBiff_bd_effect","bd6100",1) DisplayStringHead("xxBiff",~That fog stinks.~) SetGlobalTimerRandom("bd_effectbark","BD6100",2,4) Continue() END
And the tp2 patching via EXTEND_TOP:
/* End of SoD - Comment in Abduction Scene */ EXTEND_TOP ~bd6100.bcs~ ~%MOD_FOLDER%/baf/bd6100_commenting_et.baf~ EVALUATE_BUFFER
In the Dragonspear Castle exterior area (bd4000.are) after freeing the castle, Glint, Minsc, and Corwin react when reaching the top of the stairs beside the huge dragon skelleton.
To let our NPC comment, too, we need to patch the trigger script bdbark01.bcs.
This is what we will patch to bdbark01.bcs:
/* bdbark01_commenting.baf */ /* Comment in Dragonspear Castle Exterior */ IF Name("bark_mdd1246a",Myself) Global("xxBiff_bd_mdd1246a_ot","bd4000",0) Range("xxBiff",35) Global("chapter","global",11) IfValidForPartyDialog("xxBiff") THEN RESPONSE #100 SetGlobal("xxBiff_bd_mdd1246a_ot","bd4000",1) DisplayStringHead("xxBiff",~Huge dragon skelleton!~) END
And the tp2 patching:
/* Comment in Dragonspear Castle Exterior */ EXTEND_BOTTOM ~bdbark01.bcs~ ~%MOD_FOLDER%/baf/bdbark01_commenting.baf~ EVALUATE_BUFFER
When the PC interacts with the plotting nobles in the Three Kegs there is a cutscene which gets called twice which places the party NPCs inside the northwest room where the confrontation with the Flaming Fist takes place. Unfortunately, instead of just using the general Player2-6 the script works with the explicit NPC names that are available until then - Safana, Minsc, and Dynahier. We need to add our NPC explicitely, too.
This is only needed for your NPC if they are already available inside the Baldur's Gate city areas of SoD.
This is what we will patch to bdc116d.bcs:
/* bdc116d_patch.baf */ /* Move the PC in the cutscene of the plotting nobles in Three Old Kegs (bdc116d.bcs) */ IF Global("bd_uncovered_seditious_plot","BD0108",1) InParty("xxBiff") THEN RESPONSE #100 CutSceneId("xxBiff") JumpToPoint([xx.yy]) //use coordinates at the left side of the northwest room. For example, Minsc is placed at [296.246] Face(E) //adjust facing position accordingly, so the NPC looks into the room END IF Global("bd_uncovered_seditious_plot","BD0108",2) InParty("xxBiff") THEN RESPONSE #100 CutSceneId("xxBiff") JumpToPoint([xx.yy]) //use coordinates in the middle of the northwest room. For example, Minsc is placed at [424.186] Face(E) //adjust facing position accordingly, so the NPC looks into the room END
And the tp2 patching:
/* Move the PC in the cutscene of the plotting nobles in Three Old Kegs (bdc116d.bcs) */ EXTEND_TOP ~bdc116d.bcs~ ~%MOD_FOLDER%/baf/bdc116d_patch.baf~ EVALUATE_BUFFER
When reaching the closed doors before the portal, one of the original NPC comment on how evil they look.
This is what we will patch to bdvaultd.bcs so our NPC makes a comment in case none of the original NPCs is present:
/* bdvaultd_patch.baf */ /* Comment on closed vault door (to portal) in Dragonspear Castle Interior */ IF Global("bd_MDD893a_ot","bd4300",0) // if your NPC should comment in addition, change this to a unique variable with your prefix GlobalLT("bd_plot","global",400) CombatCounter(0) Range("xxBiff",25) THEN RESPONSE #100 SetGlobal("bd_MDD893a_ot","bd4300",1) // if your NPC should comment in addition, change this to the same unique variable with your prefix like above DisplayStringHead("xxBiff",~Huge, evil doors. Well, not the doors, but what lies behind.~) END
And the tp2 patching:
/* Comment on closed vault door (to portal) in Dragonspear Castle Interior */ EXTEND_BOTTOM ~bdvaultd.bcs~ ~%MOD_FOLDER%/baf/bdvaultd_patch.baf~ EVALUATE_BUFFER
In Avernus in front of the great door to the great endboss a fiend names Thrix will want to play a game with the PC: he gets a soul from either one of the group members if the PC loses, and the PC gets a weapon if saying the correct answer.
To determine which NPC Thrix proposes for taking the soul, the dialogue pretends a certain randomness which we will try to preserve with our addition for our NPC. Since the chosing of the NPC(s) is not done with real randomness, what we will do is add our NPC to each of the 4 corresponding dialogue blocks with which the randomness is simulated.
To be precise, we will add our NPC to the bottom of the first, the top of the second, at position 10 of the third and position 5 of the 4th. This way, it will not be our NPC that gets chosen every time and the outcome is somewhat unpredictable, which gives enough credit to how Thix' dialogue is coded.
This tutorial shows the standard case: Thrix will chose our NPC, the PC can either accept, request that Thrix choses another, offer their own soul, or attack. If our NPC is chosen and the PC accepts, there will be a follow-up dialogue of our NPC.
Of course, there can be other possibilities as well: Thrix can first ponder your NPC but then decide not to take them himself, and the NPC can also react to the PC offering his own soul etcpp. Feel free to expand on the example, as always.
The variable Global("xxBiff_SoDThrix","GLOBAL") is used as follows. We do not need all the variants for what we do in this tutorial, but this way, you have all you need to let your NPC react to all outcomes.
There are the following variables we can use and track in the game:
This is what we will put into a .d file. In the tutorial mod package it is called sod_event_comments.d.
The "DO 2 IF ~!Is?f?ValidForPartyDialogue("Rasaad")~" at the end of the ADD_TRANS_TRIGGER syntax makes sure the third reply option (counted from the top starting with "0") will only be patched if it's the correct one containing the check whether no NPC in party is able to talk. This means that if another mod shifted the reply option numbers, nothing will be patched. Look at argent77's function GET_RESPONSE_STRREFS to identify and patch the correct response in a dialogue state even if their numbers were shifted: (and following posts) [How-To] "GET_RESPONSE_STRREFS function - finding the correct original game reply option number of a certain state number if knowing the stringref number of that reply option", by argent77
/* Thrix's game */ /* Thrix will not propose gamble if there is no NPC available: add Biff here */ ADD_TRANS_TRIGGER BDTHRIX 13 ~!IsValidForPartyDialogue("xxBiff")~ DO 2 IF ~!Is?f?ValidForPartyDialogue("Rasaad")~ /* Thrix' game: add Biff for certain randomness to the blocks of 4 dialogue states each */ /* 1st states of 4 state blocks: add Biff to the end */ EXTEND_BOTTOM BDTHRIX 21 26 30 34 38 42 46 50 54 58 62 66 70 74 78 82 86 90 IF ~Global("xxBiff_SoDThrix","GLOBAL",0) IsValidForPartyDialogue("xxBiff")~ THEN + xxBiff_thrix END /* 2nd states of 4 state blocks: add Biff at the top, i.e. position "1" as "0" is in case there is no more NPC available */ EXTEND_TOP BDTHRIX 22 27 31 35 39 43 47 51 55 59 63 67 71 75 79 83 87 91 #1 IF ~Global("xxBiff_SoDThrix","GLOBAL",0) IsValidForPartyDialogue("xxBiff")~ THEN + xxBiff_thrix END /* 3rd states of 4 state blocks: add Biff at position 10 */ EXTEND_TOP BDTHRIX 23 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 #10 IF ~Global("xxBiff_SoDThrix","GLOBAL",0) IsValidForPartyDialogue("xxBiff")~ THEN + xxBiff_thrix END /* 4th states of 4 state blocks: add Biff at position 5 */ EXTEND_TOP BDTHRIX 24 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 #5 IF ~Global("xxBiff_SoDThrix","GLOBAL",0) IsValidForPartyDialogue("xxBiff")~ THEN + xxBiff_thrix END /* in case PC lost and Biff was chosen: Thrix claims him (only verbally) */ EXTEND_BOTTOM BDTHRIX 118 119 120 121 IF ~Global("xxBiff_SoDThrix","GLOBAL",2) IsValidForPartyDialogue("xxBiff")~ THEN + xxBiff_chosen END /* Thrix new dialogue for our NPC */ APPEND BDTHRIX IF ~~ THEN BEGIN xxBiff_thrix SAY ~The Understudy... always so well prepared. I will take his soul and show him that he is not prepared, at all.~ IF ~~ THEN REPLY ~You want Biff? Then he will be yours if I lose.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",1) SetGlobal("bd_thrix_sacrifice_companion","global",1) ~ EXTERN xxBiffJ thrix_01 IF ~RandomNum(4,1)~ THEN REPLY ~Biff is with me on a path of education. You will not get his soul.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",2) IncrementGlobal("BD_NumInParty","bd4500",1)~ + 70 IF ~RandomNum(4,2)~ THEN REPLY ~Biff is with me on a path of education. You will not get his soul.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",2) IncrementGlobal("BD_NumInParty","bd4500",1)~ + 71 IF ~RandomNum(4,3)~ THEN REPLY ~Biff is with me on a path of education. You will not get his soul.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",2) IncrementGlobal("BD_NumInParty","bd4500",1)~ + 72 IF ~RandomNum(4,4)~ THEN REPLY ~Biff is with me on a path of education. You will not get his soul.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",2) IncrementGlobal("BD_NumInParty","bd4500",1)~ + 73 IF ~!Global("BD_NumInParty","bd4500",1) !Global("BD_NumInParty","bd4500",2) !Global("BD_NumInParty","bd4500",3) !Global("BD_NumInParty","bd4500",4)~ THEN REPLY ~Biff is with me on a path of education. You will not get his soul.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",2)~ + 114 IF ~~ THEN REPLY ~He has his faults, but I'll not risk Biff's soul in so blithe a fashion. If I cannot answer your riddle, mine is the soul you will take. Agreed?~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",3)~ GOTO 113 IF ~~ THEN REPLY ~I'll feed you your own limbs if you don't let me into the tower, you wretched creature. I'm done playing games with you.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",5)~ GOTO 12 END IF ~~ THEN xxBiff_chosen SAY ~Thrix has marked your soul, Understudy. Your soul is mine!~ ++ ~Whoops. Sorry, Biff.~ DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",4)~ EXTERN xxBiffJ thrix_02 ++ ~No, you will not take his soul, devil. We will fight you!~ GOTO 10 END END //APPEND /* Biff's reactions in Thrix' dialogue */ APPEND xxBiffJ IF ~~ THEN thrix_01 SAY ~(gulp) I don't like where this is going.~ IF ~~ THEN EXTERN ~BDTHRIX~ 116 END IF ~~ THEN thrix_02 SAY ~(Fortunately I know that he never really comes to claim the soul, you know.)~ IF ~~ THEN DO ~SetGlobal("bd_thrix_won","global",1) //this is for an achievement ~ EXTERN ~BDTHRIX~ 140 END END //APPEND
After the riddle is done and Thrix is gone, our NPC should react in case their soul was chosen and the PC gave it away. This is what we will patch to Biff's SoD override script:
/* Biff reacts to Thrix's game */ /* PC offered Biff's soul */ IF IsValidForPartyDialogue(Myself) See(Player1) CombatCounter(0) !See([ENEMY]) !StateCheck(Myself,CD_STATE_NOTVALID) !StateCheck(PLAYER1,CD_STATE_NOTVALID) OR(2) /* Biff was chosen and the PC accepted it, but either won the game [will be addressed in Biff's dialogue] or tried to fight the demon off after losing. */ OR(2) Global("xxBiff_SoDThrix","GLOBAL",1) // Global("xxBiff_SoDThrix","GLOBAL",2) //etc.: add according to where your NPC should react and adjust the OR() accordingly /* Biff was chosen before the riddle and the PC sent him off to Thrix (verbally) after losing. */ Global("xxBiff_SoDThrix","GLOBAL",4) GlobalLT("bd_plot","global",550) OR(2) Global("bd_thrix_plot","global",20) Dead("bdthrix") // Thrix THEN RESPONSE #100 IncrementGlobal("xxBiff_SoDThrix","GLOBAL",5) //increases by 5 END /* trigger */ IF IsValidForPartyDialogue(Myself) See(Player1) CombatCounter(0) !See([ENEMY]) !StateCheck(Myself,CD_STATE_NOTVALID) !StateCheck(PLAYER1,CD_STATE_NOTVALID) OR(2) Global("xxBiff_SoDThrix","GLOBAL",6) // Global("xxBiff_SoDThrix","GLOBAL",7) //etc.: according to where your NPC should react and adjust the OR() accordingly Global("xxBiff_SoDThrix","GLOBAL",9) THEN RESPONSE #100 StartDialogNoSet(Player1) END
Biff's follow up dialogue again goes into a d-file, for example the same as used above:
/* I do the reaction in one CHAIN. Change this to whatever dialogue tree fits your NPC. */ CHAIN IF ~OR(2) Global("xxBiff_SoDThrix","GLOBAL",6) // Global("xxBiff_SoDThrix","GLOBAL",7) //etc.: according to where your NPC should react and adjust the OR() accordingly Global("xxBiff_SoDThrix","GLOBAL",9)~ THEN xxBiffJ after_thrix ~You were quite ready to give my soul to that fiend, <CHARNAME>.~ == xxBiffJ IF ~Global("BD_Thrix_riddle_won","GLOBAL",1)~ THEN ~Luckily, you won the game, so no harm done.~ == xxBiffJ IF ~Global("xxBiff_SoDThrix","GLOBAL",6) !Global("BD_Thrix_riddle_won","GLOBAL",1)~ THEN ~I appreciate you tried to fight the fiend in the end, but unluckily, the harm was done.~ == xxBiffJ IF ~Global("xxBiff_SoDThrix","GLOBAL",9) !Global("BD_Thrix_riddle_won","GLOBAL",1)~ THEN ~Why did you do that? Trading my soul to a fiend! You gave my soul a little bit too readily for my taste, you know.~ END IF ~~ THEN DO ~SetGlobal("xxBiff_SoDThrix","GLOBAL",11)~ EXIT // We need to do this here or the checks above will not work.
In the big coalition camp bd3000.are, there are six recruits where the PC and specific NPCs can help with their training: Clovis, Danine, Garrold, Hester, Morlis, and Taield. For most cases this is done by reply options with which the PC can ask NPCs for their help. The original reply options featuring this usually go along the lines of "npcname, do you have something to say?" with the exception of Morlis and Danine as described below.
Possibilities to contribute is depending on the NPC's class or race:
For simplification of the example, Biff will just give everyone good advice which I partly took from my NPC mods because I'm lazy. He's the Understudy, after all!
It is convenient to use the existent reply options for the 6 recruits. To account for EET compatibility we need to consider that all BG1+SoD string reference numbers in EET are higher by 200,000, meaning the sring reference #48085 in SoD will be #248085 in EET. Put this into the ALWAYS block of the tp2 so existing string reference numbers can be used for BG:SoD and EET in one go, by adding %2% in front of the string number.
Note: this works although the defined "2" is a string, not a number. There might be instances where this syntax will not work like it does here, e.g. for journal titles in ADD_JOURNAL in the tp2. Also, only adding a "2" only works for SoD strings that all have at least 5 digits. For smaller numbers from BG1 there would be additional zeros missing.
/* Define a variable to account for the differences in string ref numbers between BG:SoD and EET. - Works for string references in d- or baf-files. */ ACTION_IF GAME_IS ~bgee~ BEGIN OUTER_SPRINT ~2~ ~~ END ACTION_IF GAME_IS ~eet~ BEGIN OUTER_SPRINT ~2~ ~2~ END
This is what we will put into a d-file,n the tutorial mod package it is called sod_event_comments.d. For your own NPC mod just pick what you think would suit your NPC's character, experience, and prowess:
/* Training the Recruits in the Coalition Camp */ /* Clovis */ EXTEND_BOTTOM BDCLOVIS 3 + ~IfValidForPartyDialogue("xxBiff")~ + ~[PC reply]Biff, any advice?~ EXTERN xxBiffJ teach_clovis END CHAIN IF ~~ THEN xxBiffJ teach_clovis ~I see a mistake smaller men do when trained by taller ones. Fighting wears your arms out quite a bit, doesn't it?~ == BDCLOVIS #%2%48085 /* ~I do tire pretty quickly during drills. I thought I just needed more training.~ */ == xxBiffJ ~Focus on weak spots were you do not have to reach upwards. There are more than you might think. The foes will fear you for it - and you will wear out less quickly.~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_clovista_skill","global",2)~ EXTERN BDCLOVIS 5 /* Danine */ EXTEND_BOTTOM BDDANINE 3 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, you think you can teach this recruit to improve her skills?~ EXTERN xxBiffJ teach_danine END /* there will be a short fighting scene, then Biff talks again */ EXTEND_BOTTOM BDDANINE 4 IF ~IfValidForPartyDialogue("xxBiff")~ THEN DO ~SetGlobal("BD_DANINE_INTRO","BD3000",2) SetGlobal("xxBiff_BD_DANINE","BD3000",1) PlaySound("ACT_07") ReallyForceSpellRES("BDDANIN2",Myself) JumpToPoint([108.656]) FaceObject("BDCLOVIS") Wait(1) ReallyForceSpellRES("BDDANIN1",Myself) ApplyDamage("BDCLOVIS",1,1) SetSequence(SEQ_ATTACK) ActionOverride("BDCLOVIS",SetSequence(SEQ_DIE)) Wait(1) ActionOverride("BDCLOVIS",SetSequence(SEQ_AWAKE)) Wait(1) ActionOverride("xxBiff",StartDialogNoSet("bddanine")) ~ EXIT END APPEND xxBiffJ IF ~~ THEN teach_danine SAY ~I do. Try to be at places the foe doesn't expect you to be, be it yourself - or just your knife.~ IF ~~ THEN EXTERN ~BDDANINE~ 4 END /* final dialogue after Danine tried out the advice */ IF WEIGHT #-1 ~Global("xxBiff_BD_DANINE","BD3000",1)~ THEN teach_danine_01 SAY ~Yes, that's it.~ IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_danine_skill","global",2) SetGlobal("xxBiff_BD_DANINE","BD3000",2) ~ EXTERN ~BDDANINE~ 5 END END //APPEND /* Garrold */ EXTEND_BOTTOM BDGARROL 1 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, you seem like you want to say something?~ EXTERN xxBiffJ teach_garrold END CHAIN IF ~~ THEN xxBiffJ teach_garrold ~You definitely have potential. More than with what you do here. Would the battle mages take on new recruits as well?~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_garrold_skill","global",2)~ EXTERN BDGARROL 3 /* Hester */ /* Hester has two possible states for reply options */ EXTEND_BOTTOM BDHESTER 6 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, you think you can teach this recruit to improve his skills?~ EXTERN xxBiffJ teach_hester END EXTEND_BOTTOM BDHESTER 7 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, you think you can teach this recruit to improve his skills?~ EXTERN xxBiffJ teach_hester END CHAIN IF ~~ THEN xxBiffJ teach_hester ~You need to focus on *why* you are here. The only thing worth being afraid of is that your foe will overpower you - and not because of yourself, but because of your friends and the ones that depend on you!~ == BDHESTER #%2%48006 /* ~So by trying to avoid battle and all that comes with it, I'm missing out on my life now...?~ */ == xxBiffJ ~Exactly.~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_hester_skill","global",2) ~ EXTERN ~BDHESTER~ 10 /* Morlis */ /* #1 The first example is for the advice a fighter would give. If your NPC recognizes Morlis' joy in killing, the dialogue would go differently, see below. */ //--> take out from here if you want to use option #2 instead EXTEND_BOTTOM BDMORLIS 4 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, can you give some advice as a fighter?~ EXTERN xxBiffJ teach_morlis END CHAIN IF ~~ THEN xxBiffJ teach_morlis ~You are strong and do not shy away from being hit. You need to focus that strength on the foe. Try to be in the first row. It is where your skill will be useful the most, as you do not have to watch out not to hit allies.~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_morlis_skill","global",2)~ EXTERN BDMORLIS 8 // <-- take out until here if you want to use option #2 /* #2 Morlis, possibility to interact for an evil NPC */ /* - taken out - remove this line if you want tuse option #2 EXTEND_BOTTOM BDMORLIS 4 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, you look like you want to say something?~ EXTERN xxBiffJ teach_morlis_evil END CHAIN IF ~~ THEN xxBiffJ teach_morlis_evil ~(Imitating Dorn's voice) I sense something in you, soldier. A darkness that reminds me of my own. You like killing, don't you?~ == #%2%47935 /* ~I... yes. I do enjoy it. I thought if I said so, though, they wouldn't let me in the militia.~ */ == xxBiffJ ~Well, it seems we really need every man we get. Make sure you're in the front row, though.~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_morlis_skill","global",2)~ EXTERN BDMORLIS 6 */ //remove this line if you want to use option #2 /* Taield */ EXTEND_BOTTOM BDTAIELD 1 + ~IfValidForPartyDialogue("xxBiff")~ + ~Biff, can you give this private some advice?~ EXTERN xxBiffJ teach_taield END CHAIN IF ~~ THEN xxBiffJ teach_taield ~You seem to feel not full part of the group. I can sympathize with that... I'm always only seen as the second choice myself.~ == BDTAIELD #%2%48070 /* ~I admit I've felt somewhat alienated. It's hard to feel part of the team when I'm so obviously different.~ */ == xxBiffJ ~(Imitating Jaheira's voice) Everyone has a reason to feel alone. We each make our own paths and fight for our own causes. You must find the strength within to endure, as do we all.~ END IF ~~ THEN DO ~IncrementGlobal("BD_FIGHTERS_SKILL","BD3000",2) SetGlobal("bd_sdd301_taield_skill","global",2)~ EXTERN BDTAIELD 6
In the northwest of the Boareskyr Bridge area there is an old well. The easter egg is that putting the dusty chicken from the crusader's camp into it will lead to a dog appearing and all group NPCs giving some comment.
In the game, the dog barks after every two possible NPC interactions. If the NPCs are not present, it will bark anyway. To make sure it will not bark twice after the interjection we check for Jaheira or Khalid's presence as they would talk first after the interjection point: if they are not present the dog will not bark additionally but just give his normal line he would give anway.
Lines used by the dog are: Arf!, Yip!, Woof woof!, and Ruff!. Feel free to use a different exclamation than the example to increase variety.
This is what we will put into Biff's d-file. In the tutorial mod package it is called sod_event_comments.d:
/* The Chicken, the Well, and the Dog Easter Egg */ I_C_T3 BDDOGW01 0 C#BE_BDDOGW01_0 == xxBiffJ IF ~IfValidForPartyDialogue("xxBiff")~ THEN ~We washed the chicken in the well and the dog came to collect it. Never gets old!~ == BDDOGW01 IF ~IfValidForPartyDialogue("xxBiff") OR(2) IsValidForPartyDialogue("KHALID") IsValidForPartyDialogue("JAHEIRA")~ THEN ~Woof!~ END
I made this an extra How-To and will only give a link here: [How-To] Using EE's "Skipit" Functionality for Mod Cutscenes
The depth of what is required for your mod to be EET compatible depends strongly on what your mod will cover. If your NPC is also available in BG:EE, then the naming differences of most BG1 resources (those files that needed renaming because BGII has different files of the same name) require the use of OUTER_SPRINT variables as defined in the widely used cpmvars.tpas for e.g. area names, Imoen's scriptname, or some cre file names. The principle of this multi-platform coding is described in cmorgan's tutorial Crossing the Great Divide. k4thos made a list about different naming conventions here.
If looking "only" at SoD, there is the huge advantage that most resources didn't need to be renamed as SoD already uses unique file names and almost all resources are the same for SoD(BG:EE) and SoD(EET). One exception is Imoen's death variable: it is "IMOEN" in SoD and "IMOEN2" in EET. And of course using string reference numbers need to be toggled: the EET numbers are the BG:SoD ones plus 200,000. One example how to unify this is given in Chapter 25: Training the Recruits in the Coalition Camp.
Then the only question is whether the NPC will be available in BGII, too (and whether you realize this by a continuous NPC that has the same script variable (death name) in BGII, also), or whether the NPC should not be available if the player continuous into BGII after finishing SoD in EET.
EET offers a very comfortable function to provide your NPC mod with all needed script additions etc. for the transitions BG1 -> SoD, SoD -> SoA, and SoA -> ToB. The function is called EET_NPC_TRANSITION and there is a very detailed description how to use it and what it does in the according Modder Notes (It is well possible the link will not work because of the apostroph in it. Here is the address for copy&paste: https://cdn.rawgit.com/K4thos/EET/master/EET/docs/Modder's Notes.html.)
Biff is supposed to be an SoD NPC, so the mod would be category "1" (BG:EE/SoD NPC). The needed parameters for the function would be the following. Put this late into the tp2-file, at least after your NPC's script file compilation:
/* EET compatibility: Biff is an BG1 (SoD) NPC only. His name will be mentioned on EET's fate spirit in ToB, but he will not be summonable (like all NPCs that didn't join the group in BGII). */ ACTION_IF GAME_IS ~eet~ BEGIN INCLUDE ~EET/other/EET_functions.tph~ //this function will be in the player's own EET folder LAF ~EET_NPC_TRANSITION~ INT_VAR type = 1 //Biff is only available in BG:EE/SoD. Adapt this if needed; including the additional STR_VARs STR_VAR dv = "xxBiff" //Biff's scriptname (death variable) override_BG1 = "" /* OVERRIDE script in BG:EE. Put your NPC's BG:EE script here UNLESS you use the same script for BG:EE and SoD (adds a "destruct in Chapter greater than 7" scriptblock, for example if your NPC was spawned in BG:EE but was never in party (although "BeenInParty" is not being checked by this scriptblock)). If your NPC is SoD only like Biff, leave this open. */ override_SoD = "xxBiffs" //OVERRIDE script in SoD. This will add a "DestroySelf()" in Chapter greater than 13 to the SoD script. traFile = "%MOD_FOLDER%/tra/%LANGUAGE%/GAME-XXBIFF.tra" //path to the text line for the ToB Fate Spirit summoning string = "@0" /* ~Bring me Biff the Understudy.~ */ //from the above specified tra file stringPosDV = "Baeloth" //Name after which Biff's should be put into the order of reply options at the fate spirit summoning dialogue. /* From the "Modder's Notes for Baldur's Gate: Enhanced Edition Trilogy (EET)": //Aerie, Ajantis, Alora, Anomen, Baeloth, Branwen, Cernd, Coran, Corwin, Dorn, Dynaheir, Edwin, Eldoth, Faldorn, Garrick, //Glint, HaerDalis, Hexxat, Imoen2, Jaheira, Jan, Kagain, Keldorn, Khalid, Kivan, Korgan, MKhiin, Mazzy, Minsc, Montaron, //Nalia, Neera, Quayle, Rasaad, Safana, SharTeel, Skie, Tiax, Valygar, Viconia, Voghiln, Wilson, Xan, Xzar, Yeslick, Yoshimo //variable not set (default) = NPC name appended at the end of summoning list */ END END
For Biff being an SoD mod only, this is basically it. The transition from SoD to SoA in EET is done by K#TELBGT.bcs which lets all NPCs that are not multiplayer characters leave the party. The EET_NPC_TRANSITION will add a DestroySelf() to Biff's OVERRIDE script if the chapter (of the continuous EET chapter system) hits chapter 14. So, we do not need to add anything to make sure he will not be present in BGII.
"Road to Discovery" is a tweak mod for the SoD campaign (also with native EET compatibility). For players, it aims to make the coalition forces aware of Caelar's and Hephernaan's plans with focus on the actual important aim and danger of the crusade, and give reply options with which the PC can inform the coalition forces about what is going on. For this, all bits and pieces of information the PC can gather along the campaign are tracked and evaluated. Journal entries give an overview on what information the PC already gathered. For modders, "Road to Discovery" introduces a variable-based tracking system about the different levels of knowledge the PC and the coalition officers gain throughout the campaign, which could be used for own mods, e.g. for fine tuning mod NPCs reactions to the depths of gained information about Caelar, Hephernaan, and the crusade, but also the Hooded Man's appearances.
The mod is modular so every player as well as modder can chose how much changes and content they want to see/use. If only the second component of the mod is installed (the "main" component), only the variable tracking system will be installed - the player will see no difference while playing the game.
For your own NPC mod, feel invited to use the tracking system of "Road to Discovery" to fine-tune your NPC's reactions to game events. I developped it for exactly that purpose - my own NPC mods - and a lot of effort was put into the tracking system and the different stages of tracked PC's knowledge.
The following lists the information from the SoD campaign "Road to Discovery" is considering. For detailed description of the used variables and the exact definition of the tracked infomation see inside the mod packge:
Thank you to Argent77 for the html template!
Used Tools:
Links:
Prefix Reservation at Black Wyrm Lair Forums
[How-To] Using EE's "Skipit" Functionality for Mod Cutscenes
Tutorial: Crossing the Great Divide
EET Modder Notes (It is well possible the link will not work because of the apostroph in it. Here is the address for copy&paste: https://cdn.rawgit.com/K4thos/EET/master/EET/docs/Modder's Notes.html.)
Version 6:
Version 5:
Version 4:
Version 3:
Version 2:
Version 1: