public static IEnumerable <Toil> MakeNewToils(object __instance, float drillInTickMultiplier = 1f) { JobDriver jd = (JobDriver)__instance; jd.EndOnDespawnedOrNull(TargetIndex.A); Toil toil = Toils_Misc.FindRandomAdjacentReachableCell(TargetIndex.A, TargetIndex.B); yield return(toil); yield return(Toils_Reserve.Reserve(TargetIndex.B)); yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.OnCell)); Toil supervise = new Toil(); supervise.tickAction = delegate() { LocalTargetInfo TargetA = Traverse.Create(__instance).Property("TargetA").GetValue <LocalTargetInfo>(); jd.pawn.rotationTracker.FaceCell(TargetA.Thing.OccupiedRect().ClosestCellTo(jd.pawn.Position)); Pawn actor = supervise.actor; actor.skills.Learn(SkillDefOf.Construction, 0.275f); float statValue = actor.GetStatValue(StatDefOf.ConstructionSpeed); //CompOilDerrick compOilDerrick = TargetA.Thing.TryGetComp<CompOilDerrick>(); object compOilDerrick = null; { // getting compOilDerrick ThingWithComps thingWithComps = TargetA.Thing as ThingWithComps; if (thingWithComps != null) { var found = thingWithComps.AllComps?.Where(x => x.GetType().ToString().StartsWith("CompOilDerrick")).FirstOrDefault(); if (found != null) { compOilDerrick = found; } } } bool flag = compOilDerrick != null; if (flag) { bool flag2 = !Traverse.Create(compOilDerrick).Property("WorkingNow").GetValue <bool>(); if (flag2) { jd.EndJobWith(JobCondition.Incompletable); } // compOilDerrick.Drill(statValue); Traverse.Create(compOilDerrick).Method("Drill", statValue * drillInTickMultiplier).GetValue(); bool isDilled = Traverse.Create(compOilDerrick).Property("IsDilled").GetValue <bool>(); if (isDilled) { jd.EndJobWith(JobCondition.Succeeded); } } }; supervise.handlingFacing = true; supervise.defaultCompleteMode = ToilCompleteMode.Never; supervise.activeSkill = (() => SkillDefOf.Construction); yield return(supervise); }
public static Toil get_CurToil2(JobDriver __instance) { int cti = curToilIndex(__instance); if (cti < 0 || __instance.job == null || __instance.pawn.CurJob != __instance.job) { return(null); } if (cti >= toils(__instance).Count) { Log.Warning(__instance.pawn + " with job " + __instance.pawn.CurJob + " tried to get CurToil with curToilIndex=" + curToilIndex(__instance) + " but only has " + toils(__instance).Count + " toils."); return(null); } Toil toil; try { toil = toils(__instance)[cti]; } catch (ArgumentOutOfRangeException) { Log.Warning(__instance.pawn + " with job " + __instance.pawn.CurJob + " tried to get CurToil with curToilIndex=" + curToilIndex(__instance) + " but only has " + toils(__instance).Count + " toils."); return(null); } return(toil); }
public static void CheckForAutoAttack(JobDriver jobDriver) { List <Hediff> hediffs = jobDriver.pawn.health.hediffSet.hediffs; int hediff = hediffs.Count; for (int i = 0; i < hediff; i++) { HediffComp_VerbGiverExtended verbGiverExtended = hediffs[i].TryGetComp <HediffComp_VerbGiverExtended>(); if (verbGiverExtended != null) { List <Verb> allVerbs = verbGiverExtended.AllVerbs; int radVerb = Random.Range(0, allVerbs.Count); if (allVerbs[radVerb] != null && verbGiverExtended.canAutoAttack && verbGiverExtended.canAttack) { TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat; if (allVerbs[radVerb].IsIncendiary()) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } Thing thing = (Thing)PCF_AttackTargetFinder.BestShootTargetFromCurrentPosition(jobDriver.pawn, allVerbs[radVerb], targetScanFlags, null, 0f, 9999f); if (thing != null && !allVerbs[radVerb].IsMeleeAttack) { verbGiverExtended.rangedVerbWarmupTime = allVerbs[radVerb].verbProps.warmupTime; allVerbs[radVerb].verbProps.warmupTime = 0f; allVerbs[radVerb].TryStartCastOn(thing, false, true); allVerbs[radVerb].verbProps.warmupTime = verbGiverExtended.rangedVerbWarmupTime; } } verbGiverExtended.canAttack = false; } } }
static void ReleaseReservationsNow(JobDriver driver) { // Note: I COULD write this all out as IL instructions. I just choose not to :p // I also COULD check the mod setting here instead of in the Prepare(), // but I choose not to. driver.pawn.ClearReservationsForJob(driver.pawn.CurJob); }
internal void <> m__0() { Pawn actor = this.layDown.actor; actor.pather.StopDead(); JobDriver curDriver = actor.jobs.curDriver; if (this.hasBed) { Building_Bed t = (Building_Bed)actor.CurJob.GetTarget(this.bedOrRestSpotIndex).Thing; if (!t.OccupiedRect().Contains(actor.Position)) { Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor, false); actor.jobs.EndCurrentJob(JobCondition.Errored, true); return; } actor.jobs.posture = PawnPosture.LayingInBed; } else { actor.jobs.posture = PawnPosture.LayingOnGroundNormal; } curDriver.asleep = false; if (actor.mindState.applyBedThoughtsTick == 0) { actor.mindState.applyBedThoughtsTick = Find.TickManager.TicksGame + Rand.Range(2500, 10000); actor.mindState.applyBedThoughtsOnLeave = false; } if (actor.ownership != null && actor.CurrentBed() != actor.ownership.OwnedBed) { ThoughtUtility.RemovePositiveBedroomThoughts(actor); } }
public static void CheckForAutoAttack(JobDriver jobDriver) { List <Hediff> hediffs = jobDriver.pawn.health.hediffSet.hediffs; foreach (Hediff hediff in hediffs) { HediffComp_VerbGiverExtended verbGiverExtended = hediff.TryGetComp <HediffComp_VerbGiverExtended>(); if (verbGiverExtended != null) // for each comp that gives verbs do this: { List <Verb> allVerbs = new List <Verb>(verbGiverExtended.AllVerbs.SkipWhile((Verb verb) => verb is Verb_CastPsycast)); int radVerb = Random.Range(0, allVerbs.Count); if (allVerbs[radVerb] != null && verbGiverExtended.canAutoAttack && verbGiverExtended.canAttack) // take a random verb that can attack { TargetScanFlags targetScanFlags = TargetScanFlags.NeedLOSToPawns | TargetScanFlags.NeedLOSToNonPawns | TargetScanFlags.NeedThreat; if (allVerbs[radVerb].IsIncendiary()) { targetScanFlags |= TargetScanFlags.NeedNonBurning; } // find best thing to attack Thing thing = (Thing)PCF_AttackTargetFinder.BestShootTargetFromCurrentPosition(jobDriver.pawn, allVerbs[radVerb], targetScanFlags, null, 0f, 9999f); if (thing != null && !allVerbs[radVerb].IsMeleeAttack) // attack (weird shit inbetween) { verbGiverExtended.rangedVerbWarmupTime = allVerbs[radVerb].verbProps.warmupTime; allVerbs[radVerb].verbProps.warmupTime = 0f; allVerbs[radVerb].TryStartCastOn(thing, false, true); allVerbs[radVerb].verbProps.warmupTime = verbGiverExtended.rangedVerbWarmupTime; } } verbGiverExtended.canAttack = false; } } }
private static bool on_cleanup_driver(JobDriver __instance, JobCondition condition) { if (__instance == null) { return(true); } var lov = __instance as JobDriver_Lovin; //Edited by nizhuan-jjr: The PostFix method cannot do this. if ((lov != null) && (condition == JobCondition.Succeeded)) { //--Log.Message("[RJW]patches_lovin::on_cleanup_driver is called0"); var par = find_partner(lov); xxx.aftersex(lov.pawn, par, false, true); // note that JobDriver_Lovin will be called for both pawns //lov.pawn.mindState.canLovinTick = Find.TickManager.TicksGame + xxx.generate_min_ticks_to_next_lovin(lov.pawn); //if (par != null) // par.mindState.canLovinTick = Find.TickManager.TicksGame + xxx.generate_min_ticks_to_next_lovin(par); } else if (xxx.RomanceDiversifiedIsActive && condition == JobCondition.Succeeded && __instance.GetType() == JobDriverDoLovinCasual) { //--Log.Message("[RJW]patches_lovin::on_cleanup_driver is called1"); var any_ins = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var casuallovin_par = (Pawn)(__instance.GetType().GetProperty("Partner", any_ins).GetValue(__instance, null)); if (casuallovin_par != null) { xxx.aftersex(__instance.pawn, casuallovin_par, false, true); // note that JobDriver_DoLovinCasual will be called for both pawns //lov.pawn.mindState.canLovinTick = Find.TickManager.TicksGame + xxx.generate_min_ticks_to_next_lovin(lov.pawn); //casuallovin_par.mindState.canLovinTick = Find.TickManager.TicksGame + xxx.generate_min_ticks_to_next_lovin(casuallovin_par); } } return(true); }
public static void JobDriver_PostFix(JobDriver __instance, bool __result) { if (__result) { StoryHandler.Notify_JobStarted(__instance.job.def, __instance.GetActor()); } }
public static void PrintToils(JobDriver toilMaker) { var toils = PickToils(toilMaker); if (toils != null) { foreach (var toil in toils) { Console.WriteLine($"{toil.GetType()}"); foreach (var ci in MethodBodyReader.GetInstructions(toil.initAction.Method)) { var operand = ci.operand is Label ? ("Label " + ci.operand.GetHashCode()).ToString() : ci.operand; string labels = ""; if (ci.labels.Count > 0) { foreach (var label in ci.labels) { labels += $"Label {label.GetHashCode()}"; } } else { labels += "no labels"; } Console.WriteLine($" {ci.opcode} | {operand} | {labels}"); } } } else { Console.WriteLine("Null"); } }
private static bool PrepareToIngestToilsPrefix(JobDriver __instance, Toil chewToil, ref IEnumerable <Toil> __result) //TODO figure out how to turn this into a transpiler patch { Thing thing = __instance.job.targetA.Thing; if (RaceGenerator.TryGetMorphOfRace(__instance.pawn.def, out MorphDef def)) { if (thing.def.ingestible == null) { return(true); } FoodTypeFlags flg = thing.def.ingestible.foodType & (FoodTypeFlags.Tree | FoodTypeFlags.Plant); if (flg != 0) { __result = new[] { ReserveFoodIfWillIngestWholeStack(__instance), Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch) }; return(false); } } else if (__instance.pawn.IsSapientFormerHuman()) { if (thing.def.ingestible == null) { return(true); } } return(true); }
private static Toil ReserveFoodIfWillIngestWholeStack(JobDriver driver) { return(new Toil { initAction = delegate { if (driver.pawn.Faction == null) { return; } Thing thing = driver.job.GetTarget(TargetIndex.A).Thing; if (driver.pawn.carryTracker.CarriedThing == thing) { return; } int num = FoodUtility.WillIngestStackCountOf(driver.pawn, thing.def, thing.GetStatValue(StatDefOf.Nutrition)); if (num >= thing.stackCount) { if (!thing.Spawned) { driver.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } driver.pawn.Reserve(thing, driver.job); } }, defaultCompleteMode = ToilCompleteMode.Instant, atomicWithPrevious = true }); }
public static float GetMusicQuality(Pawn musician, Thing instrument, int?luck = null) { if (musician == null || instrument == null) { return(0f); } int artSkill = musician.skills.GetSkill(SkillDefOf.Artistic).Level; int luckActual; if (luck.HasValue) { luckActual = luck.Value; } else { JobDriver driver = musician.jobs.curDriver; luckActual = (driver != null && driver is JobDriver_MusicPlayBase ? ((JobDriver_MusicPlayBase)driver).Luck : 0); } bool isInspired = musician.Inspired ? musician.Inspiration.def == InspirationDefOf.Inspired_Creativity : false; QualityCategory instrumentQuality = QualityCategory.Normal; instrument.TryGetQuality(out instrumentQuality); float instrumentCondition = (float)instrument.HitPoints / instrument.MaxHitPoints; CompMusicalInstrument instrumentComp = instrument.TryGetComp <CompMusicalInstrument>(); float easiness = instrumentComp.Props.easiness; float expressiveness = instrumentComp.Props.expressiveness; float quality = (easiness + (expressiveness * ((artSkill + luckActual + (isInspired ? 0 : -3)) / 5.0f))) * ((float)instrumentQuality / 3.0f + 0.1f) * instrumentCondition; return(quality - 0.3f); }
public static bool Notify_DamageTaken(Pawn_JobTracker __instance, DamageInfo dinfo) { Job curJob = __instance.curJob; if (curJob == null) { return(false); } JobDriver curDriver = __instance.curDriver; if (curDriver == null) { return(false); } curDriver.Notify_DamageTaken(dinfo); Job curJob2 = __instance.curJob; if (curJob2 != curJob || !dinfo.Def.ExternalViolenceFor(__instance.pawn) || (!dinfo.Def.canInterruptJobs || curJob2.playerForced) || Find.TickManager.TicksGame < __instance.lastDamageCheckTick + 180) { return(false); } Thing instigator = dinfo.Instigator; if (curJob2.def.checkOverrideOnDamage != CheckJobOverrideOnDamageMode.Always && (curJob2.def.checkOverrideOnDamage != CheckJobOverrideOnDamageMode.OnlyIfInstigatorNotJobTarget || __instance.curJob.AnyTargetIs((LocalTargetInfo)instigator))) { return(false); } __instance.lastDamageCheckTick = Find.TickManager.TicksGame; __instance.CheckForJobOverride(); return(false); }
private static void VerbGiverExtended(JobDriver __instance) { /* * // Patch inspirated from RunAndGun mod by roolo * // License for patch when i make this mod "10 July 2019" * // That patch is free to use except don't make exact copies or only with minor adjustment of Run And Gun. The author also give permission. * // --- github.com/rheirman/RunAndGun/blob/master/README.md --- */ if (__instance is JobDriver_Goto jobDriver_Goto) { List <Toil> value = Traverse.Create(jobDriver_Goto).Field("toils").GetValue <List <Toil> >(); if (value.Count() > 0) { Toil toil = value.ElementAt(0); toil.AddPreTickAction(delegate { if (jobDriver_Goto.pawn.Downed) { return; } if (jobDriver_Goto.pawn.Faction != null && (jobDriver_Goto.pawn.drafter == null || jobDriver_Goto.pawn.drafter.FireAtWill) && jobDriver_Goto.pawn.IsHashIntervalTick(10)) { PCF_VanillaExtender.CheckForAutoAttack(jobDriver_Goto); } }); } } }
protected override ThoughtState CurrentStateInternal(Pawn p) { JobDriver curDriver = p.jobs.curDriver; if (curDriver == null) { return(ThoughtState.Inactive); } if (p.skills == null) { return(ThoughtState.Inactive); } if (curDriver.ActiveSkill == null) { return(ThoughtState.Inactive); } SkillRecord skill = p.skills.GetSkill(curDriver.ActiveSkill); if (skill == null) { return(ThoughtState.Inactive); } if (skill.passion == Passion.Minor) { return(ThoughtState.ActiveAtStage(0)); } if (skill.passion == Passion.Major) { return(ThoughtState.ActiveAtStage(1)); } return(ThoughtState.Inactive); }
protected override IEnumerable <Toil> MakeNewToils() { yield return(new Toil { initAction = delegate { this.pawn.Reserve(this.pawn.Position, this.job);// De ReserveDestinationFor(this.pawn, this.pawn.Position); this.pawn.pather.StopDead(); JobDriver curDriver = this.pawn.jobs.curDriver; pawn.jobs.posture = PawnPosture.LayingOnGroundFaceUp; curDriver.asleep = false; }, tickAction = delegate { if (this.job.expiryInterval == -1 && this.job.def == JobDefOf.Wait_Combat && !this.pawn.Drafted) { Log.Error(this.pawn + " in eternal WaitCombat without being drafted."); this.ReadyForNextToil(); return; } if ((Find.TickManager.TicksGame + this.pawn.thingIDNumber) % 4 == 0) { //base.CheckForAutoAttack(); } }, defaultCompleteMode = ToilCompleteMode.Never }); }
public static string GetName(JobDriver __instance) { var str = $"{__instance.GetType().Name}"; return(ByPawn ? $"{__instance.pawn.KindLabel} - {str}" : str); }
public void PreStartJob(Job job, JobDriver driver) { if (job != null) { job.ignoreDesignations = true; job.ignoreForbidden = true; } }
public static bool Prefix(JobDriver __instance) { if (TimeControlBase.partialTick < 1.0 && TimeControlSettings.scalePawns && !(__instance is JobDriver_TendPatient) && TimeControlSettings.slowWork) { return(false); } return(true); }
public static bool UpdateRotation(Pawn_RotationTracker __instance) { Pawn pawn = pawnField(__instance); if (pawn.Destroyed || pawn.jobs.HandlingFacing) { return(false); } if (pawn.pather.Moving) { if (pawn.pather.curPath != null && pawn.pather.curPath.NodesLeftCount >= 1) { FaceAdjacentCell2(pawn, pawn.pather.nextCell); } return(false); } Stance_Busy stance_Busy = pawn.stances.curStance as Stance_Busy; if (stance_Busy != null && stance_Busy.focusTarg.IsValid) { if (stance_Busy.focusTarg.HasThing) { __instance.Face(stance_Busy.focusTarg.Thing.DrawPos); } else { __instance.FaceCell(stance_Busy.focusTarg.Cell); } return(false); } Job job = pawn.CurJob; //ADDED if (job != null) //CHANGED { Pawn_JobTracker jobs = pawn.jobs; if (jobs != null) { JobDriver jobDriver = jobs.curDriver; if (jobDriver != null) { LocalTargetInfo target = job.GetTarget(jobDriver.rotateToFace); //CHANGED __instance.FaceTarget(target); } } } if (pawn.Drafted) { pawn.Rotation = Rot4.South; } return(false); }
protected static bool get_HaveCurToil2(JobDriver __instance) { if (curToilIndex(__instance) >= 0 && curToilIndex(__instance) < toils(__instance).Count&& __instance.job != null) { return(__instance.pawn.CurJob == __instance.job); } return(false); }
static void ClearHaulTypeAtFinish(JobDriver __instance) { __instance.AddFinishAction(() => { if (!haulTrackers.TryGetValue(__instance.pawn, out var haulTracker)) { return; } haulTracker.haulType = SpecialHaulType.None; }); }
static void ClearTrackingAfterUnload(JobDriver __instance) { Debug.WriteLine($"{RealTime.frameCount} {__instance.pawn} STARTED UNLOAD."); __instance.AddFinishAction( () => { haulTrackers.Remove(__instance.pawn); Debug.WriteLine($"{RealTime.frameCount} {__instance.pawn} FINISHED UNLOAD. Wiped tracking."); }); }
static void Prefix(JobDriver __instance) { var all = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty; List <Toil> l; Toil t; Job j = __instance.job; if (j == null) { Log.Error("+No Job for " + __instance.pawn.ToString()); return; } Log.Error("+" + __instance.pawn.ToString() + "'s " + j.ToString() + ": Toil: "); var a = typeof(JobDriver) .GetField("toils", all); l = (List <Toil>)a.GetValue(__instance); if (l == null) { Log.Error(" Null Toils list"); return; } int?x; x = (int)typeof(JobDriver) .GetField("curToilIndex", all) .GetValue(__instance); if (x != null) { Log.Warning(" Current toil: " + x + "/" + l.Count); } // Log.Warning(" ++Number toils: " + l.Count); for (int i = 0; i < l.Count; i++) { if (l[i] == null) { Log.Warning(" [" + i + "]: NULL"); } else { Log.Warning(" [" + i + "]: " + l[i].ToString() + " - " + l[i].GetType().ToString()); } } return; }
public static void Postfix_JobDriver_UpgradeTurret_Upgrade(JobDriver __instance, Toil __result) { Action tickAction = __result.tickAction; Pawn pawn = __instance.pawn; __result.tickAction = () => { SurvivalToolUtility.TryDegradeTool(pawn, StatDefOf.ConstructionSpeed); tickAction(); }; }
public static void KeepLyingDown(this JobDriver driver, TargetIndex bedIndex) { driver.AddFinishAction(delegate { Pawn pawn = driver.pawn; if (!pawn.Drafted) { pawn.jobs.jobQueue.EnqueueFirst(new Job(JobDefOf.LayDown, pawn.CurJob.GetTarget(bedIndex))); } }); }
internal void <> m__2() { Pawn actor = this.layDown.actor; JobDriver curDriver = actor.jobs.curDriver; if (actor.mindState.applyBedThoughtsOnLeave) { Toils_LayDown.ApplyBedThoughts(actor); } curDriver.asleep = false; }
public static void JobDriver_PostFix(JobDriver __instance, bool __result) { if (__result) { Action newAction = delegate { StoryHandler.Notify_JobStarted(__instance.job.def, __instance.GetActor()); }; LongEventHandler.ExecuteWhenFinished(newAction); } }
private static bool Prefix(JobDriver __instance, ref bool __result) { Thing item = __instance.job.GetTarget(TargetIndex.A).Thing; if (item != null && Base.IsResearchLocked(item.def)) { __result = false; return(false); } return(true); }
private static bool get_CanStartNextToilInBusyStance2(JobDriver __instance) { int num = curToilIndex(__instance) + 1; if (num >= toils(__instance).Count) { return(false); } return(toils(__instance)[num].atomicWithPrevious); }
static void Main(string[] args) { JobDriver driver = new JobDriver(); driver.DoWork(); }