// ================== 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)); } }