Creature AI Question - Have Creature Use Spells Only
#1
Posté 31 mars 2013 - 02:25
Assume I have never played with Creature AI (I haven't...and got amazingly far without doing so). I don't mind letting the AI decide the spells to cast (if I picked them out myself, the challenge will go up a lot...I'm evil to players like that).
#2
Posté 31 mars 2013 - 07:15
still haven't found it tho. I stumbled across what looked like it at some point, but then since i was doing something else figured "oh that could be it" and ..
I don't think it's a simple switch somewhere. I just don't want casters running in with a dagger when they have Ice Storm + half a dozen other offensive spells. Ever!
maybe someone has a creative alternative,
like spawn it as incorporeal and ranged
// Ranged attacker will attempt to stay at ranged distance from their target.
// SetCombatCondition(X0_COMBAT_FLAG_RANGED);
flag X2_L_IS_INCORPOREAL = TRUE
( but really i'm more inclined to say it *is* a job for a custom AI script )
#3
Posté 31 mars 2013 - 02:13
Inside your custom AI script, you want to cast the spells, On a successful spell casting, you want to set the X2_SPECIAL_COMBAT_AI_SCRIPT_OK variable to TRUE to tell the standard AI script that your custom script was successful, and not to do anything else.
Once your NPC is out of spells, you just want to have your custom script set the X2_SPECIAL_COMBAT_AI_SCRIPT_OK to TRUE every time. This should prevent the AI from attacking physically, though I have no tested it.
I can post a sample script later today.
#4
Posté 31 mars 2013 - 03:36
On the NPC, set the variable X2_SPECIAL_COMBAT_AI_SCRIPT=name_of_this_script
Make sure the NPC has the default script set. Load yourself up into the zone, get close to the NPC, and watch. They should cast all their magic missiles at you, and then stop.
#include "hench_i0_ai"
void FinishAI(object oTarget = OBJECT_SELF)
{
SetLocalInt(oTarget, "X2_SPECIAL_COMBAT_AI_SCRIPT_OK",TRUE);
}
void main()
{
object oTarget = GetNearestSeenOrHeardEnemyNotDead();
int nSpellId = SPELL_MAGIC_MISSILE;
// If we have spells, cast them.
if(GetHasSpell(nSpellId))
{
ClearAllActions(TRUE);
ActionCastSpellAtObject(nSpellId, oTarget);
FinishAI(OBJECT_SELF);
return;
}
// Otherwise, do nothing.
FinishAI(OBJECT_SELF);
}
Modifié par ColorsFade, 31 mars 2013 - 03:38 .
#5
Posté 31 mars 2013 - 07:14
from the default spawnscript ( nw_c2_default9 ) call a custom script via a string variable on the creature
SpawnScript = custom_script
// custom_script
#include "hench_i0_generic"
#include "hench_i0_assoc"
void main()
{
SetHenchAssociateState(HENCH_ASC_NO_MELEE_ATTACKS, TRUE, OBJECT_SELF);
}( so in this sense it is just a simple switch )
Now, this probably isn't *supposed* to work, but it does in tests here. Using TonyK's -- aka the SoZ AI called w/ HenchDetermineCombatRound() -- my ogre magi cast Cone of Cold, Charm Person, and the Heroism from its greatsword. Then it stood there and never made a physical attack!
It did not cast Darkness, Invisibility, Polymorph Self, or Sleep. ( <- just noting that, I don't know what's going into these AI decisions ) vs a 15 dwarfen Cleric
nb. i Find that the toolset is bugged when assigning #Uses of spells or spellabilities. If you set #Uses, save, close, open, and then look at the creature's Properties|Spell/abilities, the #Uses resets to 1. A save then overwrites previous values,
/fwiw
#6
Posté 31 mars 2013 - 11:11
It's been a longtime ambition of mine to figure out how to write a series of NWNX plugins that allow nwscript access to the full range of creature data, including feats, known and memorized spells, true AB, etc. My thinking is that Pain's Neverlauncher is eventually going to get to the point where it's going to be easy to run NWNX for single player anyway. Unfortunately, I don't have the C++ skills to accomplish this, but it's a direction that I see things progressing in.
#7
Posté 31 mars 2013 - 11:49
I been poking that ai, MC, and have seen areas with what you've noticed: if(hasSpell_a) +1, if(hasSpell_
ironically, as a means to counter the toolset bug i mentioned, I began to devise a 'spells_that_should_be_available.2da', which strikes me as a way to start giving an ai "here are the spells, now use them" instructions (tbh it more than 'struck me' -- put ~100 hr into developing it). But this runs into huge problems once one realizes that without extensive Caster data collection & spellscript rewrites, the spells'd have to bCheat at level 10.
/which just takes the wind right out of that method afaiac. Back to spell fixes & streamlining fer me, i guess
#8
Posté 01 avril 2013 - 03:27
kevL wrote...
ironically, as a means to counter the toolset bug i mentioned, I began to devise a 'spells_that_should_be_available.2da', which strikes me as a way to start giving an ai "here are the spells, now use them" instructions (tbh it more than 'struck me' -- put ~100 hr into developing it). But this runs into huge problems once one realizes that without extensive Caster data collection & spellscript rewrites, the spells'd have to bCheat at level 10.
Yeah, that's it exactly. My thought was that if it becomes possible to see which spells a creature has memorized and/or ready to cast, you could conceivably set a spell as memorized and ready to cast. So if you (you here being an AI writer) determine that a spell should be cast under a certain condition, you declare "Make it so!", and so it is.
#9
Posté 01 avril 2013 - 02:01
kevL wrote...
here's an interesting alternative, that uses the AI to choose spells
from the default spawnscript ( nw_c2_default9 ) call a custom script via a string variable on the creature
SpawnScript = custom_script// custom_script #include "hench_i0_generic" #include "hench_i0_assoc" void main() { SetHenchAssociateState(HENCH_ASC_NO_MELEE_ATTACKS, TRUE, OBJECT_SELF); }
( so in this sense it is just a simple switch )
That seems like the way to go for me; ColorFades idea would be great to script the spells, but this idea is better for a single script opn three different liches... which is what I'm looking for.
Now, this probably isn't *supposed* to work, but it does in tests here. Using TonyK's -- aka the SoZ AI called w/ HenchDetermineCombatRound() -- my ogre magi cast Cone of Cold, Charm Person, and the Heroism from its greatsword. Then it stood there and never made a physical attack!
It did not cast Darkness, Invisibility, Polymorph Self, or Sleep. ( <- just noting that, I don't know what's going into these AI decisions ) vs a 15 dwarfen Cleric
That's actually promising to me...Sleep is only useable if target has 4 or less Hit Dice (so don't bother vs 15), Polymorph Self is blatantly a combat-buff, and I can see why the programmers would have made invis and darkness combat buffs as well...and since he won't enter melee, he won't cast them.
Thank you to everyone for the advice, I'll have to try this out and see what happens...
#10
Posté 01 avril 2013 - 02:47
MasterChanger wrote...
Yeah, that's it exactly. My thought was that if it becomes possible to see which spells a creature has memorized and/or ready to cast, you could conceivably set a spell as memorized and ready to cast.
You can find out if a creature has any spell memorized with a call to GetHasSpell(). That's really all you need, in combination with the remaining functions that already exist.
If you wanted to write a general-purpose AI script for a given class, say a Cleric, and account for every possible spell that they could have memorized, you could do it. The functions are there. All it would take is time to write the script to account for all the possible spells, to check each spell to see if the PC has it memorized. If they do have a spell memorized - you can determine what to do from that point.
Casting a spell "under certain conditions", regardless of memorization, is already possible with bCheat=TRUE. No need to have the creature memorize it. Just have them cast it. That's what the method is there for.
MasterChanger wrote...
So if you (you here being an AI writer) determine that a spell should be cast under a certain condition, you declare "Make it so!", and so it is.
And you can do that with bCheat.
Managing spell AI is actually the easiest part of working with the AI in NWN2, as I recenty found out in building my AI library. What's much harder is tracking damge/hate/aggro and targeting enemies based on specific criteria (like class-type, or who just hurt me the most, or where is the cleric that just healed the fighter that I was about to kill?) because the game engine lacks specific functions to do that stort of stuff easily, so you have to write it yourself.
But when it comes to spells - the functions are there.
#11
Posté 01 avril 2013 - 07:53
#12
Posté 01 avril 2013 - 08:13
if you notice some spells not getting cast that you really want, tie in the X2_Special_Combat script that CF outlined, and call them there under whatever conditions you like.
- when such spells cast, set the ai OFF w/ FinishAI(), but leave it ON otherwise
eg. Greater Stoneskin instant
Displacement @ half-health
if (distance > 20 && #enemies_in_sphere > 2) do Fireball
if (Target_is_caster) do Feeblemind,
etc.
#13
Posté 02 avril 2013 - 12:35
But it might let you skip a custom AI.
Tweak the STR down as low as you can so the BA is bad / low.
Put a weapon or token on the creature as well that has a BA penalty.
Set these two variables on the creature as Integeres.
X2_L_BEH_OFFENSE = 100
X2_L_BEH_MAGIC = 100
The comment on X2_L_BEH_MAGIC says it will always use magic if set to 100.
I have not confirmed that.
"The value of this variable (int) is added to the chan
ce that a creature will use magic in combat. Set to 100 for
always, 0 for never
X2_L_BEH_MAGIC "
This setup should take you just a few minutes to try out.
#14
Posté 02 avril 2013 - 02:07
i have a /rather strong/ suspicion those variables are limited to use by the pre-MotB ai, eg. DetermineCombatRound() ... ( not HenchDetermineCombatRound() etc )luna_hawke wrote...
The comment on X2_L_BEH_MAGIC says it will always use magic if set to 100.
I have not confirmed that.
#15
Posté 02 avril 2013 - 02:15
when a spell is bCheat, the engine uses a default level of 10 ( and probably doesn't correctly store other info on an effect or AoE, like the Creator, trueSaveDC, etc. )
unfortunately there is no known 'incrementRemainingSpellUses' function, either. The hardcoded console command 'givespell' brings a spell up ready-to-use, but SetSpellKnown() doesn't ( and has other issues like the creature needs a caster_class )
So yeah, either fake it, bCheat, or rewrite spellscripts ...
#16
Posté 02 avril 2013 - 08:54
kevL wrote...
btw CF,
when a spell is bCheat, the engine uses a default level of 10 ( and probably doesn't correctly store other info on an effect or AoE, like the Creator, trueSaveDC, etc. )
unfortunately there is no known 'incrementRemainingSpellUses' function, either. The hardcoded console command 'givespell' brings a spell up ready-to-use, but SetSpellKnown() doesn't ( and has other issues like the creature needs a caster_class )
So yeah, either fake it, bCheat, or rewrite spellscripts ...
That's good to know, that it's default level 10.
With that knowledge, I can say what I would do (and will do in my campaign if the situation arises) and that is this: I will hard-code the spell into the creature then, when I paint it down.
I prefer painting down all my encounters. There have been a couple small, really generic encounters where I've used the spawn system, but otherwise, I paint every creature and set them up by hand. I use a default blueprint, adjust the stats/spells/skills/etc, then save as a blueprint and paint.
This makes working with my AI library really easy too. And it has the added benefit that when I open an area, I can easily see everything that is going on...
Anyway, my 2 cents
#17
Posté 02 avril 2013 - 09:23
i mean, just so you know, before anyone gets carried away and puts down 50 of them ....
#18
Posté 02 avril 2013 - 11:04
kevL wrote...
painting down creatures chews up overhead on the CPU
i mean, just so you know, before anyone gets carried away and puts down 50 of them ...._~
Seriously?
Sigh... Well, we'll I guess I'll have to change my ways.
#19
Posté 02 avril 2013 - 11:24
I often tie encounter spawns to opening doors, and cache the creature types in the area to minimise any pause when they appear. If you cross an encounter trigger on the ground then you almost always notice the tell-tale delay, but if you're standing still opening a door then you notice it far less. Plus, ground triggers can be unreliable, whereas you can't get through a closed door without opening it first. It *does* prevent tracking from locating creatures in other rooms though - not that tracking should be of much use indoors anyway.
It's easy enough to force a specific group to spawn by not giving the encounter settings any wiggle room. Although personally, I *like* a bit of wiggle room in my encounters, so that ever I (as the module author) won't know exactly what I'll get every time. I might specify a boss and a couple of upper-level lackies to always appear consistently, but the number and composition of the lower-level underlings can vary without much consequence.
#20
Posté 02 avril 2013 - 11:56
DannJ wrote...
I often tie encounter spawns to opening doors, and cache the creature types in the area to minimise any pause when they appear.
Dan,
How do you cache creature types?
Caching is always good...
#21
Posté 03 avril 2013 - 01:04
Modifié par DannJ, 03 avril 2013 - 04:08 .
#22
Posté 03 avril 2013 - 01:20
DannJ wrote...
You can cache creature blueprints in the area's property settings. Doing so reduces the pause that spawing an encounter causes to a degree, but you never quite get rid of it entirely.
Thanks. That's good to know.
There are ways to trigger encounters so the PC doesn't "see" the creatures emerge from nothing, and to me that's probably the most important thing. I still might paint a few in outdoor areas for tracking scenarios... We'll see.
Thanks for the tips folks.
#23
Posté 03 avril 2013 - 10:34
kevL wrote...
painting down creatures chews up overhead on the CPU
if you paint those creatures down and set them to script hidden with ai off while hidden this shouldn't take effect, right?
#24
Posté 03 avril 2013 - 12:07
that'd make them pretty much like environmental objects (or less, in terms of system stress), i figur
[edit] ... wait a sec, I seem to remember that scriptHidden creatures *do* some events; but an important thing is they shouldn't be doing any collision detection. Testing ...
[edit2] ok, it's good.
with Disable AI while hidden ON - nada, not a peep.
w/ FALSE - HB runs. (not sure on others like Perception, prolly not)
I think this might actually be why ScriptHidden was added to NwN2 -- as a means for major 'scripted fights' to get around the spawnLag that Dann mentioned. Do it on ClientEnter* and the player never notices
*[edit3] personally i like to keep critters off the table until needed. There are plenty of counter-instances ...
Modifié par kevL, 03 avril 2013 - 12:56 .
#25
Posté 03 avril 2013 - 01:32





Retour en haut







