public override void Apply(T map) { Grid.LocTest checkGround = (Loc testLoc) => { if (!Collision.InBounds(map.Width, map.Height, testLoc)) { return(false); } return(map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(testLoc)); }; Grid.LocTest checkBlock = (Loc testLoc) => { if (!Collision.InBounds(map.Width, map.Height, testLoc)) { return(false); } return(map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.WallTerrain)); }; List <LocRay4> rays = Detection.DetectWalls(((IViewPlaceableGenContext <MapGenEntrance>)map).GetLoc(0), new Rect(0, 0, map.Width, map.Height), checkBlock, checkGround); EffectTile effect = new EffectTile(LockedTile, true); TileListState state = new TileListState(); effect.TileStates.Set(state); List <Loc> freeTiles = new List <Loc>(); LocRay4? ray = PlaceRoom(map, rays, effect, freeTiles); if (ray != null) { PlaceEntities(map, freeTiles); } }
private void fillStroke(CanvasStroke <EffectTile> stroke) { if (!Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, stroke.CoveredRect.Start)) { return; } EffectTile tile = ZoneManager.Instance.CurrentMap.Tiles[stroke.CoveredRect.Start.X][stroke.CoveredRect.Start.Y].Effect; Dictionary <Loc, EffectTile> brush = new Dictionary <Loc, EffectTile>(); EffectTile brushTile = stroke.GetBrush(stroke.CoveredRect.Start); RogueElements.Grid.FloodFill(new Rect(0, 0, ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height), (Loc testLoc) => { if (brush.ContainsKey(testLoc)) { return(true); } return(tile.ID != ZoneManager.Instance.CurrentMap.Tiles[testLoc.X][testLoc.Y].Effect.ID); }, (Loc testLoc) => { return(true); }, (Loc testLoc) => { brush[testLoc] = new EffectTile(brushTile, testLoc); }, stroke.CoveredRect.Start); DiagManager.Instance.DevEditor.MapEditor.Edits.Apply(new DrawTileUndo(brush)); }
public override void DrawOnMap(T map) { if (this.Draw.Width != this.Tiles.Length || this.Draw.Height != this.Tiles[0].Length) { this.DrawMapDefault(map); return; } base.DrawOnMap(map); //create new bosses from the spawns, adjusting their locations MobSpawnState mobSpawnState = new MobSpawnState(); foreach (MobSpawn spawn in Bosses) { MobSpawn newSpawn = spawn.Copy(); MobSpawnLoc setLoc = null; foreach (MobSpawnExtra extra in newSpawn.SpawnFeatures) { MobSpawnLoc extraLoc = extra as MobSpawnLoc; if (extraLoc != null) { setLoc = extraLoc; break; } } if (setLoc != null) { setLoc.Loc = setLoc.Loc + this.Draw.Start; } else { setLoc = new MobSpawnLoc(this.Draw.Center); newSpawn.SpawnFeatures.Add(setLoc); } mobSpawnState.Spawns.Add(newSpawn); } ////place the boss bounds here //CheckIntrudeBoundsEvent trapZone = new CheckIntrudeBoundsEvent(); //trapZone.Bounds = new Rect(Trigger.Start + new Loc(this.Draw.Start), Trigger.Size); //{ // LockdownMapEvent lockdown = new LockdownMapEvent(); // lockdown.Bounds = new Rect(this.Draw.Start - new Loc(1), this.Draw.Size + new Loc(2)); // trapZone.Effects.Add(lockdown); // trapZone.Effects.Add(new BossSpawnEvent(this.Draw, mobSpawns.ToArray())); //} //map.CheckEvents.Add(trapZone); EffectTile newEffect = new EffectTile(TriggerTile, true, Trigger + this.Draw.Start); newEffect.TileStates.Set(mobSpawnState); newEffect.TileStates.Set(new BoundsState(new Rect(this.Draw.Start - new Loc(1), this.Draw.Size + new Loc(2)))); newEffect.TileStates.Set(new SongState(Song)); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(Trigger + this.Draw.Start, newEffect); }
public float CalculateCost(Node currentNode, Node targetNode, Character character) { float cost = currentNode.CostSoFar + _basicCost; if (targetNode.HasEffect) { EffectTile effect = targetNode.GetEffect(); if (effect.Type == EffectTileType.Damage) { /* * maxHealth - damage * > 80% = +30 * 50-80% = +50 * 0-50% = +100 */ float hpPercent = (character.Properties.CurrentHealth - effect.Value) / character.Properties.Health; if (hpPercent > 0.8f) { cost += 30; } else if (hpPercent < 0.5f) { cost += 50; } else { cost += 100; } } else if (effect.Type == EffectTileType.Heal) { /* * cost reduce based on current character's health * 100% = 0 * >80% = -2 * 50-80% = -4 * <50% = -6 */ if (character.Properties.CurrentHealth != character.Properties.Health) { float hpPercent = character.Properties.CurrentHealth / character.Properties.Health; if (hpPercent > 0.8f) { cost -= 2; } else if (hpPercent < 0.5f) { cost -= 6; } else { cost -= 4; } } } } return(cost); }
protected override void PlaceBorders(T map, Dictionary <Loc, SealType> sealList) { List <Loc> keyList = new List <Loc>(); List <Loc> lockList = new List <Loc>(); foreach (Loc loc in sealList.Keys) { switch (sealList[loc]) { //lay down the blocks case SealType.Blocked: map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); break; case SealType.Locked: lockList.Add(loc); break; case SealType.Key: keyList.Add(loc); break; } } //choose the key tile int keyIndex = map.Rand.Next(keyList.Count - 1); Loc keyLoc = keyList[keyIndex]; keyList.RemoveAt(keyIndex); lockList.AddRange(keyList); //seal the tiles that are gated foreach (Loc loc in lockList) { map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); EffectTile newEffect = new EffectTile(LockedTile, true, loc); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(loc, newEffect); } //finally, seal with a locked door { map.Tiles[keyLoc.X][keyLoc.Y] = (Tile)map.UnbreakableTerrain.Copy(); EffectTile newEffect = new EffectTile(KeyTile, true, keyLoc); TileListState state = new TileListState(); state.Tiles = lockList; newEffect.TileStates.Set(state); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(keyLoc, newEffect); } }
private void eyedropTile(Loc loc) { if (!Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, loc)) { return; } EffectTile effectTile = ZoneManager.Instance.CurrentMap.Tiles[loc.X][loc.Y].Effect; if (effectTile.ID > -1) { setBrush(effectTile); } }
private void setBrush(EffectTile brush) { ChosenTile = brush.ID; ChosenOwner = (int)brush.Owner; IsDanger = brush.Danger; IsRevealed = brush.Revealed; List <TileState> states = new List <TileState>(); foreach (TileState state in brush.TileStates) { states.Add(state); } TileStates.LoadFromList(states); }
private EffectTile getBrush() { EffectTile brush = new EffectTile(ChosenTile, IsRevealed); brush.Danger = IsDanger; brush.Owner = (EffectTile.TileOwner)ChosenOwner; List <TileState> states = TileStates.GetList <List <TileState> >(); for (int ii = 0; ii < states.Count; ii++) { brush.TileStates.Set(states[ii]); } return(brush); }
public void ProcessInput(InputManager input) { bool inWindow = Collision.InBounds(GraphicsManager.WindowWidth, GraphicsManager.WindowHeight, input.MouseLoc); Loc tileCoords = DungeonEditScene.Instance.ScreenCoordsToMapCoords(input.MouseLoc); switch (TileMode) { case TileEditMode.Draw: { EffectTile brush = getBrush(); CanvasStroke <EffectTile> .ProcessCanvasInput(input, tileCoords, inWindow, () => new DrawStroke <EffectTile>(tileCoords, brush), () => new DrawStroke <EffectTile>(tileCoords, new EffectTile()), paintStroke, ref DungeonEditScene.Instance.TileInProgress); } break; case TileEditMode.Rectangle: { EffectTile brush = getBrush(); CanvasStroke <EffectTile> .ProcessCanvasInput(input, tileCoords, inWindow, () => new RectStroke <EffectTile>(tileCoords, brush), () => new RectStroke <EffectTile>(tileCoords, new EffectTile()), paintStroke, ref DungeonEditScene.Instance.TileInProgress); } break; case TileEditMode.Fill: { EffectTile brush = getBrush(); CanvasStroke <EffectTile> .ProcessCanvasInput(input, tileCoords, inWindow, () => new FillStroke <EffectTile>(tileCoords, brush), () => new FillStroke <EffectTile>(tileCoords, new EffectTile()), fillStroke, ref DungeonEditScene.Instance.TileInProgress); } break; case TileEditMode.Eyedrop: { if (input[FrameInput.InputType.LeftMouse]) { eyedropTile(tileCoords); } } break; } }
private void paintStroke(CanvasStroke <EffectTile> stroke) { Dictionary <Loc, EffectTile> brush = new Dictionary <Loc, EffectTile>(); foreach (Loc loc in stroke.GetLocs()) { if (!Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, loc)) { continue; } brush[loc] = new EffectTile(stroke.GetBrush(loc), loc); } DiagManager.Instance.DevEditor.MapEditor.Edits.Apply(new DrawTileUndo(brush)); }
public bool RemoveEffect(EffectTile effect) { if (HasEffect) { foreach (var gameobject in ObjectsOnTile) { EffectTile oldEffect; bool ok = gameobject.TryGetComponent <EffectTile>(out oldEffect); if (ok && oldEffect == effect) { ObjectsOnTile.Remove(oldEffect.gameObject); oldEffect.EndEffect(); break; } } HasEffect = false; return(true); } return(false); }
protected void PlaceEntities(T map, List <Loc> freeTiles) { List <EffectTile> tileTreasures = TileTreasures.GetSpawns(map); for (int kk = 0; kk < tileTreasures.Count && freeTiles.Count > 0; kk++) { int randIndex = map.Rand.Next(freeTiles.Count); EffectTile spawnedTrap = tileTreasures[kk]; ((IPlaceableGenContext <EffectTile>)map).PlaceItem(freeTiles[randIndex], spawnedTrap); freeTiles.RemoveAt(randIndex); } List <MapItem> treasures = Treasures.GetSpawns(map); for (int kk = 0; kk < treasures.Count && freeTiles.Count > 0; kk++) { int randIndex = map.Rand.Next(freeTiles.Count); MapItem item = new MapItem(treasures[kk]); ((IPlaceableGenContext <MapItem>)map).PlaceItem(freeTiles[randIndex], item); freeTiles.RemoveAt(randIndex); } List <MobSpawn> guardTypes = GuardTypes.GetSpawns(map); for (int kk = 0; kk < guardTypes.Count && freeTiles.Count > 0; kk++) { int randIndex = map.Rand.Next(freeTiles.Count); MonsterTeam team = new MonsterTeam(); Character newChar = guardTypes[kk].Spawn(team, map); newChar.CharLoc = freeTiles[randIndex]; map.MapTeams.Add(newChar.MemberTeam); freeTiles.RemoveAt(randIndex); } }
public bool AddEffect(EffectTile effect) { //if tile already has effect when find it and rewrite if (HasEffect) { foreach (var gameobject in ObjectsOnTile) { EffectTile oldEffect; bool ok = gameobject.TryGetComponent <EffectTile>(out oldEffect); if (ok) { ObjectsOnTile.Remove(oldEffect.gameObject); oldEffect.EndEffect(); } } } ObjectsOnTile.Add(effect.gameObject); HasEffect = true; effect.StartEffect(); return(true); }
public MapGenExit() { Tile = new EffectTile(); }
void IPlaceableGenContext <EffectTile> .PlaceItem(Loc loc, EffectTile item) { Map.Tiles[loc.X][loc.Y].Effect = new EffectTile(item); }
public override void Apply(T map) { Grid.LocTest checkBlock = (Loc testLoc) => { return(!map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) || map.HasTileEffect(testLoc)); }; //choose a room to put the chest in //do not choose a room that would cause disconnection of the floor List <int> possibleRooms = new List <int>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { FloorRoomPlan testPlan = map.RoomPlan.GetRoomPlan(ii); //if (map.RoomPlan.IsChokePoint(new RoomHallIndex(ii, false))) // continue; if (!BaseRoomFilter.PassesAllFilters(testPlan, this.Filters)) { continue; } //also do not choose a room that contains the end stairs IViewPlaceableGenContext <MapGenExit> exitMap = (IViewPlaceableGenContext <MapGenExit>)map; if (Collision.InBounds(testPlan.RoomGen.Draw, exitMap.GetLoc(0))) { continue; } possibleRooms.Add(ii); } if (possibleRooms.Count == 0) { return; } List <Loc> freeTiles = new List <Loc>(); IRoomGen room = null; while (possibleRooms.Count > 0) { int chosenRoom = map.Rand.Next(possibleRooms.Count); room = map.RoomPlan.GetRoom(possibleRooms[chosenRoom]); //get all places that the chest is eligible freeTiles = Grid.FindTilesInBox(room.Draw.Start, room.Draw.Size, (Loc testLoc) => { if (map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(testLoc) && map.Tiles[testLoc.X][testLoc.Y + 1].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(new Loc(testLoc.X, testLoc.Y + 1)) && !map.PostProcGrid[testLoc.X][testLoc.Y].Status[(int)PostProcType.Panel] && !map.PostProcGrid[testLoc.X][testLoc.Y].Status[(int)PostProcType.Item]) { if (Grid.GetForkDirs(testLoc, checkBlock, checkBlock).Count < 2) { foreach (MapItem item in map.Items) { if (item.TileLoc == testLoc) { return(false); } } foreach (Team team in map.AllyTeams) { foreach (Character testChar in team.EnumerateChars()) { if (testChar.CharLoc == testLoc) { return(false); } } } foreach (Team team in map.MapTeams) { foreach (Character testChar in team.EnumerateChars()) { if (testChar.CharLoc == testLoc) { return(false); } } } return(true); } } return(false); }); if (freeTiles.Count > 0) { break; } possibleRooms.RemoveAt(chosenRoom); } //can't find any free tile in any room, return if (freeTiles.Count == 0) { return; } if (!ItemThemes.CanPick) { return; } //choose which item theme to work with ItemTheme chosenItemTheme = ItemThemes.Pick(map.Rand); //the item spawn list in this class dictates the items available for spawning //it will be queried for items that match the theme selected List <MapItem> chosenItems = chosenItemTheme.GenerateItems(map, Items); if (chosenItems.Count == 0) { return; } int randIndex = map.Rand.Next(freeTiles.Count); Loc loc = freeTiles[randIndex]; EffectTile spawnedChest = new EffectTile(37, true); if (Ambush && MobThemes.CanPick) { spawnedChest.Danger = true; //the mob theme will be selected randomly MobTheme chosenMobTheme = MobThemes.Pick(map.Rand); //the mobs in this class are the ones that would be available when the game wants to spawn things outside of the floor's spawn list //it will be queried for monsters that match the theme provided List <MobSpawn> chosenMobs = chosenMobTheme.GenerateMobs(map, Mobs); MobSpawnState mobSpawn = new MobSpawnState(); foreach (MobSpawn mob in chosenMobs) { MobSpawn copyMob = mob.Copy(); if (map.Rand.Next(ALT_COLOR_ODDS) == 0) { copyMob.BaseForm.Skin = 1; } mobSpawn.Spawns.Add(copyMob); } spawnedChest.TileStates.Set(mobSpawn); } ItemSpawnState itemSpawn = new ItemSpawnState(); itemSpawn.Spawns = chosenItems; spawnedChest.TileStates.Set(itemSpawn); Rect wallBounds = new Rect(room.Draw.X - 1, room.Draw.Y - 1, room.Draw.Size.X + 2, room.Draw.Size.Y + 2); spawnedChest.TileStates.Set(new BoundsState(wallBounds)); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(loc, spawnedChest); map.PostProcGrid[loc.X][loc.Y].Status[(int)PostProcType.Panel] = true; map.PostProcGrid[loc.X][loc.Y].Status[(int)PostProcType.Item] = true; GenContextDebug.DebugProgress("Placed Chest"); }
public override void Apply(T map) { //TODO: move magic numbers out of here EffectTile spawnedChest = new EffectTile(44, true); List <Loc> freeTiles = ((IPlaceableGenContext <EffectTile>)map).GetAllFreeTiles(); int randIndex = map.Rand.Next(freeTiles.Count); Loc chosenLoc = freeTiles[randIndex]; ((IPlaceableGenContext <EffectTile>)map).PlaceItem(chosenLoc, spawnedChest); //also put a monster house here RandRange amount = new RandRange(7, 13); int mobCount = amount.Pick(map.Rand); List <MobSpawn> chosenMobs = new List <MobSpawn>(); if (map.TeamSpawns.Count > 0) { for (int ii = 0; ii < mobCount; ii++) { List <MobSpawn> exampleList = map.TeamSpawns.Pick(map.Rand).ChooseSpawns(map.Rand); if (exampleList.Count > 0) { chosenMobs.AddRange(exampleList); } if (chosenMobs.Count >= mobCount) { break; } } } if (chosenMobs.Count > 0) { Rect bounds = new Rect(chosenLoc - new Loc(4), new Loc(9)); bounds = Rect.Intersect(bounds, new Rect(0, 0, map.Width, map.Height)); for (int xx = bounds.X; xx < bounds.End.X; xx++) { for (int yy = bounds.Y; yy < bounds.End.Y; yy++) { if ((xx == bounds.X || xx == bounds.End.X - 1) && (yy == bounds.Y || yy == bounds.End.Y - 1)) { continue; } if (map.GetTile(new Loc(xx, yy)).TileEquivalent(map.WallTerrain)) { map.SetTile(new Loc(xx, yy), map.RoomTerrain.Copy()); } } } //cover the room in a check that holds all of the monsters, and covers the room's bounds CheckIntrudeBoundsEvent check = new CheckIntrudeBoundsEvent(); check.Bounds = bounds; { MonsterHouseMapEvent house = new MonsterHouseMapEvent(); house.Bounds = check.Bounds; foreach (MobSpawn mob in chosenMobs) { house.Mobs.Add(mob.Copy()); } check.Effects.Add(house); } int intrudeStatus = 33; MapStatus status = new MapStatus(intrudeStatus); status.LoadFromData(); MapCheckState checkState = status.StatusStates.GetWithDefault <MapCheckState>(); checkState.CheckEvents.Add(check); map.Map.Status.Add(intrudeStatus, status); } }
protected override void PlaceBorders(T map, Dictionary <Loc, SealType> sealList) { Rect?bossRect = null; for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { FloorRoomPlan plan = map.RoomPlan.GetRoomPlan(ii); if (!BaseRoomFilter.PassesAllFilters(plan, this.BossFilters)) { continue; } bossRect = plan.RoomGen.Draw; break; } //if there's no way to open the door, there cannot be a door; give the player the treasure unguarded if (bossRect == null) { return; } EffectTile bossEffect = null; for (int xx = bossRect.Value.Start.X; xx < bossRect.Value.End.X; xx++) { for (int yy = bossRect.Value.Start.Y; yy < bossRect.Value.End.Y; yy++) { if (map.Tiles[xx][yy].Effect.ID == BossTile) { bossEffect = map.Tiles[xx][yy].Effect; break; } } if (bossEffect != null) { break; } } if (bossEffect == null) { return; } List <Loc> lockList = new List <Loc>(); foreach (Loc loc in sealList.Keys) { switch (sealList[loc]) { case SealType.Blocked: map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); break; default: lockList.Add(loc); break; } } foreach (Loc loc in lockList) { map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); EffectTile newEffect = new EffectTile(SealedTile, true, loc); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(loc, newEffect); } ResultEventState resultEvent = new ResultEventState(); resultEvent.ResultEvents.Add(new OpenVaultEvent(lockList)); bossEffect.TileStates.Set(resultEvent); }
public override void Apply(T map) { if (Spawns.Count > 0) { List <Loc> freeTiles = new List <Loc>(); //get all places that traps are eligible for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { IRoomGen room = map.RoomPlan.GetRoom(ii); List <Loc> tiles = ((IPlaceableGenContext <EffectTile>)map).GetFreeTiles(room.Draw); freeTiles.AddRange(tiles); } // add tile if (freeTiles.Count > 0) { int randIndex = ((IGenContext)map).Rand.Next(freeTiles.Count); Loc loc = freeTiles[randIndex]; EffectTile spawnedTrap = Spawns.Pick(((IGenContext)map).Rand); map.PlaceItem(loc, spawnedTrap); freeTiles.RemoveAt(randIndex); if (GuardSpawns.Count > 0) { for (int ii = 0; ii < 10; ii++) { Team newTeam = GuardSpawns.Pick(((IGenContext)map).Rand).Spawn(map); if (newTeam == null) { continue; } //spawn guards Grid.LocTest checkSpawnOpen = (Loc testLoc) => { return(((IGroupPlaceableGenContext <Team>)map).CanPlaceItem(testLoc)); }; Grid.LocTest checkSpawnBlock = (Loc testLoc) => { return(map.TileBlocked(testLoc)); }; Grid.LocTest checkDiagSpawnBlock = (Loc testLoc) => { return(map.TileBlocked(testLoc, true)); }; List <Loc> resultLocs = new List <Loc>(); foreach (Loc resultLoc in Grid.FindClosestConnectedTiles(new Loc(), new Loc(map.Width, map.Height), checkSpawnOpen, checkSpawnBlock, checkDiagSpawnBlock, loc, newTeam.MemberGuestCount)) { resultLocs.Add(resultLoc); } if (resultLocs.Count >= newTeam.MemberGuestCount) { Loc[] locs = new Loc[newTeam.MemberGuestCount]; for (int jj = 0; jj < locs.Length; jj++) { locs[jj] = resultLocs[jj]; } map.PlaceItems(newTeam, locs); break; } } } } } }
protected MapGenExit(MapGenExit other) { Loc = other.Loc; Tile = (EffectTile)other.Tile.Copy(); }
public void RemoveEffect(EffectTile effect) { Vector3Int coords = GetTilemapCoordsFromWorld(PathfindingMap, effect.transform.position); _graph.GetNode(coords).RemoveEffect(effect); }
public override void Apply(T map) { //choose a room to cram all the items in List <int> possibleRooms = new List <int>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { FloorRoomPlan testPlan = map.RoomPlan.GetRoomPlan(ii); if (!BaseRoomFilter.PassesAllFilters(testPlan, this.Filters)) { continue; } //also do not choose a room that contains the start or end IViewPlaceableGenContext <MapGenEntrance> entranceMap = map; if (Collision.InBounds(testPlan.RoomGen.Draw, entranceMap.GetLoc(0))) { continue; } IViewPlaceableGenContext <MapGenExit> exitMap = map; if (Collision.InBounds(testPlan.RoomGen.Draw, exitMap.GetLoc(0))) { continue; } possibleRooms.Add(ii); } FloorRoomPlan roomPlan = null; Rect limitRect = Rect.Empty; while (possibleRooms.Count > 0) { int chosenRoom = map.Rand.Next(possibleRooms.Count); roomPlan = map.RoomPlan.GetRoomPlan(possibleRooms[chosenRoom]); bool[][] eligibilityGrid = new bool[roomPlan.RoomGen.Draw.Width][]; for (int xx = 0; xx < roomPlan.RoomGen.Draw.Width; xx++) { eligibilityGrid[xx] = new bool[roomPlan.RoomGen.Draw.Height]; for (int yy = 0; yy < roomPlan.RoomGen.Draw.Height; yy++) { bool eligible = true; Loc testLoc = roomPlan.RoomGen.Draw.Start + new Loc(xx, yy); if (map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(testLoc) && map.Tiles[testLoc.X][testLoc.Y + 1].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(new Loc(testLoc.X, testLoc.Y + 1)) && !map.PostProcGrid[testLoc.X][testLoc.Y].Status[(int)PostProcType.Panel] && !map.PostProcGrid[testLoc.X][testLoc.Y].Status[(int)PostProcType.Item]) { foreach (MapItem item in map.Items) { if (item.TileLoc == testLoc) { eligible = false; break; } } } else { eligible = false; } eligibilityGrid[xx][yy] = eligible; } } List <Rect> candRects = Detection.DetectNLargestRects(eligibilityGrid, 1); if (candRects.Count > 0) { limitRect = new Rect(roomPlan.RoomGen.Draw.Start + candRects[0].Start, candRects[0].Size); if (limitRect.Size.X >= MIN_SHOP_SIZE && limitRect.Size.Y >= MIN_SHOP_SIZE) { break; } } possibleRooms.RemoveAt(chosenRoom); } if (limitRect.Size.X < MIN_SHOP_SIZE || limitRect.Size.Y < MIN_SHOP_SIZE) { return; } //randomly roll an actual rectangle within the saferect bounds: between 3x3 and the limit Loc rectSize = new Loc(map.Rand.Next(MIN_SHOP_SIZE, limitRect.Width + 1), map.Rand.Next(MIN_SHOP_SIZE, limitRect.Height + 1)); Loc rectStart = new Loc(limitRect.X + map.Rand.Next(limitRect.Width - rectSize.X + 1), limitRect.Y + map.Rand.Next(limitRect.Height - rectSize.Y + 1)); Rect safeRect = new Rect(rectStart, rectSize); // place the mat of the shop List <Loc> itemTiles = new List <Loc>(); for (int xx = safeRect.X; xx < safeRect.End.X; xx++) { for (int yy = safeRect.Y; yy < safeRect.End.Y; yy++) { Loc matLoc = new Loc(xx, yy); itemTiles.Add(matLoc); EffectTile effect = new EffectTile(45, true, matLoc); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(matLoc, effect); map.PostProcGrid[matLoc.X][matLoc.Y].Status[(int)PostProcType.Panel] = true; map.PostProcGrid[matLoc.X][matLoc.Y].Status[(int)PostProcType.Item] = true; } } // place the map status for checking shop items and spawning security guards { MapStatus status = new MapStatus(SecurityStatus); status.LoadFromData(); ShopSecurityState securityState = new ShopSecurityState(); for (int ii = 0; ii < Mobs.Count; ii++) { securityState.Security.Add(Mobs.GetSpawn(ii).Copy(), Mobs.GetSpawnRate(ii)); } status.StatusStates.Set(securityState); status.StatusStates.Set(new MapIndexState(Personality)); map.Map.Status.Add(SecurityStatus, status); } // place the mob running the shop { ExplorerTeam newTeam = new ExplorerTeam(); newTeam.SetRank(1); Character shopkeeper = StartMob.Spawn(newTeam, map); Loc randLoc = itemTiles[map.Rand.Next(itemTiles.Count)]; ((IGroupPlaceableGenContext <TeamSpawn>)map).PlaceItems(new TeamSpawn(newTeam, true), new Loc[] { randLoc }); } //choose which item theme to work with ItemTheme chosenItemTheme = ItemThemes.Pick(map.Rand); //the item spawn list in this class dictates the items available for spawning //it will be queried for items that match the theme selected List <MapItem> chosenItems = chosenItemTheme.GenerateItems(map, Items); //place the items for (int ii = 0; ii < chosenItems.Count; ii++) { if (itemTiles.Count > 0) { MapItem item = new MapItem(chosenItems[ii]); int randIndex = map.Rand.Next(itemTiles.Count); ((IPlaceableGenContext <MapItem>)map).PlaceItem(itemTiles[randIndex], item); itemTiles.RemoveAt(randIndex); } } //prevent the room from being chosen for anything else roomPlan.Components.Set(new NoEventRoom()); }
public MapGenExit(EffectTile tile) { Tile = tile; }
public MapGenExit(Loc loc, EffectTile tile) { Loc = loc; Tile = tile; }
protected override void PostDraw(SpriteBatch spriteBatch) { Matrix matrix = Matrix.CreateScale(new Vector3(drawScale, drawScale, 1)); spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, matrix); if (AutoTileInProgress != null) { for (int jj = viewTileRect.Y; jj < viewTileRect.End.Y; jj++) { for (int ii = viewTileRect.X; ii < viewTileRect.End.X; ii++) { Loc testLoc = new Loc(ii, jj); if (Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, testLoc) && AutoTileInProgress.IncludesLoc(testLoc)) { AutoTile brush = AutoTileInProgress.GetBrush(testLoc); if (brush.IsEmpty()) { GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(ii * GraphicsManager.TileSize - ViewRect.X, jj * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, Color.Black); } else { brush.Draw(spriteBatch, new Loc(ii * GraphicsManager.TileSize, jj * GraphicsManager.TileSize) - ViewRect.Start); } } } } } //draw the blocks for (int jj = viewTileRect.Y; jj < viewTileRect.End.Y; jj++) { for (int ii = viewTileRect.X; ii < viewTileRect.End.X; ii++) { Loc testLoc = new Loc(ii, jj); if (Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, testLoc)) { TerrainTile tile = ZoneManager.Instance.CurrentMap.Tiles[ii][jj].Data; if (TerrainInProgress != null && TerrainInProgress.IncludesLoc(testLoc)) { tile = TerrainInProgress.GetBrush(testLoc); if (tile.TileTex.IsEmpty()) { GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(ii * GraphicsManager.TileSize - ViewRect.X, jj * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, Color.Black); } else { tile.TileTex.Draw(spriteBatch, new Loc(ii * GraphicsManager.TileSize, jj * GraphicsManager.TileSize) - ViewRect.Start); } } if (ShowTerrain) { TerrainData data = tile.GetData(); Color color = Color.Transparent; switch (data.BlockType) { case TerrainData.Mobility.Block: color = Color.Red; break; case TerrainData.Mobility.Water: color = Color.Blue; break; case TerrainData.Mobility.Lava: color = Color.Orange; break; case TerrainData.Mobility.Abyss: color = Color.Black; break; case TerrainData.Mobility.Impassable: color = Color.White; break; } if (color != Color.Transparent) { GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(ii * GraphicsManager.TileSize - ViewRect.X, jj * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, color * 0.5f); } } } } } if (ShowEntrances) { foreach (LocRay8 entrance in ZoneManager.Instance.CurrentMap.EntryPoints) { Color showColor = Color.OrangeRed; GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(entrance.Loc.X * GraphicsManager.TileSize - ViewRect.X, entrance.Loc.Y * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, showColor * 0.75f); } } if (TileInProgress != null) { for (int jj = viewTileRect.Y; jj < viewTileRect.End.Y; jj++) { for (int ii = viewTileRect.X; ii < viewTileRect.End.X; ii++) { Loc testLoc = new Loc(ii, jj); if (Collision.InBounds(ZoneManager.Instance.CurrentMap.Width, ZoneManager.Instance.CurrentMap.Height, testLoc) && TileInProgress.IncludesLoc(testLoc)) { EffectTile tile = TileInProgress.GetBrush(testLoc); if (tile.ID < 0) { GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(ii * GraphicsManager.TileSize - ViewRect.X, jj * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, Color.Black); } else { TileData entry = DataManager.Instance.GetTile(tile.ID); if (entry.Anim.AnimIndex != "") { DirSheet sheet = GraphicsManager.GetObject(entry.Anim.AnimIndex); Loc drawLoc = new Loc(ii * GraphicsManager.TileSize, jj * GraphicsManager.TileSize) - ViewRect.Start + new Loc(GraphicsManager.TileSize / 2) - new Loc(sheet.Width, sheet.Height) / 2; sheet.DrawDir(spriteBatch, drawLoc.ToVector2(), entry.Anim.GetCurrentFrame(GraphicsManager.TotalFrameTick, sheet.TotalFrames), entry.Anim.GetDrawDir(Dir8.None), Color.White); } else { GraphicsManager.Pixel.Draw(spriteBatch, new Rectangle(ii * GraphicsManager.TileSize - ViewRect.X, jj * GraphicsManager.TileSize - ViewRect.Y, GraphicsManager.TileSize, GraphicsManager.TileSize), null, Color.White); } } } } } } spriteBatch.End(); }
public override void Apply(T map) { //first get all free tiles suitable for the switch List <Loc> freeSwitchTiles = ((IPlaceableGenContext <EffectTile>)map).GetAllFreeTiles(); if (freeSwitchTiles.Count == 0) { return; } Grid.LocTest checkGround = (Loc testLoc) => { if (!Collision.InBounds(map.Width, map.Height, testLoc)) { return(false); } return(map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.HasTileEffect(testLoc)); }; Grid.LocTest checkBlock = (Loc testLoc) => { if (!Collision.InBounds(map.Width, map.Height, testLoc)) { return(false); } return(map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.WallTerrain)); }; List <LocRay4> rays = Detection.DetectWalls(((IViewPlaceableGenContext <MapGenEntrance>)map).GetLoc(0), new Rect(0, 0, map.Width, map.Height), checkBlock, checkGround); EffectTile effect = new EffectTile(SealedTile, true); List <Loc> freeTiles = new List <Loc>(); List <LocRay4> createdEntrances = new List <LocRay4>(); int amount = EntranceCount.Pick(map.Rand); for (int ii = 0; ii < amount; ii++) { LocRay4?ray = PlaceRoom(map, rays, effect, freeTiles); if (ray != null) { createdEntrances.Add(ray.Value); } } if (createdEntrances.Count > 0) { PlaceEntities(map, freeTiles); EffectTile switchTile = new EffectTile(SwitchTile, true); if (TimeLimit) { switchTile.Danger = true; } TileListState state = new TileListState(); for (int mm = 0; mm < createdEntrances.Count; mm++) { state.Tiles.Add(new Loc(createdEntrances[mm].Loc)); } switchTile.TileStates.Set(state); int randIndex = map.Rand.Next(freeSwitchTiles.Count); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(freeSwitchTiles[randIndex], switchTile); } }
public override void DrawOnMap(T map) { Loc caveSize = ProposeSize(((IGenContext)map).Rand); if (caveSize.X != Draw.Width || caveSize.Y != Draw.Height) { DrawMapDefault(map); return; } //place room in a space that fits List <Loc> freeTiles = new List <Loc>(); Loc caveStart = Draw.Start + new Loc(2, 1); for (int x = 0; x < caveSize.X - 4; x++) { for (int y = 0; y < caveSize.Y - 4; y++) { map.SetTile(new Loc(caveStart.X + x, caveStart.Y + y), map.RoomTerrain.Copy()); freeTiles.Add(new Loc(caveStart.X + x, caveStart.Y + y)); } } //place tile treasures List <EffectTile> tileTreasures = TileTreasures.GetSpawns(map); for (int ii = 0; ii < tileTreasures.Count; ii++) { int randIndex = ((IGenContext)map).Rand.Next(freeTiles.Count); EffectTile tile = new EffectTile(tileTreasures[ii]); map.PlaceItem(freeTiles[randIndex], tile); freeTiles.RemoveAt(randIndex); } //place item treasures List <MapItem> treasures = Treasures.GetSpawns(map); for (int ii = 0; ii < treasures.Count; ii++) { int randIndex = ((IGenContext)map).Rand.Next(freeTiles.Count); MapItem item = treasures[ii]; map.PlaceItem(freeTiles[randIndex], item); freeTiles.RemoveAt(randIndex); } //open the passage to the treasure room Loc tunnel = new Loc(caveStart.X + (caveSize.X - 4) / 2, caveStart.Y + caveSize.Y - 4); map.SetTile(tunnel, map.RoomTerrain.Copy()); //dig the room into the treasure room for (int xx = 0; xx < 3; xx++) { for (int yy = 0; yy < 2; yy++) { map.SetTile(new Loc(tunnel.X - 1 + xx, tunnel.Y + 1 + yy), map.RoomTerrain.Copy()); } } //place monsters and items MonsterTeam team = new MonsterTeam(); Character newChar = GuardTypes.Pick(((IGenContext)map).Rand).Spawn(team, map); map.PlaceItems(new TeamSpawn(team, false), new Loc[1] { tunnel }); //dig tunnels within this room to hook up to the incoming demands foreach (Dir4 dir in DirExt.VALID_DIR4) { if (dir == Dir4.Up) {//if approached from the top, it must be either left or right. Dig to that side and then dig up. List <IntRange> upReq = RoomSideReqs[dir]; bool left = false; bool right = false; for (int ii = 0; ii < upReq.Count; ii++) { bool hasLeft = upReq[ii].Contains(Draw.Start.X) && BorderToFulfill[Dir4.Up][0]; bool hasRight = upReq[ii].Contains(Draw.End.X - 1) && BorderToFulfill[Dir4.Up][Draw.Width - 1]; if (hasLeft && hasRight) { if (((IGenContext)map).Rand.Next(2) == 0) { left = true; } else { right = true; } } else { left |= hasLeft; right |= hasRight; } } if (left) { DigAtBorder(map, Dir4.Left, Draw.End.Y - 1); DigAtBorder(map, Dir4.Up, Draw.Start.X); } if (right) { DigAtBorder(map, Dir4.Right, Draw.End.Y - 1); DigAtBorder(map, Dir4.Up, Draw.End.X - 1); } } else if (dir == Dir4.Down) {//if approached from bottom, do nothing; we already fulfill every possibility } else {//if approached from the sides, dig at the bottommost Y of the room, because that was the only tile allowed. if (RoomSideReqs[dir].Count > 0) { DigAtBorder(map, dir, Draw.End.Y - 1); } } } for (int x = 0; x < Draw.Width; x++) { for (int y = 0; y < Draw.Height - 1; y++) { Loc checkLoc = new Loc(Draw.X + x, Draw.Y + y); if (!map.GetTile(checkLoc).TileEquivalent(map.RoomTerrain)) { map.SetTile(checkLoc, map.UnbreakableTerrain.Copy()); } } } SetRoomBorders(map); }
protected LocRay4?PlaceRoom(T map, List <LocRay4> rays, EffectTile sealingTile, List <Loc> freeTiles) { Grid.LocTest checkBlockForPlace = (Loc testLoc) => { if (!Collision.InBounds(map.Width, map.Height, testLoc)) { return(false); } return(!map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.RoomTerrain) && !map.Tiles[testLoc.X][testLoc.Y].TileEquivalent(map.UnbreakableTerrain)); }; //try X times to dig a passage for (int ii = 0; ii < 500 && rays.Count > 0; ii++) { int rayIndex = map.Rand.Next(rays.Count); LocRay4 ray = rays[rayIndex]; rays.RemoveAt(rayIndex); Loc rayDirLoc = ray.Dir.GetLoc(); Axis4 axis = ray.Dir.ToAxis(); Axis4 orth = axis == Axis4.Horiz ? Axis4.Vert : Axis4.Horiz; int minLength = Math.Max(1, HallLength.Min); Rect hallBound = new Rect(ray.Loc + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc(), new Loc(1)); hallBound = Rect.IncludeLoc(hallBound, ray.Loc + rayDirLoc * (minLength - 1) + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc()); //make sure the MIN hall can tunnel unimpeded if (!CanPlaceRect(map, hallBound, checkBlockForPlace)) { continue; } for (int jj = 0; jj < 100; jj++) { //plan the room RoomGen <T> plan = GenericRooms.Pick(map.Rand).Copy(); Loc size = plan.ProposeSize(map.Rand); plan.PrepareSize(map.Rand, size); //attempt to place the bounds somewhere, anywhere, within the limitations that the room itself provides List <int> candidateOpenings = new List <int>(); int planLength = plan.GetBorderLength(ray.Dir.Reverse()); for (int kk = 0; kk < planLength; kk++) { if (plan.GetFulfillableBorder(ray.Dir.Reverse(), kk)) { candidateOpenings.Add(kk); } } //as well as continue extending the hall until we hit a walkable. int tunnelLen = Math.Max(1, HallLength.Pick(map.Rand)); Loc roomLoc = ray.Loc + rayDirLoc * tunnelLen; int perpOffset = candidateOpenings[map.Rand.Next(candidateOpenings.Count)]; roomLoc += orth.CreateLoc(-perpOffset, 0); if (rayDirLoc.GetScalar(axis) < 0)//move back the top-left of the entrance { roomLoc += rayDirLoc * (size.GetScalar(axis) - 1); } Rect roomTestBound = new Rect(roomLoc, size); roomTestBound.Inflate(1, 1); //make a rect for the rest of the hall Rect hallExtBound = new Rect(ray.Loc + rayDirLoc * minLength + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc(), new Loc(1)); hallExtBound = Rect.IncludeLoc(hallBound, ray.Loc + rayDirLoc * (tunnelLen - 1) + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc()); //now that we've chosen our position, let's test it if (!CanPlaceRect(map, roomTestBound, checkBlockForPlace) || !CanPlaceRect(map, hallExtBound, checkBlockForPlace)) // also test that the CHOSEN hallway can be properly sealed { continue; //invalid location, try another place } else { plan.SetLoc(roomLoc); plan.ReceiveBorderRange(new IntRange(perpOffset, perpOffset + 1) + roomLoc.GetScalar(orth), ray.Dir.Reverse()); //draw the room plan.DrawOnMap(map); //surround the room with bounds for (int xx = roomTestBound.X; xx < roomTestBound.Right; xx++) { map.Tiles[xx][roomTestBound.Y] = (Tile)map.UnbreakableTerrain.Copy(); map.Tiles[xx][roomTestBound.End.Y - 1] = (Tile)map.UnbreakableTerrain.Copy(); } for (int yy = roomTestBound.Y + 1; yy < roomTestBound.Bottom - 1; yy++) { map.Tiles[roomTestBound.X][yy] = (Tile)map.UnbreakableTerrain.Copy(); map.Tiles[roomTestBound.End.X - 1][yy] = (Tile)map.UnbreakableTerrain.Copy(); } //spawn tiles, items, foes List <Loc> addedTiles = ((IPlaceableGenContext <MapItem>)map).GetFreeTiles(plan.Draw); freeTiles.AddRange(addedTiles); //tunnel to the room Loc loc = ray.Loc; for (int tt = 0; tt < tunnelLen; tt++) { //make walkable map.Tiles[loc.X][loc.Y] = (Tile)map.RoomTerrain.Copy(); //make left side unbreakable Loc lLoc = loc + DirExt.AddAngles(ray.Dir, Dir4.Left).GetLoc(); map.Tiles[lLoc.X][lLoc.Y] = (Tile)map.UnbreakableTerrain.Copy(); //make right side unbreakable Loc rLoc = loc + DirExt.AddAngles(ray.Dir, Dir4.Right).GetLoc(); map.Tiles[rLoc.X][rLoc.Y] = (Tile)map.UnbreakableTerrain.Copy(); loc += rayDirLoc; } //finally, seal with a locked door map.Tiles[ray.Loc.X][ray.Loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); EffectTile newEffect = new EffectTile(sealingTile, ray.Loc); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(ray.Loc, newEffect); return(ray); } } } //DiagManager.Instance.LogInfo("Couldn't place sealed detour!"); return(null); }
protected override void PlaceBorders(T map, Dictionary <Loc, SealType> sealList) { List <Loc> freeSwitchTiles = new List <Loc>(); for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { FloorRoomPlan plan = map.RoomPlan.GetRoomPlan(ii); if (!BaseRoomFilter.PassesAllFilters(plan, this.SwitchFilters)) { continue; } freeSwitchTiles.AddRange(((IPlaceableGenContext <EffectTile>)map).GetFreeTiles(plan.RoomGen.Draw)); } for (int ii = 0; ii < map.RoomPlan.HallCount; ii++) { FloorHallPlan plan = map.RoomPlan.GetHallPlan(ii); if (!BaseRoomFilter.PassesAllFilters(plan, this.SwitchFilters)) { continue; } freeSwitchTiles.AddRange(((IPlaceableGenContext <EffectTile>)map).GetFreeTiles(plan.RoomGen.Draw)); } //if there's no way to open the door, there cannot be a door; give the player the treasure unguarded if (freeSwitchTiles.Count == 0) { return; } List <Loc> lockList = new List <Loc>(); foreach (Loc loc in sealList.Keys) { switch (sealList[loc]) { case SealType.Blocked: map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); break; default: lockList.Add(loc); break; } } foreach (Loc loc in lockList) { map.Tiles[loc.X][loc.Y] = (Tile)map.UnbreakableTerrain.Copy(); EffectTile newEffect = new EffectTile(SealedTile, true, loc); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(loc, newEffect); } EffectTile switchTile = new EffectTile(SwitchTile, true); if (TimeLimit) { switchTile.Danger = true; } TileListState state = new TileListState(); state.Tiles = lockList; switchTile.TileStates.Set(state); int randIndex = map.Rand.Next(freeSwitchTiles.Count); ((IPlaceableGenContext <EffectTile>)map).PlaceItem(freeSwitchTiles[randIndex], switchTile); }