Skip to content

Latest commit

 

History

History
98 lines (82 loc) · 5.35 KB

README.md

File metadata and controls

98 lines (82 loc) · 5.35 KB

sourcemod-nt-ghost-distribution

SourceMod plugin for Neotokyo that distributes the ghost spawn locations uniformly and independently.

Also check out the alternative plugin for controlled ghost spawn sequences! See the FAQ section for details on the differences between these two plugins.

Build instructions

  • Compile the plugin in addons/sourcemod/scripting, and move the compiled .smx file to your server.
  • Copy the file in addons/sourcemod/gamedata/neotokyo to your server (create the "neotokyo" folder in gamedata, if it doesn't exist).

If you're using SourceMod older than 1.11, you also need a version of the DHooks extension compatible with your SM version.

FAQ

  • What?
    • Default NT ghost spawns are not "evenly random". This plugin fixes it.
  • Does this plugin eliminate streaks of unlucky ghost spawns?
    • No. Just as with coin flipping, streaks are possible.
  • The ghost spawned in the same location twice in a row!
    • This is intended–all results are equally likely, including getting the same exact spawn twice.
  • What's the diffence between this and the nt_ghost_spawn_bias plugin?
    • This plugin is focused on ensuring statistically independent, uniform distribution and nothing more. Soft's plugin implements a controlled bias of n same ghost spawns in a row, which can be used to play "sides" for the same ghost spawn point.
  • Should I use both plugins?
    • The plugins won't interfere with each other, but if you wish to use Soft's plugin, you don't need this plugin.

Background

(optional reading, in case you're curious about the details)

In Neotokyo, the ghost spawn selection is implemented (in disassembly) as:

push    3
push    1
call    edx                             ; get random int in 1-3 range (inclusive)
mov     esi, eax
add     esi, [edi+260h]                 ; add index of previous ghost spawn to the random index
mov     eax, [edi+258h]                 ; number of ghost spawns
cmp     esi, eax
jl      short get_array_at_index_offset
sub     esi, eax                        ; modulo wrap

Or, in pseudocode: (prev_ghost_spawn_index + RandomInt(1,3)) % num_ghost_spawns.

This means that for ghost spawn G, and n amount of contiguous ghost spawns total, the next chosen ghost spawn will (excluding the modulo wrap) follow the pattern of:

random stride (1-3)          1     2     3  ← next ghost spawn guaranteed to be one of these 3
                        ┌────↓─────↓─────↓
spawn index             G   G+1   G+2   G+3   G+4   G+5   (...)   Gₙ |

While the PRNG used is uniform, limiting the random output to a stride of 1-3 means the result is not independent. You could liken this to a dice that always rolled the previous roll plus 1, 2, or 3; if you just rolled a two, you know the next throw must result in either 2+1 (3), 2+2 (4), or 2+3 (5); it is impossible for your next dice roll to be a 1, 2 or 6! With an independent (and uniformly distributed) i.e. "fair" dice, any previous rolls should not affect the current roll, and all possible results should be equally likely.

This bias can be visualized by simulating a large number of NT rounds, and recording the ghost spawn positions' distribution. A "favourable ghost spawn" in this instance is arbitrarily chosen as exactly half of the total spawn points, to demonstrate the effect of the bias.

Note the recorded distribution (blue) skewing to the right, away from the expected distribution (red), as the number of ghost spawn points increases:

2 possible ghost spawn positions

2 ghosts

4 possible ghost spawn positions

4 ghosts

6 possible ghost spawn positions

6 ghosts

8 possible ghost spawn positions

8 ghosts

16 possible ghost spawn positions

16 ghosts

This plugin patches the selection function to be independent and identically (uniformly) distributed–the blue line overlaps with the expected distribution in red:

ghostspawn_sim_16_ghosts

If you want to verify the difference yourself, the simulation related stuff is also included in the repo, in the tests folder.