public MoveToPointAction(Unit.Unit unit, Grid.Grid.Node destination, Transform toMove = null, bool twoWayCollisions = false) { _destination = destination; _twoWayCollisions = twoWayCollisions; _unit = unit; _transformToMove = toMove ?? unit.transform; }
protected override State OnExecute(AgentContext context) { var occupant = context.Agent.GetComponent <GridOccupantBehaviour>(); if (occupant == null) { return(State.Failed); } Vector2Int newPos = Vector2Int.zero; var node = new Grid.Grid.Node(); bool noPointFound = true; while (noPointFound) { var direction = Random.Range(0, 2) == 1 ? Vector2Int.right : Vector2Int.up; var magnitude = Random.Range(0, 2) == 1 ? 1 : -1; newPos = occupant.CurrentNodeIdx + (magnitude * direction); if (occupant.Get().Value.TryGetNodeAt(newPos.x, newPos.y, ref node)) { noPointFound = node.Cost < 0; } } context.AgentBlackboard.Add <Grid.Grid.Node?>(outputKey, node); return(State.Succeeded); }
public override void Check(Blackboard agentBoard) { var col = Physics2D.OverlapBox(transform.position, _size, 0, targetLayers); if (col?.transform != null) { var node = new Grid.Grid.Node(); if (_grid.Get().Value.TryGetNodeAtWorldPosition(col.transform.position, ref node)) { _hasTarget = true; _agent.Target = col.transform; agentBoard.Add <Grid.Grid.Node?>(targetNodeKey, node); return; } } if (removeTargetOnExit) { _hasTarget = false; _agent.Target = null; agentBoard.Remove(targetNodeKey); } }
public override bool CanTarget(GridOccupant target, GridOccupant wielder, Grid.Grid grid) { var direction = target.Position - wielder.Position; if (!direction.IsCardinal() || direction.CardinalMagnitude() > 1) { return(false); } var node = new Grid.Grid.Node(); if (grid.TryGetNodeAt(wielder.Position, ref node)) { return(node.Occupants.Any(it => TargetTypes.Contains(it.Type))); } return(false); }
public void Fire(Unit.Unit unit, Grid.Grid.Node destination, Action onComplete) { _move.Move(unit, destination, () => { // spawn item?? // destroy if (pickupPrefab) { unit.QueueAction(new SpawnPickupAction(pickupPrefab, transform.position, item)); unit.QueueAction(new DestroyGameObjectAction(gameObject)); } else { _unit.Occupant.UpdateGrid(transform.position); } onComplete(); }); }
public virtual List <Grid.Grid.Node> FindEffectedNodes(GridOccupant wielder, Vector2Int direction, Grid.Grid grid) { var occupants = FindTargets(wielder, direction, grid); var nodes = new List <Grid.Grid.Node>(); foreach (var occupant in occupants) { if (nodes.FindIndex(it => it.Position == occupant.Position) > -1) { var n = new Grid.Grid.Node(); if (grid.TryGetNodeAt(occupant.Position, ref n)) { nodes.Add(n); } } } return(nodes); }
protected override State OnExecute(AgentContext context) { if (!context.AgentBlackboard.Contains(targetDirKey)) { return(State.Failed); } var dir = context.AgentBlackboard.RetrieveData <Vector2Int>(targetDirKey); var occupant = context.Agent.GetComponent <GridOccupantBehaviour>(); if (occupant == null) { return(State.Failed); } var agentNode = occupant.CurrentNode; if (agentNode == null) { return(State.Failed); } dir.x = MathUtils.ClampInt(dir.x, -1, 1); dir.y = MathUtils.ClampInt(dir.y, -1, 1); dir *= speed; dir.x += agentNode.Value.X; dir.y += agentNode.Value.Y; var moveNode = new Grid.Grid.Node(); if (occupant.Get().Value.TryGetNodeAt(dir.x, dir.y, ref moveNode)) { context.AgentBlackboard.Add <Grid.Grid.Node?>(outputKey, moveNode); return(State.Succeeded); } else { return(State.Failed); } }
// public override Grid.Grid.Node[] FindTargets(Grid.Grid.Node wielder, Grid.Grid grid) // { // var neighbours = grid.GetNeighbours(wielder); // // // todo(chris) consider optimising as this will be used by every mellee enemy on the grid // return neighbours.Where(node => node.Occupants.Any(it => it.Tags.Intersect(TargetTypes).Any())).ToArray(); // } // todo(chris) shouldnt this only find targets in direction?? public override GridOccupant[] FindTargets(GridOccupant wielder, Vector2Int direction, Grid.Grid grid) { var node = new Grid.Grid.Node(); if (grid.TryGetNodeAt(wielder.Position, ref node)) { var neighbours = grid.GetNeighbours(node); var targets = new List <GridOccupant>(); foreach (var neighbour in neighbours) { var validOccupants = neighbour.Occupants.Where(it => TargetTypes.Contains(it.Type)); targets.AddRange(validOccupants); } return(targets.ToArray()); } return(null); }
protected override State OnExecute(AgentContext context) { if (!context.AgentBlackboard.Contains(relativePosKey)) { return(State.Failed); } var relativePos = context.AgentBlackboard.RetrieveData <Vector2Int>(relativePosKey); var nodeIdx = context.Occupant.CurrentNodeIdx + relativePos; var node = new Grid.Grid.Node(); if (context.Occupant.Grid.TryGetNodeAt(nodeIdx.x, nodeIdx.y, ref node)) { context.AgentBlackboard.Add <Grid.Grid.Node?>(outputKey, node); return(State.Succeeded); } else { return(State.Failed); } }
public PathDetails CalculatePath(GridOccupant wielder, Vector2Int direction, Grid.Grid grid) { PathDetails path = new PathDetails { Travelled = new List <Grid.Grid.Node>(), IsLastNodeTarget = false }; var normalised = direction.CardinalNormalise(); var magnitude = projectile.Range; var node = new Grid.Grid.Node(); for (int i = 1; i <= magnitude; i++) { if (grid.TryGetNodeAt(wielder.Position + i * normalised, ref node)) { path.Travelled.Add(node); // if we have hit something that has a type then weve eiher hit something we cant move though // or weve hit our target if (node.Occupants.Any(it => it.Type != null)) { path.IsLastNodeTarget = node.Occupants.Any(it => it.Type != null && TargetTypes.Contains(it.Type)); break; } // todo(chris) add back in when we implement penetration // else // { // var targetOccupants = node.Occupants.Where(it => TargetTypes.Contains(it.Type)); // // var gridOccupants = targetOccupants as GridOccupant[] ?? targetOccupants.ToArray(); // // // occupant isnt a target so cant go through // if (gridOccupants.Length == 0) // { // break; // } // // path.Hits.Add(node); // // var penetrating = gridOccupants.Where(occupant => projectile.PenitrationTags.Contains(occupant.Type)); // // var penetratingArray = penetrating as GridOccupant[] ?? penetrating.ToArray(); // // // cant penetrate target to this will be as far as we go // if (penetratingArray.Length == 0) // { // break; // } // // // if we cant penetrate all then we are done // if (remainingDepth <= penetratingArray.Length) // { // break; // } // // // continue; // } } else { break; } } if (path.IsLastNodeTarget && path.Travelled.Count == 0) { path = new PathDetails { Travelled = new List <Grid.Grid.Node>(), IsLastNodeTarget = false }; } else { path.Travelled.RemoveAt(0); } return(path); }
private bool QueueActions(Vector3 position) { Grid.Grid.Node clickedNode = new Grid.Grid.Node(); var isClickedNodeValid = _unit.Occupant.Grid.TryGetNodeAtWorldPosition(position, ref clickedNode); Grid.Grid.Node myNode = new Grid.Grid.Node(); var isMyNodeValid = _unit.Occupant.Grid.TryGetNodeAtWorldPosition(transform.position, ref myNode); if (isMyNodeValid && isClickedNodeValid) { if (_isUsingBomb) { if (_inventory == null) { return(false); } var diff = clickedNode.Position - myNode.Position; if (!diff.IsCardinal()) { return(false); } AggregateSlot slot; if (!_inventory.RetrieveSlot(bombKey, out slot)) { return(false); } slot.Total -= 1; _inventory.UpdateSlot(bombKey, slot); _unit.QueueRange(bombChucker.Use(_unit.Occupant.Occupant, diff, _unit.Occupant.Grid)); return(true); } else if (_isUsingItem) { if (_item != null) { var direction = clickedNode.Position - _unit.Occupant.Occupant.Position; var actions = _item.Use(_unit.Occupant.Occupant, direction, _unit.Occupant.Grid); if (actions != null && actions.Count > 0) { _unit.QueueRange(actions); return(true); } } else { return(false); } } else { // attack var direction = clickedNode.Position - _unit.Occupant.Occupant.Position; var targets = mainWeapon.FindTargets(_unit.Occupant.Occupant, direction, _unit.Occupant.Grid); if (Array.Exists(targets, it => it.Position == clickedNode.Position)) { var actions = mainWeapon.Use(_unit.Occupant.Occupant, direction, _unit.Occupant.Grid); if (actions != null && actions.Count > 0) { _unit.QueueRange(actions); return(true); } } // move var path = _pathfinding.CalculatePath(transform.position, position); if (path != null && path.Count > 0) { var first = path[0]; _unit.QueueAction(new MoveToPointAction(_unit, first)); return(true); } } } return(false); }
public LaunchProjectileAction(GridOccupant wielder, Grid.Grid.Node endPoint, ProjectileBehaviour projectile) { _wielder = wielder; _endPoint = endPoint; _projectile = projectile; }
public override List <IUnitAction> Handle(PushWeaponEffect effect, GameObject wielder) { var actions = new List <IUnitAction>(); Vector2Int direction = GetPush(effect, wielder); if (direction == Vector2Int.zero) { Debug.Log($"{wielder.name} Tried To Push {name} (0, 0)!!"); return(actions); } var pos = _occupant.CurrentNodeIdx + direction; var node = new Grid.Grid.Node(); if (_occupant.Get().Value.TryGetNodeAt(pos.x, pos.y, ref node)) { // todo(chris) this doesnt really work with anything that isnt just in 1 direction actions.Add(new MoveToPointAction(_unit, node, twoWayCollisions: true)); } return(actions); // Vector2Int magnitudes = new Vector2Int(Mathf.Abs(direction.x), Mathf.Abs(direction.y)); // Vector2Int signs = new Vector2Int(Math.Sign(direction.x), Math.Sign(direction.y)); // // var pos = _occupant.CurrentNodeIdx; // // var step = Vector2Int.one; // // // step along push path one by one (including diagonals as 1) // // until we either collide with something or reach our final destination // while (magnitudes != Vector2Int.zero) // { // if (magnitudes.x < 1) // { // step.x = 0; // } // // if (magnitudes.y < 1) // { // step.y = 0; // } // // magnitudes.x = Mathf.Max(0, magnitudes.x - 1); // magnitudes.y = Mathf.Max(0, magnitudes.y - 1); // // var next = pos + signs * step; // // // var n = new Grid.Grid.Node(); // if (_occupant.Get().Value.TryGetNodeAt(next.x, next.y, ref n)) // { // var collider = n.Occupants.FirstOrDefault(ItObstructsMe); // if (collider != null) // { // ResolveCollision(actions, collider, n); // // break; // } // } // // pos = next; // } // // // var node = new Grid.Grid.Node(); // if (_occupant.Get().Value.TryGetNodeAt(pos.x, pos.y, ref node)) // { // // todo(chris) this doesnt really work with anything that isnt just in 1 direction // actions.Add(new MoveToPointAction(_unit, node)); // } // // return actions; }
private void ResolveCollision(List <IUnitAction> actions, GridOccupant collider, Grid.Grid.Node n) { // if i have on collision effects then run them actions.AddNullableRange(_collisionBehaviour?.CollideWith(collider, n)); // if the thing i bumped has collision effects then run them var collision = collider.OccupantGameObject.GetComponent <OnCollisionBehaviour>(); if (collision != null) { var myNode = _occupant.CurrentNode; if (myNode != null) { actions.AddNullableRange(collision.CollideWith(_occupant.Occupant, myNode.Value)); } } }