private void DrawMorphInfluenceList(ref Vector2 curPos, float width) { // Set up the mutation tracker. MutationTracker mutationTracker = PawnToShowMutationsFor.GetMutationTracker(); if (mutationTracker == null) { return; } // Create a list of the current morph influences upon the pawn. var influences = mutationTracker.ToList(); // Determine the remaining human influence. float humInf = MorphUtilities.GetMaxInfluenceOfRace(PawnToShowMutationsFor.def); foreach (var influence in influences) { humInf -= influence.Value; } var maxRaceInfluence = MorphUtilities.GetMaxInfluenceOfRace(PawnToShowMutationsFor.def); // If the remaining human influence is greater than 0.0001, print its influence first. // (0.0001 is used to compensate for floating point number's occasional lack of precision.) if (humInf > EPSILON) { GUI.color = Color.green; string text = $"Human ({(humInf/maxRaceInfluence).ToStringPercent()})"; float rectHeight = Text.CalcHeight(text, width); Widgets.Label(new Rect(curPos.x, curPos.y, width, rectHeight), text); curPos.y += rectHeight; GUI.color = Color.white; } if (influences.Count == 0) { return; } float maxInfluence = influences.MaxBy(x => x.Value).Value; // List the morph influences upon the pawn in descending order. foreach (var influence in influences.OrderByDescending(x => x.Value)) { // Set the greatest influence's color to cyan if (Math.Abs(influence.Value - maxInfluence) < EPSILON) { GUI.color = Color.cyan; } var nVal = influence.Value / maxRaceInfluence; string text = $"{influence.Key.LabelCap} ({nVal.ToStringPercent()})"; float rectHeight = Text.CalcHeight(text, width); Widgets.Label(new Rect(curPos.x, curPos.y, width, rectHeight), text); curPos.y += rectHeight; GUI.color = Color.white; } }
/// <summary> /// Recalculates the mutation influences if needed. /// </summary> public void RecalcIfNeeded() { int counter = 0; foreach (Hediff hediff in Pawn.health.hediffSet.hediffs) { if (hediff is Hediff_AddedMutation) { counter++; } } if (counter != MutationsCount) { Log.Warning($"{Pawn.Name} mutation tracker has only {MutationsCount} tracked mutations but pawn actually has {counter}"); RecalculateMutationInfluences(); return; } bool anyNegative = false; float totalInfluence = 0; foreach (KeyValuePair <AnimalClassBase, float> keyValuePair in _influenceDict) { if (keyValuePair.Value < 0) { anyNegative = true; } totalInfluence += keyValuePair.Value; } var maxInfluence = MorphUtilities.GetMaxInfluenceOfRace(parent.def); if (anyNegative) { Log.Warning($"{Pawn.Name} has negative mutation influence"); RecalculateMutationInfluences(); } if (Mathf.Abs(totalInfluence - TotalInfluence) > EPSILON) { Log.Warning($"{Pawn.Name} mutation tracker total is incorrect calculated:{totalInfluence} vs cached:{TotalInfluence}"); RecalculateMutationInfluences(); } else if (totalInfluence > maxInfluence) { Log.Warning($"{Pawn.Name} mutation tracker total is incorrect calculated:{totalInfluence} greater then max:{maxInfluence}"); RecalculateMutationInfluences(); } }
protected override void FillTab() { // Set up the rects. Rect rect = new Rect(0f, 10f, mainSize.x, mainSize.y); Rect mainView = rect.ContractedBy(10f); Rect logView = new Rect(rect.x + rect.width, rect.y, LOG_WIDTH, rect.height).ContractedBy(10f); // No idea what this does, but it sounds important. GUI.BeginGroup(mainView); // Set the defualts, in case they weren't properly reset elsewhere. Text.Font = GameFont.Small; Text.Anchor = TextAnchor.UpperLeft; GUI.color = Color.white; // Draw the header. Vector2 col1 = new Vector2(0f, 0f); if (SelPawn.GetMutationTracker(false) != null) { DrawMutTabHeader(ref col1, mainView.width); } // Set up scrolling area. Rect outRect = new Rect(col1.x, col1.y, mainView.width, mainView.height - col1.y - 10f); Rect viewRect = new Rect(col1.x, col1.y, mainView.width - 16f, mainScrollViewHeight - col1.y); Widgets.BeginScrollView(outRect, ref mainScrollPosition, viewRect, true); // Set up referance variables for the other two column's current xy position. Vector2 col2 = new Vector2(viewRect.width / 3, col1.y); Vector2 col3 = new Vector2(viewRect.width / 3 * 2, col2.y); float colWidth = viewRect.width / 3 - 10f; // Draw the headers for all three columns (labels are provided by the xml). DrawColumnHeader(ref col1, colWidth, "MorphsITabHeader".Translate()); DrawColumnHeader(ref col2, colWidth, "TraitsITabHeader".Translate()); DrawColumnHeader(ref col3, colWidth, "ProductionITabHeader".Translate()); // Draw the content of the columns. if (MorphUtilities.HybridsAreEnabledFor(PawnToShowMutationsFor.def)) { DrawMorphInfluenceList(ref col1, colWidth); } DrawMorphTraitsList(ref col2, colWidth); DrawMorphProductionList(ref col3, colWidth); // Set the scroll view height if (Event.current.type == EventType.Layout) { mainScrollViewHeight = Math.Max(col1.y, Math.Max(col2.y, col3.y)); } Widgets.EndScrollView(); // Ya, this thing is important for some reason, but IDK why. GUI.EndGroup(); // Boolean to dynamically resize the iTab and draw the log's content if necessary. if (toggleLog) { size.x = mainSize.x + LOG_WIDTH; DrawMutationLog(logView); } else { size.x = mainSize.x; } // Make sure everything was reset properly. Text.Font = GameFont.Small; Text.Anchor = TextAnchor.UpperLeft; GUI.color = Color.white; }