The "Baldur’s Gate Script Compiler," this document, and any information contained herein, are provided in an "as is" state. No support will be provided for either the use of the compiler or for any script files generated by the compiler. Neither BioWare Corp. or Interplay Productions are responsible for any problems encountered in running the compiler or in creating scripts.
BALDUR'S GATE: Developed and (c)1998 BioWare Corp. All Rights Reserved. Baldur's Gate, Forgotten Realms, the Forgotten Realms logo, Advanced Dungeons & Dragons, the AD&D logo, and the TSR logo are trademarks of TSR, Inc., a subsidiary of Wizards of the Coast, Inc., and are used by Interplay under license. All Rights Reserved. BioWare, the BioWare logo and The BioWare Infinity Engine are the trademarks of Bioware Corp. All Rights Reserved. Interplay, the Interplay logo, Black Isle Studios, the Black Isle Studios logo, and "By Gamers. For Gamers." are trademarks of Interplay Productions. All Rights Reserved. Exclusively licensed and distributed by Interplay Productions. LUA copyright 1994-1998 TeCGraf, PUC-Rio. LUA written by Waldermar Celes, Robert Ierusalimschy and Luiz Henrique de Figueirido. All other trademarks and copyrights are property of their respective owners. All rights reserved. Using the Script Compiler: Before using the script compiler, you must copy the entire ScriptCompiler directory from Baldur’s Gate CD1 to your hard drive. You will be unable to run the script compiler directly from the CD. Once the ScriptCompiler directory has been copied, follow the instructions in the following sections. Creating Scripts: Initial Planning: Decide what you want the script to do before actually starting one. For example, "When attacked by an XX I want my character to react according to the range of my attacker. If I am within a range of 4 search squares I will run to get some distance between us. If I am further than 4 search squares I will attack with a ranged weapon." Preparation: After you have decided what you want the script to do open notepad or whatever else you would like to use and begin entering in the commands you will need. For mine I will need to use the commands, AttackedBy, Range, RunAwayFrom, EquipRanged and Attack. Coding: This is how my script would look: IF AttackedBy([ANYONE],DEFAULT) Range(LastAttackerOf(Myself),4) THEN RESPONSE #100 RunAwayFrom(LastAttackerOf(Myself),45) END IF !Range(LastAttackerOf(Myself),4) THEN RESPONSE #100 EquipRanged() Attack(LastAttackerOf(Myself)) END In the first part of the script I check to see if I was attacked by [ANYONE]. The object type parameter uses any function that returns an object type or objects referenced by ENEMYALLY, RACE, CLASS, etc. Examples of these are: [ANYONE], [ENEMY], [PC], etc. The object type can also be Myself. But in this case it would be useless since you would not attack yourself. Once I have determined if someone attacked me I check to see if the Range was within 4 search squares. (The screen is about 30 search squares). If the last attack of myself is within range I run away from the target for about 3 seconds. The time is given in 15ths of a second. If the range of the target is not within 4 search squares the script falls through to the next set of checks. In this next set I just check to see if the target’s range is not (using the ! to reference not) within 4 search squares. If so then I equip my ranged weapon and attack the last attacker of myself. If I do not have a ranged weapon or ammo the function will equip a melee weapon and then approach the target to get within weapons range. Compiling: Once the script is done I save it to the Source directory of the script compiler. The filename must be 1 – 8 characters with the extension .BAF. I then run the compiler by typing COMPILE <FILENAME>. The compiler will notify you of any errors in the script by placing a error file in the ERRORS directory with the script’s filename and extension .ERR. If the file size is 0 then the script compiled successfully. And the final script will be placed in the COMPILED directory with the filename and extension .BS. This will then have to be copied into your SCRIPTS directory of Baldur’s Gate. Definitions: Creature: Creatures include all objects capable of action. This includes player characters. Trigger: A trigger is sent to a creature when a certain event occurs. A trigger includes the knowledge of the cause of the trigger Condition: A combination of triggers joined with ands. Action: A specified response to a condition. An action requires the knowledge of who (or what) to perform the action upon. Response: A combination of actions which will be performed sequentially. It is possible for a response to be interrupted. Response Set: A combination of Responses, each with a weighting from 1 to 100. This weighting is used to randomly determine which response is actually executed. Creature and Object Identification Creature and Object Identification is done through the ObjectType Class. ObjectType is arranged as follows BYTE EnemyAlly General BYTE General| BYTE Race| BYTE Class| BYTE specifics V LONG Instance Specific BYTE SpecialCase EnemyAlly is a range between the PC and the evil NPC’s Creatures can fall anywhere along this range. General specifies the generic characteristics of the creature (Humanoid, animal, object etc.…) Race is the race of the creature (Elf, Dwarf …) Class is the class information (Mage, fighter …) Alternatively it can be used for more detailed information (e.g. Drow is more specific then elf) Specifics holds the identification for special NPC’s Instance is unique for each creature within the game. It should not generally be specifies in the AI scripting but will be set by the AI code once a target is selected SpecialCase is used to specify whether or not to use any special case information. Currently this will only be used for LAttacked and LTargetted. Protecting, Protector and Myself must be stored in a different way so that you can do things like Protecting.Lattacked. To specify all of a subtype, set the more specific variables to 0. e.g. To specify all Enemy Dwarfs, set Class, specifics and instance to 0. Some Special Object Identification Functions The following functions return ObjectType variables corresponding to some special cases. They are called using the following syntax: Function(Source) For Example: LAttacked(Spud) will return the ObjectType of the last thing to attack Spud. If One of Leader, Weakest, Strongest, MDamaged, LDamaged is called, the Source will be used ONLY to determine which group to use. For Example: Leader(Spud) will return the leader of Spud’s Group These functions can be used as the Source for any other of these functions. HOWEVER, this nesting can only go 5 deep. For Example: Protector(LAttacked(LTargeted(Protecting(Myself)))) is valid and will return the protector of the person last attacked by the person last targeted by the person protecting myself. Any more then this depth of nesting is NOT allowed, however. Note: If you ever use this level of nesting, please seek professional help. "NAME" -Returns ObjectType with the instance field filled out if the object currently exists. LastAttackerOf(ObjectType Caller) -Returns ObjectType - The Creature that last did Caller damage LastCommandedBy(ObjectType Caller) -Returns ObjectType -Returns the last person who issued Caller an order LastHeardBy(ObjectType Type) -Returns ObjectType -last heard by type LastHelp(ObjectType Type) -Returns ObjectType -Last person type heard call for help LastHitter(ObjectType Type) -Returns ObjectType -Last person who hit type LastSeenBy(ObjectType Type) -Returns ObjectType -Last seen by type LastTalkedToBy(ObjectType Type) -Returns ObjectType -Last talked to by type LastTargetedBy(ObjectType Caller) -Returns ObjectType - The Creature that Caller last targeted for attack LastTrigger(ObjectType Type) -Returns ObjectType -Last triggerer of type LeaderOf() -Returns ObjectType -Current leader of Player group LeastDamagedOf() -Returns ObjectType - Group member with highest percentage of remaining hit points MostDamagedOf() -Returns ObjectType - Use Source to specify Enemy / Ally status of group - Group member with the lowest percentage of remaining hit points Myself -Returns ObjectType -Yourself -Me Nearest(ObjectType Type) -Returns ObjectType -Returns the instance of the nearest ObjectType of the given Type. NearestEnemyOf(ObjectType Caller) -Returns ObjectType -Returns the nearest creature with Enemy / Ally flag opposite to the Caller. Player1 -Returns ObjectType -Character in portrait slot 1 Player2 -Returns ObjectType -Character in portrait slot 2 Player3 -Returns ObjectType -Character in portrait slot 3 Player4 -Returns ObjectType -Character in portrait slot 4 Player5 -Returns ObjectType -Character in portrait slot 5 Player6 -Returns ObjectType -Character in portrait slot 6 Protagonist - The Protagonist ProtectedBy(ObjectType Caller) - Returns ObjectType - The Creature currently protected by Caller ProtectorOf(ObjectType Caller) - Returns ObjectType - The Creature Caller is currently being protected by StrongestOf() -Returns ObjectType - Group member with the highest threat rating StrongestOfMale - Returns ObjectType - Male group member with the highest threat rating WeakestOf() -Returns ObjectType - Group member with lowest threat rating Trigger Descriptions Event Triggers Event Triggers only last until the next AI cycle. At that point they are examined and processed. At the end of the AI cycle all of the triggers are removed from the pending list. AttackedBy(ObjectType X, Style Y) Returns: Boolean (True or False) Description: I was just attacked by creature X using style Y. Information required: Attack type: DEFAULT MELEE RANGED X is an ObjectType variable. Die() Returns: Boolean (True of False) Description: I have just died Died(Object: X) Returns: Boolean (True or False) Description: X just died in my hearing range. Heard(Object:X, Integer: Y) Returns: Boolean (True or False) Description: I heard X shout Y Help(ObjectType X) Returns: Boolean (True or False) Description: a call for help is heard from X Information required: X is an ObjectType HitBy(ObjectType X, Style Y) Returns: Boolean (True or False) Description: I have just been hit by X the style is Y HotKey(HotKey X) Returns: Boolean(True or False) Description: key X has just been pressed when I was the selected creature Currently hotkeys are restricted to letters A through Z. ReceivedOrder(ObjectType X, OrderID Y) Returns: Boolean (True or False) Description: Just received order Y from X Information Required: X specifies the creature that sent the order. OrderID specifies type of the order. Said(Object:X) Returns: Boolean (True or False) Description: X said something to me Trigger(Integer TriggerId) Returns: Boolean (True or False) Description: I have just been sent the trigger TriggerId Status Triggers Status triggers are checked every time through the AI cycle. As a result they always apply if they are true. ActionListIsEmpty() Returns: Boolean (True or False) Description: I have no actions on my queue Class(ObjectType X,CLASS) Returns: Boolean (True or False) Description: Is the Class of X equal to CLASS? Information Needed: X is an ObjectType CLASS is the class MAGE FIGHTER CLERIC THIEF BARD PALADIN FIGHTER_MAGE FIGHTER_CLERIC FIGHTER_THIEF FIGHTER_MAGE_THIEF ANKHEG BASILISK BASILISK_GREATER BEAR_BLACK BEAR_BROWN BEAR_CAVE BEAR_POLAR CARRIONCRAWLER DOG_WILD DOG_WAR DOPPLEGANGER DOPPLEGANGER_GREATER DRIZZT ELMINSTER ETTERCAP GHOUL GHOUL_REVEANT GHOUL_GHAST GIBBERLING GNOLL HOBGOBLIN KOBOLD KOBOLD_TASLOI KOBOLD_XVART OGRE OGRE_MAGE OGRE_HALFOGRE OGRE_OGRILLON SAREVOK FAIRY_SIRINE FAIRY_DRYAD FAIRY_NEREID FAIRY_NYMPH SKELETON SKELETON_WARRIOR SKELETON_BANEGUARD SPIDER_GIANT SPIDER_HUGE SPIDER_PHASE SPIDER_SWORD SPIDER_WRAITH VOLO WOLF WOLF_WORG WOLF_DIRE WOLF_WINTER WOLF_VAMPIRIC WOLF_DREAD WYVERN OLIVE_SLIME MUSTARD_JELLY OCRE_JELLY GREY_OOZE GREEN_SLIME NO_CLASS Delay(Integer: X) Returns: Boolean (True or False) Description: returns False except every X seconds Use: Use to avoid excessive calling of slow triggers Exists(ObjectType X) Returns: Boolean (True or False) Description: Is X a valid ObjectType? Information Needed: X is an ObjectType variable. False() Description: Always return FALSE Gender(ObjectType X,GENDER) Returns: Boolean (True or False) Description: Is the X’s gender equal to GENDER? General(ObjectType X,GENERAL) Returns: Boolean (True or False) Description: Is the General type of X equal to GENERAL? Information Needed: X is an ObjectType GENERAL is the general type. HUMANOID ANIMAL DEAD UNDEAD GIANTHUMANOID FROZEN MONSTER HasWeaponEquiped(O:Object*) Description: Does the Object have a weapon equiped? HaveAnySpells() Returns: Boolean (True or False) Description: Do I have any Spells? HaveSpell(Integer X) Returns: Boolean (True or False) Description: Do I have spell X HP(ObjectType X, Y) Returns: Boolean (True or False) Description: X’s current hit points are EXACTLY Y Information needed: the value of Y (as a percentage). X is an ObjectType. Development Notes: the specificID flag can be used to store the percentage HPGT(ObjectType X, Y) Returns: Boolean (True or False) Description: X’s current hit points are GREATER THEN Y Information needed: the value of Y (as a percentage) . X is an ObjectType. Development Notes: the specificID flag can be used to store the percentage HPLT(ObjectType X, Y) Returns: Boolean (True or False) Description: X’s current hit points are LESS THEN Y Information needed: the value of Y (as a percentage) . X is an ObjectType. Development Notes: the specificID flag can be used to store the percentage HPPercent(ObjectType X, Integer: Y) HPPercentGT(ObjectType X, Integer: Y) HPPercentLT(ObjectType X, Integer: Y) Returns: Boolean (True or False) Description: Is the HP percent of X equal to Y? InParty(ObjectType X) Returns: Boolean (True or False) Description: Is X in the Party InWeaponRange(O:Object*) Description: Is object in Weapon range? LOS(ObjectType X, RANGE) Returns: Boolean (True or False) Description: Is Object X within RANGE search map blocks? Also, is there a clear line of sight to X? Information Needed: X is an ObjectType variable. RANGE is an integer count of intervening blocks. NotStateCheck(ObjectType X, Integer:Y) Returns: Boolean (True or False) Description: Is X in state Y NumCreature(ObjectType X, Integer: Y) NumCreatureGT(ObjectType X, Integer: Y) NumCreatureLT(ObjectType X, Integer: Y) Returns: Boolean (True or False) Description: Is the number of X’s visible Equal to Y NumTimesInteracted(Integer:NPC, Integer num) NumTimesInteractedGT(Integer:NPC, Integer num) NumTimesInteractedLT(Integer:NPC, Integer num) Returns: Boolean (True or False) Description: Have I interacted with NPC num times? OutOfAmmo() Returns: Boolean (True or False) Description: Is my current weapon out of ammo. Melee always returns false. Race(ObjectType X,RACE) Returns: Boolean (True or False) Description: Is the Race of X equal to RACE? Information Needed: X is an ObjectType RACE is the race to be compared to. Development Notes: Simply compare X.m_type.Race to RACE. HUMAN ELF HALF_ELF DWARF HALFLING ANKHEG BASILISK BEAR CARRIONCRAWLER DOG DOPPLEGANGER ETTERCAP GHOUL GIBBERLING GNOLL HOBGOBLIN KOBOLD OGRE SKELETON SPIDER WOLF WYVERN SLIME FAIRY NO_RACE RandomNum(Integer: Range, Integer: Value) RandomNumGT(Integer: Range, Integer: Value) RandomNumLT(Integer: Range, Integer: Value) Returns: Boolean (True or False) Description: Generate a number from 0 to Range and check against Value. Range(ObjectType X, RANGE) Returns: Boolean (True or False) Description: Is Object X within RANGE search map blocks? Information Needed: X is an ObjectType variable. Development Notes: Pure distance, no line of sight. Use SpecificID for Range. See(ObjectType X) Returns: Boolean (True or False) Description: Object X is in visual range Information Needed: Several options for specifying X