[Scripters] How to use NPC Cast Monitoring

free(?!) clues!

[Scripters] How to use NPC Cast Monitoring

Postby Kannkor » 24 Aug 2024, 13:09

Getting the casting ID
Using "ogre analysis" (or "ogre anal" for short... )
Go to the "Show Monitoring Actors" tab
[x] Enable Monitoring (top left)
Add in the Actor (usually the named NPC). (I usually pause the bot, target the named, and hit "Add Target").
Under "Members" click on "AbilityCastingID"
Sit and watch the Member Details (right side) for when the mob casts his spell. It will spit out the ID.
To copy this, select it, then right click on it. Now you can past. It will look something like this. [1724423754] 1032059640. The number in the brackets is the time stamp, and can be ignored. The 1032059640 is the ID we are after. Save this for now.

Image

Creating a NPC Cast Monitoring file
The path we need to create/modify the file is here:
Code: Select all
\Innerspace\Scripts\EQ2OgreBot\NPCCasting\MobInfo_Custom\


We can look at this file for examples.
Code: Select all
/Innerspace/Scripts/EQ2OgreBot/NPCCasting/MobInfo/Examples.xml


To get the proper file name, you use the following:
Code: Select all
echo ${OgreBotAPI.CleanZoneName}

This should spit out something like this: Darkpaw_Warrens_Heroic_II
Then we just add .xml to it, and that's our file name.

What I would do, is create a copy of example.xml, paste it into the MobInfo_Custom folder, then rename it.
What I'm going to do, for easy example purposes, is use my guild hall as the zone, then use one of my other characters. That way I can test in a guild hall nice and easy.
Lets assume my guild echo ${OgreBotAPI.CleanZoneName} came back as "OgreBot_Guild_Hall"
My file name:
Code: Select all
\Innerspace\Scripts\EQ2OgreBot\NPCCasting\MobInfo_Custom\OgreBot_Guild_Hall.xml


Next, we need the name of the actor we want to monitor. Since this is fake, I'm going to use an actor named "Kannkor". If you're following alone with the guild hall example, choose a character in your group.

Edit the xml file (remember, we made a copy of example.xml, so it will have stuff in it that we can easily replace).
Around line 4, you will see this, we need to change this to the actor we want to monitor. It should look like this for my example:
Code: Select all
<Set Name="Kannkor">

On around line 8, we have the spot for the AbilityID. This is the one you got from using Ogre Analysis above. The number I got, is actually from my guardian (who in this example, is Kannkor), so I'm going to use that.
Code: Select all
<Set Name="1032059640">


We have now told the NPC Cast Monitoring system, to monitor OgreBot Guild Hall, for any actors named "Kannkor" casting ability ID 1032059640. If we're just using the built in events, that's all we need. If we want to use this file to execute something, we need to add more.
Here is the completed file if we're using the built in events.
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<!-- Generated by LavishSettings v2 -->
<InnerSpaceSettings>
   <Set Name="Kannkor">
      <!-- Number below is the AbilityID the mob is casting -->
      <Set Name="1032059640">
         
      </Set>
   </Set>
</InnerSpaceSettings>


As you can see in the example.xml file, if we want it to simply Interrupt the ability, it has a built in way for that.
Also included in the example.xml file, is a way you can execute basic innerspace commands (think of it like this, when it finds this ability ID, it will copy code from "CommandToExecute" and paste it into the console.
Here is an example with everything! You will notice I added a second Actor named "LostOne", just to show how you can add a second actor. We'll even use it later on.
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<!-- Generated by LavishSettings v2 -->
<InnerSpaceSettings>
   <Set Name="Kannkor">

      <!-- Ability name 1 -->
      <!-- Number below is the AbilityID the mob is casting -->
      <Set Name="1032059640">

      </Set>

      <!-- Ability Name 2 -->
      <Set Name="987654">
         <Set Name="Actions">
            <Setting Name="CastInterrupt">TRUE</Setting>
         </Set>
      </Set>

      <!-- Ability Name 3 -->
      <Set Name="11223344">
         <Set Name="Actions">
            <Set Name="CommandsToExecute">
               <Setting Name="Command1">echo Ability name 3 was cast!</Setting>
               <Setting Name="Command2">echo we should do something</Setting>
            </Set>
         </Set>
      </Set>
   </Set>

   <Set Name="LostOne">

      <!-- Ability name 1 -->
      <!-- Number below is the AbilityID the mob is casting -->
      <Set Name="1624083660">

      </Set>
   </Set>
</InnerSpaceSettings>


Using CommandsToExecute
This is really only useful for very basic things. Depending on how you are setting things up, will depend on how you use this.
Generally speaking, I will enable NPC Cast Monitoring on everyone, so everyone can manage themselves. So if I wanted the person to change their campspot to 1,2,3, I would do:
Code: Select all
Ogre_CampSpot:Set_CCS[1,2,3]

Note: This will only execute for the characters that have npc cast monitoring enabled and are aware of the actor casting.

If you were going to have this run on only 1 person (technically you could do everyone) and wanted that person to tell your entire group to change their campspot to 5,6,7, I would do:
Code: Select all
oc !c -ccsfw igw:${Me.Name} 5 6 7

(If you don't want to see this code go to OgreConsole, you can use !ci instead of !c. The i stands for invisible! Do it AFTER you have tested and confirmed it is working).
There will be some kind of character limits, special character considerations etc. I only recommend using this if you're doing VERY basic stuff. Using the events is MUCH stronger and flexible.
While you can't technically have any "wait" in here, you can use timedcommand # in front of commands that you want delayed. Again, acceptable for very BASIC things. If you are trying to do something more, use the events and script it.

Example file:
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<!-- Generated by LavishSettings v2 -->
<InnerSpaceSettings>
   <Set Name="Kannkor">

      <!-- Ability name 1 -->
      <!-- Number below is the AbilityID the mob is casting -->
      <Set Name="1032059640">

      </Set>

      <!-- Ability Name 2 -->
      <Set Name="987654">
         <Set Name="Actions">
            <Setting Name="CastInterrupt">TRUE</Setting>
         </Set>
      </Set>

      <!-- Ability Name 3 -->
      <Set Name="11223344">
         <Set Name="Actions">
            <Set Name="CommandsToExecute">
               <Setting Name="Command1">echo Ability name 3 was cast!</Setting>
               <Setting Name="Command2">Ogre_CampSpot:Set_CCS[1,2,3]</Setting>
            </Set>
         </Set>
      </Set>

      <!-- Ability Name 4 -->
      <Set Name="55667788">
         <Set Name="Actions">
            <Set Name="CommandsToExecute">
               <Setting Name="Command1">echo Ability name 4 was cast!</Setting>
               <Setting Name="Command2">oc !c -ccsfw igw:${Me.Name} 5 6 7</Setting>
            </Set>
         </Set>
      </Set>
   </Set>

   <Set Name="LostOne">

      <!-- Ability name 1 -->
      <!-- Number below is the AbilityID the mob is casting -->
      <Set Name="1624083660">

      </Set>
   </Set>
</InnerSpaceSettings>


Using the event in a script
Okay, finally made it to the important stuff! I'll briefly cover what you have to do, then have an example script so you can see.
As I covered above, you need a VERY basic NPC cast Monitoring file, that has the zone name (file name), actor name, and Ability ID, and that's it.
Then in a script, we attach to events. Then we use those events to do whatever we want.
My examples will all use objects, because you should be using objects. But objects are not required, you can do it with atoms etc if you really want.
One thing to keep in mind, because events are atomic (be either atoms or object methods), they all execute in a single frame, meaning you cannot have waits in them. You would need to queue a function.
Okay, so this sample script got a little out of control, but it has an example of how to do almost anything in it. Please note, this is more sudo code than actual code. Meaning I didn't test the exact syntax of things. If someone finds mistakes I will update it.
Code: Select all
function main()
{
    variable Object_NPCCastMonitoringEvent Obj_NPCCastMonitoringEvent

    while 1
    {
        if ${QueuedCommands}
            ExecuteQueued

        call Obj_NPCCastMonitoringEvent.Handle_PulseCheck
       
        waitframe
    }
}

; Define our object
objectdef Object_NPCCastMonitoringEvent
{
    variable bool bFlagForSomeDescriptiveTerm=FALSE

    method Initalize()
    {
        Event[OgreEvent_CastMonitoring_CastingStarted]:AttachAtom[This:OgreEvent_CastMonitoring_CastingStarted]
      Event[OgreEvent_CastMonitoring_CastingEnded]:AttachAtom[This:OgreEvent_CastMonitoring_CastingEnded]
    }
    function Handle_PulseCheck()
    {
        if ${This.bFlagForSomeDescriptiveTerm}
        {
            call This.SomeDescriptiveNameForAFunctionHere
        }
    }
    function SomeDescriptiveNameForAFunctionHere()
    {
        This.bFlagForSomeDescriptiveTerm:Set[FALSE]
        ; whatever code you want here, including waits
    }
    method OgreEvent_CastMonitoring_CastingStarted(int64 _ActorID, int64 _AbilityID, float _AbilityCastingTime)
   {
      echo ${Time}: [${_ActorID}] ${Actor[id,${_ActorID}].Name} is casting ${_AbilityID}. Base cast time is: ${_AbilityCastingTime}
      ; Note about _AbilityCastingTime. This is the base casting time of the ability. It is NOT how much time is remaining

        switch ${Actor[id,${_ActorID}].Name}
        {
            case Kannkor
                This:CastingStarted_Kannkor[${_AbilityID},${_AbilityCastingTime}]
            break
            case LostOne

            break
            default
               
            break
        }
   }
   method OgreEvent_CastMonitoring_CastingEnded(int64 _ActorID, int64 _AbilityID)
   {
      ; echo ${Time}: [${_ActorID}] ${Actor[id,${_ActorID}].Name} FINISHED casting ${_AbilityID}
   }
    method CastingStarted_Kannkor(int64 _AbilityID, float _AbilityCastingTime)
    {
        ; You can use an if statement instead of a switch, but if you're going to have a bunch of them, I prefer a switch
        switch ${_AbilityID}
        {
            case 1032059640

            break
            default
                ; We don't care about anything else, as they are handled elsewhere/not handled at all.
            break
        }
    }
    ; 1032059640 = GuardianSphere
    method CastingStarted_Kannkor_GuardianSphere()
    {
        ; Note: You would only use ONE of these examples, not all of them.


        ; EXAMPLE 1: Everyone has [x] NPC Cast Monitoring checked and will manage their own
        ; Lets assume this is an AE we want to joust.
        OgreBotAPI:JoustOut
        Ogre_CampSpot:Set_CCS[1,2,3]


        ; EXAMPLE 2: Only 1 person has NPC Cast Monitoring checked and will manage the whole groups jousting
        oc !c -joustout igw:${Me.Name}
        oc !c -ccsfw igw:${Me.Name} 5 6 7


        ; EXAMPLE 3: Everyone has [x] NPC Cast Monitoring checked and will manage their own
        ; Lets assume we need to move people based on a criteria, such as archetype.
        ; Fighters go to loc 1,1,1, scouts to 2,2,2 etc etc.
        OgreBotAPI:JoustOut
        Ogre_CampSpot:Set_ChangeCampSpot[fighter,1,1,1]
        Ogre_CampSpot:Set_ChangeCampSpot[scout,2,2,2]
        Ogre_CampSpot:Set_ChangeCampSpot[mage,3,3,3]
        Ogre_CampSpot:Set_ChangeCampSpot[priest,4,4,4]

        ; EXAMPLE 4: Same thing as above, but will use if statements (incase you needed to have more complex things/calculations going on)
        ; ClassInfo is a global object part of Ogrebot, that contains a TON of information about your character. Mostly about their class.
        if ${ClassInfo.IsFighter}
        {
            ; Use a rescue if one is available
            OgreBotAPI:CastAbility_Via["all","IsThreatPositionIncrease"]
        }
        if ${ClassInfo.IsScout}
        {
            ; Use a DEAGGRO if one is available
            OgreBotAPI:CastAbility_Via["all","IsThreatPositionDecrease"]
        }
        if ${ClassInfo.IsMage} || ${ClassInfo.IsPriest}
        {
            OgreBotAPI:JoustOut
            ; While this does say "all", you have to be a priest or mage to get into this section, so it will be mages and priests only
            Ogre_CampSpot:Set_ChangeCampSpot[all,1,1,1]
        }


        ; EXAMPLE 5: queue a function (so we can have a wait)
        Script:QueueCommand[call This.CastingStarted_Kannkor_GuardianSphere]

        ; EXAMPLE 6: setting a flag and letting the script (you) deal with it however you want.
        This.bFlagForSomeDescriptiveTerm:Set[TRUE]
    }
    function CastingStarted_Kannkor_GuardianSphere()
    {
        ; Just an example of doing a wait. Maybe you want to wait 2s to joust
        echo ${Time}: CastingStarted_Kannkor_GuardianSphere started
        wait 20
        echo ${Time}: CastingStarted_Kannkor_GuardianSphere ended
    }
}
Kannkor
 
Posts: 361
Joined: 06 Nov 2013, 11:49

Return to Guides & Strats

Who is online

Users browsing this forum: No registered users and 3 guests