Difference between revisions of "Ai Overview"

From Legends of Aria Admin and Modding Wiki
Jump to: navigation, search
Line 38: Line 38:
 
AddView("chaseRange",SearchMobileInRange(chaseViewRange,false,false,true))
 
AddView("chaseRange",SearchMobileInRange(chaseViewRange,false,false,true))
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
And at the end of the file we find the Event Handler in case some Mobile enters that range and triggered the view:
 +
<syntaxhighlight lang="lua">
 +
--On the target coming into range
 +
RegisterEventHandler(EventType.EnterView, "chaseRange",
 +
    function (objRef)
 +
        HandleMobEnterView(objRef,false)
 +
    end)
 +
</syntaxhighlight>
 +
 +
So it seems that <code>HandleMobEnterView</code> is our canditate doing the real stuff. Below is a shortened vgersion stripped off from comments and DebugMessages:
 +
<syntaxhighlight lang="lua">
 +
function HandleMobEnterView(mobileObj,ignoreVision,forceAttack)
 +
    if (ignoreVision == nil) then ignoreVision = false end
 +
    if not(AI.IsActive()) then return end
 +
    if (not AI.IsValidTarget(mobileObj)) then
 +
        return
 +
    end
 +
    local isFriend = IsFriend(mobileObj)
 +
    if (forceAttack) then
 +
        isFriend = false
 +
    end
 +
    if (not isFriend) then
 +
        AI.AddToAggroList(mobileObj,2)
 +
        if (forceAttack) then
 +
            this:SendMessage("AttackEnemy",mobileObj,true) 
 +
        else
 +
            AI.StateMachine.ChangeState("Alert") 
 +
        end       
 +
    end
 +
end
 +
</syntaxhighlight>
 +
 +
  
  

Revision as of 20:31, 1 November 2016

Ai Overview

This article is about helping to understand how the Ai in Shards Online works.

Some Basics:

The Artificial Intelligence for NPCs follows a general Ai Principle which is the cycle of

  • Sense
  • Think
  • Act

The model of implementation is a Finite State Machine(FSM). [Wikipedia Article Finite State Machine]

To understand how an FSM would transition from one state (e.g. "Idle") to another state (e.g. "Combat") in Shards Online (SO) it is important to understand the first step: "Sense".

How does an NPC sense the world?

There are several ways:

Messages
Messages using the Sendmessage function tell the NPC someone or something sent it a message. To understand Messages the NPC needs to have the appropriate EventHandlers.
Views
Views are added to objects by using the AddView function. A view is basically a search function performed on a configurably regular basis which triggers an event if something matching that search function enters its configured range. Mobiles can carry around views with them.
FindObjects
The FindObjects function can be executed whenever an NPC needs to find something.

Each of these sensing mechanisms can call functions provided by the core Ai which lives in base_ai_state_machine.lua.

SchedulePulse()
AI.StateMachine.Init(initialState)
AI.StateMachine.Shutdown()
AI.StateMachine.ChangeState(newState)
AI.StateMachine.ChangeSubState(newState)
AI.StateMachine.EndSubStates(success,reason)
HandleAiPulse()

Especially important is function AI.StateMachine.ChangeState(newState) which could be called when something happens our NPC needs to react to, e.g. a wolf entering the perception range of a turkey.

In base_ai_mob.lua we find the following line of code in the initialization part:

AddView("chaseRange",SearchMobileInRange(chaseViewRange,false,false,true))

And at the end of the file we find the Event Handler in case some Mobile enters that range and triggered the view:

--On the target coming into range
RegisterEventHandler(EventType.EnterView, "chaseRange", 
    function (objRef)
        HandleMobEnterView(objRef,false)
    end)

So it seems that HandleMobEnterView is our canditate doing the real stuff. Below is a shortened vgersion stripped off from comments and DebugMessages:

function HandleMobEnterView(mobileObj,ignoreVision,forceAttack)
    if (ignoreVision == nil) then ignoreVision = false end
    if not(AI.IsActive()) then return end
    if (not AI.IsValidTarget(mobileObj)) then 
        return 
    end
    local isFriend = IsFriend(mobileObj)
    if (forceAttack) then
        isFriend = false
    end
    if (not isFriend) then
        AI.AddToAggroList(mobileObj,2)
        if (forceAttack) then
            this:SendMessage("AttackEnemy",mobileObj,true)  
        else
            AI.StateMachine.ChangeState("Alert")   
        end         
    end
end