Aller au contenu

Photo

CONSTANT Question


  • Veuillez vous connecter pour répondre
8 réponses à ce sujet

#1
Morbane

Morbane
  • Members
  • 1 883 messages
Is there a constant that makes a creature (bad guy) stand their ground - like stay put and not run up to the PC? 

What I mean by constant: a variable set on the creature with a value that determines its movement state upon perception etc.

Modifié par Morbane, 10 octobre 2011 - 08:51 .


#2
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
It gets complicated, with the basic problem being a command in the standard DetermineCombatRound to close with the enemy.

Giving the creature a post waypoint should limit their tendency to chase after enemies, and there is a ranged combat constant you can set. Give them some kind of ranged weapon and ammo, and they should attack the PC from a distance instead of charging.

You can also fiddle with perception, either limiting their perception ranges to short, or writing a custom perception script for them that stops them from doing anything when they first perceive the PC (Maybe a trigger on the ground could provoke them to attack at the right time).

With my tactical system, I ended up just running a script off the heartbeat that either kept them from attacking (ambush) or moved them back to a waypoint if they strayed (guard).

#3
MasterChanger

MasterChanger
  • Members
  • 686 messages

Lugaid of the Red Stripes wrote...

You can also fiddle with perception, either limiting their perception ranges to short, or writing a custom perception script for them that stops them from doing anything when they first perceive the PC (Maybe a trigger on the ground could provoke them to attack at the right time).


Using perception would get more complicated the more enemies there are at a time. I've confirmed that one faction member will piggy-back on another's perception; for example, if you have two enemies-to-the-player side by side and one has longer perception range, they'll both charge almost simultaneously when the player enters the longer range. I believe this happens because the perceiving creature calls its buddies via silent shout but I'm not sure.

Morbane, have you tested whether setting a creature's speed to immobile prevents it from attacking in melee?

#4
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Are you trying to make a guardian type creature that will attack if the PC gets close, but will not actively seek out the PC?

If so, you could make a trigger around the area to be guarded and when the PC enters the area, the NPC becomes hostile. If the PC leaves the area, then the guard will be returned to neutral faction, and will be given a command to return to its guard post.

#5
Morbane

Morbane
  • Members
  • 1 883 messages
it is a single enemy in a relatively remote section of an area. It is something like a siren - it sings its song and anyone in earshot has a chance of being drained of constitution - among other effects

MC - immobile will prevent the crypt chanter from avoiding melee attacks so that wont work.

Lugaid - What is that constant for ranged combat?

I gave it a substitute perception but it also executes the default onpercep - I will try it without

Thanks for the responses

Modifié par Morbane, 11 octobre 2011 - 08:58 .


#6
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
The constant should be listed somewhere in the default on-spawn, along with some other instructions. It will cause the creature to run away, though, to maintain distance.

#7
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Probably a good a place as any to interject. Mostly this is just relisting the tools you can use to adjust things, and with some trial and error you might be able to make things work. Some of what you are describing really should have features added to the AI to make such easier to handle without resorting to a custom AI.

The AI uses a Master integer variable to control how a creature reacts to situations. This variable is defined as "NW_GENERIC_MASTER"  ( i listed it's particular possible values at the bottom. )

A second variable is defined as "X0_COMBAT_CONDITION" which handles specific tactics used in the AI, like prefering ranged attacks. This causes the AI to use specific functions focused on very specific logic, which i assume can when combined with other vars cause a creature to focus on archery for example. ( i listed it's particular possible values at the bottom. )


It uses bits inside this integer ( ie it's binary like 01010101, where that 4th from the right digit is 0, that is the 4th bit set to off, setting that bit to on would be 01011101, based on if a bit is on or off, to us humans this shows up either as 85 or 93, its just looking at the 1's and 0's, and we humans can use google to find a converter of some sort ). This allows it to store up to 32 yes/no flags inside a single variable.

This is very hard to deal with, so the end users set a variable which is predetermined to a given value ( refer to x2_inc_switches.nss for where these are defined ), and the on spawn script ( see nw_c2_default9.nss ) uses this and converts it into a bitwise flag in the master AI variable. This is handled by the function SetSpawnInCondition which basically deals with the bits for you.

So in the spawn handler you have
if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_USE_SPAWN_STEALTH) == TRUE)
    {
        SetSpawnInCondition(NW_FLAG_STEALTH);
    }

CREATURE_VAR_USE_SPAWN_STEALTH if you look below holds "X2_L_SPAWN_USE_STEALTH" which means you need to set a integer variable on the creature named "X2_L_SPAWN_USE_STEALTH" which contains a 1 ( for true ) - without quotes.


Specific variables are as follows.
  • X2_SPECIAL_COMBAT_AI_SCRIPT
    see x2_ai_demo for details
    Variable Type = string
    Scripting Constant = CREATURE_VAR_CUSTOM_AISCRIPT
    Toolset Variable Name = X2_SPECIAL_COMBAT_AI_SCRIPT
  • X2_SPELL_RANDOM
    Setting this variable on a spellcaster creature will make its spelluse a bit more random, but their spell selection may not always be appropriate to the situation anymore.
    Variable Type = string
    Scripting Constant = CREATURE_VAR_RANDOMIZE_SPELLUSE
    Toolset Variable Name = X2_SPELL_RANDOM
  • X2_L_SPAWN_USE_STEALTH
    Set to 1 to make the creature activate stealth mode after spawn
    Variable Type = string
    Scripting Constant = CREATURE_VAR_USE_SPAWN_STEALTH
    Toolset Variable Name = X2_L_SPAWN_USE_STEALTH
  • X2_L_SPAWN_USE_SEARCH
    Set to 1 to make the creature activate detectmode after spawn
    Variable Type = string
    Scripting Constant = CREATURE_VAR_USE_SPAWN_SEARCH
    Toolset Variable Name = X2_L_SPAWN_USE_SEARCH
  • X2_L_SPAWN_USE_AMBIENT
    Set to 1 to make the creature play mobile ambient animations after spawn
    Variable Type = string
    Scripting Constant = CREATURE_VAR_USE_SPAWN_AMBIENT
    Toolset Variable Name = X2_L_SPAWN_USE_AMBIENT
  • X2_L_SPAWN_USE_AMBIENT_IMMOBILE
    Set to 1 to make the creature play immobile ambient animations after spawn
    Variable Type = string
    Scripting Constant = CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE
    Toolset Variable Name = X2_L_SPAWN_USE_AMBIENT_IMMOBILE
  • X1_L_IMMUNE_TO_DISPEL
    Set to 1 to make the creature immune to dispel magic (used for statues)
    Variable Type = string
    Scripting Constant = CREATURE_VAR_IMMUNE_TO_DISPEL
    Toolset Variable Name = X1_L_IMMUNE_TO_DISPEL
  • X2_L_IS_INCORPOREAL
    Set this variable to 1 on a creature to make it walk through other creatures
    Variable Type = string
    Scripting Constant = CREATURE_VAR_IS_INCORPOREAL
    Toolset Variable Name = X2_L_IS_INCORPOREAL
  • X2_L_NUMBER_OF_ATTACKS
    Set this variable to 1 - 6 to override the number of attacks a creature has based on its BAB
    Variable Type = string
    Scripting Constant = CREATURE_VAR_NUMBER_OF_ATTACKS
    Toolset Variable Name = X2_L_NUMBER_OF_ATTACKS
  • X2_L_BEH_MAGIC
    The value of this variable (int) is added to the chance that a creature will use magic in combat. Set to 100 for always, 0 for never
    Variable Type = string
    Scripting Constant = CREATURE_AI_MODIFIED_MAGIC_RATE
    Toolset Variable Name = X2_L_BEH_MAGIC
  • X2_L_BEH_OFFENSE
    The higher value of this variable, the higher the chance that the creature will use offensive abilities in combat. Set to 0 to make them flee.
    Variable Type = string
    Scripting Constant = CREATURE_AI_MODIFIED_OFFENSE_RATE
    Toolset Variable Name = X2_L_BEH_OFFENSE
  • X2_L_BEH_COMPASSION
    The higher value of this variable, the higher the chance that the creature will aid friendly creatures in combat. Not that helping usually degrades the overall difficulty of an encounter, but makes it more interesting.
    Variable Type = string
    Scripting Constant = CREATURE_AI_MODIFIED_COMPASSION_RATE
    Toolset Variable Name = X2_L_BEH_COMPASSION
  • X2_S_PM_SPECIAL_ITEM
    This allows you to script items that enhance a palemaster's summoned creatures. You need to put the name of a script into this variable that will be run on any creature called by the pale master's summon undead ability. You can use this script to add effects to the creature. You can use the OnEquip/OnUnEquip event hooks set this variable.
    Variable Type = string
    Scripting Constant = CREATURE_VAR_PALE_MASTER_SPECIAL_ITEM
    Toolset Variable Name = X2_S_PM_SPECIAL_ITEM

Flags used in "NW_GENERIC_MASTER" ( Note that i am adding in new flags but this is a core part of the AI so should only have the most important features implemented with this, one already added is Akavits new flee system which he did for his Sea of Dragons Persistent world. )
// these are constants to control overall behavior ( i swapped NW_ with CSL_ to prevent conflicts and those are interchangeable, i also use the BIT constants so its easier to read )
const int CSL_FLAG_SPECIAL_CONVERSATION        = BIT1;  // 0x00000001;
const int CSL_FLAG_SHOUT_ATTACK_MY_TARGET      = BIT2;  // 0x00000002;
const int CSL_FLAG_STEALTH                     = BIT3;  // 0x00000004;
const int CSL_FLAG_SEARCH                      = BIT4;  // 0x00000008;
const int CSL_FLAG_SET_WARNINGS                = BIT5;  // 0x00000010;
const int CSL_FLAG_ESCAPE_RETURN               = BIT6;  // 0x00000020; //Failed
const int CSL_FLAG_ESCAPE_LEAVE                = BIT7;  // 0x00000040;
const int CSL_FLAG_TELEPORT_RETURN             = BIT8;  // 0x00000080; //Failed
const int CSL_FLAG_TELEPORT_LEAVE              = BIT9;  // 0x00000100;
const int CSL_FLAG_PERCIEVE_EVENT              = BIT10; // 0x00000200;
const int CSL_FLAG_ATTACK_EVENT                = BIT11; // 0x00000400;
const int CSL_FLAG_DAMAGED_EVENT               = BIT12; // 0x00000800;
const int CSL_FLAG_SPELL_CAST_AT_EVENT         = BIT13; // 0x00001000;
const int CSL_FLAG_DISTURBED_EVENT             = BIT14; // 0x00002000;
const int CSL_FLAG_END_COMBAT_ROUND_EVENT      = BIT15; // 0x00004000;
const int CSL_FLAG_ON_DIALOGUE_EVENT           = BIT16; // 0x00008000;
const int CSL_FLAG_SPECIAL_COMBAT_CONVERSATION = BIT19; // 0x00040000;
const int CSL_FLAG_AMBIENT_ANIMATIONS          = BIT20; // 0x00080000;
const int CSL_FLAG_HEARTBEAT_EVENT             = BIT21; // 0x00100000;
const int CSL_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = BIT22; // 0x00200000;
const int CSL_FLAG_DAY_NIGHT_POSTING           = BIT23; // 0x00400000;
const int CSL_FLAG_AMBIENT_ANIMATIONS_AVIAN    = BIT24; // 0x00800000;
const int CSL_FLAG_APPEAR_SPAWN_IN_ANIMATION   = BIT25; // 0x01000000;
const int CSL_FLAG_SLEEPING_AT_NIGHT           = BIT26; // 0x02000000;
const int CSL_FLAG_FAST_BUFF_ENEMY             = BIT27;  // 0x04000000;

// new flags for new features I am working on below this
const int CSL_FLAG_GENERAL                     = BIT17; // group AI, this is a boss // 0x00010000;
const int CSL_FLAG_MINION                      = BIT18; // group AI, this is a minion // 0x00020000;

const int CSL_FLAG_FLEE            = BIT28; // SOD's flee system // 0x04000000;
const int CSL_FLAG_BUSYMOVING             = BIT29; // 0x04000000;
const int CSL_FLAG_XXX4            = BIT30; // 0x04000000; // need to define
const int CSL_FLAG_XXX5            = BIT31; // 0x04000000; // need to define

Flags used in "X0_COMBAT_CONDITION"
const int CSL_COMBAT_FLAG_RANGED            = 0x00000001;
const int CSL_COMBAT_FLAG_DEFENSIVE         = 0x00000002;
const int CSL_COMBAT_FLAG_COWARDLY          = 0x00000004;
const int CSL_COMBAT_FLAG_AMBUSHER          = 0x00000008;

Modifié par painofdungeoneternal, 11 octobre 2011 - 11:46 .


#8
MasterChanger

MasterChanger
  • Members
  • 686 messages
That's helpful info, Pain. A couple minor quibbles, though.

1. The variable types: all the constants (such as CREATURE_VAR_NUMBER_OF_ATTACKS) declared in x2_inc_switches are indeed const strings because they are just storing the name of the local variable you should set on the creature (as you point out). The types of the variable values themselves, though, are sometimes integers (number of attacks, as above) and sometimes strings (CREATURE_VAR_CUSTOM_AISCRIPT). The value of TRUE/FALSE flags retrieved by...
int GetCreatureFlag(object oCreature, string sFlag)
...should be stored as integers.

2. X2_L_IS_INCORPOREAL/CREATURE_VAR_IS_INCORPOREAL: the comment in x2_inc_switches does indeed say that it's to make the creature walk through other creatures. However, in the default OnSpawn script, _default9, we find:

    // * If Incorporeal, apply changes
    if (GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL) == TRUE)
    {
        effect eConceal = EffectConcealment(50, MISS_CHANCE_TYPE_NORMAL);
        eConceal = ExtraordinaryEffect(eConceal);
        effect eGhost = EffectCutsceneGhost();
        eGhost = ExtraordinaryEffect(eGhost);
        effect eImmuneToNonMagicWeapons = EffectDamageReduction(1000, DAMAGE_POWER_PLUS_ONE, 0, DR_TYPE_MAGICBONUS);
        eImmuneToNonMagicWeapons = ExtraordinaryEffect(eImmuneToNonMagicWeapons);
       
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eConceal, OBJECT_SELF);
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF);
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImmuneToNonMagicWeapons, OBJECT_SELF);
    }


The "ghost" effect above is what the comment refers to, but there are a couple other important effects here that have significant balance implications: the creature is set to have 50% concealment and to be immune to non-magic weapons.

Other than these two minor points, your reference is quite handy! :)

#9
mogromon

mogromon
  • Members
  • 41 messages
if pain's way doesnt work, you could always use CutsceneImmobilize + AreaofEffect. If any enemy gets in the area of effect the effectImmobilize is removed. OnExit script checks for creatures in a radious, if it doesnt find any enemy. Creatures goes back to his place and a new EffectImmobilize is set.