/// <summary> /// Do something after the object is spawned /// </summary> public override void SpawnSetup(Map map, bool respawnAfterLoad) { BackstoryHelper.AddNewBackstoriesToDatabase(); base.SpawnSetup(map, respawnAfterLoad); LongEventHandler.ExecuteWhenFinished(SpawnSetup_Part2); }
/// <summary> /// To write and read data (savegame) /// </summary> public override void ExposeData() { BackstoryHelper.AddNewBackstoriesToDatabase(); base.ExposeData(); Scribe_Values.Look <int>(ref refreshBaseInfosCount, "RefreshBaseInfos"); Scribe_Values.Look <int>(ref refreshQuickCount, "RefreshQuickInfos"); draftedActiveOld = this.Drafted; loaded = true; }
// ================== 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)); } }
//public static AIPawn GeneratePawn(PawnKindDef kindDef, Faction faction, Map map, Gender gender = Gender.Female, int tries = 0) public static AIPawn GenerateAIPawn(ref PawnGenerationRequest request, Map map, int tries = 0) { BackstoryHelper.AddNewBackstoriesToDatabase(); // First add the new backstories to the database //Log.Error("0"); AIPawn pawnAI = (AIPawn)ThingMaker.MakeThing(request.KindDef.race, null); //Log.Error("1"); GetXMLData(pawnAI); //request.EnsureNonNullFaction(); pawnAI.kindDef = request.KindDef; pawnAI.SetFactionDirect(request.Faction); PawnComponentsUtility.CreateInitialComponents(pawnAI); //Log.Error("2"); // Needs to be set because of not flesh user if (pawnAI.ownership == null) { pawnAI.ownership = new Pawn_Ownership(pawnAI); } pawnAI.relations = new Pawn_RelationsTracker(pawnAI); pawnAI.guest = new Pawn_GuestTracker(pawnAI); pawnAI.guilt = new Pawn_GuiltTracker(pawnAI); pawnAI.royalty = new Pawn_RoyaltyTracker(pawnAI); pawnAI.abilities = new Pawn_AbilityTracker(pawnAI); pawnAI.relations = new Pawn_RelationsTracker(pawnAI); if (request.FixedGender.HasValue) { pawnAI.gender = request.FixedGender.Value; } else if (pawnAI.RaceProps.hasGenders) { if (Rand.Value < 0.5f) { pawnAI.gender = Gender.Male; } else { pawnAI.gender = Gender.Female; } } else { pawnAI.gender = Gender.Female; } SetBirthday(pawnAI); pawnAI.needs.SetInitialLevels(); //Log.Error("3"); AIPawnGenerator.GenerateInitialHediffs(pawnAI); if (pawnAI.RaceProps.Humanlike) { pawnAI.story.melanin = 0.1f; pawnAI.story.crownType = CrownType.Average; pawnAI.story.hairColor = PawnHairColors.RandomHairColor(pawnAI.story.SkinColor, pawnAI.ageTracker.AgeBiologicalYears); pawnAI.story.childhood = GetBackstory(); //pawnAI.story.adulthood = GetBackstory(); string headGraphicPath = GraphicDatabaseHeadRecords.GetHeadRandom(pawnAI.gender, pawnAI.story.SkinColor, pawnAI.story.crownType, false).GraphicPath; // With this Reflection you can access a private variable! Here: The private string "headGraphicPath" is set System.Reflection.FieldInfo fi = typeof(Pawn_StoryTracker).GetField("headGraphicPath", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); fi.SetValue(pawnAI.story, headGraphicPath); pawnAI.story.hairDef = GetHair(); pawnAI.story.bodyType = ((pawnAI.gender != Gender.Female) ? BodyTypeDefOf.Male : BodyTypeDefOf.Female); MakeSkillsFromBackstory(pawnAI); GiveTraitsTo(pawnAI); if (pawnAI.workSettings != null && (request.Faction == Faction.OfPlayer)) { pawnAI.workSettings.EnableAndInitialize(); } } if (pawnAI.RaceProps.ToolUser) { GenerateBaseApparel(pawnAI); } pawnAI.Name = GetName(pawnAI.def, map); pawnAI.royalty = null; //Log.Error("4"); //PawnGenerationRequest request = new PawnGenerationRequest(pawnAI.kindDef , Faction.OfPlayer, PawnGenerationContext.All, true, true, false,false, false, false, 0, false, false, false,null, 0,0, pawnAI.gender, null, null); //PawnInventoryGenerator.GenerateInventoryFor(pawnAI, request); if (!pawnAI.Dead) { return(pawnAI); } if (tries < 10) { return(GenerateAIPawn(ref request, map, tries + 1)); } return(null); }
private static Backstory GetBackstory() { string researchProject; WorkTags workDisables = BackstoryHelper.GetBasicWorkDisables(); // WorkTags.Artistic <= These are never accessable for mai researchProject = "AIPawnAdvResearchAnimals"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Animals; } researchProject = "AIPawnAdvResearchSocial"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Social; } if (!enhancedAI) // do not if enhanced AI { researchProject = "AIPawnAdvResearchCombat"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Violent; } } researchProject = "AIPawnAdvResearchCrafting"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Crafting; } if (!enhancedAI) // do not if enhanced AI { researchProject = "AIPawnAdvResearchIntellectual"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Intellectual; } } researchProject = "AIPawnAdvResearchCooking"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Cooking; } researchProject = "AIPawnAdvResearchCaring"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Caring; } researchProject = "AIPawnAdvResearchConstruction"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.ManualSkilled; } researchProject = "AIPawnAdvResearchMining"; if ((DefDatabase <ResearchProjectDef> .GetNamedSilentFail(researchProject) != null) && (!ResearchProjectDef.Named(researchProject).IsFinished)) { workDisables = workDisables | WorkTags.Mining; } string backstoryUniqueKey = BackstoryHelper.GetBackstoryUniqueKey(workDisables); Backstory bs; if (BackstoryDatabase.TryGetWithIdentifier(backstoryUniqueKey, out bs)) { return(bs); } return(null); }