Пример #1
0
    private static bool TryGetHybrids(StatRequest req, out IEnumerable <HybridDef> hybridDefs)
    {
        if (AnimalGroupDef.TryGetGroups(req, out var groups))
        {
            hybridDefs = groups.Select(a => HybridDef.TryGetHybrids(a, out var h) ? h : null).Where(h => h != null)
                         .SelectMany(x => x).Select(h => h.Value).SelectMany(x => x).Distinct();
            return(true);
        }

        hybridDefs = default;
        return(false);
    }
    public static bool Guard_Hediff_AnimalFertilityReduced(Pawn male, Pawn female)
    {
        if (
            HybridDef.TryGetHybrids(male.kindDef, female.kindDef, out var hybridList) &&
            hybridList.TryGetRandomElement(out var hybrid) &&
            hybrid.fertilizationFailesIfGreaterThanZeroCurve.TryGetRandomValue(
                out var fertilizationFailesIfGreaterThanZero) &&
            fertilizationFailesIfGreaterThanZero >= 0f
            )
        {
            DogsMateMod.Debug(
                $"fertilizationFailesIfGreaterThanZero: {fertilizationFailesIfGreaterThanZero:0.000}, " +
                "failed"
                );
            return(true);
        }

        var maleHediff   = SeverityOf(male);
        var femaleHediff = SeverityOf(female);

        if (maleHediff <= 0f && femaleHediff <= 0f)
        {
            return(true);
        }

        if (maleHediff >= 1f || femaleHediff >= 1f)
        {
            DogsMateMod.Debug(
                $"male fertility: {(1f - maleHediff) * 100:0.0}%, " +
                $"female fertility: {(1f - femaleHediff) * 100:0.0}%, " +
                "can't fertilize"
                );
            return(false);
        }

        var threshold =
            Mathf.Sqrt((1f - maleHediff) * (1f - femaleHediff) * (1f - Mathf.Max(maleHediff, femaleHediff)));

        DogsMateMod.Debug(
            $"male fertility: {(1f - maleHediff) * 100:0.0}%, " +
            $"female fertility: {(1f - femaleHediff) * 100:0.0}%, " +
            $"fertilation chance:  {threshold * 50:0.0}%" // RimWorld lets every other fertilation fail.
            );
        var value = Rand.Value;

        return(value <= threshold);
    }
Пример #3
0
 public override bool ShouldShowFor(StatRequest req)
 {
     return(AnimalGroupDef.TryGetGroups(req, out var groups) &&
            groups.Any(a => HybridDef.TryGetHybrids(a, out _)));
 }
    public static bool Replace_DoBirthSpawn(Pawn mother, Pawn father)
    {
        if (father is null || mother.kindDef == father.kindDef)
        {
            return(true);
        }

        var litterCount = Math.Min(GetLitterCount(mother), GetLitterCount(father));

        List <(PawnKindDef p, List <HybridDef> h)> hybridKinds = null;

        if (
            DogsMateMod.TryGetCompatibleFemales(father.kindDef, out var dict) &&
            dict.TryGetValue(mother.kindDef, out var hybridDefs) &&
            hybridDefs.Count > 0
            )
        {
            hybridKinds = hybridDefs.Select(h => h.children.Where(c => c.IsUsable).Select(a => (a, h)))
                          .SelectMany(x => x).Select(ah => ah.a.pawnKinds.Where(p => p != null).Select(p => (p, ah.h)))
                          .SelectMany(x => x).GroupBy(ph => ph.p)
                          .Select(g => (g.Key, g.Select(ph => ph.h).Where(h => h.IsUsable).ToList())).ToList();
            DogsMateMod.Debug(
                $"father=<{father.kindDef.ToStringSafe()}> " +
                $"mother=<{mother.kindDef.ToStringSafe()}> " +
                $"hybrids=<{hybridKinds.Select(ph => ph.p.label).ToCommaList()}>"
                );
        }

        Pawn child = null;

        for (var childIndex = 0; childIndex < litterCount; ++childIndex)
        {
            PawnKindDef childKind;
            HybridDef   hybridDef = null;
            if (hybridKinds != null)
            {
                hybridKinds.TryGetRandomElement(out var ph);
                ph.h.TryGetRandomElement(out hybridDef);
                childKind = ph.p;
            }
            else if (Rand.Value > 0.5f)
            {
                childKind = mother.kindDef;
            }
            else
            {
                childKind = father.kindDef;
            }

            bool newChildIsGood;
            var  newChild = PawnGenerator.GeneratePawn(new PawnGenerationRequest(
                                                           childKind,
                                                           mother.Faction,
                                                           forceGenerateNewPawn: false,
                                                           newborn: true
                                                           ));
            if (PawnUtility.TrySpawnHatchedOrBornPawn(newChild, mother))
            {
                if (newChild.playerSettings != null && mother.playerSettings != null)
                {
                    newChild.playerSettings.AreaRestriction = mother.playerSettings.AreaRestriction;
                }

                if (newChild.RaceProps.IsFlesh)
                {
                    newChild.relations.AddDirectRelation(PawnRelationDefOf.Parent, mother);
                    newChild.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
                }

                if (hybridDef != null)
                {
                    AddHediffs(newChild, hybridDef.childrenHediffs);
                    switch (newChild.gender)
                    {
                    case Gender.Male:
                        AddHediffs(newChild, hybridDef.maleChildrenHediffs);
                        break;

                    case Gender.Female:
                        AddHediffs(newChild, hybridDef.femaleChildrenHediffs);
                        break;
                    }
                }

                newChildIsGood = true;
            }
            else
            {
                Find.WorldPawns.PassToWorld(newChild, PawnDiscardDecideMode.Discard);
                newChildIsGood = false;
            }

            TaleRecorder.RecordTale(TaleDefOf.GaveBirth, mother, newChild);

            if (newChildIsGood)
            {
                child = newChild;
            }
        }

        if (!mother.Spawned)
        {
            return(false);
        }

        FilthMaker.TryMakeFilth(mother.Position, mother.Map, ThingDefOf.Filth_AmnioticFluid,
                                mother.LabelIndefinite(), 5);
        mother.caller?.DoCall();
        child?.caller?.DoCall();

        return(false);
    }