public static ResearchProjectDef ApplyPointsToExpertise(float points, Pawn pawn) { ResearchManager researchManager = Find.ResearchManager; ResearchProjectDef result; if (!researchManager.AnyProjectIsAvailable) { result = null; } else { IEnumerable <ResearchProjectDef> source = from x in DefDatabase <ResearchProjectDef> .AllDefsListForReading where x.CanStartNow select x; source.TryRandomElementByWeight((ResearchProjectDef x) => 1f / x.baseCost, out result); points *= 12f; //stangely, that number is 121f on the mod source. I'm assuming that's a typo. float total = result.baseCost; CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); if (techComp != null) { Dictionary <ResearchProjectDef, float> expertise = techComp.expertise; float num = result.GetProgress(expertise); num += points / total; expertise[result] = (num > 1) ? 1 : num; } } return(result); }
protected Toil FinalizeTraining() { Toil finalizeTraining = new Toil(); finalizeTraining.initAction = delegate { Pawn actor = finalizeTraining.actor; if (!practice) { ThingDef weapon = job.targetB.Thing.def; CompKnowledge techComp = actor.TryGetComp <CompKnowledge>(); bool safe = true; if (unknown) { safe = !CheckExperimentFail(actor, TargetThingB); } if (!techComp.proficientWeapons.Contains(weapon) && safe) { LearnWeaponGroup(weapon, actor, techComp); } } job.bill.Notify_IterationCompleted(actor, new List <Thing> { }); actor.jobs.EndCurrentJob(JobCondition.Succeeded, false); }; finalizeTraining.defaultCompleteMode = ToilCompleteMode.Instant; finalizeTraining.FailOnDespawnedOrNull(TargetIndex.A); return(finalizeTraining); }
public static void CarefullyFinishProject(this ResearchProjectDef project, Thing place) { bool careful = !project.prerequisites.NullOrEmpty(); List <ResearchProjectDef> prerequisitesCopy = new List <ResearchProjectDef>(); if (careful) { prerequisitesCopy.AddRange(project.prerequisites); project.prerequisites.Clear(); } Find.ResearchManager.FinishProject(project); if (careful) { project.prerequisites.AddRange(prerequisitesCopy); } Messages.Message("MessageFiledTech".Translate(project.label), place, MessageTypeDefOf.TaskCompletion, true); using (IEnumerator <Pawn> enumerator = currentPawns.GetEnumerator()) { while (enumerator.MoveNext()) { CompKnowledge techComp = enumerator.Current.TryGetComp <CompKnowledge>(); techComp.homework?.RemoveAll(x => x == project); } } currentPawnsCache.Clear(); }
public static void Learned(this ResearchProjectDef tech, float amount, float recipeCost, Pawn researcher, bool research = false) { float total = research ? tech.baseCost : recipeCost *tech.StuffCostFactor(); amount *= research ? ResearchPointsPerWorkTick : StudyPointsPerWorkTick; amount *= researcher.GetStatValue(StatDefOf.GlobalLearningFactor, true); //Because, why not? CompKnowledge techComp = researcher.TryGetComp <CompKnowledge>(); Dictionary <ResearchProjectDef, float> expertise = techComp.expertise; foreach (ResearchProjectDef sucessor in expertise.Keys.Where(x => x.IsKnownBy(researcher))) { if (!sucessor.prerequisites.NullOrEmpty() && sucessor.prerequisites.Contains(tech)) { amount *= 2; break; } } if (researcher != null && researcher.Faction != null) { amount /= tech.CostFactor(techComp.techLevel); } if (DebugSettings.fastResearch) { amount *= 500f; } if (researcher != null && research) { researcher.records.AddTo(RecordDefOf.ResearchPointsResearched, amount); } float num = tech.GetProgress(expertise); num += amount / total; expertise[tech] = num; }
public override bool ShouldSkip(Pawn pawn, bool forced = false) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); if (techComp != null) { return(techComp.expertise == null || techComp.homework.NullOrEmpty()); } return(true); }
protected bool CheckExperimentFail(Pawn tester, Thing weapon) { float num = 1f; float delta = 1f; CompKnowledge techComp = tester.TryGetComp <CompKnowledge>(); if (techComp != null) { delta = (int)techComp.techLevel / (int)weapon.def.techLevel; } float factor = WeaponExperimentChanceFactor.Evaluate(delta); num *= factor; num = Mathf.Min(num, 0.98f); if (Prefs.LogVerbose) { Log.Message($"[HumanResources] Experiment weapon calculation for {tester} vs. {weapon.def}: techLevel diff is {delta} -> chance factor is {num}"); } Job job = this.job; RecipeDef recipe = job.bill.recipe; if (!Rand.Chance(num)) //Determined by the tech level difference according to curve. { if (Rand.Chance(0.5f)) //50% chance the failure is harmless; { techComp?.AddWeaponTrauma(weapon.def); if (Rand.Chance(0.5f)) //25% chance the weapon just takes some damage; { if (Rand.Chance(0.2f)) //5% chance the weapon is destroyed; { Find.LetterStack.ReceiveLetter("LetterLabelWeaponTestFailed".Translate(weapon.def.Named("WEAPON")), "MessageMedicalWeaponTestFailureRidiculous".Translate(tester.LabelShort, tester.LabelShort, weapon.def.Named("WEAPON"), tester.Named("TESTER"), recipe.Named("RECIPE")), LetterDefOf.NegativeEvent, tester, null, null, null, null); Backfire(tester, weapon); weapon.Destroy(); } else //20% chance the weapon backfires. { Find.LetterStack.ReceiveLetter("LetterLabelWeaponTestFailed".Translate(weapon.def.Named("WEAPON")), "MessageWeaponTestFailureCatastrophic".Translate(tester.LabelShort, tester.LabelShort, weapon.def.Named("WEAPON"), tester.Named("TESTER"), recipe.Named("RECIPE")), LetterDefOf.NegativeEvent, tester, null, null, null, null); Backfire(tester, weapon); } } else { Find.LetterStack.ReceiveLetter("LetterLabelWeaponTestFailed".Translate(weapon.def.Named("WEAPON")), "MessageWeaponTestFailureMinor".Translate(tester.LabelShort, tester.LabelShort, weapon.def.Named("WEAPON"), tester.Named("TESTER"), recipe.Named("RECIPE")), LetterDefOf.NegativeEvent, tester, null, null, null, null); float damageFactor = 4 - delta; Scratch(weapon, damageFactor); } } else { Messages.Message("WeaponTestFail".Translate(tester, weapon.def), MessageTypeDefOf.NegativeEvent); } return(true); } return(false); }
private static IEnumerable <Widgets.DropdownMenuElement <Pawn> > GeneratePawnRestrictionOptions(this ResearchProjectDef tech, bool completed) { SkillDef skill = SkillDefOf.Intellectual; using (IEnumerator <Pawn> enumerator = tech.SortedPawns().GetEnumerator()) { while (enumerator.MoveNext()) { Pawn pawn = enumerator.Current; CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); bool known = tech.IsKnownBy(pawn); WorkTypeDef workGiver = (completed || known) ? TechDefOf.HR_Learn : WorkTypeDefOf.Research; string header = known ? TechStrings.headerWrite : completed ? TechStrings.headerRead : TechStrings.headerResearch; if (techComp != null && (techComp.homework.NullOrEmpty() || !techComp.homework.Contains(tech))) { if (pawn.WorkTypeIsDisabled(workGiver)) { yield return(new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0}: {1} ({2})", header, pawn.LabelShortCap, "WillNever".Translate(workGiver.verb)), null, MenuOptionPriority.DisabledOption, null, null, 0f, null, null), payload = pawn }); } else if (!pawn.workSettings.WorkIsActive(workGiver)) { yield return(new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0}: {1} ({2})", header, pawn.LabelShortCap, "NotAssigned".Translate()), delegate() { techComp.AssignBranch(tech); }, MenuOptionPriority.VeryLow, null, null, 0f, null, null), payload = pawn }); } else { yield return(new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0}: {1} ({2} {3})", new object[] { header, pawn.LabelShortCap, pawn.skills.GetSkill(skill).Level, skill.label }), delegate() { techComp.AssignBranch(tech); }, MenuOptionPriority.Default, null, null, 0f, null, null), payload = pawn }); } } } } yield break; }
public static bool IsKnownBy(this ResearchProjectDef tech, Pawn pawn) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); var expertise = techComp.expertise; if (expertise != null) { return(expertise.ContainsKey(tech) && techComp.expertise[tech] >= 1f); } return(false); }
public override bool ShouldSkip(Pawn pawn, bool forced = false) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); if (techComp != null && !techComp.homework.NullOrEmpty()) { bool result = !techComp.homework.Any(x => !x.IsFinished && !x.IsKnownBy(pawn)); return(result); } return(true); }
public static void WipeAssignments(this ResearchProjectDef project) { using (IEnumerator <Pawn> enumerator = currentPawns.GetEnumerator()) { while (enumerator.MoveNext()) { CompKnowledge techComp = enumerator.Current.TryGetComp <CompKnowledge>(); techComp.homework?.RemoveAll(x => x == project); } } currentPawnsCache.Clear(); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { Building_ResearchBench Desk = t as Building_ResearchBench; if (Desk != null && pawn.CanReserve(t, 1, -1, null, forced)) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); bool result = techComp.homework.Any(x => !x.IsFinished && x.CanBeResearchedAt(Desk, false) && !x.IsKnownBy(pawn) && x.RequisitesKnownBy(pawn)); return(result); } return(false); }
protected override IEnumerable <ThingDef> StudyWeapons(Bill bill, Pawn pawn) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); IEnumerable <ThingDef> known = techComp.knownWeapons; IEnumerable <ThingDef> craftable = techComp.craftableWeapons; IEnumerable <ThingDef> available = unlocked.weapons.Concat(craftable); IEnumerable <ThingDef> chosen = bill.ingredientFilter.AllowedThingDefs; IEnumerable <ThingDef> feared = techComp.fearedWeapons; IEnumerable <ThingDef> unavailable = chosen.Except(known).Where(x => !available.Contains(x)); var result = feared.EnumerableNullOrEmpty() ? chosen.Intersect(unavailable) : chosen.Intersect(unavailable).Except(feared); return(result); }
public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { int tick = Find.TickManager.TicksGame; if (actualJob == null || lastVerifiedJobTick != tick || Find.TickManager.Paused) { actualJob = null; IBillGiver billGiver = thing as IBillGiver; if (billGiver != null && ThingIsUsableBillGiver(thing) && billGiver.BillStack.AnyShouldDoNow && billGiver.UsableForBillsAfterFueling()) { if (CheckLibrarySpace(thing)) //check library space { LocalTargetInfo target = thing; if (pawn.CanReserve(target, 1, -1, null, forced) && !thing.IsBurning() && !thing.IsForbidden(pawn)) //basic desk availabilty { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); IEnumerable <ResearchProjectDef> homework = techComp.homework; var intersection = techComp.knownTechs.Where(x => !x.IsFinished).Intersect(homework); if (intersection.Any()) //check homework { billGiver.BillStack.RemoveIncompletableBills(); foreach (Bill bill in RelevantBills(thing, pawn)) { if (bill.Allows(intersection)) //check bill filter vs. homework { actualJob = StartOrResumeBillJob(pawn, billGiver, target); lastVerifiedJobTick = tick; break; } else if (!JobFailReason.HaveReason) { JobFailReason.Is("ForbiddenAssignment".Translate()); } } } else if (!JobFailReason.HaveReason) { JobFailReason.Is("NoAssignment".Translate(pawn)); } } } else if (!JobFailReason.HaveReason) { JobFailReason.Is("NoSpaceInLibrary".Translate()); } } } return(actualJob); }
public override bool CanBeUsedBy(Pawn p, out string failReason) { failReason = null; CompKnowledge techComp = p.TryGetComp <CompKnowledge>(); if (techComp != null) { if (!techComp.homework.NullOrEmpty()) { return(techComp.homework.Any(x => !x.IsFinished)); } } failReason = "NoActiveResearchProjectToFinish".Translate(); return(false); }
protected virtual IEnumerable <ThingDef> StudyWeapons(Bill bill, Pawn pawn) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); IEnumerable <ThingDef> known = techComp.knownWeapons; IEnumerable <ThingDef> craftable = techComp.craftableWeapons; IEnumerable <ThingDef> allowed = unlocked.weapons.Concat(craftable); IEnumerable <ThingDef> chosen = bill.ingredientFilter.AllowedThingDefs; IEnumerable <ThingDef> viable = chosen.Intersect(allowed).Except(known); IEnumerable <ThingDef> unavailable = chosen.Except(viable); if (viable.EnumerableNullOrEmpty() && !unavailable.EnumerableNullOrEmpty()) { string thoseWeapons = "ThoseWeapons".Translate(); string listing = (unavailable.EnumerableCount() < 10) ? unavailable.Select(x => x.label).ToStringSafeEnumerable() : thoseWeapons; JobFailReason.Is("MissingRequirementToLearnWeapon".Translate(pawn, listing)); } return(viable); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { //Log.Message(pawn + " is looking for a document job..."); Building_WorkTable Desk = t as Building_WorkTable; if (Desk != null) { var relevantBills = RelevantBills(Desk, pawn); if (!CheckJobOnThing(pawn, t, forced) | relevantBills.EnumerableNullOrEmpty()) { return(false); } CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); return(techComp.knownTechs.Where(x => !x.IsFinished).Intersect(techComp.homework).Any()); } //Log.Message("case 4"); return(false); }
protected virtual IEnumerable <ThingDef> StudyWeapons(Bill bill, Pawn pawn) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); IEnumerable <ThingDef> known = techComp.knownWeapons; IEnumerable <ThingDef> craftable = techComp.knownTechs.SelectMany(x => x.UnlockedWeapons()); IEnumerable <ThingDef> available = ModBaseHumanResources.unlocked.weapons.Concat(craftable); IEnumerable <ThingDef> chosen = bill.ingredientFilter.AllowedThingDefs; IEnumerable <ThingDef> unavailable = chosen.Except(known).Where(x => !available.Contains(x)); if (!unavailable.EnumerableNullOrEmpty()) { string thoseWeapons = "ThoseWeapons".Translate(); string listing = (unavailable.EnumerableCount() < 10) ? unavailable.Select(x => x.label).ToStringSafeEnumerable() : thoseWeapons; JobFailReason.Is("MissingRequirementToLearnWeapon".Translate(pawn, listing)); } var result = chosen.Intersect(available).Except(known); return(result); }
public override void DoEffect(Pawn usedBy) { base.DoEffect(usedBy); CompKnowledge techComp = usedBy.TryGetComp <CompKnowledge>(); var candidates = techComp.homework.Where(x => !x.IsFinished && (x.requiredResearchBuilding == null || (bool)ResearchableInfo.GetValue(x))); List <ResearchProjectDef> means = new List <ResearchProjectDef>(); foreach (ResearchProjectDef tech in candidates) { if (tech.prerequisites != null) { means.AddRange(candidates.Where(x => tech.prerequisites.Contains(x))); } } ResearchProjectDef result = candidates.Except(means).RandomElement(); if (techComp.LearnTech(result) && result.prerequisites != null) { techComp.homework.RemoveAll(x => result.prerequisites.Contains(x)); } }
public static bool RequisitesKnownBy(this ResearchProjectDef tech, Pawn pawn) { CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); var expertise = techComp.expertise; if (expertise != null) { //1. test if any descendent is known if (expertise.Where(x => x.Value >= 1 && !x.Key.prerequisites.NullOrEmpty() && x.Key.prerequisites.Contains(tech)).Any()) { return(true); } //2. test if all ancestors are known if (!tech.prerequisites.NullOrEmpty()) { return(tech.prerequisites.All(x => x.IsKnownBy(pawn))); } } //3. test if there are any ancestors return(tech.prerequisites.NullOrEmpty()); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { //Log.Message(pawn + " is looking for a research job..."); Building_WorkTable Desk = t as Building_WorkTable; if (Desk != null) { var relevantBills = RelevantBills(Desk, pawn); if (!CheckJobOnThing(pawn, t, forced) | relevantBills.EnumerableNullOrEmpty()) { //Log.Message("...no job on desk."); return(false); } List <ResearchProjectDef> studyMaterial = new List <ResearchProjectDef>(); //Log.Message("...relevant bills: " + RelevantBills(Desk, pawn).Count); foreach (Bill bill in relevantBills) { //Log.Message("...checking recipe: " + bill.recipe+", on bill "+bill.GetType()); //Log.Message("...selected techs count: " + bill.SelectedTech().ToList().Count()); studyMaterial.AddRange(bill.SelectedTech().Where(x => !x.IsFinished && x.TechprintRequirementMet && (x.requiredResearchBuilding == null || (bool)AccessTools.Property(typeof(ResearchProjectDef), "PlayerHasAnyAppropriateResearchBench").GetValue(x)))); } availableTechs = studyMaterial; //Log.Message("...studyMaterial count is " + studyMaterial.Count()); CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); techComp.AssignHomework(studyMaterial); //Log.Message("...homework count is " + techComp.HomeWork.Count()); //if (techComp.HomeWork.Count() > 0) return true; if (studyMaterial.Intersect(techComp.HomeWork).Any()) { return(true); } if (!JobFailReason.HaveReason) { JobFailReason.Is("AlreadyKnowsThoseProjects".Translate(pawn), null); } return(false); } //Log.Message("case 4"); return(false); }
protected void LearnWeaponGroup(ThingDef weapon, Pawn pawn, CompKnowledge techComp) { bool groupRanged = ModBaseHumanResources.LearnRangedWeaponsByGroup && weapon.IsRangedWeapon; bool groupMelee = ModBaseHumanResources.LearnMeleeWeaponsByGroup && weapon.IsMeleeWeapon; if (TechTracker.FindTechs(weapon).Any() && (groupRanged || groupMelee)) { foreach (ThingDef sister in TechTracker.FindTech(weapon).Weapons) { if ((groupRanged && sister.IsRangedWeapon) || (groupMelee && sister.IsMeleeWeapon)) { techComp.LearnWeapon(sister); Messages.Message("MessageTrainingComplete".Translate(pawn, sister), MessageTypeDefOf.TaskCompletion); } } } else { techComp.LearnWeapon(weapon); Messages.Message("MessageTrainingComplete".Translate(pawn, weapon), MessageTypeDefOf.TaskCompletion); } }
protected void LearnWeaponGroup(ThingDef weapon, Pawn pawn, CompKnowledge techComp) { bool groupRanged = ModBaseHumanResources.LearnRangedWeaponsByGroup && weapon.IsRangedWeapon; bool groupMelee = ModBaseHumanResources.LearnMeleeWeaponsByGroup && weapon.IsMeleeWeapon; if (Extension_Research.TechByWeapon.ContainsKey(weapon) && (groupRanged || groupMelee)) { foreach (ThingDef sister in Extension_Research.WeaponsByTech[Extension_Research.TechByWeapon[weapon]]) { if ((groupRanged && sister.IsRangedWeapon) || (groupMelee && sister.IsMeleeWeapon)) { techComp.LearnWeapon(sister); Messages.Message("MessageTrainingComplete".Translate(pawn, sister), MessageTypeDefOf.TaskCompletion); } } } else { techComp.LearnWeapon(weapon); Messages.Message("MessageTrainingComplete".Translate(pawn, weapon), MessageTypeDefOf.TaskCompletion); } }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { //Log.Message(pawn + " is looking for a study job..."); Building_WorkTable Desk = t as Building_WorkTable; if (Desk != null) { var relevantBills = RelevantBills(Desk, pawn); if (!CheckJobOnThing(pawn, t, forced) | relevantBills.EnumerableNullOrEmpty()) { //Log.Message("...no job on desk."); return(false); } List <ResearchProjectDef> studyMaterial = new List <ResearchProjectDef>(); foreach (Bill bill in relevantBills) { //Log.Message("...checking recipe: " + bill.recipe + ", on bill " + bill.GetType()); //Log.Message("...selected techs count: " + bill.SelectedTech().ToList().Count()); studyMaterial.AddRange(bill.SelectedTech().Where(x => x.IsFinished)); } availableTechs = studyMaterial; //Log.Message("...studyMaterial count is " + studyMaterial.Count()); CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); techComp.AssignHomework(studyMaterial); //Log.Message("...homework count is " + techComp.HomeWork.Count()); if (techComp.HomeWork.Count() > 0) { return(true); } if (studyMaterial.Intersect(techComp.HomeWork).Any()) { return(true); } return(false); } Log.Message("case 4"); return(false); }
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { //Log.Message(pawn + " is looking for a document job..."); Building_WorkTable Desk = t as Building_WorkTable; if (Desk != null && ModBaseHumanResources.unlocked.libraryFreeSpace > 0) { var relevantBills = RelevantBills(Desk, pawn); if (!CheckJobOnThing(pawn, t, forced) | relevantBills.EnumerableNullOrEmpty()) { //Log.Message("... no job on thing"); return(false); } CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); return(techComp.knownTechs.Where(x => !x.IsFinished).Intersect(techComp.homework).Any()); } //Log.Message("... no free space"); if (ModBaseHumanResources.unlocked.libraryFreeSpace <= 0) { JobFailReason.Is("NoSpaceInLibrary".Translate()); } return(false); }
private static void ReflectKnowledge(object instance, CompKnowledge techComp, out IEnumerable <object> expertiseDisplay) { Find.WindowStack.FloatMenu?.Close(false); bool valid = !techComp.expertise.EnumerableNullOrEmpty(); expertiseDisplay = new object[] { }; if (AltRPal) { ToggleSearch(true); if (valid) { expertiseDisplay = from e in ResearchNodesCache where techComp.expertise.Keys.Contains(e.Key) select e.Value; } } else if (valid) { foreach (ResearchProjectDef tech in techComp.expertise.Keys) { HighlightedProxy(ResearchNodesCache[tech], true); } } }
public static bool DrawQueue_Prefix(object __instance, Rect canvas) { if (AltRPal) { canvas.xMax += 130f + 2 * Margin; //keep an eye on his MainTabWindow_ResearchTree.DrawTopBar method for changes to this number canvas = canvas.ExpandedBy(Margin); } float padding = 12f; float spacing = Find.ColonistBar.SpaceBetweenColonistsHorizontal; float height = canvas.height; float startPos = canvas.xMax - height - padding; Vector2 size = new Vector2(height + spacing, height - padding); Vector2 innerSize = new Vector2(height - padding, height - padding); IEnumerable <object> expertiseDisplay = new object[] { }; bool displayActive = false; using (IEnumerator <Pawn> enumerator = Find.ColonistBar.GetColonistsInOrder().Where(x => x.TechBound()).AsEnumerable().Reverse().GetEnumerator()) { while (enumerator.MoveNext()) { Vector2 position = new Vector2(startPos, canvas.y); Rect box = new Rect(position, size); Rect innerBox = new Rect(position.x + spacing, position.y, size.x - spacing - 2 * padding, size.y); Pawn pawn = enumerator.Current; GUI.DrawTexture(box, PortraitsCache.Get(pawn, size, Rot4.South, cameraZoom: 1.4f)); CompKnowledge techComp = pawn.TryGetComp <CompKnowledge>(); if (Mouse.IsOver(innerBox)) { DeInterest(); ReflectKnowledge(__instance, techComp, out expertiseDisplay); displayActive = true; } if (!techComp.homework.NullOrEmpty()) { StringBuilder homeworkSummary = new StringBuilder(); homeworkSummary.AppendLine("AssignedTo".Translate(pawn)); foreach (var tech in techComp.homework) { homeworkSummary.AppendLine("- " + TechStrings.GetTask(pawn, tech) + " " + tech.label); } TooltipHandler.TipRegionByKey(box, homeworkSummary.ToString()); } Vector2 pos = new Vector2(box.center.x, box.yMax); GenMapUI.DrawPawnLabel(pawn, pos, 1f, box.width, null, GameFont.Tiny, false, true); startPos -= height; } } if (AltRPal) { if (displayActive) { UpdateMatches(expertiseDisplay); expertiseDisplayed = true; } else if (expertiseDisplayed) { ToggleSearch(false); expertiseDisplayed = false; } } return(false); }
protected override IEnumerable <Toil> MakeNewToils() { Bill bill = job.bill; AddEndCondition(delegate { Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate() { IBillGiver billGiver = job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); AddFinishAction(delegate() { //Log.Message("LearnWeapon: finishing"); ThingWithComps thingWithComps = (ThingWithComps)job.targetB.Thing; if (pawn.equipment.Primary != null) { pawn.equipment.TryDropEquipment(thingWithComps, out thingWithComps, pawn.Position, false); } }); Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>())); Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true); yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(getToHaulTarget); //temporary equip yield return(new Toil { initAction = delegate() { ThingWithComps thingWithComps = (ThingWithComps)job.targetB.Thing; ThingWithComps thingWithComps2; if (thingWithComps.def.stackLimit > 1 && thingWithComps.stackCount > 1) { thingWithComps2 = (ThingWithComps)thingWithComps.SplitOff(1); } else { thingWithComps2 = thingWithComps; thingWithComps2.DeSpawn(DestroyMode.Vanish); } pawn.equipment.MakeRoomFor(thingWithComps2); pawn.equipment.AddEquipment(thingWithComps2); if (thingWithComps.def.soundInteract != null) { thingWithComps.def.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract)); yield return(gotoBillGiver); yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); Toil train = new Toil(); train.initAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = job.targetB.Thing.def; workLeft = curJob.bill.recipe.WorkAmountTotal(null); billStartTick = Find.TickManager.TicksGame; ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); //sound: if (weapon.soundInteract != null) { weapon.soundInteract.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } }; train.tickAction = delegate() { Pawn actor = train.actor; Job curJob = actor.jobs.curJob; ThingDef weapon = job.targetB.Thing.def; ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = train.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; if (billGiverWithTickAction != null) { billGiverWithTickAction.UsedThisTick(); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; if (curJob.RecipeDef.workTableSpeedStat != null) { Building_WorkTable building_WorkTable = BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(curJob.RecipeDef.workTableSpeedStat, true); } } if (DebugSettings.fastCrafting) { num *= 30f; } workLeft -= num; actor.GainComfortFromCellIfPossible(); if (workLeft <= 0f) { ReadyForNextToil(); } //pawn posture Verb verbToUse = actor.jobs.curJob.verbToUse; LocalTargetInfo target = actor.jobs.curJob.GetTarget(TargetIndex.A); pawn.stances.SetStance(new Stance_Warmup(1, target, verbToUse)); //sound: if (verbToUse.verbProps != null && verbToUse.verbProps.warmupTime > 0) { if ((ticksSpentDoingRecipeWork % verbToUse.verbProps.AdjustedFullCycleTime(verbToUse, actor).SecondsToTicks()) == 0) { if (verbToUse.verbProps.soundCast != null) { verbToUse.verbProps.soundCast.PlayOneShot(new TargetInfo(pawn.Position, pawn.Map, false)); } if (verbToUse.verbProps.soundCastTail != null) { verbToUse.verbProps.soundCastTail.PlayOneShotOnCamera(pawn.Map); } } } if (job.RecipeDef.workSkill != null) { //float xpDelta = techComp.proficientWeapons.Contains(job.targetB.Thing.def) ? 1f : 0.1f; float xp = 0.1f * job.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(job.RecipeDef.workSkill).Learn(xp, false); } }; train.defaultCompleteMode = ToilCompleteMode.Never; train.WithEffect(() => train.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); train.PlaySustainerOrSound(() => train.actor.CurJob.bill.recipe.soundWorking); train.WithProgressBar(TargetIndex.A, delegate { Pawn actor = train.actor; Job curJob = actor.CurJob; //return 1f - ((JobDriver_DoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal(null); return(1f - (workLeft / curJob.bill.recipe.WorkAmountTotal(null))); }, false, -0.5f); train.FailOn(() => train.actor.CurJob.bill.suspended); train.activeSkill = () => train.actor.CurJob.bill.recipe.workSkill; yield return(train.FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell)); Toil finalizeTraining = new Toil(); finalizeTraining.initAction = delegate { Pawn actor = finalizeTraining.actor; CompKnowledge techComp = actor.TryGetComp <CompKnowledge>(); if (!techComp.proficientWeapons.Contains(job.targetB.Thing.def)) { techComp.proficientWeapons.Add(TargetThingB.def); } job.bill.Notify_IterationCompleted(actor, new List <Thing> { }); actor.jobs.EndCurrentJob(JobCondition.Succeeded, false); }; finalizeTraining.defaultCompleteMode = ToilCompleteMode.Instant; finalizeTraining.FailOnDespawnedOrNull(TargetIndex.A); yield return(finalizeTraining); //testing yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); Toil findPlaceTarget = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(findPlaceTarget); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, findPlaceTarget, true, true)); yield break; }