C#:
using System;
using UnityEngine;
using VLB;
using System.Collections.Generic;
namespace Oxide.Plugins
{
[Info("IQCargoPhysics", "Mercury", "1.0.0")]
public class IQCargoPhysics : RustPlugin
{
private const Single rollFactor = 1.7f;
private void OnEntitySpawned(CargoShip cargo)
{
CargoPhysics physics = cargo.GetOrAddComponent<CargoPhysics>();
cargoPhysicsList.TryAdd(cargo, physics);
}
private const Single shakeIntensity = 1.0f;
private void OnEntityKill(CargoShip cargo)
{
if (!cargoPhysicsList.ContainsKey(cargo)) return;
if (cargoPhysicsList[cargo])
UnityEngine.Object.DestroyImmediate(cargoPhysicsList[cargo]);
cargoPhysicsList.Remove(cargo);
}
private const Single maxPitchAngle = 35.0f;
private static readonly BPoint bPointsInfo = new();
private void OnServerInitialized()
{
foreach (BaseNetworkable entity in BaseNetworkable.serverEntities.entityList.Get().Values)
{
if (entity is not CargoShip) continue;
CargoShip cargo = entity as CargoShip;
if (!cargo) continue;
OnEntitySpawned(cargo);
}
}
private const Single maxRollAngle = 30.0f;
private const Single pitchFactor = 5.5f;
private Dictionary<CargoShip, CargoPhysics> cargoPhysicsList = new();
public class CargoPhysics : FacepunchBehaviour
{
private CargoShip cargo;
private Single boostOceanLevel = 1f;
private void Awake()
{
cargo = gameObject.GetComponent<CargoShip>();
InvokeRepeating(WavesBuoyancy, 0.1f, 0.1f);
InvokeRepeating(UpdateOceanLevel, 0f, 60f);
}
private void UpdateOceanLevel()
{
Single oceanScale = (Boolean)(UnityEngine.Object)SingletonComponent<Climate>.Instance ? SingletonComponent<Climate>.Instance.WeatherState.OceanScale : 4f;
boostOceanLevel = oceanScale <= 6f ? 1.3f : 1f;
}
public void WavesBuoyancy()
{
Vector3 posNose = cargo.transform.TransformPoint(bPointsInfo.nose);
Vector3 posBackLeft = cargo.transform.TransformPoint(bPointsInfo.backLeft);
Vector3 posBackRight = cargo.transform.TransformPoint(bPointsInfo.backRight);
Vector3 posCenterLeft = cargo.transform.TransformPoint(bPointsInfo.centerLeft);
Vector3 posCenterRight = cargo.transform.TransformPoint(bPointsInfo.centerRight);
Single waterHeightNose = WaterLevel.GetWaterSurface(posNose, true, false) * boostOceanLevel;
Single waterHeightBackLeft = WaterLevel.GetWaterSurface(posBackLeft, true, false) * boostOceanLevel;
Single waterHeightBackRight = WaterLevel.GetWaterSurface(posBackRight, true, false) * boostOceanLevel;
Single waterHeightCenterLeft = WaterLevel.GetWaterSurface(posCenterLeft, true, false) * boostOceanLevel;
Single waterHeightCenterRight = WaterLevel.GetWaterSurface(posCenterRight, true, false) * boostOceanLevel;
Single avgWaterHeight = (waterHeightNose + waterHeightBackLeft + waterHeightBackRight + waterHeightCenterLeft + waterHeightCenterRight) / 3f;
Single velocity = 0.0f;
Vector3 targetPosition = transform.position;
targetPosition.y = Mathf.SmoothDamp(transform.position.y, avgWaterHeight, ref velocity, smoothTime);
transform.position = targetPosition;
Vector3 forwardVector = (posNose - (posBackLeft + posBackRight) / 2f);
Vector3 sideVector = (posCenterRight - posCenterLeft);
Single pitchAngle = Mathf.Atan2((waterHeightNose - (waterHeightBackLeft + waterHeightBackRight) / 2f), forwardVector.magnitude) * Mathf.Rad2Deg * pitchFactor;
Single rollAngle = Mathf.Atan2((waterHeightCenterRight - waterHeightCenterLeft), sideVector.magnitude) * Mathf.Rad2Deg * rollFactor;
pitchAngle = Mathf.Clamp(pitchAngle, -maxPitchAngle, maxPitchAngle);
rollAngle = Mathf.Clamp(rollAngle, -maxRollAngle, maxRollAngle);
Single shakePitch = (Mathf.PerlinNoise(Time.time * 0.4f, 0.0f) - 0.5f) * shakeIntensity;
Single shakeRoll = (Mathf.PerlinNoise(0.0f, Time.time * 0.4f) - 0.5f) * shakeIntensity;
shakePitch += Mathf.Sin(Time.time * 2.0f) * cosAngle;
shakeRoll += Mathf.Cos(Time.time * 1.8f) * cosAngle;
pitchAngle += shakePitch;
rollAngle += shakeRoll;
Quaternion targetRotation = Quaternion.Euler(pitchAngle, transform.eulerAngles.y, rollAngle);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSmoothTime);
}
}
private const Single smoothTime = 0.15f;
private void Unload()
{
foreach (KeyValuePair<CargoShip, CargoPhysics> valuePair in cargoPhysicsList)
{
if (valuePair.Value)
UnityEngine.Object.DestroyImmediate(valuePair.Value);
}
cargoPhysicsList.Clear();
cargoPhysicsList = null;
}
private const Single rotationSmoothTime = 0.15f;
private class BPoint
{
public readonly Vector3 backLeft = new Vector3(-9.74f, 0f, -55.14f);
public readonly Vector3 backRight = new Vector3(9.74f, 0f, -55.14f);
public readonly Vector3 centerLeft = new Vector3(-10.52f, 0, 18.90f);
public readonly Vector3 nose = new Vector3(-0.05f, 0f, 81.21f);
public readonly Vector3 centerRight = new Vector3(10.52f, 0, 18.90f);
}
private const Single cosAngle = 0.4f;
}
}