Skip to content

I am making a new set of custom party AI scripts.

taltamirtaltamir Member Posts: 288
Hello people.
The original party AI scripts in BG2 are utter [sunshine]. This is mostly not due to engine limitations, but the fact that:
1. It appears that none of the scripts were playtested, resulting in a bunch of horrific flaws in each and every script
2. Most of the scripts only give the characters 1-3 actions. We are talking about an AI being thrown together by one programmer in literally under 5 minutes.

My design philosophy:
1. AI should never override player commands
2. Player should never have to turn off AI to perform a task.
3. AI should never do something stupid, if an act is smart 90% of the time and stupid 10% of the time, then it shall perform a check to exclude acting on those 10%, if it can't perform such a check then it will not perform the task automatically and leave it up to the player to perform.

My design method:
1. Create an "idle append" script which gets appended to literally every script out there. This automates tedious out of combat abilities that should always be used when available. This would be very useful for multiclassing, but even if you single class you can just choose "melee" script and know that it will automatically handle your rangers/druid/thief/etc out of combat obligations
2. Rebuild the non spellcasting combat scripts from scratch to not suck so bad. (naturally they will each get the above mentioned append)

Use of any limited combat resource (items & most spells), will generally be left to the player (with a few exceptions) rather than handled via script.
Also, actual playtesting means I will resolve a variety of issues, example issues I seek to solve (currently solved by my latest verison scripts):
1. Combat scripts often override player commands, this is especially bad because if you order a spell cast, it will override it MID CAST and result in the spell being disrupted and wasted.
2. Ranged scripts make the character run away to 30' distance, this prevents them from functioning properly in tight quarters (eg 99% of the combat) as they get caught running around like headless chicken for the majority if not all of combat.
3. Ranged characters will close in to exactly max distance from enemy before attacking... blocking the path and even preventing other ranged characters from attacking the same enemy, if a ranged character needs to walk towards an enemy I will try to add a delay (so the meleers can go FIRST) followed by closing in to 5' less than max distance (so multiple ranged characters can pile up at the edge and attack the same enemy without blocking each other).
4. Party members switching from attacking actual enemies to attacking a confused party member (eg, jeheira has been hit with confusion, she hits minsc, misnc switches his target from an enemy to jeheira and slaughters her. dumb dumb minsc).

Interestingly, I encountered an engine bug in BG2 with my generic append (and the default thief3 script)... apparently ANY class can use the hide in shadow ability to turn invisible even if they don't have that ability and aren't thieves. So my mages and clerics are now all hiding in shadow (eventually they succeed on the check). I am not sure what to do about it yet. (maybe a separate copy of the scripts without this ability to use on non thieves?)
This apparently can cause you to miss quests (ex: the limited wish quest, Vittorio only initiates dialog with visible characters)

Download:
melee v10.7z (647 B)
https://mega.co.nz/#!iEVgEazJ!LnMjclCkcBCIquxEntBUhVBQy6QqPnvl5OHFV73muCE

melee v10 source.7z (3 KB)
https://mega.co.nz/#!CZVCGRjB!De6fLlPqAgtX1yN-zl5GNhHAOh1c73aACnz5Yvr5VME

How to install:
Extract the .bs files from the 7z file into your scripts directory. which is a subfolder in your install directory of either BGEE or BG2. Note that you do not actually need the source files unless you want to modify the script yourself.
The script files go directly into the scripts folder without any subfolders.
Example: "C:\Games\BGEE\Scripts\melee_02.bs"

NOTE: These scripts were designed for BG2 and have not been tested in BGEE yet. As far as I can tell BGEE does not come with the AI script sources and compiler (which is included in the GOG version), as such I have no way to compare the syntax of the script sources in BGEE. And no guarantee that any scripts I make in BG2 will work with BGEE or BG2EE when it is released. BGEE scripts do seem to have been significantly improved compared to the original BG2 scripts.

For script description and notes see next post.
Post edited by taltamir on

Comments

  • taltamirtaltamir Member Posts: 288
    edited October 2013
    Description of latest version scripts:
    melee v10 said:

    I call it "melee" because it is missing all the EXTRA functions I intend to add to the ranged scripts. However as it is it is already far superior ranged attack script than any of the default ranged attack scripts, because those are all AWFUL! At the moment I am using this on every single party member.
    A character with this script will use the current weapon (no automatic switching) to attack the nearest enemy. If the current weapon is melee they WILL close the distance to them (unlike some default scripts where the melee char just waits for enemy to come to them). They will NEVER override the current command. So no more lost spells, and if you tell them to kill the mage they won't leave him until he is actually dead (or turns invisible).
    Also, unlike bioware scripts they do NOT switch target whenever struck. This solves both the problem of attacking party members, as well letting go of the enemy mage just because a tank managed to hit you
    This script also includes everything in the latest Idle_Append

    History:
    v10 - updated to Idle Append v9
    v9 - updated to Idle Append v8
    v8 - updated to Idle Append v7
    v7 - Attack function switched target every 30 seconds to nearest enemy. Will now not switch target as long as you can.
    v6 - updated to Idle Append v6
    v5 - updated to Idle Append v5
    v4 - updated to Idle Append v4
    v3 - updated to Idle Append v3
    v2 - updated to Idle Append v2
    v1 - initial version.

    Note: Engine limitation prevents scripts from having over 8 characters in their name.
    Note: Giving scripts an in game description requires editing of the tlk table, modifying the tlk table mid game WILL corrupt all your saves. As such these scripts have no in game description, making them perfectly safe to insert to the game at any time. You can literally alt-tab out of the game and add them while the game is running (but if you do that, you need to save and then reload to initialize the script)

    Idle_Append performs the following functions in order, while idle & no enemies are in sight, for any AI script which includes it:
    01. Cast Slow Poison on the closest visible PC if that PC is poisoned. But only if they are not invisible and you are not poisoned too
    02. Cast Neutralize Poison on the closest visible PC if that PC is poisoned. But only if they are not invisible and you are not poisoned too.
    03. If you have Slow Poison or Neutralize Poisoned prepared, and a PC is poisoned (checked in order from 1 to 6), and that PC is not invisible, walk up to them (to trigger the 2 functions above).
    04. Cast CLW on self if HP @ 80% or lower, unless wearing an item that gives noticable regenereation
    05. Cast CLW on most injured party member if HP @ 80% or lower; unless they are invisible or wearing an item that gives noticable regenereation
    06. Cast CMW on self if HP @ 70% or lower, unless wearing an item that gives noticable regenereation
    07. Cast CLW on most injured party member if HP @ 70% or lower; unless they are invisible or wearing an item that gives noticable regenereation
    08. Consume a Goodberry if HP @ 100% or lower, wearing an item that gives noticable regenereation
    09. Give Goodberry to PC1 through PC6 if they don't have one, they don't have substantial regeneration, & their HP < 100%. Giving new berries is nearly instant. Due to engine limitation it will give 1 stack (up to 10 berries) if source is inventory, but 1 at a time if source is container.
    10. Cast Goodberry spell when it is ready
    11. Activate Detect traps if not active already

    *Equipment giving substantial regeneration currently accounted for: RING39 (Ring of Gaxx, +1HP/3sec), RING31 (Ring os Regeneration, +1HP/6sec), AX1H14 (Axe of the Unyielding +3, +1HP/round), AX1H15 (Axe of the Unyielding +5, +3HP/round)
    The following are not tested for as they are too slow to matter: Pearly White Ioun Stone (+1HP/30s)

    History:
    v9 - Fixed a bug with curing self. CLW self, CMW self, and eat goodberry functions were checking if the most injuried party member had regneration, not self.
    v8 - Give goodberry script was bad, it would only give a berry to the most injured PC. Meaning other PCs had to wait a long time to get one. It has been replaced with 6 seperate functions, one per PC, which will give a berry to any PC that needs one.
    v7 - Give Goodberry to most injured ally if they don't have one, they don't have substantial regeneration, & their HP < 100%. There is no time delay before giving new berries. Due to engine limitation it will give 1 stack (up to 10 berries) if source is inventory, but 1 at a time if source is container.
    v6 - Added Axe of the Unyielding +3, Axe of the Unyielding +5 as a regen source to be considered. Goodberries now check if HP is less than 100% rather than 99%.
    v5 - Reordered the checks on CLW and CMW functions to make them slightly more CPU efficient (probably useless). Also those functions will now exclude characters who have a ring of regeneration or a ring of gaxx equipped to prevent wasting the cure spells on a character that doesn't need it.
    v4 - Added poison curing. This one was quite a pain to do, also amusingly the default cleric scrips REFUSE to cure poison out of combat, they will only work if an enemy is visible. Naturally my script doesn't do that. I was worried it would trigger when an ally is "poisoned" by stinking cloud (0 damage, knocks prone), but it does not seem to do so in testing.
    v3 - The cure ally code (which I lifted from original bioware script) had a bug which caused them to spam you with fail messages if the target was under improved invisiblity, as they only checked to see if the target is invisible. This has been fixed.
    v2 - Added Goodberry
    v1 - initial release

    Post edited by taltamir on
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    Now, what I need from the public here is some ideas on things that I have missed.
    My current append is: CLW, CMW, hide in shadows, and detect traps.
    I intend to (try to) add to it
    1. slow poison
    2. goodberries
    3. cloak of stars daily ability to create free items
    4. thief HLA to create a random potion daily (alchemy i believe its called).
    5. Cure critical wounds
    Post edited by taltamir on
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    Older scripts:
    melee v1.1 pack.7z (385 B)
    https://mega.co.nz/#!acUHhSYR!VlZZLS07VZnpnYd0qfK-XQxEO6pTgc66tbu33vMG1SI
    melee_01 said:

    I call it "melee" because it is missing all the EXTRA functions I intend to add to the ranged scripts. However as it is it is already far superior ranged attack script than any of the default ranged attack scripts, because those are all AWFUL! I literally use this on every single party member.
    A character with this script will use the current weapon (no automatic switching) to attack the nearest enemy. If the current weapon is melee they WILL close the distance to them (unlike some scripts where the melee char just stands forlornly and waits for enemy to come to them). They will never override the current command. So no more lost spells, and if you tell them to kill the mage they won't leave him until he is actually dead (or turns invisible). This script includes Idle_Append_v1

    mel_h_01 said:

    Same as melee_01. except this uses Idle_Append_v1_hide instead. Adding automatic hide in shadows attempt, beware (see issue below)

    Note: Engine limitation prevents scripts from having over 8 characters in their name, this is why some of the names are so weird looking

    Idle_Append_v1 performs the following functions, in order, while idle, for any script which includes it:
    1. Cast CLW on self
    2. Cast CMW on self
    3. Cast CLW on ally
    4. Cast CMW on ally
    5. Activate Detect traps if not active already

    Casting CLW only occurs if HP is less than 95%, I would have picked 99% but I don't want wasting as MULTIPLE clerics will be casting it on the same character simultaneously
    Casting CMW only occurs if HP is less than 90%

    Idle_Append_v1_hide is the same as Idle_Append_v1 but adds automatic usage of the "Hide in Shadows" skill
    Due to an engine bug, AI initiated hide in shadows attempts causes ALL characters to successfully turn invisible, even those that don't have the ability. This causes issues such as missing dialog (for example Vittorio in limited wish quest will not initiate conversation with you if you are invisible when you walk past him)
    Post edited by taltamir on
  • DurenasDurenas Member Posts: 508
    edited September 2013
    I recommend you not add slow poison unless you want all your poison spells to fail every time the cleric tries to cast the spell on themselves. The PC bhaalspawn ability is fine, since it's instant cast.
  • taltamirtaltamir Member Posts: 288
    Amberion said:

    I recommend you not add slow poison unless you want all your poison spells to fail every time the cleric tries to cast the spell on themselves. The PC bhaalspawn ability is fine, since it's instant cast.

    1. I have had the bhaalspawn slow poison on self fail before due to being disrupted.
    2. You are absolutely right, good point. It didn't even occur to me. Luckily, the "cast on self" and "cast on ally" are, due to an engine limitation, 2 separate checks and commands. As such I will make them cast it only on allies and never on self.

    Biggest engine limitation there is lack of coordination so multiple healers will cast it simultaneously on the same character. :(
  • KhyronKhyron Member Posts: 635
    What we really need are Ranged scripts that:
    1. Don't run into melee range to fire a bow
    2. Don't run away to a distance and thus need micromanagement to bring into view/attack distance for other mobs - Running away before firing just makes for more work, as you have to send them back in to fight mobs now out of sight/range when original target dies.
    3. Target priority - Attack those who attack your cleric or mage, or attack any hostile mage on sight.

    Intelligent healer script:
    1. Cast appropriate tier healing spell based on number of HP target is missing. Casting CLW on a tank with 30 out of 110hp left just wastes time.

    Intelligent caster scripts:
    1. Cast spells like pierce magic if target has stoneskin etc, instead of a fireball.
    2. Ability to choose an AoE or single target script. Setting off a fireball outside the copper coronet is such a party pooper. Without this, scripting mages is hazardous at best.
    Should be possible to make a pool of spells each script will select from when casting via script.
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    @Khyron: you are totally right :), and that is my intent to create. At the moment though I am having problem with target priority (I need to figure out the right syntax, as it currently stands it corrupts the script).

    About using higher level heal spells, please note the idle append is explicitly out of combat idle activity taken by the AI. It takes only a short time for the party to be fully healed with CLW cast by the AI when idling (especially if you have multiple healers); it is EXTREMELY tedious for a human to cast 20 CLW (5 from each priest), but not at all tedious for the AI to do so. I tested it out and it works beautifully.
    If you make it use up higher level spells out of combat it wastes those spells which might be needed in an emergency (aka, in combat)

    Now, when I eventually get into overhauling the COMBAT casting scripts then yes, you should definitely use higher level healing spells first in combat if appropriate. Sadly, the engine is designed to check for HP percentage instead of HP damage count. HP starts at single digit and ends at triple digits, while CLW heals about the same amount from level 1 through 50. So this makes using healing spells intelligently very painful.
  • sarevok57sarevok57 Member Posts: 6,002
    @taltamir could you make different healing scripts for different HP characters, ex; low level characters use cure light wounds when at 90% health script, medium level characters use cure moderate wounds at 90 % health, high level characters use cure critical wounds at 90% health/ and or high level characters get the spell heal cast on them once their health hits 50%, could you make a separate healing script for each one of those? so then the healing spells could scale with the higher HP that characters will get < being that fighter types have way more HP than mage types for example, but usually its the fighter types that are getting injured the most>
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    @sarevok57: Having multiple scripts for various HP brackets is a really good idea!

    But it will be some time until I get to this aspect of script making. The current automated healing I implemented (and plan on implementing) are all out of combat stuff, for which you want the AI to use the most efficient, least combat relevant, most carpal tunnel inducing spells first (so you don't have to).

    Speaking of combat spellcasting, the biggest technical hurdle is that in order to have characters perform any combat healing I need to create interrupts where the AI takes over and cancels the current command (fight/casting a spell/etc) to perform a task (go and heal), this would cause problems with the AI wrestling the player for control of a character and result in turning off the AI for manual control. My scripts are designed to be always on, to supplement a player rather than wrestling him for command. (for example, most default AI scripts will always disrupt any spell you manually order it to cast; wasting the spell)

    I think it makes more sense for the AI to focus on the melee, ranged, etc. If a healing spell is needed you manually issue such an order. And the AI is carefully designed to NOT disrupt such an order once given.

    Please do correct me if you see a flaw in my reasoning for something. Even if I don't agree with you, if you do not accept my counter arguments and still wish something to be done differently, and it is within my means to do so, then I will provide such modified script
    Post edited by taltamir on
  • sarevok57sarevok57 Member Posts: 6,002
    can you put scripts together? for example; say you make the ultimate melee fighting scrips < presumably a hybrid of "standard attack" which to me is already pretty good, except for the fact you mentioned about attacking party members because they are confused and switched their targets> and then mix it with say the cleric healing script? so say you mixed those two together, and that makes it so normally the cleric will attack offensively but when someone gets damage, they go heal, and then go back to attacking, is that something that can be done? would that make things easier if you just put scripts together, or does that just make a huge mess in the end?
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    I can indeed combine scripts,but there is no automatic way of doing it. It is extremely easy to just copy paste 2 scripts together, the problem is that the more complex the script it, is the more likely it is to have an incompatibility that has to be identified and then manually resolved

    For example, my first ever attempt was combining thief3 and theif4 into a single script which took me about 2 minutes, most of which was learning the engine (it was my first attempt after all). In that particular example the only potential issue was that I had to append thief3 to the end of theif4, as doing it the other way around would cause problems (hiding disrupts detect traps, but detect traps does not dirsupt hiding; so they need to be done in order). I noticed that at a glance (since theif3 was a mere single command and theif4 a mere 2 commands) and did it right the first time.

    Caster scripts are fairly complex, in fact they are the ONLY complex scripts. The developers wrote the AI assuming you are going to fully automate casting while micromanaging the melee and ranged attacks. Which is moronic, you want automatic melee/ranged attacks with you micromanaging spells.

    Also, as far as I can tell there is no default cleric healing script. There is "offensive casting", "defensive casting", both, and summoner. With automatic healing sprinkled between those 4 scripts as deemed appropriate by the developers.

    I could probably rip out the healing from your favorite cleric script and add it to my improved melee script. That will be later though, I got a bunch of things to do first
  • KidCarnivalKidCarnival Member Posts: 3,747
    Something that bothers me big time, and maybe you can solve that somehow:

    Cleric/Thief --> Thief button, arguably the most used, is in the Ability tab --> just move it somewhere, ANYWHERE, else for easier access
    Mage/Cleric --> stuffs all spells in one of the Moon icons, leaving the second Moon icon unused --> seperate button for arcane and divine

    Any chance that could be added?
  • taltamirtaltamir Member Posts: 288

    Something that bothers me big time, and maybe you can solve that somehow:

    Cleric/Thief --> Thief button, arguably the most used, is in the Ability tab --> just move it somewhere, ANYWHERE, else for easier access
    Mage/Cleric --> stuffs all spells in one of the Moon icons, leaving the second Moon icon unused --> seperate button for arcane and divine

    Any chance that could be added?

    As far as I know this is all hardcoded stuff, more than that, it has been hardcoded in a way that it cannot be changed easily even with source code access according to beamdog. However the currently in development huge BGEE patch supposedly will rebuild the UI engine in such a way as to allow beamdog to make future modifications to it. I have no idea whether this will open it up for modding by the community though
  • starskystarsky Member Posts: 44
    ALWAYS wanted this, when it's done be sure to let us know.

    Hell even if it only works 10% of the time it would still be better
  • taltamirtaltamir Member Posts: 288
    I noticed more issues with hide in shadows, for now I am just not going to use it until I can resolve them.
  • taltamirtaltamir Member Posts: 288
    Uploaded v02 of melee script, now with goodberries.
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    I confirmed the hide in shadows bug occur in BGEE as well. Only not as bad.
    In BG2 you will automatically succeed every attempt. In BGEE you need a nat20 to succeed (I am guessing from the fact I average 20 failures before succeeding), but once you succeed your mage is now invisible thanks to hide in shadow skill he does not posses.
    Post edited by taltamir on
  • DurenasDurenas Member Posts: 508
    I found that while wearing heavy armor, Jahiera and Minsc would always fail their HiS attempts. Yoshimo would mostly succeed and my main, a Cleric/Mage wearing heavy armor, would rarely succeed.

    It also spams the HiS really really fast. Faster than the UI would normally allow you to make attempts.
  • DurenasDurenas Member Posts: 508
    edited September 2013
    Is there any way to add checks to not have the AI autotarget other neutral targets when you force attack a neutral target? I was messing around in the shadow thieves' lair, force killing the thief with the ring of lock picks, and the AI wanted to attack the shadow thief that ambushes him after he was dead.
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    new version released.
    melee_04.7z (2 KB)
    https://mega.co.nz/#!jBkgCAza!NB63tG9ugEmeigwaXHWAOldfQ7gWjklEnossMENjkQU

    v4 - Added poison curing. This one was quite a pain to do, also amusingly the default cleric scrips REFUSE to cure poison out of combat, they will only work if an enemy is visible. Naturally my script doesn't do that. I was worried it would trigger when an ally is "poisoned" by stinking cloud (0 damage, knocks prone), but it does not seem to do so in testing.
    v3 - The cure ally code (which I lifted from original bioware script) had a bug which caused them to spam you with fail messages if the target was under improved invisiblity, as they only checked to see if the target is invisible. This has been fixed.
    Amberion said:

    Is there any way to add checks to not have the AI autotarget other neutral targets when you force attack a neutral target? I was messing around in the shadow thieves' lair, force killing the thief with the ring of lock picks, and the AI wanted to attack the shadow thief that ambushes him after he was dead.

    I am not sure... maybe they are marked hostile after you attacked the first one and that is why the AI is attacking them?
    Then again, I remember having to disable AI to prevent it from attacking additional golems unnecessarily in some places. So maybe its a hardcoded function (or the same thing happened as above ... this bears testing)
    Post edited by taltamir on
  • DurenasDurenas Member Posts: 508
    They both had a blue ring around them. At no point did they ever turn hostile(red). I was able to back off from the shadow thief before I actually did any damage.
  • taltamirtaltamir Member Posts: 288
    edited September 2013
    I wish I knew... sounds like some hardcoded issue.

    The AI scripts actually give me very limited access, I am not programming, I am scripting. I get to call functions like "hide()" or "AttackReevaluate(,)" and so on. But I have no control of the functions themselves. It is quite possible that "AttackReevaluate(,)" or has the character automatically switch target to nearest creature of same faction once the target is dead, without performing an "is enemy" test.

    I can fix SOME things though, for example the issue with retaliating against an ally was actually done by a script. Which read something like "if hit, abort current action, attack the person who hit you". I could have solved this by adding a check to see if the thing that hit you was a PC, but I chose to remove it outright because it is bad even if it is an enemy (ex, you order AI to attack an enemy mage. A meatshield hits your PC, he now lets the mage go to fight the meatshield... dumb!)

    EDIT:
    Which AI script were you using? I just found out there is a function called:
    "GroupAttack(Object)
    This command is used to attack an Object until dead and then pick another Object of the same type."
    It is possible the AI script you used had this. My AI script does not use this function so it theory it should not do this.
    Post edited by taltamir on
Sign In or Register to comment.