@@ -86,6 +86,21 @@ class EurekaShipControl : ShipForcesInducer, ServerTickListener {
8686 if (helms < 1 ) {
8787 // Enable fluid drag if all the helms have been destroyed
8888 physShip.doFluidDrag = true
89+
90+ if (EurekaConfig .SERVER .AllowFloatersAndBalloonsOnNonEurekaShips ) {
91+ val mass = physShip.mass
92+ val velY = physShip.velocity.y()
93+
94+ var balloonForce = getBalloonForce()
95+ // balloon force 100% at y 100, 0% at y 320
96+ // the "velY * 10" reduces bobbing by sampling the height position in the future
97+ balloonForce * = 1 - Math .clamp(0.0 , 1.0 , (physShip.transform.positionInWorld.y() + velY * 10 - EurekaConfig .SERVER .PassiveBallonMinHeight ) / (EurekaConfig .SERVER .PassiveBallonMaxHeight - EurekaConfig .SERVER .PassiveBallonMinHeight ))
98+ balloonForce = min(balloonForce, max(getIdealUpwardForce(EurekaConfig .SERVER .balloonElevationMaxSpeed, velY, mass), 0.0 ))
99+ physShip.applyInvariantForce(Vector3d (0.0 , balloonForce, 0.0 ))
100+
101+ physShip.buoyantFactor = getFloaterFactor(mass)
102+ }
103+
89104 return
90105 }
91106 // Disable fluid drag when helms are present, because it makes ships hard to drive
@@ -96,21 +111,8 @@ class EurekaShipControl : ShipForcesInducer, ServerTickListener {
96111 val moiTensor = physShip.momentOfInertia
97112 val omega: Vector3dc = physShip.omega
98113 val vel: Vector3dc = physShip.velocity
99- var balloonForceProvided = balloons * forcePerBalloon
100114
101- if (EurekaConfig .SERVER .maxBalloonsPerEngine > 0 ) {
102- balloonForceProvided * = min(
103- 1.0 ,
104- ( extraForceLinear * EurekaConfig .SERVER .maxBalloonsPerEngine ) / ( EurekaConfig .SERVER .enginePowerLinear * balloons )
105- )
106- }
107-
108- val buoyantFactorPerFloater = min(
109- EurekaConfig .SERVER .floaterBuoyantFactorPerKg / 15.0 / mass,
110- EurekaConfig .SERVER .maxFloaterBuoyantFactor
111- )
112-
113- physShip.buoyantFactor = 1.0 + floaters * buoyantFactorPerFloater
115+ physShip.buoyantFactor = getFloaterFactor(mass)
114116
115117 // region Aligning
116118
@@ -189,12 +191,8 @@ class EurekaShipControl : ShipForcesInducer, ServerTickListener {
189191 idealUpwardVel = getPlayerUpwardVel(control, mass)
190192 }
191193
192- // region Elevation
193- val idealUpwardForce = (idealUpwardVel.y() - vel.y() - (GRAVITY / EurekaConfig .SERVER .elevationSnappiness)) *
194- mass * EurekaConfig .SERVER .elevationSnappiness
195-
196194 physShip.applyInvariantForce(Vector3d (0.0 ,
197- min(balloonForceProvided , max(idealUpwardForce , 0.0 )) +
195+ min(getBalloonForce() , max(getIdealUpwardForce(idealUpwardVel.y(), vel.y(), mass) , 0.0 )) +
198196 // Add drag to the y-component
199197 vel.y() * - mass,
200198 0.0 )
@@ -204,6 +202,30 @@ class EurekaShipControl : ShipForcesInducer, ServerTickListener {
204202 physShip.isStatic = anchored
205203 }
206204
205+ private fun getBalloonForce (): Double {
206+ // Disable if maxBalloonsPerEngine <= 0
207+ if (EurekaConfig .SERVER .maxBalloonsPerEngine > 0 ) {
208+ // remove power from unpowered balloons
209+ return balloons * forcePerBalloon * min(
210+ 1.0 ,
211+ // (currentTotalEnginePower * maxBalloonsPerEngine) / (enginePowerAtMaxHeat * balloonsCount)
212+ ( extraForceLinear * EurekaConfig .SERVER .maxBalloonsPerEngine ) / ( EurekaConfig .SERVER .enginePowerLinear * balloons )
213+ )
214+ }
215+ return balloons * forcePerBalloon
216+ }
217+
218+ private fun getFloaterFactor (mass : Double ): Double {
219+ return 1.0 + floaters * min(
220+ EurekaConfig .SERVER .floaterBuoyantLift / mass,
221+ EurekaConfig .SERVER .maxFloaterBuoyantFactor
222+ )
223+ }
224+
225+ private fun getIdealUpwardForce (idealUpwardVelY : Double , velY : Double , mass : Double ): Double {
226+ return (idealUpwardVelY - velY - (GRAVITY / EurekaConfig .SERVER .elevationSnappiness)) * mass * EurekaConfig .SERVER .elevationSnappiness
227+ }
228+
207229 private fun getControlData (player : SeatedControllingPlayer ): ControlData {
208230
209231 val currentControlData = ControlData .create(player)
@@ -300,28 +322,26 @@ class EurekaShipControl : ShipForcesInducer, ServerTickListener {
300322 )
301323
302324 oldSpeed = oldSpeed * (1 - s) + control.forwardImpulse.toDouble() * s // from -1 to 1.
303- var speed = oldSpeed * EurekaConfig .SERVER .linearCasualSpeed / 3 // 1 unit -> 3m/s
325+ var speed = oldSpeed * EurekaConfig .SERVER .linearBaseSpeed
304326
305327 if (extraForceLinear != 0.0 ) {
306328 // engine boost
307- val boost = max((extraForceLinear - EurekaConfig .SERVER .enginePowerLinear * EurekaConfig .SERVER .engineBoostOffset) * EurekaConfig .SERVER .engineBoost, 0.0 )
308- extraForceLinear + = boost + boost * boost * EurekaConfig .SERVER .engineBoostExponentialPower
309- extraForceLinear / = scaledMass
329+ var boost = max((extraForceLinear - EurekaConfig .SERVER .enginePowerLinear * EurekaConfig .SERVER .engineBoostOffset) * EurekaConfig .SERVER .engineBoost, 0.0 )
330+ boost = extraForceLinear + boost + boost * boost * EurekaConfig .SERVER .engineBoostExponentialPower
331+ boost / = scaledMass
310332
311333 speed + = if (speed < 0 ) {
312- smoothingATanMax(EurekaConfig .SERVER .maxReverseSpeedFromEngines, extraForceLinear * oldSpeed)
334+ smoothingATanMax(EurekaConfig .SERVER .maxReverseSpeedFromEngines, boost * oldSpeed)
313335 } else {
314- smoothingATanMax(EurekaConfig .SERVER .maxSpeedFromEngines, extraForceLinear * oldSpeed)
336+ smoothingATanMax(EurekaConfig .SERVER .maxSpeedFromEngines, boost * oldSpeed)
315337 }
316338 }
317339
318- forwardVector.mul(speed)
319-
320340 val playerUpDirection = physShip.transform.shipToWorldRotation.transform(Vector3d (0.0 , 1.0 , 0.0 ))
321341 val velOrthogonalToPlayerUp = vel.sub(playerUpDirection.mul(playerUpDirection.dot(vel)), Vector3d ())
322342
323343 // This is the speed that the ship is always allowed to go out, without engines
324- val baseForwardVel = forwardVector.mul(EurekaConfig . SERVER .baseSpeed )
344+ val baseForwardVel = forwardVector.mul(speed )
325345 val forwardForce = baseForwardVel.sub(velOrthogonalToPlayerUp).mul(scaledMass)
326346
327347 return forwardForce
0 commit comments