Skip to content

Advanced AI doesn't work properly for Exported characters...(Thank you Bubb and kjeron for the fix!)

islandkingislandking Member Posts: 426
v2.3, heavily modded, there was no problem when beating BG1 final boss and got transferred to SOD, but when I exported my f/m/t to Black Pits, Advanced AI can no longer autocast any spells. Other functions like attack, trap detection etc work fine though.
I also tried SOD>BG2, BG1>BG2 exports, same problem, any ideas?
Thanks!
Post edited by islandking on

Comments

  • CrevsDaakCrevsDaak Member Posts: 7,155
    edited April 2017
    The data about how the script should behave isn't stored on the character itself. Simple as that. Or if it is, it's getting ripped away by beginning a new game.

    Edit: typo.
  • sarevok57sarevok57 Member Posts: 5,975
    yeah that was starting to annoy me to, even if you set everyone's script to none and rescript them it still doesn't work, although if you start a new BG2 game ( with characters not from BG1) then it works fine, and even more bizarre if you had characters that started in bg1 then transferred over to bg2 and then into ToB the scripts start working again, complete bananas

    so for that reason I made my own scripts which work through out the whole series where they work regardless of game im playing
  • islandkingislandking Member Posts: 426
    Hi @CrevsDaak, I looked through the "scripts" folder, the only possible Adv AI file is "0dw#gen.bs", but I suspect it's SCS's ease-to-use AI file, also judging by how Adv AI keeps its own settings after export, I think it's fairly possible that it's stored in character instead, so is there any way to edit .chr file to make to work?
  • islandkingislandking Member Posts: 426
    @sarevok57
    Looks like I'm not the only one, for a moment I thought it was caused by mods.
    Really don't want to create anew in BG2, losing original exportable plus SoD items that way...
    My character is a f/m/t, can I use your scripts?
  • sarevok57sarevok57 Member Posts: 5,975
    indeed you can, that's why I made a whole pile of them haha, I have a discussion on this forum somewhere that has a whole bunch lets see if I can find it...

    https://forums.beamdog.com/discussion/63928/improved-scripts-for-your-bg-bg2-playing-experience#latest
  • islandkingislandking Member Posts: 426
    Thanks @sarevok57, I'll play test it and give you some feedback :)
  • sarevok57sarevok57 Member Posts: 5,975

    Thanks @sarevok57, I'll play test it and give you some feedback :)

    sounds good

  • CrevsDaakCrevsDaak Member Posts: 7,155

    the only possible Adv AI file is "0dw#gen.bs", but I suspect it's SCS's ease-to-use AI file

    Yup, sounds like it.

    also judging by how Adv AI keeps its own settings after export, I think it's fairly possible that it's stored in character instead, so is there any way to edit .chr file to make to work?

    Export just writes the data from your character into a .chr, it doesn't change the data. Also, if it was stored into the .chr, I think it's stripped at the start of a new game (because they're probably stored as local variables, which are all deleted by default to avoid any type of other problems).
  • sarevok57sarevok57 Member Posts: 5,975
    Bubb said:

    Hi @islandking. It sounds like you are all set up with sarevok57's scripts, but I went poking around in Near Infinity anyway.

    The Advanced AI script is BDDEFAI, and the problem is caused by a timer called BD_CAST. I don't fully understand how timers work, but it seems exporting to a new game resets the game's current tick. It looks as if the timer stores an absolute tick in the LOCALS of the creature, not a relative one. Thus, when you export a character, the timer is now set to a very large, very far in the future time.

    Run this console command several times, changing Player1 to Player2, Player3, etc. to fix every character in the party. Your characters should immediately start casting spells again!

    C:Eval('ActionOverride(Player1,SetGlobalTimer("BD_CAST","LOCALS",0))')
    EDIT: Fixed malformed command.

    PS: This is my first post, so sorry for any mistakes!

    perhaps that is the reason why it seemed to work again when my team mates hit ToB

  • islandkingislandking Member Posts: 426
    @CrevsDaak
    That sounds like an oversight, I’ll file an issue report on support.baldursgate site.
  • islandkingislandking Member Posts: 426
    Hi @Bubb welcome to the community :-)

    I’m always open to suggestions. And your method works! RPG perspective: my poor f/m/t must’ve got shockingly confused when transported to the arena at first, but now she finally realized she’s the mighty spellcasting Bhaalspawn and begin to rain terror upon the entire black pits :-D

    Anyways, back to topic, I was actually using EEkeeper to do the job, and while I was checking my post-SoD imported f/m/t’s local variables, besides the “BD_CAST” you mentioned, there’re other large numbers as well, listed as follows:
    BD_CAST 46616237
    BD_GLITTER 46429627
    BD_DUEL_BARK_TIMER 46253345
    BD_BLIND 1552821
    BD_SLOW 46616185
    BD_HORROR 45913796
    I also do a quick-check on other savefiles, it seems that these “BD_” variables only appear after the first time Advanced AI casts the according spells, like Glitter Dust, Slow, Horror…etc listed above, some spells won’t be listed, but any ability or spell will trigger “BD_CAST” to appear. After that, the values will increase in number as you spend time playing. This behavior explains why a fleshly-made, or never-autocast-a-spell-before character is barely affected after the import.
    In my case, not only do I have to reset “BD_CAST”, but also other large number values as well so that she can cast Glitter Dust, Slow and Horror again, hope it helps other players who encounter the same issue.

    Thanks Bubb!
  • islandkingislandking Member Posts: 426
    edited April 2017
    @sarevok57
    By the time I almost finish Baldur’s Gate, my pre-sod savefile values are like this:
    BD_CAST 35124047
    BD_GLITTER 35123961
    BD_BLIND 1552821 (still the same number? hmm this one is strange…maybe I shouldn’t reset this value…)
    BD_SLOW 35123909
    BD_HORROR 35028147
    Post edited by islandking on
  • islandkingislandking Member Posts: 426
    @Bubb
    If you don't mind, I'll use your found value names in Spoiler tag for the issue report.
  • BubbBubb Member Posts: 1,000

    @ sarevok57
    By the time I almost finish Baldur’s Gate, my pre-sod savefile values are like this:
    BD_CAST 35124047
    BD_GLITTER 35123961
    BD_BLIND 1552821 (still the same number? hmm this one is strange…maybe I shouldn’t reset this value…)
    BD_SLOW 35123909
    BD_HORROR 35028147

    @islandking
    Thanks for the welcome :)

    I'm not sarevok, but I think I can chime in here.

    Anyway, these timer values do indeed update whenever the Advanced AI casts the corresponding spell. It's completely fine to set all of these timers to 0; they will update themselves the next time they are used. The lower number on the blind timer simply means the character hasn't auto-cast blindness in a while.

    Also, using the timer names is completely fine. :-)
  • islandkingislandking Member Posts: 426
    edited April 2017
    @Bubb
    hmm I still don't get it, if the number only increases with Advanced AI uses of spells and in an imported new game Adv AI won't use spells, then how can sarevok57's tob saves exceed those numbers?
  • BubbBubb Member Posts: 1,000
    @islandking
    I am a little confused by the question, but I think I might have the idea. You're asking how sarevok57's trigger values are greater than yours, when his should be halted just as yours are? I'll try to detail the process the script takes in using these triggers:

    Let's take the example of the BD_Cast trigger. Whenever the script checks if it can cast a spell / use a potion, it checks this trigger:
    !GlobalTimerNotExpired("BD_Cast","LOCALS")
    Paraphrased, this line is asking "Is this trigger expired? If it is, cast the spell / use the item."

    It's important to understand how triggers work to understand the problem, so here is the gist: When a trigger is set to ONE_ROUND (or any value, for the matter), the game stores the absolute tick number that corresponds with the expiration of the trigger in the LOCALS of the character.

    I don't know the exact tick value of ONE_ROUND, but let's pretend it takes 100 ticks to wait one round. If the current tick is 1000, the game would store the value 1100 in the LOCALS of the character. When the game checks if the trigger is expired, it checks the current game tick against this stored expiration local. So, if the current game tick is greater than or equal to 1100, the BD_Cast trigger will be expired, and the script will continue as normal.

    This stored "ending" value is the key of the problem. Whenever you start a new game (aka exporting), the game resets the current game tick to 0. But wait.. the expiration tick of 1100 is still stored in our LOCALS, isn't it? The script still thinks it has to wait for tick 1100 to cast a spell. The script will now wait 11! rounds after exporting to cast a spell. See the problem? It only gets worse the farther you are into the game at the time of exporting.

    Let's generalize this. If you were on, say, day 100 of TotSC, then you exported to SoD, the script would think it had to wait 100 days to cast a spell. sarevok57's ToB saves could exceed your numbers for several reasons.

    1. He took more time before exporting, running the script at higher game tick values, and thus the trigger values reflect this fact.

    2. He waited long enough in ToB so that the script fixed itself, and continued updating normally.

    The way to fix these triggers is to either
    a) Have them wiped on export, just like global variables
    or
    b) Reset them to 0 on export

    You could theoretically build in some sort of error-checking into the script, and have it reset the triggers if they are absurdly high; but that is easier said than done.

    I know, big wall of text. TLDR; triggers are complicated. Here are some images with the current game tick added, to help demonstrate the triggers in relation to the game tick:

    Script casting Stoneskin right after starting new TotSC game:


    Resting 24 hours and casting another Stoneskin:


    After exporting to SoD immediately after last screenshot:


    See how there is a disconnect between the first two screenshots, and the last one? Hopefully this helps.
  • islandkingislandking Member Posts: 426
    edited April 2017
    @Bubb
    Thanks for the detailed explanation, sorry I didn’t make myself clear.

    I get your meaning of having to exceed precious numbers for Adv AI to autocast. What I didn’t get is:
    1.I thought all local variables are wiped out during exportation, looks like it’s not the case.
    2.Take my “BD_BLIND 1552821” for example, the number will only change the next time AI casts Blindness right? And time gap in-between the two casts will be added to the number, which would be HUGE in my case. That actually answered my precious question :-)
    3.The third one's not important but, why do we need those ticks in first place?
  • BubbBubb Member Posts: 1,000
    @islandking
    1) I tested this, and local variables are preserved in exports. This is most likely due to them being stored in the creature. Global variables, on the other hand, are most certainly wiped.

    2) You are correct, the timer's value will only update when the spells are auto-cast. This upate will jump the timer to the current game tick, skipping everything in between.

    3) The ticks are the internal, precise way the game keeps track of time. It's just another layer; a layer that is closer to the internal logic-loop that runs the whole program. This "tick" system is what the round system is built on top of.

    This problem is simply an oversight by the developers when making these scrips. I don't necessarily see how they can fix this easily using current methods, but it certainly is fixable. It would require scripting in resets for these timers at export, or at every new game transition. It's up to the developers to fix now, but for now you can just reset the timers manually if they ever get stuck.
  • kjeronkjeron Member Posts: 2,367
    edited April 2017
    Bubb said:

    @islandking This problem is simply an oversight by the developers when making these scrips. I don't necessarily see how they can fix this easily using current methods, but it certainly is fixable. It would require scripting in resets for these timers at export, or at every new game transition. It's up to the developers to fix now, but for now you can just reset the timers manually if they ever get stuck.

    Append the following to the top of each script in "PARTYAI.2da", for each variable:
    IF
    	True()
    	ActionListEmpty()
    THEN
    	RESPONSE #100
    		SetGlobalTimer("BD1ROUND","LOCALS",ONE_ROUND)
    		SetGlobalTimer("BD2ROUND","LOCALS",TWO_ROUNDS)
    		SetGlobalTimer("BD3ROUND","LOCALS",THREE_ROUNDS)
    		Continue()
    END
    
    IF
    	LocalsGT("BD_CAST","BD1ROUND")
    	ActionListEmpty()
    THEN
    	RESPONSE #100
    		SetGlobal("BD_CAST","LOCALS",0)
    		Continue()
    END
    IF
    	LocalsGT("BD_Spook","BD2ROUND")
    	ActionListEmpty()
    THEN
    	RESPONSE #100
    		SetGlobal("BD_Spook","LOCALS",0)
    		Continue()
    END
    IF
    	LocalsGT("BD_Support","BD2ROUND")
    	ActionListEmpty()
    THEN
    	RESPONSE #100
    		SetGlobal("BD_Support","LOCALS",0)
    		Continue()
    END
    IF
    	LocalsGT("BD_Haste","BD3ROUND")
    	ActionListEmpty()
    THEN
    	RESPONSE #100
    		SetGlobal("BD_Haste","LOCALS",0)
    		Continue()
    END
    
    etc...
    
  • BubbBubb Member Posts: 1,000
    edited April 2017
    @kjeron
    I had come up with a similar solution, but it constantly made my characters cancel whatever actions they were doing. This seems like the only way to fix it other than to hard wire resets on export. I just checked your script, and it does indeed cancel any of the characters actions when it sets the globals / timers. Maybe throwing an ActionListEmpty() in the triggers block would fix this?
  • kjeronkjeron Member Posts: 2,367
    edited April 2017
    Bubb said:

    @kjeron
    I had come up with a similar solution, but it constantly made my characters cancel whatever actions they were doing. This seems like the only way to fix it other than to hard wire resets on export. I just checked your script, and it does indeed cancel any of the characters actions when it sets the globals / timers. Maybe throwing an ActionListEmpty() in the triggers block would fix this?

    Yes it should, I'll edit it.
  • BubbBubb Member Posts: 1,000
    edited April 2017
    I've finished making a fix for the export bug using @kjeron's method. It is in the form of a WeiDU mod, and it works in bgee, bg2ee, and eet environments. It will prevent the bug from occurring, and fix any save that is currently broken. This requires modmerge to be run on SoD.

    Note: This patch reads the PARTYAI.2DA file to find the advanced ai scripts. Any mod that adds entries to this file will get their scripts unnecessarily patched, and any mod that changes the existing default values will break this patch.

    EDIT: Fixed instance where patch would interrupt thieving abilities.
  • MageMixlerMageMixler Member Posts: 1
    This thread is over a year old, but I’m running in to the same problem on iOS. Is there an equivalent fix? I don’t know of a way to put the .txt file into the game files.
  • kjeronkjeron Member Posts: 2,367
    A fix was implemented in the v2.6 update, but only for BG2EE, not BGEE/SoD.

    Sorry, I don't know how to help with mobile.
  • SwitchedSwitched Member Posts: 1
    Yep. I am now running into this issue on the Nintendo Switch. Any fix? How is the game unpatched?
Sign In or Register to comment.