fix traplaunches, like really

This commit is contained in:
RandomityGuy 2023-05-24 18:57:10 +05:30
parent 5b8b802dfd
commit 207002cbdb
5 changed files with 102 additions and 161 deletions

View file

@ -1315,15 +1315,25 @@ class Marble extends GameObject {
function advancePhysics(timeState:TimeState, m:Move, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>) { function advancePhysics(timeState:TimeState, m:Move, collisionWorld:CollisionWorld, pathedInteriors:Array<PathedInterior>) {
var timeRemaining = timeState.dt; var timeRemaining = timeState.dt;
var startTime = timeRemaining;
var it = 0; var it = 0;
var piTime = timeState.currentAttemptTime; var piTime = timeRemaining;
_bounceYet = false; _bounceYet = false;
var contactTime = 0.0; var contactTime = 0.0;
var it = 0; var it = 0;
var passedTime = timeState.currentAttemptTime;
if (this.controllable) {
for (interior in pathedInteriors) {
// interior.pushTickState();
interior.computeNextPathStep(timeRemaining);
}
}
do { do {
if (timeRemaining <= 0) if (timeRemaining <= 0)
break; break;
@ -1332,12 +1342,7 @@ class Marble extends GameObject {
if (timeRemaining < timeStep) if (timeRemaining < timeStep)
timeStep = timeRemaining; timeStep = timeRemaining;
if (this.controllable) { passedTime += timeStep;
for (interior in pathedInteriors) {
interior.pushTickState();
interior.recomputeVelocity(piTime + timeStep * 4, timeStep * 4);
}
}
var stoppedPaths = false; var stoppedPaths = false;
var tempState = timeState.clone(); var tempState = timeState.clone();
@ -1436,17 +1441,24 @@ class Marble extends GameObject {
// var expectedPos = pos.add(posAdd); // var expectedPos = pos.add(posAdd);
// var newPos = nudgeToContacts(expectedPos, _radius); // var newPos = nudgeToContacts(expectedPos, _radius);
piTime += timeStep; // if (mode == Start) {
if (this.controllable) { // var upVec = this.level.currentUp;
for (interior in pathedInteriors) { // var startpadNormal = startPad.getAbsPos().up();
interior.popTickState(); // this.velocity = upVec.multiply(this.velocity.dot(upVec));
interior.setStopped(stoppedPaths); // // Apply contact forces in startPad up direction if upVec is not startpad up, fixes the weird startpad shit in pinball wizard
var piDT = timeState.clone(); // if (upVec.dot(startpadNormal) < 0.95) {
piDT.currentAttemptTime = piTime; // for (contact in contacts) {
piDT.dt = timeStep; // var normF = contact.normal.multiply(contact.normalForce);
interior.update(piDT); // var startpadF = startpadNormal.multiply(normF.dot(startpadNormal));
} // var upF = upVec.multiply(normF.dot(upVec));
} // this.velocity = this.velocity.add(startpadF.multiply(timeStep / 4));
// }
// }
// }
// if (mode == Finish) {
// this.velocity = this.velocity.multiply(0.925);
// }
var rot = this.getRotationQuat(); var rot = this.getRotationQuat();
var quat = new Quat(); var quat = new Quat();
@ -1466,14 +1478,14 @@ class Marble extends GameObject {
if (this.heldPowerup != null && m.powerup && !this.level.outOfBounds) { if (this.heldPowerup != null && m.powerup && !this.level.outOfBounds) {
var pTime = timeState.clone(); var pTime = timeState.clone();
pTime.dt = timeStep; pTime.dt = timeStep;
pTime.currentAttemptTime = piTime; pTime.currentAttemptTime = passedTime;
this.heldPowerup.use(pTime); this.heldPowerup.use(pTime);
this.heldPowerup = null; this.heldPowerup = null;
} }
if (this.controllable && this.prevPos != null) { if (this.controllable && this.prevPos != null) {
var tempTimeState = timeState.clone(); var tempTimeState = timeState.clone();
tempState.currentAttemptTime = piTime; tempState.currentAttemptTime = passedTime;
tempState.dt = timeStep; tempState.dt = timeStep;
this.level.callCollisionHandlers(cast this, tempTimeState, pos, newPos, rot, quat); this.level.callCollisionHandlers(cast this, tempTimeState, pos, newPos, rot, quat);
} }
@ -1482,7 +1494,26 @@ class Marble extends GameObject {
contactTime += timeStep; contactTime += timeStep;
timeRemaining -= timeStep; timeRemaining -= timeStep;
if (this.controllable) {
for (interior in pathedInteriors) {
interior.advance(timeStep);
}
}
piTime += timeStep;
if (tdiff == 0 || it > 10)
break;
} while (true); } while (true);
if (timeRemaining > 0) {
// Advance pls
if (this.controllable) {
for (interior in pathedInteriors) {
interior.advance(timeRemaining);
}
}
}
this.queuedContacts = []; this.queuedContacts = [];
this.updateRollSound(contactTime / timeState.dt, this._slipAmount); this.updateRollSound(contactTime / timeState.dt, this._slipAmount);

View file

@ -24,9 +24,6 @@ import src.Resource;
typedef PIState = { typedef PIState = {
var currentTime:Float; var currentTime:Float;
var targetTime:Float; var targetTime:Float;
var changeTime:Float;
var prevPosition:Vector;
var currentPosition:Vector;
var velocity:Vector; var velocity:Vector;
} }
@ -42,21 +39,14 @@ class PathedInterior extends InteriorObject {
public var duration:Float; public var duration:Float;
public var currentTime:Float; public var currentTime:Float;
public var targetTime:Float; public var targetTime:Float;
public var changeTime:Float;
var basePosition:Vector; var basePosition:Vector;
var baseOrientation:Quat; var baseOrientation:Quat;
var baseScale:Vector; var baseScale:Vector;
public var prevPosition:Vector;
public var currentPosition:Vector;
public var velocity:Vector; public var velocity:Vector;
var stopped:Bool = false; var stopped:Bool = false;
var stopTime:Float;
var previousState:PIState;
var soundChannel:Channel; var soundChannel:Channel;
@ -145,78 +135,63 @@ class PathedInterior extends InteriorObject {
onFinish(); onFinish();
} }
public function update(timeState:TimeState) { public function computeNextPathStep(timeDelta:Float) {
// this.previousState = { stopped = false;
// currentTime: currentTime, if (currentTime == targetTime) {
// targetTime: targetTime, velocity.set(0, 0, 0);
// changeTime: changeTime, } else {
// prevPosition: prevPosition, var delta = 0.0;
// currentPosition: currentPosition, if (targetTime < 0) {
// velocity: velocity if (targetTime == -1)
// }; delta = timeDelta;
else if (targetTime == -2)
delta = -timeDelta;
currentTime += delta;
while (currentTime >= duration)
currentTime -= duration;
while (currentTime < 0)
currentTime += duration;
} else {
delta = targetTime - currentTime;
if (delta < -timeDelta)
delta = -timeDelta;
else if (delta > timeDelta)
delta = timeDelta;
currentTime += delta;
}
var thisTime = timeState.currentAttemptTime; var curTform = this.getAbsPos();
var tForm = getTransformAtTime(currentTime);
if (stopped) { var displaceDelta = tForm.getPosition().sub(curTform.getPosition());
thisTime = stopTime; velocity.set(displaceDelta.x / timeDelta, displaceDelta.y / timeDelta, displaceDelta.z / timeDelta);
popTickState(); this.collider.velocity = velocity.clone();
} }
var transform = this.getTransformAtTime(this.getInternalTime(thisTime));
this.setTransform(transform);
var position = transform.getPosition();
this.prevPosition = this.currentPosition;
this.currentPosition = position;
if (!stopped) {
this.stopTime = timeState.currentAttemptTime;
pushTickState();
}
// if (!stopped)
// this.currentTime = timeState.currentAttemptTime;
velocity = position.sub(this.prevPosition).multiply(1 / timeState.dt);
this.updatePosition();
} }
public function advance(timeDelta:Float) {
if (stopped)
return;
if (this.velocity.length() == 0)
return;
var newp = this.getAbsPos().getPosition().add(velocity.multiply(timeDelta));
this.setPosition(newp.x, newp.y, newp.z);
this.collider.setTransform(this.getTransform());
if (this.soundChannel != null) {
var spat = this.soundChannel.getEffect(Spatialization);
spat.position = newp;
}
}
public function update(timeState:TimeState) {}
public function setStopped(stopped:Bool = true) { public function setStopped(stopped:Bool = true) {
// if (!this.stopped) // if (!this.stopped)
// this.stopTime = currentTime; // this.stopTime = currentTime;
this.stopped = stopped; this.stopped = stopped;
} }
public function recomputeVelocity(currentTime:Float, dt:Float) {
var thisTime = currentTime;
var transform = this.getTransformAtTime(this.getInternalTime(thisTime));
var position = transform.getPosition();
velocity = position.sub(this.currentPosition).multiply(1 / dt);
this.collider.velocity = velocity;
}
public function pushTickState() {
this.previousState = {
currentTime: currentTime,
targetTime: targetTime,
changeTime: changeTime,
prevPosition: prevPosition,
currentPosition: currentPosition,
velocity: velocity
};
}
public function popTickState() {
this.currentTime = this.previousState.currentTime;
this.targetTime = this.previousState.targetTime;
this.changeTime = this.previousState.changeTime;
this.prevPosition = this.previousState.prevPosition;
this.currentPosition = this.previousState.currentPosition;
this.velocity = this.previousState.velocity;
this.collider.velocity = this.velocity;
// this.updatePosition();
}
function computeDuration() { function computeDuration() {
var total = 0.0; var total = 0.0;
for (i in 0...(markerData.length - 1)) { for (i in 0...(markerData.length - 1)) {
@ -227,32 +202,18 @@ class PathedInterior extends InteriorObject {
} }
public function setTargetTime(now:TimeState, target:Float) { public function setTargetTime(now:TimeState, target:Float) {
var currentInternalTime = this.getInternalTime(now.currentAttemptTime);
this.currentTime = currentInternalTime; // Start where the interior currently is
this.targetTime = target; this.targetTime = target;
this.changeTime = now.currentAttemptTime;
}
public function getInternalTime(externalTime:Float) {
if (this.targetTime < 0) {
var direction = (this.targetTime == -1) ? 1 : (this.targetTime == -2) ? -1 : 0;
return Util.adjustedMod(this.currentTime + (externalTime - this.changeTime) * direction, this.duration);
} else {
var dur = Math.abs(this.currentTime - this.targetTime);
var compvarion = Util.clamp(dur != 0 ? (externalTime - this.changeTime) / dur : 1, 0, 1);
return Util.clamp(Util.lerp(this.currentTime, this.targetTime, compvarion), 0, this.duration);
}
} }
function updatePosition() { function updatePosition() {
this.setPosition(this.currentPosition.x, this.currentPosition.y, this.currentPosition.z); var newp = this.getAbsPos().getPosition();
this.setPosition(newp.x, newp.y, newp.z);
this.collider.setTransform(this.getTransform()); this.collider.setTransform(this.getTransform());
this.collider.velocity = this.velocity; this.collider.velocity = this.velocity;
if (this.soundChannel != null) { if (this.soundChannel != null) {
var spat = this.soundChannel.getEffect(Spatialization); var spat = this.soundChannel.getEffect(Spatialization);
spat.position = this.currentPosition; spat.position = newp;
} }
} }
@ -327,7 +288,6 @@ class PathedInterior extends InteriorObject {
override function reset() { override function reset() {
this.currentTime = 0; this.currentTime = 0;
this.targetTime = 0; this.targetTime = 0;
this.changeTime = 0;
if (this.element.initialposition != "") { if (this.element.initialposition != "") {
this.currentTime = MisParser.parseNumber(this.element.initialposition) / 1000; this.currentTime = MisParser.parseNumber(this.element.initialposition) / 1000;
@ -342,14 +302,11 @@ class PathedInterior extends InteriorObject {
this.currentTime = this.duration; this.currentTime = this.duration;
} }
this.stopTime = 0;
this.stopped = false; this.stopped = false;
// Reset the position // Reset the position
var transform = this.getTransformAtTime(this.getInternalTime(0));
var position = transform.getPosition();
this.prevPosition = position.clone();
this.currentPosition = position;
this.velocity = new Vector(); this.velocity = new Vector();
var initialTform = this.getTransformAtTime(this.currentTime);
this.setTransform(initialTform);
updatePosition(); updatePosition();
} }
} }

View file

@ -20,9 +20,7 @@ class RewindFrame {
var bonusTime:Float; var bonusTime:Float;
var mpStates:Array<{ var mpStates:Array<{
curState:PIState, curState:PIState,
prevState:PIState,
stopped:Bool, stopped:Bool,
stopTime:Float
}>; }>;
var gemCount:Int; var gemCount:Int;
var gemStates:Array<Bool>; var gemStates:Array<Bool>;
@ -62,20 +60,8 @@ class RewindFrame {
currentTime: s.curState.currentTime, currentTime: s.curState.currentTime,
targetTime: s.curState.targetTime, targetTime: s.curState.targetTime,
velocity: s.curState.velocity.clone(), velocity: s.curState.velocity.clone(),
currentPosition: s.curState.currentPosition.clone(),
prevPosition: s.curState.prevPosition.clone(),
changeTime: s.curState.changeTime,
}, },
stopTime: s.stopTime,
stopped: s.stopped, stopped: s.stopped,
prevState: s.prevState != null ? {
currentTime: s.prevState.currentTime,
targetTime: s.prevState.targetTime,
velocity: s.prevState.velocity.clone(),
currentPosition: s.prevState.currentPosition.clone(),
prevPosition: s.prevState.prevPosition.clone(),
changeTime: s.prevState.changeTime,
} : null,
}); });
} }
c.trapdoorStates = []; c.trapdoorStates = [];

View file

@ -42,20 +42,8 @@ class RewindManager {
currentTime: x.currentTime, currentTime: x.currentTime,
targetTime: x.targetTime, targetTime: x.targetTime,
velocity: x.velocity.clone(), velocity: x.velocity.clone(),
currentPosition: x.currentPosition.clone(),
prevPosition: x.prevPosition.clone(),
changeTime: x.changeTime,
}, },
stopTime: @:privateAccess x.stopTime,
stopped: @:privateAccess x.stopped, stopped: @:privateAccess x.stopped,
prevState: @:privateAccess x.previousState != null ? {
currentTime: @:privateAccess x.previousState.currentTime,
targetTime: @:privateAccess x.previousState.targetTime,
velocity: @:privateAccess x.previousState.velocity.clone(),
currentPosition: @:privateAccess x.previousState.currentPosition.clone(),
prevPosition: @:privateAccess x.previousState.prevPosition.clone(),
changeTime: @:privateAccess x.previousState.changeTime,
} : null,
} }
}); });
rf.powerupStates = []; rf.powerupStates = [];
@ -145,26 +133,7 @@ class RewindManager {
level.pathedInteriors[i].currentTime = rf.mpStates[i].curState.currentTime; level.pathedInteriors[i].currentTime = rf.mpStates[i].curState.currentTime;
level.pathedInteriors[i].targetTime = rf.mpStates[i].curState.targetTime; level.pathedInteriors[i].targetTime = rf.mpStates[i].curState.targetTime;
level.pathedInteriors[i].velocity.set(rf.mpStates[i].curState.velocity.x, rf.mpStates[i].curState.velocity.y, rf.mpStates[i].curState.velocity.z); level.pathedInteriors[i].velocity.set(rf.mpStates[i].curState.velocity.x, rf.mpStates[i].curState.velocity.y, rf.mpStates[i].curState.velocity.z);
level.pathedInteriors[i].currentPosition.set(rf.mpStates[i].curState.currentPosition.x, rf.mpStates[i].curState.currentPosition.y,
rf.mpStates[i].curState.currentPosition.z);
level.pathedInteriors[i].prevPosition.set(rf.mpStates[i].curState.prevPosition.x, rf.mpStates[i].curState.prevPosition.y,
rf.mpStates[i].curState.prevPosition.z);
level.pathedInteriors[i].changeTime = rf.mpStates[i].curState.changeTime;
@:privateAccess level.pathedInteriors[i].stopTime = rf.mpStates[i].stopTime;
@:privateAccess level.pathedInteriors[i].stopped = rf.mpStates[i].stopped; @:privateAccess level.pathedInteriors[i].stopped = rf.mpStates[i].stopped;
if (rf.mpStates[i].prevState != null) {
@:privateAccess level.pathedInteriors[i].previousState.currentTime = rf.mpStates[i].prevState.currentTime;
@:privateAccess level.pathedInteriors[i].previousState.targetTime = rf.mpStates[i].prevState.targetTime;
@:privateAccess level.pathedInteriors[i].previousState.velocity.set(rf.mpStates[i].prevState.velocity.x, rf.mpStates[i].prevState.velocity.y,
rf.mpStates[i].prevState.velocity.z);
@:privateAccess level.pathedInteriors[i].previousState.currentPosition.set(rf.mpStates[i].prevState.currentPosition.x,
rf.mpStates[i].prevState.currentPosition.y, rf.mpStates[i].prevState.currentPosition.z);
@:privateAccess level.pathedInteriors[i].previousState.prevPosition.set(rf.mpStates[i].prevState.prevPosition.x,
rf.mpStates[i].prevState.prevPosition.y, rf.mpStates[i].prevState.prevPosition.z);
@:privateAccess level.pathedInteriors[i].previousState.changeTime = rf.mpStates[i].prevState.changeTime;
} else {
@:privateAccess level.pathedInteriors[i].previousState = null;
}
} }
var pstates = rf.powerupStates.copy(); var pstates = rf.powerupStates.copy();
var lmstates = rf.landMineStates.copy(); var lmstates = rf.landMineStates.copy();

View file

@ -23,8 +23,6 @@ class MustChangeTrigger extends Trigger {
// Absolutely strange, and not sure if it's even a thing in MBG, but is implement nonetheless. // Absolutely strange, and not sure if it's even a thing in MBG, but is implement nonetheless.
this.interior.currentTime = this.interior.targetTime; this.interior.currentTime = this.interior.targetTime;
this.interior.targetTime = MisParser.parseNumber(this.element.icontinuetottime) / 1000; this.interior.targetTime = MisParser.parseNumber(this.element.icontinuetottime) / 1000;
} else {
this.interior.changeTime = Math.NEGATIVE_INFINITY; // "If instant is 1, the MP will warp to targetTime instantly."
} }
} }
// this.level.replay.recordMarbleEnter(this); // this.level.replay.recordMarbleEnter(this);