public static InjurySeverity GetTendSeverity(this Pawn patient)
        {
            if (!HealthAIUtility.ShouldBeTendedNow(patient))
            {
                return(InjurySeverity.Minor);
            }

            var hediffs = patient.health.hediffSet.hediffs;
            var ticksToDeathDueToBloodLoss = HealthUtility.TicksUntilDeathDueToBloodLoss(patient);

            // going to die in <6 hours, or any tendable is life threathening
            if (ticksToDeathDueToBloodLoss <= GenDate.TicksPerHour * 6 || hediffs.Any(h => h.CurStage?.lifeThreatening ?? false))
            {
                return(InjurySeverity.LifeThreathening);
            }

            // going to die in <12 hours, or any immunity < severity and can be fatal
            if (ticksToDeathDueToBloodLoss <= GenDate.TicksPerHour * 12 ||
                hediffs.Any(PotentiallyLethalDisease))
            {
                return(InjurySeverity.Major);
            }

            // otherwise
            return(InjurySeverity.Minor);
        }
Exemple #2
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            Log.Message(pawn + " JobGiver_StockUp");
            if (pawn.StockUpIsFull())
            {
                return(null);
            }

            Log.Message("Skip need tend?");
            if (pawn.Map.mapPawns.AllPawnsSpawned.Any(p => HealthAIUtility.ShouldBeTendedNow(p) && pawn.CanReserveAndReach(p, PathEndMode.ClosestTouch, Danger.Deadly)))
            {
                return(null);
            }

            Log.Message("any things?");
            IEnumerable <Thing> things    = pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableEver);
            Predicate <Thing>   validator = (Thing t) => pawn.StockingUpOn(t) && pawn.StockUpNeeds(t) > 0 && pawn.CanReserve(t, FindBestMedicine.maxPawns, 1) && !t.IsForbidden(pawn);
            Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999, validator);

            if (thing != null)
            {
                int pickupCount = Math.Min(pawn.StockUpNeeds(thing), MassUtility.CountToPickUpUntilOverEncumbered(pawn, thing));
                Log.Message(pawn + " stock thing is " + thing + ", count " + pickupCount);
                if (pickupCount > 0)
                {
                    return new Job(SmartMedicineJobDefOf.StockUp, thing)
                           {
                               count = pickupCount
                           }
                }
                ;
            }

            Log.Message(pawn + " looking to return");
            Thing toReturn = pawn.StockUpThingToReturn();

            if (toReturn == null)
            {
                return(null);
            }
            Log.Message("returning " + toReturn);

            int dropCount = -pawn.StockUpNeeds(toReturn);

            Log.Message("dropping " + dropCount);
            if (StoreUtility.TryFindBestBetterStoreCellFor(toReturn, pawn, pawn.Map, StoragePriority.Unstored, pawn.Faction, out IntVec3 dropLoc, true))
            {
                return new Job(SmartMedicineJobDefOf.StockDown, toReturn, dropLoc)
                       {
                           count = dropCount
                       }
            }
            ;
            Log.Message("nowhere to store");
            return(null);
        }
    }
}
        public override void Tick()
        {
            base.Tick();
            if (OwnerPawn != null && OwnerPawn.Position != this.InteractionCell)
            {
                OwnerPawn = null;
                count     = 0;
                foundInj  = null;
                oldCount  = 0;
            }
            if (JobPawn != null)
            {
                if (OwnerPawn != null)
                {
                    string messageText1;
                    messageText1 = "Dermal Regenerator in use.";
                    Messages.Message(messageText1, MessageSound.Benefit);
                    JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    JobPawn = null;
                    return;
                }
                else
                {
                    if (this.UsableNow)
                    {
                        if (JobPawn.Position == this.InteractionCell)
                        {
                            OwnerPawn = JobPawn;
                            JobPawn   = null;
                            return;
                        }
                    }
                    else if (OwnerPawn == null && !this.UsableNow)
                    {
                        string messageText2;
                        messageText2 = "Dermal Regenerator doesnt have power.";
                        Messages.Message(messageText2, MessageSound.Benefit);
                        JobPawn.jobs.jobQueue.Clear();
                        JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        JobPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        JobPawn = null;
                        return;
                    }
                }
            }
            if (OwnerPawn != null && !this.UsableNow)
            {
                string messageText3;
                messageText3 = "Dermal Regenerator power interupted.";
                Messages.Message(messageText3, MessageSound.Benefit);
                OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                OwnerPawn.health.AddHediff(HediffDef.Named("DermalRegeneratorSickness"), null, null);
                OwnerPawn = null;
                count     = 0;
                foundInj  = null;
                oldCount  = 0;
                return;
            }
            if (OwnerPawn != null && OwnerPawn.Position == this.InteractionCell && this.UsableNow)
            {
                Map.glowGrid.VisualGlowAt(Position);
                if (count < 4500)
                {
                    if (count % 90 == 0)
                    {
                        ThrowMicroSparksBlue(Position.ToVector3(), Map);
                    }
                    if (count % 200 == 0)
                    {
                        ThrowLightningGlowBlue(Position.ToVector3(), Map, 1f);
                    }
                }
                else if (count > 4500)
                {
                    if (count % 90 == 0)
                    {
                        ThrowMicroSparksGreen(Position.ToVector3(), Map);
                    }
                    if (count % 200 == 0)
                    {
                        ThrowLightningGlowGreen(Position.ToVector3(), Map, 1f);
                    }
                }

                count++;

                foreach (Hediff current in OwnerPawn.health.hediffSet.GetHediffs <Hediff>())
                {
                    if (current is Hediff_Injury && current.IsOld() && (current.Label.Contains("scar") || current.Label.Contains("Scar")))
                    {
                        oldCount++;
                        foundInj = current;
                    }
                }

                if (count >= 9000)
                {
                    OwnerPawn.health.hediffSet.hediffs.Remove(foundInj);
                    OwnerPawn.health.Notify_HediffChanged(foundInj);
                    foundInj = null;
                    if (!HealthAIUtility.ShouldBeTendedNow(OwnerPawn))
                    {
                        string messageText4;
                        messageText4 = "Treatment complete.";
                        Messages.Message(messageText4, MessageSound.Benefit);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.health.AddHediff(HediffDef.Named("DermalRegeneratorSickness"), null, null);
                        count     = 0;
                        foundInj  = null;
                        oldCount  = 0;
                        OwnerPawn = null;
                    }
                }

                if (count == 4500)
                {
                    if (foundInj == null)
                    {
                        string messageText5;
                        messageText5 = "No surface injuries discovered.";
                        Messages.Message(messageText5, MessageSound.Benefit);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                        OwnerPawn.health.AddHediff(HediffDef.Named("DermalRegeneratorSickness"), null, null);
                        OwnerPawn = null;
                        count     = 0;
                        foundInj  = null;
                        oldCount  = 0;
                        return;
                    }
                }
            }
        }
Exemple #4
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Reserve the takee
            yield return(Toils_Reserve.Reserve(TargetIndex.A, 1));

            //Reserve the bed
            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1));

            //Claim the bed for the takee
            Toil claimBed = new Toil();

            claimBed.initAction = () =>
            {
                if (Takee.ownership != null && Takee.ownership.OwnedBed != DropBed && !DropBed.Medical)
                {
                    Takee.ownership.ClaimBedIfNonMedical((Building_Bed)DropBed);
                }
            };
            yield return(claimBed);

            Func <bool> ownershipFail = () =>
            {
                if (DropBed.Medical)
                {
                    if (DropBed.AnyUnownedSleepingSlot &&
                        DropBed.CurOccupants != Takee)
                    {
                        return(true);
                    }
                }
                else if (DropBed.owners != null && !DropBed.owners.Contains(Takee))
                {
                    return(true);
                }
                return(false);
            };

            //Goto takee
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch)
                         .FailOnDestroyedNullOrForbidden(TargetIndex.A)
                         .FailOnDestroyedNullOrForbidden(TargetIndex.B)
                         .FailOn(ownershipFail)                                                              //Abandon if takee loses bed ownership
                         .FailOn(() => this.job.def == JobDefOf.Arrest && !Takee.CanBeArrestedBy(this.pawn)) //Abandon arrest if takee is not of a team who is willing to be arrested
                         .FailOn(() => !pawn.CanReach(DropBed, PathEndMode.OnCell, Danger.Deadly)));

            //.FailOn(()=>!pawn.CanReach( DropBed, PathEndMode.OnCell, Danger.Deadly ) ); // From Alpha 8

            //Make unconscious if needed
            Toil makeUnconscious = new Toil();

            makeUnconscious.initAction = () =>
            {
                //Log.Error("Applying Anesthetic");
                //Takee.healthTracker.ApplyAnesthetic(); Does not work with AIPawn

                Takee.health.forceIncap = true;
                Takee.health.AddHediff(HediffDefOf.Anesthetic, null, null);
                Takee.health.forceIncap = false;
            };
            yield return(makeUnconscious);

            //Start carrying the takee
            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

            //Change takee to prisoner if necessary
            Toil makePrisoner = new Toil();

            makePrisoner.initAction = () =>
            {
                if (this.job.def == JobDefOf.Arrest || this.job.def == JobDefOf.Capture || this.job.def == JobDefOf.TakeWoundedPrisonerToBed)
                {
                    if (Takee.HostFaction != Faction.OfPlayer)
                    {
                        Takee.guest.SetGuestStatus(Faction.OfPlayer, true);
                    }
                }
            };
            yield return(makePrisoner);

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch)
                         .FailOnDestroyedNullOrForbidden(TargetIndex.A));

            //Note no failure conditions here
            //Because otherwise it's easy to get wardens to drop prisoners in arbitrary places.
            //I'd rather they just go to wherever they were going.
            // if( DropBed.owner != Takee )
            //	return true;
            //return !Toils.CanInteractStandard(DropBed);


            //Unreserve bed so takee can use it
            yield return(Toils_Reserve.Release(TargetIndex.B));


            //Drop in or near bed
            Toil tuckIntoBed = new Toil();

            tuckIntoBed.initAction = () =>
            {
                //Note: We don't stop the task if the bed is destroyed or changes ownership
                //because then the wardens drop prisoners at random points and they escape
                //So we have to handle some ugly cases here

                //note this may use the position of a destroyed bed
                IntVec3 dropPos = DropBed.Position;

                Thing unused;
                pawn.carryTracker.TryDropCarriedThing(dropPos, ThingPlaceMode.Direct, out unused);

                //Should we tuck them into bed?
                if ((Takee.Downed || Takee.health.HasHediffsNeedingTend(false) || ((HealthAIUtility.ShouldSeekMedicalRest(Takee) || HealthAIUtility.ShouldBeTendedNow(Takee)) && DropBed.Medical)) &&
                    !DropBed.Destroyed &&
                    (DropBed.owners.Contains(Takee) || (DropBed.Medical && DropBed.AnyUnoccupiedSleepingSlot))      //They could have lost ownership and the last toil would continue
                    )
                {
                    Takee.jobs.Notify_TuckedIntoBed(DropBed);
                }

                if (Takee.IsPrisonerOfColony)
                {
                    LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, Takee, OpportunityType.GoodToKnow);
                }
            };
            tuckIntoBed.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return(tuckIntoBed);
        }