public static ThinkResult TryIssueJobPackage2(ThinkNode_Priority __instance, Pawn pawn, JobIssueParams jobParams) { int count = __instance.subNodes.Count; for (int index = 0; index < count; ++index) { ThinkResult thinkResult = ThinkResult.NoJob; try { ThinkNode thinkNode = __instance.subNodes[index]; if (thinkNode == null) { return(thinkResult); } thinkResult = thinkNode.TryIssueJobPackage(pawn, jobParams); } catch (Exception ex) { Log.Error("Exception in " + __instance.GetType() + " TryIssueJobPackage: " + ex.ToString()); } if (thinkResult.IsValid) { return(thinkResult); } } return(ThinkResult.NoJob); }
public static void AssignSingleKey(ThinkNode node, int startHash) { Rand.PushState(); Rand.Seed = startHash; node.SetUniqueSaveKey(ThinkTreeKeyAssigner.NextUnusedKey()); Rand.PopState(); }
public static void Start(ThinkNode __instance, MethodBase __originalMethod, ref Profiler __state) { if (p.isActive) { __state = p.Start(__originalMethod.DeclaringType.Name, __originalMethod); } }
public bool TryGetThinkNodeWithSaveKey(int key, out ThinkNode outNode) { outNode = null; bool result; if (key == -1) { result = false; } else if (key == this.thinkRoot.UniqueSaveKey) { outNode = this.thinkRoot; result = true; } else { foreach (ThinkNode thinkNode in this.thinkRoot.ChildrenRecursive) { if (thinkNode.UniqueSaveKey == key) { outNode = thinkNode; return(true); } } result = false; } return(result); }
public static void AssignKeys(ThinkNode rootNode, int startHash) { Rand.PushState(startHash); foreach (ThinkNode item in rootNode.ThisAndChildrenRecursive) { item.SetUniqueSaveKey(NextUnusedKeyFor(item)); } Rand.PopState(); }
public static void AssignKeys(ThinkNode rootNode, int startHash) { Rand.PushState(); Rand.Seed = startHash; foreach (ThinkNode item in rootNode.ThisAndChildrenRecursive) { item.SetUniqueSaveKey(ThinkTreeKeyAssigner.NextUnusedKey()); } Rand.PopState(); }
static IEnumerable <ThinkNode> GetChildren([NotNull] ThinkNode node) { if (node is ThinkNode_SubtreesByTag) { return(Enumerable.Empty <ThinkNode>()); } if (node is ThinkNode_Subtree) { return(Enumerable.Empty <ThinkNode>()); } return(node.subNodes.MakeSafe()); }
private void ResolveParentNodes(ThinkNode node) { for (int i = 0; i < node.subNodes.Count; i++) { if (node.subNodes[i].parent != null) { Log.Warning("Think node " + node.subNodes[i] + " from think tree " + defName + " already has a parent node (" + node.subNodes[i].parent + "). This means that it's referenced by more than one think tree (should have been copied instead)."); continue; } node.subNodes[i].parent = node; ResolveParentNodes(node.subNodes[i]); } }
public static void ReplaceThinkNodeClass(this ThinkNode node, Type oldClass, Type newClass) { if (node.subNodes.NullOrEmpty()) { return; } // Do replacement in this node node.ReplaceSubNodeClass(oldClass, newClass); // Now check nodes subnodes foreach (var subNode in node.subNodes) { subNode.ReplaceThinkNodeClass(oldClass, newClass); } }
static IEnumerable <ThinkNode> GetChildren([NotNull] ThinkNode node) { if (node is ThinkNode_SubtreesByTag sNode) { var allDefs = DefDatabase <ThinkTreeDef> .AllDefs.Where(d => d.insertTag == sNode.insertTag && d.thinkRoot != null); return(allDefs.Select(d => d.thinkRoot)); } if (node is ThinkNode_Subtree) { return(Enumerable.Empty <ThinkNode>()); } return(node.subNodes.MakeSafe()); }
private void ResolveParentNodes(ThinkNode node) { for (int i = 0; i < node.subNodes.Count; i++) { if (node.subNodes[i].parent != null) { Log.Warning(string.Concat("Think node ", node.subNodes[i], " from think tree ", defName, " already has a parent node (", node.subNodes[i].parent, "). This means that it's referenced by more than one think tree (should have been copied instead).")); } else { node.subNodes[i].parent = node; ResolveParentNodes(node.subNodes[i]); } } }
static string GetNodeLabel([NotNull] ThinkNode node) { var tLabel = node.GetType().Name; if (node is ThinkNode_SubtreesByTag streeTag) { return(tLabel + "-" + streeTag.insertTag); } if (node is ThinkNode_Subtree sTree) { var fInfo = typeof(ThinkNode_Subtree).GetField("treeDef", BindingFlags.Instance | BindingFlags.NonPublic); var def = (Def)fInfo.GetValue(sTree); return(tLabel + "-" + def.defName); } return(tLabel); }
private ThinkNode HighestPriorityNode(Pawn pawn) { if (matchedTrees.NullOrEmpty()) { return(null); } var priority = 0.0f; ThinkNode node = null; for (var index = 0; index < matchedTrees.Count; ++index) { var nodePriority = matchedTrees[index].thinkRoot.GetPriority(pawn); if (nodePriority > priority) { priority = nodePriority; node = matchedTrees[index].thinkRoot; } } return(node); }
public static void ReplaceSubNodeClass(this ThinkNode node, Type oldClass, Type newClass) { if (node.subNodes.NullOrEmpty()) { return; } for (int i = node.subNodes.Count - 1; i >= 0; --i) { var subNode = node.subNodes[i]; if (subNode.GetType() == oldClass) { // Remove old node node.subNodes.Remove(subNode); // Create new node subNode = (ThinkNode)Activator.CreateInstance(newClass); // Place new node in same place as old node node.subNodes.Insert(i, subNode); } } }
static bool Prefix(ref Pawn_JobTracker_Crutch __instance, Job newJob, JobCondition lastJobEndCondition, ThinkNode jobGiver, bool resumeCurJobAfterwards, bool cancelBusyStances, ThinkTreeDef thinkTree, JobTag?tag, bool fromQueue) { if (__instance == null || __instance._pawn == null || newJob == null || newJob.def == null) { return(true); } if (Settings.fun_police && __instance._pawn.needs.joy != null && __instance._pawn.needs.joy.CurLevel < 0.8f) { CompJoyToppedOff c = __instance._pawn.TryGetComp <CompJoyToppedOff>(); if (c != null) { c.JoyToppedOff = false; } } if (!Settings.clean_before_work && !Settings.hauling_over_bills) { return(true); } if (!newJob.def.allowOpportunisticPrefix) { return(true); } Job job = null; if (newJob.def == JobDefOf.DoBill) { if (Settings.hauling_over_bills) { job = Hauling_Opportunity(newJob, __instance._pawn); } } else if (!newJob.playerForced && newJob.targetA != null && newJob.targetA.Cell != null) { IntVec3 cell = newJob.targetA.Cell; if (!cell.IsValid || cell.IsForbidden(__instance._pawn) || __instance._pawn.Downed) { return(true); } if (Settings.clean_before_work && (newJob.targetA.Thing != null && newJob.targetA.Thing.GetType().IsSubclassOf(typeof(Building)) || newJob.def.joyKind != null)) { job = Cleaning_Opportunity(newJob, cell, __instance._pawn, 20); } } if (job != null) { if (Settings.add_to_que) { __instance.jobQueue.EnqueueFirst(newJob); } __instance.jobQueue.EnqueueFirst(job); __instance.curJob = null; __instance.curDriver = null; return(false); } return(true); }
public static void AssignSingleKey(ThinkNode node, int startHash) { Rand.PushState(startHash); node.SetUniqueSaveKey(NextUnusedKeyFor(node)); Rand.PopState(); }
protected override void ResolveSubnodes() { subtreeNode = treeDef.thinkRoot.DeepCopy(); subNodes.Add(subtreeNode); }
private void InjectDehydrationThink(ThinkNode colonistTree) { bool failed = true; var dehydrationThink = DefDatabase<ThinkTreeDef>.GetNamed(defnameGetWater); if (dehydrationThink != null) { // Inject into the colonist tree, more important than food. int starvingIndex = colonistTree.subNodes.FindIndex(node => node is ThinkNode_ConditionalStarving); if (starvingIndex != -1) { colonistTree.subNodes.Insert(starvingIndex, dehydrationThink.thinkRoot); Log.Message(string.Format("Dehydration injected {0}", defnameGetWater)); failed = false; } } if (failed) { Log.Error(string.Format("Dehydration can't inject {0}", defnameGetWater)); } }
private void InjectExitMapOnThirsty(ThinkNode parent) { bool failed = true; var exitThink = DefDatabase<ThinkTreeDef>.GetNamed(defnameExitMapThirsty); if (exitThink != null) { parent.subNodes.Insert(0, new ThinkNode_Subtree() {treeDef = exitThink}); Log.Message(string.Format("Dehydration injected {0}", defnameExitMapThirsty)); failed = false; } else { Log.Error("No exit map think."); } if (failed) { Log.Error(string.Format("Dehydration can't inject {0}", defnameExitMapThirsty)); } }
private void InjectPackWaterThink(ThinkNode colonistTree) { bool failed = true; var packThink = DefDatabase<ThinkTreeDef>.GetNamed(defnamePackWater); if (packThink != null) { int packFoodIndex = colonistTree.subNodes.FindIndex(node => node is ThinkNode_ConditionalNeedAbove && node.subNodes.Exists(subnode => subnode is JobGiver_PackFood)); if (packFoodIndex != -1) { colonistTree.subNodes.Insert(packFoodIndex, packThink.thinkRoot); Log.Message(string.Format("Dehydration injected {0}", defnamePackWater)); failed = false; } } if (failed) { Log.Error(string.Format("Dehydration can't inject {0}", defnamePackWater)); } }
private void InjectGetWaterThink(ThinkNode mainBehaviours) { bool failed = true; var drinkThink = DefDatabase<ThinkTreeDef>.GetNamed(defnameGetWater); if (drinkThink != null) { int foodIndex = mainBehaviours.subNodes.FindIndex(node => node is JobGiver_GetFood); if (foodIndex != -1) { mainBehaviours.subNodes.Insert(foodIndex, drinkThink.thinkRoot.subNodes[0]); Log.Message(string.Format("Dehydration injected {0}", defnameGetWater)); failed = false; } else { Log.Error("No foodIndex"); } } else { Log.Error("No drinkThink"); } if (failed) { Log.Error(string.Format("Dehydration can't inject {0}", defnameGetWater)); } }
public static bool StartJob(Pawn_JobTracker __instance, Job newJob, JobCondition lastJobEndCondition = JobCondition.None, ThinkNode jobGiver = null, bool resumeCurJobAfterwards = false, bool cancelBusyStances = true, ThinkTreeDef thinkTree = null, JobTag?tag = null, bool fromQueue = false, bool canReturnCurJobToPool = false) { __instance.startingNewJob = true; try { if (!fromQueue && (!Find.TickManager.Paused || __instance.lastJobGivenAtFrame == RealTime.frameCount)) { ++__instance.jobsGivenThisTick; if (Prefs.DevMode) { __instance.jobsGivenThisTickTextual = __instance.jobsGivenThisTickTextual + "(" + newJob.ToString() + ") "; } } __instance.lastJobGivenAtFrame = RealTime.frameCount; if (__instance.jobsGivenThisTick > 10) { string givenThisTickTextual = __instance.jobsGivenThisTickTextual; __instance.jobsGivenThisTick = 0; __instance.jobsGivenThisTickTextual = ""; __instance.startingNewJob = false; __instance.pawn.ClearReservationsForJob(newJob); JobUtility.TryStartErrorRecoverJob(__instance.pawn, __instance.pawn.ToStringSafe <Pawn>() + " started 10 jobs in one tick. newJob=" + newJob.ToStringSafe <Job>() + " jobGiver=" + jobGiver.ToStringSafe <ThinkNode>() + " jobList=" + givenThisTickTextual); } else { if (__instance.debugLog) { __instance.DebugLogEvent("StartJob [" + (object)newJob + "] lastJobEndCondition=" + (object)lastJobEndCondition + ", jobGiver=" + (object)jobGiver + ", cancelBusyStances=" + cancelBusyStances.ToString()); } Pawn_StanceTracker stances = __instance.pawn.stances; //changed if (cancelBusyStances && stances != null && stances.FullBodyBusy) //changed { stances.CancelBusyStanceHard(); } if (__instance.curJob != null) { if (lastJobEndCondition == JobCondition.None) { Log.Warning(__instance.pawn.ToString() + " starting job " + (object)newJob + " from JobGiver " + (object)newJob.jobGiver + " while already having job " + (object)__instance.curJob + " without a specific job end condition."); lastJobEndCondition = JobCondition.InterruptForced; } if (resumeCurJobAfterwards && __instance.curJob.def.suspendable) { __instance.jobQueue.EnqueueFirst(__instance.curJob); if (__instance.debugLog) { __instance.DebugLogEvent(" JobQueue EnqueueFirst curJob: " + (object)__instance.curJob); } __instance.CleanupCurrentJob(lastJobEndCondition, false, cancelBusyStances); } else { __instance.CleanupCurrentJob(lastJobEndCondition, true, cancelBusyStances, canReturnCurJobToPool); } } if (newJob == null) { Log.Warning(__instance.pawn.ToString() + " tried to start doing a null job."); } else { newJob.startTick = Find.TickManager.TicksGame; if (__instance.pawn.Drafted || newJob.playerForced) { newJob.ignoreForbidden = true; newJob.ignoreDesignations = true; } __instance.curJob = newJob; __instance.curJob.jobGiverThinkTree = thinkTree; __instance.curJob.jobGiver = jobGiver; JobDriver cDriver = __instance.curJob.MakeDriver(__instance.pawn); //changed __instance.curDriver = cDriver; //changed bool flag = fromQueue; if (__instance.curDriver.TryMakePreToilReservations(!flag)) { Job newJob1 = __instance.TryOpportunisticJob(newJob); if (newJob1 != null) { __instance.jobQueue.EnqueueFirst(newJob); __instance.curJob = (Job)null; __instance.curDriver = (JobDriver)null; __instance.StartJob(newJob1); } else { if (tag.HasValue) { __instance.pawn.mindState.lastJobTag = tag.Value; } cDriver.SetInitialPosture(); //changed cDriver.Notify_Starting(); //changed cDriver.SetupToils(); //changed cDriver.ReadyForNextToil(); //changed } } else if (flag) { __instance.EndCurrentJob(JobCondition.QueuedNoLongerValid); } else { Log.Warning("TryMakePreToilReservations() returned false for a non-queued job right after StartJob(). This should have been checked before. curJob=" + __instance.curJob.ToStringSafe <Job>()); __instance.EndCurrentJob(JobCondition.Errored); } } } } finally { __instance.startingNewJob = false; } return(false); }
static bool Prefix(ref Pawn_JobTracker_Crutch __instance, Job newJob, JobCondition lastJobEndCondition, ThinkNode jobGiver, bool resumeCurJobAfterwards, bool cancelBusyStances, ThinkTreeDef thinkTree, JobTag?tag, bool fromQueue) { try { if (__instance == null || __instance._pawn == null || !__instance._pawn.IsColonistPlayerControlled || newJob == null || newJob.def == null) { return(true); } if (Settings.fun_police && __instance._pawn.needs.joy != null && __instance._pawn.needs.joy.CurLevel < 0.8f) { CompJoyToppedOff c = __instance._pawn.TryGetComp <CompJoyToppedOff>(); if (c != null) { c.JoyToppedOff = false; } } if (!Settings.clean_before_work && !Settings.hauling_over_bills) { return(true); } if (!newJob.def.allowOpportunisticPrefix) { return(true); } Job job = null; if (newJob.def == JobDefOf.DoBill) { if (Settings.hauling_over_bills) { job = Hauling_Opportunity(newJob, __instance._pawn); } } else if (!newJob.playerForced && newJob.targetA != null && newJob.targetA.Cell != null) { IntVec3 cell = newJob.targetA.Cell; if (!cell.IsValid || cell.IsForbidden(__instance._pawn) || __instance._pawn.Downed) { return(true); } if (Settings.clean_before_work && (newJob.targetA.Thing != null && newJob.targetA.Thing.GetType().IsSubclassOf(typeof(Building)) && newJob.def != JobDefOf.PlaceNoCostFrame && newJob.def != JobDefOf.FinishFrame || newJob.def.joyKind != null) && !HealthAIUtility.ShouldBeTendedNowByPlayer(__instance._pawn)) { job = Cleaning_Opportunity(newJob, cell, __instance._pawn, Settings.op_clean_num); } } //Log.Message($"pawn={__instance._pawn},job={newJob},enque={job}, limit = {Settings.op_clean_num}"); if (job != null) { if (Settings.add_to_que) { newJob.playerForced = true; __instance.jobQueue.EnqueueFirst(newJob); } __instance.jobQueue.EnqueueFirst(job); //__instance.curJob = null; //__instance.curDriver = null; return(false); } } catch (Exception e) { Log.Error($"CommonSense: opportunistic task skipped due to error ({e.Message})"); } return(true); }