private Dictionary <int, int> GetNaughtyPrisoners(TroopRoster prisonRoster) { Dictionary <int, int> nPrisoners = new Dictionary <int, int>(); for (int i = 0; i < prisonRoster.Count; i++) { CharacterObject characterAtIndex = prisonRoster.GetCharacterAtIndex(i); if (IsPrisonerRecruitable(characterAtIndex)) { int naughty = 0; if (GlobalSettings <Settings> .Instance.ApplyEachUnit) { naughty = prisonRoster.GetElementNumber(i) - GetRecruitableNumberInternal(characterAtIndex); } else { naughty = 1; } if (naughty > 0) { nPrisoners[i] = naughty; } } } return(nPrisoners); }
private void DailyTick() { MobileParty mainParty = MobileParty.MainParty; TroopRoster memberRoster = mainParty.MemberRoster; if (memberRoster.TotalManCount >= mainParty.Party.PartySizeLimit) { return; } TroopRoster prisonRoster = mainParty.PrisonRoster; if (prisonRoster.TotalManCount == 0) { return; } IRecruitPrisonersCampaignBehavior recruitPrisonerBehavior = Campaign.Current.GetCampaignBehavior <IRecruitPrisonersCampaignBehavior>(); if (recruitPrisonerBehavior == null) { return; } List <Tuple <CharacterObject, int> > recruitablePrisoners = new List <Tuple <CharacterObject, int> >(); for (int i = 0; i < prisonRoster.Count; i++) { CharacterObject prisoner = prisonRoster.GetCharacterAtIndex(i); int numRecruitable = recruitPrisonerBehavior.GetRecruitableNumber(prisoner); if (numRecruitable > 0) { recruitablePrisoners.Add(new Tuple <CharacterObject, int>(prisoner, numRecruitable)); } } recruitablePrisoners.Sort((x, y) => y.Item1.Tier.CompareTo(x.Item1.Tier)); for (int i = 0; i < recruitablePrisoners.Count; i++) { CharacterObject prisoner = recruitablePrisoners[i].Item1; int numRecruitable = recruitablePrisoners[i].Item2; while (numRecruitable > 0) { recruitPrisonerBehavior.SetRecruitableNumber(prisoner, --numRecruitable); prisonRoster.AddToCounts(prisoner, -1, false, 0, 0, true, -1); mainParty.MemberRoster.AddToCounts(prisoner, 1, false, 0, 0, true, -1); if (memberRoster.TotalManCount >= mainParty.Party.PartySizeLimit) { break; } } if (memberRoster.TotalManCount >= mainParty.Party.PartySizeLimit) { break; } } }
private void outputRoster(TroopRoster roster) { for (int i = 0; i < roster.Count(); i++) { CharacterObject troop = roster.GetCharacterAtIndex(i); Debug.WriteLine("roster member: " + troop.Name + ", count: " + roster.GetTroopCount(troop)); } }
private void DailyTick() { Settings settings = GlobalSettings <Settings> .Instance; TroopRoster prisonRoster = MobileParty.MainParty.PrisonRoster; // I'm not sure how the following line redirects to my function. Todd Howard: "It just works" float[] dailyRecruitedPrisoners = Campaign.Current.Models.PrisonerRecruitmentCalculationModel.GetDailyRecruitedPrisoners(MobileParty.MainParty); float excess = dailyRecruitedPrisoners[dailyRecruitedPrisoners.Length - 1]; // This is pooled chance to recruit higher tiers than we have settings for Dictionary <int, int> nPrisoners = GetNaughtyPrisoners(prisonRoster); // Get prisoner index -> not yet recruitable number int totalN = GetTotalNaughty(nPrisoners); // Determine how many loops we need to process the above dictionary for (int n = 0; n < totalN; n++) { int i = MBRandom.RandomInt(nPrisoners.Count); // Get random for better distribution int index = nPrisoners.ElementAt(i).Key; nPrisoners[index] -= 1; if (nPrisoners[index] < 1) { nPrisoners.Remove(index); } CharacterObject characterAtIndex = prisonRoster.GetCharacterAtIndex(index); int tier = characterAtIndex.Tier; if (dailyRecruitedPrisoners[tier] > 0f) // TODO We should probably organise nPrisoners by Tier, index, then unrecruited so we can remove Tier chance < 0 { if (tier < dailyRecruitedPrisoners.Length) { if (MBRandom.RandomFloat < dailyRecruitedPrisoners[tier]) { // 100 Leadership decreases chance decrease per recruitment by 33%, capped at 275 float chanceDecreaseLeadership = settings.LeadershipBase - Math.Min(settings.LeadershipCap, Clan.PlayerClan.Leader.GetSkillValue(DefaultSkills.Charm)) / (float)settings.LeadershipDiv; SetRecruitableNumberInternal(characterAtIndex, GetRecruitableNumberInternal(characterAtIndex) + 1); // Clan Tier has exponential effect, increase power base to increase steepness, change float multipler to change ceiling float clanPowerThing = (float)Math.Pow(settings.ClanTierChanceLossDecreasePowerBase, Clan.PlayerClan.Tier + settings.ClanTierChanceLossDecreasePowerAdd); float clanImpact = settings.ClanTierChanceLossDecreaseBase + settings.ClanTierChanceLossDecreaseFloat * clanPowerThing - settings.ClanTierChanceLossDecreaseFloat; dailyRecruitedPrisoners[tier] -= chanceDecreaseLeadership / (clanImpact); } } else if (MBRandom.RandomFloat < excess) { float chanceDecreaseLeadership = settings.LeadershipBase - Math.Min(settings.LeadershipCap, Clan.PlayerClan.Leader.GetSkillValue(DefaultSkills.Charm)) / (float)settings.LeadershipDiv; SetRecruitableNumberInternal(characterAtIndex, GetRecruitableNumberInternal(characterAtIndex) + 1); float clanPowerThing = (float)Math.Pow(settings.ClanTierChanceLossDecreasePowerBase, Clan.PlayerClan.Tier + settings.ClanTierChanceLossDecreasePowerAdd); float clanImpact = settings.ClanTierChanceLossDecreaseBase + settings.ClanTierChanceLossDecreaseFloat * clanPowerThing - settings.ClanTierChanceLossDecreaseFloat; excess -= chanceDecreaseLeadership / clanImpact; } } } RemoveUnused(prisonRoster); }
private void RemoveTroops() { MobileParty heroParty = MobileParty.MainParty; TroopRoster troops = heroParty.MemberRoster; TroopRosterElement troopElement; CharacterObject troop; int troopTypeCount; int numOfTroopsToTake; TroopRoster tempTroopRoster; for (int i = 0; i < troops.Count; i++) { tempTroopRoster = new TroopRoster(); troop = troops.GetCharacterAtIndex(i); troopElement = troops.GetElementCopyAtIndex(i); Debug.WriteLine("troopElement " + i + ": " + troopElement.Character.Name); troopTypeCount = troops.GetTroopCount(troop); Debug.WriteLine("cons2 Troop " + i + ": " + troop.Name + ", count:" + troopTypeCount); if (numOfTroopNeeded > 0) { numOfTroopsToTake = getNumTroopNeeded(troop, troopTypeCount); int numOfTroopsToRemove = troopTypeCount - numOfTroopsToTake; Debug.WriteLine("take Troop " + troop.Name + ", num to take: " + numOfTroopsToTake + ", num to remove: " + numOfTroopsToRemove); numOfTroopNeeded -= numOfTroopsToTake; if (numOfTroopsToRemove > 0) { Debug.WriteLine("remove Troop1 " + troop.Name + ", num: " + numOfTroopsToRemove); CharacterObject tempTroop = troopElement.Character; tempTroopRoster.FillMembersOfRoster(numOfTroopsToTake, troop); troopRosterRemovedTroops.Add(tempTroopRoster); Debug.WriteLine("troopRoosterRemovedTroops count" + troopRosterRemovedTroops.Count()); troops.RemoveTroop(troop, numOfTroopsToRemove); i--; } } else { Debug.WriteLine("remove Troop2 " + troop.Name + ", num: " + troopTypeCount + ", troopCound: " + troopTypeCount); CharacterObject tempTroop = troopElement.Character; tempTroopRoster.FillMembersOfRoster(troopTypeCount, troop); Debug.WriteLine("output temp roster: "); outputRoster(troopRosterRemovedTroops); troopRosterRemovedTroops.Add(tempTroopRoster); Debug.WriteLine("output roster: "); outputRoster(troopRosterRemovedTroops); Debug.WriteLine("troopRoosterRemovedTroops count" + troopRosterRemovedTroops.Count() + ", troopRoster tootalCount: " + troopRosterRemovedTroops.TotalManCount); troops.RemoveTroop(troop, troopTypeCount); i--; } } Debug.WriteLine("end of remove troops"); }
internal void MakeFreedHeroesEscape(TroopRoster freedTroops) { for (int i = freedTroops.Count <TroopRosterElement>() - 1; i >= 0; i--) { CharacterObject characterAtIndex = freedTroops.GetCharacterAtIndex(i); if (characterAtIndex.IsHero) { if (!characterAtIndex.IsPlayerCharacter) { EndCaptivityAction.ApplyByReleasedAfterBattle(characterAtIndex.HeroObject, null, null); } freedTroops.RemoveTroop(characterAtIndex, 1, new UniqueTroopDescriptor(), 0); } } }
public void Recruit(Settlement settlement) { if (!settlement.IsTown && !settlement.IsCastle) { return; } var town = settlement.Town; if (town.Owner == null || town.Owner.PrisonRoster == null) { return; } if (town.GarrisonParty == null) { town.Settlement.AddGarrisonParty(false); } TroopRoster prisonRoster = town.Owner.PrisonRoster; float[] dailyRecruitedPrisoners = Array.Empty <float>(); PrisonerRecruitmentCalculationModelPatch.GetDailyRecruitedPrisoners(ref dailyRecruitedPrisoners, MobileParty.MainParty); int num = MBRandom.RandomInt(prisonRoster.Count); for (int i = 0; i < prisonRoster.Count; i++) { int index = (i + num) % prisonRoster.Count; CharacterObject characterAtIndex = prisonRoster.GetCharacterAtIndex(index); if (characterAtIndex.Tier > 6 || characterAtIndex.IsHero) { continue; } int tier = characterAtIndex.Tier; if (tier < dailyRecruitedPrisoners.Length && dailyRecruitedPrisoners[tier] > 0f && MBRandom.RandomFloat < dailyRecruitedPrisoners[tier])// { dailyRecruitedPrisoners[tier] -= 1f; if (MBRandom.RandomFloat < (town.Settlement.OwnerClan == Clan.PlayerClan ? 0.8 : 1)) { town.GarrisonParty.MemberRoster.AddToCounts(characterAtIndex, 1); } prisonRoster.AddToCounts(characterAtIndex, -1); } } }
private void DailyTick() { TroopRoster prisonRoster = MobileParty.MainParty.PrisonRoster; float[] dailyRecruitingProbabilityByTier = (float[])_dailyRecruitingProbabilityByTier.Clone(); float[] dailyTierRecruitProbabilityDecay = (float[])_dailyTierRecruitProbabilityDecay.Clone(); int randomIndexToStartAt = MBRandom.RandomInt(prisonRoster.Count); for (int i = 0; i < prisonRoster.Count; i++) { int index = (i + randomIndexToStartAt) % prisonRoster.Count; CharacterObject characterAtIndex = prisonRoster.GetCharacterAtIndex(index); if (!IsPrisonerRecruitable(characterAtIndex)) { continue; } int numberOfTroops = prisonRoster.GetElementNumber(index); int numberOfCurrentlyRecruitableTroops = this.GetRecruitableNumber(characterAtIndex); int troopTier = characterAtIndex.Tier; int troopsToRoll = numberOfTroops; if (ConfigLoader.Instance.Config.ScaleByReadyToRecruit) { troopsToRoll -= numberOfCurrentlyRecruitableTroops; } //Loop through all the prisoners we want to roll a probability for changing into a recruitable prisoner for (int n = 0; n < troopsToRoll && numberOfCurrentlyRecruitableTroops < numberOfTroops; n++) { //If any of them pass their current probability check. if (troopTier < dailyRecruitingProbabilityByTier.Length && dailyRecruitingProbabilityByTier[troopTier] > 0f && MBRandom.RandomFloat < dailyRecruitingProbabilityByTier[troopTier]) { numberOfCurrentlyRecruitableTroops++; this.SetRecruitableNumber(characterAtIndex, numberOfCurrentlyRecruitableTroops); dailyRecruitingProbabilityByTier[troopTier] -= dailyTierRecruitProbabilityDecay[troopTier]; } } } }
private void DailyTick() { TroopRoster prisonRoster = MobileParty.MainParty.PrisonRoster; float[] dailyRecruitingProbabilityByTier = (float[])_dailyRecruitingProbabilityByTier.Clone(); float[] dailyTierRecruitProbabilityDecay = (float[])_dailyTierRecruitProbabilityDecay.Clone(); int num = MBRandom.RandomInt(prisonRoster.Count); for (int i = 0; i < prisonRoster.Count; i++) { int index = (i + num) % prisonRoster.Count; CharacterObject characterAtIndex = prisonRoster.GetCharacterAtIndex(index); if (!IsPrisonerRecruitable(characterAtIndex)) { continue; } int elementNumber = prisonRoster.GetElementNumber(index); int recruitableNumberInternal = GetRecruitableNumber(characterAtIndex); prisonRoster.GetElementCopyAtIndex(index); if (recruitableNumberInternal < elementNumber) { int tier = characterAtIndex.Tier; int troopsLeftToRecruit = elementNumber; if (ConfigLoader.Instance.Config.ScaleByReadyToRecruit) { troopsLeftToRecruit -= recruitableNumberInternal; } for (int n = 0; n < troopsLeftToRecruit; n++) { if (tier < dailyRecruitingProbabilityByTier.Length && dailyRecruitingProbabilityByTier[tier] > 0f && MBRandom.RandomFloat < dailyRecruitingProbabilityByTier[tier]) { recruitableNumberInternal++; SetRecruitableNumber(characterAtIndex, recruitableNumberInternal); dailyRecruitingProbabilityByTier[tier] -= dailyTierRecruitProbabilityDecay[tier]; } } } } }
private CharacterObject getBestRecruitablePrisoner() { TroopRoster prisoners = MobileParty.MainParty.PrisonRoster; CharacterObject bestPrisoner = null; int highestLevel = -1; for (int i = 0; i < prisoners.Count; i++) { CharacterObject current = prisoners.GetCharacterAtIndex(i); int level = current.Level; int recruitableNumer = Campaign.Current.GetCampaignBehavior <IRecruitPrisonersCampaignBehavior>().GetRecruitableNumber(current); if (recruitableNumer > 0 && level > highestLevel) { highestLevel = level; bestPrisoner = current; } } return(bestPrisoner); }
private void RemoveUnused(TroopRoster roster) { if (_recruitables.Count == 0) { return; } Dictionary <CharacterObject, int> dictionary = new Dictionary <CharacterObject, int>(); for (int i = 0; i < roster.Count; i++) { CharacterObject characterAtIndex = roster.GetCharacterAtIndex(i); _recruitables.TryGetValue(characterAtIndex, out int value); int num = Math.Min(value, roster.GetElementNumber(i)); if (num > 0) { dictionary[characterAtIndex] = num; } } _recruitables = dictionary; }
private void CalculatePriceAndNumInjured(ref int price, ref int numberTreated, bool includeMainHero, bool restoreHealth) { TroopRoster memberRoster = MobileParty.MainParty.MemberRoster; if (memberRoster.TotalHeroes > 0) { for (int i = 0; i < memberRoster.Count; i++) { Hero heroObject = memberRoster.GetCharacterAtIndex(i).HeroObject; if (heroObject != null) { if (heroObject.HitPoints < heroObject.MaxHitPoints && (includeMainHero || heroObject != Hero.MainHero)) { numberTreated++; price += PriceToHeal(heroObject); if (restoreHealth) { heroObject.HitPoints = heroObject.MaxHitPoints; } } } } } }