static void Postfix(ref bool __result, RuleSavingThrow __instance) { if (settings.toggleNoFriendlyFireForAOE) { if (__instance.Reason != null) { if (__instance.Reason.Ability != null) { if (__instance.Reason.Caster != null && __instance.Reason.Caster.IsPlayerFaction && __instance.Initiator.IsPlayerFaction && __instance.Reason.Ability.Blueprint != null && ((__instance.Reason.Ability.Blueprint.EffectOnAlly == AbilityEffectOnUnit.Harmful) || (__instance.Reason.Ability.Blueprint.EffectOnEnemy == AbilityEffectOnUnit.Harmful))) { __result = true; } } } } #if false if (StringUtils.ToToggleBool(settings.togglePassSavingThrowIndividual)) { for (int i = 0; i < settings.togglePassSavingThrowIndividualArray.Count(); i++) { if (StringUtils.ToToggleBool(settings.togglePassSavingThrowIndividualArray[i]) && Storage.statsSavesDict[Storage.individualSavesArray[i]] == __instance.StatType) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, (UnitSelectType)settings.indexPassSavingThrowIndividuall)) { __result = true; } } } } #endif }
public static bool Prefix(UnitEntityData unit, ClickGroundHandler.CommandSettings settings) { var moveAsOne = Main.settings.toggleMoveSpeedAsOne; var speedLimit = moveAsOne ? UnitEntityDataUtils.GetMaxSpeed(Game.Instance.UI.SelectionManager.SelectedUnits) : unit.ModifiedSpeedMps; speedLimit *= Main.settings.partyMovementSpeedMultiplier; UnitMoveTo unitMoveTo = new UnitMoveTo(settings.Destination, 0.3f) { MovementDelay = settings.Delay, Orientation = new float?(settings.Orientation), CreatedByPlayer = true }; if (BuildModeUtility.IsDevelopment) { if (CheatsAnimation.SpeedForce > 0f) { unitMoveTo.OverrideSpeed = new float?(CheatsAnimation.SpeedForce); } unitMoveTo.MovementType = (UnitAnimationActionLocoMotion.WalkSpeedType)CheatsAnimation.MoveType.Get(); } if (Main.settings.partyMovementSpeedMultiplier > 1) { unitMoveTo.OverrideSpeed = speedLimit; } unitMoveTo.SpeedLimit = speedLimit; unitMoveTo.ApplySpeedLimitInCombat = settings.ApplySpeedLimitInCombat; unit.Commands.Run(unitMoveTo); if (unit.Commands.Queue.FirstOrDefault((UnitCommand c) => c is UnitMoveTo) == unitMoveTo || Game.Instance.IsPaused) { ClickGroundHandler.ShowDestination(unit, unitMoveTo.Target, false); } return(false); }
static void Postfix(ref bool __result, RuleAttackRoll __instance) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, settings.allHitsCritical)) { __result = true; } }
private static void Postfix(ref UnitEntityData unit) { //if (settings.toggleSetSpeedOnSummon) { // unit.Descriptor.Stats.GetStat(StatType.Speed).BaseValue = settings.setSpeedOnSummonValue; //} if (settings.toggleMakeSummmonsControllable && SummonedByPlayerFaction) { // Main.Log($"SummonPool.Register: Unit [{unit.CharacterName}] [{unit.UniqueId}]"); UnitEntityDataUtils.Charm(unit); //unit.Ensure<UnitPartFollowUnit>().Init(Game.Instance.Player.MainCharacter.Value, true, false); #if false if (unit.Blueprint.AssetGuid == "6fdf7a3f850a1eb48bfbf44d9d0f45dd" && StringUtils.ToToggleBool(settings.toggleDisableWarpaintedSkullAbilityForSummonedBarbarians)) // WarpaintedSkullSummonedBarbarians { if (unit.Body.Head.HasItem && unit.Body.Head.Item?.Blueprint?.AssetGuid == "5d343648bb8887d42b24cbadfeb36991") // WarpaintedSkullItem { unit.Body.Head.Item.Ability.Deactivate(); Common.ModLoggerDebug(unit.Body.Head.Item.Name + "'s ability active: " + unit.Body.Head.Item.Ability.Active); } } #endif SummonedByPlayerFaction = false; } #if false if (StringUtils.ToToggleBool(settings.toggleRemoveSummonsGlow)) { unit.Buffs.RemoveFact(Utilities.GetBlueprintByGuid <BlueprintFact>("706c182e86d9be848b59ddccca73d13e")); // SummonedCreatureVisual unit.Buffs.RemoveFact(Utilities.GetBlueprintByGuid <BlueprintFact>("e4b996b5168fe284ab3141a91895d7ea")); // NaturalAllyCreatureVisual } #endif }
public static void Prefix(UnitEntityData initiator, BlueprintUnit blueprint, Vector3 position, ref Rounds duration, ref int level, RuleSummonUnit __instance) { Mod.Debug($"old duration: {duration} level: {level} \n mult: {settings.summonDurationMultiplier1} levelInc: {settings.summonLevelModifier1}\n initiatior: {initiator} tweakTarget: {settings.summonTweakTarget1} shouldTweak: {UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.summonTweakTarget1)}"); if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.summonTweakTarget1)) { if (settings.summonDurationMultiplier1 != 1) { duration = new Rounds(Convert.ToInt32(duration.Value * settings.summonDurationMultiplier1)); } if (settings.summonLevelModifier1 != 0) { level = Math.Max(0, Math.Min(level + (int)settings.summonLevelModifier1, 20)); } } else if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.summonTweakTarget2)) { if (settings.summonDurationMultiplier2 != 1) { duration = new Rounds(Convert.ToInt32(duration.Value * settings.summonDurationMultiplier2)); } if (settings.summonLevelModifier2 >= 0) { level = Math.Max(0, Math.Min(level + (int)settings.summonLevelModifier1, 20)); } } Mod.Debug($"new duration: {duration} level: {level}"); if (settings.toggleMakeSummmonsControllable) { SummonedByPlayerFaction = initiator.IsPlayerFaction; } Mod.Debug("Initiator: " + initiator.CharacterName + $"(PlayerFaction : {initiator.IsPlayerFaction})" + "\nBlueprint: " + blueprint.CharacterName + "\nDuration: " + duration.Value); }
static bool Prefix(UnitEntityData target) { if (UnitEntityDataUtils.CheckUnitEntityData(target, settings.noAttacksOfOpportunitySelection)) { return(false); } return(true); }
private static void Postfix(RuleRollDice __instance) { if (__instance.DiceFormula.Dice != DiceType.D20) { return; } var initiator = __instance.Initiator; var result = __instance.m_Result; //modLogger.Log($"initiator: {initiator.CharacterName} isInCombat: {initiator.IsInCombat} alwaysRole20OutOfCombat: {settings.alwaysRoll20OutOfCombat}"); //Mod.Debug($"initiator: {initiator.CharacterName} Initial D20Roll: " + result); if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.alwaysRoll20) || (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.alwaysRoll20OutOfCombat) && !initiator.IsInCombat ) ) { result = 20; } else if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.alwaysRoll1)) { result = 1; } else { if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.rollWithAdvantage)) { result = Math.Max(result, UnityEngine.Random.Range(1, 21)); } else if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.rollWithDisadvantage)) { result = Math.Min(result, UnityEngine.Random.Range(1, 21)); } var min = 1; if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.neverRoll1) && result == 1) { result = UnityEngine.Random.Range(2, 21); min = 2; } if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.take10always) && result < 10 && !initiator.IsInCombat) { result = 10; min = 10; } if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.take10minimum) && result < 10 && !initiator.IsInCombat) { result = UnityEngine.Random.Range(10, 21); min = 10; } if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.neverRoll20) && result == 20) { result = UnityEngine.Random.Range(min, 20); } } //Mod.Debug("Modified D20Roll: " + result); __instance.m_Result = result; }
private static bool Prefix(UnitEntityData target) { if (settings.toggleAttacksofOpportunity && target.IsPlayerFaction) { return(false); } if (UnitEntityDataUtils.CheckUnitEntityData(target, settings.noAttacksOfOpportunitySelection)) { return(false); } return(true); }
static void Postfix(RuleInitiativeRoll __instance, ref int __result) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, settings.roll1Initiative)) { __result = 1; Logger.ModLoggerDebug("Modified InitiativeRoll: " + __result); } if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, settings.roll20Initiative)) { __result = 20; Logger.ModLoggerDebug("Modified InitiativeRoll: " + __result); } }
private static void Postfix(RuleInitiativeRoll __instance, ref int __result) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, settings.roll1Initiative)) { __result = 1 + __instance.Modifier; Mod.Trace("Modified InitiativeRoll: " + __result); } else if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, settings.roll20Initiative)) { __result = 20 + __instance.Modifier; Mod.Trace("Modified InitiativeRoll: " + __result); } }
public static void KillFunctions() { switch (Main.settings.actionKeyKillIndex) { case 0: UnitEntityDataUtils.Kill(Common.GetUnitUnderMouse()); break; case 1: UnitEntityDataUtils.ForceKill(Common.GetUnitUnderMouse()); break; } }
public static bool Prefix(UnitEntityData unit, ClickGroundHandler.CommandSettings settings) { var moveAsOne = Main.settings.toggleMoveSpeedAsOne; //Main.Log($"ClickGroundHandler_RunCommand_Patch - isInCombat: {unit.IsInCombat} turnBased:{Game.Instance.Player.IsTurnBasedModeOn()} moveAsOne:{moveAsOne}"); if (unit.IsInCombat && Game.Instance.Player.IsTurnBasedModeOn()) { return(true); } // As of WoTR 1.03c RunCommand is once again the main place to adjust movement speed. The following was needed when we used UnitEntityData_CalculateSpeedModifier_Patch above to adjust speed in non move as one cases. if (!moveAsOne) { return(true); } var partTacticalCombat = unit.Get <UnitPartTacticalCombat>(); if (partTacticalCombat != null && partTacticalCombat.Faction != ArmyFaction.Crusaders) { return(true); } var speedLimit = moveAsOne ? UnitEntityDataUtils.GetMaxSpeed(Game.Instance.UI.SelectionManager.SelectedUnits) : unit.ModifiedSpeedMps; Mod.Trace($"RunCommand - moveAsOne: {moveAsOne} speedLimit: {speedLimit} selectedUnits: {string.Join(" ", Game.Instance.UI.SelectionManager.SelectedUnits.Select(u => $"{u.CharacterName} {u.ModifiedSpeedMps}"))}"); speedLimit *= Main.settings.partyMovementSpeedMultiplier; unitMoveTo = new UnitMoveTo(settings.Destination, 0.3f) { MovementDelay = settings.Delay, Orientation = new float?(settings.Orientation), CreatedByPlayer = true }; if (BuildModeUtility.IsDevelopment) { if (CheatsAnimation.SpeedForce > 0f) { unitMoveTo.OverrideSpeed = new float?(CheatsAnimation.SpeedForce); } unitMoveTo.MovementType = (UnitAnimationActionLocoMotion.WalkSpeedType)CheatsAnimation.MoveType.Get(); } unitMoveTo.SpeedLimit = speedLimit; unitMoveTo.ApplySpeedLimitInCombat = settings.ApplySpeedLimitInCombat; unitMoveTo.OverrideSpeed = speedLimit * 1.5f; unit.Commands.Run(unitMoveTo); if (unit.Commands.Queue.FirstOrDefault((UnitCommand c) => c is UnitMoveTo) == unitMoveTo || Game.Instance.IsPaused) { ClickGroundHandler.ShowDestination(unit, unitMoveTo.Target, false); } return(false); }
private static void Postfix(ref bool __result, RulePartyStatCheck __instance) { if (settings.toggleNoFriendlyFireForAOE) { if (__instance.Reason != null) { if (__instance.Reason.Ability != null) { if (__instance.Reason.Caster != null && __instance.Reason.Caster.Descriptor.IsPartyOrPet() && __instance.Initiator.Descriptor.IsPartyOrPet() && __instance.Reason.Ability.Blueprint != null && ((__instance.Reason.Ability.Blueprint.EffectOnAlly == AbilityEffectOnUnit.Harmful) || (__instance.Reason.Ability.Blueprint.EffectOnEnemy == AbilityEffectOnUnit.Harmful))) { __result = true; } } } } #if false if (StringUtils.ToToggleBool(settings.togglePassSavingThrowIndividual)) { for (int i = 0; i < settings.togglePassSavingThrowIndividualArray.Count(); i++) { if (StringUtils.ToToggleBool(settings.togglePassSavingThrowIndividualArray[i]) && Storage.statsSavesDict[Storage.individualSavesArray[i]] == __instance.StatType) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, (UnitSelectType)settings.indexPassSavingThrowIndividuall)) { __result = true; } } } } if (StringUtils.ToToggleBool(settings.togglePassSkillChecksIndividual)) { for (int i = 0; i < settings.togglePassSkillChecksIndividualArray.Count(); i++) { if (StringUtils.ToToggleBool(settings.togglePassSkillChecksIndividualArray[i]) && Storage.statsSkillsDict.Union(Storage.statsSocialSkillsDict).ToDictionary(d => d.Key, d => d.Value)[Storage.individualSkillsArray[i]] == __instance.StatType) { if (UnitEntityDataUtils.CheckUnitEntityData(__instance.Initiator, (UnitSelectType)settings.indexPassSkillChecksIndividual)) { __result = true; } } } } #endif }
static void Postfix(RuleRollDice __instance) { if (__instance.DiceFormula.Dice != DiceType.D20) { return; } var initiator = __instance.Initiator; int result = __instance.m_Result; Logger.ModLoggerDebug("Initial D20Roll: " + result); if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.alwaysRoll20)) { result = 20; } else if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.alwaysRoll1)) { result = 1; } else { if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.rollWithAdvantage)) { result = Math.Max(result, UnityEngine.Random.Range(1, 21)); } else if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.rollWithDisadvantage)) { result = Math.Min(result, UnityEngine.Random.Range(1, 21)); } int min = 1; if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.neverRoll1) && result == 1) { result = UnityEngine.Random.Range(2, 21); min = 2; } if (UnitEntityDataUtils.CheckUnitEntityData(initiator, settings.neverRoll20) && result == 20) { result = UnityEngine.Random.Range(min, 20); } } Logger.ModLoggerDebug("Modified D20Roll: " + result); __instance.m_Result = result; }
public static void Functions(int index) { switch (index) { case 0: break; case 1: GameInfo(); break; case 2: KillFunctions(); break; case 3: UnitEntityDataUtils.ResurrectAndFullRestore(Common.GetUnitUnderMouse()); break; case 4: UnitEntityDataUtils.Buff(Common.GetUnitUnderMouse(), FavouritesFactory.GetFavouriteBuffs.FavouritesList[Main.settings.actionKeyBuffIndex]); break; case 5: editUnit = Common.GetUnitUnderMouse(); break; case 6: teleportUnit = Common.GetUnitUnderMouse(); if (teleportUnit != null && StringUtils.ToToggleBool(Main.settings.toggleAddToLog)) { Common.AddLogEntry(Strings.GetText("label_TeleportUnit") + $": {teleportUnit.CharacterName}", Color.black); } break; case 7: if (StringUtils.ToToggleBool(settings.toggleSpawnEnemiesFromUnitFavourites)) { try { Vector3 pos = Common.MousePositionLocalMap(); float x = 0.0f; float z = 0.0f; foreach (string guid in SpawnUnits.GetStoredGUIDs) { Vector3 finalPos = new Vector3(pos.x + 1.5f * x, pos.y, pos.z + 1.5f * z); SpawnUnits.UnitSpawner(finalPos, guid); x++; if (x > 10f) { x = 0.0f; z++; } } } catch (Exception e) { modLogger.Log(e.ToString()); } } else if (settings.actionKeySpawnRandomEnemy && StringUtils.ToToggleBool(settings.toggleActionKeyExperimental)) { try { Common.SpawnHostileUnit(Common.MousePositionLocalMap(), ResourcesLibrary.GetBlueprints <BlueprintUnit>().RandomElement()); } catch (Exception e) { modLogger.Log(e.ToString()); } } else { Common.SpawnHostileUnit(Common.MousePositionLocalMap(), banditsGuids[banidtCrIndex]); } break; case 8: rotateUnit = Common.GetUnitUnderMouse(); if (rotateUnit != null && StringUtils.ToToggleBool(Main.settings.toggleAddToLog)) { Common.AddLogEntry(Strings.GetText("arrayItem_ActionKeyMain_RotateUnit") + $": {rotateUnit.CharacterName}", Color.black); } break; case 9: Common.GetUnitUnderMouse().View.AnimationManager.Execute(animationTypes[animationTypesIndex]); break; case 10: FxHelper.SpawnFxOnPoint(BlueprintRoot.Instance.Cheats.SillyCheatBlood, Common.MousePositionLocalMap()); break; case 11: UnitEntityDataUtils.Charm(Common.GetUnitUnderMouse()); break; case 12: UnitEntityDataUtils.AddToParty(Common.GetUnitUnderMouse()); break; case 13: Common.GetUnitUnderMouse().Descriptor.Recreate = true; break; } }
public static void ActionKeyEditStatsGui(UnitEntityData unit) { GL.Space(10); GL.BeginHorizontal(); ActionKey.editUnitSelectedSizeIndex = GL.SelectionGrid(ActionKey.editUnitSelectedSizeIndex, Storage.charSizeArray, 4); GL.EndHorizontal(); GL.Space(10); GL.BeginHorizontal(); if (GL.Button(Strings.GetText("button_SetSizeTo") + $" {Storage.charSizeArray[ActionKey.editUnitSelectedSizeIndex]}", GL.ExpandWidth(false))) { unit.Descriptor.State.Size = (Size)ActionKey.editUnitSelectedSizeIndex; } GL.EndHorizontal(); GL.BeginHorizontal(); if (GL.Button(Strings.GetText("button_SetToOriginalSize") + $" ({unit.Descriptor.OriginalSize})", GL.ExpandWidth(false))) { unit.Descriptor.State.Size = unit.Descriptor.OriginalSize; } GL.EndHorizontal(); MenuTools.SingleLineLabel(Strings.GetText("label_CurrentSize") + ": " + unit.Descriptor.State.Size); GL.Space(10); GL.BeginHorizontal(); if (unit.Descriptor.HPLeft > 0) { if (GL.Button(Strings.GetText("button_Kill"), GL.ExpandWidth(false))) { UnitEntityDataUtils.Kill(unit); } if (GL.Button(Strings.GetText("button_Panic"), GL.ExpandWidth(false))) { unit.Descriptor.AddFact((BlueprintUnitFact)Utilities.GetBlueprintByGuid <BlueprintBuff>("cf0e277e6b785f449bbaf4e993b556e0"), (MechanicsContext)null, new FeatureParam()); } if (GL.Button(Strings.GetText("button_Freeze"), GL.ExpandWidth(false))) { unit.Descriptor.AddFact((BlueprintUnitFact)Utilities.GetBlueprintByGuid <BlueprintBuff>("af1e2d232ebbb334aaf25e2a46a92591"), (MechanicsContext)null, new FeatureParam()); } if (GL.Button(Strings.GetText("button_MakeCower"), GL.ExpandWidth(false))) { unit.Descriptor.AddFact((BlueprintUnitFact)Utilities.GetBlueprintByGuid <BlueprintBuff>("6062e3a8206a4284d867cbb7120dc091"), (MechanicsContext)null, new FeatureParam()); } if (GL.Button(Strings.GetText("button_SetOnFire"), GL.ExpandWidth(false))) { unit.Descriptor.AddFact((BlueprintUnitFact)Utilities.GetBlueprintByGuid <BlueprintBuff>("315acb0b29671f74c8c7cc062b23b9d6"), (MechanicsContext)null, new FeatureParam()); } } GL.EndHorizontal(); GL.BeginHorizontal(); editUnitStatsAmount = GL.TextField(editUnitStatsAmount, 10, GL.Width(85f)); MenuTools.SettingParse(ref editUnitStatsAmount, ref editUnitFinalStatsAmount); GL.EndHorizontal(); CharacterStats charStats = unit.Descriptor.Stats; MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_AttributesBaseValues"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsAttributesDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, ActionKey.editUnitFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_SkillsRanks"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSkillsDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, ActionKey.editUnitFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_SocialSkillsBaseValues"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSocialSkillsDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, ActionKey.editUnitFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_StatsSaves"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSavesDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, ActionKey.editUnitFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_StatsCombat"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsCombatDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, ActionKey.editUnitFinalStatsAmount); } }
public static void Render() { GL.BeginVertical("box"); GL.BeginHorizontal(); settings.showPartyStatisticsCategory = GL.Toggle(settings.showPartyStatisticsCategory, RichTextUtils.MainCategoryFormat(Strings.GetText("mainCategory_PartyStats")), GL.ExpandWidth(false)); if (!settings.showPartyStatisticsCategory) { GL.EndHorizontal(); } else { MenuTools.FlexibleSpaceCategoryMenuElementsEndHorizontal("PartyOptions"); GL.Space(10); MenuTools.ToggleButton(ref settings.toggleAccessRemoteCharacters, "buttonToggle_AccessRemoteCharacters", "tooltip_AccessRemoteCharacters", nameof(settings.toggleAccessRemoteCharacters)); MenuTools.ToggleButtonActions(ref settings.toggleShowAllPartyPortraits, GroupControllerUtils.NaviBlockShowAllPartyMembers, GroupControllerUtils.NaviBlockShowDefault, "buttonToggle_ShowAllPartyPortraits", "tooltip_ShowAllPartyPortraits", nameof(settings.toggleShowAllPartyPortraits)); GL.Space(10); GL.BeginHorizontal(); Storage.statsFilterUnitEntityDataIndex = GL.SelectionGrid(Storage.statsFilterUnitEntityDataIndex, unitEntityDataFiltersArray, 3); GL.EndHorizontal(); Player player = Game.Instance.Player; switch (Storage.statsFilterUnitEntityDataIndex) { case 0: Storage.statsUnitEntityData = player.Party; break; case 1: Storage.statsUnitEntityData = player.ControllableCharacters; break; case 2: Storage.statsUnitEntityData = player.ActiveCompanions; break; case 3: Storage.statsUnitEntityData = player.AllCharacters; break; case 4: Storage.statsUnitEntityData = PartyUtils.GetRemoteCompanions(); break; case 5: Storage.statsUnitEntityData = PartyUtils.GetCustomCompanions(); break; case 6: Storage.statsUnitEntityData = PartyUtils.GetPets(); break; } if (Storage.statsFilterUnitEntityDataIndex != Storage.statsFilterUnitEntityDataIndexOld) { Storage.reloadPartyStats = true; Storage.statsFilterUnitEntityDataIndexOld = Storage.statsFilterUnitEntityDataIndex; } GL.Space(10); if (Storage.statsUnitEntityData.Any()) { if (Storage.reloadPartyStats) { Storage.statsSelectedControllableCharacterIndex = 0; Storage.statsPartyMembers = Storage.statsUnitEntityData; Storage.statsControllableCharacterNamesList.Clear(); foreach (UnitEntityData controllableCharacter in Storage.statsUnitEntityData) { Storage.statsControllableCharacterNamesList.Add(controllableCharacter.CharacterName); } Storage.reloadPartyStats = false; } if (!Storage.reloadPartyStats) { GL.BeginHorizontal(); Storage.statsSelectedControllableCharacterIndex = GL.SelectionGrid(Storage.statsSelectedControllableCharacterIndex, Storage.statsControllableCharacterNamesList.ToArray(), 6); GL.EndHorizontal(); GL.Space(10); GL.BeginVertical("box"); if (Storage.statsFilterUnitEntityDataIndex != 4) { MenuTools.SingleLineLabelGt("warning_SelectRemoteCharacters"); } else { if (GL.Button(MenuTools.TextWithTooltip("button_AddRemoteCompanionToParty", "tooltip_AddRemoteCompanionToParty", false), GL.ExpandWidth(false))) { UnitEntityDataUtils.AddCompanion(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex]); } GL.Space(10); if (!StringUtils.ToToggleBool(settings.toggleShowAllPartyPortraits) && Game.Instance.Player.Party.Count > 6) { MenuTools.SingleLineLabelGt("warning_PartyLimitShowAllPartyPortraits"); } } GL.EndVertical(); GL.Space(10); MainMenu.CurrentHitPointsOptions(); GL.Space(10); MainMenu.ChangeName(); GL.Space(10); MainMenu.ChangeGender(); GL.Space(10); MainMenu.ClassData(); GL.Space(10); //Menu.RaceData(); //GL.Space(10); /* * if (GL.Button(MenuTools.TextWithTooltip("button_RemoveEquippedItems", "tooltip_RemoveEquippedItems", false), GL.ExpandWidth(false))) * { * foreach (ItemEntity itemEntity in Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Inventory.Items) * { * if (itemEntity.Owner == Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor) * { * itemEntity.HoldingSlot.RemoveItem(); * } * } * } * GL.Space(10);*/ GL.BeginVertical("box"); GL.BeginHorizontal(); if (GL.Button(MenuTools.TextWithTooltip("button_ResetCharacterLevel", "tooltip_ResetCharacterLevel", false), GL.ExpandWidth(false))) { int level = 21; int xp = Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression.Experience; BlueprintStatProgression xpTable = BlueprintRoot.Instance.Progression.XPTable; for (int i = 20; i >= 1; i--) { int xpBonus = xpTable.GetBonus(i); modLogger.Log(i + ": " + xpBonus + " | " + xp); if ((xp - xpBonus) >= 0) { modLogger.Log(i + ": " + (xp - xpBonus)); level = i; break; } } Type type = Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression.GetType(); PropertyInfo propertyInfo = type.GetProperty("CharacterLevel"); propertyInfo.SetValue(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression, level, null); } GL.EndHorizontal(); GL.Space(10); GL.BeginHorizontal(); Storage.setCharLevel = GL.HorizontalSlider(Storage.setCharLevel, 1f, 20f, GL.Width(250f)); GL.Label($" {Mathf.RoundToInt(Storage.setCharLevel)}", GL.ExpandWidth(false)); GL.EndHorizontal(); GL.BeginHorizontal(); if (GL.Button(MenuTools.TextWithTooltip("button_SetCharacterLevel", "tooltip_SetCharacterLevel", "", $" {Mathf.RoundToInt(Storage.setCharLevel)}" + " " + StringUtils.PutInParenthesis(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName)), GL.ExpandWidth(false))) { Type type = Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression.GetType(); PropertyInfo propertyInfoLvl = type.GetProperty("CharacterLevel"); propertyInfoLvl.SetValue(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression, Mathf.RoundToInt(Storage.setCharLevel), null); int newXp = BlueprintRoot.Instance.Progression.XPTable.GetBonus(Mathf.RoundToInt(Storage.setCharLevel)); PropertyInfo propertyInfoXp = type.GetProperty("Experience"); propertyInfoXp.SetValue(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Progression, newXp, null); } GL.EndHorizontal(); MenuTools.SingleLineLabel(Strings.GetText("warning_SetCharacterLevel")); GL.EndVertical(); GL.Space(10); MenuTools.UnitAlignment(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex]); GL.Space(10); GL.BeginVertical("box"); MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_Size"))); GL.BeginHorizontal(); Storage.partySelectedSizeIndex = GL.SelectionGrid(Storage.partySelectedSizeIndex, Storage.charSizeArray, 4); GL.EndHorizontal(); GL.Space(10); GL.BeginHorizontal(); if (GL.Button(MenuTools.TextWithTooltip("button_SetSizeTo", "tooltip_SetSize", "", $" {Storage.charSizeArray[Storage.partySelectedSizeIndex]}"), GL.ExpandWidth(false))) { Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.State.Size = (Size)Storage.partySelectedSizeIndex; } GL.EndHorizontal(); GL.BeginHorizontal(); if (GL.Button(MenuTools.TextWithTooltip("button_SetToOriginalSize", "tooltip_SetToOriginalSize", "", $" ({Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.OriginalSize})"), GL.ExpandWidth(false))) { Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.State.Size = Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.OriginalSize; } GL.EndHorizontal(); MenuTools.SingleLineLabel(Strings.GetText("label_CurrentSize") + ": " + Common.SizeToString(Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.State.Size)); GL.EndVertical(); GL.Space(10); GL.BeginHorizontal(); GL.Label(MenuTools.TextWithTooltip("header_Statistics", "tooltip_Statistics", true)); GL.EndHorizontal(); GL.BeginHorizontal(); settings.partyStatsAmount = GL.TextField(settings.partyStatsAmount, 10, GL.Width(85f)); MenuTools.SettingParse(ref settings.partyStatsAmount, ref settings.partyFinalStatsAmount); GL.EndHorizontal(); CharacterStats charStats = Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].Descriptor.Stats; MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_AttributesBaseValues"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsAttributesDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_SkillsRanks"))); MenuTools.ToggleButton(ref settings.toggleShowOnlyClassSkills, "buttonToggle_ShowOnlyClassSkills", "tooltip_ShowOnlyClassSkills"); foreach (KeyValuePair <string, StatType> entry in Storage.statsSkillsDict) { if (StringUtils.ToToggleBool(settings.toggleShowOnlyClassSkills)) { ModifiableValueSkill stat = charStats.GetStat(entry.Value) as ModifiableValueSkill; if (stat.ClassSkill && stat.BaseValue > 0) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount); } } else { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount, true); } } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_SocialSkillsBaseValues"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSocialSkillsDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_StatsSaves"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSavesDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_StatsCombat"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsCombatDict) { MenuTools.CreateStatInterface(entry.Key, charStats, entry.Value, settings.partyFinalStatsAmount); } GL.Space(10); GL.BeginHorizontal(); GL.Label(MenuTools.TextWithTooltip("header_PartyMultipliers", "tooltip_PartyMultipliers", true)); GL.EndHorizontal(); GL.BeginHorizontal(); settings.partyStatMultiplier = GL.HorizontalSlider(settings.partyStatMultiplier, 0.1f, 10f, GL.Width(300f)); GL.Label($" {Math.Round(settings.partyStatMultiplier, 1)}", GL.ExpandWidth(false)); GL.EndHorizontal(); MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_Attributes"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsAttributesDict) { MenuTools.CreateStatMultiplierInterface(entry.Key, charStats, entry.Value, Storage.statsPartyMembers, settings.partyStatMultiplier); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_Skills"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSkillsDict) { MenuTools.CreateStatMultiplierInterface(entry.Key, charStats, entry.Value, Storage.statsPartyMembers, settings.partyStatMultiplier); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_SocialSkills"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSocialSkillsDict) { MenuTools.CreateStatMultiplierInterface(entry.Key, charStats, entry.Value, Storage.statsPartyMembers, settings.partyStatMultiplier); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_Saves"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsSavesDict) { MenuTools.CreateStatMultiplierInterface(entry.Key, charStats, entry.Value, Storage.statsPartyMembers, settings.partyStatMultiplier); } MenuTools.SingleLineLabel(RichTextUtils.Bold(Strings.GetText("header_Combat"))); foreach (KeyValuePair <string, StatType> entry in Storage.statsCombatDict) { MenuTools.CreateStatMultiplierInterface(entry.Key, charStats, entry.Value, Storage.statsPartyMembers, settings.partyStatMultiplier); } GL.BeginHorizontal(); if (GL.Button(MenuTools.TextWithTooltip("button_ExportCharInfo", "tooltip_ExportCharInfo", false), GL.ExpandWidth(false))) { List <string> charInfoTxt = new List <string>(); charInfoTxt.Add($"{Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName}"); charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_AttributesBaseValues")); foreach (KeyValuePair <string, StatType> entry in Storage.statsAttributesDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_SkillsRanks")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSkillsDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_SocialSkillsBaseValues")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSocialSkillsDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_StatsSaves")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSavesDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_StatsCombat")); foreach (KeyValuePair <string, StatType> entry in Storage.statsCombatDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } File.WriteAllLines(Path.Combine(Common.ExportPath(), $"{Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName}.txt"), charInfoTxt.ToArray()); } GL.Label(" " + Strings.GetText("label_Location") + $": {Path.Combine(Common.ExportPath(), $"{Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName}.txt")}"); GL.EndHorizontal(); if (File.Exists(Storage.modEntryPath + Storage.charactersImportFolder + "\\" + Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName + ".txt")) { if (GL.Button(MenuTools.TextWithTooltip("button_ImportStatsFrom", "tooltip_ImportStatsFrom", "", $" { Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName}.txt"), GL.ExpandWidth(false))) { if (settings.settingCreateBackupBeforeImport) { List <string> charInfoTxt = new List <string>(); charInfoTxt.Add($"{Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName}"); charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_AttributesBaseValues")); foreach (KeyValuePair <string, StatType> entry in Storage.statsAttributesDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_SkillsRanks")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSkillsDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_SocialSkillsBaseValues")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSocialSkillsDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_StatsSaves")); foreach (KeyValuePair <string, StatType> entry in Storage.statsSavesDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } charInfoTxt.Add(""); charInfoTxt.Add(Strings.GetText("header_StatsCombat")); foreach (KeyValuePair <string, StatType> entry in Storage.statsCombatDict) { charInfoTxt.Add(($"{entry.Key}: {charStats.GetStat(entry.Value).BaseValue} ({charStats.GetStat(entry.Value).ModifiedValue})")); } File.WriteAllLines(Path.Combine(Storage.modEntryPath + Storage.charactersImportFolder + "\\" + Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName + "_Backup.txt"), charInfoTxt.ToArray()); } string[] lines = File.ReadAllLines(Storage.modEntryPath + Storage.charactersImportFolder + "\\" + Storage.statsPartyMembers[Storage.statsSelectedControllableCharacterIndex].CharacterName + ".txt"); lines = lines.Where(x => !string.IsNullOrEmpty(x)).ToArray(); lines = lines.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray(); for (int i = 0; i < lines.Length; i++) { if (Regex.IsMatch(lines[i], @"[\x20A-Za-z()]+:\s*[0-9]+")) { Match match = Regex.Match(lines[i], @"[\x20A-Za-z()]+:\s*[0-9]+"); lines[i] = match.Value; string[] splitLine = lines[i].Split(':'); Dictionary <string, StatType> allStats = Storage.statsAttributesDict.Union(Storage.statsSkillsDict).Union(Storage.statsSocialSkillsDict).Union(Storage.statsSavesDict).Union(Storage.statsCombatDict).ToDictionary(k => k.Key, v => v.Value); if (allStats.TryGetValue(splitLine[0], out StatType statType) && int.TryParse(splitLine[1], out int baseValue)) { charStats.GetStat(statType).BaseValue = baseValue; } } else { } } } } } } else { MenuTools.SingleLineLabel(Strings.GetText("message_NoUnitFound")); } } GL.EndVertical(); }