SPAWN DISTRIBUTION PLUS 1.2 - CONFIGURATION GUIDE
==================================================

This guide is for the config.json supplied with Spawn Distribution Plus.
The ready-to-use file is already set to the supplied high-level spawn profile.
You can run the plugin without changing anything.

For an easier visual setup, open ConfigDesigner.html from the packaged plugin
folder. It works offline, checks the current version 3 rules, previews projected
level frequencies, imports an existing config, and downloads config.json.


WHERE THE CONFIG GOES
---------------------

After installation, the live file is:

ShooterGame\Binaries\Win64\ArkApi\Plugins\SpawnDistributionPlus\config.json

Keep JSON punctuation exactly as shown. JSON does not allow comments, so use
config.reference.jsonc when you want a commented example. Before editing the
live config, make a backup.


THE SAFE WAY TO MAKE A CHANGE
-----------------------------

1. Edit config.json and save it.
2. Run reloadspawns from RCON, chat, or the in-game console.
3. Run currentsettings and check the resolved mode, chances, and base ranges.
4. Run spawnstats to make sure failures and vanilla fallbacks are not climbing.
5. For a real distribution check, wipe wild dinos, allow fresh dinos to spawn,
   then run dinolevels.

An invalid reload is rejected. The last working configuration stays active.
Existing wild dinos do not have their levels changed; this plugin affects new
level rolls, so use the normal DestroyWildDinos workflow when testing a change.

Changing a command name requires a full server restart. Command names cannot be
changed with reloadspawns because ARK API commands must be registered safely.


QUICK MODE CHOICES
------------------

Use ARK's original distribution:

"Distribution": {
  "Mode": "Official"
}

Use the supplied Spawn Distribution Plus Ragnarok-style profile:

"Distribution": {
  "Mode": "Ragnarok"
}

Use your own four band chances:

"Distribution": {
  "Mode": "Custom",
  "BandChancesPercent": {
    "Low": 25,
    "Mid": 25,
    "MidHigh": 25,
    "High": 25
  }
}

The equal 25 percent example is only an example, not a recommendation. Pick a
distribution that suits your server.


EVERY CONFIGURATION SETTING
---------------------------

ConfigVersion
  Use 3 for the supplied format. Version 1, version 2, and old configs without
  this field remain accepted and keep their prior behavior because new options
  default off. ExtendedLevelLerp itself requires version 3. No value above 3 is
  accepted.

General.Enabled
  true enables the plugin's level-roll changes. false leaves ARK's original
  rolls in place while keeping the plugin and its commands loaded.

General.DebugLogging
  true writes every distribution failure to the SpawnDistributionPlus log.
  false logs the first failure and then uses Safety.LogEveryNthFailure to limit
  repeats. Leave it false for normal use and turn it on while investigating.

General.LogConfigOnStartup
  true writes the resolved settings summary to the ARK API log when the plugin
  starts. This is useful for confirming which config the server loaded.


COMMANDS
--------

Commands.RequireAdmin
  true restricts player chat and console commands to server admins. RCON is
  already protected by RCON authentication. Set this to false only if regular
  players should be allowed to run the report and status commands too.

Commands.LevelList
  Name of the wild-dino report command. Default: dinolevels

Commands.LevelSettingsList
  Name of the active-settings command. Default: currentsettings

Commands.Reload
  Name of the config reload command. Default: reloadspawns

Commands.Stats
  Name of the runtime counter command. Default: spawnstats

All four names must be different, cannot be empty, and cannot contain spaces.
Set command names before the server starts. Restart after changing them.


CUSTOM LEVEL GENERATION
-----------------------

CustomLevels.Enabled
  false uses the four weighted distribution bands. true bypasses those bands
  and uniformly rolls within the custom minimum and maximum below.

CustomLevels.Min
  Lowest displayed level requested by the custom generator. Must be at least 1.

CustomLevels.Max
  Highest displayed level requested by the custom generator. It cannot be lower
  than Min.

CustomLevels.LevelStep
  The displayed-level increment that has been verified for your server. When
  CustomLevels.Enabled is true, this must be greater than zero. The plugin does
  not guess it because live testing proved the level hook's float argument is
  not a safe source for this value. Zero is allowed only while custom levels
  are disabled.

CustomLevels is an advanced alternative to the distribution profile. Do not
enable it simply to raise the chance of high-level dinos; use the band chances
for that. Confirm your server's actual results with dinolevels.


EXTENDED-CREATURE RAGNAROK LEVEL INTERPOLATION

ExtendedLevelLerp.Enabled
  false is the safe default and performs no lerp field access. Setting it to
  true is verified as of 1.2; the plugin measures the level field from the
  running game build and turns the feature off for the session if it cannot do
  so unambiguously. It cannot be true while CustomLevels.Enabled is true,
  because custom uniform rolls bypass ARK's native level bands.

ExtendedLevelLerp.Rules
  An array of at most 256 map-and-dino rules. Each rule requires MapPattern,
  DinoPattern, and Amount. Patterns are case-insensitive, cannot be empty, and
  support * and ?. The matching rule with the most non-wildcard characters
  across both patterns wins; file order breaks an exact specificity tie.

  The packaged rule is ready to enable for Aberration Rock Drakes:

  "ExtendedLevelLerp": {
    "Enabled": true,
    "Rules": [
      {
        "MapPattern": "Aberration_WP",
        "DinoPattern": "*RockDrake_Character_BP*",
        "Amount": 0.5
      }
    ]
  }

  Amount is the target effective native interpolation after ARK's read-only
  world setting and per-dino modifier are combined. It must be finite, greater
  than zero, and no greater than 1. The plugin considers it only when ARK
  supplies the exact extended four-range layout: 1-5, 6-12, 13-20, and 21-38.
  Weights do not affect that safety check.

This feature controls ARK's native within-band interpolation independently from
Distribution.Mode. Mode Ragnarok keeps Spawn Distribution Plus's enhanced band
weights and adds the configured interpolation. To reproduce vanilla Ragnarok's
Rock Drake distribution exactly, add a matching DinoOverride with Mode Official
so ARK keeps its native 40/20/20/20 band weights while the lerp rule supplies
the 0.5 within-band behavior.

The setting never changes the global world lerp value. Each matched dino's
original field is restored immediately after its one native level roll. A field
read, write, or restore fault disables all later lerp writes until server
restart and is visible in spawnstats.

To roll back, set ExtendedLevelLerp.Enabled to false, run reloadspawns, wipe
wild dinos, and compare only fresh spawns. Existing creatures do not change.


DISTRIBUTION PROFILE
--------------------

Distribution.Mode
  Official  - do not modify ARK's distribution.
  Ragnarok - use the supplied Spawn Distribution Plus behavior.
  Custom    - use your chosen profile.

  Mode names are case-insensitive. The legacy aliases Vanilla and Disabled map
  to Official, and Rag maps to Ragnarok.

Distribution.RewriteCanonicalRanges
  true replaces the ranges when ARK presents the standard four-band layout.
  false changes compatible weights but keeps ARK's original ranges.

Distribution.RewriteExtendedRanges
  false is the compatibility default and keeps an extended creature's native
  ranges. true rewrites only an exact 1-5, 6-12, 13-20, 21-38 layout by scaling
  the profile's four canonical 1-30 BaseLevelRanges into 1-38.

  Every boundary uses ceiling(value x 38 / 30), then clamps to 1-38. If scaled
  bands overlap, each later minimum moves to one above the previous maximum and
  its maximum moves with it when needed. A configuration is rejected
  transactionally if four ordered bands cannot fit; no ARK entry is partially
  changed. Near matches and every other noncanonical layout keep native ranges.

  With the supplied 3-5, 9-12, 17-20, 26-30 ranges, the exact extended result is
  4-7, 12-16, 22-26, 33-38. At a verified 5x displayed-level multiplier, those
  correspond to 20-35, 60-80, 110-130, and 165-190. This is a static scaling
  result, not a new live compatibility claim.

Distribution.ApplyToNonCanonical
  true maps the four configured chances across safe layouts that do not match
  the standard four-band layout. Their native ranges are kept. This is the path
  used for Aberration-style and other valid non-standard layouts.
  false leaves every non-standard layout on ARK's original roll.

Distribution.ReverseApexWeights
  true reverses Low, Mid, MidHigh, and High weights for dinos matching
  ApexDinoBPs. false keeps the normal order.

Distribution.ApexWeightMultiplier
  A finite number of zero or more. It scales all four weights for matched apex
  dinos after any reversal. The supplied Ragnarok profile uses 1.0. Selecting
  Custom mode sets the recovered custom defaults (no reversal and 0.5) unless
  you explicitly supply these two apex settings in that profile.

Distribution.BandChancesPercent
  The readable chance values for the Low, Mid, MidHigh, and High bands. Each
  number must be from 0 through 100, and all four must total 100 (within the
  parser's 0.05 rounding tolerance). At least one band must be greater than 0.

  Supplied Spawn Distribution Plus values:

  "BandChancesPercent": {
    "Low": 33.333333,
    "Mid": 26.666667,
    "MidHigh": 23.333333,
    "High": 16.666667
  }

  Use BandChancesPercent or the legacy Weights field, never both in the same
  profile.

Distribution.BaseLevelRanges
  Exactly four range objects, ordered from low to high. Min cannot be greater
  than Max. These are ARK engine base-level indices, not displayed dino levels.

  Supplied ranges:

  "BaseLevelRanges": [
    { "Min": 3, "Max": 5 },
    { "Min": 9, "Max": 12 },
    { "Min": 17, "Max": 20 },
    { "Min": 26, "Max": 30 }
  ]

  On the verified test server with OverrideOfficialDifficulty=5.0, those base
  ranges produced displayed ranges of 15-25, 45-60, 85-100, and 130-150. That
  observation is not proof of the conversion on a differently configured
  server. Use dinolevels to verify your own result.

  Use BaseLevelRanges or the legacy Ranges field, never both in the same
  profile.


MAP AND DINO OVERRIDES
----------------------

Distribution.MapOverrides
  An object keyed by a map-name pattern. Matching is case-insensitive. Patterns
  can be a plain substring or use * for any number of characters and ? for one
  character. If more than one pattern matches, the most specific pattern wins.

  Example:

  "MapOverrides": {
    "Aberration*": {
      "Mode": "Ragnarok",
      "ApplyToNonCanonical": true
    },
    "*ExampleModMap*": {
      "Mode": "Custom",
      "BandChancesPercent": {
        "Low": 10,
        "Mid": 20,
        "MidHigh": 30,
        "High": 40
      }
    }
  }

  The ExampleModMap percentages demonstrate the format only.

Distribution.DinoOverrides
  Works like MapOverrides but matches the resolved dino blueprint name. A dino
  override wins over both the default profile and a matching map override.

  Example:

  "DinoOverrides": {
    "*Titanosaur*": { "Mode": "Official" }
  }

An override inherits settings from the main Distribution profile, then replaces
only the fields written inside that override. A profile in either override can
use Mode, RewriteCanonicalRanges, RewriteExtendedRanges, ApplyToNonCanonical,
ReverseApexWeights, ApexWeightMultiplier, BandChancesPercent, and
BaseLevelRanges. Changing Mode resets the rewrite options to their mode-preset
defaults (canonical true, extended false) before later fields in the same
override are applied.

Profile precedence is:

  main Distribution profile -> best matching map rule -> best matching dino rule


DINO LISTS
----------

ExcludedDinoBPs
  A JSON array of blueprint-name patterns that must use ARK's original level
  roll. Matching is case-insensitive and supports the same substring, *, and ?
  rules used by overrides. An exclusion bypasses all distribution and custom
  level changes for that dino.

ApexDinoBPs
  A JSON array of blueprint-name patterns treated as apex dinos. A matching dino
  uses the active profile's ReverseApexWeights and ApexWeightMultiplier rules.

Set Reports.IncludeBlueprint to true and run dinolevels when you need the exact
resolved blueprint text for an override, exclusion, or apex entry.


REPORTS
-------

Reports.Enabled
  true allows dinolevels to write reports. false makes that command return a
  disabled message. The other commands continue to work.

Reports.MaxActors
  Safety limit for the total dino actors examined during one report. It must be
  at least 1. The report is cancelled rather than scanning beyond this limit.

Reports.MinimumLevel
  Lowest wild-dino level included in a report. It must be at least 1.

Reports.MaximumLevel
  Highest wild-dino level included in a report. Use 0 for no upper limit.
  Any other value must be at least MinimumLevel.

Reports.IncludeBlueprint
  true adds a Blueprint column to report files. false writes the shorter Dino,
  Level, and Count layout.

Only wild dinos are counted. Tamed or owned dinos are not included.


SAFETY
------

Safety.MaxWeightEntries
  Maximum number of ARK weight entries the plugin will accept for one roll. The
  valid range is 1 through 256; the supplied value is 64. Unexpected or larger
  layouts safely fall back to ARK's original roll.

Safety.LogEveryNthFailure
  Controls repeated failure logging. The first failure is logged, followed by
  every Nth failure. It must be at least 1. The supplied value is 1000, which
  avoids filling the log during a repeated problem.

The old Safety.RestoreEntriesAfterRoll field is still read for compatibility,
but false is deliberately ignored. Restoring ARK's original entries after every
roll is mandatory for map safety.


WHAT EACH COMMAND DOES
----------------------

dinolevels
  Writes two reports in the SpawnDistributionPlus plugin folder:

  - All-Dinos.txt keeps the tab-separated data format used by analysis tools.
  - All-Dinos-pretty.txt uses "Level - Dino - Count", sorts levels from low to
    high, and puts a blank line between visible level tiers and dino names.

  The readable report combines identical display names even when
  Reports.IncludeBlueprint is true; use the tab-separated report when exact
  blueprint identity matters.

dinolevels rex
  Writes rex.txt and rex-pretty.txt, including only wild dinos whose descriptive
  name contains "rex". The filter is case-insensitive. Unsafe filename
  characters are changed to underscores.

currentsettings
  Shows whether the plugin is enabled, config version, active map, default mode,
  normalized chances, both range-rewrite switches, configured base ranges,
  custom-level state, and the number of exclusions, overrides, and
  extended-lerp rules. Base ranges are not displayed dino levels.

reloadspawns
  Reads and validates config.json, then atomically activates it. A bad file does
  not replace the running configuration.

spawnstats
  Shows total rolls, modified rolls, custom rolls, exclusions, invalid layouts,
  failures, vanilla fallbacks, lerp matches, applications, already-equal no-ops,
  layout bypasses, field failures, restore failures, and the lerp circuit state.
  A fallback means the safe original ARK roll was used for that event. Release
  validation requires zero lerp field/restore failures and circuit=open.

The commands are registered for chat, player console, and RCON. The actual names
are whatever you set in the Commands section.


LEGACY CONFIG SUPPORT
---------------------

Old configurations remain usable, but new edits should use the version 3 format.
Version 1 and 2 configs always leave ExtendedLevelLerp disabled.

Weights
  Legacy alternative to BandChancesPercent. It can be an array of four
  non-negative numbers or an object with Low, Mid, MidHigh, and High. The values
  are relative weights and do not need to total 100. At least one must be above
  zero. Do not use Weights and BandChancesPercent together.

Ranges
  Legacy name for BaseLevelRanges. It still requires exactly four ordered Min
  and Max objects. Do not use both names together.

RagnarokStyle
  Legacy boolean mode switch. true selects Ragnarok behavior; false selects
  Official behavior unless the legacy Custom section is enabled.

Custom
  Legacy custom-weight object with Enabled, Low, Mid, MidHigh, and High fields.
  This is different from the top-level CustomLevels uniform level generator.

RestoreEntriesAfterRoll
  Legacy safety field. false is ignored because entry restoration is mandatory.


COMMON MISTAKES
---------------

- BandChancesPercent does not total 100.
- Both BandChancesPercent and Weights appear in one profile.
- Both BaseLevelRanges and Ranges appear in one profile.
- RewriteExtendedRanges cannot fit four ordered scaled bands inside 1-38.
- CustomLevels is enabled while LevelStep is zero or unverified.
- CustomLevels and ExtendedLevelLerp are enabled together.
- An ExtendedLevelLerp rule has an empty pattern, duplicate map/dino pair, or
  Amount outside the greater-than-zero through 1 range.
- A broad lerp wildcard unintentionally matches several creatures or maps.
- A command name is duplicated, contains a space, or was changed without a
  server restart.
- A JSON comma, quote, brace, or bracket is missing.
- A report is used before enough fresh wild dinos have spawned.
- Existing dinos are expected to change after a reload.
- BaseLevelRanges are mistaken for displayed dino levels.

If a reload fails, read the SpawnDistributionPlus ARK API log entry. It names
the field that failed validation, while the server continues with the last good
configuration.
