mirror of
https://github.com/RandomityGuy/MBHaxe.git
synced 2025-10-30 08:11:25 +00:00
deterministic gem hunt spawn
This commit is contained in:
parent
423f551655
commit
cc84f4d30e
5 changed files with 110 additions and 2 deletions
|
|
@ -581,6 +581,7 @@ class MarbleWorld extends Scheduler {
|
||||||
this.playGui.setCenterText('');
|
this.playGui.setCenterText('');
|
||||||
this.clearSchedule();
|
this.clearSchedule();
|
||||||
this.outOfBounds = false;
|
this.outOfBounds = false;
|
||||||
|
this.gameMode.onRespawn();
|
||||||
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
AudioManager.playSound(ResourceLoader.getResource('data/sound/spawn_alternate.wav', ResourceLoader.getAudio, this.soundResources));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
53
src/RandomLCG.hx
Normal file
53
src/RandomLCG.hx
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
class RandomLCG {
|
||||||
|
var seed:Int;
|
||||||
|
|
||||||
|
static var msSeed:Int = 1376312589;
|
||||||
|
|
||||||
|
static var quotient = 127773;
|
||||||
|
static var remainder = 2836;
|
||||||
|
|
||||||
|
public function new(seed = -1) {
|
||||||
|
this.seed = (seed == -1) ? generateSeed() : seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function generateSeed() {
|
||||||
|
// A very, VERY crude LCG but good enough to generate
|
||||||
|
// a nice range of seed values
|
||||||
|
msSeed = (msSeed * 0x015a4e35) + 1;
|
||||||
|
msSeed = (msSeed >> 16) & 0x7fff;
|
||||||
|
return (msSeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSeed(seed:Int) {
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function randInt() {
|
||||||
|
if (seed <= quotient)
|
||||||
|
seed = (seed * 16807) % 2147483647;
|
||||||
|
else {
|
||||||
|
var high_part:Int = Std.int(seed / quotient);
|
||||||
|
var low_part = seed % quotient;
|
||||||
|
|
||||||
|
var test:Int = (16807 * low_part) - (remainder * high_part);
|
||||||
|
|
||||||
|
if (test > 0)
|
||||||
|
seed = test;
|
||||||
|
else
|
||||||
|
seed = test + 2147483647;
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function randFloat() {
|
||||||
|
return randInt() / 2147483647.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function randRange(i:Int, n:Int) {
|
||||||
|
return (i + (randInt() % (n - i + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function randRangeF(i:Float, n:Int) {
|
||||||
|
return (i + (n - i) * randFloat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ interface GameMode {
|
||||||
public function applyRewindState(state:RewindableState):Void;
|
public function applyRewindState(state:RewindableState):Void;
|
||||||
public function onTimeExpire():Void;
|
public function onTimeExpire():Void;
|
||||||
public function onRestart():Void;
|
public function onRestart():Void;
|
||||||
|
public function onRespawn():Void;
|
||||||
public function onGemPickup(gem:Gem):Void;
|
public function onGemPickup(gem:Gem):Void;
|
||||||
|
|
||||||
public function getPreloadFiles():Array<String>;
|
public function getPreloadFiles():Array<String>;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package modes;
|
package modes;
|
||||||
|
|
||||||
|
import hxd.Rand;
|
||||||
import rewind.RewindableState;
|
import rewind.RewindableState;
|
||||||
import gui.AchievementsGui;
|
import gui.AchievementsGui;
|
||||||
import modes.GameMode.ScoreType;
|
import modes.GameMode.ScoreType;
|
||||||
|
|
@ -81,6 +82,8 @@ class HuntState implements RewindableState {
|
||||||
var activeGemSpawnGroup:Array<GemSpawnSphere>;
|
var activeGemSpawnGroup:Array<GemSpawnSphere>;
|
||||||
var activeGems:Array<Gem>;
|
var activeGems:Array<Gem>;
|
||||||
var points:Int;
|
var points:Int;
|
||||||
|
var rngState:Int;
|
||||||
|
var rngState2:Int;
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
|
|
@ -94,6 +97,8 @@ class HuntState implements RewindableState {
|
||||||
c.activeGemSpawnGroup = activeGemSpawnGroup.copy();
|
c.activeGemSpawnGroup = activeGemSpawnGroup.copy();
|
||||||
c.points = points;
|
c.points = points;
|
||||||
c.activeGems = activeGems.copy();
|
c.activeGems = activeGems.copy();
|
||||||
|
c.rngState = rngState;
|
||||||
|
c.rngState2 = rngState2;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,6 +114,8 @@ class HuntMode extends NullMode {
|
||||||
var activeGems:Array<Gem> = [];
|
var activeGems:Array<Gem> = [];
|
||||||
var gemBeams:Array<GemBeam> = [];
|
var gemBeams:Array<GemBeam> = [];
|
||||||
var gemToBeamMap:Map<Gem, GemBeam> = [];
|
var gemToBeamMap:Map<Gem, GemBeam> = [];
|
||||||
|
var rng:RandomLCG = new RandomLCG(100);
|
||||||
|
var rng2:RandomLCG = new RandomLCG(100);
|
||||||
|
|
||||||
var points:Int = 0;
|
var points:Int = 0;
|
||||||
|
|
||||||
|
|
@ -131,7 +138,7 @@ class HuntMode extends NullMode {
|
||||||
};
|
};
|
||||||
|
|
||||||
override function getSpawnTransform() {
|
override function getSpawnTransform() {
|
||||||
var randomSpawn = playerSpawnPoints[Math.floor(Math.random() * playerSpawnPoints.length)];
|
var randomSpawn = playerSpawnPoints[Math.floor(rng2.randRange(0, playerSpawnPoints.length - 1))];
|
||||||
var spawnPos = MisParser.parseVector3(randomSpawn.position);
|
var spawnPos = MisParser.parseVector3(randomSpawn.position);
|
||||||
spawnPos.x *= -1;
|
spawnPos.x *= -1;
|
||||||
var spawnRot = MisParser.parseRotation(randomSpawn.rotation);
|
var spawnRot = MisParser.parseRotation(randomSpawn.rotation);
|
||||||
|
|
@ -170,6 +177,7 @@ class HuntMode extends NullMode {
|
||||||
var spawnMat = spawnRot.toMatrix();
|
var spawnMat = spawnRot.toMatrix();
|
||||||
var up = spawnMat.up();
|
var up = spawnMat.up();
|
||||||
spawnPos = spawnPos.add(up.multiply(0.727843 / 3)); // 1.5 -> 0.5
|
spawnPos = spawnPos.add(up.multiply(0.727843 / 3)); // 1.5 -> 0.5
|
||||||
|
|
||||||
return {
|
return {
|
||||||
position: spawnPos,
|
position: spawnPos,
|
||||||
orientation: spawnRot,
|
orientation: spawnRot,
|
||||||
|
|
@ -179,6 +187,26 @@ class HuntMode extends NullMode {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override function onRespawn() {
|
||||||
|
if (activeGemSpawnGroup.length != 0) {
|
||||||
|
var gemAvg = new Vector();
|
||||||
|
for (g in activeGemSpawnGroup) {
|
||||||
|
gemAvg = gemAvg.add(g.position);
|
||||||
|
}
|
||||||
|
gemAvg.scale(1 / activeGemSpawnGroup.length);
|
||||||
|
var delta = gemAvg.sub(level.marble.getAbsPos().getPosition());
|
||||||
|
var gravFrame = level.getOrientationQuat(0).toMatrix();
|
||||||
|
var v1 = gravFrame.front();
|
||||||
|
var v2 = gravFrame.right();
|
||||||
|
var deltaRot = new Vector(delta.dot(v2), delta.dot(v1));
|
||||||
|
if (deltaRot.length() >= 0.001) {
|
||||||
|
var ang = Math.atan2(deltaRot.x, deltaRot.y);
|
||||||
|
level.marble.camera.CameraYaw = ang;
|
||||||
|
level.marble.camera.nextCameraYaw = ang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override public function getStartTime() {
|
override public function getStartTime() {
|
||||||
return level.mission.qualifyTime;
|
return level.mission.qualifyTime;
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +216,8 @@ class HuntMode extends NullMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
override function onRestart() {
|
override function onRestart() {
|
||||||
|
rng.setSeed(100);
|
||||||
|
rng2.setSeed(100);
|
||||||
setupGems();
|
setupGems();
|
||||||
points = 0;
|
points = 0;
|
||||||
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
@:privateAccess level.playGui.formatGemHuntCounter(points);
|
||||||
|
|
@ -242,9 +272,26 @@ class HuntMode extends NullMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
activeGemSpawnGroup = [];
|
||||||
|
|
||||||
activeGems = [];
|
activeGems = [];
|
||||||
refillGemGroups();
|
refillGemGroups();
|
||||||
|
|
||||||
|
var gemAvg = new Vector();
|
||||||
|
for (g in activeGemSpawnGroup) {
|
||||||
|
gemAvg = gemAvg.add(g.position);
|
||||||
|
}
|
||||||
|
gemAvg.scale(1 / activeGemSpawnGroup.length);
|
||||||
|
var delta = gemAvg.sub(level.marble.getAbsPos().getPosition());
|
||||||
|
var gravFrame = level.getOrientationQuat(0).toMatrix();
|
||||||
|
var v1 = gravFrame.front();
|
||||||
|
var v2 = gravFrame.right();
|
||||||
|
var deltaRot = new Vector(delta.dot(v2), delta.dot(v1));
|
||||||
|
if (deltaRot.length() >= 0.001) {
|
||||||
|
var ang = Math.atan2(deltaRot.x, deltaRot.y);
|
||||||
|
level.marble.camera.CameraYaw = ang;
|
||||||
|
level.marble.camera.nextCameraYaw = ang;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function refillGemGroups() {
|
function refillGemGroups() {
|
||||||
|
|
@ -320,7 +367,7 @@ class HuntMode extends NullMode {
|
||||||
|
|
||||||
function findGemSpawnGroup(outSpawnPoint:Vector) {
|
function findGemSpawnGroup(outSpawnPoint:Vector) {
|
||||||
// Pick random spawn point
|
// Pick random spawn point
|
||||||
var rnd:Int = Std.int(Math.random() * gemSpawnPoints.length);
|
var rnd:Int = Std.int(rng.randRange(0, gemSpawnPoints.length - 1));
|
||||||
if (level.isRecording)
|
if (level.isRecording)
|
||||||
level.replay.recordRandomGenState(rnd);
|
level.replay.recordRandomGenState(rnd);
|
||||||
if (level.isWatching)
|
if (level.isWatching)
|
||||||
|
|
@ -394,6 +441,8 @@ class HuntMode extends NullMode {
|
||||||
s.points = points;
|
s.points = points;
|
||||||
s.activeGemSpawnGroup = activeGemSpawnGroup;
|
s.activeGemSpawnGroup = activeGemSpawnGroup;
|
||||||
s.activeGems = activeGems.copy();
|
s.activeGems = activeGems.copy();
|
||||||
|
s.rngState = @:privateAccess rng.seed;
|
||||||
|
s.rngState2 = @:privateAccess rng2.seed;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,5 +464,7 @@ class HuntMode extends NullMode {
|
||||||
var gemBeam = gemToBeamMap.get(gem);
|
var gemBeam = gemToBeamMap.get(gem);
|
||||||
gemBeam.setHide(false);
|
gemBeam.setHide(false);
|
||||||
}
|
}
|
||||||
|
rng.setSeed(s.rngState);
|
||||||
|
rng2.setSeed(s.rngState2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ class NullMode implements GameMode {
|
||||||
|
|
||||||
public function onRestart() {}
|
public function onRestart() {}
|
||||||
|
|
||||||
|
public function onRespawn() {}
|
||||||
|
|
||||||
public function onGemPickup(gem:Gem) {
|
public function onGemPickup(gem:Gem) {
|
||||||
this.level.gemCount++;
|
this.level.gemCount++;
|
||||||
var string:String;
|
var string:String;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue