Help - Search - Members - Calendar
Full Version: Spellpack and SCS AI
The Black Wyrm's Lair - Forums > Mods under development - Baldur's Gate II > Lost Crossroads
DavidW
I'm in the process of revising the AI in the original Sword Coast Stratagems, and I've probably got time to make some modest allowance for the possibility of Spellpack being installed. It would be helpful to know:

(i) some foolproof way of detecting if Spellpack is installed;
(ii) your advice on how clerics, druids and mages optimised for the old spellset ought to be rethinking their strategy and spell choices if Spellpack is installed (L1-5 spells only).

If this turns out to be viable, I'll extend it to SCSII in the fullness of time.
Galactygon
QUOTE(DavidW @ Aug 9 2008, 08:35 PM) *
I'm in the process of revising the AI in the original Sword Coast Stratagems, and I've probably got time to make some modest allowance for the possibility of Spellpack being installed.


Thanks, DavidW. That is quite a favour. smile.gif

Roughly, what scope do you have in mind? Would you be willing to account for only radically modified spells, slightly modified spells plus the previous, or new spells plus the previous two? In the latter case, we have quite a bit to talk about.

QUOTE(DavidW @ Aug 9 2008, 08:35 PM) *
(i) some foolproof way of detecting if Spellpack is installed;


The zeroth component of SpellPack B5 installs the file "LCPACKB5.xxx", but that component only goes into to the graphics. What you would be looking for is a listing of each of the files for component that you are interested in. Just in case, try to include both the files "LCPACKB5.xxx" and whatever file that component installs into your ACTION_IFs and whatnot.

Here is a list of components (up to lvl 5) and what files to look for:
  • Entangle, Magical Stone, Sanctuary, Sunscorch: SPPR105C.cre and LCPACKB5.xxx
  • Battlefate, Call Upon Faith, Doom, Faerie Fire, Shillelagh: SPPR120A.spl and LCPACKB5.xxx
  • Chant, Flame Blade, Spiritual Hammer, Alicorn Lance, Beast Claw, Produce Flame, Moon Motes: FBLADE1.spl and LCPACKB5.xxx
  • Moment, Seeking, Silence 15-foot radius: LCSILENT.vvc and LCPACKB5.xxx
  • Call Lightning, Invisibility Purge, Miscast Magic, Spike Growth, Random Casualty, Prayer, Moonblade, Stormshell, Elysium's Tears: LCSKYBO1.vvc and LCPACKB5.xxx
  • Circle of Bones, Holy Smite, Mold Touch, Unholy Blight: COBONH1.vvc and LCPACKB5.xxx
  • Thorn Spray, Recitation, Cloud of Pestilence, Static Charge, Adamantite Mace: LC_RECI1.vvc and LCPACKB5.xxx
  • Produce Fire (replaces Poison): SPPR411B.spl and LCPACKB5.xxx
  • Blood Rage, Mental Domination: LCMENDOM.spl and LCPACKB5.xxx
  • Flame Strike, Undead Ward, Animal Rage, Produce Ice, Spike Stones: LCFLSRIN.vvc and LCPACKB5.xxx
  • Insect Plague, Iron Skins, Smashing Wave (replaces Greater Command), Wall of Fire: LC_SWARM.vvc and LCPACKB5.xxx
  • Charm Person: I wouldn't worry about it, unless you wish to do this as a seperate component. SpellPack simply removes total control and allows the player to converse with the charmed creature. It sets the variable ("CHARMED","LOCALS") to 1, so it could be used in the dialogues of TuTu/BGT to TEXTUALLY_REPLACE ~StateCheck(Myself,STATE_CHARMED)~ with an ~OR(2) StateCheck(Myself,STATE_CHARMED) Global("CHARMED","LOCALS",1)~
    The files are SPWI104A.spl and LCPACKB5.xxx
  • Armour, Burning Hands, Chill Touch, Colour Spray, Friends, Sleep, Spook: SPWI117F.spl and LCPACKB5.xxx
  • Agannazar's Scorcher, Detect Invisibility, Glitterdust, Hypnotic Pattern, Stinking Cloud, Melf's Acid Arrow, Vocalize, Web: LC_WEBA1.vvc and LCPACKB5.xxx
  • Fireball, Ghost Armour, Invisibility 10-foot radius, Lightning Bolt, Wraithform: SPWI315Z.spl and LCPACKB5.xxx
  • Larloch's Minor Drain, Vampiric Touch: LC_VT00.spl and LCPACKB5.xxx
  • Dimension Door (replaces Teleport Field): LC_DIMDR.spl and LCPACKB5.xxx
  • Flame Arrow, Ice Storm, Improved Invisibility, Otiluke's Resilient Sphere, Wizard Eye: IMPINVI.spl and LCPACKB5.xxx
  • Cloudkill, Cone of Cold, Shadow Door, Domination, Chaos, Invulnerability to Normal Weapons, Lower Resistance: LCDOMINA.spl and LCPACKB5.xxx
  • Shroud of Flame (replaces Oracle!): EF515_00.spl and LCPACKB5.xxx

QUOTE(DavidW @ Aug 9 2008, 08:35 PM) *
(ii) your advice on how clerics, druids and mages optimised for the old spellset ought to be rethinking their strategy and spell choices if Spellpack is installed (L1-5 spells only).

Well, this list I posted is quite a number. SpellPack's Readme has a section in it that goes through each spell. It might be easier to look through them and see what is important and what is not, since you have a realistic estimate of what is feasable to implement.

I wish for an "Enable Dialogue with charmed NPCs" component. wink.gif

QUOTE(DavidW @ Aug 9 2008, 08:35 PM) *
If this turns out to be viable, I'll extend it to SCSII in the fullness of time.


Cool.

-Galactygon
The Bigg
IF (MOD_IS_INSTALLED ~tp2name~ #componentnumber) THEN APPLY_SP_STUFF?

QUOTE
I wish for an "Enable Dialogue with charmed NPCs" component.

It's well-hidden, but http://www.shsforums.net/index.php?autocom...mp;showfile=506.
Galactygon
QUOTE(The Bigg @ Aug 10 2008, 12:06 PM) *


Okay wow, patching the .exe is very elaborate.

EDIT: Although it changes the way the opcode works. This means you can still talk to Dominated creatures, which is not AD&D-ish. There ought to be a difference on how Charm x and Domination spells work. In SpellPack, Charm Person switches allegiances, where you cannot control the charmed character, but could talk to it.

This might cause some trouble if there is a scripting block that checks allegiances and does a NoAction().

-Galactygon
Galactygon
I will keep the list as short as possible. In this case a FILE_EXISTS_IN_GAME is a better idea IMO, since there is both a "Setup-SpellPackB5.tp2" and a "Setup-SpellPackB5_Patch.tp2". With MOD_IS_INSTALLED, you will have to write everything twice (or more, since some people might still use B4).

Here is the list:
1.) Sanctuary can be cast to protect allies.
2.) Shillelagh gives you 2 attacks per round, more useful for druids.
3.) Call Lightning does not fire off automatically once per turn. Instead, you would have to cast SPIN193.spl every turn. Also, it is a very long range spell and can be tricky to pull off in a battle (casting time of 1 round). I might suggest something like this:
CODE
IF
  AreaType(OUTDOOR)
  HaveSpell(CLERIC_CALL_LIGHTNING) // Do this for SPIN193 as well
  !See(NearestEnemyOf(Myself))
  Range(LastSeenBy(Myself),100)
... // more triggers if necessary
// I would not do more elaborate checks, since the druid is too far to realistically evaluate resistances
THEN
  RESPONSE #100
    Spell(LastSeenBy(Myself),CLERIC_CALL_LIGHTNING)
END

IF
  AreaType(OUTDOOR)
  HaveSpell(CLERIC_CALL_LIGHTNING) // Do this for SPIN193 as well
  !See(NearestEnemyOf(Myself))
  OR(3)
    Heard([0.ANIMAL],ALERT)
    Heard([0.0.0.DRUID_ALL],ALERT)
    Heard([0.0.WYVERN],ALERT)
  !See(LastSeenBy(LastHeardBy(Myself)))
  OR(2)
    Allegiance(Myself,EVILCUTOFF)
    Allegiance(Myself,GOODBUTRED)
  OR(2)
    Allegiance(LastSeenBy(LastHeardBy(Myself)),PC)
    Allegiance(LastSeenBy(LastHeardBy(Myself)),ALLY)
... // more triggers if necessary
// I would not do more elaborate checks, since the druid is too far to realistically evaluate resistances
THEN
  RESPONSE #100
    Spell(LastSeenBy(LastHeardBy(Myself)),CLERIC_CALL_LIGHTNING)
END

IF
  AreaType(OUTDOOR)
  HaveSpell(CLERIC_CALL_LIGHTNING) // Do this for SPIN193 as well
  !AttackedBy([ANYONE])
  See(NearestEnemyOf(Myself))
... // more checks if necessary
THEN
  RESPONSE #100
    RunAwayFrom(NearestEnemyOf(Myself),15) // The druid would keep running away until it does not see any enemies and proceeds to call lightning bolts
END

// After a whole bunch of other blocks should druids resort to csating Call Lightning in combat

This can give the druids of cloakwood the reputation they deserve.

4.) Invisibility Purge is now an abjuration spell, and lasts for a long time. I have not made it detectable yet, but I will have a variable "INVPURGE" being set in B6 (but I can send you the files earlier).

5.) Mental Domination requires concentration to maintain, so I would not have the AI cast it.

6.) Flamestrike hsa a small area of effect, so place checks of
CODE
!Range(LastSeenBy(Myself),10)
!AttackedBy(LastSeenBy(Myself),MELEE)


7.) Like Call Lightning, Insect Plague is a very potent spell that takes 2 rounds to pull off, but has a long range. Druids should use it just like Call Lightning; ie not directly in battle.

8.) Colour Spray is a short range spell, but affects creatures of all hit die. Should be a favourite of low level mages (like the bounty hunters you meet), since characters below their level and level 6 recieve no saving throw.

9.) Armour lasts for 1 full week, so that means all mages have it as a buff. Speaking of Buffs, it wouldn't hurt to have some mages start with invisibility before combat.

10.) Detect Invsibility lasts for 2 rounds per level, and sets the stat SEEINVISIBLE.

11.) It is impossible to fire missile weapons on webbed creatures. Unfortunately stat ACMISSILEMOD is broken so you will have to look for WEB instead.
12.) Web summons a whole bunch of invisible creatures that react to fire damage. Their class is set to 41. Something your spellcasters could do is cast fireshield or flameblade if they are in the middle of a web, or run away (outdoor areas have enough space to circumvent webs). I wouldn't have them cast a fireball on webbed enemies.
CODE
IF
  Detect([0.0.0.41])
  Range(LastSeenBy(Myself),5)
  !HasItemEquiped("ANTIWEB"Myself)
  HaveSpell(WIZARD_FIRE_SHIELD_RED) // Do this for fireshield blue, aura of flaming death, and flameblade as well
... // more checks if necessary

IF
  AreaType(OUTDOOR)
  Detect([0.0.0.41])
  Range(LastSeenBy(Myself),10)
  !Range(LastSeenBy(Myself),5)
  !HasItemEquiped("ANTIWEB"Myself)
... // more checks if necessary
THEN
... // more actions if necessary
RunAwayFrom(LastSeenBy(Myself),15)
END

IF
  HaveSpell(WIZARD_FIREBALL)
  See(NearestEnemyOf(Myself))
  !CheckStatGT(LastSeenBy(Myself),0,WEB)
... // more checks if necessary


I imagine these blocks would appear very differently in SCSII scripts, but something like this works.

13.) Glitterdust sets the local variable ("GLITTER","LOCALS") to one. There is a bug in B5 that doesn't always reset the local variable back to zero when the spell ends/is dispelled. I simply forgot to include an .eff file. I have fixed this, and it will appear in B6.

But I can send you that .eff file so you could include that with SCSII in case you manage a new version earlier than I do.

14.) Otiluke's Resilient Sphere can be cast to protect allies, and they forego their saving throws and magic resistance

15.) Shadow Door has the potential to maze low-level creatures if they pursue the fleeing wizard through the door. Use this spell after Improved Invisibility, and when creatures are closing in on the wizard.

DavidW, if you are interested, I have a few script blocks somewhere that utilizes Dimension Door so that creatures can cast it to flee the party.

-Galactygon
DavidW
Thanks. I'll give that lot some thought and see how much is conveniently implementable in SCS.

Regarding Call Lightning, I'm quite surprised those blocks work - have you tested them? (The game handles offscreen targetting pretty suboptimally).

Regarding Invisibility, I do use it to buff.

Does Summon Insects still work normally?
Galactygon
QUOTE(DavidW @ Aug 17 2008, 05:24 PM) *
Regarding Call Lightning, I'm quite surprised those blocks work - have you tested them? (The game handles offscreen targetting pretty suboptimally).


Yes, they work. You cannot really do elaborate checks unless you summon an invisible .cre offscreen that sets your LastSeenBy() for you and starts shouting.

But in cases like this, a brute check does the intended job very well.

QUOTE(DavidW @ Aug 17 2008, 05:24 PM) *
Does Summon Insects still work normally?


I forgot to cover this, so now I will.

If you are speaking of the 3rd level spell, I haven't touched Summon Insects. Of the insect spells, I have so far only changed Insect Plague.

It sets the same stat as vanilla's, so you will not have to worry about spellcasters attempting to pull of a spell in the middle of the swarm. Something I forgot to mention is that some of the enemies might start swinging at the insects, since they are pretty much invisible creatures with an overlay and some effects slapped on. There is nothing wrong with this, but more intelligent creatures (INT>7) should try and get out of the insects.

The insects have their CLASS set to 63. So Detect([0.0.0.63]) and Range([0.0.0.63],15) should work. If you could, exclude the classes 41 and 63 from all your spellcasting blocks (with the exceptions below), because everyonce inawhile, the insects are subject to a not optimally placed chaos.

I would allow for mages to cast Agannazar's Scorcher/Fireball/Dispel at the swarm if the battle is taking INDOORS. Outdoors, we can assume there is enough room to circumvent the swarm. Fireshield and such are always effective, but not flaming swords (as per the Spell Description).

One more thing I forgot to mention from last time is that you can place permanent Webs in dungeons or forests; they look really nice and allows the party to rest. Place WEB.cres at your leisure, roughly 2 foot circles apart.

-Galactygon
DavidW
Okay, this is starting to look pretty complicated. How well does the vanilla-game AI handle it, incidentally?

I take it the area of effect of Flame Strike isn't party-friendly. So probably that makes it hard for AI to use without the risk of incinerating one's allies. Is Color Spray area-of-effect or single-target?
Galactygon
QUOTE(DavidW @ Aug 18 2008, 10:39 AM) *
Okay, this is starting to look pretty complicated. How well does the vanilla-game AI handle it, incidentally?


I have rarely seen them cast it (I have the impression that Creeping Doom is more common), so I thought I could get away with it. Admittedly, the vanilla does a poor job in handling the Plague on the rare occasions it casts it.

QUOTE(DavidW @ Aug 18 2008, 10:39 AM) *
I take it the area of effect of Flame Strike isn't party-friendly. So probably that makes it hard for AI to use without the risk of incinerating one's allies. Is Color Spray area-of-effect or single-target?


Neither of them are party-friendly which can cause potential problems. I have a personal preference against party-friendly spells, and unless the people start rioting I do not want to make everything party-friendly. Colour Spray has the same graphics and area of effect as it did in BG1.

Though even in vanilla + SCSII, I have seen the AI employ a triple skull-trap sequencer. So non-friendly area of effects aren't completely new.

You could handle area of effect spells pretty nicely if you use shouts and LastSeenBy(LastHeardBy(Myself)). I have done some test runs, and I will give you some results:

The AI runs away at a sluggish pace, but it works really well.

I added this to some script that employs Flamestrike.
CODE
IF
  HaveSpell(CLERIC_FLAME_STRIKE)
  See(Nearestenemyof(Myself))
  !Range(Lastseenby(Myself),10)
  !Attackedby(Lastseenby(Myself),MELEE)
  ... // more elaborate checks if needed
THEN
  RESPONSE #100
    Shout(111) // This can be any shout, but I would use something more unique
    Spell(Lastseenby(Myself),CLERIC_FLAME_STRIKE)
END


I added this to WTASIGHT.bcs
CODE
IF
  Heard([0],111) // This can be any shout, but I would use something more unique
  Range(LastSeenBy(LastHeardBy(Myself)),10) // We don't want to run away if we are not within the area of effect
  !StateCheck(LastHeardBy(Myself),STATE_DEAD) // If the caster was killed in the middle of the spell, we will not run away
  !ObjectActionListEmpty(LastHeardBy(Myself)) // It works rarely, but it might account if the spell were disrupted
  !StateCheck(Myself,STATE_MIRRORIMAGE)
  CheckStatLT(Myself,100,RESISTMAGICFIRE)
  ... // more elaborate checks if needed
THEN
  RESPONSE #100
    SetGlobalTimer("RunAway_SPPR503","LOCALS",6) // This is very important to have the creature execute the next block repeatedly
    RunAwayFromNoInterrupt(LastSeenBy(LastHeardBy(Myself)),30)
END

IF
  GlobalTimerNotExpired("RunAway_SPPR503","LOCALS")
  Range(LastSeenBy(LastHeardBy(Myself)),10) // We don't want to run away if we are not within the area of effect
  !StateCheck(LastHeardBy(Myself),STATE_DEAD) // If the caster was killed in the middle of the spell, we will not run away
  !ObjectActionListEmpty(LastHeardBy(Myself)) // It works rarely, but it might account if the spell were disrupted
  ... // more elaborate checks if needed
THEN
  RESPONSE #100
    RunAwayFromNoInterrupt(LastSeenBy(LastHeardBy(Myself)),30)
END


-Galactygon
DavidW
QUOTE(Galactygon @ Aug 18 2008, 05:51 PM) *
Neither of them are party-friendly which can cause potential problems. I have a personal preference against party-friendly spells, and unless the people start rioting I do not want to make everything party-friendly.

I sympathise, but it really is very fiddly to script for in a reliable way. You have to check that your own allies are out of range too, somehow prevent them casually wandering into range, and even then you're sunk if the enemy moves up towards you (which usually doesn't happen when the party casts, as their area-effect spells are usually cast at a point, not an enemy).

QUOTE
Though even in vanilla + SCSII, I have seen the AI employ a triple skull-trap sequencer. So non-friendly area of effects aren't completely new.

I'll hazard a guess that the caster was either a lich, a rakshasa, or had minor globe running, and that any other enemies in the area were summons or otherwise expendable.
Galactygon
QUOTE(Galactygon @ Aug 18 2008, 05:51 PM) *
I sympathise, but it really is very fiddly to script for in a reliable way. You have to check that your own allies are out of range too, somehow prevent them casually wandering into range, and even then you're sunk if the enemy moves up towards you (which usually doesn't happen when the party casts, as their area-effect spells are usually cast at a point, not an enemy).

That is true. In the case of Flamestrike, you will not have to worry about the target pursuing fleeing enemies, since the area of effect of a flamestrike is so small, that it will not catch the creature in front of a moving target (this has been tested). The real problem occours with larger area effect spells such as Fireball and Horrid Wilting.

I am assuming you are intending to use flamestrike on less mobile targets, like mages and priests who are usually casting spells. In that case, it will be even less of a problem than we imagined earlier.

QUOTE(Galactygon @ Aug 18 2008, 05:51 PM) *
I'll hazard a guess that the caster was either a lich, a rakshasa, or had minor globe running, and that any other enemies in the area were summons or otherwise expendable.

Yes, it was a Lich with other undead (IIRC mummies and ghouls) present.

-Galactygon
DavidW
Okay, so I'll be making these changes to SCS, conditional on Spell Pack components being installed. As I warned, these are modest: I don't really have time, unfortunately, to test and play with the more exciting options SP allows. Often I'm just avoiding a certain spell, because it looks as if coding for it would just be too much work... sorry.

- avoid using Insect Plague.
- prebuff with Armour
- use Colour Spray
- don't use Mental Domination
- use Flame Strike at a distance
- use Shillelagh
- use Alicorn Lance
- use Thorn Spray

Galactygon
QUOTE(DavidW @ Aug 20 2008, 01:06 AM) *
- use Alicorn Lance

This is a new spell, and the file you would be looking for is SPPR216.spl.

QUOTE(DavidW @ Aug 20 2008, 01:06 AM) *
- use Thorn Spray


I would watch out for this one, since it is not party-friendly as well (although it is safer to use due itsg cone-shape). I would opt for the safe-to-use-always-works-but-random Static Charge instead. It works like vanilla Call Lightning without the OUTDOOR restriction.

The main spell file for Thorn Spray is SPPR421.spl, and for Static Charge is SPPR426.spl.

-Galactygon
SirLancelot
QUOTE
QUOTE(DavidW @ Aug 17 2008, 05:24 PM)
Regarding Call Lightning, I'm quite surprised those blocks work - have you tested them? (The game handles offscreen targetting pretty suboptimally).


Yes, they work. You cannot really do elaborate checks unless you summon an invisible .cre offscreen that sets your LastSeenBy() for you and starts shouting.

But in cases like this, a brute check does the intended job very well.


The "summon an invisible .cre" seems to have so many uses... it's not just for shouting, but for targetting purposes as well. I remember Horred implemented it within BP scripts in a suboptimal way. It had a lot of merit, though.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2024 Invision Power Services, Inc.