Targets

The Target class defines an object an action can act on. It uses a builder pattern to combine filters and checks. Targets validate parameters to actions at runtime allowing you to easily and safely discriminate an any type to something more specific. They are designed such that you can pass in any arbitrary Lua type into the Action’s parameters without runtime errors.

This how-to is going to use a simple Health component as an example, this does not ship with the engine but can be found in the tutorial.

Creating a basic target

To create a Target that requires certain components:

local myTarget = prism.Target(prism.components.Health, prism.components.Opaque)

You can add additional required components with the :with(...) function:

myTarget:with(prism.components.Collider, prism.components.Senses)

This ensures the target object must have the specified component(s).

Adding custom filters

You can add custom logic with :filter(). For example, to target only actors with less than half health:

myTarget:filter(function(level, owner, target)
   local health = target:get(prism.components.Health)
   return health and health.hp < (health.maxHP / 2)
end)

Limiting targets to a range

Restrict targets to those within a certain distance (in tiles):

myTarget:range(5)

This ensures the target is at most 5 tiles away from the actor performing the action.

Sensed targets

Require the target to be visible or otherwise sensed by the actor:

myTarget:sensed()

This uses the actor’s Senses component.

Line of sight

Require an unobstructed path from the actor to the target:

myTarget:los(collisionMask)

This checks tiles along a Bresenham line and fails if any cell blocks movement. For more info on collision masks see the Collision how-to!

Checking target types

Require the target to be an instance of a specific object class:

myTarget:isPrototype(prism.Actor)

Or check the target’s Lua type:

myTarget:isType("number")

Targeting outside the level

If your target is not part of the level (e.g. an inventory item):

myTarget:outsideLevel()

By default, targets are required to exist in the level.

Making targets optional

myTarget:optional()

This target will now validate even if it’s nil.

An example complex target

Suppose we want a target that:

  • Must be an Actor

  • Must have the Health component

  • Must be sensed

  • Must be within 3 tiles

  • Must be wounded (health < max)

local woundedEnemyTarget = prism.Target:new(prism.components.Health)
   :isPrototype(prism.Actor)
   :sensed()
   :range(3)
   :filter(function(level, owner, target)
      local health = target:expect(prism.components.Health)
      return health and health.current < health.max
   end)

We can chain our builder functions together like so to accomplish this. This can then be specified in an Action’s targets table to discriminate targets.