Пример #1
0
        public void GetInstantTrainCount_WhenEffectIsAssociateWithMultipleUnits([Frozen] IObjectTypeFactory objectTypeFactory,
                                                                                Formula formula,
                                                                                IStructure structure,
                                                                                ITroopStub troopStub)
        {
            var effects = new List <Effect>
            {
                new Effect
                {
                    Id        = EffectCode.UnitTrainInstantTime,
                    IsPrivate = false,
                    Location  = EffectLocation.City,
                    Value     = new object[] { 1, "BarrackUnits", 50, 50 }
                }
            };

            structure.City.Technologies.GetEffects(EffectCode.UnitTrainInstantTime).Returns(effects);
            objectTypeFactory.IsObjectType("BarrackUnits", 101).Returns(true);
            objectTypeFactory.IsObjectType("BarrackUnits", 102).Returns(true);
            objectTypeFactory.IsObjectType("BarrackUnits", 105).Returns(false);
            structure.Type.Returns((ushort)1);

            troopStub.ToUnitList().ReturnsForAnyArgs(new List <Unit>
            {
                new Unit(101, 10),
                new Unit(102, 25),
                new Unit(105, 10)
            });
            structure.City.Troops.MyStubs().Returns(new List <ITroopStub> {
                troopStub
            });

            formula.GetInstantTrainCount(structure).Should().Be(15);
        }
Пример #2
0
        public virtual Error CityMaxConcurrentBuildActions(ushort structureType, uint currentActionId, ICity city, IObjectTypeFactory objectTypeFactory)
        {
            int maxConcurrentUpgrades = ConcurrentBuildUpgrades(city.MainBuilding.Lvl);

            if (!objectTypeFactory.IsObjectType("UnlimitedBuilding", structureType) &&
                city.Worker.ActiveActions.Values.Count(action =>
            {
                if (action.ActionId == currentActionId)
                {
                    return(false);
                }

                if (action.Type == ActionType.StructureUpgradeActive)
                {
                    return(true);
                }

                if (action.Type != ActionType.StructureBuildActive)
                {
                    return(false);
                }

                return(!objectTypeFactory.IsObjectType("UnlimitedBuilding", ((StructureBuildActiveAction)action).BuildType));
            }) >= maxConcurrentUpgrades)
            {
                return(Error.ActionTotalMaxReached);
            }

            return(Error.Ok);
        }
Пример #3
0
        private void BattleActionAttacked(IBattleManager battle,
                                          BattleManager.BattleSide attackingside,
                                          ICombatGroup attackerGroup,
                                          ICombatObject attacker,
                                          ICombatGroup targetGroup,
                                          ICombatObject target,
                                          decimal damage,
                                          int attackerCount,
                                          int targetCount)
        {
            if (target.ClassType == BattleClass.Structure && attackingside == BattleManager.BattleSide.Attack && target.IsDead)
            {
                if (objectTypeFactory.IsObjectType("BattleNoStaminaReduction", target.Type))
                {
                    return;
                }

                if (objectTypeFactory.IsObjectType("BattleNoStaminaReductionEarlyLevels", target.Type) && target.Lvl < 5)
                {
                    return;
                }

                Stamina = BattleFormulas.GetStaminaStructureDestroyed(Stamina, target);
            }
        }
Пример #4
0
        public void GetInstantTrainCount_WhenThereAreMultipleEffects([Frozen] IObjectTypeFactory objectTypeFactory,
                                                                     Formula formula,
                                                                     IStructure structure)
        {
            var effects = new List <Effect>
            {
                new Effect
                {
                    Id        = EffectCode.UnitTrainInstantTime,
                    IsPrivate = false,
                    Location  = EffectLocation.City,
                    Value     = new object[] { 1, "BarrackUnits", 20, 150 }
                },
                new Effect
                {
                    Id        = EffectCode.UnitTrainInstantTime,
                    IsPrivate = false,
                    Location  = EffectLocation.City,
                    Value     = new object[] { 1, "BarrackUnits", 30, 150 }
                }
            };

            structure.City.Technologies.GetEffects(EffectCode.UnitTrainInstantTime).Returns(effects);
            objectTypeFactory.IsObjectType("BarrackUnits", 101).Returns(true);
            structure.Type.Returns((ushort)1);
            formula.GetInstantTrainCount(structure).Should().Be(50);
        }
Пример #5
0
        public StructureBuildActiveActionExecuteBuilder(IFixture fixture)
        {
            this.fixture = fixture;

            requirementCsvFactory = fixture.Freeze <IRequirementCsvFactory>();
            requirementCsvFactory
            .GetLayoutRequirement(Arg.Any <ushort>(), Arg.Any <byte>())
            .Validate(Arg.Any <IStructure>(), Arg.Any <ushort>(), Arg.Any <uint>(), Arg.Any <uint>(), Arg.Any <byte>())
            .Returns(true);

            structureBaseStats = fixture.Freeze <IStructureBaseStats>();
            structureBaseStats.Size.Returns <byte>(0);
            var structureCost = new Resource(1234, 8446, 1343, 1234, 1246);

            structureBaseStats.Cost.Returns(structureCost);

            var structure = fixture.Freeze <IStructure>();

            structure.Stats.Base.Returns(structureBaseStats);

            objectTypeFactory = fixture.Freeze <IObjectTypeFactory>();
            objectTypeFactory.IsObjectType("NoRoadRequired", Arg.Any <ushort>()).Returns(true);

            city = fixture.Create <ICity>();
            city.PrimaryPosition.Returns(new Position(99, 98));
            city.Radius.Returns <byte>(5);
            city.Resource.HasEnough(structureBaseStats.Cost).Returns(true);
            city.CreateStructure(Arg.Any <ushort>(), Arg.Any <byte>(), Arg.Any <uint>(), Arg.Any <uint>()).Returns(structure);

            roadPathFinder = fixture.Freeze <IRoadPathFinder>();
            roadPathFinder.CanBuild(Arg.Any <Position>(), Arg.Any <byte>(), city, Arg.Any <bool>()).Returns(Error.Ok);

            tileLocator = fixture.Freeze <ITileLocator>();
            tileLocator.TileDistance(new Position(99, 98), 1, Arg.Any <Position>(), 1).Returns(1);

            world = fixture.Freeze <IWorld>();
            ICity outCity;

            world.TryGetObjects(Arg.Any <uint>(), out outCity).Returns(x =>
            {
                x[1] = city;
                return(true);
            });
            world.Regions.GetObjectsInTile(Arg.Any <uint>(), Arg.Any <uint>()).Returns(new List <ISimpleGameObject>());
            world.Regions.IsValidXandY(0, 0).ReturnsForAnyArgs(true);
            world.Regions.Add(structure).Returns(true);

            structureCsvFactory = fixture.Freeze <IStructureCsvFactory>();
            structureCsvFactory.GetBaseStats(0, 0).ReturnsForAnyArgs(structureBaseStats);

            formula = Substitute.For <Formula>();
            formula.CityMaxConcurrentBuildActions(0, 0, null, null).ReturnsForAnyArgs(Error.Ok);
            formula.StructureCost(null, null).ReturnsForAnyArgs(structureCost);
            fixture.Register(() => formula);
        }
Пример #6
0
        public virtual int GetNumberOfHits(ICombatObject currentAttacker, ICombatList defenderCombatList)
        {
            int splashEvery200 = objectTypeFactory.IsObjectType("SplashEvery200", currentAttacker.Type) ? (Math.Min(defenderCombatList.UpkeepExcludingWaitingToJoinBattle, 4000) / 200) : 0;

            return(currentAttacker.Stats.Splash == 0 ? 1 : currentAttacker.Stats.Splash + splashEvery200);
        }
Пример #7
0
        public Error CanBuild(Position position, byte size, ICity city, bool requiresRoad)
        {
            var buildingPositions = tileLocator.ForeachMultitile(position.X, position.Y, size).ToArray();
            var buildingNeighbors = tileLocator.ForeachRadius(position.X, position.Y, size, 1).ToArray();

            var mainBuildingPositions = tileLocator.ForeachMultitile(city.MainBuilding).ToArray();

            var roadsBeingBuiltOn = buildingPositions.Any(buildingPosition => world.Roads.IsRoad(buildingPosition.X, buildingPosition.Y));

            if (!requiresRoad)
            {
                // Cant build on road if this building doesnt require roads
                return(roadsBeingBuiltOn ? Error.RoadDestroyUniquePath : Error.Ok);
            }

            if (roadsBeingBuiltOn)
            {
                // All structures should still have a valid path if we are building on top of a road
                foreach (var str in city)
                {
                    if (str.IsMainBuilding || objectTypeFactory.IsObjectType("NoRoadRequired", str.Type))
                    {
                        continue;
                    }

                    if (!HasPath(start: str.PrimaryPosition,
                                 startSize: str.Size,
                                 city: city,
                                 excludedPoints: buildingPositions))
                    {
                        return(Error.RoadDestroyUniquePath);
                    }
                }

                // All neighboring roads should have a different path
                foreach (var neighborPosition in buildingNeighbors)
                {
                    if (mainBuildingPositions.Contains(neighborPosition) || !world.Roads.IsRoad(neighborPosition.X, neighborPosition.Y))
                    {
                        continue;
                    }

                    if (!HasPath(start: neighborPosition,
                                 startSize: 1,
                                 city: city,
                                 excludedPoints: buildingPositions))
                    {
                        return(Error.RoadDestroyUniquePath);
                    }
                }
            }

            // There should be a road around this building
            foreach (var neighborPosition in buildingNeighbors)
            {
                bool hasStructure = world.Regions.GetObjectsInTile(neighborPosition.X, neighborPosition.Y)
                                    .Any(obj => obj is IStructure);

                if (hasStructure || !world.Roads.IsRoad(neighborPosition.X, neighborPosition.Y))
                {
                    continue;
                }

                if (roadsBeingBuiltOn && !HasPath(start: neighborPosition,
                                                  startSize: 1,
                                                  city: city,
                                                  excludedPoints: buildingPositions))
                {
                    continue;
                }

                return(Error.Ok);
            }

            return(Error.RoadNotAround);
        }
Пример #8
0
        public override Error Execute()
        {
            ICity city;

            if (!world.TryGetObjects(cityId, out city))
            {
                return(Error.ObjectNotFound);
            }

            var maxConcurrentUpgradesResult = formula.CityMaxConcurrentBuildActions(type, ActionId, city, objectTypeFactory);

            if (maxConcurrentUpgradesResult != Error.Ok)
            {
                return(maxConcurrentUpgradesResult);
            }

            var structureBaseStats = structureCsvFactory.GetBaseStats(type, level);

            var lockedRegions = world.Regions.LockMultitileRegions(X, Y, structureBaseStats.Size);

            foreach (var position in tileLocator.ForeachMultitile(X, Y, structureBaseStats.Size))
            {
                var tileType = world.Regions.GetTileType(position.X, position.Y);
                // tile requirement
                if (!string.IsNullOrEmpty(tileRequirement) && !objectTypeFactory.IsTileType(tileRequirement, tileType))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.TileMismatch);
                }

                // Only allow buildings that require resource tile to built on them
                if (tileRequirement != "TileResource" && objectTypeFactory.IsTileType("TileResource", tileType))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.TileMismatch);
                }

                // dont allow building on edge of world
                if (!world.Regions.IsValidXandY(position.X, position.Y))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.ActionInvalid);
                }

                // radius requirements
                if (tileLocator.TileDistance(city.PrimaryPosition, 1, position, 1) >= city.Radius)
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.NotWithinWalls);
                }

                // check if tile is occupied
                if (world.Regions.GetObjectsInTile(position.X, position.Y).Any(obj => obj is IStructure))
                {
                    world.Regions.UnlockRegions(lockedRegions);
                    return(Error.StructureExists);
                }
            }

            // cost requirement
            cost = formula.StructureCost(city, structureBaseStats);
            if (!city.Resource.HasEnough(cost))
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(Error.ResourceNotEnough);
            }

            // layout requirement
            if (!requirementCsvFactory.GetLayoutRequirement(type, level).Validate(WorkerObject as IStructure, type, X, Y, structureBaseStats.Size))
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(Error.LayoutNotFullfilled);
            }

            // check for road requirements
            var requiresRoad = !objectTypeFactory.IsObjectType("NoRoadRequired", type);
            var canBuild     = roadPathFinder.CanBuild(new Position(X, Y), structureBaseStats.Size, city, requiresRoad);

            if (canBuild != Error.Ok)
            {
                world.Regions.UnlockRegions(lockedRegions);
                return(canBuild);
            }

            // add structure to the map
            IStructure structure = city.CreateStructure(type, 0, X, Y);

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

            structure.BeginUpdate();

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

                world.Regions.UnlockRegions(lockedRegions);
                return(Error.MapFull);
            }

            structure.EndUpdate();

            callbackProcedure.OnStructureUpgrade(structure);

            structureId = structure.ObjectId;

            // add to queue for completion
            var buildTime = formula.BuildTime(structureBaseStats.BuildTime, city, city.Technologies);

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

            city.References.Add(structure, this);

            world.Regions.UnlockRegions(lockedRegions);
            return(Error.Ok);
        }