示例#1
0
        public IEnumerable <ISimpleGameObject> GetObjectsWithin(uint x, uint y, int radius)
        {
            var list = new List <ISimpleGameObject>();

            foreach (var position in tileLocator.ForeachTile(x, y, radius))
            {
                if (position.X < WorldWidth && position.Y < WorldHeight)
                {
                    list.AddRange(GetObjectsInTile(position.X, position.Y));
                }
            }

            return(list);
        }
示例#2
0
        public Error SetRoadTheme(ICity city, string id)
        {
            if (!HasTheme(city.Owner, id))
            {
                return(Error.ThemeNotPurchased);
            }

            var previousTheme = city.RoadTheme;

            city.BeginUpdate();
            city.RoadTheme = id;
            city.EndUpdate();

            var lockedRegions = regionManager.LockRegions(tileLocator.ForeachTile(city.PrimaryPosition.X, city.PrimaryPosition.Y, city.Radius));

            roadManager.ChangeRoadTheme(city, previousTheme, id);

            regionManager.UnlockRegions(lockedRegions);

            return(Error.Ok);
        }
示例#3
0
        private void GenerateCityLocationsAndResources()
        {
            var cityLocations = new HashSet <Position>();

            do
            {
                var newCityPosition = new Position((uint)random.Next(10, WIDTH - 10), (uint)random.Next(10, HEIGHT - 10));

                var tooCloseToOtherCity = tileLocator.ForeachTile(newCityPosition.X, newCityPosition.Y, MIN_DIST_BETWEEN_CITIES).Any(cityLocations.Contains);

                if (tooCloseToOtherCity)
                {
                    continue;
                }

                cityResourceTileGenerator.GenerateResource(newCityPosition, map);

                cityLocations.Add(newCityPosition);

                map[newCityPosition.X, newCityPosition.Y] = CITY_TILE;
            }while (cityLocations.Count < TOTAL_PLAYERS);
        }
示例#4
0
 public bool TooCloseToCities(Position position, byte size)
 {
     return(tileLocator.ForeachMultitile(position.X, position.Y, size)
            .SelectMany(eachPosition => tileLocator.ForeachTile(eachPosition.X, eachPosition.Y, MIN_DISTANCE_AWAY_FROM_CITIES))
            .Any(positionToCheck => cityLocationsByPosition.Contains(positionToCheck)));
 }
示例#5
0
        public void Callback(object custom)
        {
            ICity      city;
            IStructure mainBuilding;

            if (!world.TryGetObjects(cityId, out city))
            {
                throw new Exception("City not found");
            }

            bool shouldReturn = locker.Lock(GetForeignTroopLockList, new object[] { city }, city)
                                .Do(() =>
            {
                if (city == null)
                {
                    return(true);
                }

                // if local city is in battle, try again later
                if (city.Battle != null)
                {
                    Reschedule(SHORT_RETRY);
                    return(true);
                }

                // send all stationed from other players back
                if (city.Troops.StationedHere().Any())
                {
                    IEnumerable <ITroopStub> stationedTroops = new List <ITroopStub>(city.Troops.StationedHere());

                    foreach (var stub in stationedTroops)
                    {
                        if (RemoveForeignTroop(stub) != Error.Ok)
                        {
                            logger.Error(String.Format("removeForeignTroop failed! cityid[{0}] stubid[{1}]", city.Id, stub.StationTroopId));
                        }
                    }
                }

                // If city is being targetted by an assignment, try again later
                var reader = dbManager.ReaderQuery(string.Format("SELECT id FROM `{0}` WHERE `location_type` = 'City' AND `location_id` = @locationId  LIMIT 1", Assignment.DB_TABLE),
                                                   new[] { new DbColumn("locationId", city.Id, DbType.UInt32) });
                bool beingTargetted = reader.HasRows;
                reader.Close();
                if (beingTargetted)
                {
                    Reschedule(LONG_RETRY);
                    return(true);
                }

                return(false);
            });

            if (shouldReturn)
            {
                return;
            }

            shouldReturn = locker.Lock(GetLocalTroopLockList, new object[] { city }, city)
                           .Do(() =>
            {
                if (city.TryGetStructure(1, out mainBuilding))
                {
                    // don't continue unless all troops are either idle or stationed
                    if (city.TroopObjects.Any() || city.Troops.Any(s => s.State != TroopState.Idle && s.State != TroopState.Stationed))
                    {
                        Reschedule(LONG_RETRY);
                        return(true);
                    }

                    // starve all troops)
                    city.Troops.Starve(100, true);

                    if (city.Troops.Upkeep > 0)
                    {
                        Reschedule(LONG_RETRY);
                        return(true);
                    }

                    // remove all buildings except mainbuilding
                    if (city.Any(structure => !structure.IsMainBuilding))
                    {
                        city.BeginUpdate();
                        foreach (IStructure structure in
                                 new List <IStructure>(city).Where(structure => structure.IsBlocked == 0 && !structure.IsMainBuilding))
                        {
                            structure.BeginUpdate();
                            world.Regions.Remove(structure);
                            city.ScheduleRemove(structure, false);
                            structure.EndUpdate();
                        }
                        city.EndUpdate();
                        Reschedule(SHORT_RETRY);
                        return(true);
                    }

                    // remove all customized tiles
                    foreach (var position in tileLocator.ForeachTile(city.PrimaryPosition.X, city.PrimaryPosition.Y, city.Radius))
                    {
                        world.Regions.RevertTileType(position.X, position.Y, true);
                    }
                }

                return(false);
            });

            if (shouldReturn)
            {
                return;
            }

            // remove all remaining passive action
            if (city.TryGetStructure(1, out mainBuilding))
            {
                foreach (var passiveAction in new List <PassiveAction>(city.Worker.PassiveActions.Values))
                {
                    passiveAction.WorkerRemoved(false);
                }
            }

            locker.Lock(cityId, out city).Do(() =>
            {
                if (city.Notifications.Count > 0)
                {
                    Reschedule(SHORT_RETRY);
                    return;
                }

                // remove mainbuilding
                if (city.TryGetStructure(1, out mainBuilding))
                {
                    // remove default troop
                    city.Troops.Remove(1);

                    // remove city from the region
                    world.Regions.MiniMapRegions.Remove(city);

                    mainBuilding.BeginUpdate();
                    world.Regions.Remove(mainBuilding);
                    city.ScheduleRemove(mainBuilding, false);
                    mainBuilding.EndUpdate();

                    Reschedule(SHORT_RETRY);
                    return;
                }

                // in the case of the OjectRemoveAction for mainbuilding is still there
                if (city.Worker.PassiveActions.Count > 0)
                {
                    Reschedule(SHORT_RETRY);
                    return;
                }

                logger.Info(string.Format("Player {0}:{1} City {2}:{3} Lvl {4} is deleted.",
                                          city.Owner.Name,
                                          city.Owner.PlayerId,
                                          city.Name,
                                          city.Id,
                                          city.Lvl));
                world.Cities.Remove(city);
            });
        }
示例#6
0
        public override Error Execute()
        {
            ICity      city;
            IStructure lumbermill;
            IForest    forest;

            if (!world.TryGetObjects(cityId, lumbermillId, out city, out lumbermill) || !forestManager.TryGetValue(forestId, out forest))
            {
                return(Error.ObjectNotFound);
            }

            // Count number of camps and verify there's enough space left
            int campCount = city.Count(s => objectTypeFactory.IsStructureType("ForestCamp", s));

            if (campCount >= 5)
            {
                return(Error.ForestCampMaxReached);
            }

            // Make sure some labors are being put in
            if (labors <= 0)
            {
                return(Error.LaborNotEnough);
            }

            // Make sure we have the specified number of laborers
            int currentInUsedLabor = lumbermill.City.Where(s => objectTypeFactory.IsStructureType("ForestCamp", s)).Sum(x => x.Stats.Labor);

            if (formula.GetLumbermillMaxLabor(lumbermill) < labors + currentInUsedLabor)
            {
                return(Error.LaborOverflow);
            }

            // Make sure it's within the limit of a forest camp
            if (labors > formula.GetForestCampMaxLabor(lumbermill))
            {
                return(Error.ForestCampMaxLaborReached);
            }

            // Make sure this user is not already milking this forest.
            if (forest.Count(obj => obj.City == city) > 0)
            {
                return(Error.AlreadyInForest);
            }

            // Cost requirement
            Resource cost = formula.StructureCost(city, structureCsvFactory.GetBaseStats(campType, 1));

            // Add labor count to the total cost
            cost.Labor += labors;

            if (!city.Resource.HasEnough(cost))
            {
                return(Error.ResourceNotEnough);
            }

            // find an open space around the forest
            uint emptyX = 0;
            uint emptyY = 0;

            foreach (var position in tileLocator.ForeachTile(forest.PrimaryPosition.X, forest.PrimaryPosition.Y, 1, false).Reverse())
            {
                // Make sure it's not taken
                if (world.Regions.GetObjectsInTile(position.X, position.Y).Any())
                {
                    continue;
                }

                emptyX = position.X;
                emptyY = position.Y;

                break;
            }

            if (emptyX == 0 || emptyY == 0)
            {
                return(Error.ForestFull);
            }

            world.Regions.LockRegion(emptyX, emptyY);

            // add structure to the map
            IStructure structure = city.CreateStructure(campType, 0, emptyX, emptyY);

            structure.BeginUpdate();
            structure["Rate"]     = 0; // Set initial rate for camp
            structure.Stats.Labor = labors;

            city.BeginUpdate();
            city.Resource.Subtract(cost);
            city.EndUpdate();

            if (!world.Regions.Add(structure))
            {
                city.ScheduleRemove(structure, false);
                city.BeginUpdate();
                city.Resource.Add(cost);
                city.EndUpdate();
                structure.EndUpdate();

                world.Regions.UnlockRegion(emptyX, emptyY);
                return(Error.MapFull);
            }

            structure.EndUpdate();

            campId = structure.ObjectId;

            forest.BeginUpdate();
            forest.AddLumberjack(structure);
            forest.RecalculateForest();
            forest.EndUpdate();

            lumbermill.BeginUpdate();
            lumbermill["Labor"] = formula.GetForestCampLaborerString(lumbermill);
            lumbermill.EndUpdate();

            // add to queue for completion
            var campBuildTime = structureCsvFactory.GetTime(campType, 1);
            var actionEndTime = formula.GetLumbermillCampBuildTime(campBuildTime, lumbermill, forest, tileLocator);

            endTime   = SystemClock.Now.AddSeconds(CalculateTime(actionEndTime));
            BeginTime = SystemClock.Now;

            city.References.Add(structure, this);

            world.Regions.UnlockRegion(emptyX, emptyY);

            return(Error.Ok);
        }