With fog-of-war, lighting, and scrying implemented, determining line of sight becomes just a check:
- Is there a static obstacle (box2d)?
- Are they visible (not hidden or in fog of war)?
Spells and autoattacks silently failing isn’t a great UX. Mages should move into position
after the AttackCommand
or CastCommand
has been given.
Since I already have a MoveCommand
, I wrote a moveIntoRange
function for my SpellCastSystem
if the target was out of range or move within line of sight.
if (isTargetOutbounds(wantsToCast)) {
moveIntoRange(wantsToCast, castCommand);
}
// moveIntoRange just sends a MoveCommand to the target.
// This could cause issues if pathfinding isn't possible to that location
void moveIntoRange(Entity wantsToCast, CastCommand castCommand) {
Position target = Comps.position.get(castCommand.target);
wantsToCast.add(
createComponent(MoveCommand.class).setup(target.x, target.y)
);
}
However, for dynamic targets (like other entities), the MoveCommand
wouldn’t
update position until they arrived at the wrong location.
Spamming MoveCommands
seemed like a bad idea given how expensive pathfinding could be,
so I added a UpdatePathWithTolerance
function that reissued a new MoveCommand
when they drifted out of a static tolerance of ~0.5m.
As a bonus, I created an AutoTargetSystem
that issues AttackCommand
when an enemy enters line of sight.
So now boarding is the survival horror it was always meant to be.