Add Health% as combat item use condition
authorLiza Carvelli <liza@carvel.li>
Sat, 12 Oct 2024 23:51:44 +0000 (01:51 +0200)
committerLiza Carvelli <liza@carvel.li>
Sat, 12 Oct 2024 23:51:44 +0000 (01:51 +0200)
QuestPaths/5.x - Shadowbringers/MSQ/L-5.55/4066_Death Unto Dawn.json
QuestPaths/6.x - Endwalker/MSQ/E-Elpis/4421_Petalouda Hunt.json
QuestPaths/6.x - Endwalker/Side Quests/Garlemald/4226_With Folded Hands.json
QuestPaths/quest-v1.json
Questionable.Model/Questing/CombatItemUse.cs
Questionable.Model/Questing/Converter/CombatItemUseConditionConverter.cs
Questionable.Model/Questing/ECombatItemUseCondition.cs
Questionable/Controller/CombatModules/ItemUseModule.cs

index dee4eaecfb608f7269dcbba020b8325fa56d0bf8..2e79679975813b1f05100d319a6473c54b7ed924 100644 (file)
@@ -55,7 +55,7 @@
       "Steps": [
         {
           "TerritoryId": 351,
-          "InteractionType": "WaitForManualProgress",
+          "InteractionType": "None",
           "Comment": "Credits"
         }
       ]
index 04c452c57b1391b4ea39395207be84871ba73b36..c11ebd1da9a14b012b46e1875db89df91e58b234 100644 (file)
       "Sequence": 2,
       "Steps": [
         {
+          "Position": {
+            "X": 206.0426,
+            "Y": 20.561113,
+            "Z": 629.14465
+          },
           "DataId": 1039998,
           "TerritoryId": 961,
-          "InteractionType": "WaitForManualProgress",
-          "Comment": "Capture Mobs with less than 50% HP"
+          "InteractionType": "Combat",
+          "EnemySpawnType": "OverworldEnemies",
+          "KillEnemyDataIds": [
+            13447, 13448, 13449
+          ],
+          "CombatItemUse": {
+            "ItemId": 2003232,
+            "Condition": "Health%",
+            "Value": 50
+          }
         }
       ]
     },
index dff6a220a331194777e1abc495696888500a0f7c..0001cbe93bab5e9f2ad80da37a94c73b1d3a5a41 100644 (file)
       "Sequence": 1,
       "Steps": [
         {
-          "DataId": 13468,
           "Position": {
             "X": -159.59418,
             "Y": 10.8,
             "Z": -468.8335
           },
+          "StopDistance": 0.5,
           "TerritoryId": 958,
-          "InteractionType": "WaitForManualProgress",
-          "Comment": "Use item 2003202 on 13468 after \"weakening\"",
+          "InteractionType": "Combat",
+          "EnemySpawnType": "OverworldEnemies",
+          "KillEnemyDataIds": [
+            13468
+          ],
+          "CombatItemUse": {
+            "ItemId": 2003202,
+            "Condition": "Health%",
+            "Value": 40
+          },
           "Fly": true
         }
       ]
index 50d39d05261b6c738575604419a200940b64154e..eefbf1eb7734ef6354e773645331f1e0e45bdfc3 100644 (file)
                   "Condition": {
                     "type": "string",
                     "enum": [
-                      "Incapacitated"
+                      "Incapacitated",
+                      "Health%"
                     ]
+                  },
+                  "Value": {
+                    "type": "integer"
                   }
                 },
                 "required": [
index bbcfd10065b43824959ffa28d3960ecbbf660c52..565a0c7788b0f41f34c2f7debce760dba350aea0 100644 (file)
@@ -9,4 +9,6 @@ public sealed class CombatItemUse
 
     [JsonConverter(typeof(CombatItemUseConditionConverter))]
     public ECombatItemUseCondition Condition { get; set; }
+
+    public int Value { get; set; }
 }
index d2bca66a7ad12bf1c72bb11e61fd140db8ce5f44..1b4086ffd07b3545bb3d634af9be229a7ddeacb0 100644 (file)
@@ -8,5 +8,6 @@ public sealed class CombatItemUseConditionConverter() : EnumConverter<ECombatIte
     private static readonly Dictionary<ECombatItemUseCondition, string> Values = new()
     {
         { ECombatItemUseCondition.Incapacitated, "Incapacitated" },
+        { ECombatItemUseCondition.HealthPercent, "Health%" },
     };
 }
index dab191e670b47df44a6594f52b7667666674d95d..7bb4e2b2092daf9a730a989ff5a5f3a55f7edc01 100644 (file)
@@ -4,4 +4,5 @@ public enum ECombatItemUseCondition
 {
     None,
     Incapacitated,
+    HealthPercent,
 }
index cff431617e6abfc22796f4c935b6c08398f9ac8d..91b4ca1dd44161f27c2ee921caba2664b68dd62c 100644 (file)
@@ -6,6 +6,7 @@ using Dalamud.Game.ClientState.Objects.Types;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.Game;
 using FFXIVClientStructs.FFXIV.Client.Game.Character;
+using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Questionable.Functions;
@@ -16,19 +17,17 @@ namespace Questionable.Controller.CombatModules;
 internal sealed class ItemUseModule : ICombatModule
 {
     private readonly IServiceProvider _serviceProvider;
-    private readonly GameFunctions _gameFunctions;
     private readonly ICondition _condition;
     private readonly ILogger<ItemUseModule> _logger;
 
     private ICombatModule? _delegate;
     private CombatController.CombatData? _combatData;
     private bool _isDoingRotation;
+    private DateTime _continueAt;
 
-    public ItemUseModule(IServiceProvider serviceProvider, GameFunctions gameFunctions, ICondition condition,
-        ILogger<ItemUseModule> logger)
+    public ItemUseModule(IServiceProvider serviceProvider, ICondition condition, ILogger<ItemUseModule> logger)
     {
         _serviceProvider = serviceProvider;
-        _gameFunctions = gameFunctions;
         _condition = condition;
         _logger = logger;
     }
@@ -51,6 +50,7 @@ internal sealed class ItemUseModule : ICombatModule
         {
             _combatData = combatData;
             _isDoingRotation = true;
+            _continueAt = DateTime.Now;
             return true;
         }
 
@@ -65,6 +65,7 @@ internal sealed class ItemUseModule : ICombatModule
             _isDoingRotation = false;
             _combatData = null;
             _delegate = null;
+            _continueAt = DateTime.Now;
         }
 
         return true;
@@ -75,6 +76,9 @@ internal sealed class ItemUseModule : ICombatModule
         if (_delegate == null)
             return;
 
+        if (_continueAt > DateTime.Now)
+            return;
+
         if (_combatData?.CombatItemUse == null)
         {
             _delegate.Update(nextTarget);
@@ -93,6 +97,7 @@ internal sealed class ItemUseModule : ICombatModule
                     {
                         _isDoingRotation = false;
                         _delegate.Stop();
+                        return;
                     }
                 }
 
@@ -100,7 +105,11 @@ internal sealed class ItemUseModule : ICombatModule
                 {
                     _isDoingRotation = false;
                     _delegate.Stop();
-                    _gameFunctions.UseItem(nextTarget.DataId, _combatData.CombatItemUse.ItemId);
+                    unsafe
+                    {
+                        AgentInventoryContext.Instance()->UseItem(_combatData.CombatItemUse.ItemId);
+                    }
+                    _continueAt = DateTime.Now.AddSeconds(2);
                 }
                 else
                     _delegate.Update(nextTarget);
@@ -108,6 +117,9 @@ internal sealed class ItemUseModule : ICombatModule
             else if (_condition[ConditionFlag.Casting])
             {
                 // do nothing
+                DateTime alternativeContinueAt = DateTime.Now.AddSeconds(0.5);
+                if (alternativeContinueAt > _continueAt)
+                    _continueAt = alternativeContinueAt;
             }
             else
             {
@@ -131,6 +143,9 @@ internal sealed class ItemUseModule : ICombatModule
             BattleChara* battleChara = (BattleChara*)gameObject.Address;
             if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.Incapacitated)
                 return (battleChara->Flags2 & 128u) != 0;
+
+            if (_combatData.CombatItemUse.Condition == ECombatItemUseCondition.HealthPercent)
+                return (100f * battleChara->Health / battleChara->MaxHealth) < _combatData.CombatItemUse.Value;
         }
 
         return false;