SPAWN DISTRIBUTION PLUS 1 - 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.


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 2 for the supplied format. Version 1 and old configs without this field
  remain accepted for compatibility. No value above 2 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.


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.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, ApplyToNonCanonical, ReverseApexWeights,
ApexWeightMultiplier, BandChancesPercent, and BaseLevelRanges.

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 All-Dinos.txt in the SpawnDistributionPlus plugin folder. Rows are
  grouped by dino name and level, with a count for each group.

dinolevels rex
  Writes rex.txt and includes 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, configured base ranges, custom-level state, and the number
  of exclusions and overrides. 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, and vanilla fallbacks. A fallback means the safe original ARK roll
  was used for that event.

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 2 names.

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.
- CustomLevels is enabled while LevelStep is zero or unverified.
- 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.
