Custom Character scripting
Lorel
Member Posts: 9
1. I modified Mage4 script to cast different spells. It works great but after casting about 6 fireballs it stops casting all the magic missiles that my char has memorized and just starts meleeing. How do I get it to keep casting until all do the spells are exhausted? I tried removing the melee script and same thing happens...he stops casting even tho he has some spells left but instead of meleeing he just stands there.
2. What is the command for scripting innate abilities? Does anyone have an example of the full script (IF, THEN, END) so I can try out some things?
I just started messing around with scripts and slowly figuring it out. It's very fun tho...thanks!
2. What is the command for scripting innate abilities? Does anyone have an example of the full script (IF, THEN, END) so I can try out some things?
I just started messing around with scripts and slowly figuring it out. It's very fun tho...thanks!
0
Comments
2. For "Special Abilities", those are listed differently; here is a script that someone else wrote (I can't find the link for the download), but here, the character has the ALCHEMY ability. (This person's scripting is very well thought out, but I think he puts too much coding):
// Alchemy
IF
ActionListEmpty()
CombatCounter(0)
Global("GBAlchemy","LOCALS",1)
HaveSpellRES("spcl918")
!GlobalTimerNotExpired("GBHalfAttack","LOCALS")
THEN
RESPONSE #100
SetGlobalTimer("GBHalfAttack","LOCALS",6)
SpellRES("spcl918",Myself)
END
IF
ActionListEmpty()
CombatCounter(0)
Global("GBAlchemy","LOCALS",1)
HaveSpellRES("gbalchpr")
!GlobalTimerNotExpired("GBHalfAttack","LOCALS")
THEN
RESPONSE #100
SetGlobalTimer("GBHalfAttack","LOCALS",6)
SpellRES("gbalchpr",Myself)
END
Here is "scribe scroll":
// Scribe Scrolls
IF
ActionListEmpty()
CombatCounter(0)
Global("GBAlchemy","LOCALS",1)
HaveSpellRES("spcl919")
!GlobalTimerNotExpired("GBHalfAttack","LOCALS")
THEN
RESPONSE #100
SetGlobalTimer("GBHalfAttack","LOCALS",6)
SpellRES("spcl919",Myself)
END
IF
ActionListEmpty()
CombatCounter(0)
Global("GBAlchemy","LOCALS",1)
HaveSpellRES("gbscrbpr")
!GlobalTimerNotExpired("GBHalfAttack","LOCALS")
THEN
RESPONSE #100
SetGlobalTimer("GBHalfAttack","LOCALS",6)
SpellRES("gbscrbpr",Myself)
END
--------
If you script it to cast a spell, it will continue casting that spell until it's exhausted, given that certain conditions are true. Possibly you could add a variable in the script.
I don't have BG2:EE, but I'm assuming that the scripts are pretty much the same. Here is the script from Mage4 involving "Fireball":
IF
ActionListEmpty()
See(NearestEnemyOf(Myself))
HaveSpell(WIZARD_FIREBALL)
!Range(LastSeenBy(Myself),20)
THEN
RESPONSE #100
Spell(NearestEnemyOf(Myself),WIZARD_FIREBALL)
END
So, as long as the conditions are true (Action list is empty, there is an enemy, he has the Fireball spell, and the range is correct), the spell will be cast. In order to stop the casting of the spells until the spells are depleted, we need to create a condition that becomes false (as in, running out of the Fireball spell, thus HaveSpell(WIZARD_FIREBALL) becomes false).
One possibility in doing this is to create a variable that limits the number of times "Fireball" is used:
IF
ActionListEmpty()
See(NearestEnemyOf(Myself))
HaveSpell(WIZARD_FIREBALL)
!Range(LastSeenBy(Myself),20)
GlobalLT("Fireball","LOCALS",1)
THEN
RESPONSE #100
Spell(NearestEnemyOf(Myself),WIZARD_FIREBALL)
SetGlobal("Fireball","LOCALS",1)
END
In the above revision, the wizard will cast fireball 1 time. One of the conditions is now that the variable "Fireball" is less than one. After the spell is cast, the value for "Fireball" now becomes one.
If we do set this kind of a variable, however, you will need to add something to the bottom of the script that changes "Fireball" back to 0; or else the Wizard will cast Fireball only once in his entire career:
IF
!See(NearestEnemyOf(Myself))
CombatCounter(0)
GlobalGT("Fireball","LOCALS",0)
THEN
RESPONSE #100
SetGlobal("Fireball","LOCALS",0)
END
--------------
In short, before the wizard will stop casting FIREBALL, a condition has to become "false".
IF
ActionListEmpty()
See(NearestEnemyOf(Myself))
HaveSpell(WIZARD_MAGIC_MISSILE)
HPGT(LastSeenBy(Myself),20)
!HasBounceEffects(LastSeenBy(Myself))
THEN
RESPONSE #100
Spell(NearestEnemyOf(Myself),WIZARD_MAGIC_MISSILE)
END
IF
ActionListEmpty()
See(NearestEnemyOf(Myself))
HaveSpell(WIZARD_MELF_ACID_ARROW)
HPGT(LastSeenBy(Myself),20)
!HasBounceEffects(LastSeenBy(Myself))
THEN
RESPONSE #100
Spell(NearestEnemyOf(Myself),WIZARD_MELF_ACID_ARROW)
END
It's a bad idea to remove the !HasBounceEffect. That causes our characters to check to see if something like "Minor Spell Turning" is in effect.
I did not have that in my Druid script; so, when Jaheira encountered the "escaped clone", she cast her "Summon Insects". It bounced off the escaped clone, so now here are Minsc, Boo, Imoen and Yoshimo taking on the clone while Jaheira has a cloud of insects around her head and she's going "Ah! Ah! Ah!" and my Bhaalspawn was busy standing behind her healing her and it was a real mess ....
I can NOT find a link to that script. But this link has some more scripting downloads:
http://www.sorcerers.net/Games/BG2/index_editors.php
I'm interested in adding innate abilities to my AI scripts myself, but I just haven't gotten around to it. If you tell me which innate ability you want to script, I'm sure we can work together on it. Up to you ...
@Lorel
If you aren't already, you'll want to consult the IESDP, particularly the sections on actions and triggers.
** I think scripts are somewhat of an "achille's heel"; while they reduce our workload while playing the game, they also have a tendency to take away control of the characters, sometimes causing them to do other than what we, at the moment, want them to do. It would be nice if we had the option to turn AI on/off for each character instead of as an entire group. **
At the very (very) top of Bards or Clerics and Paladins, I put this script. If instructed to use Bard Song or Turn Undead, this causes all other actions to be bypassed. So, if we click "Turn Undead" action or "Bard Song" action, they don't decide by themselves to quit that action and do something else for us ....
// ================================ BARD SONG ======================
// (* This prevents the character from performing any actions other than bard song.*)
// (* Player must initiate and stop bard song. *)
IF
ModalState(BARDSONG)
THEN
RESPONSE #100
END
// ================================ UNDEAD TURNING ===================
// (* This prevents the character from performing any actions other than turning undead.*)
// (* Player must initiate and stop undead turning. *)
IF
ModalState(TURNUNDEAD)
THEN
RESPONSE #100
END
Here is a script I put near the top of all of my scripts. It instructs the character to use healing potions and Antidotes. The script does not implement when they are currently engaged with an enemy.
// =================== POTIONS ==========================
// Antidote
IF
ActionListEmpty()
HasItem("POTN20",Myself)
StateCheck(Myself,STATE_POISONED)
THEN
RESPONSE #100
UseItem("POTN20",Myself)
END
// Potion of Superior Healing
IF
ActionListEmpty()
HasItem("POTN55",Myself)
HPPercentLT(Myself,80)
THEN
RESPONSE #100
UseItem("POTN55",Myself)
END
// Extra Healing
IF
ActionListEmpty()
HasItem("POTN08",Myself)
HPPercentLT(Myself,80)
THEN
RESPONSE #100
UseItem("POTN08",Myself)
END
// Healing
IF
ActionListEmpty()
HasItem("POTN52",Myself)
HPPercentLT(Myself,50)
THEN
RESPONSE #100
UseItem("POTN52",Myself)
END
You were talking about scripting special abilities. While I have not yet experimented with this, here are some codes I have ran accross:
// Whirlwind Attack: SPCL900
// Greater Whirlwind Attack: SPCL901
// Deathbow: SPCL902
// Greater Deathbow: SPCL903
// CRITICAL STRIKE: SPCL905
// Power Attack: SPCL906
// War Cry: SPCL908
// Smite: SPCL909
// Shapeshifts Werewolf: SPCL643
// Shapeshifts Greater Werewolf: SPCL644
// Pocket Plane: SPIN649
// Slayer Change: SPIN822
--------------------------------------------------
In revising, I broke my ClericMage script, LoL. Somewhere is an extra IF, THEN or END and I can't find it for the life of me! But, I have backups; just have to gather my last save and do today's revisions again.
It depends on what you mean by "cycle", but no, there isn't. Multiple targets require one block per target and result in long scripts. Scripts with advanced targeting frequently clock in at thousands or tens of thousands of lines of BAF, and most of the length is targeting. If you want something comparatively brief, I would suggest you have a look at the AI scripts in aTweaks written by aVENGER, which is most of the fiend and all of the elemental and fey scripts. There are other ways of doing it, with different advantages and disadvantages, but one of the advantages of this particular method is that achieves advanced targeting with a comparatively low number of lines of BAF. (Caveat: some of the fiend scripts in aTweaks are written by me and are considerably longer [and you are much better off reading the SSL source instead of the BAF].)