public void DeleteTroopObject_WhenTroopObjectCreated_AddsUnitsBackToOriginalTroop( [Frozen] ITroopStub stub, [Frozen] ISimpleStub unitsToRetreat, StationedPartialTroopObjectInitializer troopInitializer) { unitsToRetreat.TotalCount.Returns <ushort>(1); stub.State.Returns(TroopState.Stationed); stub.RemoveFromFormation(FormationType.Defense, Arg.Any <ISimpleStub>()).Returns(true); stub.City.Troops.Remove(Arg.Any <ushort>()).Returns(true); var newStub = Substitute.For <ITroopStub>(); stub.City.CreateTroopStub().Returns(newStub); ITroopObject troopObject = Substitute.For <ITroopObject>(); troopObject.Stub.Returns(newStub); stub.City.CreateTroopObject(newStub, Arg.Any <uint>(), Arg.Any <uint>()).Returns(troopObject); troopInitializer.GetTroopObject(out troopObject); troopInitializer.DeleteTroopObject(); stub.Received(1).BeginUpdate(); stub.Received(1).AddAllToFormation(FormationType.Defense, newStub); stub.Received(1).EndUpdate(); }
public AttackCombatUnit(uint id, uint battleId, ITroopObject troopObject, FormationType formation, ushort type, byte lvl, ushort count, UnitFactory unitFactory, IBattleFormulas battleFormulas, Formula formula, ITileLocator tileLocator, IDbManager dbManager) : base(id, battleId, battleFormulas, dbManager) { this.troopObject = troopObject; this.formation = formation; this.type = type; this.count = count; this.formula = formula; this.tileLocator = tileLocator; this.lvl = lvl; stats = troopObject.Stub.Template[type]; LeftOverHp = stats.MaxHp; eachUnitUpkeep = unitFactory.GetUnitStats(type, lvl).Upkeep; }
private void SetLootedResources(IBattleManager battle, ITroopObject troopObject, ICombatGroup combatGroup) { if (!battle.BattleStarted) { return; } // Calculate bonus Resource resource = battleFormula.GetBonusResources(troopObject, originalUnitCount, troopObject.Stub.TotalCount); // Destroyed Structure bonus resource.Add(bonus); // Copy looted resources since we'll be modifying the troop's loot variable var looted = new Resource(troopObject.Stats.Loot); // Add bonus to troop object Resource returning; Resource actual; Resource cap = new Resource(troopObject.Stub.Carry / 1, troopObject.Stub.Carry / 2, troopObject.Stub.Carry / Config.battle_loot_resource_iron_ratio, troopObject.Stub.Carry / 1, troopObject.Stub.Carry / Config.battle_loot_resource_labor_ratio); troopObject.Stats.Loot.Add(resource, cap, out actual, out returning); // Update battle report view with actual received bonus battle.BattleReport.SetLootedResources(combatGroup.Owner, combatGroup.Id, battle.BattleId, looted, actual); }
public void Lock_CityIdTroopId_WhenCityIsFound_ShouldReturnLockedCity( [Frozen] IGameObjectLocator locator, ICity city, ITroopObject troop, DefaultLocker locker) { ICity outCity; locator.TryGetObjects(1, out outCity).Returns(call => { call[1] = city; return(true); }); ITroopObject outTroop; city.TryGetTroop(2, out outTroop).Returns(call => { call[1] = troop; return(true); }); ICity lockedCity; ITroopObject lockedTroop; var multiObjLock = locker.Lock(1, 2, out lockedCity, out lockedTroop); ((object)lockedCity).Should().Be(city); lockedTroop.Should().Be(troop); multiObjLock.Received(1) .Lock(Arg.Is <ILockable[]>(itemsLocked => itemsLocked.SequenceEqual(new[] { city }))); }
private bool CalculateNextPosition(ITroopObject obj) { if (distanceRemaining <= 0) { return(false); } var recordForeach = new RecordForeach { ShortestDistance = int.MaxValue, IsShortestDistanceDiagonal = false }; foreach (var position in tileLocator.ForeachTile(obj.PrimaryPosition.X, obj.PrimaryPosition.Y, 1, false)) { int distance = tileLocator.TileDistance(position, 1, new Position(x, y), 1); if (distance < recordForeach.ShortestDistance) { recordForeach.ShortestDistance = distance; recordForeach.X = position.X; recordForeach.Y = position.Y; recordForeach.IsShortestDistanceDiagonal = IsDiagonal(position.Y, obj.PrimaryPosition.X, obj.PrimaryPosition.Y); } else if (distance == recordForeach.ShortestDistance && !recordForeach.IsShortestDistanceDiagonal) { recordForeach.ShortestDistance = distance; recordForeach.X = position.X; recordForeach.Y = position.Y; recordForeach.IsShortestDistanceDiagonal = IsDiagonal(position.Y, obj.PrimaryPosition.X, obj.PrimaryPosition.Y); } } nextX = recordForeach.X; nextY = recordForeach.Y; return(true); }
public bool Add(uint objId, ITroopObject troop, bool save) { lock (objLock) { if (!troopobjects.TryAdd(objId, troop)) { return(false); } troop.City = this; objectIdGen.Set(objId); if (save) { dbManager.Save(troop); } troop.ObjectUpdated += OnObjectUpdated; ObjectAdded(this, new GameObjectArgs { Object = troop }); } return(true); }
public Error GetTroopObject(out ITroopObject troopObject) { if (newTroopObject != null) { troopObject = newTroopObject; return(Error.Ok); } if (stub.State != TroopState.Stationed) { troopObject = null; return(Error.TroopNotStationed); } originalStation = stub.Station; if (!stub.Station.Troops.RemoveStationed(stub.StationTroopId)) { troopObject = null; return(Error.TroopNotStationed); } troopObject = stub.City.CreateTroopObject(stub, originalStation.PrimaryPosition.X, originalStation.PrimaryPosition.Y + 1); newTroopObject = troopObject; troopObject.BeginUpdate(); troopObject.Stats = new TroopStats(formula.GetTroopRadius(stub, null), formula.GetTroopSpeed(stub)); world.Regions.Add(troopObject); troopObject.EndUpdate(); return(Error.Ok); }
public AssignmentTroopObjectInitializer(ITroopObject existingTroopObject, TroopBattleGroup group, AttackMode mode, Formula formula) { this.existingTroopObject = existingTroopObject; this.group = group; this.mode = mode; this.formula = formula; }
private bool TroopObjectCreateFromCity(ICity city, ISimpleStub stub, uint x, uint y, out ITroopObject troopObject) { if (stub.TotalCount == 0 || !city.DefaultTroop.RemoveFromFormation(FormationType.Normal, stub)) { troopObject = null; return(false); } var troopStub = city.CreateTroopStub(); troopStub.BeginUpdate(); troopStub.Add(stub); troopStub.EndUpdate(); troopObject = city.CreateTroopObject(troopStub, x, y + 1); troopObject.BeginUpdate(); troopObject.Stats = new TroopStats(formula.GetTroopRadius(troopStub, null), formula.GetTroopSpeed(troopStub)); world.Regions.Add(troopObject); troopObject.EndUpdate(); return(true); }
public Error GetTroopObject(out ITroopObject troopObject) { if (newTroopObject != null) { troopObject = newTroopObject; return(Error.Ok); } ICity city; if (!gameObjectLocator.TryGetObjects(cityId, out city)) { troopObject = null; return(Error.ObjectNotFound); } if (!TroopObjectCreateFromCity(city, simpleStub, city.PrimaryPosition.X, city.PrimaryPosition.Y, out troopObject)) { troopObject = null; return(Error.TroopChanged); } newTroopObject = troopObject; //Load the units stats into the stub troopObject.Stub.BeginUpdate(); troopObject.Stub.Template.LoadStats(group); troopObject.Stub.InitialCount = troopObject.Stub.TotalCount; troopObject.Stub.RetreatCount = (ushort)formula.GetAttackModeTolerance(troopObject.Stub.TotalCount, mode); troopObject.Stub.AttackMode = mode; troopObject.Stub.EndUpdate(); return(Error.Ok); }
public virtual void TroopObjectCreate(ICity city, ITroopStub stub, out ITroopObject troopObject) { troopObject = city.CreateTroopObject(stub, city.PrimaryPosition.X, city.PrimaryPosition.Y); troopObject.BeginUpdate(); troopObject.Stats = new TroopStats(formula.GetTroopRadius(stub, null), formula.GetTroopSpeed(stub)); world.Regions.Add(troopObject); troopObject.EndUpdate(); }
public virtual void TroopObjectStation(ITroopObject troop, IStation station) { station.Troops.AddStationed(troop.Stub); troop.BeginUpdate(); regions.Remove(troop); troop.City.ScheduleRemove(troop, false); troop.EndUpdate(); }
private void MoveFromAttackToDefenseFormation(ITroopObject troopObject) { if (!troopObject.Stub.HasFormation(FormationType.Defense)) { troopObject.Stub.BeginUpdate(); troopObject.Stub.ChangeFormation(FormationType.Attack, FormationType.Defense); troopObject.Stub.EndUpdate(); } }
private void StationTroopInStronghold(ITroopObject troopObject, IStronghold stronghold, TroopState stubState = TroopState.Stationed) { procedure.TroopObjectStation(troopObject, stronghold); if (troopObject.Stub.State != stubState) { troopObject.Stub.BeginUpdate(); troopObject.Stub.State = stubState; troopObject.Stub.EndUpdate(); } StateChange(ActionState.Completed); }
public Error SetTroopTheme(ITroopObject troop, string id) { if (!HasTheme(troop.City.Owner, id)) { return(Error.ThemeNotPurchased); } troop.BeginUpdate(); troop.Theme = id; troop.EndUpdate(); return(Error.Ok); }
private bool TroopIsDead(ITroopObject troopObject, ICity city) { if (troopObject.Stub.TotalCount != 0) { return(false); } // Remove troop since he's dead city.BeginUpdate(); procedure.TroopObjectDelete(troopObject, false); city.EndUpdate(); return(true); }
public bool ScheduleRemove(ITroopObject obj, bool wasKilled) { lock (objLock) { if (!troopobjects.ContainsKey(obj.ObjectId) || obj.IsBlocked > 0) { return(false); } var removeAction = actionFactory.CreateObjectRemovePassiveAction(Id, obj.ObjectId, wasKilled, new List <uint>()); return(Worker.DoPassive(this, removeAction, false) == Error.Ok); } }
public virtual Resource GetBonusResources(ITroopObject troop, int originalCount, int remainingCount) { if (originalCount == 0) { return(new Resource()); } int max = troop.City.Technologies.GetEffects(EffectCode.SunDance, EffectInheritance.Self) .DefaultIfEmpty() .Sum(x => x != null ? (int)x.Value[0] : 0); float troopsLostPercentage = 1 - remainingCount / (float)originalCount; return(new Resource(troop.Stats.Loot) * (troopsLostPercentage) * (1f + (Config.Random.Next(max) / 100f))); }
public virtual void JoinOrCreateCityBattle(ICity targetCity, ITroopObject attackerTroopObject, IDbManager dbManager, out ICombatGroup combatGroup, out uint battleId) { // If battle already exists, then we just join it in also bringing any new units if (targetCity.Battle != null) { AddLocalUnitsToBattle(targetCity.Battle, targetCity); AddLocalStructuresToBattle(targetCity.Battle, targetCity, attackerTroopObject); combatGroup = battleProcedure.AddAttackerToBattle(targetCity.Battle, attackerTroopObject); } // Otherwise, the battle has to be created else { targetCity.Battle = battleManagerFactory.CreateBattleManager(new BattleLocation(BattleLocationType.City, targetCity.Id), new BattleOwner(BattleOwnerType.City, targetCity.Id), targetCity); var battlePassiveAction = actionFactory.CreateCityBattlePassiveAction(targetCity.Id); AddLocalStructuresToBattle(targetCity.Battle, targetCity, attackerTroopObject); combatGroup = battleProcedure.AddAttackerToBattle(targetCity.Battle, attackerTroopObject); Error result = targetCity.Worker.DoPassive(targetCity, battlePassiveAction, false); if (result != Error.Ok) { throw new Exception(string.Format("Failed to start a battle due to error {0}", result)); } // send message to player telling them to build tower and basement if (targetCity.Owner.NeverAttacked) { const string warnMessage = @"Now that you are out of newbie protection, other players are able to attack you. Someone has just finished attacking your town and has probably taken some resources from you. You can see how strong the attack was and how much resources they took in the battle report that was generated for this battle. You have several things you can do to help protect your city from attacks. The first is to build a basement which can be done from your lumbermill. Basements will protect up to a certain amount of resources from being looted. If you plan on going offline for a while, your basements can also build temporary basements which will extend the amount of protected resources. Another option is increase your city's defenses. The best way to do this early in the game is to build some towers. Towers are built from the training ground or barrack and provide defense for structures within its radius. Any units in your city will also join the battle but be careful since an attacker may kill your entire army in a battle. You can hide your units if you don't want them to defend your town when you get attacked. Good luck and feel free to ask for help in the chat if you have any questions."; targetCity.Owner.SendSystemMessage(null, "Your city has been attacked", warnMessage); targetCity.Owner.NeverAttacked = false; dbManager.Save(targetCity.Owner); } } battleId = targetCity.Battle.BattleId; }
protected virtual void AddLocalStructuresToBattle(IBattleManager battleManager, ICity targetCity, ITroopObject attackerTroopObject) { var localGroup = GetOrCreateLocalGroup(targetCity.Battle, targetCity); foreach (IStructure structure in GetStructuresInRadius(targetCity, attackerTroopObject) .Where(structure => structure.State.Type == ObjectState.Normal && CanStructureBeAttacked(structure) == Error.Ok)) { structure.BeginUpdate(); structure.State = GameObjectStateFactory.BattleState(battleManager.BattleId); structure.EndUpdate(); localGroup.Add(combatUnitFactory.CreateStructureCombatUnit(battleManager, structure)); } }
public AttackCombatUnit[] CreateAttackCombatUnit(IBattleManager battleManager, ITroopObject troop, FormationType formation, ushort type, ushort count) { var battleFormulas = kernel.Get <IBattleFormulas>(); IBaseUnitStats template = troop.City.Template[type]; BattleStats stats = troop.Stub.Template[type]; var groupSize = (from effect in troop.City.Technologies.GetEffects(EffectCode.UnitStatMod) where ((string)effect.Value[0]).ToLower() == "groupsize" && battleFormulas.UnitStatModCheck(stats.Base, TroopBattleGroup.Attack, (string)effect.Value[3]) select(int) effect.Value[2]).DefaultIfEmpty <int>(0).Max() + stats.Base.GroupSize; var units = new AttackCombatUnit[(count - 1) / groupSize + 1]; int i = 0; do { ushort size = (ushort)(groupSize > count ? count : groupSize); AttackCombatUnit newUnit = new AttackCombatUnit(battleManager.GetNextCombatObjectId(), battleManager.BattleId, troop, formation, type, template.Lvl, size, kernel.Get <UnitFactory>(), battleFormulas, kernel.Get <Formula>(), kernel.Get <ITileLocator>(), kernel.Get <IDbManager>()); units[i++] = newUnit; count -= size; }while (count > 0); return(units); }
/// <summary> /// Removes the object from the city. This function should NOT be called directly. Use ScheduleRemove instead! /// </summary> /// <param name="troop"></param> public void DoRemove(ITroopObject troop) { lock (objLock) { if (!troopobjects.TryRemove(troop.ObjectId, out troop)) { return; } dbManager.Delete(troop); troop.ObjectUpdated -= OnObjectUpdated; ObjectRemoved(this, new GameObjectArgs { Object = troop }); } }
/// <summary> /// DB loader constructor /// </summary> public AttackCombatUnit(uint id, uint battleId, ITroopObject troopObject, FormationType formation, ushort type, byte lvl, ushort count, decimal leftOverHp, Resource loot, UnitFactory unitFactory, IBattleFormulas battleFormulas, Formula formula, ITileLocator tileLocator, IDbManager dbManager) : this(id, battleId, troopObject, formation, type, lvl, count, unitFactory, battleFormulas, formula, tileLocator, dbManager) { LeftOverHp = leftOverHp; this.loot = loot; }
public Error GetTroopObject(out ITroopObject troopObject) { if (newTroopObject != null) { troopObject = newTroopObject; return(Error.Ok); } if (unitsToRetreat.TotalCount == 0) { troopObject = null; return(Error.TroopEmpty); } if (stub.State != TroopState.Stationed) { troopObject = null; return(Error.TroopNotStationed); } if (!stub.RemoveFromFormation(FormationType.Defense, unitsToRetreat)) { troopObject = null; return(Error.TroopChanged); } var newTroopStub = stub.City.CreateTroopStub(); newTroopStub.BeginUpdate(); newTroopStub.Add(unitsToRetreat); newTroopStub.EndUpdate(); newTroopObject = stub.City.CreateTroopObject(newTroopStub, stub.Station.PrimaryPosition.X, stub.Station.PrimaryPosition.Y + 1); newTroopObject.BeginUpdate(); newTroopObject.Stats = new TroopStats(formula.GetTroopRadius(stub, null), formula.GetTroopSpeed(stub)); world.Regions.Add(newTroopObject); newTroopObject.EndUpdate(); troopObject = newTroopObject; return(Error.Ok); }
public Error GetTroopObject(out ITroopObject troopObject) { if (newTroopObject != null) { troopObject = newTroopObject; return(Error.Ok); } troopObject = existingTroopObject; newTroopObject = troopObject; //Load the units stats into the stub troopObject.Stub.BeginUpdate(); troopObject.Stub.Template.LoadStats(group); troopObject.Stub.InitialCount = troopObject.Stub.TotalCount; troopObject.Stub.RetreatCount = (ushort)formula.GetAttackModeTolerance(troopObject.Stub.TotalCount, mode); troopObject.Stub.AttackMode = mode; troopObject.Stub.EndUpdate(); return(Error.Ok); }
public void GetTroopObject_WhenAbleToRetreat_LoadsStats( [Frozen] ITroopStub stub, [Frozen] ISimpleStub unitsToRetreat, [FrozenMock] Formula formula, ITroopObject newTroopObject, StationedPartialTroopObjectInitializer troopInitializer) { unitsToRetreat.TotalCount.Returns <ushort>(1); formula.GetTroopRadius(stub, null).Returns <byte>(34); formula.GetTroopSpeed(stub).Returns(44); stub.State.Returns(TroopState.Stationed); stub.RemoveFromFormation(FormationType.Defense, Arg.Any <ISimpleStub>()).Returns(true); ITroopObject troopObject; troopInitializer.GetTroopObject(out troopObject).Should().Be(Error.Ok); troopObject.Stats.Speed.Should().Be(44); troopObject.Stats.AttackRadius.Should().Be(34); }
public virtual bool TroopObjectDelete(ITroopObject troop, bool addBackToNormal) { if (addBackToNormal) { AddToNormal(troop.Stub, troop.City.DefaultTroop); troop.City.BeginUpdate(); troop.City.Resource.Add(troop.Stats.Loot); troop.City.LootStolen += (uint)troop.Stats.Loot.Total; troop.City.EndUpdate(); } troop.City.Troops.Remove(troop.Stub.TroopId); troop.BeginUpdate(); world.Regions.Remove(troop); troop.City.ScheduleRemove(troop, false); troop.Stub = null; troop.EndUpdate(); return(true); }
public virtual void JoinOrCreateStrongholdGateBattle(IStronghold targetStronghold, ITroopObject attackerTroopObject, out ICombatGroup combatGroup, out uint battleId) { // If battle already exists, then we just join it in also bringing any new units if (targetStronghold.GateBattle != null) { combatGroup = battleProcedure.AddAttackerToBattle(targetStronghold.GateBattle, attackerTroopObject); } // Otherwise, the battle has to be created else { var battleOwner = targetStronghold.Tribe == null ? new BattleOwner(BattleOwnerType.Stronghold, targetStronghold.ObjectId) : new BattleOwner(BattleOwnerType.Tribe, targetStronghold.Tribe.Id); targetStronghold.GateBattle = battleManagerFactory.CreateStrongholdGateBattleManager( new BattleLocation(BattleLocationType.StrongholdGate, targetStronghold.ObjectId), battleOwner, targetStronghold); combatGroup = battleProcedure.AddAttackerToBattle(targetStronghold.GateBattle, attackerTroopObject); var battlePassiveAction = actionFactory.CreateStrongholdGateBattlePassiveAction(targetStronghold.ObjectId); Error result = targetStronghold.Worker.DoPassive(targetStronghold, battlePassiveAction, false); if (result != Error.Ok) { throw new Exception(string.Format("Failed to start a battle due to error {0}", result)); } targetStronghold.BeginUpdate(); targetStronghold.State = GameObjectStateFactory.BattleState(targetStronghold.GateBattle.BattleId); targetStronghold.EndUpdate(); } battleId = targetStronghold.GateBattle.BattleId; }
public virtual void JoinOrCreateBarbarianTribeBattle(IBarbarianTribe barbarianTribe, ITroopObject attackerTroopObject, out ICombatGroup combatGroup, out uint battleId) { // If battle already exists, then we just join it in also bringing any new units if (barbarianTribe.Battle != null) { combatGroup = battleProcedure.AddAttackerToBattle(barbarianTribe.Battle, attackerTroopObject); } // Otherwise, the battle has to be created else { var battleOwner = new BattleOwner(BattleOwnerType.BarbarianTribe, barbarianTribe.ObjectId); barbarianTribe.Battle = battleManagerFactory.CreateBarbarianBattleManager(new BattleLocation(BattleLocationType.BarbarianTribe, barbarianTribe.ObjectId), battleOwner, barbarianTribe); combatGroup = battleProcedure.AddAttackerToBattle(barbarianTribe.Battle, attackerTroopObject); var battlePassiveAction = actionFactory.CreateBarbarianTribeBattlePassiveAction(barbarianTribe.ObjectId); Error result = barbarianTribe.Worker.DoPassive(barbarianTribe, battlePassiveAction, false); if (result != Error.Ok) { throw new Exception(string.Format("Failed to start a battle due to error {0}", result)); } barbarianTribe.BeginUpdate(); barbarianTribe.LastAttacked = DateTime.UtcNow; barbarianTribe.State = GameObjectStateFactory.BattleState(barbarianTribe.Battle.BattleId); barbarianTribe.EndUpdate(); } battleId = barbarianTribe.Battle.BattleId; }
public void Lock_CityIdTroopId_WhenTroopIsNotFound_ShouldReturnEmptyLockAndNullCity( [Frozen] IGameObjectLocator locator, [FrozenMock] DefaultMultiObjectLock.Factory lockFactory, IMultiObjectLock cityLock, IMultiObjectLock emptyLock, ICity city, ITroopObject troop, DefaultLocker locker) { lockFactory().Returns(cityLock, emptyLock); ICity outCity; locator.TryGetObjects(1, out outCity).Returns(call => { call[1] = city; return(true); }); ITroopObject outTroop; city.TryGetTroop(2, out outTroop).Returns(false); ICity lockedCity; ITroopObject lockedTroop; var multiObjLock = locker.Lock(1, 2, out lockedCity, out lockedTroop); ((object)lockedCity).Should().BeNull(); lockedTroop.Should().BeNull(); multiObjLock.Should().Be(emptyLock); emptyLock.Received(1) .Lock(Arg.Is <ILockable[]>(itemsLocked => !itemsLocked.Any())); cityLock.Received(1) .Lock(Arg.Is <ILockable[]>(itemsLocked => itemsLocked.SequenceEqual(new[] { city }))); cityLock.Received(1).UnlockAll(); }