FAForever Forums
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Login

    How to Dynamically Modify Threat Levels in Unit Blueprints Based on Unit Stats

    Scheduled Pinned Locked Moved I need help
    6 Posts 5 Posters 204 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R Offline
      Raysor
      last edited by

      Hi everyone,

      I’m working on creating a mod for FAF (Forged Alliance Forever) that dynamically modifies the Threat Levels of all units during runtime, without manually editing .bp files. The goal is to implement a system that calculates new Threat Levels based on the unit's stats (like DPS, range, and HP) and applies these changes automatically.

      This idea stems from my desire to make my games with the M28AI mod more interesting and balanced. I love the M28AI, but I’ve noticed that units with very low Threat Levels tend to be too passive, while units with overly high Threat Levels can be excessively aggressive. By dynamically recalculating Threat Levels to better represent the capabilities of each unit, I believe this will not only improve how M28AI plays but also enhance the performance of other AI mods or systems that rely on Threat Levels for decision-making.

      The specific section I want to adjust in the .bp files looks like this:

      Defense = {
          AirThreatLevel = 0,
          ArmorType = 'Normal',
          EconomyThreatLevel = 0,
          Health = 13000,
          MaxHealth = 13000,
          RegenRate = 0,
          SubThreatLevel = 0,
          SurfaceThreatLevel = 50,
      },
      

      What I Want to Achieve:

      • Dynamically calculate Threat Levels using relevant unit stats:
        • Combat units: Use stats like DPS, range, and HP to compute values for AirThreatLevel, SurfaceThreatLevel, and SubThreatLevel.
        • Economic units: Use mass and energy production to calculate EconomyThreatLevel.
      • Apply these calculations at runtime without manually editing .bp files, ensuring compatibility with all units (including those added by other mods).
      • Ensure compatibility with AI mods like M28AI and potentially improve how AI systems interact with units based on their adjusted Threat Levels.

      My Current Approach:

      I believe this can be achieved by overriding the UnitBlueprint function in Lua, which processes unit blueprints during game loading. The idea would be to intercept each blueprint, extract the relevant stats, calculate new Threat Levels, and update the blueprint accordingly.

      Here’s a rough outline of how I imagine the logic:

      local OldUnitBlueprint = UnitBlueprint
      
      function UnitBlueprint(bp)
          if bp.Defense then
              -- Example calculation for combat Threat Levels
              local dps = 0
              local range = 0
              local hp = bp.Defense.MaxHealth or 0
      
              if bp.Weapon then
                  for _, weapon in ipairs(bp.Weapon) do
                      dps = dps + (weapon.Damage or 0) * (weapon.RateOfFire or 1)
                      range = math.max(range, weapon.MaxRadius or 0)
                  end
              end
      
              -- Calculate new Threat Levels dynamically
              if dps > 0 and range > 0 then
                  bp.Defense.SurfaceThreatLevel = (dps * range) / 1000 + (hp / 1000)
              end
      
              -- Example calculation for economic Threat Levels
              if bp.Economy then
                  local massProd = bp.Economy.ProductionPerSecondMass or 0
                  local energyProd = bp.Economy.ProductionPerSecondEnergy or 0
                  bp.Defense.EconomyThreatLevel = (massProd * 10) + (energyProd / 10)
              end
          end
      
          -- Call the original function to ensure other mods and game features work
          OldUnitBlueprint(bp)
      end
      

      Questions:

      • Is overriding UnitBlueprint the best way to dynamically adjust Threat Levels based on unit stats?
      • For extracting stats like DPS and range from weapons, is there a better approach than iterating over bp.Weapon?
      • How can I ensure compatibility with other mods and make sure my mod loads after them?
      • Are there any potential performance concerns with dynamically calculating Threat Levels for all units during loading?
      • Has anyone implemented a similar system, and are there best practices or caveats I should keep in mind?

      Why This Matters:

      My main objective is to improve how AI mods like M28AI handle units, but I suspect this would also apply to other AI mods or systems I haven’t yet considered. By dynamically calculating Threat Levels based on unit stats, I hope to make the AI’s decision-making more logical and engaging, resulting in more interesting games.

      I’d love to hear any advice, suggestions, or experiences you might have. Thank you in advance for your help!

      1 Reply Last reply Reply Quote 1
      • maudlin27M Offline
        maudlin27
        last edited by

        While I'm not sure on the answer to your question, I'd note that if you do find a solution it won't impact M28AI (or M27AI) as they use custom threat assessments, so the threat values in the blueprint have no impact on them.
        Blueprint threat values are relevant to AIs that use the built in "IMAP" threat system - at a high level, this divides the map into squares, and calculates the threat of units in that square with a few different threat types. The threat then decays gradually over time when the units leave that square.

        M27AI and M28AI developer; Devlogs and more general AI development guide:
        https://forum.faforever.com/topic/2373/ai-development-guide-and-m27ai-v71-devlog
        https://forum.faforever.com/topic/5331/m28ai-devlog-v150

        1 Reply Last reply Reply Quote 3
        • S Offline
          Sprouto
          last edited by

          The LOUD project has extensive work on threat values - and as you have already determined, modification of the blueprint values, at runtime, is the most accessible method of doing this. Your intent is aimed in the right direction - without meaningful, and accurate, threat values, no AI can make informed decisions based off of the data - and this is a long standing problem going back to the release of the game. No direction was provided, so many unit authors just dropped in values that made sense to them, and were not related to any particular capability of the units.

          Since you have no surefire method of controlling the load order of mods, your blueprint changes are at the mercy of any other unit mods that may alter the values. As Maudlin identified, he sidestepped this issue by performing calculations similar to what you are proposing, but doing so on the fly, during the game. This gets around any question of the values in use, but it may have performance concerns - doing it during loading has no impact on the performance of the game itself.

          DPS calculations are going to be an issue, as unit authors are not exactly consistent in how they arrive at the kind of damage output their units will put out. There are MANY combinations and control values that can impact the actual DPS calculation - it goes far beyond the 'RateOfFire' blueprint value, which many consider to be the 'be all and end all' of DPS calculations. It is not - and anyone who has done sufficient weapon 'rigging' can tell you the many pitfalls, in the blueprint values, that can lead to an erroneous DPS value.

          One issue that is not addressable is the impact of unit enhancements on DPS - as the blueprint threat values, once set, are static for the duration.

          1 Reply Last reply Reply Quote 1
          • N Offline
            Nomander
            last edited by

            For FAF the file blueprints-ai.lua already calculates threat levels from unit stats, you'd want to overwrite the function SetThreatValuesOfUnit in there to properly replace the threat level calculation. This also means you don't have to worry about mod load order since that threat calculation is done in PostModBlueprints.

            There are MANY combinations and control values that can impact the actual DPS calculation - it goes far beyond the 'RateOfFire' blueprint value, which many consider to be the 'be all and end all' of DPS calculations. It is not - and anyone who has done sufficient weapon 'rigging' can tell you the many pitfalls, in the blueprint values, that can lead to an erroneous DPS value.

            @Sprouto There's a rather comprehensive DPS calculation in FAF's unitviewdetail.lua, I think it's only missing fire rate when it is limited by energy requirements or animation speed, and if I remember correctly some rounding for some stat should be floored instead, but it's still quite complete. I should really put that calculation in a library.

            1 Reply Last reply Reply Quote 1
            • S Offline
              Sprouto
              last edited by

              There are a lot of other factors that can contribute to the 'threat' of a unit, beyond DPS, namely range, mobility & protection (HP) - all have a part to play in how 'threatening' a unit can be - and a discussion of those is likely beyond the scope of the question here. I'm not familiar with the contents of the FAF threat calculation, in as much as dovetailing threat to DPS was a big step forward when we introduced it in LOUD back in the day, so I was pleased to see that idea taken to heart some years later in FAF. It was abundantly clear, especially for AI (and the long standing issues with Sorian AI's in particular) that threat assessment, and understanding how it works internally, has a lot of follow-on impact on how any AI 'reads' a situation, and the map. It impacts almost every aspect of activity, pathfinding for example, and building position and selection, to name just two.

              1 Reply Last reply Reply Quote 1
              • R Offline
                relentless
                last edited by relentless

                The blueprints-ai.lua file that Nomander referenced is what you want to look at.

                Your obviously motivated to do something positive here. I don't believe we can dynamically adjust threat during the game as the blueprints are read once on startup sort of thing. BUT, I think the development team would be more than happy to see someone put time into improving the existing threat calculations that we are creating. The current calculations are based on a formula that Balthazar did however long ago and some adjustments since then and while it is ALOT better than what we had originally there is room for improvement.

                You'll eventually hit limitations since threat also depends on situational factors (a sniper bot in dangerous unless an enemy Obsidian tank is sitting next to it sort of thing). So why not rather than making a mod look at improving what we are doing now? We're happy to collaborate and provide feedback on the impact it makes on AI games.

                1 Reply Last reply Reply Quote 1
                • First post
                  Last post