Idea: Procedurally-Generated Armor (A Time-Saving Level-Balance Feature for Devs and Modders Alike?)

Discussion in 'Gear and Items' started by Shadow Wolf TJC, Mar 7, 2016.

?

Should randomly-generated armor be added?

  1. Yes

    100.0%
  2. No

    0 vote(s)
    0.0%
  3. Don't care

    0 vote(s)
    0.0%
  1. Shadow Wolf TJC

    Shadow Wolf TJC Spaceman Spiff

    With the way that weapons, shields, monsters, and npcs are generated and modified according to their level (which may be pre-set, or determined by the danger level of the planet that they're found in), why don't armor pieces benefit from this? Even if the devs decide against allowing the game to spawn randomly-generated pieces of armor as rewards in chests, monster drops, etc., they ought to admit that trying to rebalance numerous variables in each tier of armor, and to copy-paste those new values across the various racial armor sets, is kind of tedious.

    The following is an example of some code that could be added into levelingmultipliers.functions:
    Code:
      // Applies a StatBaseMultiplier to armor health
      "armorLevelHealthMultiplier" : [ "linear", "clamp",
        [0,   0],
        [1,   1],
        [2,   2],
        [3,   3],
        [4,   4],
        [5,   5],
        [6,   6],
        [7,   7],
        [8,   8],
        [9,   9],
        [10,   10]
      ],
    
      // Applies a StatBaseMultiplier to armor energy
      "armorLevelEnergyMultiplier" : [ "linear", "clamp",
        [0,   0],
        [1,   1],
        [2,   2],
        [3,   3],
        [4,   4],
        [5,   5],
        [6,   6],
        [7,   7],
        [8,   8],
        [9,   9],
        [10,   10]
      ],
    
      // this name is slightly ridiculous, but it results in a StatValueModifier
      // on a stat which is then used as a multiplier, thus "multiplier modifier"
      "armorLevelPowerMultiplierModifier" : [ "linear", "clamp",
        [0, 0.5],
        [1, 1.0],
        [2, 1.5],
        [3, 2.0],
        [4, 2.5],
        [5, 3.0],
        [6, 3.5],
        [7, 4.0],
        [8, 4.5],
        [9, 5.0],
        [10,5.5]
      ],
    
      // Modifies base armor protection based on item level
      // This is a little weird, but it's tough to effectively scale protection when 100
      // is 100% damage reduction
      "armorLevelProtectionMultiplier" : [ "linear", "clamp",
        [0,   0],
        [1,   9],
        [2,  24],
        [3,  43],
        [4,  59],
        [5,  69],
        [6,  76],
        [7,  80],
        [8,  84],
        [9,  86],
        [10, 88]
      ],
    
    However, it seems as if some of your recent coding and/or scripting decisions have made it difficult to reliably implement a system like this, such as tying armor protection directly to damage reduction percentage, and the weird way that the game uses "powerModifier" to calculate how big of a bonus the player's weapons receive towards their damage. Might I suggest a few code tweaks?

    1st, perhaps we should replace "powerModifier" with something less wonky, like, say, a "powerBonus" variable, which is added to the player's base attack stat directly. Instead of this:

    Code:
    damage = weaponDamage(basePower + (chest.powerModifier-1) + (head.powerModifier-1) + (legs.powerModifier-1))
    //Assuming that basePower = 1
    It could be more like this:

    Code:
    damage = weaponDamage(basePower + chest.powerBonus + head.powerBonus + legs.powerBonus)
    As for your current protection system, I see why you guys might've made it that way, not only to make damage reduction clearer to both you and the player, but also to make lower-level healing items more useful at higher levels. Thus, I'd personally leave it alone for now.

    Instead, one option is to implement a series of "levelModifier" stats, that cause individual stats to be treated as various levels higher or lower than what they normally would be.

    With this system, armor pieces, like this apextier1.chest, could be made to look more like this:
    Code:
    {
      "itemName" : "apextier1chest",
      "price" : 125,
      "inventoryIcon" : "icons.png:chest",
      "level" : 1, //A new variable for quickly and automatically adjusting the armor's stats for the proper tier
      "maxStack" : 1,
      "rarity" : "Common",
      "description" : "A cheap military-grade Chestguard which protects the most vital organs.",
      "shortdescription" : "Defector's Chestguard",
      "tooltipKind" : "armor",
    
      "maleFrames" : {
        "body" : "chestm.png",
        "backSleeve" : "bsleeve.png",
        "frontSleeve" : "fsleeve.png"
      },
    
      "femaleFrames" : {
        "body" : "chestf.png",
        "backSleeve" : "bsleeve.png",
        "frontSleeve" : "fsleeve.png"
      },
    
      "statusEffects" : [
        {
          "stat" : "powerBonus", //replaces "powerMultiplier"
          "amount" : 0.5 //50% received from chest armor
        },
    
        {
          "stat" : "protection",
          "amount" : 0.5 //50% received from chest armor
        },
    
        {
          "stat" : "maxEnergy",
          "amount" : 5 //50% received from chest armor
        },
    
        {
          "stat" : "maxHealth",
          "amount" : 5 //50% received from chest armor
        }
      ],
    
      "palette" : "items/active/armor/colors/tier10armor.armorcolors",
    
      "builder" : "/items/buildscripts/buildunrandarmor.lua",
    
      "learnBlueprintsOnPickup" : [
        "apextier2chest"
      ]
    }
    
    Meanwhile, a less standard armor set, like this Impervium-grade apextier6separator.chest, could look more like this:
    Code:
    {
      "itemName" : "apextier6schest",
      "price" : 125, //Price will be adjusted based on the item's level
      "inventoryIcon" : "icons.png:chest",
      "level" : 6, //A new variable for quickly and automatically adjusting the armor's stats for the proper tier
      "maxStack" : 1,
      "rarity" : "Legendary",
      "description" : "The giant pauldrons on this impervium armour show that the wearer means business.",
      "shortdescription" : "Frontliner's Breastplate",
      "tooltipKind" : "armor",
    
      "maleFrames" : {
        "body" : "chestm.png",
        "backSleeve" : "bsleeve.png",
        "frontSleeve" : "fsleeve.png"
      },
    
      "femaleFrames" : {
        "body" : "chestf.png",
        "backSleeve" : "bsleeve.png",
        "frontSleeve" : "fsleeve.png"
      },
    
      "statusEffects" : [
        {
          "stat" : "powerBonus", //replaces "powerMultiplier"
          "levelModifier" : -2, //Treat this as being equivalent of a piece of armor that's 2 tiers below
          "amount" : 0.5 //50% received from chest armor
        },
    
        {
          "stat" : "protection",
          "levelModifier" : 2, //Treat this as being equivalent of a piece of armor that's 2 tiers above
          "amount" : 0.5 //50% received from chest armor
        },
    
        {
          "stat" : "maxEnergy",
          "amount" : 5 //50% received from chest armor
        },
    
        {
          "stat" : "maxHealth",
          "levelModifier" : 2, //Treat this as being equivalent of a piece of armor that's 2 tiers above
          "amount" : 5 //50% received from chest armor
        }
      ],
    
      "palette" : "items/active/armor/colors/tier10armor.armorcolors",
    
      "builder" : "/items/buildscripts/buildunrandarmor.lua"
    }
    
    Finally, if you really do want to add randomly-generated armor, possibly called, say, commonchest.activeitem or commonlegs.activeitem, to go along with this idea, I'd imagine that its code could look like this:
    Code:
    {
      "itemName" : "commonchest", //or "commonlegs" or "commonhead"
      "price" : 125,
      "maxStack" : 1,
      "rarity" : "common",
      "description" : "",
      "shortdescription" : "Common Chest Armor",
      "tooltipKind" : "armor",
      "armorType" : "Chest", //Could be needed in order to tell the builder that this is for generating chestpieces
      "itemTags" : [ //These will be needed for use in quest progression
        [0, ["armor","chest"]],
        [1, ["armor","chest", "ironarmor" ]],
        [2, ["armor","chest", "steelarmor"]],
        [3, ["armor","chest", "titaniumarmor"]],
        [4, ["armor","chest", "durasteelarmor"]],
        [5, ["armor","chest", "tier5armor"]],
        [6, ["armor","chest", "tier6armor"]]
      ],
    
      //"mask" : "mask.png", //Only used for head armor I'm guessing
    
      "levelOffset" : [-0.1, 0.1], //This is how far the item's level may deviate from where it spawned.
      "statLevelVariance" : [-2, 2], //This is how far each of the individual stats below may be varied in terms of level. However, the mean of the stat levels must be within the item's level, so no level 1 items with all level 3 stats for example.
      "statusEffects" : [
        {
          "stat" : "powerBonus",
          "levelModifier" : 0, //Adjust this in order to treat this stat as being equivalent of a higher or lower-tiered item. Applied after "levelOffset" and "statLevelVariance"
          "amount" : [0.4, 0.6] //An alternative way to add stat variance. Probably shouldn't be used alongside the "statLevelVariance" variable
        },
    
        {
          "stat" : "protection",
          "levelModifier" : 0,
          "amount" : [0.4, 0.6]
        },
    
        {
          "stat" : "maxEnergy",
          "levelModifier" : 0,
          "amount" : [4, 6]
        },
    
        {
          "stat" : "maxHealth",
          "levelModifier" : 0,
          "amount" : [4, 6]
        }
      ],
    
      "builder" : "/items/buildscripts/buildarmor.lua",
      "builderConfig" : [{
        "nameGenerator" : "armorchestnames.config:nameGen",
        "animationParts" : {
          //These parts would be defined for chest armor
          "body" : {
            "maleFrames" : {
              "path" : "/items/active/armor/chestm/<variant>.png",
            },
            "femaleFrames" : {
              "path" : "/items/active/armor/chestf/<variant>.png",
            },
            "variants" : 20,
            "paletteSwap" : true
          },
          "sleeves" : {
            "backSleeve" : {
              "path" : "/items/active/armor/bsleeve/<variant>.png",
            },
            "frontSleeve" : {
              "path" : "/items/active/armor/fsleeve/<variant>.png",
            },
            "variants" : 20,
            "paletteSwap" : true
          },
          //This part would be defined for head armor
          "head" : {
            "maleFrames" : {
              "path" : "/items/active/armor/headm/<variant>.png",
            },
            "femaleFrames" : {
              "path" : "/items/active/armor/headf/<variant>.png",
            },
            "variants" : 20,
            "paletteSwap" : true
          },
          //This part would be defined for leg armor
          "pants" : {
            "maleFrames" : {
              "path" : "/items/active/armor/pantsm/<variant>.png",
            },
            "femaleFrames" : {
              "path" : "/items/active/armor/pantsf/<variant>.png",
            },
            "variants" : 20,
            "paletteSwap" : true
          },
        "palette" : "/items/active/armor/colors/armor.armorcolors",
        "iconDrawables" : ["chest", "sleeves"] //This would just be "head" for head armor, and "pants" for leg armor
      }]
    }
    
    While I personally know very little about how the .lua scripting works, I believe that each of the individual stats that would be calculated upon the armor's generation would have a similar structure to the following calculations:
    Code:
    while (levelVariance =! 0)
    {
      armorPowerLevelVariance = random(statLevelVariance[0], statLevelVariance[1])
      armorProtectionLevelVariance = random(statLevelVariance[0], statLevelVariance[1])
      armorEnergyLevelVariance = random(statLevelVariance[0], statLevelVariance[1])
      armorHealthLevelVariance = random(statLevelVariance[0], statLevelVariance[1])
      levelVariance = (armorPowerLevelVariance + armorProtectionLevelVariance + armorEnergyLevelVariance + armorHealthLevelVariance) / 4 
    }
    
    newArmorPowerBonus = random(armor.powerBonus.amount[0], armor.powerBonus.amount[1]) * (armorLevelPowerBonusMultiplier(armor.level + random(armor.levelOffset[0], armor.levelOffset[1]) + armorPowerLevelVariance + armor.powerBonus.levelModifier))
    newArmorProtection = random(armor.protection.amount[0], armor.protection.amount[1]) * (armorLevelProtectionMultiplier(armor.level + random(armor.levelOffset[0], armor.levelOffset[1]) + armorProtectionLevelVariance + armor.protection.levelModifier))
    newArmorEnergy = random(armor.energy.amount[0], armor.energy.amount[1]) * (armorLevelEnergyMultiplier(armor.level + random(armor.levelOffset[0], armor.levelOffset[1]) + armorEnergyLevelVariance + armor.energy.levelModifier))
    newArmorHealth = random(armor.health.amount[0], armor.health.amount[1]) * (armorLevelHealthMultiplier(armor.level + random(armor.levelOffset[0], armor.levelOffset[1]) + armorHealthLevelVariance + armor.health.levelModifier))
     
    Celesmeh and jakecool19 like this.

Share This Page