private bool CanMoveTo_Cardinal__CanOccupy(int targetX, int targetY, bool allowSurf, BlocksetBlockBehavior curBehavior, BlocksetBlockBehavior blockedTarget, bool checkElevation, byte curElevation) { // Get the x/y/map of the target block Map.GetXYMap(targetX, targetY, out int outX, out int outY, out Map outMap); Map.Layout.Block targetBlock = outMap.GetBlock_InBounds(outX, outY); // Check occupancy permission if ((targetBlock.Passage & LayoutBlockPassage.AllowOccupancy) == 0) { return(false); } // Check block behaviors BlocksetBlockBehavior targetBehavior = targetBlock.BlocksetBlock.Behavior; if ((!allowSurf && Overworld.IsSurfable(targetBehavior)) || targetBehavior == blockedTarget) { return(false); } // Check elevation byte targetElevations = targetBlock.Elevations; if (checkElevation && !ElevationCheck(curBehavior, targetBehavior, curElevation, targetElevations)) { return(false); } byte newElevation = Overworld.GetElevationIfMovedTo(curElevation, targetElevations); // Check if we can pass through objs at the position if (CollidesWithAny_InBounds(outMap, outX, outY, newElevation)) { return(false); } return(true); }
// Southwest/Southeast/Northwest/Northeast private bool CanMoveTo_Diagonal(int targetX, int targetY, bool allowSurf, LayoutBlockPassage neighbor1Passage, int neighbor1X, int neighbor1Y, LayoutBlockPassage neighbor2Passage, int neighbor2X, int neighbor2Y, BlocksetBlockBehavior blockedCurrentCardinal1, BlocksetBlockBehavior blockedCurrentCardinal2, BlocksetBlockBehavior blockedCurrentDiagonal, BlocksetBlockBehavior blockedTargetCardinal1, BlocksetBlockBehavior blockedTargetCardinal2, BlocksetBlockBehavior blockedTargetDiagonal, BlocksetBlockBehavior blockedNeighbor1, BlocksetBlockBehavior blockedNeighbor2) { // Current block - return false if we are blocked Position p = Pos; Map.Layout.Block curBlock = Map.GetBlock_InBounds(p.X, p.Y); BlocksetBlockBehavior curBehavior = curBlock.BlocksetBlock.Behavior; if (curBehavior == blockedCurrentCardinal1 || curBehavior == blockedCurrentCardinal2 || curBehavior == blockedCurrentDiagonal) { return(false); } // Target block - return false if we are blocked Map.GetXYMap(targetX, targetY, out int targetOutX, out int targetOutY, out Map targetOutMap); Map.Layout.Block targetBlock = targetOutMap.GetBlock_InBounds(targetOutX, targetOutY); if ((targetBlock.Passage & LayoutBlockPassage.AllowOccupancy) == 0) { return(false); } // Check block behaviors BlocksetBlockBehavior targetBehavior = targetBlock.BlocksetBlock.Behavior; if ((!allowSurf && Overworld.IsSurfable(targetBehavior)) || targetBehavior == blockedTargetCardinal1 || targetBehavior == blockedTargetCardinal2 || targetBehavior == blockedTargetDiagonal) { return(false); } // Check elevation byte curElevation = p.Elevation; byte targetElevations = targetBlock.Elevations; if (!ElevationCheck(curBehavior, targetBehavior, curElevation, targetElevations)) { return(false); } byte newElevation = Overworld.GetElevationIfMovedTo(curElevation, targetElevations); // Check if we can pass through objs at the position if (CollidesWithAny_InBounds(targetOutMap, targetOutX, targetOutY, newElevation)) { return(false); } // Target's neighbors - check if we can pass through them diagonally if (!CanPassThroughDiagonally(neighbor1X, neighbor1Y, curElevation, neighbor1Passage, blockedCurrentCardinal1, blockedTargetCardinal2, blockedNeighbor1) || !CanPassThroughDiagonally(neighbor2X, neighbor2Y, curElevation, neighbor2Passage, blockedTargetCardinal1, blockedCurrentCardinal2, blockedNeighbor2)) { return(false); } return(true); }
// West/East private bool CanMoveTo_Cardinal_ConsiderStairs(int targetX, int targetY, bool allowSurf, BlocksetBlockBehavior blockedCurrent, BlocksetBlockBehavior blockedTarget, BlocksetBlockBehavior upBehavior, BlocksetBlockBehavior downBehavior) { // Current block - return false if we are blocked Position p = Pos; Map.Layout.Block curBlock = Map.GetBlock_InBounds(p.X, p.Y); BlocksetBlockBehavior curBehavior = curBlock.BlocksetBlock.Behavior; if (curBehavior == blockedCurrent) { return(false); } // Stairs - check if we can go up a stair that's above our target Map.GetXYMap(targetX, targetY - 1, out int upStairX, out int upStairY, out Map upStairMap); Map.Layout.Block upStairBlock = upStairMap.GetBlock_InBounds(upStairX, upStairY); if ((upStairBlock.Passage & LayoutBlockPassage.AllowOccupancy) != 0) { BlocksetBlockBehavior upStairBehavior = upStairBlock.BlocksetBlock.Behavior; if (upStairBehavior == upBehavior) { // Check if we can pass through objs on the position byte newElevation = Overworld.GetElevationIfMovedTo(p.Elevation, upStairBlock.Elevations); if (CollidesWithAny_InBounds(upStairMap, upStairX, upStairY, newElevation)) { return(false); } return(true); } } bool canChangeElevation = false; // Stairs - If we are on a down stair, then we will be going to the block diagonally below us if (curBehavior == downBehavior) { canChangeElevation = true; targetY++; } else if (curBehavior == upBehavior) { canChangeElevation = true; } // Target block - return false if we are blocked if (!CanMoveTo_Cardinal__CanOccupy(targetX, targetY, allowSurf, curBehavior, blockedTarget, !canChangeElevation, p.Elevation)) { return(false); } return(true); }
private void ApplyMovement(FacingDirection facing) { switch (facing) { case FacingDirection.South: { Pos.Y++; break; } case FacingDirection.North: { Pos.Y--; break; } case FacingDirection.West: { Position p = Pos; Pos.X--; ApplyStairMovement(p, BlocksetBlockBehavior.Stair_W, BlocksetBlockBehavior.Stair_E); break; } case FacingDirection.East: { Position p = Pos; Pos.X++; ApplyStairMovement(p, BlocksetBlockBehavior.Stair_E, BlocksetBlockBehavior.Stair_W); break; } case FacingDirection.Southwest: { Pos.X--; Pos.Y++; MovementSpeed *= DiagonalMovementSpeedModifier; break; } case FacingDirection.Southeast: { Pos.X++; Pos.Y++; MovementSpeed *= DiagonalMovementSpeedModifier; break; } case FacingDirection.Northwest: { Pos.X--; Pos.Y--; MovementSpeed *= DiagonalMovementSpeedModifier; break; } case FacingDirection.Northeast: { Pos.X++; Pos.Y--; MovementSpeed *= DiagonalMovementSpeedModifier; break; } } Map curMap = Map; int newX = Pos.X; int newY = Pos.Y; Map.Layout.Block block = curMap.GetBlock_CrossMap(newX, newY, out int outX, out int outY, out Map map); Pos.Elevation = Overworld.GetElevationIfMovedTo(Pos.Elevation, block.Elevations); if (map == curMap) { return; } // Map crossing - Update Map, Pos, and PrevPos curMap.Objs.Remove(this); map.Objs.Add(this); Map = map; Pos.X = outX; Pos.Y = outY; PrevPos.X += outX - newX; PrevPos.Y += outY - newY; OnMapChanged(curMap, map); }