Def-ItemStringParser icon

ItemStringParser

A library for parsing Item Strings. Does nothing on its own.

Last updated an hour ago
Total downloads 1
Total rating 0 
Categories Libraries
Dependency string Def-ItemStringParser-1.0.0
Dependants 0 other packages depend on this package

README

ItemStringParser

This mod is a library for parsing ItemStrings. See bottom on the developer manual.

User Manual

ItemStrings are a way to describe a droptable using plain text. They let you describe what items should appear and how many in a simple, readable line. ItemStrings can include instructions for repeating items, choosing items randomly, or excluding certain items.

ItemString Operators

ItemString operators are symbols that help you decide which items to give, repeat, or exclude in a list. They make it easy to write rules like "give this item", "skip that one", or "choose one randomly" using short codes. Each entry in the ItemString roughly follows the format: <repeat>x<itemkey>!<itemname>*<multiplier>: <weight>. Entries can be separated by & or |. Entries can be grouped with { and }.

! (Not-Operator)

  • Purpose: Blacklist items from tiers or droptables.
  • Placement: Directly after the name of the droptable or tier.
  • Example:
    • Tier1!Hoof - White item but not a Hoof
    • dtChest1!Bear!Crowbar - Content of a Small Chest but neither Tougher Times nor Crowbar.

& (And-Operator)

  • Purpose: Every item separated by & will be selected.
  • Example:
    • Hoof & Boss - The player receives both a Hoof and a random Boss item.

| (Or-Operator)

  • Purpose: Only one of the items separated by | will be chosen at random.
  • Weights: You can specify selection weights using a colon : after the item (e.g., Tier1: 0.5 | Tier2: 0.5).
  • Example:
    • Tier1 | Tier2 - The player gets either a Tier1 or a Tier2 item (equal chance unless weighted).

: (Weight Separator)

  • Purpose: Assigns probability weights to options with the Or-Operator (|).
  • Default: If omitted, the default weight 1 is used.
  • Example:
    • Tier1: 0.6 | Tier2: 0.4 - Tier1 has a 60% chance, Tier2 a 40% chance.
    • Tier1: 3.0 | Tier2 - Tier1 has a 75% chance, Tier2 a 25% chance.

x (Repeat-Operator)

  • Purpose: Repeats the immediately following item or group a fixed number of times.
  • Placement: Directly before a group or item.
  • Example:
    • 5xHoof - The player gets 5 Hoof items.
    • 3x{ Tier1 | Tier2 } - The player gets 3 times a randomly selected item from Tier1 or Tier2.

* (Multiplier-Operator)

  • Purpose: Multiplies the amount of items of a group.
  • Placement: Directly after a group or item.
  • Example:
    • Hoof*5 - The player gets 5 Hoof items.
    • { Tier1 | Tier2 }*3 - The player gets 3 copies of a single type of item from either Tier1 or Tier2.

{ and } (Grouping Symbols)

  • Purpose: Group items and operators together. Can use & and | within a group, but they cannot be mixed.
  • Operator precedence: Use { } to explicitly control grouping and order of operations, especially when combining repeat, and, or multiply.
  • Nested groups: You can nest { } for more complex item generation logic.
  • Example:
    • { 2xdtChest1 | dtChest2 } - Represents a choice between "2x small chest" and "1 large chest" as a single entity; useful with other operators.

Summary Table

Operator Symbol Description Example
Not ! Blacklists the item from the group A!B
And & All items, together A & B
Or | Only one item, random (optional weight via :) A | B:0.7 | C:0.3
Weight : Specifies probability weight for options when using | A: 0.6 | B: 0.4
Repeat x Repeats the following item/group N times 5xA or 3x{A | B}
Multiply * Multiplies the amount of items in the group by N {A & B}*4
Grouping {} Groups items/expressions {A & 2xB}

Examples

A random lunar item, except for Light Flux Pauldron and Stone Flux Pauldron:

ItemList = Lunar!HalfSpeedDoubleHealth!HalfAttackSpeedHalfCooldowns

5 Hooves:

ItemList = 5xHoof

Also 5 Hooves:

ItemList = Hoof*5

5 random whites:

ItemList = 5xTier1

5 copies of the same white:

ItemList = Tier1*5

5 Hooves and 2 Armor Plates:

ItemList = 5xHoof & 2xArmorPlate

Either 5 Hooves or 2 Armor Plates:

ItemList = 5xHoof | 2xArmorPlate

Either 5 Hooves with 30% chance or 2 Armor Plates with 70% chance:

ItemList = 5xHoof: 0.3 | 2xArmorPlate: 0.7

Infusion and either 5 Hooves with 30% chance or 2 Armor Plates with 70% chance:

ItemList = Infusion & { 5xHoof: 0.3 | 2xArmorPlate: 0.7 }

Either Infusion or Feather and either 5 Hooves with 30% chance or 2 Armor Plates with 70% chance:

ItemList = { Infusion | Feather } & { 5xHoof: 0.3 | 2xArmorPlate: 0.7 }

75% chance: Infusion and feather, 25% chance: 5 hoves and 5 Armor Plates

ItemList = { Infusion & Feather }: 0.75 | { Hoof & ArmorPlate }*5: 0.25

Either 5 whites or 3 greens or 1 red:

ItemList = 5xTier1 | 3xTier2 | Tier3

Between 1 and 5 whites.

ItemList = 1xTier1 | 2xTier1 | 3xTier1 | 4xTier1 | 5xTier1

10 random items which consist of around 50% whites, around 35% greens and around 15% red:

ItemList = 10x{ Tier1: 0.5 | Tier2: 0.35 | Tier3: 0.15 }

5 times one of the following: Either the contents of 2 small chests (except for Tougher Times) or the content of 1 large chest

ItemList = 5x{ 2xdtChest1!Bear | dtChest2 }

Preon Accumulator and 10 Gesture of the Drowned or Ifrit's Distinction and 1 Ignition Tank

{ BFG & 10xAutoCastEquipment } | { EliteFireEquipment & StrengthenBurn }

Item Keywords

You can use:

  • Internal item names (see R2Wiki - Items-and-Equipments-Data).
  • Item Tier names: Tier1, Tier2, Tier3, Lunar, Boss, VoidTier1, VoidTier2, VoidTier3, VoidBoss, FoodTier
  • Droptable names: e.g. dtChest1, dtLunarChest, dtVoidChest. See below.

Droptable Names

Here is a list of supported droptables:

Drop Table Name tier1 tier2 tier3 boss lunarEquipment lunarItem lunarCombined equipment voidTier1 voidTier2 voidTier3 voidBoss foodTier powerShapes canDropBeReplaced requiredItemTags bannedItemTags
dtCasinoChest 0.7 0.3 0.01 0 0 0 0 0.1 0 0 0 0 0 0 True
dtSmallChestDamage 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True Damage
dtSmallChestHealing 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True Healing
dtSmallChestUtility 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True Utility
dtChest1 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True
dtChest2 0 0.8 0.2 0 0 0 0 0 0 0 0 0 0 0 True
dtAISafeTier1Item 1 0 0 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, SprintRelated
dtAISafeTier2Item 0 1 0 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, SprintRelated
dtAISafeTier3Item 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, SprintRelated
dtEquipment 0 0 0 0 0 0 0 1 0 0 0 0 0 0 True
dtTier1Item 1 0 0 0 0 0 0 0 0 0 0 0 0 0 True
dtTier2Item 0 1 0 0 0 0 0 0 0 0 0 0 0 0 True
dtTier3Item 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True
dtVoidChest 0 0 0 0 0 0 0 0 6 3 1 0 0 0 True
dtDuplicatorTier1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 True CannotDuplicate
dtDuplicatorTier2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 True CannotDuplicate
dtDuplicatorTier3 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True CannotDuplicate
dtDuplicatorWild 0 0 0 1 0 0 0 0 0 0 0 0 0 0 True WorldUnique
dtGoldChest 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True
dtLunarChest 0 0 0 0 0 0 1 0 0 0 0 0 0 0 True
dtMonsterTeamTier1Item 1 0 0 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, OnKillEffect, EquipmentRelated, SprintRelated
dtMonsterTeamTier2Item 0 1 0 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, OnKillEffect, EquipmentRelated, SprintRelated
dtMonsterTeamTier3Item 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True AIBlacklist, OnKillEffect, EquipmentRelated, SprintRelated
dtSacrificeArtifact 0.7 0.3 0.01 0 0 0 0 0.1 0 0 0 0 0 0 True SacrificeBlacklist
dtShrineChance 8 2 0.2 0 0 0 0 2 0 0 0 0 0 0 True
dtLockbox 0 4 1 0 0 0 0 0 0 0 0 0 0 0 True
dtCommandChest 0.2 0.2 0.05 0.05 0 0 0 0.2 0.1 0.1 0.05 0.05 0 0 True Any, Any, Any, Any, Any
dtCategoryChest2Damage 0 0.8 0.2 0 0 0 0 0 0 0 0 0 0 0 True Damage
dtCategoryChest2Healing 0 0.8 0.2 0 0 0 0 0 0 0 0 0 0 0 True Healing
dtCategoryChest2Utility 0 0.8 0.2 0 0 0 0 0 0 0 0 0 0 0 True Utility
dtITBossWave 0 80 7.5 7.5 0 0 0 0 0 0 0 0 0 0 True
dtITDefaultWave 80 10 0.25 0.25 0 0 0 0 0 0 0 0 0 0 True
dtITLunar 0 0 0 0 0 0 100 0 0 0 0 0 0 0 True
dtITSpecialBossWave 0 0 80 20 0 0 0 0 0 0 0 0 0 0 True
dtITVoid 0 0 0 0 0 0 0 0 80 20 1 0 0 0 True
dtVoidLockbox 0 0 0 0 0 0 0 0 5 5 2 0 0 0 True
dtVoidCamp 40 40 10 3 0 0 0 0 5.714286 5.714286 1.25 0 0 0 True
dtVoidTriple 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True
AurelioniteHeartPickupDropTable 0 0 0.4 0.6 0 0 0 0 0 0 0 0 0 0 True
dtShrineHalcyoniteTier1 0.65 0.3 0.05 0 0 0 0 0 0 0 0 0 0 0 True
dtShrineHalcyoniteTier2 0.65 0.3 0.05 0 0 0 0 0 0 0 0 0 0 0 True HalcyoniteShrine
dtShrineHalcyoniteTier3 0.65 0.3 0.05 0 0 0 0 0 0 0 0 0 0 0 True
GeodeRewardDropTable 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True
dtChanceDoll 0 0.79 0.2 0.01 0 0 0 0 0 0 0 0 0 0 True
dtSonorousEcho 0.9 0.1 0.001 0 0 0 0 0 0 0 0 0 0 0 True
dtSalvage 0.75 0.25 0.05 0 0 0 0 0 0 0 0 0 0 0 False CanBeTemporary
dtDrifterBagChest 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 True
dtJunkDrone 0.7 0.25 0.05 0 0 0 0 0 0 0 0 0 0 0 False CanBeTemporary
dtSolusHeart 0 0 1 0 0 0 0 0 0 0 0 0 0 0 True Technology WorldUnique, CannotCopy, FoodRelated, ObjectiveRelated
dtTemporaryItemsDistributor 0.8 0.2 0.01 0 0 0 0 0 0 0 0 0 0 0 False CanBeTemporary

EBNF

You can use this EBNF to validate your item string for example at PaulKlineLabs' BNF Playground.

<ItemList>       ::= <AND_LIST> | <OR_LIST>
<AND_LIST>       ::= <ENTRY> (" & " <ENTRY>)*
<OR_LIST>        ::= <WEIGHTED_ENTRY> (" | " <WEIGHTED_ENTRY>)*
<ENTRY>          ::= (<rep> "x")? <ITEM_KEY> ("*" <mult>)?
<WEIGHTED_ENTRY> ::= <ENTRY> (": " <weight>)?
<ITEM_KEY>       ::= <itemname> | <tier> ("!" <itemname>)* | <droptable> ("!" <itemname>)* | "{ " <AND_LIST> " }" | "{ " <OR_LIST> " }"

<itemname>  ::= "AACannon" | "AdaptiveArmor" | "AlienHead" | "ArmorPlate" | "ArmorReductionOnHit" | "AttackSpeedAndMoveSpeed" | "AttackSpeedOnCrit" | "AttackSpeedPerNearbyAllyOrEnemy" | "AutoCastEquipment" | "Bandolier" | "BarrageOnBoss" | "BarrierOnCooldown" | "BarrierOnKill" | "BarrierOnOverHeal" | "Bear" | "BearVoid" | "BeetleGland" | "Behemoth" | "BleedOnHit" | "BleedOnHitAndExplode" | "BleedOnHitVoid" | "BonusGoldPackOnKill" | "BonusHealthBoost" | "BoostAllStats" | "BoostAttackSpeed" | "BoostDamage" | "BoostEquipmentRecharge" | "BoostHp" | "BossDamageBonus" | "BounceNearby" | "BurnNearby" | "ChainLightning" | "ChainLightningVoid" | "Clover" | "CloverVoid" | "ConvertCritChanceToCritDamage" | "CooldownOnCrit" | "CrippleWardOnLevel" | "CritAtLowerElevation" | "CritDamage" | "CritGlasses" | "CritGlassesVoid" | "CritHeal" | "Crowbar" | "CutHp" | "Dagger" | "DeathMark" | "DelayedDamage" | "DestructibleSpawner" | "DrizzlePlayerHelper" | "DroneDynamiteDisplay" | "DroneUpgradeHidden" | "DroneWeapons" | "DroneWeaponsBoost" | "DroneWeaponsDisplay1" | "DroneWeaponsDisplay2" | "DronesDropDynamite" | "Duplicator" | "ElementalRingVoid" | "EmpowerAlways" | "EnergizedOnEquipmentUse" | "EquipmentMagazine" | "EquipmentMagazineVoid" | "ExecuteLowHealthElite" | "ExplodeOnDeath" | "ExplodeOnDeathVoid" | "ExtraEquipment" | "ExtraLife" | "ExtraLifeConsumed" | "ExtraLifeVoid" | "ExtraLifeVoidConsumed" | "ExtraShrineItem" | "ExtraStatsOnLevelUp" | "FallBoots" | "Feather" | "FireRing" | "FireballsOnHit" | "Firework" | "FlatHealth" | "FocusConvergence" | "FragileDamageBonus" | "FragileDamageBonusConsumed" | "FreeChest" | "Ghost" | "GhostOnKill" | "GoldOnHit" | "GoldOnHurt" | "GummyCloneIdentifier" | "HalfAttackSpeedHalfCooldowns" | "HalfSpeedDoubleHealth" | "HeadHunter" | "HealOnCrit" | "HealWhileSafe" | "HealingPotion" | "HealingPotionConsumed" | "HealthDecay" | "Hoof" | "IceRing" | "Icicle" | "IgniteOnKill" | "ImmuneToDebuff" | "IncreaseDamageOnMultiKill" | "IncreaseHealing" | "IncreasePrimaryDamage" | "Incubator" | "Infusion" | "InvadingDoppelganger" | "ItemDropChanceOnKill" | "JumpBoost" | "JumpDamageStrike" | "Junk" | "KillEliteFrenzy" | "KnockBackHitEnemies" | "Knurl" | "LaserTurbine" | "LemurianHarness" | "LevelBonus" | "LightningStrikeOnHit" | "LowerPricedChests" | "LowerPricedChestsConsumed" | "LunarBadLuck" | "LunarDagger" | "LunarPrimaryReplacement" | "LunarSecondaryReplacement" | "LunarSpecialReplacement" | "LunarSun" | "LunarTrinket" | "LunarUtilityReplacement" | "LunarWings" | "MageAttunement" | "Medkit" | "MeteorAttackOnHighDamage" | "MinHealthPercentage" | "MinionLeash" | "MinorConstructOnKill" | "Missile" | "MissileVoid" | "MoneyLoan" | "MonsoonPlayerHelper" | "MonstersOnShrineUse" | "MoreMissile" | "MoveSpeedOnKill" | "Mushroom" | "MushroomVoid" | "NearbyDamageBonus" | "NovaOnHeal" | "NovaOnLowHealth" | "OnLevelUpFreeUnlock" | "OutOfCombatArmor" | "ParentEgg" | "PermanentDebuffOnHit" | "PersonalShield" | "Phasing" | "PhysicsProjectile" | "Plant" | "PlantOnHit" | "PlasmaCore" | "PrimarySkillShuriken" | "RandomDamageZone" | "RandomEquipmentTrigger" | "RandomlyLunar" | "RegeneratingScrap" | "RegeneratingScrapConsumed" | "RepeatHeal" | "RoboBallBuddy" | "SecondarySkillMagazine" | "Seed" | "SharedSuffering" | "ShieldBooster" | "ShieldOnly" | "ShockDamageAura" | "ShockNearby" | "SiphonOnLowHealth" | "SkullCounter" | "SlowOnHit" | "SlowOnHitVoid" | "SpeedBoostPickup" | "SpeedOnPickup" | "SprintArmor" | "SprintBonus" | "SprintOutOfCombat" | "SprintWisp" | "Squid" | "StatsFromScrap" | "StickyBomb" | "StrengthenBurn" | "StunAndPierce" | "StunChanceOnHit" | "Syringe" | "TPHealingNova" | "Talisman" | "TeamSizeDamageBonus" | "TeleportOnLowHealth" | "TeleportOnLowHealthConsumed" | "TeleportWhenOob" | "TempestOnKill" | "Thorns" | "TonicAffliction" | "Tooth" | "TransferDebuffOnHit" | "TreasureCache" | "TreasureCacheVoid" | "TriggerEnemyDebuffs" | "UseAmbientLevel" | "UtilitySkillMagazine" | "VoidMegaCrabItem" | "VoidmanPassiveItem" | "WarCryOnCombat" | "WarCryOnMultiKill" | "WardOnLevel" | "BFG" | "Blackhole" | "BossHunter" | "BurnNearby" | "Cleanse" | "CommandMissile" | "CrippleWard" | "CritOnUse" | "DeathProjectile" | "DroneBackup" | "FireBallDash" | "Fruit" | "GainArmor" | "Gateway" | "GoldGat" | "GummyClone" | "HealAndRevive" | "Jetpack" | "LifestealOnHit" | "Lightning" | "Meteor" | "Molotov" | "MultiShopCard" | "Parry" | "PassiveHealing" | "Recycle" | "Saw" | "Scanner" | "TeamWarCry" | "Tonic" | "VendingMachine"
<droptable> ::= "dtCasinoChest" | "dtSmallChestDamage" | "dtSmallChestHealing" | "dtSmallChestUtility" | "dtChest1" | "dtChest2" | "dtAISafeTier1Item" | "dtAISafeTier2Item" | "dtAISafeTier3Item" | "dtEquipment" | "dtTier1Item" | "dtTier2Item" | "dtTier3Item" | "dtVoidChest" | "dtDuplicatorTier1" | "dtDuplicatorTier2" | "dtDuplicatorTier3" | "dtDuplicatorWild" | "dtGoldChest" | "dtLunarChest" | "dtMonsterTeamTier1Item" | "dtMonsterTeamTier2Item" | "dtMonsterTeamTier3Item" | "dtSacrificeArtifact" | "dtShrineChance" | "dtLockbox" | "dtCommandChest" | "dtCategoryChest2Damage" | "dtCategoryChest2Healing" | "dtCategoryChest2Utility" | "dtITBossWave" | "dtITDefaultWave" | "dtITLunar" | "dtITSpecialBossWave" | "dtITVoid" | "dtVoidLockbox" | "dtVoidCamp" | "dtVoidTriple" | "AurelioniteHeartPickupDropTable" | "dtShrineHalcyoniteTier1" | "dtShrineHalcyoniteTier2" | "dtShrineHalcyoniteTier3" | "GeodeRewardDropTable" | "dtChanceDoll" | "dtSonorousEcho" | "dtSalvage" | "dtDrifterBagChest" | "dtJunkDrone" | "dtSolusHeart" | "dtTemporaryItemsDistributor"
<tier>      ::= "Tier1" | "Tier2" | "Tier3" | "Lunar" | "Boss" | "VoidTier1" | "VoidTier2" | "VoidTier3" | "VoidBoss"
<rep>       ::= <int>
<mult>      ::= <int>
<weight>    ::= <float>

<int>   ::= [1-9] [0-9]*
<float> ::= ("0" | <int>) ("." [0-9]+ )?

Or use this one if you have modded items:

<ItemList>       ::= <AND_LIST> | <OR_LIST>
<AND_LIST>       ::= <ENTRY> (" & " <ENTRY>)*
<OR_LIST>        ::= <WEIGHTED_ENTRY> (" | " <WEIGHTED_ENTRY>)*
<ENTRY>          ::= (<rep> "x")? <ITEM_KEY> ("*" <mult>)?
<WEIGHTED_ENTRY> ::= <ENTRY> (": " <weight>)?
<ITEM_KEY>       ::= <itemname> | <tier> ("!" <itemname>)* | <droptable> ("!" <itemname>)* | "{ " <AND_LIST> " }" | "{ " <OR_LIST> " }"

<itemname>  ::= [a-z]+
<droptable> ::= "dtCasinoChest" | "dtSmallChestDamage" | "dtSmallChestHealing" | "dtSmallChestUtility" | "dtChest1" | "dtChest2" | "dtAISafeTier1Item" | "dtAISafeTier2Item" | "dtAISafeTier3Item" | "dtEquipment" | "dtTier1Item" | "dtTier2Item" | "dtTier3Item" | "dtVoidChest" | "dtDuplicatorTier1" | "dtDuplicatorTier2" | "dtDuplicatorTier3" | "dtDuplicatorWild" | "dtGoldChest" | "dtLunarChest" | "dtMonsterTeamTier1Item" | "dtMonsterTeamTier2Item" | "dtMonsterTeamTier3Item" | "dtSacrificeArtifact" | "dtShrineChance" | "dtLockbox" | "dtCommandChest" | "dtCategoryChest2Damage" | "dtCategoryChest2Healing" | "dtCategoryChest2Utility" | "dtITBossWave" | "dtITDefaultWave" | "dtITLunar" | "dtITSpecialBossWave" | "dtITVoid" | "dtVoidLockbox" | "dtVoidCamp" | "dtVoidTriple" | "AurelioniteHeartPickupDropTable" | "dtShrineHalcyoniteTier1" | "dtShrineHalcyoniteTier2" | "dtShrineHalcyoniteTier3" | "GeodeRewardDropTable" | "dtChanceDoll" | "dtSonorousEcho" | "dtSalvage" | "dtDrifterBagChest" | "dtJunkDrone" | "dtSolusHeart" | "dtTemporaryItemsDistributor"
<tier>      ::= "Tier1" | "Tier2" | "Tier3" | "Lunar" | "Boss" | "VoidTier1" | "VoidTier2" | "VoidTier3" | "VoidBoss"
<rep>       ::= <int>
<mult>      ::= <int>
<weight>    ::= <float>

<int>   ::= [1-9] [0-9]*
<float> ::= ("0" | <int>) ("." [0-9]+ )?

Developer Manual

As a developer if you want to use the ItemStringParser in your mod, here is what you need to do.

  1. Add the ItemStringParser.dll as dependency to your Visual Studio project. Set Copy Local to No so that the dll does not get copied to your build output. Example:
<Reference Include="ItemStringParser">
  <HintPath>libs\ItemStringParser.dll</HintPath>
  <Private>false</Private>
</Reference>
  1. Add [BepInDependency(ItemStringParser.ItemStringParser.PluginGUID)] to your UnityBasePlugin class
  2. Add dependency string Def-ItemStringParser-1.0.0 to the dependencies list in your manifest.json

It provides two public methods: (1) ParseItemString and (2) ResolveItemKey

Attention: The methods rely on the Run.instance.available*DropList to be populated. As such, only run the ItemStringParser after Run.BuildDropTable() was executed.

ParseItemString

This is the main method you will want to use. This method interprets an item string, applying repetitions and other formatting rules, to build a collection of items/equipments with their amounts.

Signature

bool ItemStringParser.ItemStringParser.ParseItemString(string itemString, Dictionary<PickupIndex, int> resolvedItems, ManualLogSource log, int index = -1)

itemString (string): The input string containing item definitions to parse. It includes items, operators, and formatting syntax.

resolvedItems (Dictionary<PickupIndex, int>): A dictionary to which parsed item entries and their amounts will be added or updated.

log (ManualLogSource): For logging in case the provided itemString contains syntax errors.

index (int, optional): Specifies if a certain entry of the top-level or-group shall be taken or if it should be picked at random. -1 is default and means random.

Return Value: Whether it was successful

Usage Example

var resolvedItems = new Dictionary<PickupIndex, int>();
bool success = ItemStringParser.ItemStringParser.ParseItemString("5xHoof & {Tier1 | Tier2}*3", resolvedItems, Logger);
if (success) {
    foreach (var (pickupIndex, itemAmount) in resolvedItems) {
        if (itemIndex != ItemIndex.None && itemAmount > 0)
        {
            inventory.GiveItemPermanent(itemIndex, itemAmount);
        }
    }
}

Equipments are also supported. Example:

var inventory = master.inventory;
Dictionary<PickupIndex, int> itemsToGive = new Dictionary<PickupIndex, int>();
ItemStringParser.ItemStringParser.ParseItemString(itemString, itemsToGive, Logger);
uint equipIndex = 0;
foreach (var (pickupIndex, itemAmount) in itemsToGive)
{
    var pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
    // handle items
    var itemIndex = pickupDef.itemIndex;
    if (itemIndex != ItemIndex.None && itemAmount > 0)
    {
        inventory.GiveItemPermanent(itemIndex, itemAmount);
    }
    // handle equipments
    int maxEquipmentSlots = master.bodyPrefab.name == "ToolbotBody" ? 2 : 1;
    int maxEquipmentSets = master.inventory.GetItemCountEffective(DLC3Content.Items.ExtraEquipment.itemIndex) + 1;
    int maxEquipmentCount = maxEquipmentSlots * maxEquipmentSets;
    var equipmentCount = itemAmount;
    var equipmentIndex = pickupDef.equipmentIndex;
    while (equipmentIndex != EquipmentIndex.None && equipmentCount > 0 && equipIndex < maxEquipmentCount)
    {
        uint slot = (uint)(equipIndex % maxEquipmentSlots);
        uint set = (uint)(equipIndex / maxEquipmentSlots);
        inventory.SetEquipmentIndexForSlot(equipmentIndex, slot, set);
        equipmentCount--;
        equipIndex++;
    }
}

Index can be used to retrieve the n-th entry of the root or-group. Example:

ItemStringParser.ItemStringParser.ParseItemString("Hoof | AlienHead", resolvedItems, Logger, 0); // results in "Hoof"
ItemStringParser.ItemStringParser.ParseItemString("Hoof | AlienHead", resolvedItems, Logger, 1); // results in "AlienHead"
ItemStringParser.ItemStringParser.ParseItemString("Hoof | AlienHead", resolvedItems, Logger, -1); // results in either "Hoof" or "AlienHead"

ResolveItemKey

This method resolves a single item key string into actual items and adds them to the resolvedItems dictionary. It supports parsing item keys that represent item tiers, drop tables, concrete items, or concrete equipment. It also supports blacklisting certain items from selection. As such this method only supports the !-operator, but no other operator.

Signature

bool ItemStringParser.ItemStringParser.ResolveItemKey(string itemkey, int repeat, Dictionary<PickupIndex, int> resolvedItems, ManualLogSource log)

itemkey (string): The identifier string for the item or group of items to resolve. May exclude items from droptables or tiers with with !.

repeat (int): How many times to add the resolved items.

resolvedItems (Dictionary<PickupIndex, int>): Dictionary where resolved items and their counts will be added or updated.

log (ManualLogSource): For logging in case of errors in the item string.

Return Value: Whether it was successful.

Usage Example

var resolvedItems = new Dictionary<PickupIndex, int>();
ManualLogSource log = new ManualLogSource();

bool success = ItemStringParser.ResolveItemKey(
    "Tier1!Crowbar", // Tier1 items excluding Crowbar
    3,               // Add 3 items from this tier
    resolvedItems,
    Logger
);

if (success)
{
    // Use resolvedItems as needed
}