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.
- 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.
- 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.
(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 |
4 possible ghost spawn positions |
6 possible ghost spawn positions |
8 possible ghost spawn positions |
16 possible ghost spawn positions |
This plugin patches the selection function to be independent and identically (uniformly) distributed–the blue line overlaps with the expected distribution in red:
If you want to verify the difference yourself, the simulation related stuff is also included in the repo, in the tests folder.