diff --git a/Resources/RotationSolverRecord.json b/Resources/RotationSolverRecord.json index 6472150d3..2dbfe9c17 100644 --- a/Resources/RotationSolverRecord.json +++ b/Resources/RotationSolverRecord.json @@ -1,5 +1,5 @@ { - "ClickingCount": 60549, + "ClickingCount": 61038, "SayingHelloCount": 13, "SaidUsers": [] } \ No newline at end of file diff --git a/RotationSolver.Basic/Actions/ActionTargetInfo.cs b/RotationSolver.Basic/Actions/ActionTargetInfo.cs index 2d0bd8eb3..8bf0f06b6 100644 --- a/RotationSolver.Basic/Actions/ActionTargetInfo.cs +++ b/RotationSolver.Basic/Actions/ActionTargetInfo.cs @@ -751,10 +751,12 @@ private readonly bool CanGetTarget(GameObject target, GameObject subTarget) return null; } - private static BattleChara RandomObject(IEnumerable objs) + private static BattleChara? RandomObject(IEnumerable objs) { Random ran = new(DateTime.Now.Millisecond); - return objs.ElementAt(ran.Next(objs.Count())); + var count = objs.Count(); + if (count == 0) return null; + return objs.ElementAt(ran.Next(count)); } #endregion diff --git a/RotationSolver.Basic/Attributes/UIAttributes.cs b/RotationSolver.Basic/Attributes/UIAttributes.cs index 58f83040e..b8f033b3d 100644 --- a/RotationSolver.Basic/Attributes/UIAttributes.cs +++ b/RotationSolver.Basic/Attributes/UIAttributes.cs @@ -18,6 +18,7 @@ public class UIAttribute(string name) : Attribute public enum JobFilterType : byte { + None, NoJob, NoHealer, Healer, @@ -28,12 +29,12 @@ public enum JobFilterType : byte Melee, } -[AttributeUsage(AttributeTargets.Field)] +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] internal class JobConfigAttribute : Attribute { } -[AttributeUsage(AttributeTargets.Field)] +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] internal class JobChoiceConfigAttribute : Attribute { } diff --git a/RotationSolver.Basic/Configuration/Configs.cs b/RotationSolver.Basic/Configuration/Configs.cs index e825c0dbd..b53f9cab4 100644 --- a/RotationSolver.Basic/Configuration/Configs.cs +++ b/RotationSolver.Basic/Configuration/Configs.cs @@ -312,7 +312,7 @@ public const string [ConditionBool, UI("Automatically trigger dps burst phase", Filter = AutoActionCondition)] private static readonly bool _autoBurst = true; - [ConditionBool, UI("Automatic Heal")] + [ConditionBool, UI("Automatic Heal", Filter = AutoActionCondition)] private static readonly bool _autoHeal = true; [ConditionBool, UI("Auto-use abilities", Filter = AutoActionUsage)] @@ -711,11 +711,11 @@ public const string [LinkDescription($"https://raw.githubusercontent.com/{Service.USERNAME}/{Service.REPO}/main/Images/HowAndWhenToClick.svg", "This plugin helps you to use the right action during the combat. Here is a guide about the different options.")] [JobConfig, Range(0, 0.5f, ConfigUnitType.Seconds)] - [UI("Action Ahead")] + [UI("Action Ahead", Filter = BasicTimer)] private readonly float _actionAhead = 0.08f; [JobConfig, UI("Engage settings", Filter = TargetConfig, PvPFilter = JobFilterType.NoJob)] - private readonly TargetHostileType _hostileType; + private readonly TargetHostileType _hostileType = TargetHostileType.TargetsHaveTarget; [JobConfig] private readonly string _PvPRotationChoice = string.Empty; diff --git a/RotationSolver.Basic/Rotations/Basic/BardRotation.cs b/RotationSolver.Basic/Rotations/Basic/BardRotation.cs index 6ecc8f9cd..8898a358d 100644 --- a/RotationSolver.Basic/Rotations/Basic/BardRotation.cs +++ b/RotationSolver.Basic/Rotations/Basic/BardRotation.cs @@ -71,11 +71,15 @@ static partial void ModifyWindbitePvE(ref ActionSetting setting) static partial void ModifyIronJawsPvE(ref ActionSetting setting) { - setting.TargetStatusNeed = setting.TargetStatusProvide = - [StatusID.VenomousBite, StatusID.CausticBite, - StatusID.Windbite, StatusID.Stormbite]; + setting.TargetStatusProvide = [StatusID.VenomousBite, StatusID.CausticBite, StatusID.Windbite, StatusID.Stormbite]; + setting.CanTarget = t => + { + if (t.WillStatusEndGCD(0, 0, true, StatusID.VenomousBite, StatusID.CausticBite)) return false; + if (t.WillStatusEndGCD(0, 0, true, StatusID.Windbite, StatusID.Stormbite)) return false; + return true; + }; } - + static partial void ModifyPitchPerfectPvE(ref ActionSetting setting) { setting.ActionCheck = () => Song == Song.WANDERER && Repertoire > 0; diff --git a/RotationSolver.SourceGenerators/JobChoiceConfigGenerator.cs b/RotationSolver.SourceGenerators/JobChoiceConfigGenerator.cs index 398e6652e..f50acee1b 100644 --- a/RotationSolver.SourceGenerators/JobChoiceConfigGenerator.cs +++ b/RotationSolver.SourceGenerators/JobChoiceConfigGenerator.cs @@ -68,6 +68,7 @@ private void Execute(SourceProductionContext context, ImmutableArray<(VariableDe is "RotationSolver.Basic.Attributes.UIAttribute" or "RotationSolver.Basic.Attributes.UnitAttribute" or "RotationSolver.Basic.Attributes.RangeAttribute" + or "RotationSolver.Basic.Attributes.JobChoiceConfigAttribute" or "RotationSolver.Basic.Attributes.LinkDescriptionAttribute") { names.Add(attr.ToString()); diff --git a/RotationSolver.SourceGenerators/JobConfigGenerator.cs b/RotationSolver.SourceGenerators/JobConfigGenerator.cs index 2aa3682ca..b0b4d91b7 100644 --- a/RotationSolver.SourceGenerators/JobConfigGenerator.cs +++ b/RotationSolver.SourceGenerators/JobConfigGenerator.cs @@ -65,6 +65,7 @@ private void Execute(SourceProductionContext context, ImmutableArray<(VariableDe is "RotationSolver.Basic.Attributes.UIAttribute" or "RotationSolver.Basic.Attributes.UnitAttribute" or "RotationSolver.Basic.Attributes.RangeAttribute" + or "RotationSolver.Basic.Attributes.JobConfigAttribute" or "RotationSolver.Basic.Attributes.LinkDescriptionAttribute") { names.Add(attr.ToString()); diff --git a/RotationSolver/Localization/Localization.json b/RotationSolver/Localization/Localization.json index 101b3963e..b86f2f6d2 100644 --- a/RotationSolver/Localization/Localization.json +++ b/RotationSolver/Localization/Localization.json @@ -1,25 +1,10 @@ { "RotationSolver.Data.UiString.ConfigWindowHeader": "Rotation Solver Settings v", "RotationSolver.Data.UiString.Commands_Rotation": "Open config window.", - "RotationSolver.Data.UiString.ConfigWindow_About_Punchline": "Analyses PvE combat information in every frame and finds the best action.", - "RotationSolver.Data.UiString.ConfigWindow_About_Clicking100k": "Well, you must be a lazy player!", - "RotationSolver.Data.UiString.ConfigWindow_About_Clicking500k": "You're tiring RS out, give it a break!", - "RotationSolver.Data.UiString.ConfigWindow_Helper_GameVersion": "Game", - "RotationSolver.Data.UiString.ConfigWindow_Helper_SwitchRotation": "Click to switch rotations", - "RotationSolver.Data.UiString.ConfigWindow_ConditionSetDesc": "The condition set you chose, click to modify.", - "RotationSolver.Data.UiString.ConfigWindow_Searching": "Search... ", - "RotationSolver.Data.UiString.ConfigWindow_About_Description": "This means almost all the information available in one frame in combat, including the status of all players in the party, the status of any hostile targets, skill cooldowns, the MP and HP of characters, the location of characters, casting status of the hostile target, combo, combat duration, player level, etc.\n\nThen, it will highlight the best action on the hot bar, or help you to click on it.", - "RotationSolver.Data.UiString.ConfigWindow_About_Warning": "It is designed for GENERAL COMBAT, not for savage or ultimate. Use it carefully.", - "RotationSolver.Data.UiString.ConfigWindow_About_ClickingCount": "Rotation Solver helped you by clicking actions {0:N0} times.", - "RotationSolver.Data.UiString.ConfigWindow_About_SayHelloCount": "You have said hello to other users {0:N0} times!", - "RotationSolver.Data.UiString.ConfigWindow_About_Macros": "Macro", - "RotationSolver.Data.UiString.ConfigWindow_About_Compatibility": "Compatibility", - "RotationSolver.Data.UiString.ConfigWindow_About_Supporters": "Supporters", - "RotationSolver.Data.UiString.ConfigWindow_About_Links": "Links", "RotationSolver.Basic.Data.StateCommandType.Manual": "Start the addon in Manual mode. You need to choose the target manually. This will bypass any engage settings that you have set up and will start attacking immediately once something is targeted.", "RotationSolver.Basic.Data.StateCommandType.Cancel": "Stop the addon. Always remember to turn it off when it is not in use!", "RotationSolver.Basic.Data.StateCommandType.Auto": "Start the addon in Auto mode. When out of combat or when combat starts, switches the target according to the set condition.", - "RotationSolver.Basic.Data.TargetingType.Big": "Big", + "RotationSolver.Basic.Data.TargetingType.Small": "Small", "RotationSolver.Data.UiString.InfoWindowNoMove": "No Move", "RotationSolver.Data.UiString.InfoWindowMove": "Move", "RotationSolver.Basic.Data.SpecialCommandType.HealArea": "Open a window to use AoE heal.", @@ -35,58 +20,61 @@ "RotationSolver.Basic.Data.SpecialCommandType.AntiKnockback": "Open a window to use knockback immunity actions.", "RotationSolver.Basic.Data.SpecialCommandType.Speed": "Open a window to speed up.", "RotationSolver.Basic.Data.TargetHostileType.AllTargetsCanAttack": "All targets that are in range for any abilities", - "RotationSolver.Data.UiString.ActionAttack": "Attack", "RotationSolver.Data.UiString.ActionAbility": "Ability", + "RotationSolver.Data.UiString.ActionAttack": "Attack", "RotationSolver.Data.UiString.ActionFriendly": "Friendly", - "RotationSolver.Data.UiString.ConfigWindow_Rotation_Description": "Description", - "RotationSolver.Data.UiString.ConfigWindow_Rotation_Status": "Status", - "RotationSolver.Data.UiString.ConfigWindow_Rotation_Configuration": "Configuration", - "RotationSolver.Data.UiString.ConfigWindow_Rotation_Rating": "Rating", - "RotationSolver.Data.UiString.ConfigWindow_Rotation_Information": "Information", - "RotationSolver.UI.RotationConfigWindowTab.UI": "Settings about the user interface.", - "RotationSolver.UI.RotationConfigWindowTab.Basic": "Basic settings", - "RotationSolver.UI.RotationConfigWindowTab.List": "Some things that have to be lists.", - "RotationSolver.UI.RotationConfigWindowTab.Rotations": "All rotations that RS has loaded.", - "RotationSolver.UI.RotationConfigWindowTab.Actions": "The abilities and custom conditions that your selected job has.", - "RotationSolver.Data.UiString.ConfigWindow_Actions_Description": "To customize when Rotation Solver uses specific actions automatically, click on an action's icon in the left list. Below, you may set the conditions for when that specific action is used. Each action can have a different set of conditions to override the default rotation behavior.", - "RotationSolver.Data.UiString.ConfigWindow_Actions_ConditionDescription": "Forced Conditions have a higher priority. If Forced Conditions are met, Disabled Condition will be ignored.", - "RotationSolver.Data.UiString.ConfigWindow_Actions_ForcedConditionSet": "Forced Condition", - "RotationSolver.Data.UiString.ConfigWindow_Actions_DisabledConditionSet": "Disabled Condition", - "RotationSolver.Data.UiString.ConfigWindow_UI_Information": "Information", - "RotationSolver.Data.UiString.ConfigWindow_UI_Overlay": "Overlay", - "RotationSolver.Data.UiString.ConfigWindow_UI_Windows": "Windows", - "DrawMeleeOffsetName": "Draw the offset of melee on the screen", - "ShowMoveTargetName": "Show the target of the move action", - "ShowHostilesIconsName": "Show the hostile target icon", - "TeachingModeName": "Teaching mode", - "UseOverlayWindowName": "Display UI Overlay", - "ShowStateIconName": "Show RS state icon", - "ShowBeneficialPositionsName": "Show beneficial AoE locations.", - "ShowHostilesIconsDescription": "", - "UseOverlayWindowDescription": "This top window is used to display some extra information on your game window, such as target's positional, target and sub-target, etc.", - "InfoWindowBgName": "Info Window's Background", - "DrawIconAnimationName": "Show RS logo animation", - "OnlyShowWithHostileOrInDutyName": "Only show these windows if there are enemies in or in duty", - "ShowControlWindowName": "Show Control Window", - "IsControlWindowLockName": "Is Control Window Lock", - "ShowNextActionWindowName": "Show Next Action Window", - "ShowCooldownWindowName": "Show Cooldown Window", - "ShowCooldownWindowDescription": "", - "CooldownFontSizeName": "Change the cooldown font size.", - "CooldownWindowIconSizeName": "Cooldown window icon size", - "ShowItemsCooldownName": "Show Items' Cooldown", - "ShowGcdCooldownName": "Show GCD' Cooldown", - "UseOriginalCooldownName": "Show Original Cooldown", - "CooldownFontSizeDescription": "", - "RotationSolver.Basic.Attributes.ConfigUnitType.Pixels": "Display Unit, in pixels.", - "CooldownWindowIconSizeDescription": "", - "ShowGcdCooldownDescription": "", - "UseOriginalCooldownDescription": "", - "RotationSolver.Data.UiString.ConfigWindow_Actions_ShowOnCDWindow": "Show on CD window", - "RotationSolver.Data.UiString.ConfigWindow_Actions_TTK": "TTK that this action needs the target be.", - "RotationSolver.Basic.Attributes.ConfigUnitType.Seconds": "Time Unit, in seconds.", - "RotationSolver.Data.UiString.ConfigWindow_Actions_HealRatio": "The HP ratio to auto heal", - "RotationSolver.Basic.Attributes.ConfigUnitType.Percent": "Ratio Unit, as percentage.", + "RotationSolver.Data.UiString.ConfigWindow_About_Punchline": "Analyses PvE combat information in every frame and finds the best action.", + "RotationSolver.Data.UiString.ConfigWindow_About_Clicking100k": "Well, you must be a lazy player!", + "RotationSolver.Data.UiString.ConfigWindow_About_Clicking500k": "You're tiring RS out, give it a break!", + "RotationSolver.Data.UiString.ConfigWindow_Helper_GameVersion": "Game", + "RotationSolver.Data.UiString.ConfigWindow_Helper_SwitchRotation": "Click to switch rotations", + "RotationSolver.Data.UiString.ConfigWindow_ConditionSetDesc": "The condition set you chose, click to modify.", + "RotationSolver.Data.UiString.ConfigWindow_Searching": "Search... ", + "RotationSolver.Data.UiString.ConfigWindow_About_Description": "This means almost all the information available in one frame in combat, including the status of all players in the party, the status of any hostile targets, skill cooldowns, the MP and HP of characters, the location of characters, casting status of the hostile target, combo, combat duration, player level, etc.\n\nThen, it will highlight the best action on the hot bar, or help you to click on it.", + "RotationSolver.Data.UiString.ConfigWindow_About_Warning": "It is designed for GENERAL COMBAT, not for savage or ultimate. Use it carefully.", + "RotationSolver.Data.UiString.ConfigWindow_About_ClickingCount": "Rotation Solver helped you by clicking actions {0:N0} times.", + "RotationSolver.Data.UiString.ConfigWindow_About_SayHelloCount": "You have said hello to other users {0:N0} times!", + "RotationSolver.Data.UiString.ConfigWindow_About_Macros": "Macro", + "RotationSolver.Data.UiString.ConfigWindow_About_Compatibility": "Compatibility", + "RotationSolver.Data.UiString.ConfigWindow_About_Supporters": "Supporters", + "RotationSolver.Data.UiString.ConfigWindow_About_Links": "Links", + "RotationSolver.UI.RotationConfigWindowTab.Extra": "Some features that shouldn't be included in RS but help you.", "RotationSolver.UI.RotationConfigWindowTab.Target": "The way to find the targets, hostiles or friends.", - "RotationSolver.UI.RotationConfigWindowTab.Extra": "Some features that shouldn't be included in RS but help you." + "RotationSolver.Data.UiString.ConfigWindow_Target_Config": "Configuration", + "RotationSolver.Data.UiString.ConfigWindow_List_Hostile": "Hostile", + "RotationSolver.Data.UiString.ConfigWindow_Param_HostileDesc": "You can The logic of hostile target selection to allow flexibility in switching the logic of selecting hostile in battle.", + "RotationSolver.Data.UiString.ConfigWindow_List_Remove": "Remove", + "RotationSolver.Data.UiString.ConfigWindow_Actions_MoveUp": "Move Up", + "RotationSolver.Data.UiString.ConfigWindow_Actions_MoveDown": "Move Down", + "RotationSolver.Data.UiString.ConfigWindow_Param_HostileCondition": "Hostile target selection condition", + "MoveTargetAngleName": "The size of the sector angle that can be selected as the moveable target", + "DistanceForMovingName": "Use gapcloser as a damage ability if the distance to your target is less then this.", + "MoveTowardsScreenCenterName": "Using movement actions towards the object in the center of the screen", + "MoveAreaActionFarthestName": "Target movement area ability to the farthest possible location", + "BossTimeToKillName": "If target's time until death is higher than this, regard it as boss.", + "DyingTimeToKillName": "If target's time until death is lower than this, regard it is dying.", + "ChangeTargetForFateName": "Select only Fate targets in Fate", + "OnlyAttackInViewName": "Only attack the target in view.", + "OnlyAttackInVisionConeName": "Only attack the targets in vision cone", + "TargetFatePriorityName": "Target Fate priority", + "TargetHuntingRelicLevePriorityName": "Target Hunt/Relic/Leve priority.", + "TargetQuestPriorityName": "Target quest priority.", + "AddEnemyListToHostileName": "Add enemy list to the hostile targets.", + "ChooseAttackMarkName": "Priority attack targets with attack markers", + "FilterStopMarkName": "Never attack targets with stop markers", + "RotationSolver.Data.UiString.JobConfigTip": "This config is job specific", + "HostileTypeName": "Engage settings", + "SwitchTargetFriendlyName": "Target allies for friendly actions.", + "TargetAllForFriendlyName": "Target all for friendly actions (include passerby)", + "MoveTargetAngleDescription": "If the selection mode is based on character facing, i.e., targets within the character's viewpoint are moveable targets. \nIf the selection mode is screen-centered, i.e., targets within a sector drawn upward from the character's point are movable targets.", + "RotationSolver.Basic.Attributes.ConfigUnitType.Degree": "Angle Unit, in degrees.", + "BossTimeToKillDescription": "", + "RotationSolver.Basic.Attributes.ConfigUnitType.Seconds": "Time Unit, in seconds.", + "AddEnemyListToHostileDescription": "", + "ChooseAttackMarkDescription": "", + "FilterStopMarkDescription": "", + "HostileTypeDescription": "", + "RotationSolver.Basic.Data.TargetHostileType.TargetsHaveTarget": "Previously engaged targets (engages on countdown timer)", + "TargetAllForFriendlyDescription": "", + "SwitchTargetFriendlyDescription": "" } \ No newline at end of file diff --git a/RotationSolver/UI/SearchableCollection.cs b/RotationSolver/UI/SearchableCollection.cs index 2b3fc0395..d994c1a57 100644 --- a/RotationSolver/UI/SearchableCollection.cs +++ b/RotationSolver/UI/SearchableCollection.cs @@ -25,6 +25,9 @@ public SearchableCollection() var item = CreateSearchable(property); if (item == null) continue; + item.PvEFilter = new(ui.PvEFilter); + item.PvPFilter = new(ui.PvPFilter); + pairs.Add(new(ui, item)); if (item is not CheckBoxSearch search) continue; diff --git a/RotationSolver/UI/SearchableConfigs/EnumSearch.cs b/RotationSolver/UI/SearchableConfigs/EnumSearch.cs index 99f542333..26b973d79 100644 --- a/RotationSolver/UI/SearchableConfigs/EnumSearch.cs +++ b/RotationSolver/UI/SearchableConfigs/EnumSearch.cs @@ -5,7 +5,7 @@ internal class EnumSearch(PropertyInfo property) : Searchable(property) protected int Value { get => Convert.ToInt32(_property.GetValue(Service.Config)); - set => _property.SetValue(Service.Config, value); + set => _property.SetValue(Service.Config, Enum.ToObject(_property.PropertyType, value)); } protected override void DrawMain()