diff --git a/src/CameraController.hx b/src/CameraController.hx index efa25822..8ff3031c 100644 --- a/src/CameraController.hx +++ b/src/CameraController.hx @@ -396,7 +396,7 @@ class CameraController extends Object { camera.target = marblePosition.add(cameraVerticalTranslation); var closeness = 0.1; - var rayCastOrigin = marblePosition.add(level.currentUp.multiply(marble._radius)).add(cameraVerticalTranslation); + var rayCastOrigin = marblePosition.add(level.marble.currentUp.multiply(marble._radius)).add(cameraVerticalTranslation); for (pi in level.pathedInteriors) { pi.pushTickState(); diff --git a/src/Marble.hx b/src/Marble.hx index ef6cb056..62125a3f 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -75,6 +75,7 @@ class Move { public var d:Vector; public var jump:Bool; public var powerup:Bool; + public var blast:Bool; public function new() {} } @@ -249,6 +250,7 @@ class Marble extends GameObject { public var heldPowerup:PowerUp; public var lastContactNormal:Vector; public var lastContactPosition:Vector; + public var currentUp = new Vector(0, 0, 1); var helicopter:HelicopterImage; var blastWave:BlastWave; @@ -256,6 +258,8 @@ class Marble extends GameObject { var megaMarbleEnableTime:Float = -1e8; var blastUseTime:Float = -1e8; + public var blastAmount:Float = 0; + var teleportEnableTime:Null = null; var teleportDisableTime:Null = null; var bounceEmitDelay:Float = 0; @@ -537,7 +541,7 @@ class Marble extends GameObject { if (this.controllable && !this.isNetUpdate) { motiondir.transform(Matrix.R(0, 0, camera.CameraYaw)); motiondir.transform(level.newOrientationQuat.toMatrix()); - var updir = this.level.currentUp; + var updir = this.currentUp; var sidedir = motiondir.cross(updir); sidedir.normalize(); @@ -546,7 +550,7 @@ class Marble extends GameObject { } else { if (moveMotionDir != null) motiondir = moveMotionDir; - var updir = this.level.currentUp; + var updir = this.currentUp; var sidedir = motiondir.cross(updir); return [sidedir, motiondir, updir]; } @@ -555,7 +559,7 @@ class Marble extends GameObject { function getExternalForces(currentTime:Float, m:Move, dt:Float) { if (this.mode == Finish) return this.velocity.multiply(-16); - var gWorkGravityDir = this.level != null ? this.level.currentUp.multiply(-1) : new Vector(0, 0, -1); + var gWorkGravityDir = this.currentUp.multiply(-1); var A = new Vector(); A = gWorkGravityDir.multiply(this._gravity); if (currentTime - this.helicopterEnableTime < 5) { @@ -617,7 +621,7 @@ class Marble extends GameObject { } function computeMoveForces(m:Move, aControl:Vector, desiredOmega:Vector) { - var currentGravityDir = this.level != null ? this.level.currentUp.multiply(-1) : new Vector(0, 0, -1); + var currentGravityDir = this.currentUp.multiply(-1); var R = currentGravityDir.multiply(-this._radius); var rollVelocity = this.omega.cross(R); var axes = this.getMarbleAxis(); @@ -795,7 +799,7 @@ class Marble extends GameObject { function applyContactForces(dt:Float, m:Move, isCentered:Bool, aControl:Vector, desiredOmega:Vector, A:Vector) { var a = new Vector(); this._slipAmount = 0; - var gWorkGravityDir = this.level != null ? this.level.currentUp.multiply(-1) : new Vector(0, 0, -1); + var gWorkGravityDir = this.currentUp.multiply(-1); var bestSurface = -1; var bestNormalForce = 0.0; for (i in 0...contacts.length) { @@ -1467,6 +1471,14 @@ class Marble extends GameObject { } } + // Blast + if (m.blast) { + this.useBlast(); + if (level.isRecording) { + level.replay.recordMarbleStateFlags(false, false, false, true); + } + } + do { if (timeRemaining <= 0) break; @@ -1687,6 +1699,7 @@ class Marble extends GameObject { } public function updateClient(timeState:TimeState, pathedInteriors:Array) { + this.level.updateBlast(this, timeState); if (oldPos != null && newPos != null) { var deltaT = physicsAccumulator / 0.032; var renderPos = Util.lerpThreeVectors(this.oldPos, this.newPos, deltaT); @@ -1732,7 +1745,7 @@ class Marble extends GameObject { this._radius = 0.675; this.collider.radius = 0.675; this._marbleScale *= 2.25; - var boost = this.level.currentUp.multiply(5); + var boost = this.currentUp.multiply(5); this.velocity = this.velocity.add(boost); } else if (timeState.currentAttemptTime - this.megaMarbleEnableTime > 10) { if (this._radius != this._prevRadius) { @@ -1893,7 +1906,7 @@ class Marble extends GameObject { this._radius = 0.675; this.collider.radius = 0.675; this._marbleScale *= 2.25; - var boost = this.level.currentUp.multiply(5); + var boost = this.currentUp.multiply(5); this.velocity = this.velocity.add(boost); } else if (timeState.currentAttemptTime - this.megaMarbleEnableTime > 10) { if (this._radius != this._prevRadius) { @@ -2032,14 +2045,15 @@ class Marble extends GameObject { } public function useBlast() { - if (this.level.blastAmount < 0.25 || this.level.game != "ultra") + if (this.blastAmount < 0.25) return false; - var impulse = this.level.currentUp.multiply(this.level.blastAmount * 8); + var impulse = this.currentUp.multiply(this.blastAmount * 8); this.applyImpulse(impulse); - AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources)); + if (this.controllable) + AudioManager.playSound(ResourceLoader.getResource('data/sound/use_blast.wav', ResourceLoader.getAudio, this.soundResources)); this.blastWave.doSequenceOnceBeginTime = this.level.timeState.timeSinceLoad; this.blastUseTime = this.level.timeState.currentAttemptTime; - this.level.blastAmount = 0; + this.blastAmount = 0; return true; } diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 08620b7c..427bbec9 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -143,8 +143,6 @@ class MarbleWorld extends Scheduler { public var game:String; public var marble:Marble; - public var worldOrientation:Quat; - public var currentUp = new Vector(0, 0, 1); public var outOfBounds:Bool = false; public var outOfBoundsTime:TimeState; public var finishTime:TimeState; @@ -152,7 +150,6 @@ class MarbleWorld extends Scheduler { public var finishYaw:Float; public var totalGems:Int = 0; public var gemCount:Int = 0; - public var blastAmount:Float = 0; public var skipStartBugPauseTime:Float = 0.0; var renderBlastAmount:Float = 0; @@ -509,7 +506,7 @@ class MarbleWorld extends Scheduler { this.timeState.gameplayClock = this.gameMode.getStartTime(); this.bonusTime = 0; this.outOfBounds = false; - this.blastAmount = 0; + this.marble.blastAmount = 0; this.renderBlastAmount = 0; this.outOfBoundsTime = null; this.finishTime = null; @@ -1093,7 +1090,7 @@ class MarbleWorld extends Scheduler { } this.updateGameState(); - this.updateBlast(timeState); + this.updateBlast(this.marble, timeState); ProfilerUI.measure("updateDTS"); for (obj in dtsObjects) { obj.update(timeState); @@ -1223,18 +1220,6 @@ class MarbleWorld extends Scheduler { this.tickSchedule(timeState.currentAttemptTime); - if (Key.isDown(Settings.controlsSettings.blast) - || (MarbleGame.instance.touchInput.blastbutton.pressed) - || Gamepad.isDown(Settings.gamepadSettings.blast) - && !this.isWatching - && this.game == "ultra") { - if (this.marble.useBlast()) { - if (this.isRecording) { - this.replay.recordMarbleStateFlags(false, false, false, true); - } - } - } - if (this.isWatching && this.replay.currentPlaybackFrame.marbleStateFlags.has(UsedBlast)) this.marble.useBlast(); @@ -1250,7 +1235,8 @@ class MarbleWorld extends Scheduler { radar.update(dt); this.updateGameState(); - this.updateBlast(timeState); + if (!this.isMultiplayer) + this.updateBlast(this.marble, timeState); ProfilerUI.measure("updateDTS"); for (obj in dtsObjects) { obj.update(timeState); @@ -1450,16 +1436,17 @@ class MarbleWorld extends Scheduler { this.replay.recordTimeState(timeState.currentAttemptTime, timeState.gameplayClock, this.bonusTime); } - function updateBlast(timestate:TimeState) { - if (this.game == "ultra") { - if (this.blastAmount < 1) { - this.blastAmount = Util.clamp(this.blastAmount + (timeState.dt / 30), 0, 1); - this.renderBlastAmount = this.blastAmount; - } else { - this.renderBlastAmount = Math.min(this.blastAmount, timestate.dt * 0.75 + this.renderBlastAmount); - } - this.playGui.setBlastValue(this.renderBlastAmount); + public function updateBlast(marble:Marble, timestate:TimeState) { + if (marble.blastAmount < 1) { + marble.blastAmount = Util.clamp(marble.blastAmount + (timeState.dt / 30), 0, 1); + if (marble == this.marble) + this.renderBlastAmount = marble.blastAmount; + } else { + if (marble == this.marble) + this.renderBlastAmount = Math.min(marble.blastAmount, timestate.dt * 0.75 + this.renderBlastAmount); } + if (marble == this.marble) + this.playGui.setBlastValue(this.renderBlastAmount); } function updateTexts() { @@ -1828,7 +1815,7 @@ class MarbleWorld extends Scheduler { } public function setUp(vec:Vector, timeState:TimeState, instant:Bool = false) { - this.currentUp = vec; + this.marble.currentUp = vec; var currentQuat = this.getOrientationQuat(timeState.currentAttemptTime); var oldUp = new Vector(0, 0, 1); oldUp.transform(currentQuat.toMatrix()); @@ -1926,7 +1913,7 @@ class MarbleWorld extends Scheduler { this.currentCheckpoint = shape; this.currentCheckpointTrigger = trigger; this.checkpointCollectedGems.clear(); - this.cheeckpointBlast = this.blastAmount; + this.cheeckpointBlast = this.marble.blastAmount; // Remember all gems that were collected up to this point for (gem in this.gems) { if (gem.pickedUp) @@ -1962,7 +1949,7 @@ class MarbleWorld extends Scheduler { this.marble.camera.oob = false; @:privateAccess this.marble.helicopterEnableTime = -1e8; @:privateAccess this.marble.megaMarbleEnableTime = -1e8; - this.blastAmount = this.cheeckpointBlast; + this.marble.blastAmount = this.cheeckpointBlast; if (this.isRecording) { this.replay.recordCameraState(this.marble.camera.CameraYaw, this.marble.camera.CameraPitch); this.replay.recordMarbleInput(0, 0); diff --git a/src/net/MoveManager.hx b/src/net/MoveManager.hx index 2abb3051..7e475c51 100644 --- a/src/net/MoveManager.hx +++ b/src/net/MoveManager.hx @@ -73,6 +73,12 @@ class MoveManager { || Gamepad.isDown(Settings.gamepadSettings.powerup)) { move.powerup = true; } + + if (Key.isDown(Settings.controlsSettings.blast) + || (MarbleGame.instance.touchInput.blastbutton.pressed) + || Gamepad.isDown(Settings.gamepadSettings.blast)) + move.blast = true; + if (MarbleGame.instance.touchInput.movementInput.pressed) { move.d.y = -MarbleGame.instance.touchInput.movementInput.value.x; move.d.x = MarbleGame.instance.touchInput.movementInput.value.y; @@ -106,6 +112,8 @@ class MoveManager { flags |= 1; if (m.move.powerup) flags |= 2; + if (m.move.blast) + flags |= 4; b.writeByte(flags); b.writeFloat(m.motionDir.x); b.writeFloat(m.motionDir.y); @@ -122,6 +130,7 @@ class MoveManager { var flags = b.readByte(); move.jump = (flags & 1) != 0; move.powerup = (flags & 2) != 0; + move.blast = (flags & 4) != 0; var motionDir = new Vector(); motionDir.x = b.readFloat(); motionDir.y = b.readFloat(); diff --git a/src/rewind/RewindManager.hx b/src/rewind/RewindManager.hx index 1c289fc2..50559653 100644 --- a/src/rewind/RewindManager.hx +++ b/src/rewind/RewindManager.hx @@ -58,7 +58,7 @@ class RewindManager { rf.gemCount = level.gemCount; rf.gemStates = level.gems.map(x -> x.pickedUp); rf.activePowerupStates = [@:privateAccess level.marble.helicopterEnableTime, @:privateAccess level.marble.megaMarbleEnableTime]; - rf.currentUp = level.currentUp.clone(); + rf.currentUp = level.marble.currentUp.clone(); rf.lastContactNormal = level.marble.lastContactNormal.clone(); rf.mpStates = level.pathedInteriors.map(x -> { var mpstate = new RewindMPState(); @@ -91,7 +91,7 @@ class RewindManager { rf.powerupStates.push(ab.lastContactTime); } } - rf.blastAmt = level.blastAmount; + rf.blastAmt = level.marble.blastAmount; rf.oobState = { oob: level.outOfBounds, timeState: level.outOfBoundsTime != null ? level.outOfBoundsTime.clone() : null @@ -147,7 +147,9 @@ class RewindManager { @:privateAccess level.marble.helicopterEnableTime = rf.activePowerupStates[0]; @:privateAccess level.marble.megaMarbleEnableTime = rf.activePowerupStates[1]; - if (level.currentUp.x != rf.currentUp.x || level.currentUp.y != rf.currentUp.y || level.currentUp.z != rf.currentUp.z) { + if (level.marble.currentUp.x != rf.currentUp.x + || level.marble.currentUp.y != rf.currentUp.y + || level.marble.currentUp.z != rf.currentUp.z) { level.setUp(rf.currentUp, level.timeState); // Hacky things @:privateAccess level.orientationChangeTime = level.timeState.currentAttemptTime - 300; @@ -162,7 +164,7 @@ class RewindManager { @:privateAccess level.orientationChangeTime = -1e8; } - level.currentUp.load(rf.currentUp); + level.marble.currentUp.load(rf.currentUp); level.marble.lastContactNormal.load(rf.lastContactNormal); for (i in 0...rf.mpStates.length) { level.pathedInteriors[i].currentTime = rf.mpStates[i].currentTime; @@ -215,7 +217,7 @@ class RewindManager { @:privateAccess level.playGui.setCenterText(''); level.marble.camera.oob = rf.oobState.oob; level.outOfBoundsTime = rf.oobState.timeState != null ? rf.oobState.timeState.clone() : null; - level.blastAmount = rf.blastAmt; + level.marble.blastAmount = rf.blastAmt; @:privateAccess level.checkpointCollectedGems = rf.checkpointState.checkpointCollectedGems; @:privateAccess level.cheeckpointBlast = rf.checkpointState.checkpointBlast; @:privateAccess level.checkpointHeldPowerup = rf.checkpointState.checkpointHeldPowerup; diff --git a/src/shaders/DirLight.hx b/src/shaders/DirLight.hx index e549eb92..6ed5ecf5 100644 --- a/src/shaders/DirLight.hx +++ b/src/shaders/DirLight.hx @@ -34,9 +34,9 @@ class DirLight extends Light { } override function getShadowDirection():h3d.Vector { - if (MarbleGame.instance.world == null) + if (MarbleGame.instance.world == null || MarbleGame.instance.world.marble == null) return new h3d.Vector(0, 0, -1); - return MarbleGame.instance.world.currentUp.multiply(-1); + return MarbleGame.instance.world.marble.currentUp.multiply(-1); } override function emit(ctx) { diff --git a/src/shapes/AntiGravity.hx b/src/shapes/AntiGravity.hx index 8beb0f13..90b135a9 100644 --- a/src/shapes/AntiGravity.hx +++ b/src/shapes/AntiGravity.hx @@ -30,20 +30,18 @@ class AntiGravity extends PowerUp { public function pickUp(marble:Marble):Bool { var direction = new Vector(0, 0, -1); direction.transform(this.getRotationQuat().toMatrix()); - return !direction.equals(this.level.currentUp); + return !direction.equals(this.level.marble.currentUp); } public function use(marble:Marble, timeState:TimeState) { if (!this.level.rewinding) { var direction = new Vector(0, 0, -1); direction.transform(this.getRotationQuat().toMatrix()); - this.level.setUp(direction, timeState); + if (marble == level.marble) + this.level.setUp(direction, timeState); + else + marble.currentUp.load(direction); } - // marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity - // if (!this.level.rewinding) - // AudioManager.play(this.sounds[1]); - // this.level.particles.createEmitter(superJumpParticleOptions, null, () => Util.vecOimoToThree(marble.body.getPosition())); - // this.level.deselectPowerUp(); } public override function init(level:MarbleWorld, onFinish:Void->Void) { diff --git a/src/shapes/Blast.hx b/src/shapes/Blast.hx index 7c05a5ab..864d3941 100644 --- a/src/shapes/Blast.hx +++ b/src/shapes/Blast.hx @@ -33,7 +33,7 @@ class Blast extends PowerUp { } public function use(marble:Marble, timeState:TimeState) { - this.level.blastAmount = 1.2; + marble.blastAmount = 1.2; } override function getPreloadMaterials(dts:dts.DtsFile) { diff --git a/src/shapes/SuperJump.hx b/src/shapes/SuperJump.hx index e4f27726..fa7a1b13 100644 --- a/src/shapes/SuperJump.hx +++ b/src/shapes/SuperJump.hx @@ -69,7 +69,7 @@ class SuperJump extends PowerUp { public function use(marble:Marble, timeState:TimeState) { var masslessFactor = marble.getMass() * 0.7 + 1 - 0.7; - var boost = this.level.currentUp.multiply(20 * masslessFactor / marble.getMass()); + var boost = marble.currentUp.multiply(20 * masslessFactor / marble.getMass()); marble.velocity = marble.velocity.add(boost); this.level.particleManager.createEmitter(superJumpParticleOptions, this.sjEmitterParticleData, null, () -> marble.getAbsPos().getPosition()); // marble.body.addLinearVelocity(this.level.currentUp.scale(20)); // Simply add to vertical velocity diff --git a/src/shapes/SuperSpeed.hx b/src/shapes/SuperSpeed.hx index 0a4b3bb2..51f7337a 100644 --- a/src/shapes/SuperSpeed.hx +++ b/src/shapes/SuperSpeed.hx @@ -78,7 +78,7 @@ class SuperSpeed extends PowerUp { var quat2 = new Quat(); // Determine the necessary rotation to rotate the up vector to the contact normal. - quat2.initMoveTo(this.level.currentUp, marble.lastContactNormal); + quat2.initMoveTo(marble.currentUp, marble.lastContactNormal); movementVector.transform(quat2.toMatrix()); var masslessFactor = marble.getMass() * 0.7 + 1 - 0.7; marble.velocity = marble.velocity.add(movementVector.multiply(-25 * masslessFactor / marble.getMass()));