Пример #1
0
 public void HealthTick()
 {
     if (!Dead)
     {
         for (int num = hediffSet.hediffs.Count - 1; num >= 0; num--)
         {
             Hediff hediff = hediffSet.hediffs[num];
             try
             {
                 hediff.Tick();
                 hediff.PostTick();
             }
             catch (Exception ex)
             {
                 Log.Error("Exception ticking hediff " + hediff.ToStringSafe() + " for pawn " + pawn.ToStringSafe() + ". Removing hediff... Exception: " + ex);
                 try
                 {
                     RemoveHediff(hediff);
                 }
                 catch (Exception arg)
                 {
                     Log.Error("Error while removing hediff: " + arg);
                 }
             }
         }
         bool flag = false;
         for (int num2 = hediffSet.hediffs.Count - 1; num2 >= 0; num2--)
         {
             Hediff hediff2 = hediffSet.hediffs[num2];
             if (hediff2.ShouldRemove)
             {
                 hediffSet.hediffs.RemoveAt(num2);
                 hediff2.PostRemoved();
                 flag = true;
             }
         }
         if (flag)
         {
             Notify_HediffChanged(null);
         }
         if (!Dead)
         {
             immunity.ImmunityHandlerTick();
             if (pawn.RaceProps.IsFlesh && pawn.IsHashIntervalTick(600) && (pawn.needs.food == null || !pawn.needs.food.Starving))
             {
                 bool flag2 = false;
                 if (hediffSet.HasNaturallyHealingInjury())
                 {
                     float num3 = 8f;
                     if (pawn.GetPosture() != 0)
                     {
                         num3 += 4f;
                         Building_Bed building_Bed = pawn.CurrentBed();
                         if (building_Bed != null)
                         {
                             num3 += building_Bed.def.building.bed_healPerDay;
                         }
                     }
                     Hediff_Injury hediff_Injury = hediffSet.GetHediffs <Hediff_Injury>().Where(HediffUtility.CanHealNaturally).RandomElement();
                     hediff_Injury.Heal(num3 * pawn.HealthScale * 0.01f);
                     flag2 = true;
                 }
                 if (hediffSet.HasTendedAndHealingInjury() && (pawn.needs.food == null || !pawn.needs.food.Starving))
                 {
                     Hediff_Injury hediff_Injury2 = hediffSet.GetHediffs <Hediff_Injury>().Where(HediffUtility.CanHealFromTending).RandomElement();
                     float         tendQuality    = hediff_Injury2.TryGetComp <HediffComp_TendDuration>().tendQuality;
                     float         num4           = GenMath.LerpDouble(0f, 1f, 0.5f, 1.5f, Mathf.Clamp01(tendQuality));
                     hediff_Injury2.Heal(8f * num4 * pawn.HealthScale * 0.01f);
                     flag2 = true;
                 }
                 if (flag2 && !HasHediffsNeedingTendByPlayer() && !HealthAIUtility.ShouldSeekMedicalRest(pawn) && !hediffSet.HasTendedAndHealingInjury() && PawnUtility.ShouldSendNotificationAbout(pawn))
                 {
                     Messages.Message("MessageFullyHealed".Translate(pawn.LabelCap, pawn), pawn, MessageTypeDefOf.PositiveEvent);
                 }
             }
             if (pawn.RaceProps.IsFlesh && hediffSet.BleedRateTotal >= 0.1f)
             {
                 float num5 = hediffSet.BleedRateTotal * pawn.BodySize;
                 num5 = ((pawn.GetPosture() != 0) ? (num5 * 0.0004f) : (num5 * 0.004f));
                 if (Rand.Value < num5)
                 {
                     DropBloodFilth();
                 }
             }
             if (pawn.IsHashIntervalTick(60))
             {
                 List <HediffGiverSetDef> hediffGiverSets = pawn.RaceProps.hediffGiverSets;
                 if (hediffGiverSets != null)
                 {
                     for (int i = 0; i < hediffGiverSets.Count; i++)
                     {
                         List <HediffGiver> hediffGivers = hediffGiverSets[i].hediffGivers;
                         for (int j = 0; j < hediffGivers.Count; j++)
                         {
                             hediffGivers[j].OnIntervalPassed(pawn, null);
                             if (pawn.Dead)
                             {
                                 return;
                             }
                         }
                     }
                 }
                 if (pawn.story != null)
                 {
                     List <Trait> allTraits = pawn.story.traits.allTraits;
                     for (int k = 0; k < allTraits.Count; k++)
                     {
                         TraitDegreeData currentData = allTraits[k].CurrentData;
                         if (currentData.randomDiseaseMtbDays > 0f && Rand.MTBEventOccurs(currentData.randomDiseaseMtbDays, 60000f, 60f))
                         {
                             BiomeDef biome;
                             if (pawn.Tile != -1)
                             {
                                 biome = Find.WorldGrid[pawn.Tile].biome;
                             }
                             else
                             {
                                 biome = DefDatabase <BiomeDef> .GetRandom();
                             }
                             IncidentDef incidentDef = (from d in DefDatabase <IncidentDef> .AllDefs
                                                        where d.category == IncidentCategoryDefOf.DiseaseHuman
                                                        select d).RandomElementByWeightWithFallback((IncidentDef d) => biome.CommonalityOfDisease(d));
                             if (incidentDef != null)
                             {
                                 string      blockedInfo;
                                 List <Pawn> list = ((IncidentWorker_Disease)incidentDef.Worker).ApplyToPawns(Gen.YieldSingle(pawn), out blockedInfo);
                                 if (PawnUtility.ShouldSendNotificationAbout(pawn))
                                 {
                                     if (list.Contains(pawn))
                                     {
                                         Find.LetterStack.ReceiveLetter("LetterLabelTraitDisease".Translate(incidentDef.diseaseIncident.label), "LetterTraitDisease".Translate(pawn.LabelCap, incidentDef.diseaseIncident.label, pawn.Named("PAWN")).AdjustedFor(pawn), LetterDefOf.NegativeEvent, pawn);
                                     }
                                     else if (!blockedInfo.NullOrEmpty())
                                     {
                                         Messages.Message(blockedInfo, pawn, MessageTypeDefOf.NeutralEvent);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
Пример #2
0
        public IEnumerable <StatDrawEntry> SpecialDisplayStats(ThingDef parentDef)
        {
            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "Race".Translate(), parentDef.LabelCap, 2000, ""));

            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "Diet".Translate(), this.foodType.ToHumanString().CapitalizeFirst(), 0, ""));

            if (parentDef.race.leatherDef != null)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "LeatherType".Translate(), parentDef.race.leatherDef.LabelCap, 0, ""));
            }
            if (parentDef.race.Animal || this.wildness > 0f)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "Wildness".Translate(), this.wildness.ToStringPercent(), 0, "")
                {
                    overrideReportText = TrainableUtility.GetWildnessExplanation(parentDef)
                });
            }
            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "HarmedRevengeChance".Translate(), PawnUtility.GetManhunterOnDamageChance(parentDef.race).ToStringPercent(), 0, "")
            {
                overrideReportText = "HarmedRevengeChanceExplanation".Translate()
            });

            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "TameFailedRevengeChance".Translate(), parentDef.race.manhunterOnTameFailChance.ToStringPercent(), 0, ""));

            if (this.intelligence < Intelligence.Humanlike && this.trainability != null)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "Trainability".Translate(), this.trainability.LabelCap, 0, ""));
            }
            yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "StatsReport_LifeExpectancy".Translate(), this.lifeExpectancy.ToStringByStyle(ToStringStyle.Integer, ToStringNumberSense.Absolute), 0, ""));

            if (this.intelligence < Intelligence.Humanlike)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "AnimalFilthRate".Translate(), (PawnUtility.AnimalFilthChancePerCell(parentDef, parentDef.race.baseBodySize) * 1000f).ToString("F2"), 0, "")
                {
                    overrideReportText = "AnimalFilthRateExplanation".Translate(new object[]
                    {
                        1000.ToString()
                    })
                });
            }
            if (this.packAnimal)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.Basics, "PackAnimal".Translate(), "Yes".Translate(), 0, "")
                {
                    overrideReportText = "PackAnimalExplanation".Translate()
                });
            }
            if (parentDef.race.nuzzleMtbHours > 0f)
            {
                yield return(new StatDrawEntry(StatCategoryDefOf.PawnSocial, "NuzzleInterval".Translate(), Mathf.RoundToInt(parentDef.race.nuzzleMtbHours * 2500f).ToStringTicksToPeriod(), 0, "")
                {
                    overrideReportText = "NuzzleIntervalExplanation".Translate()
                });
            }
            yield break;
        }
Пример #3
0
        public bool TryStartMentalState(MentalStateDef stateDef, string reason = null, bool forceWake = false, bool causedByMood = false, Pawn otherPawn = null, bool transitionSilently = false)
        {
            if ((!pawn.Spawned && !pawn.IsCaravanMember()) || CurStateDef == stateDef || pawn.Downed || (!forceWake && !pawn.Awake()))
            {
                return(false);
            }
            if (TutorSystem.TutorialMode && pawn.Faction == Faction.OfPlayer)
            {
                return(false);
            }
            if (!stateDef.Worker.StateCanOccur(pawn))
            {
                return(false);
            }
            MentalState mentalState = (MentalState)Activator.CreateInstance(stateDef.stateClass);

            mentalState.pawn         = pawn;
            mentalState.def          = stateDef;
            mentalState.causedByMood = causedByMood;
            if (otherPawn != null)
            {
                ((MentalState_SocialFighting)mentalState).otherPawn = otherPawn;
            }
            mentalState.PreStart();
            if (!transitionSilently)
            {
                if ((pawn.IsColonist || pawn.HostFaction == Faction.OfPlayer) && stateDef.tale != null)
                {
                    TaleRecorder.RecordTale(stateDef.tale, pawn);
                }
                if (stateDef.IsExtreme && pawn.IsPlayerControlledCaravanMember())
                {
                    Messages.Message("MessageCaravanMemberHasExtremeMentalBreak".Translate(), pawn.GetCaravan(), MessageTypeDefOf.ThreatSmall);
                }
                pawn.records.Increment(RecordDefOf.TimesInMentalState);
            }
            if (pawn.Drafted)
            {
                pawn.drafter.Drafted = false;
            }
            curStateInt = mentalState;
            if (pawn.needs.mood != null)
            {
                pawn.needs.mood.thoughts.situational.Notify_SituationalThoughtsDirty();
            }
            if (stateDef != null && stateDef.IsAggro && pawn.caller != null)
            {
                pawn.caller.Notify_InAggroMentalState();
            }
            if (curStateInt != null)
            {
                curStateInt.PostStart(reason);
            }
            if (pawn.CurJob != null)
            {
                pawn.jobs.StopAll();
            }
            if (pawn.Spawned)
            {
                pawn.Map.attackTargetsCache.UpdateTarget(pawn);
            }
            if (pawn.Spawned && forceWake && !pawn.Awake())
            {
                pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
            }
            if (!transitionSilently && PawnUtility.ShouldSendNotificationAbout(pawn))
            {
                string text = mentalState.GetBeginLetterText();
                if (!text.NullOrEmpty())
                {
                    string label = (stateDef.beginLetterLabel ?? stateDef.LabelCap).CapitalizeFirst() + ": " + pawn.LabelShortCap;
                    if (!reason.NullOrEmpty())
                    {
                        text = text + "\n\n" + reason;
                    }
                    Find.LetterStack.ReceiveLetter(label, text, stateDef.beginLetterDef, pawn);
                }
            }
            return(true);
        }
Пример #4
0
        private void expandNode(Step currentNode)
        {
            bool     previousNodeHasDoor, previousNodeIsPathCostIgnoreRepeater;
            Building previousBuilding = edificeGrid[currentNode.currentIndx];

            if (previousBuilding is Building_Door)
            {
                previousNodeHasDoor = true;
            }
            else
            {
                previousNodeHasDoor = false;
            }

            previousNodeIsPathCostIgnoreRepeater = false;
            foreach (ThingDef def in map.thingGrid.ThingsListAtFast(currentNode.currentIndx).Select(t => t.def))
            {
                if (def.pathCostIgnoreRepeat)
                {
                    previousNodeIsPathCostIgnoreRepeater = true;
                    break;
                }
            }

            //add all neighboring tiles but diagonal only if it is allowed, fixed size where we null out the after last entry if it is not full
            int currentIndice = currentNode.currentIndx;
            int currentX      = currentNode.current.x;
            int currentZ      = currentNode.current.z;

            int[]   Directions     = DirectionsShared;
            IntVec3 invalidIntVec3 = invalidIntVec3Shared;

            byte byteDirections;

            if (pathfinderDirections != null)
            {
                byteDirections = pathfinderDirections.GetDirections(currentNode.current);
            }
            else
            {
                byteDirections = 0xFF;
            }
            for (int i = 0; i < 8; i++)
            {
                if (byteDirections != 0xFF)
                {
                    //{ 0, 1, 0, -1,  1, 1, -1, -1,
                    // -1, 0, 1,  0, -1, 1,  1, -1 }
                    switch (i)
                    {
                    case 2: if ((byteDirections & 1) != 1)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 5: if ((byteDirections & 2) != 2)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 1: if ((byteDirections & 4) != 4)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 4: if ((byteDirections & 8) != 8)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 0: if ((byteDirections & 16) != 16)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 8: if ((byteDirections & 32) != 32)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 3: if ((byteDirections & 64) != 64)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    case 7: if ((byteDirections & 128) != 128)
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                        break;

                    default: neighbors[i] = invalidIntVec3; continue;
                    }
                }
                int neighborX = currentX + Directions[i];
                int neighborZ = currentZ + Directions[i + 8];
                //check if we are within map bounds
                if (neighborX >= mapSizeX || neighborZ >= mapSizeZ || neighborX < 0 || neighborZ < 0)
                {
                    neighbors[i] = invalidIntVec3; continue;
                }
                //check if we have to skip diagonal movement due to adjacent tiles.
                if (i > 3)
                {
                    if (Directions[i] == 1)
                    {
                        if (BlocksDiagonalMovement(currentIndice + 1))
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                    }
                    else
                    {
                        if (BlocksDiagonalMovement(currentIndice - 1))
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                    }
                    if (Directions[i + 8] == 1)
                    {
                        if (BlocksDiagonalMovement(currentIndice + mapSizeX))
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                    }
                    else
                    {
                        if (BlocksDiagonalMovement(currentIndice - mapSizeX))
                        {
                            neighbors[i] = invalidIntVec3; continue;
                        }
                    }
                }
                //check if we can cross water tiles
                IntVec3 ngb = new IntVec3(neighborX, 0, neighborZ);
                if (dontPassWater && ngb.GetTerrain(map).HasTag("Water"))
                {
                    neighbors[i] = invalidIntVec3; continue;
                }
                neighbors[i] = ngb;
            }
            for (int i = 0; i < neighbors.Count(); i++)
            {
                IntVec3 neighbor = neighbors[i];
                if (neighbor == invalidIntVec3)
                {
                    continue;
                }
                int  neighborIndice = cellIndices.CellToIndex(neighbor);
                Step successor      = stepCache.getCachedOrNewStep(neighbor, neighborIndice);

                // wenn der Nachfolgeknoten bereits geschlossen wurde - tue nichts
                if (successor.closed)
                {
                    continue;
                }

                //can the tile be walked across?
                bool useTerrainCost = true;
                int  costToDestroyInsteadOfTerrainCost = 0;
                if (!pathGrid.WalkableFast(neighborIndice))
                {
                    if (traverseParms.mode != TraverseMode.PassAllDestroyableThings)
                    {
                        continue;
                    }
                    useTerrainCost = false;
                    costToDestroyInsteadOfTerrainCost += 70;
                    Building building = edificeGrid[neighborIndice];
                    if (building == null)
                    {
                        continue;
                    }
                    if (!PathFinder.IsDestroyable(building))
                    {
                        continue;
                    }
                    costToDestroyInsteadOfTerrainCost += (int)((float)building.HitPoints * 0.11f);
                }

                bool isUpdate = successor.costToReachThis > 0;

                int      stepCosts = (i <= 3) ? costPerMoveCardinal : costPerMoveDiagonal;
                Building building2 = edificeGrid[neighborIndice];
                if (building2 != null)
                {
                    int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn);
                    if (buildingCost == Int32.MaxValue)
                    {
                        continue;
                    }
                    stepCosts += buildingCost;
                }
                List <Blueprint> blueprints = this.blueprintGrid[neighborIndice];
                if (blueprints != null)
                {
                    int maxBluprintCost = 0;
                    blueprints.ForEach(bp => maxBluprintCost = Math.Max(maxBluprintCost, PathFinder.GetBlueprintCost(bp, pawn)));
                    if (maxBluprintCost == Int32.MaxValue)
                    {
                        continue;
                    }
                    stepCosts += maxBluprintCost;
                }
                if (useTerrainCost)
                {
                    stepCosts += pathGridArray[neighborIndice] - minTerrainCost;
                    //PathGrid uses cached static cost and does not account for directional costs
                    //1. moving from a thing with pathCostIgnoreRepeat and a cost of at least 25 to a thing with pathCostIgnoreRepeat reduces the cost by the pathCost of the first thing
                    //2. moving from door to door increases the cost by 45
                    if (previousNodeHasDoor && building2 != null && building2 is Building_Door)
                    {
                        stepCosts += 45;
                    }
                    if (previousNodeIsPathCostIgnoreRepeater)
                    {
                        foreach (ThingDef def in map.thingGrid.ThingsListAtFast(neighborIndice).Select(t => t.def))
                        {
                            if (def.pathCostIgnoreRepeat && def.pathCost >= 25)
                            {
                                stepCosts -= def.pathCost;
                            }
                        }
                    }
                    //new in 1.0
                    if (drafted)
                    {
                        stepCosts += topGrid[neighborIndice].extraDraftedPerceivedPathCost;
                    }
                    else
                    {
                        stepCosts += topGrid[neighborIndice].extraNonDraftedPerceivedPathCost;
                    }
                }
                else
                {
                    stepCosts += costToDestroyInsteadOfTerrainCost;
                }
                if (avoidGrid != null)
                {
                    stepCosts += (int)(avoidGrid[neighborIndice] * 8);
                }
                //Variation to default behaviour:
                //When pathfinding from outside the allowed area back into the allowed area we ignore the malus for forbidden area to avoid ruining the performance for no good reason.
                //We check the current position and if it is forbidden we do not apply a malus if it is allowed the current neighbor is tested.
                if (allowedArea != null && allowedArea[currentIndice] && !allowedArea[neighborIndice])
                {
                    stepCosts += 600;
                }
                if (collidesWithPawns && PawnUtility.AnyPawnBlockingPathAt(neighbor, pawn, false, false, true))
                {
                    stepCosts += 175;
                }

                // g Wert für den neuen Weg berechnen: g Wert des Vorgängers plus
                // die Kosten der gerade benutzten Kante
                int costToReachThisNeighbor = currentNode.costToReachThis + stepCosts;
                // wenn der Nachfolgeknoten bereits auf der Open List ist,
                // aber der neue Weg nicht besser ist als der alte - tue nichts
                if (isUpdate && successor.costToReachThis <= costToReachThisNeighbor)
                {
                    continue;
                }
                successor.costToReachThis = costToReachThisNeighbor;
                // Vorgängerzeiger setzen und g Wert merken
                successor.predecessor = currentNode;
                // f Wert des Knotens in der Open List aktualisieren
                // bzw. Knoten mit f Wert in die Open List einfügen
                if (isUpdate)
                {
                    openlist.UpdatePriority(successor, successor.costToReachThis + successor.estimatedCostsToDestination);
                    //if ( drawPath ) map.debugDrawer.FlashCell(successor.current, 0.1f, "updated", 100);
                }
                else
                {
                    openlist.Enqueue(successor, successor.costToReachThis + successor.estimatedCostsToDestination);
                    if (drawPath)
                    {
                        map.debugDrawer.FlashCell(successor.current, 0.22f, "opened", 100);
                    }
                }
            }
        }
Пример #5
0
        public override void Tick()
        {
            ageTicks++;
            if (pawn.IsHashIntervalTick(PawnStateCheckInterval))
            {
                //Log.Message("Father = " + father);
                if (pawn.needs.food != null && pawn.needs.food.CurCategory == HungerCategory.Starving && Rand.MTBEventOccurs(0.5f, 60000f, 1000f))
                {
                    if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
                    {
                        //Messages.Message("MessageMiscarriedStarvation".Translate(pawn.LabelIndefinite()).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeHealthEvent);

                        Messages.Message("MessageMiscarriedStarvation".Translate(new object[]
                        {
                            pawn.LabelIndefinite()
                        }).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeHealthEvent);
                    }
                    Miscarry();
                    return;
                }

                if (IsSeverelyWounded && Rand.MTBEventOccurs(0.5f, 60000f, 1000f))
                {
                    if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
                    {
                        //Messages.Message("MessageMiscarriedPoorHealth".Translate(pawn.LabelIndefinite()).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeHealthEvent);

                        Messages.Message("MessageMiscarriedPoorHealth".Translate(new object[]
                        {
                            pawn.LabelIndefinite()
                        }).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeHealthEvent);
                    }
                    Miscarry();
                    return;
                }

                if (GestationProgress >= 1f)
                {
                    /*
                     * if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
                     * {
                     *      Messages.Message("MessageAvaliLayedAnEgg".Translate(new object[]
                     *      {
                     *              pawn.LabelIndefinite()
                     *      }).CapitalizeFirst(), pawn, MessageTypeDefOf.PositiveEvent);
                     * }
                     */

                    /*
                     * if (Visible && PawnUtility.ShouldSendNotificationAbout(pawn))
                     * {
                     *
                     *      Messages.Message("MessageLayedEgg".Translate(new object[]
                     *      {
                     *              this.pawn.LabelIndefinite()
                     *      }).CapitalizeFirst(), this.pawn, MessageTypeDefOf.PositiveEvent);
                     * }
                     */

                    //Log.Message(pawn + " try to start job GotoLayAvaliEgg");
                    //Log.Message(pawn + " egg.father = " + father);
                    //Log.Message(pawn + " bed = " + RestUtility.FindBedFor(pawn));

                    Job          newJob = null;
                    Building_Bed bed    = RestUtility.FindBedFor(pawn);
                    if (bed != null)
                    {
                        newJob = new Job(JobDefOf.GotoLayAvaliEgg, father, bed);
                    }
                    else
                    {
                        IntVec3 cell = RCellFinder.RandomWanderDestFor(pawn, pawn.Position, 5f, null, Danger.Some);
                        newJob = new Job(JobDefOf.GotoLayAvaliEgg, father, cell);
                    }

                    pawn.jobs.StartJob(newJob, JobCondition.InterruptForced, null, false, true, null, null, false);

                    //Hediff_AvaliHasEgg.LayEgg(this.pawn, this.father);
                    //this.pawn.health.RemoveHediff(this);
                }
            }
            if (GestationProgress < 1f)
            {
                GestationProgress += 1f / (pawn.RaceProps.gestationPeriodDays * 60000f);
            }
        }
Пример #6
0
        public static void GiveVitaeEffects(Pawn receiver, Pawn donor)
        {
            var pawn = receiver;

            //Give Vitae High Effect
            Hediff vitaeHighHediff = HediffMaker.MakeHediff(VampDefOf.ROMV_VitaeHigh, pawn, null);
            float  numHigh         = 0.75f;

            AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize(pawn, VampDefOf.ROMV_VitaeChemical, ref numHigh);
            vitaeHighHediff.Severity = numHigh;
            pawn.health.AddHediff(vitaeHighHediff, null, null);

            //Give Vitae Tolerance Effect
            Hediff vitaeToleranceHediff = HediffMaker.MakeHediff(VampDefOf.ROMV_VitaeTolerance, pawn, null);
            float  numTol = 0.035f;

            numTol /= receiver.BodySize;
            AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize(pawn, VampDefOf.ROMV_VitaeChemical, ref numTol);
            vitaeToleranceHediff.Severity = numTol;
            pawn.health.AddHediff(vitaeToleranceHediff, null, null);

            const float addictiveness                   = 1.0f;
            const float minToleranceToAddict            = 0.01f;
            const float existingAddictionSeverityOffset = 0.2f;

            var needLevelOffset        = 1f;
            var overdoseSeverityOffset = new FloatRange(0.18f, 0.35f);
            var chemical = VampDefOf.ROMV_VitaeChemical;

            var addictionHediffDef = VampDefOf.ROMV_VitaeAddiction;
            var lookTarget         = receiver;
            var hediff             = AddictionUtility.FindToleranceHediff(lookTarget, VampDefOf.ROMV_VitaeChemical);
            var num             = hediff?.Severity ?? 0f;
            var hediffAddiction = AddictionUtility.FindAddictionHediff(lookTarget, VampDefOf.ROMV_VitaeChemical);

            if (hediffAddiction != null)
            {
                hediffAddiction.Severity += existingAddictionSeverityOffset;
            }
            else if (Rand.Value < addictiveness && num >= minToleranceToAddict)
            {
                lookTarget.health.AddHediff(addictionHediffDef, null, null);
                if (PawnUtility.ShouldSendNotificationAbout(lookTarget))
                {
                    Find.LetterStack.ReceiveLetter("LetterLabelNewlyAddicted".Translate(new object[]
                    {
                        chemical.label
                    }).CapitalizeFirst(), "LetterNewlyAddicted".Translate(new object[]
                    {
                        lookTarget.LabelShort,
                        chemical.label
                    }).AdjustedFor(lookTarget).CapitalizeFirst(), LetterDefOf.NegativeEvent, lookTarget, null);
                }
                AddictionUtility.CheckDrugAddictionTeachOpportunity(lookTarget);
            }

            if (addictionHediffDef.causesNeed != null)
            {
                var need = lookTarget.needs.AllNeeds.Find((Need x) => x.def == addictionHediffDef.causesNeed);
                if (need != null)
                {
                    AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize(lookTarget, chemical,
                                                                                 ref needLevelOffset);
                    need.CurLevel += needLevelOffset;
                }
            }
//            var firstHediffOfDef = lookTarget.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.DrugOverdose, false);
//            var num2 = firstHediffOfDef?.Severity ?? 0f;
//            if (num2 < 0.9f && Rand.Value < largeOverdoseChance)
//            {
//                var num3 = Rand.Range(0.85f, 0.99f);
//                HealthUtility.AdjustSeverity(lookTarget, HediffDefOf.DrugOverdose, num3 - num2);
//                if (lookTarget.Faction == Faction.OfPlayer)
//                {
//                    Messages.Message("MessageAccidentalOverdose".Translate(new object[]
//                    {
//                        lookTarget.LabelIndefinite(),
//                        chemical.LabelCap
//                    }).CapitalizeFirst(), MessageTypeDefOf.NegativeHealthEvent);
//                }
//            }
//            else
//            {
//                var num4 = overdoseSeverityOffset.RandomInRange / lookTarget.BodySize;
//                if (num4 > 0f)
//                {
//                    HealthUtility.AdjustSeverity(lookTarget, HediffDefOf.DrugOverdose, num4);
//                }
//            }
        }
    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);
    }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            base.AddEndCondition(delegate()
            {
                var thing = base.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing;
                if (thing is Building && !thing.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            this.FailOnBurningImmobile <JobDriver_DoBill>(TargetIndex.A);
            this.FailOn <JobDriver_DoBill>(delegate()
            {
                if (!(this.job.GetTarget(TargetIndex.A).Thing is IBillGiver billGiver))
                {
                    return(false);
                }
                if (this.job.bill.DeletedOrDereferenced)
                {
                    return(true);
                }
                if (!billGiver.CurrentlyUsableForBills())
                {
                    return(true);
                }
                return(false);
            });
            yield return(Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null));

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell));

            var            tableThing     = this.job.GetTarget(TargetIndex.A).Thing as Building_СontainmentBreach;
            CompRefuelable refuelableComp = tableThing.GetComp <CompRefuelable>();
            Toil           toil           = new Toil();

            toil.initAction = delegate()
            {
                this.job.bill.Notify_DoBillStarted(this.pawn);
                this.workCycleProgress = this.job.bill.recipe.workAmount;
            };
            toil.tickAction = delegate()
            {
                this.workCycleProgress -= StatExtension.GetStatValue(this.pawn, StatDefOf.WorkToMake, true);
                tableThing.UsedThisTick();
                if (!tableThing.CurrentlyUsableForBills() || (refuelableComp != null && !refuelableComp.HasFuel))
                {
                    this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true, true);
                }
                if (this.workCycleProgress <= 0f)
                {
                    SkillDef workSkill = this.job.bill.recipe.workSkill;
                    if (workSkill != null)
                    {
                        SkillRecord skill = this.pawn.skills.GetSkill(workSkill);
                        if (skill != null)
                        {
                            skill.Learn(0.11f * this.job.bill.recipe.workSkillLearnFactor, false);
                        }
                    }
                    GenSpawn.Spawn(tableThing.GetKorsolianToxin(this.job.bill.recipe),
                                   tableThing.InteractionCell, tableThing.Map, 0);
                    Toils_Reserve.Release(TargetIndex.A);
                    PawnUtility.GainComfortFromCellIfPossible(this.pawn, false);
                    this.job.bill.Notify_IterationCompleted(this.pawn, null);
                    this.ReadyForNextToil();
                }
            };
            toil.defaultCompleteMode = ToilCompleteMode.Never;
            ToilEffects.WithEffect(toil, () => this.job.bill.recipe.effectWorking, TargetIndex.A);
            ToilEffects.PlaySustainerOrSound(toil, () => toil.actor.CurJob.bill.recipe.soundWorking);
            ToilEffects.WithProgressBar(toil, TargetIndex.A, delegate()
            {
                return(PurpleIvyUtils.GetPercentageFromPartWhole
                           (this.job.bill.recipe.workAmount - this.workCycleProgress,
                           (int)this.job.bill.recipe.workAmount) / 100f);
            }, false, 0.5f);
            ToilFailConditions.FailOn <Toil>(toil, delegate()
            {
                IBillGiver billGiver = this.job.GetTarget(TargetIndex.A).Thing as IBillGiver;
                return(this.job.bill.suspended || this.job.bill.DeletedOrDereferenced || (billGiver != null && !billGiver.CurrentlyUsableForBills()));
            });
            yield return(toil);

            yield break;
        }
Пример #9
0
        private static void EvaluateCell(IntVec3 c)
        {
            if (CastPositionFinder.maxRangeFromTargetSquared > 0.01f && CastPositionFinder.maxRangeFromTargetSquared < 250000f && (float)(c - CastPositionFinder.req.target.Position).LengthHorizontalSquared > CastPositionFinder.maxRangeFromTargetSquared)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0f, "range target", 50);
                }
                return;
            }
            if ((double)CastPositionFinder.maxRangeFromLocusSquared > 0.01 && (float)(c - CastPositionFinder.req.locus).LengthHorizontalSquared > CastPositionFinder.maxRangeFromLocusSquared)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.1f, "range home", 50);
                }
                return;
            }
            if (CastPositionFinder.maxRangeFromCasterSquared > 0.01f)
            {
                CastPositionFinder.rangeFromCasterToCellSquared = (float)(c - CastPositionFinder.req.caster.Position).LengthHorizontalSquared;
                if (CastPositionFinder.rangeFromCasterToCellSquared > CastPositionFinder.maxRangeFromCasterSquared)
                {
                    if (DebugViewSettings.drawCastPositionSearch)
                    {
                        CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.2f, "range caster", 50);
                    }
                    return;
                }
            }
            if (!c.Walkable(CastPositionFinder.req.caster.Map))
            {
                return;
            }
            if (CastPositionFinder.req.maxRegions > 0 && c.GetRegion(CastPositionFinder.req.caster.Map, RegionType.Set_Passable).mark != CastPositionFinder.inRadiusMark)
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.64f, "reg radius", 50);
                }
                return;
            }
            if (!CastPositionFinder.req.caster.Map.reachability.CanReach(CastPositionFinder.req.caster.Position, c, PathEndMode.OnCell, TraverseParms.For(CastPositionFinder.req.caster, Danger.Some, TraverseMode.ByPawn, false)))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.4f, "can't reach", 50);
                }
                return;
            }
            float num = CastPositionFinder.CastPositionPreference(c);

            if (CastPositionFinder.avoidGrid != null)
            {
                byte b = CastPositionFinder.avoidGrid[c];
                num *= Mathf.Max(0.1f, (37.5f - (float)b) / 37.5f);
            }
            if (DebugViewSettings.drawCastPositionSearch)
            {
                CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, num / 4f, num.ToString("F3"), 50);
            }
            if (num < CastPositionFinder.bestSpotPref)
            {
                return;
            }
            if (!CastPositionFinder.verb.CanHitTargetFrom(c, CastPositionFinder.req.target))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.6f, "can't hit", 50);
                }
                return;
            }
            if (!CastPositionFinder.req.caster.Map.pawnDestinationReservationManager.CanReserve(c, CastPositionFinder.req.caster, false))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, num * 0.9f, "resvd", 50);
                }
                return;
            }
            if (PawnUtility.KnownDangerAt(c, CastPositionFinder.req.caster.Map, CastPositionFinder.req.caster))
            {
                if (DebugViewSettings.drawCastPositionSearch)
                {
                    CastPositionFinder.req.caster.Map.debugDrawer.FlashCell(c, 0.9f, "danger", 50);
                }
                return;
            }
            CastPositionFinder.bestSpot     = c;
            CastPositionFinder.bestSpotPref = num;
        }
 private void CheckDiscovered()
 {
     if (!this.discovered)
     {
         if (this.parent.CurStage.becomeVisible)
         {
             this.discovered = true;
             if (this.Props.sendLetterWhenDiscovered && PawnUtility.ShouldSendNotificationAbout(base.Pawn))
             {
                 if (base.Pawn.RaceProps.Humanlike)
                 {
                     string label;
                     if (!this.Props.discoverLetterLabel.NullOrEmpty())
                     {
                         label = string.Format(this.Props.discoverLetterLabel, base.Pawn.LabelShort.CapitalizeFirst()).CapitalizeFirst();
                     }
                     else
                     {
                         label = "LetterLabelNewDisease".Translate() + " (" + base.Def.label + ")";
                     }
                     string text;
                     if (!this.Props.discoverLetterText.NullOrEmpty())
                     {
                         text = string.Format(this.Props.discoverLetterText, base.Pawn.LabelIndefinite()).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     else if (this.parent.Part == null)
                     {
                         text = "NewDisease".Translate(new object[]
                         {
                             base.Pawn.LabelIndefinite(),
                             base.Def.label,
                             base.Pawn.LabelDefinite()
                         }).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     else
                     {
                         text = "NewPartDisease".Translate(new object[]
                         {
                             base.Pawn.LabelIndefinite(),
                             this.parent.Part.Label,
                             base.Pawn.LabelDefinite(),
                             base.Def.LabelCap
                         }).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     Find.LetterStack.ReceiveLetter(label, text, (this.Props.letterType == null) ? LetterDefOf.NegativeEvent : this.Props.letterType, base.Pawn, null, null);
                 }
                 else
                 {
                     string text2;
                     if (!this.Props.discoverLetterText.NullOrEmpty())
                     {
                         text2 = string.Format(this.Props.discoverLetterText, base.Pawn.LabelIndefinite()).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     else if (this.parent.Part == null)
                     {
                         text2 = "NewDiseaseAnimal".Translate(new object[]
                         {
                             base.Pawn.LabelShort,
                             base.Def.LabelCap,
                             base.Pawn.LabelDefinite()
                         }).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     else
                     {
                         text2 = "NewPartDiseaseAnimal".Translate(new object[]
                         {
                             base.Pawn.LabelShort,
                             this.parent.Part.Label,
                             base.Pawn.LabelDefinite(),
                             base.Def.LabelCap
                         }).AdjustedFor(base.Pawn, "PAWN").CapitalizeFirst();
                     }
                     Messages.Message(text2, base.Pawn, (this.Props.messageType == null) ? MessageTypeDefOf.NegativeHealthEvent : this.Props.messageType, true);
                 }
             }
         }
     }
 }
        /// <summary>
        /// GC().The best way to shrink Rimworld saves,I think.
        /// </summary>
        /// <param name="verbose">Determine if GC() should log details very very verbosely</param>
        /// <returns>Count of disposed World pawns</returns>
        public int GC(bool verbose = false)
        {
            /*
             * TODO Log
             * 1.talelog by interest             -X
             * 2.animal  - deconstruct relation  -Done
             * 3.deeperclean?remove hediffs      -X
             * 5.correct verbose log             -Done
             * 6.yield return "status"           -X
             * 7.UI compability                  -Done
             * 8.Filth cleaner                   -Done
             * 9.Fix:Faction Leader              -Done
             * 10.Fix:Faction Relations          -Done
             * 12.Warp->Wrap                     -Done
             */

            /*
             * TODO A18
             *  4.adjustable GC depth           -X
             *  11.GC boostup                   -Done
             *  13.remake GC System             -Done
             *  13.Keyed in Float menu items    -Done
             *  14.help contents                -Done
             *  15.Optimize Cleanser frame      -Done
             *  16.Optimize Floatmenu System    -Done
             *  17.Debug only options           -Done
             */

            /*
             * TODO 1.0
             *  18.Clean snow                   -Done
             *  19.whole-map clean              -Done
             *  20.remake log                   -Done
             *  21.Mod framework                -Done
             *  22.settings                     -Done
             *  23.MuteGC                       -Done
             *  24.MuteCL                       -Done
             *  25.remake FloatMenuUtil         -Done
             *  26.timer of gc                  -X
             *  27.toolbox integration          -Done
             *  28.MainButtonDef into xml       -Done
             *  29.try catch                    -Done
             *  30.Find.CurrentMap==null check  -Done
             *  31.MainButtonWorker             -Done
             *  32.Messages.Message(str,historical) settings -Done
             *  33.AvoidGrid rework             -Done
             *  34.Faction rework & cleanup     -Done
             *  35.Close letter stack           -Done
             */

            if (Current.ProgramState != ProgramState.Playing)
            {
                Verse.Log.Error("You must be kidding me...GC a save without loading one?");
                return(0);
            }

            /*Initialization*/
            Verse.Log.Message("[GC Log] Pre-Initializing GC...");
            this.reference = Find.WorldPawns.AllPawnsAliveOrDead.ToList();
            this.allFlags.Clear();
            this.verbose = verbose;
            if (verbose)
            {
                allFlagsCounter.Clear();
                allFlagsCounter.Add(Flags.None, 0);
                for (int j = 0; j < FlagsCountNotNull; j++)
                {
                    allFlagsCounter.Add((Flags)(1 << j), 0);
                }
            }

            /*Generate EntryPoints from Map Pawns*/
            Verse.Log.Message("[GC Log] Generating EntryPoints from Map Pawns...");
            List <Pawn> mapPawnEntryPoints;

            DiagnoseMapPawns(out mapPawnEntryPoints);
            if (verbose)
            {
                Verse.Log.Message("[GC Log][Verbose] " + allPawnsCounter.Count().ToString() + " Map Pawns marked during diagnosis");
            }

            /*Reset counters*/
            allPawnsCounter.Clear();
            if (verbose)
            {
                allFlagsCounter.Clear();
                allFlagsCounter.Add(Flags.None, 0);
                for (int j = 0; j < FlagsCountNotNull; j++)
                {
                    allFlagsCounter.Add((Flags)(1 << j), 0);
                }
            }

            /*Generate a list of pawns concerned by used Tales*/
            Verse.Log.Message("[GC Log] Collecting Pawns concerned by Used Tales...");
            List <Pawn> allUsedTalePawns;

            CleanserUtil.InitUsedTalePawns(out allUsedTalePawns);

            /*Diagnosis:marking entries on WorldPawns.*/
            Verse.Log.Message("[GC Log] Running diagnosis on WorldPawns...");
            foreach (Pawn p in reference)
            {
                if (p.IsColonist)
                {
                    addFlag(p, Flags.Colonist | Flags.RelationLvl2);
                }
                if (p.IsPrisonerOfColony)
                {
                    addFlag(p, Flags.Prisoner | Flags.RelationLvl2);
                }
                if (PawnUtility.IsFactionLeader(p))
                {
                    addFlag(p, Flags.KeptWorldPawn | Flags.FactionLeader | Flags.RelationLvl1);
                }
                if (PawnUtility.IsKidnappedPawn(p))
                {
                    addFlag(p, Flags.KeptWorldPawn | Flags.RelationLvl2);
                }
                if (p.Corpse != null)
                {
                    addFlag(p, Flags.CorpseOwner | Flags.RelationLvl1);
                }
                if (allUsedTalePawns.Contains(p))
                {
                    addFlag(p, Flags.TaleEntryOwner | Flags.RelationLvl0);
                }

                if (p.InContainerEnclosed)
                {
                    addFlag(p, Flags.KeptWorldPawn | Flags.RelationLvl0);
                }
                if (p.Spawned)
                {
                    addFlag(p, Flags.RelationLvl0);
                }
                if (p.IsPlayerControlledCaravanMember())
                {
                    addFlag(p, Flags.KeptWorldPawn | Flags.RelationLvl2);
                }
                if (PawnUtility.IsTravelingInTransportPodWorldObject(p))
                {
                    addFlag(p, Flags.KeptWorldPawn | Flags.RelationLvl2);
                }

                //Patch:A18 new entry
                if (PawnUtility.ForSaleBySettlement(p))
                {
                    addFlag(p, Flags.OnSale | Flags.RelationLvl0);
                }

                if (verbose)
                {
                    Verse.Log.Message("[worldPawn] " + p.LabelShort + " [flag] " + markedFlagsString(p));
                }
            }

            if (verbose)
            {
                Verse.Log.Message("[GC Log][Verbose] " + allPawnsCounter.Count().ToString() + " World Pawns marked during diagnosis");
            }


            int i;

            /*Expansion 1:Expand relation network from map pawns.*/
            Verse.Log.Message("[GC Log] Expanding Relation networks through Map Pawn Entry Points...");
            for (i = mapPawnEntryPoints.Count - 1; i > -1; i--)
            {
                if (containsFlag(mapPawnEntryPoints[i], Flags.RelationLvl2))
                {
                    expandRelation(mapPawnEntryPoints[i], Flags.RelationLvl1);
                    mapPawnEntryPoints.RemoveAt(i);
                }
            }

            for (i = mapPawnEntryPoints.Count - 1; i > -1; i--)
            {
                if (containsFlag(mapPawnEntryPoints[i], Flags.RelationLvl1))
                {
                    expandRelation(mapPawnEntryPoints[i], Flags.RelationLvl0);
                    mapPawnEntryPoints.RemoveAt(i);
                }
            }

            /*Its unnecessary to process RelationLvl0 in mapPawnEntryPoints,
             * for they are not related to any world pawns.
             */

            /*Expansion 2:Expand relation network from world pawns.*/
            Verse.Log.Message("[GC Log] Expanding Relation networks on marked World Pawns...");
            for (i = reference.Count - 1; i > -1; i--)
            {
                if (containsFlag(reference[i], Flags.RelationLvl2))
                {
                    expandRelation(reference[i], Flags.RelationLvl1);
                    reference.RemoveAt(i);
                }
            }

            for (i = reference.Count - 1; i > -1; i--)
            {
                if (containsFlag(reference[i], Flags.RelationLvl1))
                {
                    expandRelation(reference[i], Flags.RelationLvl0);
                    reference.RemoveAt(i);
                }
            }

            for (i = reference.Count - 1; i > -1; i--)
            {
                if (containsFlag(reference[i], Flags.RelationLvl0))
                {
                    reference.RemoveAt(i);
                }
            }


            int a = 0;

            /*VerboseMode:counting addFlag() calls.*/
            if (verbose)
            {
                foreach (KeyValuePair <Pawn, int> p in allPawnsCounter)
                {
                    a += p.Value;
                }
                Verse.Log.Message("[GC Log][Verbose] " + allPawnsCounter.Count().ToString() + " World Pawns marked during Expanding");
                if (debug)
                {
                    Verse.Log.Message("addFlag() called " + a + " times");
                }
            }


            /*Posfix:remove UsedTalePawns.*/
            Verse.Log.Message("[GC Log] Excluding Pawns concerned by Used Tales...");
            foreach (Pawn p in allUsedTalePawns)
            {
                reference.Remove(p);
            }


            /*GC Core:dispose all pawns left in reference list.*/
            Verse.Log.Message("[GC Log] Disposing World Pawns...");
            a = reference.Count;
            Pawn pawn;

            for (i = reference.Count - 1; i > -1; i--)
            {
                pawn = reference[i];
                //Patch:Mysterious WorldPawn.missing
                //Update:This patch is disabled due to safety concerns.
                //if(Find.WorldPawns.Contains(pawn))
                Find.WorldPawns.RemovePawn(pawn);
                if (!pawn.Destroyed)
                {
                    pawn.Destroy(DestroyMode.Vanish);
                }
                if (!pawn.Discarded)
                {
                    pawn.Discard(true);
                }
            }

            /*VerboseMode:Finalize output*/
            if (verbose)
            {
                string s = "[GC Log][Verbose] Flag calls stat:";
                allFlagsCounter.Remove(Flags.None);
                foreach (KeyValuePair <Flags, int> pair in allFlagsCounter)
                {
                    s += "\n  " + pair.Key.ToString() + " : " + pair.Value;
                }
                Verse.Log.Message(s);
            }

            Verse.Log.Message("[GC Log] GC() completed with " + a + " World Pawns disposed");

            return(a);
        }
Пример #12
0
 public void Notify_DamageTaken(DamageInfo dinfo)
 {
     this.mentalStateHandler.Notify_DamageTaken(dinfo);
     if (dinfo.Def.ExternalViolenceFor(this.pawn))
     {
         this.lastHarmTick = Find.TickManager.TicksGame;
         if (this.pawn.Spawned)
         {
             Pawn pawn = dinfo.Instigator as Pawn;
             if (!this.mentalStateHandler.InMentalState && dinfo.Instigator != null && (pawn != null || dinfo.Instigator is Building_Turret) && dinfo.Instigator.Faction != null && (dinfo.Instigator.Faction.def.humanlikeFaction || (pawn != null && pawn.def.race.intelligence >= Intelligence.ToolUser)) && this.pawn.Faction == null && (this.pawn.RaceProps.Animal || this.pawn.IsWildMan()) && (this.pawn.CurJob == null || this.pawn.CurJob.def != JobDefOf.PredatorHunt || dinfo.Instigator != ((JobDriver_PredatorHunt)this.pawn.jobs.curDriver).Prey) && Rand.Chance(PawnUtility.GetManhunterOnDamageChance(this.pawn, dinfo.Instigator)))
             {
                 this.StartManhunterBecauseOfPawnAction("AnimalManhunterFromDamage");
             }
             else if (dinfo.Instigator != null && dinfo.Def.makesAnimalsFlee && Pawn_MindState.CanStartFleeingBecauseOfPawnAction(this.pawn))
             {
                 this.StartFleeingBecauseOfPawnAction(dinfo.Instigator);
             }
         }
         if (this.pawn.GetPosture() != PawnPosture.Standing)
         {
             this.lastDisturbanceTick = Find.TickManager.TicksGame;
         }
     }
 }
Пример #13
0
 public void MindStateTick()
 {
     if (this.wantsToTradeWithColony)
     {
         TradeUtility.CheckInteractWithTradersTeachOpportunity(this.pawn);
     }
     if (this.meleeThreat != null && !this.MeleeThreatStillThreat)
     {
         this.meleeThreat = null;
     }
     this.mentalStateHandler.MentalStateHandlerTick();
     this.mentalBreaker.MentalBreakerTick();
     this.inspirationHandler.InspirationHandlerTick();
     if (!this.pawn.GetPosture().Laying())
     {
         this.applyBedThoughtsTick = 0;
     }
     if (this.pawn.IsHashIntervalTick(100))
     {
         if (this.pawn.Spawned)
         {
             int regionsToScan = (!this.anyCloseHostilesRecently) ? 18 : 24;
             this.anyCloseHostilesRecently = PawnUtility.EnemiesAreNearby(this.pawn, regionsToScan, true);
         }
         else
         {
             this.anyCloseHostilesRecently = false;
         }
     }
     if (this.WillJoinColonyIfRescued && this.pawn.Spawned && this.pawn.IsHashIntervalTick(30))
     {
         if (this.pawn.Faction == Faction.OfPlayer)
         {
             this.WillJoinColonyIfRescued = false;
         }
         else if (this.pawn.IsPrisoner && !this.pawn.HostFaction.HostileTo(Faction.OfPlayer))
         {
             this.WillJoinColonyIfRescued = false;
         }
         else if (!this.pawn.IsPrisoner && this.pawn.Faction != null && this.pawn.Faction.HostileTo(Faction.OfPlayer) && !this.pawn.Downed)
         {
             this.WillJoinColonyIfRescued = false;
         }
         else
         {
             foreach (Pawn current in this.pawn.Map.mapPawns.FreeColonistsSpawned)
             {
                 if (current.IsColonistPlayerControlled && current.Position.InHorDistOf(this.pawn.Position, 4f) && GenSight.LineOfSight(this.pawn.Position, current.Position, this.pawn.Map, false, null, 0, 0))
                 {
                     this.JoinColonyBecauseRescuedBy(current);
                     break;
                 }
             }
         }
     }
     if (this.pawn.Spawned && this.pawn.IsWildMan() && !this.WildManEverReachedOutside && this.pawn.GetRoom(RegionType.Set_Passable) != null && this.pawn.GetRoom(RegionType.Set_Passable).TouchesMapEdge)
     {
         this.WildManEverReachedOutside = true;
     }
     if (Find.TickManager.TicksGame % 123 == 0 && this.pawn.Spawned && this.pawn.RaceProps.IsFlesh && this.pawn.needs.mood != null)
     {
         TerrainDef terrain = this.pawn.Position.GetTerrain(this.pawn.Map);
         if (terrain.traversedThought != null)
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(terrain.traversedThought);
         }
         WeatherDef curWeatherLerped = this.pawn.Map.weatherManager.CurWeatherLerped;
         if (curWeatherLerped.exposedThought != null && !this.pawn.Position.Roofed(this.pawn.Map))
         {
             this.pawn.needs.mood.thoughts.memories.TryGainMemoryFast(curWeatherLerped.exposedThought);
         }
     }
     if (GenLocalDate.DayTick(this.pawn) == 0)
     {
         this.interactionsToday = 0;
     }
 }
Пример #14
0
        public static bool FindPath(PathFinder __instance, ref PawnPath __result, IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }

            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != __instance.map)
            {
                Log.Error(string.Concat("Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=", pawn, " pawn.Map=", pawn.Map, " map=", __instance.map));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!start.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid start ", start, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!dest.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (traverseParms.mode == TraverseMode.ByPawn)
            {
#if RW12
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
#endif
#if RW13
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBashDoors, traverseParms.canBashFences, traverseParms.mode))
#endif
                {
                    __result = PawnPath.NotFound;
                    return(false);
                }
            }
            else if (!__instance.map.reachability.CanReach(start, dest, peMode, traverseParms))
            {
                __result = PawnPath.NotFound;
                return(false);
            }

            __instance.PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, dest.HasThing ? (" at " + dest.Cell) : ""));
            __instance.cellIndices = __instance.map.cellIndices;
#if RW12
            __instance.pathGrid = __instance.map.pathGrid;
#endif
#if RW13
            __instance.pathingContext = __instance.map.pathing.For(traverseParms);
            __instance.pathGrid       = __instance.pathingContext.pathGrid;
#endif
            __instance.edificeGrid   = __instance.map.edificeGrid.InnerArray;
            __instance.blueprintGrid = __instance.map.blueprintGrid.InnerArray;
            int      x               = dest.Cell.x;
            int      z               = dest.Cell.z;
            int      curIndex        = __instance.cellIndices.CellToIndex(start);
            int      num             = __instance.cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid        = pawn?.GetAvoidGrid();
            bool     flag            = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag2           = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3           = !flag;
            CellRect destinationRect = __instance.CalculateDestinationRect(dest, peMode);
            bool     flag4           = destinationRect.Width == 1 && destinationRect.Height == 1;
#if RW12
            int[] array = __instance.map.pathGrid.pathGrid;
#endif
#if RW13
            int[] array = __instance.pathGrid.pathGrid;
#endif
            TerrainDef[] topGrid     = __instance.map.terrainGrid.topGrid;
            EdificeGrid  edificeGrid = __instance.map.edificeGrid;
            int          num2        = 0;
            int          num3        = 0;
            Area         allowedArea = __instance.GetAllowedArea(pawn);
            bool         flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = !flag && start.GetRegion(__instance.map) != null && flag2;
            bool         flag7       = !flag || !flag3;
            bool         flag8       = false;
            bool         flag9       = pawn?.Drafted ?? false;
            int          num4        = (pawn?.IsColonist ?? false) ? 100000 : 2000;
            int          num5        = 0;
            int          num6        = 0;
            float        num7        = __instance.DetermineHeuristicStrength(pawn, start, dest);
            int          num8;
            int          num9;
            if (pawn != null)
            {
                num8 = pawn.TicksPerMoveCardinal;
                num9 = pawn.TicksPerMoveDiagonal;
            }
            else
            {
                num8 = 13;
                num9 = 18;
            }
#if RW12
            __instance.CalculateAndAddDisallowedCorners(traverseParms, peMode, destinationRect);
#endif
#if RW13
            __instance.CalculateAndAddDisallowedCorners(peMode, destinationRect);
#endif
            __instance.InitStatusesAndPushStartNode(ref curIndex, start);
            while (true)
            {
                __instance.PfProfilerBeginSample("Open cell");
                if (openList.Count <= 0)
                {
                    string text  = (pawn != null && pawn.CurJob != null) ? pawn.CurJob.ToString() : "null";
                    string text2 = (pawn != null && pawn.Faction != null) ? pawn.Faction.ToString() : "null";
                    Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2));
                    __instance.DebugDrawRichData();
                    __instance.PfProfilerEndSample();
                    __instance.PfProfilerEndSample();
                    __result = PawnPath.NotFound;
                    return(false);
                }

                num5 += openList.Count;
                num6++;
                PathFinder.CostNode costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    __instance.PfProfilerEndSample();
                    continue;
                }

                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    __instance.PfProfilerEndSample();
                    continue;
                }

                IntVec3 c  = __instance.cellIndices.IndexToCell(curIndex);
                int     x2 = c.x;
                int     z2 = c.z;
                if (flag4)
                {
                    if (curIndex == num)
                    {
                        __instance.PfProfilerEndSample();
                        PawnPath result = __instance.FinalizedPath(curIndex, flag8);
                        __instance.PfProfilerEndSample();
                        __result = result;
                        return(false);
                    }
                }
                else if (destinationRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex))
                {
                    __instance.PfProfilerEndSample();
                    PawnPath result2 = __instance.FinalizedPath(curIndex, flag8);
                    __instance.PfProfilerEndSample();
                    __result = result2;
                    return(false);
                }

                if (num2 > 160000)
                {
                    break;
                }

                __instance.PfProfilerEndSample();
                __instance.PfProfilerBeginSample("Neighbor consideration");
                for (int i = 0; i < 8; i++)
                {
                    uint num10 = (uint)(x2 + PathFinder.Directions[i]);
                    uint num11 = (uint)(z2 + PathFinder.Directions[i + 8]);
                    if (num10 >= __instance.mapSizeX || num11 >= __instance.mapSizeZ)
                    {
                        continue;
                    }

                    int num12 = (int)num10;
                    int num13 = (int)num11;
                    int num14 = __instance.cellIndices.CellToIndex(num12, num13);
                    if (calcGrid[num14].status == statusClosedValue && !flag8)
                    {
                        continue;
                    }

                    int  num15  = 0;
                    bool flag10 = false;
                    if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(__instance.map).HasTag("Water"))
                    {
                        continue;
                    }

                    if (!__instance.pathGrid.WalkableFast(num14))
                    {
                        if (!flag)
                        {
                            continue;
                        }

                        flag10 = true;
                        num15 += 70;
                        Building building = edificeGrid[num14];
                        if (building == null || !PathFinder.IsDestroyable(building))
                        {
                            continue;
                        }

                        num15 += (int)(building.HitPoints * 0.2f);
                    }

                    switch (i)
                    {
                    case 4:
                        if (__instance.BlocksDiagonalMovement(curIndex - __instance.mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (__instance.BlocksDiagonalMovement(curIndex + 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 5:
                        if (__instance.BlocksDiagonalMovement(curIndex + __instance.mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (__instance.BlocksDiagonalMovement(curIndex + 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 6:
                        if (__instance.BlocksDiagonalMovement(curIndex + __instance.mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (__instance.BlocksDiagonalMovement(curIndex - 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 7:
                        if (__instance.BlocksDiagonalMovement(curIndex - __instance.mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (__instance.BlocksDiagonalMovement(curIndex - 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;
                    }

                    int num16 = (i > 3) ? num9 : num8;
                    num16 += num15;
                    if (!flag10)
                    {
                        num16 += array[num14];
                        num16  = ((!flag9) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost));
                    }

                    if (byteGrid != null)
                    {
                        num16 += byteGrid[num14] * 8;
                    }

                    if (allowedArea != null && !allowedArea[num14])
                    {
                        num16 += 600;
                    }

                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true))
                    {
                        num16 += 175;
                    }

                    Building building2 = __instance.edificeGrid[num14];
                    if (building2 != null)
                    {
                        __instance.PfProfilerBeginSample("Edifices");
                        int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn);
                        if (buildingCost == int.MaxValue)
                        {
                            __instance.PfProfilerEndSample();
                            continue;
                        }

                        num16 += buildingCost;
                        __instance.PfProfilerEndSample();
                    }

                    List <Blueprint> list = __instance.blueprintGrid[num14];
                    if (list != null)
                    {
                        __instance.PfProfilerBeginSample("Blueprints");
                        int num17 = 0;
                        for (int j = 0; j < list.Count; j++)
                        {
                            num17 = Mathf.Max(num17, PathFinder.GetBlueprintCost(list[j], pawn));
                        }

                        if (num17 == int.MaxValue)
                        {
                            __instance.PfProfilerEndSample();
                            continue;
                        }

                        num16 += num17;
                        __instance.PfProfilerEndSample();
                    }

                    int    num18  = num16 + calcGrid[curIndex].knownCost;
                    ushort status = calcGrid[num14].status;
                    if (status == statusClosedValue || status == statusOpenValue)
                    {
                        int num19 = 0;
                        if (status == statusClosedValue)
                        {
                            num19 = num8;
                        }

                        if (calcGrid[num14].knownCost <= num18 + num19)
                        {
                            continue;
                        }
                    }

                    if (flag8)
                    {
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt(__instance.regionCostCalculator.GetPathCostFromDestToRegion(num14) * PathFinder.RegionHeuristicWeightByNodesOpened.Evaluate(num3));
                        if (calcGrid[num14].heuristicCost < 0)
                        {
                            Log.ErrorOnce(string.Concat("Heuristic cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0xB8DC389);
                            calcGrid[num14].heuristicCost = 0;
                        }
                    }
                    else if (status != statusClosedValue && status != statusOpenValue)
                    {
                        int dx    = Math.Abs(num12 - x);
                        int dz    = Math.Abs(num13 - z);
                        int num20 = GenMath.OctileDistance(dx, dz, num8, num9);
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt(num20 * num7);
                    }

                    int num21 = num18 + calcGrid[num14].heuristicCost;
                    if (num21 < 0)
                    {
                        Log.ErrorOnce(string.Concat("Node cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0x53CB9DE);
                        num21 = 0;
                    }

                    calcGrid[num14].parentIndex  = curIndex;
                    calcGrid[num14].knownCost    = num18;
                    calcGrid[num14].status       = statusOpenValue;
                    calcGrid[num14].costNodeCost = num21;
                    num3++;
                    openList.Push(new PathFinder.CostNode(num14, num21));
                }

                __instance.PfProfilerEndSample();
                num2++;
                calcGrid[curIndex].status = statusClosedValue;
                if (num3 >= num4 && flag6 && !flag8)
                {
                    flag8 = true;
                    __instance.regionCostCalculator.Init(destinationRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndices);
                    __instance.InitStatusesAndPushStartNode(ref curIndex, start);
                    openList.Clear();
                    openList.Push(new PathFinder.CostNode(curIndex, 0));
                    num3 = 0;
                    num2 = 0;
                }
            }

            Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells."));
            __instance.DebugDrawRichData();
            __instance.PfProfilerEndSample();
            __instance.PfProfilerEndSample();
            __result = PawnPath.NotFound;
            return(false);
        }
Пример #15
0
        private WorkPriority GetPriorityWork(Pawn pawn)
        {
            #region Traders have no work priority
            if (pawn.kindDef.trader)
            {
                return(WorkPriority.None);
            }
            #endregion

            //#region Pawns with non-idle jobs have no work priority
            //bool hasCurJob = pawn.CurJob != null;
            //JobDef jobDef = hasCurJob ? pawn.CurJob.def : null;

            //if (hasCurJob && !jobDef.isIdle)
            //{
            //    return WorkPriority.None;
            //}
            //#endregion

            bool         hasPrimary      = (pawn.equipment != null && pawn.equipment.Primary != null);
            CompAmmoUser primaryAmmoUser = hasPrimary ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : hasWeaponInInventory(pawn) ? weaponInInventory(pawn) : null;

            #region Colonists with primary ammo-user and a loadout have no work priority
            if (pawn.Faction.IsPlayer &&
                primaryAmmoUser != null)
            {
                Loadout loadout = pawn.GetLoadout();
                // if (loadout != null && !loadout.Slots.NullOrEmpty())
                if (loadout != null && loadout.SlotCount > 0)
                {
                    return(WorkPriority.None);
                }
            }
            #endregion

            // Pawns without weapon..
            if (!hasPrimary)
            {
                // With inventory && non-colonist && not stealing && little space left
                if (Unload(pawn))
                {
                    return(WorkPriority.Unloading);
                }
                // Without inventory || colonist || stealing || lots of space left
                if (!hasWeaponInInventory(pawn))
                {
                    return(WorkPriority.Weapon);
                }
            }

            CompInventory compInventory = pawn.TryGetComp <CompInventory>();
            // Pawn with ammo-using weapon..
            if (primaryAmmoUser != null && primaryAmmoUser.UseAmmo)
            {
                // Magazine size
                FloatRange magazineSize = new FloatRange(1f, 2f);
                LoadoutPropertiesExtension loadoutPropertiesExtension = (LoadoutPropertiesExtension)(pawn.kindDef.modExtensions?.FirstOrDefault(x => x is LoadoutPropertiesExtension));
                bool hasWeaponTags = pawn.kindDef.weaponTags?.Any() ?? false;

                if (hasWeaponTags &&
                    primaryAmmoUser.parent.def.weaponTags.Any(pawn.kindDef.weaponTags.Contains) &&
                    loadoutPropertiesExtension != null &&
                    loadoutPropertiesExtension.primaryMagazineCount != FloatRange.Zero)
                {
                    magazineSize.min = loadoutPropertiesExtension.primaryMagazineCount.min;
                    magazineSize.max = loadoutPropertiesExtension.primaryMagazineCount.max;
                }

                magazineSize.min *= primaryAmmoUser.Props.magazineSize;
                magazineSize.max *= primaryAmmoUser.Props.magazineSize;

                // Number of things in inventory that could be put in the weapon
                int   viableAmmoCarried = 0;
                float viableAmmoBulk    = 0;
                foreach (AmmoLink link in primaryAmmoUser.Props.ammoSet.ammoTypes)
                {
                    var count = compInventory.AmmoCountOfDef(link.ammo);
                    viableAmmoCarried += count;
                    viableAmmoBulk    += count * link.ammo.GetStatValueAbstract(CE_StatDefOf.Bulk);
                }

                // ~2/3rds of the inventory bulk minus non-usable and non-ammo bulk could be filled with ammo
                float potentialAmmoBulk = ammoFractionOfNonAmmoInventory * (compInventory.capacityBulk - compInventory.currentBulk + viableAmmoBulk);
                // There's less ammo [bulk] than fits the potential ammo bulk [bulk]
                if (viableAmmoBulk < potentialAmmoBulk)
                {
                    // There's less ammo [nr] than fits a clip [nr]
                    if (primaryAmmoUser.Props.magazineSize == 0 || viableAmmoCarried < magazineSize.min)
                    {
                        return(Unload(pawn) ? WorkPriority.Unloading : WorkPriority.LowAmmo);
                    }

                    // There's less ammo [nr] than fits two clips [nr] && no enemies are close
                    if (viableAmmoCarried < magazineSize.max &&
                        !PawnUtility.EnemiesAreNearby(pawn, 20, true))
                    {
                        return(Unload(pawn) ? WorkPriority.Unloading : WorkPriority.Ammo);
                    }
                }
            }
            return(WorkPriority.None);
        }
Пример #16
0
        void TickAction()
        {
            var fadeOff               = Tools.PheromoneFadeoff();
            var agitatedFadeoff       = fadeOff / 4;
            var checkSmashableFadeoff = agitatedFadeoff / 2;

            var zombie = (Zombie)pawn;

            if (zombie.state == ZombieState.Emerging)
            {
                return;
            }
            var map = zombie.Map;

            if (zombie.Dead || zombie.Destroyed)
            {
                EndJobWith(JobCondition.InterruptForced);
                return;
            }

            if (zombie.state == ZombieState.ShouldDie)
            {
                EndJobWith(JobCondition.InterruptForced);
                zombie.Kill(null);
                return;
            }

            if (ZombieSettings.Values.zombiesDieVeryEasily)
            {
                if (zombie.health.hediffSet.GetHediffs <Hediff_Injury>().Any())
                {
                    zombie.Kill(null);
                    return;
                }
            }

            if (zombie.Downed)
            {
                if (ZombieSettings.Values.zombiesDieVeryEasily || ZombieSettings.Values.doubleTapRequired == false)
                {
                    zombie.Kill(null);
                    return;
                }

                var walkCapacity = PawnCapacityUtility.CalculateCapacityLevel(zombie.health.hediffSet, PawnCapacityDefOf.Moving);
                var missingBrain = zombie.health.hediffSet.GetBrain() == null;
                if (walkCapacity < 0.25f || missingBrain)
                {
                    zombie.Kill(null);
                    return;
                }

                var injuries = zombie.health.hediffSet.GetHediffs <Hediff_Injury>();
                foreach (var injury in injuries)
                {
                    if (ZombieSettings.Values.zombiesDieVeryEasily)
                    {
                        zombie.Kill(null);
                        return;
                    }

                    if (injury.IsOld() == false)
                    {
                        injury.Heal(injury.Severity + 0.5f);
                        break;
                    }
                }

                if (zombie.Downed)
                {
                    return;
                }
            }

            // handling invalid destinations
            //
            if (destination.x == 0 && destination.z == 0)
            {
                destination = IntVec3.Invalid;
            }
            if (zombie.HasValidDestination(destination))
            {
                return;
            }

            // if we are near targets then attack them
            //
            var enemy = CanAttack();

            if (enemy != null)
            {
                destination = enemy.Position;

                zombie.state = ZombieState.Tracking;
                if (Constants.USE_SOUND)
                {
                    var info = SoundInfo.InMap(enemy);
                    SoundDef.Named("ZombieHit").PlayOneShot(info);
                }

                AttackThing(enemy, JobDefOf.AttackMelee);
                return;
            }

            // eat a downed or dead pawn
            //
            if (eatTarget == null)
            {
                eatTarget = CanIngest(out eatTargetIsCorpse);
                if (eatTarget != null)
                {
                    eatTargetDied = eatTarget.Dead;
                }
            }

            if (eatTarget != null)
            {
                if (eatDelayCounter == 0)
                {
                    if (eatTarget != lastEatTarget)
                    {
                        lastEatTarget = eatTarget;
                        zombie.Drawer.rotator.FaceCell(eatTarget.Position);
                        var zombieLeaner = zombie.Drawer.leaner as ZombieLeaner;
                        if (zombieLeaner != null)
                        {
                            zombieLeaner.extraOffset = (eatTarget.Position.ToVector3() - zombie.Position.ToVector3()) * 0.5f;
                        }

                        Tools.CastThoughtBubble(pawn, Constants.EATING);
                    }
                    CastEatingSound();
                }

                eatDelayCounter++;
                if (eatDelayCounter <= EatDelay)
                {
                    return;
                }
                eatDelayCounter = 0;

                var bodyPartRecord = FirstEatablePart(eatTarget);
                if (bodyPartRecord != null)
                {
                    var hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, eatTarget, bodyPartRecord);
                    hediff_MissingPart.lastInjury = HediffDefOf.Bite;
                    hediff_MissingPart.IsFresh    = true;
                    eatTarget.health.AddHediff(hediff_MissingPart, null, null);

                    if (eatTargetIsCorpse == false && eatTargetDied == false && eatTarget.Dead)
                    {
                        Tools.DoWithAllZombies(map, z =>
                        {
                            if (z.jobs != null)
                            {
                                var driver = z.jobs.curDriver as JobDriver_Stumble;
                                if (driver != null && driver.eatTarget == eatTarget)
                                {
                                    driver.eatTargetDied     = true;
                                    driver.eatTargetIsCorpse = true;
                                }
                            }
                        });

                        if (PawnUtility.ShouldSendNotificationAbout(eatTarget) && eatTarget.RaceProps.Humanlike)
                        {
                            Messages.Message("MessageEatenByPredator".Translate(new object[]
                            {
                                eatTarget.LabelShort,
                                zombie.LabelIndefinite()
                            }).CapitalizeFirst(), zombie, MessageSound.Negative);
                        }

                        eatTarget.Strip();
                    }

                    return;
                }
                else
                {
                    var corpse = map.thingGrid
                                 .ThingsListAt(eatTarget.Position)
                                 .OfType <Corpse>()
                                 .FirstOrDefault(c => c.InnerPawn == eatTarget);
                    if (corpse != null)
                    {
                        corpse.Destroy(DestroyMode.Vanish);
                    }

                    Tools.DoWithAllZombies(map, z =>
                    {
                        if (z.jobs != null)
                        {
                            var driver = z.jobs.curDriver as JobDriver_Stumble;
                            if (driver != null && driver.eatTarget == eatTarget)
                            {
                                driver.eatTarget       = null;
                                driver.lastEatTarget   = null;
                                driver.eatDelayCounter = 0;
                            }
                        }
                    });
                }
            }
            else
            {
                var zombieLeaner = zombie.Drawer.leaner as ZombieLeaner;
                if (zombieLeaner != null)
                {
                    zombieLeaner.extraOffset = Vector3.zero;
                }
            }

            var basePos = zombie.Position;

            // calculate possible moves, sort by pheromone value and take top 3
            // then choose the one with the lowest zombie count
            // also, emit a circle of timestamps when discovering a pheromone
            // trace so nearby zombies pick it up too (leads to a chain reaction)
            //
            var grid = zombie.Map.GetGrid();
            var possibleTrackingMoves = new List <IntVec3>();
            var currentTicks          = Tools.Ticks();
            var timeDelta             = long.MaxValue;

            for (int i = 0; i < 8; i++)
            {
                var pos = basePos + GenAdj.AdjacentCells[i];
                if (currentTicks - grid.Get(pos, false).timestamp < fadeOff && zombie.HasValidDestination(pos))
                {
                    possibleTrackingMoves.Add(pos);
                }
            }
            if (possibleTrackingMoves.Count > 0)
            {
                possibleTrackingMoves.Sort((p1, p2) => SortByTimestamp(grid, p1, p2));
                possibleTrackingMoves = possibleTrackingMoves.Take(Constants.NUMBER_OF_TOP_MOVEMENT_PICKS).ToList();
                possibleTrackingMoves = possibleTrackingMoves.OrderBy(p => grid.Get(p, false).zombieCount).ToList();
                var nextMove = possibleTrackingMoves.First();
                timeDelta = currentTicks - grid.Get(nextMove, false).timestamp;

                destination = nextMove;
                if (zombie.state == ZombieState.Wandering)
                {
                    Tools.ChainReact(zombie.Map, basePos, nextMove);
                    if (timeDelta <= agitatedFadeoff)
                    {
                        CastBrainzThought();
                    }
                }
                zombie.state = ZombieState.Tracking;
            }
            if (destination.IsValid == false)
            {
                zombie.state = ZombieState.Wandering;
            }

            bool checkSmashable = timeDelta >= checkSmashableFadeoff;

            if (ZombieSettings.Values.smashOnlyWhenAgitated)
            {
                checkSmashable &= zombie.state == ZombieState.Tracking;
            }

            if (destination.IsValid == false || checkSmashable)
            {
                var building = CanSmash();
                if (building != null)
                {
                    destination = building.Position;

                    if (Constants.USE_SOUND)
                    {
                        var info = SoundInfo.InMap(enemy);
                        SoundDef.Named("ZombieHit").PlayOneShot(info);
                    }

                    AttackThing(building, JobDefOf.AttackStatic);
                    return;
                }
            }

            if (destination.IsValid == false)
            {
                var hour = GenLocalDate.HourOfDay(Find.VisibleMap);

                // check for day/night and dust/dawn
                //
                var moveTowardsCenter = false;
                if (map.areaManager.Home[basePos] == false)
                {
                    if (hour < 12)
                    {
                        hour += 24;
                    }
                    if (hour > Constants.HOUR_START_OF_NIGHT && hour < Constants.HOUR_END_OF_NIGHT)
                    {
                        moveTowardsCenter = true;
                    }
                    else if (hour >= Constants.HOUR_START_OF_DUSK && hour <= Constants.HOUR_START_OF_NIGHT)
                    {
                        moveTowardsCenter = Rand.RangeInclusive(hour, Constants.HOUR_START_OF_NIGHT) == Constants.HOUR_START_OF_NIGHT;
                    }
                    else if (hour >= Constants.HOUR_END_OF_NIGHT && hour <= Constants.HOUR_START_OF_DAWN)
                    {
                        moveTowardsCenter = Rand.RangeInclusive(Constants.HOUR_END_OF_NIGHT, hour) == Constants.HOUR_END_OF_NIGHT;
                    }
                }

                var possibleMoves = new List <IntVec3>();
                for (int i = 0; i < 8; i++)
                {
                    var pos = basePos + GenAdj.AdjacentCells[i];
                    if (zombie.HasValidDestination(pos))
                    {
                        possibleMoves.Add(pos);
                    }
                }
                if (possibleMoves.Count > 0)
                {
                    // during night, zombies drift towards the colonies center
                    //
                    if (moveTowardsCenter)
                    {
                        var center = zombie.wanderDestination.IsValid ? zombie.wanderDestination : map.Center;
                        possibleMoves.Sort((p1, p2) => SortByDirection(center, p1, p2));
                        possibleMoves = possibleMoves.Take(Constants.NUMBER_OF_TOP_MOVEMENT_PICKS).ToList();
                        possibleMoves = possibleMoves.OrderBy(p => grid.Get(p, false).zombieCount).ToList();
                        destination   = possibleMoves.First();
                    }
                    else
                    {
                        // otherwise they sometimes stand or walk towards a random direction
                        //
                        if (Rand.Chance(Constants.STANDING_STILL_CHANCE))
                        {
                            var n = possibleMoves.Count();
                            destination = possibleMoves[Constants.random.Next(n)];
                        }
                    }
                }
            }

            // if we have a valid destination, go there
            //
            if (destination.IsValid)
            {
                MoveToCell(destination);
            }
        }
Пример #17
0
        //Handles the spawning of pawns
        public override void GiveBirth()
        {
            Pawn mother = pawn;

            if (mother == null)
            {
                return;
            }
            try
            {
                //fail if hediff added through debug, since babies not initialized
                if (babies.Count > 9999)
                {
                    Log.Message("RJW mech pregnancy birthing pawn count: " + babies.Count);
                }
            }
            catch
            {
                Initialize(mother, father);
            }
            foreach (Pawn baby in babies)
            {
                Faction spawn_faction = null;
                if (!is_hacked)
                {
                    spawn_faction = Faction.OfMechanoids;
                }

                Pawn baby1 = PawnGenerator.GeneratePawn(new PawnGenerationRequest(PawnKindDef.Named("Mech_Scyther"), spawn_faction));
                PawnUtility.TrySpawnHatchedOrBornPawn(baby1, mother);
                if (!is_hacked)
                {
                    LordJob_MechanoidsDefendShip lordJob = new LordJob_MechanoidsDefendShip(mother, baby1.Faction, 50f, mother.Position);
                    Lord lord = LordMaker.MakeNewLord(baby1.Faction, lordJob, baby1.Map);
                    lord.AddPawn(baby1);
                }
                FilthMaker.MakeFilth(baby1.PositionHeld, baby1.MapHeld, mother.RaceProps.BloodDef, mother.LabelIndefinite());
            }

            IEnumerable <BodyPartRecord> source = from x in mother.health.hediffSet.GetNotMissingParts()
                                                  where x.IsInGroup(BodyPartGroupDefOf.Torso) &&
                                                  !x.IsCorePart
                                                  //someday include depth filter
                                                  //so it doesnt cut out external organs (breasts)?
                                                  //vag  is genital part and genital is external
                                                  //anal is internal
                                                  //make sep part of vag?
                                                  //&& x.depth == BodyPartDepth.Inside
                                                  select x;

            if (source.Any())
            {
                foreach (BodyPartRecord part in source)
                {
                    Hediff_MissingPart hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, mother, part);
                    hediff_MissingPart.lastInjury = HediffDefOf.Cut;
                    hediff_MissingPart.IsFresh    = true;
                    mother.health.AddHediff(hediff_MissingPart);

                    //idk blood doesnt drop
                    //mother.health.DropBloodFilth();
                    //FilthMaker.MakeFilth(corpse.PositionHeld, corpse.MapHeld, mother.RaceProps.BloodDef, mother.LabelIndefinite());
                }
            }
            mother.health.RemoveHediff(this);
        }
Пример #18
0
        public PawnPath FindShipPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }
            Pawn pawn = traverseParms.pawn;

            if (!(pawn is null) && pawn.Map != this.map)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindShipPath for pawn which is spawned in another map. his map ShipPathFinder should  have been used, not this one. " +
                    "pawn=", pawn,
                    " pawn.Map=", pawn.Map,
                    " map=", this.map
                }), false);
                return(PawnPath.NotFound);
            }
            if (!start.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindShipPath with invalid start ",
                    start,
                    ", pawn=", pawn
                }), false);
                return(PawnPath.NotFound);
            }
            if (!dest.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath with invalid dest ",
                    dest,
                    ", pawn= ",
                    pawn
                }), false);
                return(PawnPath.NotFound);
            }
            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!ShipReachabilityUtility.CanReachShip(pawn, dest, peMode, Danger.Deadly, false, traverseParms.mode))
                {
                    return(PawnPath.NotFound);
                }
            }
            else if (!mapE.getShipReachability.CanReachShip(start, dest, peMode, traverseParms))
            {
                return(PawnPath.NotFound);
            }
            this.PfProfilerBeginSample(string.Concat(new object[]
            {
                "FindPath for ", pawn,
                " from ", start,
                " to ", dest,
                (!dest.HasThing) ? string.Empty : (" at " + dest.Cell)
            }));
            this.cellIndices   = this.map.cellIndices;
            this.shipPathGrid  = mapE.getShipPathGrid;
            this.edificeGrid   = this.map.edificeGrid.InnerArray;
            this.blueprintGrid = this.map.blueprintGrid.InnerArray;
            int      x        = dest.Cell.x;
            int      z        = dest.Cell.z;
            int      num      = this.cellIndices.CellToIndex(start);
            int      num2     = this.cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid = (pawn is null) ? null : pawn.GetAvoidGrid(true);
            bool     flag     = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag2    = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3    = !flag;
            CellRect cellRect = this.CalculateDestinationRect(dest, peMode);
            bool     flag4    = cellRect.Width == 1 && cellRect.Height == 1;

            int[]        array       = mapE.getShipPathGrid.pathGrid;
            TerrainDef[] topGrid     = this.map.terrainGrid.topGrid;
            EdificeGrid  edificeGrid = this.map.edificeGrid;
            int          num3        = 0;
            int          num4        = 0;
            Area         allowedArea = this.GetAllowedArea(pawn);
            bool         flag5       = !(pawn is null) && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = true && DebugViewSettings.drawPaths;
            bool         flag7       = !flag && !(WaterGridsUtility.GetRegion(start, this.map, RegionType.Set_Passable) is null) && flag2;
            bool         flag8       = !flag || !flag3;
            bool         flag9       = false;
            bool         flag10      = !(pawn is null) && pawn.Drafted;
            bool         flag11      = !(pawn is null) && !(pawn.GetComp <CompShips>() is null);

            int   num5  = (!flag11) ? NodesToOpenBeforeRegionbasedPathing_NonShip : NodesToOpenBeforeRegionBasedPathing_Ship;
            int   num6  = 0;
            int   num7  = 0;
            float num8  = this.DetermineHeuristicStrength(pawn, start, dest);
            int   num9  = !(pawn is null) ? pawn.TicksPerMoveCardinal : DefaultMoveTicksCardinal;
            int   num10 = !(pawn is null) ? pawn.TicksPerMoveDiagonal : DefaultMoveTicksDiagonal;

            this.CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect);
            this.InitStatusesAndPushStartNode(ref num, start);
            for (;;)
            {
                this.PfProfilerBeginSample("Open cell");
                if (this.openList.Count <= 0)
                {
                    break;
                }
                num6 += this.openList.Count;
                num7++;
                ShipPathFinder.CostNode costNode = this.openList.Pop();
                num = costNode.index;
                if (costNode.cost != this.calcGrid[num].costNodeCost)
                {
                    this.PfProfilerEndSample();
                }
                else if (this.calcGrid[num].status == this.statusClosedValue)
                {
                    this.PfProfilerEndSample();
                }
                else
                {
                    IntVec3 c  = this.cellIndices.IndexToCell(num);
                    int     x2 = c.x;
                    int     z2 = c.z;
                    if (flag6)
                    {
                        this.DebugFlash(c, (float)this.calcGrid[num].knownCost / 1500f, this.calcGrid[num].knownCost.ToString());
                    }
                    if (flag4)
                    {
                        if (num == num2)
                        {
                            goto Block_32;
                        }
                    }
                    else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num))
                    {
                        goto Block_34;
                    }
                    if (num3 > SearchLimit)
                    {
                        goto Block_35;
                    }
                    this.PfProfilerEndSample();
                    this.PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        uint num11 = (uint)(x2 + ShipPathFinder.Directions[i]);
                        uint num12 = (uint)(z2 + ShipPathFinder.Directions[i + 8]);
                        if ((ulong)num11 < ((ulong)this.mapSizeX) && (ulong)num12 < (ulong)((long)this.mapSizeZ))
                        {
                            int num13 = (int)num11;
                            int num14 = (int)num12;
                            int num15 = this.cellIndices.CellToIndex(num13, num14);
                            if (this.calcGrid[num15].status != this.statusClosedValue || flag9)
                            {
                                int num16 = 0;
                                //bool flag12 = false; Extra cost for traversing water

                                if (flag2 || !new IntVec3(num13, 0, num14).GetTerrain(this.map).HasTag("Water"))
                                {
                                    if (!this.shipPathGrid.WalkableFast(num15))
                                    {
                                        if (!flag)
                                        {
                                            if (flag6)
                                            {
                                                this.DebugFlash(new IntVec3(num13, 0, num14), 0.22f, "walk");
                                            }
                                            goto IL_E3A;
                                        }
                                        //flag12 = true;
                                        num16 += 70;
                                        Building building = edificeGrid[num15];
                                        if (building is null)
                                        {
                                            goto IL_E3A;
                                        }
                                        if (!IsDestroyable(building))
                                        {
                                            goto IL_E3A;
                                        }
                                        num16 += (int)((float)building.HitPoints * 0.2f);
                                    }
                                    if (i > 3)
                                    {
                                        switch (i)
                                        {
                                        case 4:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            break;

                                        case 5:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            break;

                                        case 6:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            break;

                                        case 7:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "ships");
                                                    }
                                                    goto IL_E3A;
                                                }
                                                num16 += 70;
                                            }
                                            break;
                                        }
                                    }
                                    int num17 = (i <= 3) ? num9 : num10;
                                    num17 += num16;

                                    /*if(!flag12)
                                     * {
                                     *  //Extra Costs for traversing water
                                     *  num17 += array[num15];
                                     *  num17 += flag10 ? topGrid[num15].extraDraftedPerceivedPathCost : topGrid[num15].extraNonDraftedPerceivedPathCost;
                                     * }*/
                                    if (!(byteGrid is null))
                                    {
                                        num17 += (int)(byteGrid[num15] * 8);
                                    }
                                    //Allowed area cost?
                                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num13, 0, num14), pawn, false, false, true))
                                    {
                                        num17 += Cost_PawnCollision;
                                    }
                                    Building building2 = this.edificeGrid[num15];
                                    if (!(building2 is null))
                                    {
                                        //Building Costs Here
                                    }
                                    List <Blueprint> list = this.blueprintGrid[num15];
                                    if (!(list is null))
                                    {
                                        this.PfProfilerBeginSample("Blueprints");
                                        int num18 = 0;
                                        foreach (Blueprint bp in list)
                                        {
                                            num18 = Mathf.Max(num18, GetBlueprintCost(bp, pawn));
                                        }
                                        if (num18 == int.MaxValue)
                                        {
                                            this.PfProfilerEndSample();
                                            goto IL_E3A;
                                        }
                                        num17 += num18;
                                        this.PfProfilerEndSample();
                                    }
                                    int    num19  = num17 + this.calcGrid[num].knownCost;
                                    ushort status = this.calcGrid[num15].status;
                                    if (!(pawn.GetComp <CompShips>() is null) && !this.map.terrainGrid.TerrainAt(num15).IsWater)
                                    {
                                        num19 += 10000;
                                    }
                                    if (status == this.statusClosedValue || status == this.statusOpenValue)
                                    {
                                        int num20 = 0;
                                        if (status == this.statusClosedValue)
                                        {
                                            num20 = num9;
                                        }
                                        if (this.calcGrid[num15].knownCost <= num19 + num20)
                                        {
                                            goto IL_E3A;
                                        }
                                    }
                                    if (flag9)
                                    {
                                        this.calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num15) *
                                                                                              ShipPathFinder.RegionheuristicWeighByNodesOpened.Evaluate((float)num4));
                                        if (this.calcGrid[num15].heuristicCost < 0)
                                        {
                                            Log.ErrorOnce(string.Concat(new object[]
                                            {
                                                "Heuristic cost overflow for ship ", pawn.ToStringSafe <Pawn>(),
                                                " pathing from ", start,
                                                " to ", dest, "."
                                            }), pawn.GetHashCode() ^ 193840009, false);
                                            this.calcGrid[num15].heuristicCost = 0;
                                        }
                                    }
                                    else if (status != this.statusClosedValue && status != this.statusOpenValue)
                                    {
                                        int dx    = Math.Abs(num13 - x);
                                        int dz    = Math.Abs(num14 - z);
                                        int num21 = GenMath.OctileDistance(dx, dz, num9, num10);
                                        this.calcGrid[num15].heuristicCost = Mathf.RoundToInt((float)num21 * num8);
                                    }
                                    int num22 = num19 + this.calcGrid[num15].heuristicCost;
                                    //Log.Message("Num19: " + num19 + " || num22: " + num22);
                                    if (num22 < 0)
                                    {
                                        Log.ErrorOnce(string.Concat(new object[]
                                        {
                                            "Node cost overflow for ship ", pawn.ToStringSafe <Pawn>(),
                                            " pathing from ", start,
                                            " to ", dest, "."
                                        }), pawn.GetHashCode() ^ 87865822, false);
                                        num22 = 0;
                                    }
                                    this.calcGrid[num15].parentIndex  = num;
                                    this.calcGrid[num15].knownCost    = num19;
                                    this.calcGrid[num15].status       = this.statusOpenValue;
                                    this.calcGrid[num15].costNodeCost = num22;
                                    num4++;
                                    this.openList.Push(new ShipPathFinder.CostNode(num15, num22));
                                }
                            }
                        }
                        IL_E3A :;
                    }
                    this.PfProfilerEndSample();
                    num3++;
                    this.calcGrid[num].status = this.statusClosedValue;
                    if (num4 >= num5 && flag7 && !flag9)
                    {
                        flag9 = true;
                        this.regionCostCalculator.Init(cellRect, traverseParms, num9, num10, byteGrid, allowedArea, flag10,
                                                       this.disallowedCornerIndices);
                        this.InitStatusesAndPushStartNode(ref num, start);
                        num4 = 0;
                        num3 = 0;
                    }
                }
            }
            string text  = ((pawn is null) || pawn.CurJob is null) ? "null" : pawn.CurJob.ToString();
            string text2 = ((pawn is null) || pawn.Faction is null) ? "null" : pawn.Faction.ToString();

            Log.Warning(string.Concat(new object[]
            {
                "ship pawn: ", pawn, " pathing from ", start,
                " to ", dest, " ran out of cells to process.\nJob:", text,
                "\nFaction: ", text2
            }), false);
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);

Block_32:
            this.PfProfilerEndSample();
            PawnPath result = this.FinalizedPath(num, flag9);

            this.PfProfilerEndSample();
            return(result);

Block_34:
            this.PfProfilerEndSample();
            PawnPath result2 = this.FinalizedPath(num, flag9);

            this.PfProfilerEndSample();
            return(result2);

Block_35:
            Log.Warning(string.Concat(new object[]
            {
                "Ship ", pawn, " pathing from ", start,
                " to ", dest, " hit search limit of ", SearchLimit, " cells."
            }), false);
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);
        }
Пример #19
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                //Empty
            };


            this.EndOnDespawnedOrNull(InquisitorIndex, JobCondition.Incompletable);
            this.EndOnDespawnedOrNull(PreacherIndex, JobCondition.Incompletable);
            //this.EndOnDespawnedOrNull(Build, JobCondition.Incompletable);
            yield return(Toils_Reserve.Reserve(PreacherIndex, this.job.def.joyMaxParticipants));

            Toil gotoPreacher;

            gotoPreacher = Toils_Goto.GotoThing(PreacherIndex, PathEndMode.ClosestTouch);
            yield return(gotoPreacher);

            if (Preacher.jobs.curDriver.asleep)
            {
                Toil watchToil = new Toil();
                watchToil.defaultCompleteMode = ToilCompleteMode.Delay;
                watchToil.defaultDuration     = this.job.def.joyDuration;
                watchToil.AddPreTickAction(() =>
                {
                    this.pawn.rotationTracker.FaceCell(Preacher.Position);
                    this.pawn.GainComfortFromCellIfPossible();
                });
                yield return(watchToil);
            }

            Action hitAction = delegate
            {
                Pawn prey           = Preacher;
                bool surpriseAttack = this.firstHit;
                if (pawn.meleeVerbs.TryMeleeAttack(prey, this.job.verbToUse, surpriseAttack))
                {
                    if (!this.notifiedPlayer && PawnUtility.ShouldSendNotificationAbout(prey))
                    {
                        this.notifiedPlayer = true;
                        if (Prefs.PauseOnUrgentLetter && !Find.TickManager.Paused)
                        {
                            Find.TickManager.TogglePaused();
                        }
                        Messages.Message("MessageAttackedByPredator".Translate(new object[]
                        {
                            prey.LabelShort,
                            this.pawn.LabelShort,
                        }).CapitalizeFirst(), prey, MessageTypeDefOf.ThreatBig);
                    }
                    this.pawn.Map.attackTargetsCache.UpdateTarget(this.pawn);
                }
                this.firstHit = false;
            };

            yield return(Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, hitAction).JumpIfDespawnedOrNull(TargetIndex.A, toil).FailOn(() => Find.TickManager.TicksGame > this.startTick + 5000 && (this.job.GetTarget(TargetIndex.A).Cell - this.pawn.Position).LengthHorizontalSquared > 4f));

            yield return(toil);

            this.AddFinishAction(() =>
            {
                //if (this.TargetB.HasThing)
                //{
                //    Find.Reservations.Release(this.job.targetC.Thing, pawn);
                //}
            });
        }
Пример #20
0
        public virtual void Tick()
        {
            ageTicks++;
            if (def.hediffGivers != null && pawn.IsHashIntervalTick(60))
            {
                for (int i = 0; i < def.hediffGivers.Count; i++)
                {
                    def.hediffGivers[i].OnIntervalPassed(pawn, this);
                }
            }
            if (Visible && !visible)
            {
                visible = true;
                if (def.taleOnVisible != null)
                {
                    TaleRecorder.RecordTale(def.taleOnVisible, pawn, def);
                }
            }
            HediffStage curStage = CurStage;

            if (curStage == null)
            {
                return;
            }
            if (curStage.hediffGivers != null && pawn.IsHashIntervalTick(60))
            {
                for (int j = 0; j < curStage.hediffGivers.Count; j++)
                {
                    curStage.hediffGivers[j].OnIntervalPassed(pawn, this);
                }
            }
            if (curStage.mentalStateGivers != null && pawn.IsHashIntervalTick(60) && !pawn.InMentalState)
            {
                for (int k = 0; k < curStage.mentalStateGivers.Count; k++)
                {
                    MentalStateGiver mentalStateGiver = curStage.mentalStateGivers[k];
                    if (Rand.MTBEventOccurs(mentalStateGiver.mtbDays, 60000f, 60f))
                    {
                        pawn.mindState.mentalStateHandler.TryStartMentalState(mentalStateGiver.mentalState, "MentalStateReason_Hediff".Translate(Label));
                    }
                }
            }
            if (curStage.mentalBreakMtbDays > 0f && pawn.IsHashIntervalTick(60) && !pawn.InMentalState && !pawn.Downed && Rand.MTBEventOccurs(curStage.mentalBreakMtbDays, 60000f, 60f))
            {
                TryDoRandomMentalBreak();
            }
            if (curStage.vomitMtbDays > 0f && pawn.IsHashIntervalTick(600) && Rand.MTBEventOccurs(curStage.vomitMtbDays, 60000f, 600f) && pawn.Spawned && pawn.Awake() && pawn.RaceProps.IsFlesh)
            {
                pawn.jobs.StartJob(JobMaker.MakeJob(JobDefOf.Vomit), JobCondition.InterruptForced, null, resumeCurJobAfterwards: true);
            }
            if (curStage.forgetMemoryThoughtMtbDays > 0f && pawn.needs != null && pawn.needs.mood != null && pawn.IsHashIntervalTick(400) && Rand.MTBEventOccurs(curStage.forgetMemoryThoughtMtbDays, 60000f, 400f) && pawn.needs.mood.thoughts.memories.Memories.TryRandomElement(out Thought_Memory result))
            {
                pawn.needs.mood.thoughts.memories.RemoveMemory(result);
            }
            if (!recordedTale && curStage.tale != null)
            {
                TaleRecorder.RecordTale(curStage.tale, pawn);
                recordedTale = true;
            }
            if (curStage.destroyPart && Part != null && Part != pawn.RaceProps.body.corePart)
            {
                pawn.health.AddHediff(HediffDefOf.MissingBodyPart, Part);
            }
            if (curStage.deathMtbDays > 0f && pawn.IsHashIntervalTick(200) && Rand.MTBEventOccurs(curStage.deathMtbDays, 60000f, 200f))
            {
                bool    num     = PawnUtility.ShouldSendNotificationAbout(pawn);
                Caravan caravan = pawn.GetCaravan();
                pawn.Kill(null, null);
                if (num)
                {
                    pawn.health.NotifyPlayerOfKilled(null, this, caravan);
                }
            }
        }
Пример #21
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            pawn.drafter.Drafted = true;

            IntVec3 cell = pawn.mindState.duty.focus.Cell;

            if (pawn.IsBoat() && !ShipReachabilityUtility.CanReachShip(pawn, cell, PathEndMode.OnCell, PawnUtility.ResolveMaxDanger(pawn, maxDanger), false, TraverseMode.ByPawn))
            {
                return(null);
            }
            else if (!pawn.IsBoat() && pawn is VehiclePawn vehicle && !ReachabilityUtility.CanReach(vehicle, cell, PathEndMode.OnCell, PawnUtility.ResolveMaxDanger(vehicle, maxDanger), false))
            {
                return(null);
            }
            if (exactCell && pawn.Position == cell)
            {
                return(null);
            }

            return(new Job(JobDefOf.Goto, cell)
            {
                locomotionUrgency = PawnUtility.ResolveLocomotion(pawn, locomotionUrgency),
                expiryInterval = jobMaxDuration
            });
        }
        public static IAttackTarget BestAttackTarget(IAttackTargetSearcher searcher, TargetScanFlags flags, Predicate <Thing> validator = null, float minDist = 0f, float maxDist = 9999f, IntVec3 locus = default(IntVec3), float maxTravelRadiusFromLocus = float.MaxValue, bool canBash = false, bool canTakeTargetsCloserThanEffectiveMinRange = true)
        {
            Thing searcherThing = searcher.Thing;
            Pawn  searcherPawn  = searcher as Pawn;
            Verb  verb          = searcher.CurrentEffectiveVerb;

            if (verb == null)
            {
                Log.Error("BestAttackTarget with " + searcher.ToStringSafe() + " who has no attack verb.");
                return(null);
            }
            bool  onlyTargetMachines = verb.IsEMP();
            float minDistSquared     = minDist * minDist;
            float num = maxTravelRadiusFromLocus + verb.verbProps.range;
            float maxLocusDistSquared         = num * num;
            Func <IntVec3, bool> losValidator = null;

            if ((flags & TargetScanFlags.LOSBlockableByGas) != 0)
            {
                losValidator = delegate(IntVec3 vec3)
                {
                    Gas gas = vec3.GetGas(searcherThing.Map);
                    return(gas == null || !gas.def.gas.blockTurretTracking);
                };
            }
            Predicate <IAttackTarget> innerValidator = delegate(IAttackTarget t)
            {
                Thing thing = t.Thing;
                if (t == searcher)
                {
                    return(false);
                }
                if (minDistSquared > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < minDistSquared)
                {
                    return(false);
                }
                if (!canTakeTargetsCloserThanEffectiveMinRange)
                {
                    float num2 = verb.verbProps.EffectiveMinRange(thing, searcherThing);
                    if (num2 > 0f && (float)(searcherThing.Position - thing.Position).LengthHorizontalSquared < num2 * num2)
                    {
                        return(false);
                    }
                }
                if (maxTravelRadiusFromLocus < 9999f && (float)(thing.Position - locus).LengthHorizontalSquared > maxLocusDistSquared)
                {
                    return(false);
                }
                if (!searcherThing.HostileTo(thing))
                {
                    return(false);
                }
                if (validator != null && !validator(thing))
                {
                    return(false);
                }
                if (searcherPawn != null)
                {
                    Lord lord = searcherPawn.GetLord();
                    if (lord != null && !lord.LordJob.ValidateAttackTarget(searcherPawn, thing))
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedNotUnderThickRoof) != 0)
                {
                    RoofDef roof = thing.Position.GetRoof(thing.Map);
                    if (roof != null && roof.isThickRoof)
                    {
                        return(false);
                    }
                }
                if ((flags & TargetScanFlags.NeedLOSToAll) != 0)
                {
                    if (losValidator != null && (!losValidator(searcherThing.Position) || !losValidator(thing.Position)))
                    {
                        return(false);
                    }
                    if (!searcherThing.CanSee(thing, losValidator))
                    {
                        if (t is Pawn)
                        {
                            if ((flags & TargetScanFlags.NeedLOSToPawns) != 0)
                            {
                                return(false);
                            }
                        }
                        else if ((flags & TargetScanFlags.NeedLOSToNonPawns) != 0)
                        {
                            return(false);
                        }
                    }
                }
                if (((flags & TargetScanFlags.NeedThreat) != 0 || (flags & TargetScanFlags.NeedAutoTargetable) != 0) && t.ThreatDisabled(searcher))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedAutoTargetable) != 0 && !IsAutoTargetable(t))
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedActiveThreat) != 0 && !GenHostility.IsActiveThreatTo(t, searcher.Thing.Faction))
                {
                    return(false);
                }
                Pawn pawn = t as Pawn;
                if (onlyTargetMachines && pawn != null && pawn.RaceProps.IsFlesh)
                {
                    return(false);
                }
                if ((flags & TargetScanFlags.NeedNonBurning) != 0 && thing.IsBurning())
                {
                    return(false);
                }
                if (searcherThing.def.race != null && (int)searcherThing.def.race.intelligence >= 2)
                {
                    CompExplosive compExplosive = thing.TryGetComp <CompExplosive>();
                    if (compExplosive != null && compExplosive.wickStarted)
                    {
                        return(false);
                    }
                }
                if (thing.def.size.x == 1 && thing.def.size.z == 1)
                {
                    if (thing.Position.Fogged(thing.Map))
                    {
                        return(false);
                    }
                }
                else
                {
                    bool flag2 = false;
                    foreach (IntVec3 item in thing.OccupiedRect())
                    {
                        if (!item.Fogged(thing.Map))
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        return(false);
                    }
                }
                return(true);
            };

            if (HasRangedAttack(searcher) && (searcherPawn == null || !searcherPawn.InAggroMentalState))
            {
                tmpTargets.Clear();
                tmpTargets.AddRange(searcherThing.Map.attackTargetsCache.GetPotentialTargetsFor(searcher));
                if ((flags & TargetScanFlags.NeedReachable) != 0)
                {
                    Predicate <IAttackTarget> oldValidator2 = innerValidator;
                    innerValidator = (IAttackTarget t) => oldValidator2(t) && CanReach(searcherThing, t.Thing, canBash);
                }
                bool flag = false;
                for (int i = 0; i < tmpTargets.Count; i++)
                {
                    IAttackTarget attackTarget = tmpTargets[i];
                    if (attackTarget.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) && innerValidator(attackTarget) && CanShootAtFromCurrentPosition(attackTarget, searcher, verb))
                    {
                        flag = true;
                        break;
                    }
                }
                IAttackTarget result;
                if (flag)
                {
                    tmpTargets.RemoveAll((IAttackTarget x) => !x.Thing.Position.InHorDistOf(searcherThing.Position, maxDist) || !innerValidator(x));
                    result = GetRandomShootingTargetByScore(tmpTargets, searcher, verb);
                }
                else
                {
                    result = (IAttackTarget)GenClosest.ClosestThing_Global(validator: ((flags & TargetScanFlags.NeedReachableIfCantHitFromMyPos) == 0 || (flags & TargetScanFlags.NeedReachable) != 0) ? ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t))) : ((Predicate <Thing>)((Thing t) => innerValidator((IAttackTarget)t) && (CanReach(searcherThing, t, canBash) || CanShootAtFromCurrentPosition((IAttackTarget)t, searcher, verb)))), center: searcherThing.Position, searchSet: tmpTargets, maxDistance: maxDist);
                }
                tmpTargets.Clear();
                return(result);
            }
            if (searcherPawn != null && searcherPawn.mindState.duty != null && searcherPawn.mindState.duty.radius > 0f && !searcherPawn.InMentalState)
            {
                Predicate <IAttackTarget> oldValidator = innerValidator;
                innerValidator = delegate(IAttackTarget t)
                {
                    if (!oldValidator(t))
                    {
                        return(false);
                    }
                    return(t.Thing.Position.InHorDistOf(searcherPawn.mindState.duty.focus.Cell, searcherPawn.mindState.duty.radius) ? true : false);
                };
            }
            IAttackTarget attackTarget2 = (IAttackTarget)GenClosest.ClosestThingReachable(searcherThing.Position, searcherThing.Map, ThingRequest.ForGroup(ThingRequestGroup.AttackTarget), PathEndMode.Touch, TraverseParms.For(searcherPawn, Danger.Deadly, TraverseMode.ByPawn, canBash), maxDist, (Thing x) => innerValidator((IAttackTarget)x), null, 0, (maxDist > 800f) ? (-1) : 40);

            if (attackTarget2 != null && PawnUtility.ShouldCollideWithPawns(searcherPawn))
            {
                IAttackTarget attackTarget3 = FindBestReachableMeleeTarget(innerValidator, searcherPawn, maxDist, canBash);
                if (attackTarget3 != null)
                {
                    float lengthHorizontal  = (searcherPawn.Position - attackTarget2.Thing.Position).LengthHorizontal;
                    float lengthHorizontal2 = (searcherPawn.Position - attackTarget3.Thing.Position).LengthHorizontal;
                    if (Mathf.Abs(lengthHorizontal - lengthHorizontal2) < 50f)
                    {
                        attackTarget2 = attackTarget3;
                    }
                }
            }
            return(attackTarget2);
        }
Пример #23
0
        public static bool TryFindBestPawnStandCell(Pawn forPawn, out IntVec3 cell, bool cellByCell = false)
        {
            cell = IntVec3.Invalid;
            int   num    = -1;
            float radius = 10f;

            while (true)
            {
                CellFinder.tmpDistances.Clear();
                CellFinder.tmpParents.Clear();
                Dijkstra <IntVec3> .Run(forPawn.Position, (IntVec3 x) => CellFinder.GetAdjacentCardinalCellsForBestStandCell(x, radius, forPawn), delegate(IntVec3 from, IntVec3 to)
                {
                    float num4 = 1f;
                    if (from.x != to.x && from.z != to.z)
                    {
                        num4 = 1.41421354f;
                    }
                    if (!to.Standable(forPawn.Map))
                    {
                        num4 += 3f;
                    }
                    if (PawnUtility.AnyPawnBlockingPathAt(to, forPawn, false, false, false))
                    {
                        bool flag = to.GetThingList(forPawn.Map).Find((Thing x) => x is Pawn && x.HostileTo(forPawn)) != null;
                        if (flag)
                        {
                            num4 += 40f;
                        }
                        else
                        {
                            num4 += 15f;
                        }
                    }
                    Building_Door building_Door = to.GetEdifice(forPawn.Map) as Building_Door;
                    if (building_Door != null && !building_Door.FreePassage)
                    {
                        if (building_Door.PawnCanOpen(forPawn))
                        {
                            num4 += 6f;
                        }
                        else
                        {
                            num4 += 50f;
                        }
                    }
                    return(num4);
                }, CellFinder.tmpDistances, CellFinder.tmpParents);

                if (CellFinder.tmpDistances.Count == num)
                {
                    break;
                }
                float num2 = 0f;
                foreach (KeyValuePair <IntVec3, float> current in CellFinder.tmpDistances)
                {
                    if ((!cell.IsValid || current.Value < num2) && current.Key.Walkable(forPawn.Map) && !PawnUtility.AnyPawnBlockingPathAt(current.Key, forPawn, false, false, false))
                    {
                        Building_Door door = current.Key.GetDoor(forPawn.Map);
                        if (door == null || door.FreePassage)
                        {
                            cell = current.Key;
                            num2 = current.Value;
                        }
                    }
                }
                if (cell.IsValid)
                {
                    goto Block_3;
                }
                if (radius > (float)forPawn.Map.Size.x && radius > (float)forPawn.Map.Size.z)
                {
                    return(false);
                }
                radius *= 2f;
                num     = CellFinder.tmpDistances.Count;
            }
            return(false);

Block_3:
            if (!cellByCell)
            {
                return(true);
            }
            IntVec3 intVec = cell;
            int     num3   = 0;

            while (intVec.IsValid && intVec != forPawn.Position)
            {
                num3++;
                if (num3 >= 10000)
                {
                    Log.Error("Too many iterations.", false);
                    break;
                }
                if (intVec.Walkable(forPawn.Map))
                {
                    Building_Door door2 = intVec.GetDoor(forPawn.Map);
                    if (door2 == null || door2.FreePassage)
                    {
                        cell = intVec;
                    }
                }
                intVec = CellFinder.tmpParents[intVec];
            }
            return(true);
        }
Пример #24
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.interactions.InteractedTooRecentlyToInteract() || lastRomanceTick > Find.TickManager.TicksGame - 1000)
            {
                return(null);
            }
            Predicate <Thing> validator = delegate(Thing t)
            {
                Pawn pawn3 = (Pawn)t;
                return(pawn3 != pawn && pawn3.Spawned && !pawn3.Dead && !pawn3.Downed && pawn3.Awake() && pawn3.IsColonist);
            };
            Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator);

            if (pawn2 == null)
            {
                return(null);
            }
            if (Rand.Chance(0.005f) && new InteractionWorker_RomanceAttempt().SuccessChance(pawn2, pawn) > 0f)
            {
                return(new Job(JobDefOfPsychology.MakeAdvance, pawn2));
            }
            else if (Rand.Value < 0.5f)
            {
                IntVec3 root = WanderUtility.BestCloseWanderRoot(pawn2.PositionHeld, pawn);
                Func <Pawn, IntVec3, IntVec3, bool> wanderDestValidator = delegate(Pawn p, IntVec3 c, IntVec3 wRoot)
                {
                    Room room = root.GetRoom(p.Map, RegionType.Set_Passable);
                    if (room != null && !WanderRoomUtility.IsValidWanderDest(p, c, root))
                    {
                        return(false);
                    }
                    return(true);
                };
                return(new Job(JobDefOf.Goto, RCellFinder.RandomWanderDestFor(pawn, root, 3f, wanderDestValidator, PawnUtility.ResolveMaxDanger(pawn, Danger.Deadly))));
            }
            return(null);
        }
Пример #25
0
        // Token: 0x06000053 RID: 83 RVA: 0x000040E4 File Offset: 0x000022E4
        public void TryHealRandomOldWound()
        {
            var           healAmount = AYProps.RegenHealVal;
            var           candidates = new List <Hediff>();
            var           pawn       = Pawn;
            List <Hediff> list;

            if (pawn == null)
            {
                list = null;
            }
            else
            {
                var health = pawn.health;
                list = health?.hediffSet.hediffs;
            }

            var hediffs = list;

            if (hediffs != null && hediffs.Count > 0)
            {
                foreach (var hediff in hediffs)
                {
                    if (Def.defName == "AYAloeCreamHigh")
                    {
                        if (hediff.def == HediffDefOf.Burn)
                        {
                            candidates.Add(hediff);
                        }
                    }
                    else if (Def.defName == "AYScarCreamHigh")
                    {
                        if (hediff.IsPermanent() || hediff.def == HediffDefOf.Burn)
                        {
                            candidates.Add(hediff);
                        }
                    }
                    else if (hediff.IsPermanent())
                    {
                        candidates.Add(hediff);
                    }
                }
            }

            if (candidates.Count <= 0)
            {
                return;
            }

            candidates.TryRandomElement(out var hediffToHeal);
            if (hediffToHeal == null)
            {
                return;
            }

            if (hediffToHeal.IsTended())
            {
                healAmount = (int)(healAmount * 1.2f);
                var healfactor = GetHealFactor(Def, hediffToHeal);
                if (healfactor > 0f)
                {
                    healAmount = (int)(healAmount * healfactor);
                    if (healAmount < 1)
                    {
                        healAmount = 1;
                    }
                }
            }

            if (hediffToHeal.Severity - healAmount <= 0f && PawnUtility.ShouldSendNotificationAbout(Pawn))
            {
                Messages.Message(
                    "Apothecary.WoundHealed".Translate(parent.LabelCap, Pawn.LabelShort, hediffToHeal.Label,
                                                       Pawn.Named("PAWN")), Pawn, MessageTypeDefOf.PositiveEvent);
            }

            if (hediffToHeal.Severity - healAmount > 0f)
            {
                hediffToHeal.Severity -= healAmount;
                return;
            }

            hediffToHeal.Severity = 0f;
        }
Пример #26
0
        //public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, Pawn pawn, PathEndMode peMode = PathEndMode.OnCell)
        //{
        //    bool flag = false;
        //    if (pawn != null && pawn.CurJob != null && pawn.CurJob.canBash)
        //    {
        //        flag = true;
        //    }
        //    Danger maxDanger = Danger.Deadly;
        //    bool canBash = flag;
        //    return this.FindPath(start, dest, TraverseParms.For(pawn, maxDanger, TraverseMode.ByPawn, canBash), peMode);
        //}

        public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            //Walk through Walls Mode
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }
            //Check if there's a pawn to path for
            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != this.map)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath for pawn which is spawned in another map. His map CVPathFinder should have been used, not this one. pawn=",
                    pawn,
                    " pawn.Map=",
                    pawn.Map,
                    " map=",
                    this.map
                }));
                return(PawnPath.NotFound);
            }
            //Make sure the start is valid
            if (!start.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath with invalid start ",
                    start,
                    ", pawn= ",
                    pawn
                }));
                return(PawnPath.NotFound);
            }
            //Make sure the end is valid
            if (!dest.IsValid)
            {
                Log.Error(string.Concat(new object[]
                {
                    "Tried to FindPath with invalid dest ",
                    dest,
                    ", pawn= ",
                    pawn
                }));
                return(PawnPath.NotFound);
            }
            //Check if it's possible to get to the destination
            Log.Error(traverseParms.mode.ToString());
            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
                {
                    return(PawnPath.NotFound);
                }
            }
            else if (!this.map.reachability.CanReach(start, dest, peMode, traverseParms))
            {
                return(PawnPath.NotFound);
            }
            Log.Error("a");
            this.PfProfilerBeginSample(string.Concat(new object[]
            {
                "FindPath for ",
                pawn,
                " from ",
                start,
                " to ",
                dest,
                (!dest.HasThing) ? string.Empty : (" at " + dest.Cell)
            }));
            this.cellIndices = this.map.cellIndices;
            this.pathGrid    = this.map.pathGrid;
            this.edificeGrid = this.map.edificeGrid.InnerArray;
            int      x        = dest.Cell.x;
            int      z        = dest.Cell.z;
            int      num      = this.cellIndices.CellToIndex(start);
            int      num2     = this.cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid = (pawn == null) ? null : pawn.GetAvoidGrid();
            bool     flag     = traverseParms.mode == TraverseMode.PassAllDestroyableThings;
            bool     flag2    = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3    = !flag;
            CellRect cellRect = this.CalculateDestinationRect(dest, peMode);
            bool     flag4    = cellRect.Width == 1 && cellRect.Height == 1;

            int[]       array       = this.map.pathGrid.pathGrid;
            EdificeGrid edificeGrid = this.map.edificeGrid;
            int         num3        = 0;
            int         num4        = 0;
            Area        allowedArea = this.GetAllowedArea(pawn);
            bool        flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool        flag6       = true && DebugViewSettings.drawPaths;
            bool        flag7       = !flag && start.GetRegion(this.map, RegionType.Set_Passable) != null;
            bool        flag8       = !flag || !flag3;
            bool        flag9       = false;
            int         num5        = 0;
            int         num6        = 0;
            float       num7        = this.DetermineHeuristicStrength(pawn, start, dest);
            int         num8;
            int         num9;

            Log.Error("b");
            if (pawn != null)
            {
                num8 = pawn.TicksPerMoveCardinal;
                num9 = pawn.TicksPerMoveDiagonal;
            }
            else
            {
                num8 = 13;
                num9 = 18;
            }
            this.CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect);
            this.InitStatusesAndPushStartNode(ref num, start);
            while (true)
            {
                Log.Error("c");
                this.PfProfilerBeginSample("Open cell");
                if (this.openList.Count <= 0)
                {
                    break;
                }
                num5 += this.openList.Count;
                num6++;
                CVPathFinder.CostNode costNode = this.openList.Pop();
                num = costNode.index;
                if (costNode.cost != this.calcGrid[num].costNodeCost)
                {
                    Log.Error("d");
                    this.PfProfilerEndSample();
                }
                else if (this.calcGrid[num].status == this.statusClosedValue)
                {
                    Log.Error("e");
                    this.PfProfilerEndSample();
                }
                else
                {
                    Log.Error("f");
                    IntVec3 c  = this.cellIndices.IndexToCell(num);
                    int     x2 = c.x;
                    int     z2 = c.z;
                    if (flag6)
                    {
                        this.DebugFlash(c, (float)this.calcGrid[num].knownCost / 1500f, this.calcGrid[num].knownCost.ToString());
                    }
                    if (flag4)
                    {
                        if (num == num2)
                        {
                            goto Block_27;
                        }
                    }
                    else if (cellRect.Contains(c) && !this.disallowedCornerIndices.Contains(num))
                    {
                        goto Block_29;
                    }
                    if (num3 > 160000)
                    {
                        goto Block_30;
                    }
                    this.PfProfilerEndSample();
                    this.PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        uint num10 = (uint)(x2 + CVPathFinder.Directions[i]);
                        uint num11 = (uint)(z2 + CVPathFinder.Directions[i + 8]);
                        if ((ulong)num10 < (ulong)((long)this.mapSizeX) && (ulong)num11 < (ulong)((long)this.mapSizeZ))
                        {
                            int num12 = (int)num10;
                            int num13 = (int)num11;
                            int num14 = this.cellIndices.CellToIndex(num12, num13);
                            if (this.calcGrid[num14].status != this.statusClosedValue || flag9)
                            {
                                int  num15  = 0;
                                bool flag10 = false;
                                if (flag2 || !new IntVec3(num12, 0, num13).GetTerrain(this.map).HasTag("Water") || (pawn.GetComp <CompVehicle>() != null && pawn.GetComp <CompVehicle>().Props.vehicleType == VehicleType.Amphibious))
                                {
                                    if (!this.pathGrid.WalkableFast(num14))
                                    {
                                        if (!flag)
                                        {
                                            if (flag6)
                                            {
                                                this.DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk");
                                            }
                                            goto IL_C2E;
                                        }
                                        flag10 = true;
                                        num15 += 70;
                                        Building building = edificeGrid[num14];
                                        if (building == null)
                                        {
                                            goto IL_C2E;
                                        }
                                        if (!CVPathFinder.IsDestroyable(building))
                                        {
                                            goto IL_C2E;
                                        }
                                        num15 += (int)((float)building.HitPoints * 0.11f);
                                    }
                                    if (i > 3)
                                    {
                                        switch (i)
                                        {
                                        case 4:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 5:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num + 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 6:
                                            if (this.BlocksDiagonalMovement(num + this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;

                                        case 7:
                                            if (this.BlocksDiagonalMovement(num - this.mapSizeX))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            if (this.BlocksDiagonalMovement(num - 1))
                                            {
                                                if (flag8)
                                                {
                                                    if (flag6)
                                                    {
                                                        this.DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                    }
                                                    goto IL_C2E;
                                                }
                                                num15 += 70;
                                            }
                                            break;
                                        }
                                    }
                                    Log.Error("g");
                                    int num16 = (i <= 3) ? num8 : num9;
                                    num16 += num15;
                                    if (!flag10)
                                    {
                                        num16 += array[num14];
                                    }
                                    if (byteGrid != null)
                                    {
                                        num16 += (int)(byteGrid[num14] * 8);
                                    }
                                    if (allowedArea != null && !allowedArea[num14])
                                    {
                                        num16 += 600;
                                    }
                                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, false, false))
                                    {
                                        num16 += 175;
                                    }
                                    Log.Error("h");
                                    Building building2 = this.edificeGrid[num14];
                                    if (building2 != null)
                                    {
                                        this.PfProfilerBeginSample("Edifices");
                                        int buildingCost = CVPathFinder.GetBuildingCost(building2, traverseParms, pawn);
                                        if (buildingCost == 2147483647)
                                        {
                                            this.PfProfilerEndSample();
                                            goto IL_C2E;
                                        }
                                        num16 += buildingCost;
                                        this.PfProfilerEndSample();
                                    }
                                    int    num17  = num16 + this.calcGrid[num].knownCost;
                                    ushort status = this.calcGrid[num14].status;
                                    if (status == this.statusClosedValue || status == this.statusOpenValue)
                                    {
                                        int num18 = 0;
                                        if (status == this.statusClosedValue)
                                        {
                                            num18 = num8;
                                        }
                                        if (this.calcGrid[num14].knownCost <= num17 + num18)
                                        {
                                            goto IL_C2E;
                                        }
                                    }
                                    if (status != this.statusClosedValue && status != this.statusOpenValue)
                                    {
                                        if (flag9)
                                        {
                                            this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)this.regionCostCalculator.GetPathCostFromDestToRegion(num14) * CVPathFinder.RegionHeuristicWeightByNodesOpened.Evaluate((float)num4));
                                        }
                                        else
                                        {
                                            int dx    = Math.Abs(num12 - x);
                                            int dz    = Math.Abs(num13 - z);
                                            int num19 = GenMath.OctileDistance(dx, dz, num8, num9);
                                            this.calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num19 * num7);
                                        }
                                    }
                                    int num20 = num17 + this.calcGrid[num14].heuristicCost;
                                    this.calcGrid[num14].parentIndex  = num;
                                    this.calcGrid[num14].knownCost    = num17;
                                    this.calcGrid[num14].status       = this.statusOpenValue;
                                    this.calcGrid[num14].costNodeCost = num20;
                                    num4++;
                                    this.openList.Push(new CVPathFinder.CostNode(num14, num20));
                                }
                            }
                        }
                        IL_C2E :;
                    }
                    this.PfProfilerEndSample();
                    num3++;
                    this.calcGrid[num].status = this.statusClosedValue;
                    if (num4 >= 2000 && flag7 && !flag9)
                    {
                        flag9 = true;
                        this.regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, this.disallowedCornerIndices);
                        this.InitStatusesAndPushStartNode(ref num, start);
                        num4 = 0;
                        num3 = 0;
                    }
                }
            }
            string text  = (pawn == null || pawn.CurJob == null) ? "null" : pawn.CurJob.ToString();
            string text2 = (pawn == null || pawn.Faction == null) ? "null" : pawn.Faction.ToString();

            Log.Warning(string.Concat(new object[]
            {
                pawn,
                " pathing from ",
                start,
                " to ",
                dest,
                " ran out of cells to process.\nJob:",
                text,
                "\nFaction: ",
                text2
            }));
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);

Block_27:
            this.PfProfilerEndSample();
            PawnPath result = this.FinalizedPath(num);

            this.PfProfilerEndSample();
            return(result);

Block_29:
            this.PfProfilerEndSample();
            PawnPath result2 = this.FinalizedPath(num);

            this.PfProfilerEndSample();
            return(result2);

Block_30:
            Log.Warning(string.Concat(new object[]
            {
                pawn,
                " pathing from ",
                start,
                " to ",
                dest,
                " hit search limit of ",
                160000,
                " cells."
            }));
            this.DebugDrawRichData();
            this.PfProfilerEndSample();
            return(PawnPath.NotFound);
        }
Пример #27
0
        public static void PawnGroupGenSampled()
        {
            List <DebugMenuOption> list = new List <DebugMenuOption>();

            foreach (Faction faction in Find.FactionManager.AllFactions)
            {
                if (faction.def.pawnGroupMakers != null)
                {
                    if (faction.def.pawnGroupMakers.Any((PawnGroupMaker x) => x.kindDef == PawnGroupKindDefOf.Combat))
                    {
                        Faction localFac = faction;
                        list.Add(new DebugMenuOption(localFac.Name + " (" + localFac.def.defName + ")", DebugMenuOptionMode.Action, delegate()
                        {
                            List <DebugMenuOption> list2 = new List <DebugMenuOption>();
                            foreach (float num in Dialog_DebugActionsMenu.PointsOptions(true))
                            {
                                float localP2     = num;
                                float localP      = localP2;
                                float maxPawnCost = PawnGroupMakerUtility.MaxPawnCost(localFac, localP, null, PawnGroupKindDefOf.Combat);
                                string defName    = (from op in localFac.def.pawnGroupMakers.SelectMany((PawnGroupMaker gm) => gm.options)
                                                     where op.Cost <= maxPawnCost
                                                     select op).MaxBy((PawnGenOption op) => op.Cost).kind.defName;
                                string label = string.Concat(new string[]
                                {
                                    localP.ToString(),
                                    ", max ",
                                    maxPawnCost.ToString("F0"),
                                    " ",
                                    defName
                                });
                                list2.Add(new DebugMenuOption(label, DebugMenuOptionMode.Action, delegate()
                                {
                                    Dictionary <ThingDef, int>[] weaponsCount = new Dictionary <ThingDef, int> [20];
                                    string[] pawnKinds = new string[20];
                                    for (int i = 0; i < 20; i++)
                                    {
                                        weaponsCount[i]   = new Dictionary <ThingDef, int>();
                                        List <Pawn> list3 = PawnGroupMakerUtility.GeneratePawns(new PawnGroupMakerParms
                                        {
                                            groupKind = PawnGroupKindDefOf.Combat,
                                            tile      = Find.CurrentMap.Tile,
                                            points    = localP,
                                            faction   = localFac
                                        }, false).ToList <Pawn>();
                                        pawnKinds[i] = PawnUtility.PawnKindsToCommaList(list3, true);
                                        foreach (Pawn pawn in list3)
                                        {
                                            if (pawn.equipment.Primary != null)
                                            {
                                                if (!weaponsCount[i].ContainsKey(pawn.equipment.Primary.def))
                                                {
                                                    weaponsCount[i].Add(pawn.equipment.Primary.def, 0);
                                                }
                                                Dictionary <ThingDef, int> dictionary;
                                                ThingDef def;
                                                (dictionary = weaponsCount[i])[def = pawn.equipment.Primary.def] = dictionary[def] + 1;
                                            }
                                            pawn.Destroy(DestroyMode.Vanish);
                                        }
                                    }
                                    int totalPawns = weaponsCount.Sum((Dictionary <ThingDef, int> x) => x.Sum((KeyValuePair <ThingDef, int> y) => y.Value));
                                    List <TableDataGetter <int> > list4 = new List <TableDataGetter <int> >();
                                    list4.Add(new TableDataGetter <int>(string.Empty, (int x) => (x != 20) ? (x + 1).ToString() : "avg"));
                                    list4.Add(new TableDataGetter <int>("pawns", delegate(int x)
                                    {
                                        string str = " ";
                                        string str2;
                                        if (x == 20)
                                        {
                                            str2 = ((float)totalPawns / 20f).ToString("0.#");
                                        }
                                        else
                                        {
                                            str2 = weaponsCount[x].Sum((KeyValuePair <ThingDef, int> y) => y.Value).ToString();
                                        }
                                        return(str + str2);
                                    }));
                                    list4.Add(new TableDataGetter <int>("kinds", (int x) => (x != 20) ? pawnKinds[x] : string.Empty));
                                    list4.AddRange(from x in DefDatabase <ThingDef> .AllDefs
                                                   where x.IsWeapon && !x.weaponTags.NullOrEmpty <string>() && weaponsCount.Any((Dictionary <ThingDef, int> wc) => wc.ContainsKey(x))
                                                   orderby x.IsMeleeWeapon descending, x.techLevel, x.BaseMarketValue
                                                   select new TableDataGetter <int>(x.label.Shorten(), delegate(int y)
                                    {
                                        if (y == 20)
                                        {
                                            return(" " + ((float)weaponsCount.Sum((Dictionary <ThingDef, int> z) => (!z.ContainsKey(x)) ? 0 : z[x]) / 20f).ToString("0.#"));
                                        }
                                        string result;
                                        if (weaponsCount[y].ContainsKey(x))
                                        {
                                            object[] array = new object[5];
                                            array[0]       = " ";
                                            array[1]       = weaponsCount[y][x];
                                            array[2]       = " (";
                                            array[3]       = ((float)weaponsCount[y][x] / (float)weaponsCount[y].Sum((KeyValuePair <ThingDef, int> z) => z.Value)).ToStringPercent("F0");
                                            array[4]       = ")";
                                            result         = string.Concat(array);
                                        }
                                        else
                                        {
                                            result = string.Empty;
                                        }
                                        return(result);
                                    }));
                                    DebugTables.MakeTablesDialog <int>(Enumerable.Range(0, 21), list4.ToArray());
                                }));
                            }
                            Find.WindowStack.Add(new Dialog_DebugOptionListLister(list2));
                        }));
                    }
                }
            }
            Find.WindowStack.Add(new Dialog_DebugOptionListLister(list));
        }
Пример #28
0
        public void HealthTick()
        {
            if (this.Dead)
            {
                return;
            }
            for (int i = this.hediffSet.hediffs.Count - 1; i >= 0; i--)
            {
                Hediff hediff = this.hediffSet.hediffs[i];
                hediff.Tick();
                hediff.PostTick();
            }
            bool flag = false;

            for (int j = this.hediffSet.hediffs.Count - 1; j >= 0; j--)
            {
                Hediff hediff2 = this.hediffSet.hediffs[j];
                if (hediff2.ShouldRemove)
                {
                    this.hediffSet.hediffs.RemoveAt(j);
                    hediff2.PostRemoved();
                    flag = true;
                }
            }
            if (flag)
            {
                this.Notify_HediffChanged(null);
            }
            if (this.Dead)
            {
                return;
            }
            this.immunity.ImmunityHandlerTick();
            if (this.pawn.RaceProps.IsFlesh && this.pawn.IsHashIntervalTick(600) && (this.pawn.needs.food == null || !this.pawn.needs.food.Starving))
            {
                bool flag2 = false;
                if (this.hediffSet.HasNaturallyHealingInjury())
                {
                    float num = 8f;
                    if (this.pawn.GetPosture() != PawnPosture.Standing)
                    {
                        num += 4f;
                        Building_Bed building_Bed = this.pawn.CurrentBed();
                        if (building_Bed != null)
                        {
                            num += building_Bed.def.building.bed_healPerDay;
                        }
                    }
                    Hediff_Injury hediff_Injury = this.hediffSet.GetHediffs <Hediff_Injury>().Where(new Func <Hediff_Injury, bool>(HediffUtility.CanHealNaturally)).RandomElement <Hediff_Injury>();
                    hediff_Injury.Heal(num * this.pawn.HealthScale * 0.01f);
                    flag2 = true;
                }
                if (this.hediffSet.HasTendedAndHealingInjury() && (this.pawn.needs.food == null || !this.pawn.needs.food.Starving))
                {
                    Hediff_Injury hediff_Injury2 = this.hediffSet.GetHediffs <Hediff_Injury>().Where(new Func <Hediff_Injury, bool>(HediffUtility.CanHealFromTending)).RandomElement <Hediff_Injury>();
                    float         tendQuality    = hediff_Injury2.TryGetComp <HediffComp_TendDuration>().tendQuality;
                    float         num2           = GenMath.LerpDouble(0f, 1f, 0.5f, 1.5f, Mathf.Clamp01(tendQuality));
                    hediff_Injury2.Heal(22f * num2 * this.pawn.HealthScale * 0.01f);
                    flag2 = true;
                }
                if (flag2 && !this.HasHediffsNeedingTendByColony(false) && !HealthAIUtility.ShouldSeekMedicalRest(this.pawn) && !this.hediffSet.HasTendedAndHealingInjury() && PawnUtility.ShouldSendNotificationAbout(this.pawn))
                {
                    Messages.Message("MessageFullyHealed".Translate(new object[]
                    {
                        this.pawn.LabelCap
                    }), this.pawn, MessageTypeDefOf.PositiveEvent);
                }
            }
            if (this.pawn.RaceProps.IsFlesh && this.hediffSet.BleedRateTotal >= 0.1f)
            {
                float num3 = this.hediffSet.BleedRateTotal * this.pawn.BodySize;
                if (this.pawn.GetPosture() == PawnPosture.Standing)
                {
                    num3 *= 0.008f;
                }
                else
                {
                    num3 *= 0.0008f;
                }
                if (Rand.Value < num3)
                {
                    this.TryDropBloodFilth();
                }
            }
            List <HediffGiverSetDef> hediffGiverSets = this.pawn.RaceProps.hediffGiverSets;

            if (hediffGiverSets != null && this.pawn.IsHashIntervalTick(60))
            {
                for (int k = 0; k < hediffGiverSets.Count; k++)
                {
                    List <HediffGiver> hediffGivers = hediffGiverSets[k].hediffGivers;
                    for (int l = 0; l < hediffGivers.Count; l++)
                    {
                        hediffGivers[l].OnIntervalPassed(this.pawn, null);
                        if (this.pawn.Dead)
                        {
                            return;
                        }
                    }
                }
            }
        }
Пример #29
0
        protected virtual IntVec3 GetExactWanderDest(Pawn pawn)
        {
            IntVec3 wanderRoot = pawn.PositionHeld;

            return(RCellFinder.RandomWanderDestFor(pawn, wanderRoot, this.wanderRadius, delegate(Pawn p, IntVec3 v) { if (v.Roofed(p.MapHeld))
                                                                                                                      {
                                                                                                                          return true;
                                                                                                                      }
                                                                                                                      return false; }, PawnUtility.ResolveMaxDanger(pawn, this.maxDanger)));
        }
Пример #30
0
        /// <summary>
        /// Manual finalizer for WorldPawnCleaner.GC().
        /// Deconstruct all animal families on map and discard the redundant members.
        /// </summary>
        /// <returns>The count of discarded members.</returns>
        public static int DeconstructAnimalFamily()
        {
            List <Pawn> worldpawns = new List <Pawn>();

            foreach (Pawn p in Find.WorldPawns.AllPawnsAliveOrDead)
            {
                worldpawns.Add(p);
            }

            List <Pawn> queue    = new List <Pawn>();
            List <Pawn> pawnlist = new List <Pawn>();

            foreach (Map map in Find.Maps)
            {
                foreach (Pawn p in map.mapPawns.AllPawns)
                {
                    if ((p.records.GetAsInt(RecordDefOf.TimeAsColonistOrColonyAnimal) > 0) && !(p.RaceProps.Humanlike))
                    {
                        pawnlist.Add(p);
                    }
                }
            }

            foreach (Pawn p in pawnlist)
            {
                //Patch:null relationship on robots.
                if (p.relations != null)
                {
                    foreach (Pawn p2 in expandRelation(p))
                    {
                        if (worldpawns.Contains(p2) && (!p2.Spawned) && (!p2.IsPlayerControlledCaravanMember()) && (!PawnUtility.IsTravelingInTransportPodWorldObject(p2))
                            //Patch:Corpses remained on maps.
                            && (p.Corpse == null)
                            )
                        {
                            queue.Add(p2);
                            worldpawns.Remove(p2);
                        }
                    }
                }
            }


            //Patch:2nd Pawn of a used Tale_DoublePawn will raise Scribe Warnings if discarded
            List <Pawn> allUsedTaleOwner;

            CleanserUtil.InitUsedTalePawns(out allUsedTaleOwner);
            foreach (Pawn pawn in allUsedTaleOwner)
            {
                queue.Remove(pawn);
            }

            int a = queue.Count;

            foreach (Pawn pawn in queue)
            {
                Find.WorldPawns.RemovePawn(pawn);
                if (!pawn.Destroyed)
                {
                    pawn.Destroy(DestroyMode.Vanish);
                }
                if (!pawn.Discarded)
                {
                    pawn.Discard(true);
                }
            }

            Find.WindowStack.WindowOfType <UserInterface>().Notify_PawnsCountDirty();
            return(a);
        }