public override IEnumerable <FloatMenuOption> GetFloatMenuOptions(Pawn myPawn)
        {
            //// No base float menu options allowed!
            //foreach (FloatMenuOption fmo in base.GetFloatMenuOptionsFor(myPawn))
            //{
            //    yield return fmo;
            //}

            // No self medication!
            if (myPawn == this)
            {
                yield break;
            }

            // Sedate AIPawn
            Action action_OrderSedateMai = delegate
            {
                myPawn.drafter.Drafted = false;

                Job jobNew = new Job(DefDatabase <JobDef> .GetNamed("AIPawn_Sedate"), this)
                {
                    count = 1
                };
                myPawn.jobs.TryTakeOrderedJob(jobNew);
            };

            yield return(new FloatMenuOption(txtFloatMenuSedateAIPawn.Translate(this.Label), action_OrderSedateMai));


            // Sedate and Carry AIPawn to recharge station
            Building_AIPawnRechargeStation rechargeStation;

            rechargeStation = HelperAIPawn.FindMedicalRechargeStationFor(this);
            if (rechargeStation == null)
            {
                rechargeStation = HelperAIPawn.FindRechargeStationFor(this);
            }

            Action action_OrderSedateAndCarryMai = delegate
            {
                myPawn.drafter.Drafted = false;

                Job jobNew = new Job(DefDatabase <JobDef> .GetNamed("AIPawn_SedateAndRescue"), this, rechargeStation)
                {
                    count = 1
                };
                myPawn.jobs.TryTakeOrderedJob(jobNew);
            };

            if (rechargeStation != null)
            {
                yield return(new FloatMenuOption(txtFloatMenuSedateAndRescueAIPawn.Translate(this.Label), action_OrderSedateAndCarryMai));
            }
            else
            {
                yield return(new FloatMenuOption(txtFloatMenuSedateAndRescueAIPawn.Translate(this.Label), null));
            }

            yield break;
        }
Beispiel #2
0
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (Find.TickManager.TicksGame - pawn.mindState.lastDisturbanceTick < 400)
            {
                return(null);
            }

            AIPawn aiPawn = pawn as AIPawn;
            Building_AIPawnRechargeStation rechargeStation = HelperAIPawn.FindRechargeStationFor(aiPawn);

            if (rechargeStation == null)
            {
                return(null);
            }

            if (rechargeStation.owners != null && !rechargeStation.owners.Contains(aiPawn) && !rechargeStation.Medical)
            {
                aiPawn.ownership.ClaimBedIfNonMedical(rechargeStation);
            }

            if (aiPawn.ownership.OwnedBed == null || aiPawn.ownership.OwnedBed != rechargeStation)
            {
                return(null);
            }

            Job job = new Job(JobDefOf.LayDown, rechargeStation);

            return(job);
        }
        private void TryGoRecharging()
        {
            // Drafting active, do nothing
            if (this.Drafted || !this.Spawned)
            {
                return;
            }

            // No recharge station, do nothing
            if (this.ownership.OwnedBed == null)
            {
                Building_AIPawnRechargeStation rs = HelperAIPawn.FindRechargeStationFor(this);
                if (rs == null)
                {
                    return;
                }

                this.ownership.ClaimBedIfNonMedical(rs);
                //rs.TryAssignPawn(this); OLD

                if (this.ownership.OwnedBed == null)
                {
                    return;
                }
            }

            Building_AIPawnRechargeStation rechargeStation = this.ownership.OwnedBed as Building_AIPawnRechargeStation;

            if (rechargeStation == null)
            {
                return;
            }

            if (rechargeStation.Position == this.Position)
            {
                return;
            }

            rechargeStation.Button_CallOwnerToRecharge();
        }
        // ================== Ticks ==================

        public override void Tick()
        {
            base.Tick();

            // Do init work after spawning
            if (!init)
            {
                HelperAIPawn.ReApplyThingToListerThings(this.Position, this);

                Drawer.renderer.graphics.ResolveAllGraphics(); //Causes errors!
                UpdateGraphics();

                initTicks--;
                if (initTicks <= 0)
                {
                    // Replace invalid Mai with valid Mai
                    if (!story.childhood.identifier.Contains(BackstoryHelper.BackstoryDefNameIdentifier))
                    {
                        string  savedDefName  = def.defName;
                        IntVec3 savedPosition = Position;
                        Map     savedMap      = Map;
                        Gender  savedGender   = this.gender;

                        // Destroy me
                        destroyMeWithoutExplosion = true;
                        Destroy(DestroyMode.Vanish);

                        // Create a new me
                        AIPawn mai = Building_AIPawnCreator.CreateAIPawn(savedDefName, savedPosition, savedMap, savedGender);

                        return;
                    }

                    BackstoryHelper.RemoveNewBackstoriesFromDatabase();
                    init = true;
                }
                return;
            }

            //// To circumvent the strange pathing error!
            //if ((this.CurJob == null || this.CurJob != curJobOld) && Map != null)
            //{
            //    HelperAIPawn.ReApplyThingToListerThings(this.Position, this);
            //    curJobOld = this.CurJob;
            //}

            // To circumvent the destroy apparel error
            if (this.CurJob != null && this.CurJob.def.defName == "Wear" && this.CurJob.targetA.Cell == this.Position)
            {
                AIPawnGenerator.DestroyBaseShielding(this);
            }

            // Update drafted graphics
            if (draftedActiveOld != this.Drafted)
            {
                UpdateGraphics();
                draftedActiveOld = this.Drafted;
            }

            // When AIPawn is in a Container, do nothing
            if (this.InContainerEnclosed)
            {
                return;
            }

            // When AIPawn is in a bed, fix rest value to prevent explosions in the hospital room
            if (Find.TickManager.TicksGame % fixRestWhenInBedCounter == 0)
            {
                Building_AIPawnRechargeStation rechargeStation;
                if (this.InBed() && !this.IsInAIRechargeStation(Map, out rechargeStation))
                {
                    needs.rest.CurLevel = fixRestWhenInBedFixedValue;
                }
                else
                {
                    fixRestWhenInBedFixedValue = needs.rest.CurLevel;
                }
            }

            // Disable food reduction <-- Food is needed or some errors are thrown
            if (needs != null && needs.food != null && needs.food.CurLevel <= 0.95f)
            {
                needs.food.CurLevel = 1.0f;
            }

            //// Disable joy reduction
            //if (needs != null && needs.joy != null && needs.joy.CurLevel <= 0.95f)
            //    needs.joy.CurLevel = 1.0f;

            //// Disable beauty reduction
            //if (needs != null && needs.beauty != null && needs.beauty.CurLevel <= 0.95f)
            //    needs.beauty.CurLevel = 1.0f;

            //// Disable comfort reduction
            //if (needs != null && needs.comfort != null && needs.comfort.CurLevel <= 0.95f)
            //    needs.comfort.CurLevel = 1.0f;

            //// Disable rest reduction when traveling in a caravan!
            //if (needs != null && needs.rest != null && needs.rest.CurLevel <= 0.95f && !Destroyed && !Downed && Map == null)
            //    needs.rest.CurLevel += 0.01f / 60f;

            // If in bed, slowly increase rest (to circumvent bed problems)
            if (IsInBed(Map))
            {
                needs.rest.CurLevel += 0.025f / 60f;
            }

            // Self healing ability (Nanobots)
            healDamagedPartsCounter -= 1;
            if (healDamagedPartsCounter <= 0)
            {
                DoHealDamagedBodyPart(enhancedAI);
                healDamagedPartsCounter = healDamagedPartsCounterStartValue;
            }

            refreshQuickCount += 1;
            if (refreshQuickCount >= refreshQuickMax)
            {
                refreshQuickCount = 0;
            }

            if (refreshQuickCount == 0)
            {
                // Add thought when health < x
                if (this.health.summaryHealth.SummaryHealthPercent < 0.75)
                {
                    this.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("AIShieldingError"));
                }

                // disable diseases
                DoDiseaseHandling();

                if (Destroyed)
                {
                    destroyMeWithoutExplosion = true;
                    Destroy(DestroyMode.Vanish);
                    return;
                }

                // Do explosion when downed, dead or incapable of moving
                if (Dead || (!isAnestheticIncap && !IsInBed(Map) && (Downed || health.capacities.GetLevel(PawnCapacityDefOf.Moving) < 0.1f)))
                {
                    incapToExplosionCounter -= refreshQuickMax;
                    if (incapToExplosionCounter <= 0)
                    {
                        Destroy(DestroyMode.KillFinalize);
                        return;
                    }
                }

                // Reset counter when health is rising -- Not working right now
                if ((Downed && this.health.summaryHealth.SummaryHealthPercent > incapHealthOld) || !Downed && (incapToExplosionCounter < incapToExplosionCounterStartValue))
                {
                    incapToExplosionCounter = incapToExplosionCounterStartValue;
                }

                incapHealthOld = this.health.summaryHealth.SummaryHealthPercent;

                //// Add thought when rested
                //if (rest.Rest.CurLevel >= 98.9f)
                //    psychology.thoughts.memories.TryGainMemoryThought(ThoughtDef.Named("AIBatteriesRefilled"));

                // Change color when near exhausted
                float levelLowBatterie         = 0.25f;
                float levelLowCriticalBatterie = 0.15f;
                if (needs.rest.CurLevel <= levelLowCriticalBatterie && !graphicHueActive)
                {
                    // Switch to alternate graphic
                    graphicHueActive = true;
                    UpdateGraphics();
                }
                else if (needs.rest.CurLevel > levelLowCriticalBatterie && graphicHueActive)
                {
                    // Switch back to normal graphic
                    graphicHueActive = false;
                    UpdateGraphics();
                }

                // Add thought when rest(batteries) < x
                if (needs.rest.CurLevel < levelLowCriticalBatterie)
                {
                    needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("AILowCriticalBattery"));
                }
                // Add thought when rest(batteries) < x
                else if (needs.rest.CurLevel < levelLowBatterie)
                {
                    needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("AILowBattery"));
                }

                // Explosion when exhausted
                if (needs.rest.CurLevel <= 0.011f)
                {
                    if (!Downed)
                    {
                        HealthUtility.DamageUntilDowned(this, false);
                    }
                }
                else if (needs.rest.CurLevel < 0.2f)
                {
                    TryGoRecharging();
                }

                // unclaim bed when fully rested // Activate? Don't Activate?
                //if (ownership != null && (rest.Rest.CurLevel >= 94.8f || rest.DoneResting))
                //    ownership.UnclaimBed();
            }

            // Update base AI thought every x
            refreshBaseInfosCount += 1;
            if (refreshBaseInfosCount >= refreshBaseInfosMax || refreshBaseInfosCount < 0)
            {
                refreshBaseInfosCount            = 0;
                this.mindState.canFleeIndividual = false;

                DoRelationHandling();

                //Base thought is only available after save/load (why?) so it needs to be set
                this.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("AIBaseThought"));

                // Rebuild Base Shielding if needed
                Building_AIPawnRechargeStation rs2;
                AIPawnGenerator.GiveBaseApparelWhileInBed(this, IsInAIRechargeStation(Map, out rs2));
            }
        }
Beispiel #5
0
        private static IEnumerable <Backstory> NewBackstories()
        {
            if (backstories == null)
            {
                Backstory backstory;

                backstories = new List <Backstory>();
                string   txtBaseDesc   = "----------";
                string   txtTitle      = "---";
                string   txtTitleShort = "AI";
                BodyType bodyType      = BodyType.Female;

                if (workTagCollection == null)
                {
                    // Set a list with the possible disabled items
                    workTagCollection = new List <WorkTags>();
                    workTagCollection.Add(WorkTags.Animals);
                    //workTagCollection.Add(WorkTags.Artistic); //- In BasicWorkDisables
                    workTagCollection.Add(WorkTags.Caring);
                    workTagCollection.Add(WorkTags.Cleaning);
                    workTagCollection.Add(WorkTags.Cooking);
                    workTagCollection.Add(WorkTags.Crafting);
                    workTagCollection.Add(WorkTags.Firefighting);
                    workTagCollection.Add(WorkTags.Hauling);
                    workTagCollection.Add(WorkTags.Intellectual);
                    workTagCollection.Add(WorkTags.ManualDumb);
                    workTagCollection.Add(WorkTags.ManualSkilled);
                    workTagCollection.Add(WorkTags.Mining);
                    workTagCollection.Add(WorkTags.PlantWork);
                    workTagCollection.Add(WorkTags.Social);
                    workTagCollection.Add(WorkTags.Violent);
                    //workTagCollection.Add();
                }

                // Get the base disables (The AI can never do these)
                WorkTags workDisables1 = GetBasicWorkDisables();
                WorkTags workDisables2;

                // Create minimal backstory
                backstory          = new Backstory();
                backstory.baseDesc = txtBaseDesc;
                backstory.SetTitle(txtTitle);
                backstory.SetTitleShort(txtTitleShort);
                backstory.bodyTypeGlobal = bodyType;
                backstory.bodyTypeFemale = BodyType.Female;
                backstory.bodyTypeMale   = BodyType.Male;
                backstory.workDisables   = workDisables1;
                backstory.identifier     = GetBackstoryUniqueKey(backstory.workDisables);
                backstories.Add(backstory);

                //string log = workDisables1.ToString().Replace(", ", "_"); //Logging

                // add other backstories
                if (allCombos == null)
                {
                    allCombos = HelperAIPawn.GetAllCombos <WorkTags>(workTagCollection);
                }

                foreach (List <WorkTags> activeCombo in allCombos)
                {
                    workDisables2 = GetBasicWorkDisables();
                    foreach (WorkTags entry in activeCombo)
                    {
                        workDisables2 = workDisables2 | entry;
                    }

                    backstory          = new Backstory();
                    backstory.baseDesc = txtBaseDesc;
                    backstory.SetTitle(txtTitle);
                    backstory.SetTitleShort(txtTitleShort);
                    backstory.bodyTypeGlobal = bodyType;
                    backstory.bodyTypeFemale = BodyType.Female;
                    backstory.bodyTypeMale   = BodyType.Male;
                    backstory.workDisables   = workDisables2;
                    backstory.identifier     = GetBackstoryUniqueKey(backstory.workDisables);
                    backstories.Add(backstory);

                    //log = log + Environment.NewLine + backstory.defName; // workDisables2.ToString().Replace(", ", "_"); //Logging
                }
            }

            //Log.Error(log); //Logging

            return(backstories.AsEnumerable <Backstory>());
        }