This tutorial assumes a certain knowledge of the BGII syntax and IE-modding in general. It highlights some crucial differences between the engines of BG2 and BG1, especially with regards to the restrictions of the BG1 engine in comparison to that of BG2, but it also includes some available BG1 syntax that might not be readily apparent.
The focus of this tutorial is on the workarounds and simulations that emulate BG2 functionality.
Comments, corrections, and additions are welcome, especially if you can provide not yet listed workarounds for missing BGII functions, please feel free to post them here. I will update the tutorial accordingly.
Thank you to berelinde for language corrections!
BG1 - plain BG1, without the Tales of the Sword coast Add-on.
BG1:TotSC - BG1 with the add-on installed.
cre: creature file used in IE-modding
itm: item file used in IE-modding
The IESDP is always a good source, but for BG1 triggers and actions, it only reflects BG1:TotSC, and some of the used examples contain BGII only syntax.
BAMs: only decompressed. BGII BAMs are usually compressed. For BG1, they have to be decompressed, or the item will lead to a CTD. Decompressed BAMs work in BGII. Near Infinity can be used to decompress BAMs.
Further, description BAMs have to be quartered in BG1 into four frames. BGII description BAMs are unsplit, they have to be split if meant to be used in BG1. I used BAMWorkshop II (scroll down the page) to split the BGII BAMs. Note: Unsplit BAMs work as intended in BG1:TotSC. (Split BAMs work also fine in BGII.)
There is no overall script like "Baldur.BCS" in BG1. A replacement could be the dplayer3.bcs, which is the script of Player1. Some "monologues" are triggered via this script in the game.
cre and itm, if they are supposed to work in both BG1 and BGII engine (for Tutu or BGT): BG1 items and creature files without any special abilities, effects or weapon proficiencies will work for BGII, but not necessarily the other way around. Therefore, if you are planning a mod that should be compatible with all BG1 games, I suggest creating the files using BG1 resources.
For differences in special abilities, effects or weapon proficiencies, please have a look at Miloch's (aka Tervadh) tutorial Converting BG1 items to BG2: Weapon proficiencies need to be set (at 0x31), otherwise all items will get a Large Sword proficiency. All the kit usability flags need to be unset as relevant. Since BG1 did not have kits, it didn't matter whether they were set or not. I could imagine differences could be covered during installation via tp2-patching depending on the detected game, as described by Miloch, but I cannot provide examples for this yet.
No dialogues at rest
NPCs have no dream script. There is no "...D.bcs", meaning that the engine is not capable of directly triggering a dialogue before rest, i.e. if the player presses the "rest" button.
I know of no way of realising this for BG1.
For the Ajantis vanilla BG1 romance, I used the following workaround: upon entering a tavern, the NPC starts a dialogue in which the player can choose whether he wants to directly end and therefore postpone the dialogue, or whether he wants to play the dialogue that will be followed by a forced rest. The dialogue is triggered by a variable that got set in the script of the tavern area.
The dialogue would start like this:
IF WEIGHT #-2 ~Global("X#AjantisReadyForNT1","GLOBAL",3)~ THEN resttalk_1 SAY ~Is this where we will rest for today?~ ++ ~No, not yet.~ DO ~SetGlobal("X#AjantisReadyForNT1","GLOBAL",4)~ + resttalk_1_0a //-> ends the dialogue and resets the timer for the next tavern ++ ~Yes, we will rest immediately.~ DO ~SetGlobal("X#AjantisReadyForNT1","GLOBAL",4)~ + resttalk_1_0b //-> plays the dialogue, followed by a forced rest ENDIn the tavern script, the variable "X#AjantisReadyForNT1" was set to 1 beforehand, and in ajantis.bcs, the dialogue was triggered.
tp2-Patching of the tavern scripts looks like this (only the first levels of taverns were used, as the dialogue gets triggered after the entering of the tavern. Thanks to Zed Nocear for providing the list):
//Patching of the tavern scripts for "rest talk" EXTEND_BOTTOM ~AR1001.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0116.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0119.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0103.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0114.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0705.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0105.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR0133.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR2301.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR3304.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR3307.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR3351.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~ EXTEND_BOTTOM ~AR3357.BCS~ ~C#AjantisRomance_BG1/Scripts/C#Tavern_AD.BAF~
"Greeting sound": In BG1, it is not possible to "mute" a creature by assigning another blank sound reference (e.g. [C#BLANK]). Creatures say their assigned "greeting sound" nontheless. This results from a difference in processing of the sound reference between the engines, but I don't know how exactly. I haven't tried to assign a different sound file to a creature, so I don't know whether both sounds would be played if the creature is talked to, but considering Kulyok's experience for IWD I assume they'd do.
Coding interjections is a bit more complicated, since INTERJECT_COPY_TRANS (and presumably INTERJECT, as well) doesn't work as intended: The PC replies of the original dialogue state show during the interjection lines.
To simulate I_C_T, as it would appear using the BG2 engine, the following workaround has to be used ((thanks to Kulyok). Please refer also to the tutorial IWD engine: dialogue coding):
You need three files, that get compiled separately. The first one is a placeholder and is called PREFIX_DUMP.d. Make as much entries as you have interjections, for example:
BEGIN PREFIX_DUMP IF ~~ 0 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 1 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 2 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 3 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 4 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 5 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 6 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 7 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 8 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 9 SAY ~Temp~ IF ~~ THEN EXIT END IF ~~ 10 SAY ~Temp~ IF ~~ THEN EXIT END
The second file is called REPLACE.d. It is for saving the original, and adding an additional transition trigger to the original transitions of the state where the interjection should be added. The third file is the actual interjection, divided into an EXTEND_BOTTOM that adds the new interjection to the original state, and a CHAIN that allows the interjection flow like an I_C_T type of interjections. Important is to add a check variable, so the interjection only runs once. This variable can also be used as new transition trigger for the original transitions, so they show the next time once the interjection occurred since then check variable = 1.
The only drawback, and I guess there is no solution to that, is the missing OR() trigger in BG1. This makes it necessary to add a stupid extra-line to the original state, in case the NPC isn't able to speak his interjection line. A way to avoid this is to use less triggers for the interjection, e.g. only "InParty("npc")" instead of the triple "InParty("npc") See("npc") !StateCheck("npc",CD_STATENOTVALID)", but I wouldn't advise to.
Example. Ajantis meets Raleo Windspear in Beregost, and greets him as the brother of Lord Garren Windspear. So we have (please note that "C#" is my personal prefix):
BEGIN PREFIX_DUMP IF ~~ 0 SAY ~TEMP~ IF ~~ THEN EXIT END
REPLACE PREFIX_DUMP IF ~~ THEN 0 SAY ~TEMP~ COPY_TRANS Raleo 0 END END ADD_TRANS_TRIGGER Raleo 0 ~Global("C#AjantisBG1RALEO0","GLOBAL",1)~ //original transitions fire if the interjection run
EXTEND_BOTTOM RALEO 0 IF ~Global("C#AjantisBG1RALEO0","GLOBAL",0)~ EXTERN RALEO Ajantis_Windspear_interjection IF ~InParty("ajantis") Detect("ajantis") !StateCheck("ajantis",CD_STATE_NOTVALID) Global("C#AjantisBG1RALEO0","GLOBAL",0)~ EXTERN AJANTJ Ajantis_Windspear_interjection END CHAIN AJANTJ Ajantis_Windspear_interjection ~Sir Raleo Windspear! I am delighted to see (blabla).~ DO ~SetGlobal("C#AjantisBG1RALEO0","GLOBAL",1)~ == RALEO ~Ah, the youngest Ilvastarr's offspring. (bla).~ == RALEO ~Indeed. That will be another while, though. But now I am sure your friend has some questions about this town, hm?~ END COPY_TRANS PREFIX_DUMP 0 CHAIN RALEO Ajantis_Windspear_interjection ~Don't be shy and ask away.~ //stupid passback line if Ajantis didn't come to say his bit END COPY_TRANS PREFIX_DUMP 0
All that's missing is the lines in the tp2, to compile the files separately:
COMPILE ~Mod/Dialogue/PREFIX_DUMP.d~ COMPILE ~Mod/Dialogue/REPLACE.d~ COMPILE ~Mod/Dialogue/INTERJECTION.d~
Items with charges: there exists no "recharges after rest" behaviour. This behaviour could be simulated by replacing the old item with a fresh one after rest, using Zed Nocear's PartyRested() trigger simulation, but for BG1, it's only limited charges or always usable.
Add mod NPC to BG1 Joinable NPCs have to be listed in the baldur.gam. In BGII every NPC that is not listed in Baldur.gam will be added automatically as soon as he joins the group, hence in BGII, the baldur.gam doesn't have to be altered by a mod. The BG1-Engine does not add NPCs automatically to the baldur.gam, but the mod has to alter the baldur.gam to make the mod NPC fully available in the game. If not, the game will crash the first time the NPC tries to travel fom one area to another.
WeiDU offers ADD_GAM_NPC (please refer to the WeiDU-readme), but with ADD_GAM_NPC all BALDUR.GAM files in SAVE and MPSAVE get altered, which is... cruel. EDIT: It seems that this leads to scew-ups if a mod that adds NPCs via ADD_GAM_NPC gets installed twice, as it can happen easily during a complex install, plus a proper deinstallation doesn't seem to be possible: ADD_GAM_NPC and uninstallation, non-functionality of.
Zed Nocear suggests the following possibility to add a custom joinable NPC to the game via the tp2:
COPY_EXISTING ~baldur.gam~ ~override~ INSERT_BYTES 0xB4 0x160 WRITE_LONG 0x140 0xFFFFFFFF WRITE_LONG 0x144 0xFFFFFFFF WRITE_LONG 0x168 0xFFFFFFFF WRITE_SHORT 0x16C 0xFFFF READ_LONG 0x34 npc_count WRITE_LONG 0x34 ("%npc_count%" + 1) READ_LONG 0x20 party_offset WRITE_LONG 0x20 ("%party_offset%" + 0x160) WRITE_LONG 0x28 ("%party_offset%" + 0x160) WRITE_LONG 0x50 ("%party_offset%" + 0x930) WRITE_ASCII 0xC0 ~MYNPC~ // name of file MYNPC.CRE (without extension) WRITE_ASCII 0xCC ~AR2600~ // area that you want NPC placed in WRITE_SHORT 0xD4 123 // x co-ordinate on the map WRITE_SHORT 0xD6 456 // y co-ordinate on the map WRITE_LONG 0xC8 7 // face orientation
This solution has one disadvantage: A new game has to be started for the NPC to be present in the game.
The advantages are:
- only the main file Baldur.GAM gets changed, SAVEs don't get touched.
- the NPC-CRE-changes as defined by NPCLEVEL.2DA get applied, depending on the level of the PC (this would also be true for ADD_GAM_NPC).
- "face orientation" can be used.
- ADD_GAM_NPC carries the flag "do not use this".
Post-dialogue of joinable NPCs
In BG1, the engine does not switch automatically from the joined dialogue "...J.dlg" to the post dialogue "...P.dlg" upon kickout. The kickout dialogue state is contained in the joined dialogue. Upon kickout, the post-dialogue has to be set via ~SetDialog("mynpcP")~. Upon joining, the dialogue is triggered via the post dialogue and the dialogue file is changed to the joined dialogue like in BGII.
An example: Ajantis' kickout dialogue is in his AJANTJ.dlg:
IF ~True() ~ THEN BEGIN 1 // from: SAY #16623 /* ~Aber ... aber ... wir waren doch ein Team und durch Ehre verbunden! Seufz... Warum ist bloÃŸ alles immer so kompliziert? ~ */ IF ~~ THEN DO ~LeaveParty() SetDialog("AjantP") ~ EXIT END
This means in addition, that no "Kickout" variable is needed in BG1.
Further tutorials connected to NPC creation: Extended list of BG1 character sound offset names, BG1 TotSC by Baronius, linking to the BG1 CREATURE SOUND SLOTS by Baronius
Player initiated dialogue In BGII, player initiated dialogue (PID for short) can be realized by selection of the "dialogue" button, and klicking on the NPC. In BG1, chosing the "dialogue" icon will not work if applied to party members. To realize PIDs in BG1, I therefore chose the hotkey to enable the dialogue. The hotkey will only be executed, if the NPC in question is selected. Please note: If more than one NPC is selected, all could react to the hotkey. If all of them have PIDs that are coded like this, they would fire their dialogue one after the other.
I used the hotkey "k", and (instead of having the last dialogue state triggered with ~True()~ to be the PID like in BGII) I used a variable that will be set, and reset to "0" by the script. Further, the script block activated by the hotkey will lead to the NPC approaching to the PC, and only if he sees her. This was to make up for the missing "IsGabber()", to make sure it is the NPC and the PC talking.
So, to enable the hotkey, a script block has to be added to the NPC's script. The second block is for setting the variable back to zero, this will happen after the flirt menu was opened. (Theoretically, this variable could be set to zero in the dialog file after the flirt. But I didn't feel like adding closing variables for x++ flirts, and forgetting some in the end, so I went for the easier solution.):
// Player-initiated dialogue IF InParty(Myself) HotKey(K) Detect(Player1) !StateCheck(Myself,CD_STATE_NOTVALID) !StateCheck(Player1,CD_STATE_NOTVALID) THEN RESPONSE #100 SetGlobal("C#AjantisPCIniFlirtTime","GLOBAL",1) Dialogue(Player1) END IF Global("C#AjantisPCIniFlirtTime","GLOBAL",1) THEN RESPONSE #100 SetGlobal("C#AjantisPCIniFlirtTime","GLOBAL",0) ENDAnd in the dialogue file, the PID dialogue state trigger would look like this:
IF WEIGHT #-2 ~Global("C#AjantisPCIniFlirtTime","GLOBAL",1) Global("X#AjantisRomanceMatch","GLOBAL",1) Global("X#AjantisRomanceActive","GLOBAL",1) !Detect([ENEMY])~ THEN BEGIN ajantisflirts_begin_01 SAY @0 ...
Portraits The used format notation is "S" for the small and "L" for the medium sized portraits. Large, like they are used in BGII for the ToB epilogue, are not used in BG1.
No real time timers
RealGlobalTimerExpired() and RealSetGlobalTimer() do not exist: there is no real time timer. Only the global game time timer (GlobalTimerExpired() - SetGlobalTimer()) exists. Possible time frames are ONE_DAY, TWO_DAYS etc.
If using numbers, like "150", experiences vary. Some say, it leads to unstable results. Zed Nocear reported the following:
From GTIMES.IDS, a game day takes 7200 seconds. The timer counts in real seconds, if the game is set to 30 frames per second. This would mean, that "150" is two minutes real time, or half an hour game time.
Variables: Original BG1 uses mostly global variables. BG1:TotSC uses two AREA-type variables. Still, all three variable types exist ("GLOBAL", "LOCALS", "AREA"), but with some difference in how they function compared to BGII (by Zed Nocear):
GLOBAL-variables function the way they do in BGII.
LOCALS-variables work like in BGII, but they are not saved in the savegames. This means, that after every start or loading of the game the local variables are reset to zero. They are like temporary help variables. This might be of advantage, as they do not accumulate in the SAVEs.
Further, there seems to exist an upper boundary as to how much local variables can be used, although I don't know whether for the whole game or per creature. Trying to set 80 LOCAL variables via dplayer3.bcs has led to a CTD.
AREA-variables work, but they are globally available like GLOBAL variables. "MYAREA" is not available in BG1, so for AREA-variables, the area name has to be specified, which makes the variable available in other areas, too.
For testing, the NPCs of the party were placed in different inside areas. If a variable "Global("VariableName","AR0701",1)" was set of one creature in AR0701, it could be read by the script of an NPC in area AR0702.
Therefore, AREA-variables seem to be useless and can be replaced by global variables.
Setting of variables in dialogues and scripts - how fast are the new values available? (by Zed Nocear) If a variable gets set in a dialogue or a script, how long does it take until it is available? It will lead to errors, if a variable is called before the engine actually got to setting the new value.
1. Script (this behaviour is equal to BGII, as far as I know, but I will list it nonetheless): A script gets executed from top to bottom, until a block with valid trigger is found. This block gets executed, and the script execution starts from the top again. If the script block was about setting a new variable value, the new value will be available after the new script call.
An exception to the restart of the script appears if Continue() is used at the end of the script block. In this case, the following script block will be executed directly, but all variables will still have the old value. The new values, again, will only be available after the restart of the script.
2. dialogue: Experience has shown, that for variables set with SetGlobal(), the new value was available in the following dialogue state. For IncrementGlobal(), it takes two dialogue states, though.
Alignment triggers: MASK_GOOD, MASK_EVIL and MASK_NEUTRAL do not seem to work for BG1 at all. Further, the single "alignmen.ids" identifiers ("LAWFUL_GOOD","CHAOTIC_NEUTRAL", etc.) if used like this don't seem to work, either. For checking the alignment of a creature, the (correct) numbers have to be used:
Thus, to check for a CHAOTIC_GOOD PC, the trigger would be "Alignment(Player1,49)".
AreaCheck() does not exist. Have a look at Zed Nocear's Trigger-Simulations for BG1 for a neat workaround for this.
AreaType() does not exist. Have a look at Zed Nocear's Trigger-Simulations for BG1 for a neat workaround for this.
Class check: class.ids does not contain the _ALL identifiers ("MAGE_ALL" etc.) known from BGII. For BG1, only the plain class identifiers are available (for example "MAGE").
CombatCounter(0) does not exist. Have a look at Zed Nocear's Trigger-Simulations for BG1 for a possible workaround.
IsGabber(O:Object*) does not exist.
Level(), including LevelGT() and LevelLT() do not exist. "CheckStatLT(Myself,10,LEVEL)" might work, but I have no experience with this. As avenger_RR noted: "Note however, that LEVEL, LEVEL2 and LEVEL3 are different values and are used for multi and dual-classed characters".
OR() does not exist.
To minimize the amount of necessary script blocks for a large amount of "OR()" triggers, there are workarounds possible. See tutorial of Vlasak for coding helps concerning OR() and AND(): AND and OR in scripting, How to simulate them in various IE games
From my experience, I want to add: Always keep in mind, that scripts and dialogue files are executed from top to bottom. Take the following example, two dialogue blocks from Ajantis' player initiated dialogues. According to the alignments of the party members, different dialogues should be triggered:
//Original dialogue blocks as used in Tutu/BGT IF //first block: no party member is of evil alignment ~Global("C#AjantisPCIniFlirtTime","GLOBAL",1) Global("X#AjantisRomanceMatch","GLOBAL",1) Global("X#AjantisRomanceActive","GLOBAL",1) !Detect([ENEMY]) !TimeOfDay(Night) !Alignment(Player1,MASK_EVIL) !Alignment(Player2,MASK_EVIL) !Alignment(Player3,MASK_EVIL) !Alignment(Player4,MASK_EVIL) !Alignment(Player5,MASK_EVIL) !Alignment(Player6,MASK_EVIL) GlobalLT("X#AjantisRomanceBadDecision","GLOBAL",5)~ THEN BEGIN ajantisflirts_begin_01 SAY ~...~ IF //second block: at least one NPC is of evil alignment ~Global("C#AjantisPCIniFlirtTime","GLOBAL",1) Global("X#AjantisRomanceMatch","GLOBAL",1) Global("X#AjantisRomanceActive","GLOBAL",1) !Detect([ENEMY]) !TimeOfDay(Night) !Alignment(Player1,MASK_EVIL) OR(5) Alignment(Player2,MASK_EVIL) Alignment(Player3,MASK_EVIL) Alignment(Player4,MASK_EVIL) Alignment(Player5,MASK_EVIL) Alignment(Player6,MASK_EVIL) GlobalLT("X#AjantisRomanceBadDecision","GLOBAL",5)~ THEN BEGIN ajantisflirts_begin_02 SAY ~...~
First the MASK_EVIL has to be replaced as described above. Then, Instead of replacing the OR() in the second dialogue block in the example with a lot of new blocks, putting it last as unconditioned is equal to the wanted trigger condition, since the dialogue file will be executed from top to bottom, therefore the second block only will be triggered if the conditions of the first aren't met.
//Adapted dialogue blocks for BG1: IF //first block: no party member is of evil alignment, BG1 syntax ~Global("C#AjantisPCIniFlirtTime","GLOBAL",1) Global("X#AjantisRomanceMatch","GLOBAL",1) Global("X#AjantisRomanceActive","GLOBAL",1) !Detect([ENEMY]) !TimeOfDay(Night) !Alignment(Player1,19) !Alignment(Player1,35) !Alignment(Player1,51) !Alignment(Player2,19) !Alignment(Player2,35) !Alignment(Player2,51) !Alignment(Player3,19) !Alignment(Player3,35) !Alignment(Player3,51) !Alignment(Player4,19) !Alignment(Player4,35) !Alignment(Player4,51) !Alignment(Player5,19) !Alignment(Player5,35) !Alignment(Player5,51) !Alignment(Player6,19) !Alignment(Player6,35) !Alignment(Player6,51) GlobalLT("X#AjantisRomanceBadDecision","GLOBAL",5)~ THEN BEGIN ajantisflirts_begin_01 SAY ~...~ //second block, only triggers if one group member except player1 is of evil alignment IF WEIGHT #-2 ~Global("C#AjantisPCIniFlirtTime","GLOBAL",1) Global("X#AjantisRomanceMatch","GLOBAL",1) Global("X#AjantisRomanceActive","GLOBAL",1) !Detect([ENEMY]) !TimeOfDay(Night) !Alignment(Player1,19) !Alignment(Player1,35) !Alignment(Player1,51) GlobalLT("X#AjantisRomanceBadDecision","GLOBAL",5)~ THEN BEGIN ajantisflirts_begin_02 SAY ~...~
PartyRested() does not exist. To trigger a dialogue directly after rest, have a look at Zed Nocear's Trigger-Simulations for BG1 for a neat workaround for this.
XP(), including XPGT() and XPLT() do not exist. For checking the amount of XP an NPC has, a check of the form "CheckStatLT(Myself,161000,XP)" can be used instead.
Here, some difference between BG1 and BG1:TotSC have to be considered. They are pointed out accordingly.
ApplySpellRES() works for both BG1 and BG1:TotSC (by Zed Nocear).
The Action.ids has to be patched accordingly:
APPEND ~action.ids~ ~160 ApplySpellRES(S:ResRef*,O:Target*)~
CreateCreature() For BG1:TotSC, the syntax for CrateCreature() is the same as in BGII: "CreateCreature("name",[x.y],0)", with "0" being the face orientation of the creature.
For BG1 without TotSC, there is no face orientation: "CreateCreature("name",[x.y])" is the correct syntax here.
To code for both in one file, the method described by cmorgan's "Crossing the Great Divide" tutorial using OUTER_SPRINT has to be used (see here for more details: crossing the great divide: Coding for BG1, Tutu and BGT).
CreateCreatureObjectOffScreen() does not exist. This action is used in BGII to create creatures outside the visual range of the group, but in BG1, this action is not available.
CreateItem() doesn't work for containers: The item lands on the ground in front of the container.
Normally, creating an item in a container would be done via area script, for example:
Unfortunately, this does not work for BG1: the item is not created inside the container, but in front on the ground.
CreateVisualEffectObject() does not exist.
EraseJournalEntry() is not available/ does not exist. To cross-code for Tutu/BGT and BG1, and make the EraseJournalEntry() available to the Tutu/BGT versions, see here for more details: crossing the great divide: Coding for BG1, Tutu and BGTl.
EscapeAreaMove(S:Area*,I:X*,I:Y*,I:Face*) does not exist. A very simple work around for unjoinable NPCs would be, to destroy the creature at one place and recreate it at another, using for example
~MoveToPoint(), Destroyself()~ and then ~CreateCreature()~ at the new location (remember that possible local variables of the first encounter are lost then, like "NumTimesTalkedTo").
Zed Nocear suggests the following for BG1:TotSC: ~RunAwayFrom(LastTalkedToBy,60) LeaveAreaLUA("AR4801","",[284.454],0)~
I don't know whether LeaveAreaLUA() would work in BG1 (without TotSC), though.
FaceObject() does not exist.
If you know where the two characters that should face each other are standing (either they were created or moved to another area with known coordinates) "Face()" could be used to let them turn.
If you don't know where the chracters are going to be, devSin proposed a possible workaround which I haven't checked yet, though: "You could always do something (...) like have your NPC ReallyForceSpell(Player1,FAKE_SPELL_DOES_NOTHING) Wait(1) StartDialog("DLG",Player1). Spellcasting should have the character zip around to face the target (you have to create the fake spell, though)."
FindTraps() does not work. Instead, it seems to disables the "find trap" modus, if it was chosen by the player by clicking on the game icon. If used in scripts, the thief would be unable to use the "find traps" modus as it gets repeatedly disabled. (by Zed Nocear)
GivePartyGoldGlobal(S:Name*,S:Area*) does not work as intended. IESDP: "Will give the party a sum of gold corresponding to the given global variable. The gold amount is deducted from the actor running the script." In BG1, the amount specified by the value of the global variable will be ignored, and all gold of the creature running the script will be transferred. (by Zed Nocear)
only JOURNAL. There exists no "SOLVED_JOURNAL" or "UNSOLVED_JOURNAL" as known from the BGII engine (To cross-code for Tutu/BGT and BG1, see here for more details: crossing the great divide: Coding for BG1, Tutu and BGT)
Journal entries as actions: AddJournalEntry(~text~). For BGII engine, the syntax is AddJournalEntry(~text~,QUEST_DONE) for solved journal, and AddJournalEntry(~text~,QUEST) for unsolved quests. (To cross-code for Tutu/BGT and BG1, see here for more details: crossing the great divide: Coding for BG1, Tutu and BGT)
107 MoveToOffset(P:Offset*) does not work in BG1 and BG1:TotSC. If used, nothing will happen.
RestParty() does not exist.
I use the following Workaround:
1a. In a tavern, for BG1:TotSC:
A cutscene is used, that blackens the screen for a moment (there is no "rest at inn" movie in BG1, so in this case blackening the screen would be sufficient):
ClearAllActions() StartCutSceneMode() CutSceneId(Player1) FadeToColor([20.0],0) Wait(5) Rest() ActionOverride(Player2,Rest()) ActionOverride(Player3,Rest()) ActionOverride(Player4,Rest()) ActionOverride(Player5,Rest()) ActionOverride(Player6,Rest()) Wait(10) FadeFromColor([20.0],0) Wait(1) EndCutSceneMode()1b. In a tavern, BG1 without TotSC: For BG1 without TotSC, FadeToColor() is not available. I helped myself by triggering the "resting outdoor" movie also for an inside rest. See 2. for the cutscene.
2. For resting outdoor, the "resting outdoor" movie can be triggered (BG1 with or without TotSC):
ClearAllActions() StartCutSceneMode() CutSceneId(Player1) Rest() ActionOverride(Player2,Rest()) ActionOverride(Player3,Rest()) ActionOverride(Player4,Rest()) ActionOverride(Player5,Rest()) ActionOverride(Player6,Rest()) StartMovie("REST") Wait(1) EndCutSceneMode()
SetPlayerSound() does not exist. I don't know any workaround, so this means that there is no possibility to provide a "fix-it" script to restore the creature's sounds in BG1.
StartDialogNoSet() does not exist. Dialogue() has to be used instead.
TakePartyItemNum(S:ResRef*,I:Num*) should both be used with care: Stackable items in the inventory are treated as one and all are items of the stack are removed. (by Zed Nocear)
4. Spell Effects
#122 (0x7a) Item: Create Inventory Item  does not work as in BGII: It will always only create one item, and only, if timing mode is set to "Delay/Permanent (4)" and number of items is set to "0". (by Zed Nocear)
Not all BGII Tokens are available.
I repost the list from the IESDP for BG1:TotSC here:
<CHARNAME> Returns the name of the PC.
<DAY> Returns the current numerical day.
<DAYANDMONTH> Returns the current numerical day as well as the month. (Example: It is <DAYANDMONTH>, would produce: It is 24 Mirtul...or whatever the current day and month happens to be.)
<DURATION> Returns the elapsed time from the start of the game in days and hours. (Example: We've been around for <DURATION>, would produce: We've been around for 23 days and 13 hours...or whatever the elapsed time happens to be.)
<DURATIONNOAND> Returns the same thing as <DURATION> except it omits the and. So it would be 23 days 13 hours rather than 23 days and 13 hours.
<GABBER> Returns the name of the current speaker. (Example: If I use Jaheira and click-talk her on a creature rather than using the PC, this would return Jaheira if used in a dialogue.)
<GAMEDAY> Returns the current game day. (Starts at 1 for a new game.)
<GAMEDAYS> Returns the number of game days that have elapsed since the start of the game. (Starts at 0 for a new game.)
<HOUR> Returns the current hour of the day in numerical 24 hour format.
<MINUTE> Returns the current number of real-time minutes (0-59) that have passed in the last hour.
<MONTHNAME> Returns the current month's name. (Example: It is <MONTHNAME>, would produce: It is Mirtul...or whatever the current month is in your game.)
<YEAR> Returns the current year in numerical format. (Example: It is <YEAR> currently, would produce: It is 1369 currently...or whatever year it is in your game.
I am not sure whether all tokens will work for BG1 without TotSC, but the tokens <LADYLORD> and <PRO_LADYLORD> definitely do not work for BG1 but return empty spaces.
Edited by jastey, 19 June 2008 - 10:41 AM.