public List <MoneySpawn> GetSpawns(T map) { MoneySpawn total = map.Spawner.Pick(map.Rand); int chosenDiv = Math.Min(total.Amount, Math.Max(1, DivAmount.Pick(map.Rand))); int avgAmount = total.Amount / chosenDiv; int currentTotal = 0; List <MoneySpawn> results = new List <MoneySpawn>(); for (int ii = 0; ii < chosenDiv; ii++) { int nextTotal = total.Amount; if (ii + 1 < chosenDiv) { int expectedCurrentTotal = total.Amount * (ii + 1) / chosenDiv; int amount = avgAmount * (/*map.Rand.Next(DIV_DIFF * 2)*/ ((ii % 2 == 0) ? 0 : 99) - DIV_DIFF) / 200; nextTotal = expectedCurrentTotal + amount; } if (nextTotal > currentTotal) { results.Add(new MoneySpawn(nextTotal - currentTotal)); } currentTotal = nextTotal; } return(results); }
public override void Apply(T map) { int chosenAmount = Amount.Pick(map.Rand); if (chosenAmount > 0 && Spawns.Count > 0 && PatternSpawns.Count > 0) { List <int> openRooms = new List <int>(); //get all places that traps are eligible for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { if (BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetRoomPlan(ii), this.Filters)) { openRooms.Add(ii); } } for (int ii = 0; ii < chosenAmount; ii++) { // add traps if (openRooms.Count > 0) { int randIndex = map.Rand.Next(openRooms.Count); TrapPattern pattern = PatternSpawns.Pick(map.Rand); } } } }
protected MoneySpawnZoneStep(MoneySpawnZoneStep other, ulong seed) : this() { StartAmount = other.StartAmount; AddAmount = other.AddAmount; Priority = other.Priority; ReRandom rand = new ReRandom(seed); chosenStart = StartAmount.Pick(rand); chosenAdd = AddAmount.Pick(rand); }
protected Character SpawnBase(Team team, IMobSpawnMap map) { MonsterID formData = BaseForm; MonsterData dex = DataManager.Instance.GetMonster(formData.Species); if (formData.Form == -1) { int form = map.Rand.Next(dex.Forms.Count); formData.Form = form; } BaseMonsterForm formEntry = dex.Forms[formData.Form]; if (formData.Gender == Gender.Unknown) { formData.Gender = formEntry.RollGender(map.Rand); } if (formData.Skin == -1) { formData.Skin = formEntry.RollSkin(map.Rand); } CharData character = new CharData(); character.BaseForm = formData; character.Level = Level.Pick(map.Rand); List <int> final_skills = formEntry.RollLatestSkills(character.Level, SpecifiedSkills); for (int ii = 0; ii < final_skills.Count; ii++) { character.BaseSkills[ii] = new SlotSkill(final_skills[ii]); } if (Intrinsic == -1) { character.BaseIntrinsics[0] = formEntry.RollIntrinsic(map.Rand, 2); } else { character.BaseIntrinsics[0] = Intrinsic; } character.Discriminator = map.Rand.Next(); Character new_mob = new Character(character, team); team.Players.Add(new_mob); return(new_mob); }
protected SpreadPlanSpaced(SpreadPlanSpaced other, ulong seed) : base(other, seed) { FloorSpacing = other.FloorSpacing; FloorRange = other.FloorRange; ReRandom rand = new ReRandom(seed); dropPoints = new HashSet <int>(); int currentFloor = FloorRange.Min; currentFloor += rand.Next(FloorSpacing.Max); while (currentFloor < FloorRange.Max) { dropPoints.Add(currentFloor); currentFloor += FloorSpacing.Pick(rand); } }
public override Loc ProposeSize(IRandom rand) { Loc isleSize = new Loc(1); while (isleSize.X * isleSize.Y < ItemAmount) { if (isleSize.X > isleSize.Y) { isleSize.Y++; } else { isleSize.X++; } } Loc ringSize = isleSize + new Loc(2); Loc pad = new Loc(Math.Max(PadWidth.Pick(rand), 2), Math.Max(PadHeight.Pick(rand), 2)); return(new Loc(ringSize.X + pad.X, ringSize.Y + pad.Y)); }
public override void Apply(T map) { int chosenAmount = Amount.Pick(map.Rand); if (chosenAmount > 0) { SpawnList <int> spawningRooms = new SpawnList <int>(); //get all places that spawnings are eligible for (int ii = 0; ii < map.RoomPlan.RoomCount; ii++) { IRoomGen room = map.RoomPlan.GetRoom(ii); if (!BaseRoomFilter.PassesAllFilters(map.RoomPlan.GetRoomPlan(ii), this.Filters)) { continue; } spawningRooms.Add(ii, 10000); } int trials = 10 * chosenAmount; for (int ii = 0; ii < trials && chosenAmount > 0; ii++) { if (spawningRooms.SpawnTotal == 0)//check to make sure there's still spawn choices left { break; } int spawnIndex = spawningRooms.PickIndex(map.Rand); int roomNum = spawningRooms.GetSpawn(spawnIndex); Team newTeam = Spawn.GetSpawn(map); if (newTeam == null) { continue; } List <Loc> freeTiles = Grid.FindTilesInBox(map.RoomPlan.GetRoom(roomNum).Draw.Start, map.RoomPlan.GetRoom(roomNum).Draw.Size, (Loc testLoc) => { return(((IGroupPlaceableGenContext <Team>)map).CanPlaceItem(testLoc)); }); //this actually places the members of the team in random scattered locations, leaving them to group together via wandering if (freeTiles.Count >= newTeam.Players.Count) { Loc[] locs = new Loc[newTeam.Players.Count]; for (int jj = 0; jj < newTeam.Players.Count; jj++) { int randIndex = map.Rand.Next(freeTiles.Count); locs[jj] = freeTiles[randIndex]; freeTiles.RemoveAt(randIndex); } ((IGroupPlaceableGenContext <Team>)map).PlaceItems(newTeam, locs); chosenAmount--; } if (freeTiles.Count == 0)//if spawningRooms is now impossible there, remove the room entirely { spawningRooms.RemoveAt(spawnIndex); } else //otherwise decrease spawn rate for room { spawningRooms.SetSpawnRate(spawnIndex, Math.Max(spawningRooms.GetSpawnRate(spawnIndex) * ClumpFactor / 100, 1)); } } } }
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); }
public override void ApplyToPath(IRandom rand, GridPlan floorPlan) { int chosenBigRooms = RoomAmount.Pick(rand); for (int ii = 0; ii < chosenBigRooms; ii++) { for (int jj = 0; jj < 20; jj++) { LargeRoom <T> chosenRoom = GiantRooms.Pick(rand); Rect destRect = new Rect(new Loc(rand.Next(floorPlan.GridWidth - chosenRoom.Size.X), rand.Next(floorPlan.GridHeight - chosenRoom.Size.Y)), chosenRoom.Size); if (spaceViable(floorPlan, destRect)) { List <LocRay4> raysOut = new List <LocRay4>(); for (int xx = destRect.Start.X; xx < destRect.End.X; xx++) { LocRay4 locUp = new LocRay4(xx, destRect.Start.Y, Dir4.Up); if (destRect.Start.Y > 0 && floorPlan.GetHall(locUp) != null) { raysOut.Add(locUp); } LocRay4 locDown = new LocRay4(xx, destRect.Start.Y + chosenRoom.Size.Y - 1, Dir4.Down); if (destRect.Start.Y < floorPlan.GridHeight - 1 && floorPlan.GetHall(locDown) != null) { raysOut.Add(locDown); } } for (int yy = destRect.Start.Y; yy < destRect.End.Y; yy++) { LocRay4 locLeft = new LocRay4(destRect.Start.X, yy, Dir4.Left); if (destRect.Start.X > 0 && floorPlan.GetHall(locLeft) != null) { raysOut.Add(locLeft); } LocRay4 locRight = new LocRay4(destRect.Start.X + chosenRoom.Size.X - 1, yy, Dir4.Right); if (destRect.Start.X < floorPlan.GridWidth - 1 && floorPlan.GetHall(locRight) != null) { raysOut.Add(locRight); } } List <List <LocRay4> > exitSets = findHallSets(floorPlan, destRect, raysOut); //exits: no more than allowed if (exitSets.Count > chosenRoom.AllowedEntrances) { continue; } //this block tallies all sets that can be joined to the big room //it also chooses which ones to keep by randomly removing them from the raysOut list int setsTaken = 0; foreach (List <LocRay4> set in exitSets) { List <LocRay4> possibleRays = new List <LocRay4>(); foreach (LocRay4 ray in set) { int scalar = (ray.Loc - destRect.Start).GetScalar(ray.Dir.ToAxis().Orth()); if (chosenRoom.OpenBorders[(int)ray.Dir][scalar]) { possibleRays.Add(ray); } } if (possibleRays.Count > 0) { LocRay4 locRay = possibleRays[rand.Next(possibleRays.Count)]; raysOut.Remove(locRay); setsTaken++; } else { break; } } if (setsTaken == exitSets.Count) { for (int xx = 0; xx < chosenRoom.Size.X; xx++) { for (int yy = 0; yy < chosenRoom.Size.Y; yy++) { //erase rooms in vicinity Loc loc = new Loc(xx + destRect.Start.X, yy + destRect.Start.Y); //erase halls in vicinity floorPlan.EraseRoom(loc); if (xx > 0) { floorPlan.SetHall(new LocRay4(loc, Dir4.Left), null, new ComponentCollection()); } if (yy > 0) { floorPlan.SetHall(new LocRay4(loc, Dir4.Up), null, new ComponentCollection()); } } } //remove all halls still in the list foreach (LocRay4 rayOut in raysOut) { floorPlan.SetHall(rayOut, null, new ComponentCollection()); } //add room floorPlan.AddRoom(destRect, chosenRoom.Gen, new ComponentCollection()); break; } } } } }
public override void Apply(T map) { int chosenAmount = Amount.Pick(map.Rand); if (chosenAmount > 0) { bool[][] connectionGrid = new bool[map.Width][]; for (int xx = 0; xx < map.Width; xx++) { connectionGrid[xx] = new bool[map.Height]; for (int yy = 0; yy < map.Height; yy++) { connectionGrid[xx][yy] = false; } } //first mark all tiles in the main path Grid.FloodFill(new Rect(0, 0, map.Width, map.Height), (Loc testLoc) => { if (connectionGrid[testLoc.X][testLoc.Y]) { return(true); } foreach (ITile tile in AcceptedTiles) { if (map.GetTile(testLoc).TileEquivalent(tile)) { return(false); } } return(true); }, (Loc testLoc) => { return(true); }, (Loc fillLoc) => { connectionGrid[fillLoc.X][fillLoc.Y] = true; }, ((IViewPlaceableGenContext <MapGenEntrance>)map).GetLoc(0)); //obtain all tiles not in the main path List <Loc> freeTiles = new List <Loc>(); for (int xx = 0; xx < map.Width; xx++) { for (int yy = 0; yy < map.Height; yy++) { if (!connectionGrid[xx][yy]) { bool allowPlacement = false; foreach (ITile tile in AcceptedTiles) { if (map.GetTile(new Loc(xx, yy)).TileEquivalent(tile)) { allowPlacement = true; } } if (allowPlacement) { freeTiles.Add(new Loc(xx, yy)); } } } } int trials = 10 * chosenAmount; for (int ii = 0; ii < trials; ii++) { Team newTeam = Spawn.GetSpawn(map); if (newTeam == null) { continue; } if (freeTiles.Count >= newTeam.Players.Count) { Loc[] locs = new Loc[newTeam.Players.Count]; for (int jj = 0; jj < newTeam.Players.Count; jj++) { int randIndex = map.Rand.Next(freeTiles.Count); locs[jj] = freeTiles[randIndex]; freeTiles.RemoveAt(randIndex); } ((IGroupPlaceableGenContext <Team>)map).PlaceItems(newTeam, locs); chosenAmount--; } if (freeTiles.Count == 0 || chosenAmount == 0) { break; } } } }
public override Loc ProposeSize(IRandom rand) { return(new Loc(Width.Pick(rand), Height.Pick(rand))); }
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 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); } }