Key Randomization - Die4Ever/deus-ex-randomizer GitHub Wiki
Key Randomization
The code for determining where a key can end up is here DXRKeys.uc#L329 and here DXRActorsBase.uc#L675
If we look at the DuClare Chateau, we see the key is supposed to be on the 2nd floor, and the door goes down from the kitchen
Bad Key Randomization 1
If we just make sure to put the key closer to the player's starting position than the door is, it looks like this The red Xs show where the randomizer would not allow the key to go, and the green checkmark shows where it would allow the key to go. This has a couple problems. As you can see, the key could easily be placed into the wine cellar, where the player would be unable to get it. Also, this means that key randomization depends on how the player first enters the level, which matters for areas that have multiple entrances, and that could affect a competitive race.
Bad Key Randomization 2
Here is a smarter method. We make sure we place the key closer to the original key's position than to the door. This no longer relies on the player's starting position, but it still allows some key locations in the cellar that shouldn't be allowed (shown with the yellow question mark).
"Smart" Key Randomization v1.0
Here is the "Smart" method used in v1.0 (this is just called "On" in v1.3) Here we calculate the distance on each axis independently. So we make sure that the key ends up closer to the original position than to the door, not the overall distance, but the X-distance, Y-distance, and Z-distance.
The code for it basically looks like this
function vector AbsEach(vector v)
{
v.X = abs(v.X);
v.Y = abs(v.Y);
v.Z = abs(v.Z);
return v;
}
function bool AnyGreater(vector a, vector b)
{
return a.X > b.X || a.Y > b.Y || a.Z > b.Z;
}
//some loops...
distkey = AbsEach(actor.Location - key.Location);
distdoor = AbsEach(actor.Location - doorloc);
if ( AnyGreater( distkey, distdoor ) ) continue;
else Swap(actor, key);
"Smarter" Key Randomization?
One other method that I'm thinking of, is using the normal (not per-axis) distance from the key vs door, but also a per-axis check against the position of the door. (This is called "Smart" in v1.3, now it's just called "On" in v1.3.3.7) Here the yellow + sign is the axis of the door's position, the green diagonal line is the line equidistant from the key's original position and the door. So here we make sure that the key's new position is on the correct side of the green line, and also within the correct octant (cause it's 3d, the diagram is 2d so you can call it quadrant in that case) of the yellow grid based on the door's position. This is a little more permissive than the v1.0 "Smart" method, but still should be safe for every level in the game. The red Xs show where the randomizer would not allow the key to go, and the green checkmark shows where it would allow the key to go.