static void Postfix(SGBarracksMWDetailPanel __instance, Pilot p, SGBarracksAdvancementPanel ___advancement, GameObject ___advancementSectionGO, SGBarracksDossierPanel ___dossier, SGBarracksServicePanel ___servicePanel, GameObject ___serviceSectionGO, HBSDOTweenButton ___customizeButton) { if (p == null) { return; } CrewDetails details = ModState.GetCrewDetails(p.pilotDef); GameObject skillsButton = __instance.gameObject.FindFirstChildNamed(ModConsts.GO_HBS_Barracks_Skill_Button); if (skillsButton == null) { Mod.Log.Debug?.Write("SkillsButton is null!"); } if (details.IsMechTechCrew || details.IsMedTechCrew || details.IsAerospaceCrew) { __instance.OnServiceSectionClicked(); skillsButton.SetActive(false); } else { skillsButton.SetActive(true); } }
static void Postfix(AAR_ContractObjectivesWidget __instance, Contract ___theContract) { try { List <Pilot> deployedPilots = ___theContract.PlayerUnitResults.Select(ur => ur.pilot).ToList(); int hazardPaySum = 0; foreach (Pilot p in deployedPilots) { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); hazardPaySum -= details.HazardPay; } Mod.Log.Debug?.Write($"Total hazard pay for mission is: {hazardPaySum}"); string hazardPayTitleS = new Text(Mod.LocalizedText.Labels[ModText.LT_Contract_Hazard_Pay], new object[] { SimGameState.GetCBillString(hazardPaySum) }).ToString(); string guid = Guid.NewGuid().ToString(); MissionObjectiveResult hazardPayObjective = new MissionObjectiveResult(hazardPayTitleS, guid, false, true, ObjectiveStatus.Succeeded, false); Traverse addObjective = Traverse.Create(__instance).Method("AddObjective", new Type[] { typeof(MissionObjectiveResult) }); addObjective.GetValue(new object[] { hazardPayObjective }); } catch (Exception e) { Mod.Log.Warn?.Write(e, "Failed to build hazard pay for contract!"); } }
static void Postfix(SimGameState __instance, Pilot pilot, ref bool __result) { int currentMRBLevel = __instance.GetCurrentMRBLevel(); CrewDetails details = ModState.GetCrewDetails(pilot.pilotDef); __result = details.CanBeHiredAtMRBLevel(currentMRBLevel); }
public static void Postfix(SimGameState __instance, ref int __result, EconomyScale expenditureLevel, bool proRate) { Mod.Log.Trace?.Write($"SGS:GE entered with {__result}"); // Evaluate old versus new cost int vanillaCosts = 0; int newCosts = 0; for (int i = 0; i < __instance.PilotRoster.Count; i++) { PilotDef def = __instance.PilotRoster[i].pilotDef; vanillaCosts += __instance.GetMechWarriorValue(def); CrewDetails details = ModState.GetCrewDetails(def); newCosts += details.AdjustedSalary; } // Multiply old costs by expenditure. New has that built in. Then subtract them from the running total float expenditureCostModifier = __instance.GetExpenditureCostModifier(expenditureLevel); int vanillaTotal = Mathf.CeilToInt((float)vanillaCosts * expenditureCostModifier); Mod.Log.Trace?.Write($"Removing {vanillaCosts} costs x {expenditureCostModifier} expenditureMulti " + $"= {vanillaTotal} total vanilla costs."); __result -= vanillaTotal; // Add the new costs __result += newCosts; }
static void Postfix(SG_HiringHall_Screen __instance, Pilot ___selectedPilot, LocalizableText ___MWInitialCostText, UIColorRefTracker ___MWCostColor, HBSDOTweenButton ___HireButton) { Mod.Log.Debug?.Write("Updating UpdateMoneySpot"); if (___selectedPilot != null) { Mod.Log.Debug?.Write(" -- pilot is selected"); // Account for the salary CrewDetails details = ModState.GetCrewDetails(___selectedPilot.pilotDef); int modifiedBonus = (int)Mathf.RoundToInt(details.AdjustedBonus); string bonus = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Bonus_Label], new string[] { SimGameState.GetCBillString(Mathf.RoundToInt(modifiedBonus)) }) .ToString(); Mod.Log.Debug?.Write($" -- bonus will be: {bonus}"); ___MWInitialCostText.SetText(bonus); if (modifiedBonus > ModState.SimGameState.Funds) { Mod.Log.Debug?.Write(" -- Disabling hire."); ___MWCostColor.SetUIColor(UIColor.Red); ___HireButton.SetState(ButtonState.Disabled); } else { Mod.Log.Debug?.Write(" -- Enabling hire."); ___MWCostColor.SetUIColor(UIColor.White); ___HireButton.SetState(ButtonState.Enabled); } } }
static bool Prefix(SG_HiringHall_Screen __instance, Pilot ___selectedPilot, string button) { Mod.Log.Debug?.Write("Updating Dialog"); if (___selectedPilot != null && "Hire".Equals(button, StringComparison.InvariantCultureIgnoreCase) && __instance.HireButtonValid()) { Mod.Log.Debug?.Write(" -- pilot is selected"); CrewDetails details = ModState.GetCrewDetails(___selectedPilot.pilotDef); int modifiedBonus = (int)Mathf.RoundToInt(details.AdjustedBonus); string salaryS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Hire_Button], new string[] { SimGameState.GetCBillString(Mathf.RoundToInt(modifiedBonus)) }) .ToString(); Mod.Log.Debug?.Write($" -- bonus will be: {salaryS}"); GenericPopupBuilder.Create("Confirm?", salaryS) .AddButton("Cancel") .AddButton("Accept", __instance.HireCurrentPilot) .CancelOnEscape() .AddFader(LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.PopupBackfill) .Render(); return(false); } return(true); }
static bool Prefix(SimGameState __instance, PilotDef def, ref int __result) { CrewDetails details = ModState.GetCrewDetails(def); __result = details != null ? details.Salary : 0; return(false); }
static List <Pilot> AllMechWarriors() { List <Pilot> allPilots = ModState.SimGameState.PilotRoster.ToList(); return(allPilots.Where((p) => { CrewDetails cd = ModState.GetCrewDetails(p.pilotDef); return cd.IsMechWarrior; }).ToList()); }
public static int UsedBerths(IEnumerable <Pilot> pilots) { int used = 0; foreach (Pilot pilot in pilots) { CrewDetails details = ModState.GetCrewDetails(pilot.pilotDef); used += details.Size; } return(used); }
static void Postfix(SimGameState __instance, int timeLapse, SimGameInterruptManager ___interruptQueue, SimGameEventTracker ___companyEventTracker, SimGameEventTracker ___mechWarriorEventTracker, SimGameEventTracker ___deadEventTracker, SimGameEventTracker ___moraleEventTracker) { Mod.Log.Debug?.Write($"OnDayPassed called with timeLapse: {timeLapse}"); // Only check for events if another event isn't firing, and we're in orbit around a system if (!___interruptQueue.IsOpen && __instance.TravelState == SimGameTravelStatus.IN_SYSTEM) { foreach (Pilot pilot in __instance.PilotRoster) { CrewDetails details = ModState.GetCrewDetails(pilot.pilotDef); if (details.ExpirationDay <= __instance.DaysPassed) { Mod.Log.Debug?.Write($"CONTRACT FOR PILOT: {pilot.Name} HAS ELAPSED, FIRING EVENT"); ModState.ExpiredContracts.Enqueue((pilot, details)); } } if (ModState.ExpiredContracts.Count > 0) { // Fire the first event, if there are more they will be fired from OnEventDismissed{ Mod.Log.Info?.Write($"Contract expiration event fired."); (Pilot Pilot, CrewDetails Details)expired = ModState.ExpiredContracts.Peek(); SimGameEventDef newEvent = EventHelper.ModifyContractExpirationEventForPilot(expired.Pilot, expired.Details); ModState.SimGameState.OnEventTriggered(newEvent, EventScope.MechWarrior, ___mechWarriorEventTracker); } else if (Mod.Config.HeadHunting.Enabled && __instance.TravelState == SimGameTravelStatus.IN_SYSTEM) { // TODO: Only do check if not at planet with blacklisted tags if (HeadHuntingHelper.ShouldCheckHeadHunting()) { Pilot headHuntedCrew = HeadHuntingHelper.TestAllCrews(); if (headHuntedCrew != null) { CrewDetails cd = ModState.GetCrewDetails(headHuntedCrew.pilotDef); SimGameEventDef newEvent = EventHelper.CreateHeadHuntingEvent(headHuntedCrew, cd, cd.HiringBonus, cd.HiringBonus); ModState.HeadHuntedPilot = headHuntedCrew; ModState.SimGameState.OnEventTriggered(newEvent, EventScope.MechWarrior, ___mechWarriorEventTracker); HeadHuntingHelper.UpdateNextDayOnSuccess(); } else { HeadHuntingHelper.UpdateNextDayOnFailure(); } } } } }
static bool Prefix(SimGameState __instance, PilotDef def, ref string __result) { string salaryLabel = "------"; if (!def.IsFree) { CrewDetails details = ModState.GetCrewDetails(def); string cbillString = SimGameState.GetCBillString(Mathf.RoundToInt(details.AdjustedSalary)); salaryLabel = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Salary_Label], new object[] { cbillString }) .ToString(); } __result = salaryLabel; return(false); }
// This is stupidly slow, but because the way the weighted works it's not easy to get a list of the // remaining elements. So we (unfortunately) iterate through the pilots until we find a mechwarrior. static Pilot NextSGSMechwarrior() { //___sim.PilotRoster.GetNext(true); Pilot mechWarrior = null; while (mechWarrior == null) { Pilot pilot = ModState.SimGameState.PilotRoster.GetNext(true); CrewDetails cd = ModState.GetCrewDetails(pilot.pilotDef); if (cd.IsMechWarrior) { mechWarrior = pilot; } } return(mechWarrior); }
static void Postfix(SG_HiringHall_MWSelectedPanel __instance, Pilot p, LocalizableText ___BaseSalaryText) { if (p != null && ___BaseSalaryText != null) { Mod.Log.Debug?.Write($"Updating MWSelectedPanel for pilot: {p.Name}"); // Account for the salary CrewDetails details = ModState.GetCrewDetails(p.pilotDef); int modifiedSalary = (int)Mathf.RoundToInt(details.AdjustedSalary); string modifiedSalaryS = SimGameState.GetCBillString(modifiedSalary); Mod.Log.Debug?.Write($" -- salary will be: {modifiedSalaryS}"); string salaryS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Salary_Label], new string[] { modifiedSalaryS }) .ToString(); ___BaseSalaryText.SetText(salaryS); } }
static void Postfix(SG_HiringHall_DetailPanel __instance, Pilot p, LocalizableText ___DescriptionText) { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); StringBuilder sb = new StringBuilder(); // Check hazard pay if (details.HazardPay > 0) { string hazardPayS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Hazard_Pay], new object[] { SimGameState.GetCBillString(details.HazardPay) }).ToString(); Mod.Log.Debug?.Write($"Hazard pay is: {hazardPayS}"); sb.Append(hazardPayS); sb.Append("\n\n"); } // Convert favored and hated faction if (details.FavoredFactionId > 0) { FactionValue faction = FactionEnumeration.GetFactionByID(details.FavoredFactionId); string favoredFactionS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Biography_Faction_Favored], new object[] { faction.FactionDef.CapitalizedName }).ToString(); sb.Append(favoredFactionS); sb.Append("\n\n"); Mod.Log.Debug?.Write($" Favored Faction is: {favoredFactionS}"); //Mod.Log.Debug?.Write($" Favored Faction => name: '{faction.Name}' friendlyName: '{faction.FriendlyName}' " + // $"factionDef.Name: {faction.FactionDef?.Name} factionDef.CapitalizedName: {faction.FactionDef.CapitalizedName} " + // $"factionDef.ShortName: {faction.FactionDef?.ShortName} factionDef.CapitalizedShortName: {faction.FactionDef.CapitalizedShortName} " + // $""); } if (details.HatedFactionId > 0) { FactionValue faction = FactionEnumeration.GetFactionByID(details.HatedFactionId); string hatedFactionS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Biography_Faction_Hated], new object[] { faction.FactionDef.CapitalizedName }).ToString(); sb.Append(hatedFactionS); sb.Append("\n\n"); Mod.Log.Debug?.Write($" Hated Faction is: {hatedFactionS}"); } sb.Append(Interpolator.Interpolate(p.pilotDef.Description.GetLocalizedDetails().ToString(true), ModState.SimGameState.Context, true)); ___DescriptionText.SetText(sb.ToString()); }
static void Postfix(SG_HiringHall_Screen __instance, GameObject ___WarningAreaObject, HBSDOTweenButton ___HireButton, LocalizableText ___WarningText, HBSTooltip ___NoHireTooltip, Pilot ___selectedPilot) { Mod.Log.Debug?.Write("Updating MWSelectedPanel:WarningsCheck"); // Use the warnings area to display the contract length terms if (___selectedPilot != null && ___HireButton.State == ButtonState.Enabled) { ___WarningAreaObject.SetActive(true); CrewDetails details = ModState.GetCrewDetails(___selectedPilot.pilotDef); string contractTermS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Contract_Term], new object[] { details.ContractTerm } ).ToString(); ___WarningText.SetText(contractTermS); } }
static void Postfix(SGBarracksMWDetailPanel __instance, Pilot ___curPilot, SGBarracksAdvancementPanel ___advancement, GameObject ___advancementSectionGO, SGBarracksDossierPanel ___dossier, SGBarracksServicePanel ___servicePanel, GameObject ___serviceSectionGO, HBSDOTweenButton ___customizeButton) { if (___curPilot == null) { return; } CrewDetails details = ModState.GetCrewDetails(___curPilot.pilotDef); if (details.IsMechTechCrew || details.IsMedTechCrew || details.IsAerospaceCrew) { ___advancementSectionGO.SetActive(false); } }
static void Postfix(Contract __instance) { try { List <Pilot> deployedPilots = __instance.PlayerUnitResults.Select(ur => ur.pilot).ToList(); int hazardPaySum = 0; foreach (Pilot p in deployedPilots) { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); hazardPaySum -= details.HazardPay; } Mod.Log.Debug?.Write($"Total hazard pay for contract is: {hazardPaySum}"); int newResult = Mathf.FloorToInt(__instance.MoneyResults - hazardPaySum); Traverse.Create(__instance).Property("MoneyResults").SetValue(newResult); } catch (Exception e) { Mod.Log.Error?.Write(e, "Failed to add hazard pay costs to contract"); } }
static void Prefix(LanceConfiguratorPanel __instance, ref List <Pilot> pilots) { if (ModState.SimGameState == null) { return; // Only patch if we're in SimGame } // Remove any pilots who are aerospace, mechtechs, or medtechs Mod.Log.Debug?.Write("Filtering pilots for LanceConfiguratorPanel"); List <Pilot> selectablePilots = new List <Pilot>(); foreach (Pilot p in pilots) { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); if (details.IsMechWarrior || details.IsVehicleCrew) { Mod.Log.Debug?.Write($"Pilot {p.Name} is a mechwarrior or vehicle crew, adding as option"); selectablePilots.Add(p); } } pilots.Clear(); pilots.AddRange(selectablePilots); }
public static Pilot TestAllCrews() { // Determine our headhunting roll float randomRoll = (float)Mod.Random.NextDouble(); float econMod = Mod.Config.HeadHunting.EconMods[(int)ModState.SimGameState.ExpenditureLevel + 2]; float modifiedRoll = randomRoll + econMod; Mod.Log.Info?.Write($"HeadHunting roll: {modifiedRoll} = randomRoll: {randomRoll} + econMod: {econMod}"); if (econMod >= 100 || econMod <= 0) { Mod.Log.Info?.Write($" outside 0-100 bounds, failing roll."); return(null); } // Determine a random order for the list List <Pilot> pilots = ModState.SimGameState.PilotRoster.ToList(); pilots.Shuffle <Pilot>(); Pilot headHuntedPilot = null; foreach (Pilot pilot in pilots) { CrewDetails cd = ModState.GetCrewDetails(pilot.pilotDef); Mod.Log.Debug?.Write($"Checking pilot: {pilot.Name} for poaching for expertise: {cd.Expertise}"); float crewChance = Mod.Config.HeadHunting.ChanceBySkill[cd.Expertise]; Mod.Log.Debug?.Write($" -- chance for crew: {crewChance} vs. modifiedRoll: {modifiedRoll}"); if (crewChance <= modifiedRoll) { Mod.Log.Info?.Write($"Pilot: {pilot.Name} should be headhunted."); headHuntedPilot = pilot; break; } } return(headHuntedPilot); }
static bool Prefix(SGBarracksRosterList __instance, Pilot pilot, UnityAction <SGBarracksRosterSlot> pilotSelectedOnClick, bool isInHireHall, Dictionary <string, SGBarracksRosterSlot> ___currentRoster) { if (ModState.SimGameState == null) { return(true); // Only patch if we're in SimGame } Mod.Log.Debug?.Write($"Adding pilot {pilot.Callsign} to roster list."); if (!___currentRoster.ContainsKey(pilot.GUID)) { SGBarracksRosterSlot slot = __instance.GetSlot(); if (isInHireHall) { slot.InitNoDrag(pilot, ModState.SimGameState, pilotSelectedOnClick, showTheCost: true); slot.SetDraggable(isDraggable: false); // Update the pilot's contract end date CrewDetails details = ModState.GetCrewDetails(pilot.pilotDef); details.ExpirationDay = ModState.SimGameState.DaysPassed + details.ContractTerm; Mod.Log.Debug?.Write($" - pilot's contract ends on day: {details.ExpirationDay}"); ModState.UpdateOrCreateCrewDetails(pilot.pilotDef, details); } else { slot.Init(pilot, __instance, pilotSelectedOnClick); } ___currentRoster.Add(pilot.GUID, slot); slot.AddToRadioSet(__instance.listRadioSet); // Performance tweak; skip //ForceRefreshImmediate(); } return(false); }
static void Postfix(SGBarracksRosterSlot __instance, Pilot ___pilot, GameObject ___AbilitiesObject, LocalizableText ___callsign, Image ___portrait, SVGImage ___roninIcon, SVGImage ___veteranIcon, LocalizableText ___expertise, HBSTooltip ___ExpertiseTooltip) { if (ModState.SimGameState == null) { return; // Only patch if we're in SimGame } if (___pilot == null) { return; } Mod.Log.Debug?.Write($"POST Calling refresh for pilot: {___pilot.Name}"); CrewDetails details = ModState.GetCrewDetails(___pilot.pilotDef); // Find the common GameObjects we need to manipulate GameObject portraitOverride = GetOrCreateProfileOverride(___portrait); if (details.IsAerospaceCrew || details.IsMechTechCrew || details.IsMedTechCrew || details.IsVehicleCrew) { portraitOverride.SetActive(true); } else { portraitOverride.SetActive(false); } GameObject crewBlock = GetOrCreateCrewBlock(___portrait.gameObject); if (details.IsAerospaceCrew || details.IsMechTechCrew || details.IsMedTechCrew) { crewBlock.SetActive(true); } else { crewBlock.SetActive(false); } GameObject mwStats = ___portrait.transform.parent.parent.gameObject.FindFirstChildNamed(ModConsts.GO_HBS_Profile_Stats_Block); if (details.IsAerospaceCrew || details.IsMechTechCrew || details.IsMedTechCrew) { mwStats.SetActive(false); } else { mwStats.SetActive(true); } GameObject layoutTitleGO = __instance.GameObject.FindFirstChildNamed(ModConsts.GO_HBS_Profile_Layout_Title); Image layoutTitleImg = layoutTitleGO.GetComponent <Image>(); if (details.IsAerospaceCrew) { Mod.Log.Debug?.Write($" -- pilot is Aerospace crew"); layoutTitleImg.color = Mod.Config.Crew.AerospaceColor; ___portrait.gameObject.SetActive(false); ___AbilitiesObject.SetActive(false); ___roninIcon.gameObject.SetActive(false); ___veteranIcon.gameObject.SetActive(false); // Set the portrait icon SVGAsset icon = ModState.SimGameState.DataManager.GetObjectOfType <SVGAsset>(Mod.Config.Icons.CrewPortrait_Aerospace, BattleTechResourceType.SVGAsset); if (icon == null) { Mod.Log.Warn?.Write($"ERROR READING ICON: {Mod.Config.Icons.CrewPortrait_Aerospace}"); } SVGImage image = portraitOverride.GetComponentInChildren <SVGImage>(); image.vectorGraphics = icon; // Set the crew size LocalizableText[] texts = crewBlock.GetComponentsInChildren <LocalizableText>(); LocalizableText lt1 = texts[0]; string sizeText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Size], new object[] { details.SizeLabel, details.Size }).ToString(); lt1.SetText(sizeText); // Force the font size here, otherwise the right hand panel isn't correct lt1.fontSize = 16f; lt1.fontSizeMin = 16f; lt1.fontSizeMax = 16f; LocalizableText lt2 = texts[1]; string skillText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Skill_Aerospace_Points], new object[] { details.Value }).ToString(); lt2.SetText(skillText); // Force the font size here, otherwise the right hand panel isn't correct lt2.fontSize = 16f; lt2.fontSizeMin = 16f; lt2.fontSizeMax = 16f; // Set the expertise of the crew ___expertise.color = Color.white; ___expertise.SetText(details.ExpertiseLabel); } else if (details.IsMechTechCrew) { Mod.Log.Debug?.Write($" -- pilot is Mechtech crew"); layoutTitleImg.color = Mod.Config.Crew.MechTechCrewColor; ___portrait.gameObject.SetActive(false); ___AbilitiesObject.SetActive(false); ___roninIcon.gameObject.SetActive(false); ___veteranIcon.gameObject.SetActive(false); // Set the portrait icon SVGAsset icon = ModState.SimGameState.DataManager.GetObjectOfType <SVGAsset>(Mod.Config.Icons.CrewPortrait_MechTech, BattleTechResourceType.SVGAsset); if (icon == null) { Mod.Log.Warn?.Write($"ERROR READING ICON: {Mod.Config.Icons.CrewPortrait_MechTech}"); } SVGImage image = portraitOverride.GetComponentInChildren <SVGImage>(); image.vectorGraphics = icon; // Set the crew size LocalizableText[] texts = crewBlock.GetComponentsInChildren <LocalizableText>(); LocalizableText lt1 = texts[0]; string sizeText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Size], new object[] { details.SizeLabel, details.Size }).ToString(); lt1.SetText(sizeText); // Force the font size here, otherwise the right hand panel isn't correct lt1.fontSize = 16f; lt1.fontSizeMin = 16f; lt1.fontSizeMax = 16f; LocalizableText lt2 = texts[1]; string skillText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Skill_MechTech_Points], new object[] { details.Value }).ToString(); lt2.SetText(skillText); // Force the font size here, otherwise the right hand panel isn't correct lt2.fontSize = 16f; lt2.fontSizeMin = 16f; lt2.fontSizeMax = 16f; // Set the expertise of the crew ___expertise.color = Color.white; ___expertise.SetText(details.ExpertiseLabel); } else if (details.IsMedTechCrew) { Mod.Log.Debug?.Write($" -- pilot is Medtech crew"); layoutTitleImg.color = Mod.Config.Crew.MedTechCrewColor; ___portrait.gameObject.SetActive(false); ___AbilitiesObject.SetActive(false); ___roninIcon.gameObject.SetActive(false); ___veteranIcon.gameObject.SetActive(false); // Set the portrait icon SVGAsset icon = ModState.SimGameState.DataManager.GetObjectOfType <SVGAsset>(Mod.Config.Icons.CrewPortrait_MedTech, BattleTechResourceType.SVGAsset); if (icon == null) { Mod.Log.Warn?.Write($"ERROR READING ICON: {Mod.Config.Icons.CrewPortrait_MedTech}"); } SVGImage image = portraitOverride.GetComponentInChildren <SVGImage>(); image.vectorGraphics = icon; // Set the crew size LocalizableText[] texts = crewBlock.GetComponentsInChildren <LocalizableText>(); LocalizableText lt1 = texts[0]; string sizeText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Size], new object[] { details.SizeLabel, details.Size }).ToString(); lt1.SetText(sizeText); // Force the font size here, otherwise the right hand panel isn't correct lt1.fontSize = 16f; lt1.fontSizeMin = 16f; lt1.fontSizeMax = 16f; LocalizableText lt2 = texts[1]; string skillText = new Localize.Text(Mod.LocalizedText.Labels[ModText.LT_Skill_MedTech_Points], new object[] { details.Value }).ToString(); lt2.SetText(skillText); // Force the font size here, otherwise the right hand panel isn't correct lt2.fontSize = 16f; lt2.fontSizeMin = 16f; lt2.fontSizeMax = 16f; // Set the expertise of the crew ___expertise.color = Color.white; ___expertise.SetText(details.ExpertiseLabel); } else if (details.IsVehicleCrew) { Mod.Log.Debug?.Write($" -- pilot is Vehicle crew"); layoutTitleImg.color = Mod.Config.Crew.VehicleCrewColor; ___portrait.gameObject.SetActive(false); ___roninIcon.gameObject.SetActive(false); ___callsign.SetText("VCREW: " + ___pilot.Callsign); // Set the portrait icon SVGAsset icon = ModState.SimGameState.DataManager.GetObjectOfType <SVGAsset>(Mod.Config.Icons.CrewPortrait_Vehicle, BattleTechResourceType.SVGAsset); if (icon == null) { Mod.Log.Warn?.Write($"ERROR READING ICON: {Mod.Config.Icons.CrewPortrait_Vehicle}"); } SVGImage image = portraitOverride.GetComponentInChildren <SVGImage>(); image.vectorGraphics = icon; ___expertise.color = Color.white; } else { Mod.Log.Debug?.Write($" -- pilot is Mechwarrior"); ___portrait.gameObject.SetActive(true); } Mod.Log.Debug?.Write($"LayoutTitleImg color set to: {layoutTitleImg.color}"); }
public static int CompareByCrewTypeAndValue(SGBarracksRosterSlot slot1, SGBarracksRosterSlot slot2) { // Check nullity if (slot1 == null && slot2 == null) { return(0); } else if (slot1 != null && slot2 == null) { return(1); } else if (slot1 == null && slot2 != null) { return(-1); } // Check pilot vs. non-pilot if (slot1.Pilot == null && slot2.Pilot == null) { return(0); } else if (slot1.Pilot != null && slot2.Pilot == null) { return(1); } else if (slot1.Pilot == null && slot2.Pilot != null) { return(-1); } // Check pilot vs. non-pilot using pilotDefs if (slot1.Pilot.pilotDef == null && slot2.Pilot.pilotDef == null) { return(0); } else if (slot1.Pilot.pilotDef != null && slot2.Pilot.pilotDef == null) { return(1); } else if (slot1.Pilot.pilotDef == null && slot2.Pilot.pilotDef != null) { return(-1); } // Check details CrewDetails cd1 = ModState.GetCrewDetails(slot1.Pilot.pilotDef); CrewDetails cd2 = ModState.GetCrewDetails(slot2.Pilot.pilotDef); // Compare by type int typeComparison = CrewDetails.CompareByType(cd1, cd2); if (typeComparison != 0) { return(typeComparison); } // Compare by skill int skillComparison = CrewDetails.CompareByValue(cd1, cd2); if (skillComparison != 0) { return(skillComparison); } return(0); }
static void Postfix(SimGameState __instance) { List <FactionValue> alliedFactions = new List <FactionValue>(); foreach (string factionName in __instance.GetAllCareerAllies()) { alliedFactions.Add(FactionEnumeration.GetFactionByName(factionName)); } foreach (Pilot pilot in __instance.PilotRoster) { CrewDetails details = ModState.GetCrewDetails(pilot.pilotDef); // Decay positive attitude if (details.Attitude > 0) { int decayAmount = (int)Math.Ceiling(details.Attitude * Mod.Config.Attitude.Monthly.Decay); Mod.Log.Debug?.Write($"Decaying positive attitude from {details.Attitude} by {decayAmount}"); details.Attitude -= decayAmount; } // Apply the morale modifier int econMod = Mod.Config.Attitude.Monthly.EconomyNormalMod; if (__instance.ExpenditureLevel == EconomyScale.Spartan) { econMod = Mod.Config.Attitude.Monthly.EconSpartanMod; } else if (__instance.ExpenditureLevel == EconomyScale.Restrictive) { econMod = Mod.Config.Attitude.Monthly.EconRestrictiveMod; } else if (__instance.ExpenditureLevel == EconomyScale.Generous) { econMod = Mod.Config.Attitude.Monthly.EconomyGenerousMod; } else if (__instance.ExpenditureLevel == EconomyScale.Extravagant) { econMod = Mod.Config.Attitude.Monthly.EconomyExtravagantMod; } details.Attitude += econMod; // Check pilots to see if they favor or hate an allied faction if (details.FavoredFactionId > 0 && !details.IsPlayer) { foreach (FactionValue faction in alliedFactions) { if (faction.FactionID == details.FavoredFactionId) { Mod.Log.Debug?.Write($"Pilot {pilot.Name} favors allied faction: {faction.FriendlyName}, " + $"applying attitude mod: {Mod.Config.Attitude.Monthly.FavoredEmployerAlliedMod}"); details.Attitude += Mod.Config.Attitude.Monthly.FavoredEmployerAlliedMod; ModState.UpdateOrCreateCrewDetails(pilot.pilotDef, details); } } } if (details.HatedFactionId > 0 && !details.IsPlayer) { foreach (FactionValue faction in alliedFactions) { if (faction.FactionID == details.HatedFactionId) { Mod.Log.Debug?.Write($"Pilot {pilot.Name} hates allied faction: {faction.FriendlyName}, " + $"applying attitude mod: {Mod.Config.Attitude.Monthly.HatedEmployerAlliedMod}"); details.Attitude += Mod.Config.Attitude.Monthly.HatedEmployerAlliedMod; ModState.UpdateOrCreateCrewDetails(pilot.pilotDef, details); } } } // Clamp values details.Attitude = Mathf.Clamp(details.Attitude, Mod.Config.Attitude.ThresholdMin, Mod.Config.Attitude.ThresholdMax); ModState.UpdateOrCreateCrewDetails(pilot.pilotDef, details); } }
static void Postfix(SGBarracksDossierPanel __instance, Pilot p, LocalizableText ___healthText, List <GameObject> ___healthList, LocalizableText ___salary, LocalizableText ___firstName, LocalizableText ___lastName) { if (p == null) { return; } Mod.DossierLog.Debug?.Write($"Updating Dossier for pilot: {p.Name}"); CrewDetails details = ModState.GetCrewDetails(p.pilotDef); if (details.IsMechTechCrew || details.IsMedTechCrew || details.IsAerospaceCrew) { ___healthText.SetText("N/A"); for (int i = 0; i < ___healthList.Count; i++) { ___healthList[i].SetActive(false); } } string nameS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Name_Format], new object[] { p.FirstName, p.LastName }).ToString(); ___firstName.SetText(nameS); // Set the firstname label to 'Name' instead of 'First Name' Mod.DossierLog.Debug?.Write("Updating firstName to Name"); GameObject firstNameGO = __instance.gameObject.FindFirstChildNamed(ModConsts.GO_HBS_Barracks_Dossier_LastName); GameObject firstNameLabelGO = firstNameGO.transform.parent.GetChild(0).GetChild(0).gameObject; LocalizableText firstNameLabel = firstNameLabelGO.GetComponentInChildren <LocalizableText>(); string firstNameS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Contract_Term]).ToString(); firstNameLabel.SetText(firstNameS); // Set the lastname label to 'Contract End' and the name value to the remaining days Mod.DossierLog.Debug?.Write("Updating lastName to ContractTerm"); GameObject lastNameGO = __instance.gameObject.FindFirstChildNamed(ModConsts.GO_HBS_Barracks_Dossier_LastName); GameObject lastNameLabelGO = lastNameGO.transform.parent.GetChild(0).GetChild(0).gameObject; // should be text_lastName -> parent -> layout-label -> label LocalizableText lastNameLabel = lastNameLabelGO.GetComponentInChildren <LocalizableText>(); string contractTermS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Contract_Term]).ToString(); lastNameLabel.SetText(contractTermS); string contractTermRemaining = "------"; if (!details.IsPlayer && details.ContractTerm != 0) { int daysRemaining = details.ExpirationDay - ModState.SimGameState.DaysPassed; if (daysRemaining < 0) { daysRemaining = 0; } contractTermRemaining = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Days_Remaining], new object[] { daysRemaining }).ToString(); Mod.DossierLog.Debug?.Write($" {daysRemaining} daysRemaining = {ModState.SimGameState.DaysPassed} daysPassed - {details.ExpirationDay} endDay"); } ___lastName.SetText(contractTermRemaining); Mod.DossierLog.Debug?.Write($" -- done updating dossier for pilot: {p.Name}"); }
static void Postfix(SGBarracksServicePanel __instance, Pilot p, BattleTech.UI.TMProWrapper.LocalizableText ___biographyLabel, SimGameState ___sim, HBSTagView ___tagViewer) { if (p == null) { return; } CrewDetails details = ModState.GetCrewDetails(p.pilotDef); // Disable the battle stats GameObject battleStats = __instance.gameObject.FindFirstChildNamed(ModConsts.GO_HBS_Barracks_ServicePanel_BattleStats); if (details.IsMechTechCrew || details.IsMedTechCrew || details.IsAerospaceCrew) { battleStats.SetActive(false); } else { battleStats.SetActive(true); } Mod.Log.Debug?.Write($"Iterating tags for pilot: {p.Name}"); // Filter the HR GUID tag out List <string> filteredTags = p.pilotDef.PilotTags.Where(t => !t.StartsWith(ModTags.Tag_GUID)).ToList(); TagSet baseTags = new TagSet(filteredTags); foreach (string tag in p.pilotDef.PilotTags) { ___tagViewer.Initialize(baseTags, ___sim.Context, ___sim.DebugMode, 4); } Mod.Log.Debug?.Write("Updating attitude fields."); StringBuilder sb = new StringBuilder(); if (!details.IsPlayer) { // Inject hazard pay, if appropriate if (details.HazardPay > 0) { string hazardPayS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Hazard_Pay], new object[] { SimGameState.GetCBillString(details.HazardPay) }).ToString(); Mod.Log.Debug?.Write($"Hazard pay is: {hazardPayS}"); sb.Append(hazardPayS); sb.Append("\n"); } // Inject attitude string attitudeValKey = ModText.LT_Crew_Attitude_Average; if (details.Attitude >= Mod.Config.Attitude.ThresholdBest) { attitudeValKey = ModText.LT_Crew_Attitude_Best; } else if (details.Attitude >= Mod.Config.Attitude.ThresholdGood) { attitudeValKey = ModText.LT_Crew_Attitude_Good; } else if (details.Attitude <= Mod.Config.Attitude.ThresholdWorst) { attitudeValKey = ModText.LT_Crew_Attitude_Worst; } else if (details.Attitude <= Mod.Config.Attitude.ThresholdPoor) { attitudeValKey = ModText.LT_Crew_Attitude_Poor; } string attitudeDescS = new Text(Mod.LocalizedText.Labels[attitudeValKey]).ToString(); Mod.Log.Debug?.Write($"Attitude value is: {details.Attitude} with label: {attitudeDescS}"); string attitudeS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Biography_Attitude], new object[] { attitudeDescS, details.Attitude }).ToString(); sb.Append(attitudeS); sb.Append("\n"); // Convert favored and hated faction if (details.FavoredFactionId > 0) { FactionValue faction = FactionEnumeration.GetFactionByID(details.FavoredFactionId); string favoredFactionS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Biography_Faction_Favored], new object[] { faction.FactionDef.CapitalizedName }).ToString(); sb.Append(favoredFactionS); sb.Append("\n"); Mod.Log.Debug?.Write($" Favored Faction is: {favoredFactionS}"); } if (details.HatedFactionId > 0) { FactionValue faction = FactionEnumeration.GetFactionByID(details.HatedFactionId); string hatedFactionS = new Text(Mod.LocalizedText.Labels[ModText.LT_Crew_Dossier_Biography_Faction_Hated], new object[] { faction.FactionDef.CapitalizedName }).ToString(); sb.Append(hatedFactionS); sb.Append("\n"); Mod.Log.Debug?.Write($" Hated Faction is: {hatedFactionS}"); } } // Add the original description sb.Append(Interpolator.Interpolate(p.pilotDef.Description.GetLocalizedDetails().ToString(true), ___sim.Context, true)); string biographyS = sb.ToString(); Mod.Log.Debug?.Write($"Biography will be: {biographyS}"); ___biographyLabel.SetText(biographyS, Array.Empty <object>()); }
static void Postfix(Pilot ___pilot, GameObject ___cantBuyMRBOverlay, HBSTooltip ___cantBuyToolTip, LocalizableText ___costText, UIColorRefTracker ___costTextColor) { if (ModState.SimGameState == null) { return; // Only patch if we're in SimGame } Mod.Log.Debug?.Write($"Refreshing availability for pilot: {___pilot.Name}"); // TODO: This may need to be improved, as it's used inside a loop. Maybe write to company stats? CrewDetails details = ModState.GetCrewDetails(___pilot.pilotDef); Mod.Log.Debug?.Write($" -- pilot requires: {details.Size} berths"); int usedBerths = CrewHelper.UsedBerths(ModState.SimGameState.PilotRoster); int availableBerths = ModState.SimGameState.GetMaxMechWarriors() - usedBerths; Mod.Log.Debug?.Write($"AvailableBerths: {availableBerths} = max: {ModState.SimGameState.GetMaxMechWarriors()} - used: {usedBerths}"); // Check berths limitations if (details.Size > availableBerths) { Mod.Log.Info?.Write($"Pilot {___pilot.Name} cannot be hired, not enough berths (needs {details.Size})"); ___cantBuyMRBOverlay.SetActive(true); HBSTooltipStateData tooltipStateData = new HBSTooltipStateData(); tooltipStateData.SetContextString($"DM.BaseDescriptionDefs[{ModConsts.Tooltip_NotEnoughBerths}]"); ___cantBuyToolTip.SetDefaultStateData(tooltipStateData); } // Check type limitations if (!CrewHelper.CanHireMoreCrewOfType(details)) { Mod.Log.Info?.Write($"Pilot {___pilot.Name} cannot be hired, too many of type already employed."); ___cantBuyMRBOverlay.SetActive(true); HBSTooltipStateData tooltipStateData = new HBSTooltipStateData(); tooltipStateData.SetContextString($"DM.BaseDescriptionDefs[{ModConsts.Tooltip_TooManyOfType}]"); ___cantBuyToolTip.SetDefaultStateData(tooltipStateData); } else { Mod.Log.Debug?.Write($"Pilot {___pilot.Name} can be hired, no limiations on max."); } // Set the prices //int purchaseCostAfterReputationModifier = ModState.SimGameState.CurSystem.GetPurchaseCostAfterReputationModifier( // ModState.SimGameState.GetMechWarriorHiringCost(___pilot.pilotDef) // ); // TODO: Apply system cost multiplier // Hiring cost is influenced by: // - current morale rating // - any faction alignment for units // - any reputation modifiers ___costText.SetText(SimGameState.GetCBillString(details.HiringBonus)); UIColor costColor = UIColor.Red; if (details.HiringBonus <= ModState.SimGameState.Funds) { costColor = UIColor.White; } ___costTextColor.SetUIColor(costColor); }
public static void Postfix(SGCaptainsQuartersStatusScreen __instance, EconomyScale expenditureLevel, bool showMoraleChange, Transform ___SectionTwoExpensesList, TextMeshProUGUI ___SectionTwoExpensesField, SimGameState ___simState) { // Redo all the mechwarrior cost float expenditureCostModifier = ___simState.GetExpenditureCostModifier(expenditureLevel); ClearListLineItems(___SectionTwoExpensesList, ___simState); int ongoingMechWariorCosts = 0; //int oldCosts = 0; List <KeyValuePair <string, int> > list = new List <KeyValuePair <string, int> >(); foreach (Pilot item in ___simState.PilotRoster) { string key = item.pilotDef.Description.DisplayName; CrewDetails details = ModState.GetCrewDetails(item.pilotDef); //oldCosts += Mathf.CeilToInt(expenditureCostModifier * (float)___simState.GetMechWarriorValue(item.pilotDef)); Mod.Log.Debug?.Write($" Pilot: {item.Name} has salary: {details.AdjustedSalary}"); list.Add(new KeyValuePair <string, int>(key, details.AdjustedSalary)); } // Sort by most expensive list.Sort((KeyValuePair <string, int> a, KeyValuePair <string, int> b) => b.Value.CompareTo(a.Value)); // Create a new line item for each list.ForEach(delegate(KeyValuePair <string, int> entry) { ongoingMechWariorCosts += entry.Value; AddListLineItem(___SectionTwoExpensesList, ___simState, entry.Key, SimGameState.GetCBillString(entry.Value)); }); ___SectionTwoExpensesField.SetText(SimGameState.GetCBillString(ongoingMechWariorCosts)); // Rectify the salary field //SimGameState simGameState = UnityGameInstance.BattleTechGame.Simulation; //if (__instance == null || ___SectionOneExpensesList == null || ___SectionOneExpensesField == null || simGameState == null) //{ // Mod.Log.Debug?.Write($"SGCQSS:RD - skipping"); // return; //} //// TODO: Add this to mech parts maybe? ////float expenditureCostModifier = simGameState.GetExpenditureCostModifier(expenditureLevel); //// Determine the level of aerospace support ////Statistic aerospaceAssets = simGameState.CompanyStats.GetStatistic("AerospaceAssets"); ////int aerospaceSupport = aerospaceAssets != null ? aerospaceAssets.Value<int>() : 0; //Mod.Log.Info?.Write($"SGCQSS:RD - entered. Parsing current keys."); //List<KeyValuePair<string, int>> currentKeys = GetCurrentKeys(___SectionOneExpensesList, ___simState); //// Extract the active mechs from the list, then re-add the updated price //List<KeyValuePair<string, int>> filteredKeys = FilterActiveMechs(currentKeys, ___simState); //List<KeyValuePair<string, int>> activeMechs = GetUpkeepLabels(___simState); //filteredKeys.AddRange(activeMechs); //// Add the new costs //int newActiveMechCosts = MonthlyCostCalcs.SumMonthlyMechCosts(___simState); //filteredKeys.Sort(new ExpensesSorter()); //Mod.Log.Info?.Write($"SGCQSS:RD - Clearing items"); //ClearListLineItems(___SectionOneExpensesList, ___simState); //Mod.Log.Info?.Write($"SGCQSS:RD - Adding listLineItems"); //int totalCost = 0; //try //{ // foreach (KeyValuePair<string, int> kvp in filteredKeys) // { // Mod.Log.Info?.Write($"SGCQSS:RD - Adding key:{kvp.Key} value:{kvp.Value}"); // totalCost += kvp.Value; // AddListLineItem(___SectionOneExpensesList, ___simState, kvp.Key, SimGameState.GetCBillString(kvp.Value)); // } //} //catch (Exception e) //{ // Mod.Log.Info?.Write($"SGCQSS:RD - failed to add lineItemParts due to: {e.Message}"); //} //// Update summary costs //int newCosts = totalCost; //string newCostsS = SimGameState.GetCBillString(newCosts); //Mod.Log.Debug?.Write($"SGCQSS:RD - total:{newCosts} = activeMechs:{newActiveMechCosts}"); //try //{ // ___SectionOneExpensesField.SetText(SimGameState.GetCBillString(newCosts)); // Mod.Log.Debug?.Write($"SGCQSS:RD - updated "); //} //catch (Exception e) //{ // Mod.Log.Info?.Write($"SGCQSS:RD - failed to update summary costs section due to: {e.Message}"); //} }
static bool Prefix(string button) { Mod.Log.Info?.Write($"RBP invoked for button: {button}"); if ("Hiring".Equals(button, StringComparison.InvariantCultureIgnoreCase)) { if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)) { Mod.Log.Info?.Write("-- Regenerating pilots in system."); ModState.SimGameState.CurSystem.AvailablePilots.Clear(); ModState.SimGameState.CurSystem.GeneratePilots(ModState.SimGameState.Constants.Story.DefaultPilotsPerSystem); } else if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl) && Mod.Config.HeadHunting.Enabled && ModState.SimGameState.TravelState == SimGameTravelStatus.IN_SYSTEM) { Mod.Log.Info?.Write("-- Forcing poaching on random crew."); // Randomize pilots instead of sorting by skill? List <Pilot> pilots = ModState.SimGameState.PilotRoster.ToList(); pilots.Sort((p1, p2) => { CrewDetails p1cd = ModState.GetCrewDetails(p1.pilotDef); CrewDetails p2cd = ModState.GetCrewDetails(p2.pilotDef); return(CrewDetails.CompareByValue(p1cd, p2cd)); }); int idx = Mod.Random.Next(0, pilots.Count - 1); Pilot random = pilots[idx]; Mod.Log.Info?.Write($"-- Headhunted pilot: {random.Name}"); CrewDetails cd = ModState.GetCrewDetails(random.pilotDef); SimGameEventDef newEvent = EventHelper.CreateHeadHuntingEvent(random, cd, cd.HiringBonus, cd.HiringBonus); Traverse mechWarriorEventTrackerT = Traverse.Create(ModState.SimGameState).Field("mechWarriorEventTracker"); SimGameEventTracker mechWarriorEventTracker = mechWarriorEventTrackerT.GetValue <SimGameEventTracker>(); ModState.HeadHuntedPilot = random; Mod.Log.Info?.Write($"-- Firing debug event"); ModState.SimGameState.Context.SetObject(GameContextObjectTagEnum.TargetMechWarrior, random); ModState.SimGameState.OnEventTriggered(newEvent, EventScope.MechWarrior, mechWarriorEventTracker); return(false); } else if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) && ModState.SimGameState.TravelState == SimGameTravelStatus.IN_SYSTEM) { Mod.Log.Info?.Write("-- Forcing contract expiration on random crew."); // Randomize pilots instead of sorting by skill? List <Pilot> pilots = ModState.SimGameState.PilotRoster.ToList(); pilots.Sort((p1, p2) => { CrewDetails p1cd = ModState.GetCrewDetails(p1.pilotDef); CrewDetails p2cd = ModState.GetCrewDetails(p2.pilotDef); return(CrewDetails.CompareByValue(p1cd, p2cd)); }); int idx = Mod.Random.Next(0, pilots.Count - 1); Pilot random = pilots[idx]; Mod.Log.Info?.Write($"-- Expired pilot: {random.Name}"); CrewDetails cd = ModState.GetCrewDetails(random.pilotDef); ModState.ExpiredContracts.Enqueue((random, cd)); SimGameEventDef newEvent = EventHelper.ModifyContractExpirationEventForPilot(random, cd); Traverse mechWarriorEventTrackerT = Traverse.Create(ModState.SimGameState).Field("mechWarriorEventTracker"); SimGameEventTracker mechWarriorEventTracker = mechWarriorEventTrackerT.GetValue <SimGameEventTracker>(); ModState.SimGameState.OnEventTriggered(newEvent, EventScope.MechWarrior, mechWarriorEventTracker); return(false); } } return(true); }
static void Postfix(BattleTech.UI.AAR_ContractResults_Screen __instance, Contract ___theContract) { StringBuilder bodySB = new StringBuilder(); bodySB.Append(new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Body], new object[] { }).ToString()); int killedPilotsMod = Mod.Config.Attitude.PerMission.PilotKilledMod * ___theContract.KilledPilots.Count; if (___theContract.KilledPilots.Count > 0) { Mod.Log.Debug?.Write($"Player lost {___theContract.KilledPilots.Count} pilots, applying a modifier of {killedPilotsMod} to all pilots."); bodySB.Append( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Pilot_Killed], new object[] { killedPilotsMod }).ToString() ); } // Add the monospace tag bodySB.Append(new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Font], new object[] { }).ToString()); // Calculate the contract bonus int contractBonus = Mod.Config.Attitude.PerMission.ContractFailedMod; if (___theContract.State == Contract.ContractState.Complete) { contractBonus = Mod.Config.Attitude.PerMission.ContractSuccessMod; Mod.Log.Debug?.Write($"Contract was successful, applying contract modifier of: {contractBonus}"); bodySB.Append( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Contract_Success], new object[] { contractBonus }).ToString() ); } else if (___theContract.IsGoodFaithEffort) { contractBonus = Mod.Config.Attitude.PerMission.ContractFailedGoodFaithMod; Mod.Log.Debug?.Write($"Contract was a good faith effort, applying contract modifier of: {contractBonus}"); bodySB.Append( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Contract_GoodFaith], new object[] { contractBonus }).ToString() ); } else { Mod.Log.Debug?.Write($"Contract was failed, applying contract modifier of: {contractBonus}"); bodySB.Append( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Contract_Failed], new object[] { contractBonus }).ToString() ); } bodySB.Append("\n"); // Find just combat pilots (for benched mod) List <Pilot> allPilots = __instance.Sim.PilotRoster.ToList(); List <Pilot> combatPilots = allPilots.Where(p => { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); return(details.IsCombatCrew); }).ToList(); Mod.Log.Debug?.Write($"All Combat pilots are: {string.Join(", ", combatPilots.Select(p => p.Name).ToList())}"); List <Pilot> deployedPilots = ___theContract.PlayerUnitResults.Select(ur => ur.pilot).ToList(); Mod.Log.Debug?.Write($"Deployed pilots were: {string.Join(", ", deployedPilots.Select(p => p.Name).ToList())}"); // Iterate pilots apply modifiers foreach (Pilot p in allPilots) { CrewDetails details = ModState.GetCrewDetails(p.pilotDef); if (details.IsPlayer) { continue; } int startingAttitude = details.Attitude; Mod.Log.Debug?.Write($"Applying attitude modifiers to pilot: {p.Name}"); // Apply modifier for contract success details.Attitude += contractBonus; // Applied killed pilots modifier details.Attitude += killedPilotsMod; List <string> detailDescs = new List <string>(); // Check for bench - only applies to combat pilots if (deployedPilots.Contains(p)) { Mod.Log.Debug?.Write($" -- combat pilot was deployed, adding {Mod.Config.Attitude.PerMission.DeployedOnMissionMod} attitude"); details.Attitude += Mod.Config.Attitude.PerMission.DeployedOnMissionMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Deployed], new object[] { Mod.Config.Attitude.PerMission.DeployedOnMissionMod }).ToString() ); } else if (combatPilots.Contains(p)) { Mod.Log.Debug?.Write($" -- combat pilot was benched, adding {Mod.Config.Attitude.PerMission.BenchedOnMissionMod} attitude"); details.Attitude += Mod.Config.Attitude.PerMission.BenchedOnMissionMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Benched], new object[] { Mod.Config.Attitude.PerMission.BenchedOnMissionMod }).ToString() ); } // Check favored / hated factions if (details.FavoredFactionId > 0) { if (details.FavoredFactionId == ___theContract.Override.employerTeam.FactionValue.FactionID) { Mod.Log.Debug?.Write($" -- pilot favors employer faction, applying modifier: {Mod.Config.Attitude.PerMission.FavoredFactionIsEmployerMod}"); details.Attitude += Mod.Config.Attitude.PerMission.FavoredFactionIsEmployerMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Favored_Employer], new object[] { Mod.Config.Attitude.PerMission.FavoredFactionIsEmployerMod }).ToString() ); } if (details.FavoredFactionId == ___theContract.Override.targetTeam.FactionValue.FactionID) { Mod.Log.Debug?.Write($" -- pilot favors target faction, applying modifier: {Mod.Config.Attitude.PerMission.FavoredFactionIsTargetMod}"); details.Attitude += Mod.Config.Attitude.PerMission.FavoredFactionIsTargetMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Favored_Target], new object[] { Mod.Config.Attitude.PerMission.FavoredFactionIsTargetMod }).ToString() ); } } if (details.HatedFactionId > 0) { if (details.HatedFactionId == ___theContract.Override.employerTeam.FactionValue.FactionID) { Mod.Log.Debug?.Write($" -- pilot hates employer faction, applying modifier: {Mod.Config.Attitude.PerMission.HatedFactionIsEmployerMod}"); details.Attitude += Mod.Config.Attitude.PerMission.HatedFactionIsEmployerMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Hated_Employer], new object[] { Mod.Config.Attitude.PerMission.HatedFactionIsEmployerMod }).ToString() ); } if (details.HatedFactionId == ___theContract.Override.targetTeam.FactionValue.FactionID) { Mod.Log.Debug?.Write($" -- pilot hates target faction, applying modifier: {Mod.Config.Attitude.PerMission.HatedFactionIsTargetMod}"); details.Attitude += Mod.Config.Attitude.PerMission.HatedFactionIsTargetMod; detailDescs.Add( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Mod_Hated_Target], new object[] { Mod.Config.Attitude.PerMission.HatedFactionIsTargetMod }).ToString() ); } } // Clamp values to max and min details.Attitude = Mathf.Clamp(details.Attitude, Mod.Config.Attitude.ThresholdMin, Mod.Config.Attitude.ThresholdMax); string detailsS = string.Join(", ", detailDescs); bodySB.Append( new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Pilot_Line], new object[] { details.Attitude, p.Callsign, detailsS }).ToString() ); ModState.UpdateOrCreateCrewDetails(p.pilotDef, details); } // Close the mspace tag bodySB.Append("</mspace>"); // Display a dialog with changes string localDialogTitle = new Text(Mod.LocalizedText.Dialogs[ModText.DIAT_AAR_Title]).ToString(); string localDialogText = bodySB.ToString(); GenericPopup gp = GenericPopupBuilder.Create(localDialogTitle, localDialogText) .Render(); TextMeshProUGUI contentText = (TextMeshProUGUI)Traverse.Create(gp).Field("_contentText").GetValue(); contentText.alignment = TextAlignmentOptions.Left; }
static void Prefix(SimGameState __instance, Pilot p) { if (p == null || !__instance.PilotRoster.Contains(p)) { return; } Mod.Log.Debug?.Write($"Removing pilot: {p.Name} from company."); CrewDetails details = ModState.GetCrewDetails(p.pilotDef); // Remove any mechtech, medtech, or aerospace points if (details.IsAerospaceCrew) { // Track our skill points Statistic aerospaceSkill = __instance.CompanyStats.GetStatistic(ModStats.Aerospace_Skill); if (aerospaceSkill == null) { aerospaceSkill = __instance.CompanyStats.AddStatistic <int>(ModStats.Aerospace_Skill, 0); } if (aerospaceSkill.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.Aerospace_Skill, StatCollection.StatOperation.Int_Subtract, details.Value); } // Track the crew count Statistic crewCount = __instance.CompanyStats.GetStatistic(ModStats.CrewCount_Aerospace); if (crewCount == null) { crewCount = __instance.CompanyStats.AddStatistic <int>(ModStats.CrewCount_Aerospace, 0); } if (crewCount.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.CrewCount_Aerospace, StatCollection.StatOperation.Int_Subtract, 1); } } else if (details.IsMechTechCrew) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.HBS_Company_MechTech_Skill, StatCollection.StatOperation.Int_Subtract, details.Value); // Track the crew count Statistic crewCount = __instance.CompanyStats.GetStatistic(ModStats.CrewCount_MechTechs); if (crewCount == null) { crewCount = __instance.CompanyStats.AddStatistic <int>(ModStats.CrewCount_MechTechs, 0); } if (crewCount.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.CrewCount_MechTechs, StatCollection.StatOperation.Int_Subtract, 1); } } else if (details.IsMechWarrior) { // Track the crew count Statistic crewCount = __instance.CompanyStats.GetStatistic(ModStats.CrewCount_MechWarriors); if (crewCount == null) { crewCount = __instance.CompanyStats.AddStatistic <int>(ModStats.CrewCount_MechWarriors, 0); } if (crewCount.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.CrewCount_MechWarriors, StatCollection.StatOperation.Int_Subtract, 1); } } else if (details.IsMedTechCrew) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.HBS_Company_MedTech_Skill, StatCollection.StatOperation.Int_Subtract, details.Value); // Track the crew count Statistic crewCount = __instance.CompanyStats.GetStatistic(ModStats.CrewCount_MedTechs); if (crewCount == null) { crewCount = __instance.CompanyStats.AddStatistic <int>(ModStats.CrewCount_MedTechs, 0); } if (crewCount.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.CrewCount_MedTechs, StatCollection.StatOperation.Int_Subtract, 1); } } else if (details.IsVehicleCrew) { // Track the crew count Statistic crewCount = __instance.CompanyStats.GetStatistic(ModStats.CrewCount_VehicleCrews); if (crewCount == null) { crewCount = __instance.CompanyStats.AddStatistic <int>(ModStats.CrewCount_VehicleCrews, 0); } if (crewCount.Value <int>() > 0) { __instance.CompanyStats.ModifyStat <int>(null, -1, ModStats.CrewCount_VehicleCrews, StatCollection.StatOperation.Int_Subtract, 1); } } // Cleanup company state ModState.RemoveCrewDetails(p.pilotDef, details); __instance.RoomManager.RefreshTimeline(false); __instance.RoomManager.RefreshDisplay(); }