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);
        }
Exemplo n.º 2
0
        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;
                }
            }
        }
Exemplo n.º 3
0
 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);
        }
Exemplo n.º 5
0
        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");
        }
Exemplo n.º 6
0
 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];
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        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;
        }
Exemplo n.º 12
0
        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;
                            }
                        }
                    }
                }
            }
        }