Aller au contenu

Photo

Issue with Custom AI script on multiple mobs


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

#1
Shadram

Shadram
  • Members
  • 5 messages
I hope this isn't a repeated question, I did a bit of searching but couldn't find anything similar.

I've written a custom AI script, and want to use it with several creatures in an area.  The first creature encountered works great, but the subsequent ones spawn, don't move/attack and are not interactive.  I've confirmed it's the script and not the creatures by swapping around the order in which they spawn (there's one mob in each group using the script, and groups spawn in waves, one after the other), and I've tried both creating 2 instances of the same creature type and creating 2 separate creature types.

Any ideas what I could be doing wrong?  Is it even possible to have more than one creature using the same script? This is the first time I've tried it.  My guess is that I need to do some sort of clean up when the first creature dies to reset the script variables, maybe?

I can post my code if that's useful, although it is a bit messy. :P

#2
FergusM

FergusM
  • Members
  • 460 messages
It would probably be a good idea to post your code.

You can indeed use the same script on multiple creatures. However, if you are setting some sort of variables on anything other than the creature, yes, it might not go so well.

EDIT: I should clarify that, I mean if you're doing something like SetLocalInt() or something. If you're just running a more or less self-contained script, one creature's script should not effect the next.

Modifié par FergusM, 21 juillet 2010 - 06:05 .


#3
Shadram

Shadram
  • Members
  • 5 messages
OK, here's my code.  It's based on one of the Single Player bosses (I think it was the Spider Queen from the Deep Roads).  The idea is that the mob spawns and sits shooting fireballs at the PCs while none of them are in melee range.  I don't think there's any script variables being modified

#include "cai_h"
#include "utility_h"

const int RAGEDEMON_CAI_AT_RANGE1       = 1001;
const int RAGEDEMON_CAI_AT_RANGE2       = 1002;

void main()
{

    //--------------------------------------------------------------------------
    // Initialization
    //--------------------------------------------------------------------------

    // Load Event Variables
    event   evEvent         = GetCurrentEvent();            // Event
    int     nEventType      = GetEventType(evEvent);        // Event Type
    object  oEventCreator   = GetEventCreator(evEvent);     // Event Creator

    // Standard Variables
    object  oPC             = GetHero();
    object  oParty          = GetParty( oPC );
    int     bEventHandled   = FALSE;

    //--------------------------------------------------------------------------
    // Events
    //--------------------------------------------------------------------------

    switch ( nEventType )
    {
        case EVENT_TYPE_DEATH:
        {
            break;
        }

        case EVENT_TYPE_HANDLE_CUSTOM_AI:
        {

            int nCustomAI = GetLocalInt( OBJECT_SELF, AI_CUSTOM_AI_ACTIVE );

            // Creature still has a command to finish, so just let him do that.
            if (GetEventInteger(evEvent,2)==COMMAND_FAILED)
            {
                WR_AddCommand(OBJECT_SELF,CommandWait(0.01f),TRUE);
                return;
            }
                 
            // Update CAI State
            switch ( nCustomAI )
            {
                case CAI_INITIATE:
                {
                    CAI_SetCustomAI(OBJECT_SELF, RAGEDEMON_CAI_AT_RANGE2);
                    AI_DetermineCombatRound();
                    bEventHandled = TRUE;
                    break;
                }

                case RAGEDEMON_CAI_AT_RANGE1:
                case RAGEDEMON_CAI_AT_RANGE2:
                {
                    object []   arParty = GetPartyList(oPC);
                    int         i, size = GetArraySize(arParty);
                    // if any party members are close enough, kill this custom ai
                    for (i=0;i<size;i++)
                        if (!IsDead(arParty[i]) && GetDistanceBetween(OBJECT_SELF,arParty[i]) < 3.0f)
                            nCustomAI = CAI_SetCustomAI(OBJECT_SELF,CAI_INACTIVE);
                    break;
                }

                case CAI_INACTIVE:
                {
                    object []   arParty = GetPartyList(oPC);
                    int         i, size = GetArraySize(arParty);
                    float       closest = 100.0f;
                    // if no party members in melee, do range mode
                    for (i=0;i<size;i++)
                        if (!IsDead(arParty[i]) && GetDistanceBetween(OBJECT_SELF,arParty[i]) < closest)
                            closest = GetDistanceBetween(OBJECT_SELF,arParty[i]);
                    if (closest > 3.0f)
                        nCustomAI = CAI_SetCustomAI(OBJECT_SELF,RAGEDEMON_CAI_AT_RANGE1);
                    break;
                }
            }

            // If the Custom AI is handled Globally, we can skip the rest
            if ( CAI_HandleGlobalCAI(OBJECT_SELF,nCustomAI) )
                break;
                    
            // Handle Custom AI
            switch( nCustomAI )
            {
                case RAGEDEMON_CAI_AT_RANGE1:
                {
                    //----------------------------------------------------------
                    // RAGEDEMON_CAI_AT_RANGE1
                    //----------------------------------------------------------
                    effect      effRestoreManaStam  = EffectModifyManaStamina(Ability_GetAbilityCost(OBJECT_SELF,ABILITY_SPELL_FIREBALL));
                    object []   arParty             = GetPartyList(oPC);
                    object      oTarget;

                    // restore mana stamina
                    ApplyEffectOnObject(EFFECT_DURATION_TYPE_INSTANT,effRestoreManaStam,OBJECT_SELF);

                    // pick random party member and spit at thems
                    oTarget = arParty[Random(GetArraySize(arParty))];
                    SetCooldown(OBJECT_SELF,ABILITY_SPELL_FIREBALL,0.0f);
                    Ability_UseAbilityWrapper(OBJECT_SELF,ABILITY_SPELL_FIREBALL,oTarget,TRUE);

                    CAI_SetCustomAI(OBJECT_SELF,RAGEDEMON_CAI_AT_RANGE2);

                    break;
                }
                case RAGEDEMON_CAI_AT_RANGE2:
                {
                    //----------------------------------------------------------
                    // RAGEDEMON_AT_RANGE2
                    // Delay
                    //----------------------------------------------------------
                    // wait a bit before firing again
                    WR_AddCommand(OBJECT_SELF,CommandWait(3.0f));
                    CAI_SetCustomAI(OBJECT_SELF,RAGEDEMON_CAI_AT_RANGE1);
                    break;
                }
                case CAI_STASIS: break;
                default: AI_DetermineCombatRound();
            }
            bEventHandled = TRUE;
            break;
        }
    }
    // -------------------------------------------------------------------------
    // Any event not handled is also handled by creature_core:
    // -------------------------------------------------------------------------

    HandleEvent(evEvent, RESOURCE_SCRIPT_CREATURE_CORE);

}



#4
FergusM

FergusM
  • Members
  • 460 messages
Hrm, I admit I don't really know what the problem is. However, you may wish to investigate using an AI Package 2DA; the AI you're describing sounds simple enough to create that way.



If you're not familiar with creating/exporting 2DAs, check out the wiki article. As for the specifics here:



1) Create a new 2DA, call it aip_caster or something. Give it the same format as all the other aip_ 2das in [dragon age]/tools/source/packages.

2) Add an entry to M2DA_Base, which is also in the source folder, (or an M2DA of M2DA_Base...see the wiki on M2DAs). The entry needs to have a unique id number, a label for you and the name of the worksheet you made in step 1. It also needs the last column filled out; this specifies what package this ai is for. If you open up packages_base.xls, you can see the package types. Pick the appropriate id (i.e. from pellcaster or something).

3) Look at AI_TacticsConditions.xls and ABI_Base.xls (in the /rules folder). You want to fill out your 2DA like the other AI packages; its basically like the tactics screen in-game.

4) In your particular case, you could put in a 'jump' step that jumps to itself, checking if there are targets at close range. If there aren't, it goes on to the second tactic, to use ability fireball.



It's a bit of a mess to wrap your head around at first, but it's a little easier to use than custom ai scripts.

#5
Shadram

Shadram
  • Members
  • 5 messages
Thanks for your help. I'll have a go at learning the 2DA way of doing things, then. :)