public Atrribute(AttributeFormat[] characterFormat, LengthType lengthType, AttributeMask[] attributeMask, short maxLength) { AttributeFormat = characterFormat; LengthType = lengthType; AttributeMask = attributeMask; MaxLength = maxLength; Length = MaxLength; }
public Atrribute(AttributeFormat[] attributeFormat, LengthType lengthType, AttributeMask[] attributeMask, short maxLength, short length) { AttributeFormat = attributeFormat; AttributeMask = attributeMask; LengthType = lengthType; MaxLength = maxLength; Length = lengthType != LengthType.FIXED ? length : maxLength; }
void IPathNode.GetVirtualNeighbours(DynamicArray <IPathNode> neighbours, AttributeMask requesterAttributes) { if (_virtualNeighbours == null) { return; } for (int i = 0; i < _virtualNeighbours.Count; i++) { var vn = _virtualNeighbours[i]; if (vn.isWalkable(requesterAttributes)) { neighbours.Add(vn); } } }
/// <summary> /// Determines if an active portal exists between two grids. /// </summary> /// <param name="first">The first grid</param> /// <param name="second">The second grid.</param> /// <param name="requesterAttributes">The attribute mask of the requester, i.e. the entity asking to use the portal.</param> /// <returns> /// <c>true</c> if at least one portal exists; otherwise <c>false</c> /// </returns> public bool PortalExists(IGrid first, IGrid second, AttributeMask requesterAttributes) { int portalCount = _portals.count; for (int i = 0; i < portalCount; i++) { var p = _portals[i]; if (p.enabled && p.IsUsableBy(requesterAttributes) && ((p.gridOne == first && p.gridTwo == second) || (p.gridOne == second && p.gridTwo == first))) { return(true); } } return(false); }
/// <summary> /// Gets the nearest walkable cell to a position. /// </summary> /// <param name="grid">The grid.</param> /// <param name="position">The position to initiate from.</param> /// <param name="inRelationTo">The position of approach.</param> /// <param name="requireWalkableFromPosition">Whether the cell to find must be accessible from the direction of <paramref name="position"/></param> /// <param name="maxCellDistance">The maximum cell distance to check.</param> /// <param name="requesterAttributes">The requester's attributes.</param> /// <returns>The first walkable cell in the neighbourhood of <paramref name="position"/> that is the closest to <paramref name="inRelationTo"/>. If no such cell is found, null is returned.</returns> public static Cell GetNearestWalkableCell(this IGrid grid, Vector3 position, Vector3 inRelationTo, bool requireWalkableFromPosition, int maxCellDistance, AttributeMask requesterAttributes) { var cell = grid.GetCell(position); if (cell == null) { return null; } if (cell.isWalkable(requesterAttributes)) { return cell; } int dist = 1; var candidates = new List<Cell>(); while (candidates.Count == 0 && dist <= maxCellDistance) { foreach (var c in grid.GetConcentricNeighbours(cell, dist++)) { if (requireWalkableFromPosition) { if (c.isWalkableFrom(cell, requesterAttributes)) { candidates.Add(c); } } else if (c.isWalkable(requesterAttributes)) { candidates.Add(c); } } } Cell winner = null; float lowestDist = float.MaxValue; for (int i = 0; i < candidates.Count; i++) { var distSqr = (candidates[i].position - inRelationTo).sqrMagnitude; if (distSqr < lowestDist) { winner = candidates[i]; lowestDist = distSqr; } } return winner; }
public static AttributeMask GetAttributeColors(Creature creature) { AttributeMask colorMask = 0; // defaults to debuffed - highlight masked above if (creature.Strength.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Strength; } if (creature.Endurance.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Endurance; } if (creature.Quickness.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Quickness; } if (creature.Coordination.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Coordination; } if (creature.Focus.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Focus; } if (creature.Self.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Self; } if (creature.Health.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Health; } if (creature.Stamina.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Stamina; } if (creature.Mana.ModifierType == ModifierType.Buffed) { colorMask |= AttributeMask.Mana; } return(colorMask); }
public static AttributeMask GetAttributeHighlights(Creature creature) { AttributeMask highlightMask = 0; if (creature.Strength.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Strength; } if (creature.Endurance.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Endurance; } if (creature.Quickness.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Quickness; } if (creature.Coordination.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Coordination; } if (creature.Focus.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Focus; } if (creature.Self.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Self; } if (creature.Health.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Health; } if (creature.Stamina.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Stamina; } if (creature.Mana.ModifierType != ModifierType.None) { highlightMask |= AttributeMask.Mana; } return(highlightMask); }
private void Initialize(string name, PortalType type, PortalDirection direction, Bounds portalOne, Bounds portalTwo, AttributeMask exclusiveTo, IPortalAction action) { _type = type; _direction = direction; _exclusiveTo = exclusiveTo; _portalOneBounds = portalOne; _portalTwoBounds = portalTwo; _cellOne = new PortalCell(this, false, action); _cellTwo = new PortalCell(this, _direction == PortalDirection.Oneway, action); _gridOne = _cellOne.Initialize(_cellTwo, portalOne); _gridTwo = _cellTwo.Initialize(_cellOne, portalTwo); if (_gridOne == null || _gridTwo == null) { throw new ArgumentException("A grid portal has been placed with one or more of its portals outside a grid. Portals must be on a grid."); } _name = GridManager.instance.RegisterPortal(name, this); }
/// <summary> /// Called when a request is about to be processed. /// </summary> /// <param name="start">The start node.</param> protected override void OnStart(IPathNode start) { _openSet.Clear(); //Reset all g's on all nodes marking them not expanded _expandedSet.Apply(c => c.g = 0); _expandedSet.Clear(); _closestNode = start; //Initialize and add the start node. Since no expanded set is used start g must be initialized to a small > 0 value to mark it as expanded //Since the start node will never reenter the open set, there is no need to initialize the h and f values. start.g = 1; start.h = this.costProvider.GetHeuristic(start, this.goal); start.predecessor = null; _openSet.Add(start); _expandedSet.Add(start); _unitProps = this.currentRequest.requesterProperties; _unitAttributes = _unitProps.attributes; _preventDiagonalMoves = this.currentRequest.pathFinderOptions.preventDiagonalMoves; _cutCorners = this.currentRequest.pathFinderOptions.allowCornerCutting; }
public void Unpack(BinaryReader reader) { Flags = reader.ReadUInt32(); Health = reader.ReadUInt32(); HealthMax = reader.ReadUInt32(); if ((Flags & 0x00000008) != 0) { Strength = reader.ReadUInt32(); Endurance = reader.ReadUInt32(); Quickness = reader.ReadUInt32(); Coordination = reader.ReadUInt32(); Focus = reader.ReadUInt32(); Self = reader.ReadUInt32(); Stamina = reader.ReadUInt32(); Mana = reader.ReadUInt32(); StaminaMax = reader.ReadUInt32(); ManaMax = reader.ReadUInt32(); } if ((Flags & 0x00000001) != 0) { AttrHighlight = (AttributeMask)reader.ReadUInt16(); AttrColor = (AttributeMask)reader.ReadUInt16(); } }
/// <summary> /// Creates a GridPortal instance. /// </summary> /// <param name="name">The name.</param> /// <param name="type">The type of the portal.</param> /// <param name="direction">The direction of the portal.</param> /// <param name="portalOne">The bounds of the first portal.</param> /// <param name="portalTwo">The bounds of the second portal.</param> /// <param name="exclusiveTo">The attribute mask to indicate if this portal is exclusive to (only available to) certain units.</param> /// <param name="action">The action that handles moving between portals.</param> /// <returns>The portal instance</returns> public static GridPortal Create(string name, PortalType type, PortalDirection direction, Bounds portalOne, Bounds portalTwo, AttributeMask exclusiveTo, IPortalAction action) { var p = new GridPortal(); p.Initialize(name, type, direction, portalOne, portalTwo, exclusiveTo, action); return p; }
/// <summary> /// Determines whether the cell is walkable. /// </summary> /// <param name="mask">The attribute mask used to determine walk-ability.</param> /// <returns> /// <c>true</c> if the cell is walkable, otherwise <c>false</c> /// </returns> public bool isWalkable(AttributeMask mask) { if (_permanentlyBlocked) { return false; } if (mask == AttributeMask.None) { return (_blockMask == AttributeMask.None); } return (_blockMask & mask) != mask; }
/// <summary> /// Creates a GridPortal instance. /// </summary> /// <param name="name">The name.</param> /// <param name="type">The type of the portal.</param> /// <param name="portalOne">The bounds of the first portal.</param> /// <param name="portalTwo">The bounds of the second portal.</param> /// <param name="exclusiveTo">The attribute mask to indicate if this portal is exclusive to (only available to) certain units.</param> /// <param name="action">The action that handles moving between portals.</param> /// <returns>The portal instance</returns> public static GridPortal Create(string name, PortalType type, Bounds portalOne, Bounds portalTwo, AttributeMask exclusiveTo, IPortalAction action) { return Create(name, type, PortalDirection.Twoway, portalOne, portalTwo, exclusiveTo, action); }
void IPathNode.GetWalkableNeighbours(DynamicArray<IPathNode> neighbours, AttributeMask requesterAttributes, bool cornerCuttingAllowed, bool preventDiagonalMoves) { var destinationNodes = _partner._neighbourNodes; var nodeCount = destinationNodes.Length; for (int i = 0; i < nodeCount; i++) { if (destinationNodes[i].isWalkable(requesterAttributes)) { neighbours.Add(destinationNodes[i]); } } }
/// <summary> /// Determines whether the cell is walkable. /// </summary> /// <param name="mask">The attribute mask used to determine walk-ability.</param> /// <returns> /// <c>true</c> if the cell is walkable, otherwise <c>false</c> /// </returns> public bool isWalkable(AttributeMask mask) { return _parentPortal.IsUsableBy(mask); }
bool IGridCell.isWalkableFrom(NeighbourPosition pos, AttributeMask mask) { return _parentPortal.IsUsableBy(mask); }
bool IGridCell.isWalkableFromAllDirections(AttributeMask mask) { return isWalkable(mask); }
/// <summary> /// Gets the nearest walkable cell on the specified perimeter. /// </summary> /// <param name="position">The reference position.</param> /// <param name="perimeter">The perimeter to check.</param> /// <param name="requesterAttributes">The requester attributes.</param> /// <param name="adjustPositionToPerimiter">if set to <c>true</c> <paramref name="position" /> will be adjusted to be on the perimeter (if it is not already).</param> /// <returns>The nearest walkable perimeter cell</returns> public Cell GetNearestWalkablePerimeterCell(Vector3 position, Vector3 perimeter, AttributeMask requesterAttributes, bool adjustPositionToPerimiter) { //Adjust the cell to the perimeter and within bounds if (adjustPositionToPerimiter) { if (perimeter.x != 0) { position.x = GetPerimeterEdge(perimeter, true); var dzb = this.bottom.edgeMid; var dzf = this.top.edgeMid; if (position.z < dzb) { position.z = dzb; } else if (position.z > dzf) { position.z = dzf; } } else if (perimeter.z != 0) { position.z = GetPerimeterEdge(perimeter, true); var dxl = this.left.edgeMid; var dxr = this.right.edgeMid; if (position.x < dxl) { position.x = dxl; } else if (position.x > dxr) { position.x = dxr; } } } //If this is already the nearest walkable cell return it var c = GetCell(position); if (c == null) { return(null); } if (c.isWalkable(requesterAttributes)) { return(c); } //Traverse along the perimeter to find the closet walkable cell if (perimeter.x != 0) { return(TraversePerimeterX(c, 1, requesterAttributes)); } return(TraversePerimeterZ(c, 1, requesterAttributes)); }
/// <summary> /// Called when attributes changed. /// </summary> /// <param name="previous">The previous attributes, before the change.</param> protected virtual void OnAttributesChanged(AttributeMask previous) { }
static extern void pushAttrib(AttributeMask mask);
public void PushAttrib(AttributeMask mask) => pushAttrib(mask);
/// <summary> /// Determines if an active portal exists between two grids. /// </summary> /// <param name="first">The first grid</param> /// <param name="second">The second grid.</param> /// <param name="requesterAttributes">The attribute mask of the requester, i.e. the entity asking to use the portal.</param> /// <returns> /// <c>true</c> if at least one portal exists; otherwise <c>false</c> /// </returns> public bool PortalExists(IGrid first, IGrid second, AttributeMask requesterAttributes) { int portalCount = _portals.count; for (int i = 0; i < portalCount; i++) { var p = _portals[i]; if (p.enabled && p.IsUsableBy(requesterAttributes) && ((p.gridOne == first && p.gridTwo == second) || (p.gridOne == second && p.gridTwo == first))) { return true; } } return false; }
private bool ValidateGoalNeighbour(AttributeMask requesterAttributes, int dx, int dz) { var c = _goal.GetNeighbour(dx, dz); return ((c == null) || c.isWalkableFrom(_goal, requesterAttributes)); }
internal bool IsUsableBy(AttributeMask requesterAttributes) { if (_exclusiveTo == AttributeMask.None) { return true; } return (_exclusiveTo & requesterAttributes) > 0; }
/// <summary> /// Determines whether the cell is walkable. /// </summary> /// <param name="mask">The attribute mask used to determine walk-ability.</param> /// <returns> /// <c>true</c> if the cell is walkable, otherwise <c>false</c> /// </returns> public bool isWalkable(AttributeMask mask) { return(_parentPortal.IsUsableBy(mask)); }
/// <summary> /// Gets the walkable neighbours. /// </summary> /// <param name="grid">The grid</param> /// <param name="c">The cell whose walkable neighbours to return.</param> /// <param name="requesterAttributes">The attributes of the requesting unit</param> /// <param name="excludeCornerCutting">if set to <c>true</c> otherwise walkable neighbours on the diagonal that would cause a move from it to the current cell to cut a corner are excluded (deemed not walkable).</param> /// <returns>The walkable neighbours to the referenced cell.</returns> public static IEnumerable<Cell> GetWalkableNeighbours(this IGrid grid, IGridCell c, AttributeMask requesterAttributes, bool excludeCornerCutting) { Cell n; //Straight move neighbours bool uw = grid.TryGetWalkableNeighbour(c, 0, 1, requesterAttributes, out n); if (uw) { yield return n; } bool dw = grid.TryGetWalkableNeighbour(c, 0, -1, requesterAttributes, out n); if (dw) { yield return n; } bool rw = grid.TryGetWalkableNeighbour(c, 1, 0, requesterAttributes, out n); if (rw) { yield return n; } bool lw = grid.TryGetWalkableNeighbour(c, -1, 0, requesterAttributes, out n); if (lw) { yield return n; } //Diagonal neighbours. First determine if they are unwalkable as a consequence of their straight neighbours bool urw, drw, dlw, ulw; if (excludeCornerCutting) { urw = uw && rw; drw = dw && rw; dlw = dw && lw; ulw = uw && lw; } else { urw = uw || rw; drw = dw || rw; dlw = dw || lw; ulw = uw || lw; } urw = urw && grid.TryGetWalkableNeighbour(c, 1, 1, requesterAttributes, out n); if (urw) { yield return n; } drw = drw && grid.TryGetWalkableNeighbour(c, 1, -1, requesterAttributes, out n); if (drw) { yield return n; } dlw = dlw && grid.TryGetWalkableNeighbour(c, -1, -1, requesterAttributes, out n); if (dlw) { yield return n; } ulw = ulw && grid.TryGetWalkableNeighbour(c, -1, 1, requesterAttributes, out n); if (ulw) { yield return n; } }
bool IGridCell.isWalkableFrom(IGridCell neighbour, AttributeMask mask) { return _parentPortal.IsUsableBy(mask); }
/// <summary> /// Creates a GridPortal instance. /// </summary> /// <param name="name">The name.</param> /// <param name="type">The type of the portal.</param> /// <param name="portalOne">The bounds of the first portal.</param> /// <param name="portalTwo">The bounds of the second portal.</param> /// <param name="exclusiveTo">The attribute mask to indicate if this portal is exclusive to (only available to) certain units.</param> /// <param name="action">The action that handles moving between portals.</param> /// <returns>The portal instance</returns> public static GridPortal Create(string name, PortalType type, Bounds portalOne, Bounds portalTwo, AttributeMask exclusiveTo, IPortalAction action) { return(Create(name, type, PortalDirection.Twoway, portalOne, portalTwo, exclusiveTo, action)); }
void IPathNode.GetVirtualNeighbours(DynamicArray<IPathNode> neighbours, AttributeMask requesterAttributes) { /* Currently not supported */ }
/// <summary> /// Creates a GridPortal instance. /// </summary> /// <param name="name">The name.</param> /// <param name="type">The type of the portal.</param> /// <param name="direction">The direction of the portal.</param> /// <param name="portalOne">The bounds of the first portal.</param> /// <param name="portalTwo">The bounds of the second portal.</param> /// <param name="exclusiveTo">The attribute mask to indicate if this portal is exclusive to (only available to) certain units.</param> /// <param name="action">The action that handles moving between portals.</param> /// <returns>The portal instance</returns> public static GridPortal Create(string name, PortalType type, PortalDirection direction, Bounds portalOne, Bounds portalTwo, AttributeMask exclusiveTo, IPortalAction action) { var p = new GridPortal(); p.Initialize(name, type, direction, portalOne, portalTwo, exclusiveTo, action); return(p); }
bool IPathNode.TryGetWalkableNeighbour(int dx, int dz, AttributeMask requesterAttributes, DynamicArray<IPathNode> neighbours) { return false; }
/// <summary> /// Initializes a new instance of the <see cref="ManualDynamicObstacle"/> class. /// </summary> /// <param name="coverage">The coverage area.</param> /// <param name="exceptions">The exceptions mask controlling which units ignore this obstacle.</param> public ManualDynamicObstacle(Bounds coverage, AttributeMask exceptions) { _bounds = coverage; this.exceptionsMask = exceptions; }
void IPathNode.GetVirtualNeighbours(DynamicArray<IPathNode> neighbours, AttributeMask requesterAttributes) { if (_virtualNeighbours == null) { return; } for (int i = 0; i < _virtualNeighbours.Count; i++) { var vn = _virtualNeighbours[i]; if (vn.isWalkable(requesterAttributes)) { neighbours.Add(vn); } } }
/// <summary> /// Determines whether the specified entity has all of the specified attributes. /// </summary> /// <param name="entity">The entity.</param> /// <param name="attributes">The attributes to check for.</param> /// <returns><c>true</c> if the entity has all of the specified attributes, otherwise, <c>false</c></returns> public static bool HasAll(this IHaveAttributes entity, AttributeMask attributes) { return((entity.attributes & attributes) == attributes); }
/// <summary> /// Called when attributes changed. /// </summary> /// <param name="previous">The previous attributes, before the change.</param> protected override void OnAttributesChanged(AttributeMask previous) { GameServices.messageBus.Post(new MessageAttributesChanged(this)); }
void IPathNode.GetVirtualNeighbours(DynamicArray <IPathNode> neighbours, AttributeMask requesterAttributes) { /* Currently not supported */ }
private static bool CanReducePath(IPositioned point1, IPositioned point3, AttributeMask requesterAttributes, float requesterRadius, CellMatrix matrix) { Vector3 p1; Vector3 p3; //Assign the points so we start with the point with the lowest x-value to simplify things if (point1.position.x > point3.position.x) { p1 = point3.position; p3 = point1.position; } else { p1 = point1.position; p3 = point3.position; } var tan = Tangents.Create(p1, p3, requesterRadius); var incZ = tan.slopeDir; var cellSize = matrix.cellSize; var halfCell = cellSize / 2.0f; //Adjust the start and end cells to possibly include their immediate neighbour if the unit's radius crossed said boundary. var radiusAdjust = new Vector3(requesterRadius, 0.0f, requesterRadius * incZ); var startCell = matrix.GetCell(p1 - radiusAdjust); if (startCell == null) { startCell = matrix.GetCell(p1); } var endCell = matrix.GetCell(p3 + radiusAdjust); if (endCell == null) { endCell = matrix.GetCell(p3); } //We want x to end up on cell boundaries, the first of which is this far from the first points position var xAdj = p1.x + (startCell.position.x - p1.x) + halfCell; //We want to adjust z so that we correctly count impacted cells, this adjusts z so it starts at the bottom boundary of the first cell (for purposes of calculation) var zAdj = p1.z - (halfCell + ((p1.z - startCell.position.z) * incZ)); //The movement across the x-axis float deltaX = 0.0f; var cellMatrix = matrix.rawMatrix; int indexX = 0; for (int x = startCell.matrixPosX; x <= endCell.matrixPosX; x++) { //So instead of just checking all cells in the bounding rect defined by the two cells p1 and p3, //we limit it to the cells immediately surrounding the proposed line (tangents), including enough cells that we ensure the unit will be able to pass through, //at the extreme routes between the two cells (i.e top corner to top corner and bottom corner to bottom corner int startZ; int endZ; //If the tangents are horizontal or vertical z range is obvious if (tan.isAxisAligned) { startZ = startCell.matrixPosZ; endZ = endCell.matrixPosZ + incZ; } else { if (indexX == 0) { startZ = startCell.matrixPosZ; } else { var startCellsPassed = Mathf.FloorToInt((tan.LowTangent(deltaX) - zAdj) / cellSize) * incZ; startZ = LimitStart( startCell.matrixPosZ + startCellsPassed, startCell.matrixPosZ, incZ); } //The movement this step will perform across the x-axis deltaX = xAdj + (indexX * cellSize); var endCellsIntercepted = Mathf.FloorToInt((tan.HighTangent(deltaX) - zAdj) / cellSize) * incZ; endZ = LimitEnd( startCell.matrixPosZ + endCellsIntercepted, endCell.matrixPosZ, incZ) + incZ; } indexX++; for (int z = startZ; z != endZ; z += incZ) { var intermediary = cellMatrix[x, z]; if (!intermediary.isWalkableFrom(startCell, requesterAttributes)) { return false; } } } return true; }