Interest
A shared map of points of interest with a strength each, and Best, which picks where an
agent should look next. Exposed as VluxyAI.Interest. Make one per map, fill it from your
level (hiding spots, doors, rooms, the generator), raise points from events, and give
enemies a States.Roam over it or ask Best from a state of your own.
local interest = VluxyAI.Interest.new({ Decay = 0.1, Visited = 30 })
for _, locker in CollectionService:GetTagged("Locker") do
interest:Add(locker, { Position = locker.Position, Strength = 1, Tags = { "Hiding" } })
end
noises:Connect(function(position, loudness)
interest:BumpNear(position, 15, loudness or 1) -- a noise makes nearby spots worth a look
end)
Search = VluxyAI.States.Roam({ Interest = interest, Then = "Patrol", Duration = 40 }),
An enemy never learns where a player is from this; it learns where a player would plausibly
be. Pair it with Sight's PredictedPosition for "they went that way" and the enemy hunts
like something that has to look.
Types
Clue
interface Clue {Radius: number--
Studs the clue spreads; points further away are not raised. 0 makes the kind no clue at all.
Heat: number--
How much it raises a point at its centre, less with distance, whatever the noise's loudness.
}InterestPoint
interface InterestPoint {Id: any--
What it was added under.
Position: Vector3Strength: number--
The current strength, after decay.
Base: number--
What it drifts back to.
Tags: {string}?--
For Best to filter on.
}Functions
new
Types
interface InterestOptions {Decay: number?--
Strength drifts back toward a point's base at this much per second. Default 0.1.
Visited: number?--
Seconds a point stays uninteresting to an agent that just looked there. Default 30.
Key: string?--
The agent.Data key visits are remembered under. Default "Interest".
NoiseRadius: number?--
How far Interest:Heard spreads a noise whose kind has no entry in Clues. Default 24.
NoiseHeat: number?--
How much such a noise raises the points at its centre, per unit of loudness. Default 2.
Clues: {[string]: Clue}?--
How each kind of noise counts, by the kind passed to [Interest:Heard]: a door or an alarm is a big clue, a footstep none at all. Default {}.
}Add
Interest.Add(id: any,--
A part, a name, anything usable as a key. Adding it again replaces it.
options: InterestPointOptions) → ()Types
interface InterestPointOptions {Position: Vector3Strength: number?--
The base strength. Default 1.
Tags: {string}?--
Labels such as "Hiding", "Door", "Room".
}Errors
| Type | Description |
|---|---|
| string | No Vector3 `Position`. |
Remove
Get
Points
Interest.Points(self: Interest) → {InterestPoint}--
Every point, strengths as of now, in no particular order.
Bump
Interest.Bump(id: any,amount: number--
Added to the strength; it decays back toward the base. Negative lowers it.
) → ()BumpNear
Interest.BumpNear(radius: number,amount: number--
Added in full at the position, fading to nothing at radius.
) → number--
How many points were raised.
A noise, a slammed door, a light: everything near it becomes worth a look.
Heard
Interest.Heard(loudness: number?,--
Default 1; only used for a kind with no entry in Clues.
kind: string?--
What it was: "Door", "Running", "Alarm", "Footstep".
) → number--
How many points it raised.
A noise as a clue: raises the points near it by what kind of noise it was (the Clues option),
or by its loudness when the kind has no entry. Connect it to the signal your Hearing senses
listen to, and every noise the players make becomes somewhere worth a look, weighted the way
your game decides: a door opening counts, a footstep does not.
AddAll
Interest.AddAll() → number--
How many points were added. Their ids are their indices in positions.
Adds a point at each position, all with the same base strength and tags, leaving out any
Skip returns true for (a safe room, say: Skip = VluxyAI.SafeAreas.Contains).
Set
Interest.Set() → ()Visit
Marks the point as looked at by this agent, so Best passes over it for Visited seconds.
SinceVisit
Interest.SinceVisit() → number--
Seconds since this agent last visited the point, math.huge if never.
Best
Interest.Best() → (number--
Its score in [0, 1].
)Types
interface BestOptions {Range: number?--
Studs at which distance alone scores a point to nothing. Default 120.
Tags: {string}?--
Only points carrying one of these tags.
Exclude: {any}?--
Point ids to leave out (the one the agent is standing at, say).
IgnoreStrength: boolean?--
Score every point as if equally interesting, so only nearness, visits and Considerations count: a pick that does not follow the clues. Default false.
}
Scores every point by strength (against the strongest) and nearness (linear to Range),
multiplied, then any Considerations given, and returns the best. A point this agent
visited within Visited seconds scores 0, so a roaming enemy spreads its search instead of
circling one spot.
Destroy
Forgets every point. Agents keep their visit times in their own Data.