Skip to content

Commit

Permalink
[CVRSuperMario64] Added limit of max tris count, skip animations disa…
Browse files Browse the repository at this point in the history
…bled when close to camera mario, nuke mario after dead. Fix level not updating when changing types.
  • Loading branch information
kafeijao committed Mar 11, 2023
1 parent c4fb529 commit 206d55b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 35 deletions.
2 changes: 1 addition & 1 deletion CVRSuperMario64/Components/CVRSM64Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private void Awake() {

// Update context's colliders
Interop.StaticSurfacesLoad(Utils.GetAllStaticSurfaces());
Config.MeIgnoreCollidersHigherThanPolygons.OnEntryValueChanged.Subscribe((oldValue, newValue) => {
Config.MeMaxMeshColliderTotalTris.OnEntryValueChanged.Subscribe((oldValue, newValue) => {
if (newValue == oldValue) return;
Interop.StaticSurfacesLoad(Utils.GetAllStaticSurfaces());
});
Expand Down
9 changes: 9 additions & 0 deletions CVRSuperMario64/Components/CVRSM64LevelModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ public static void ContextTick(List<CVRSM64Mario> marios) {
return;
}

// Reset the old type
if (maxLevelModifier.modifierType != _lastModifierType) {
lock (marios) {
foreach (var mario in marios) {
Interop.SetLevelModifier(mario.MarioId, _lastModifierType, float.MinValue);
}
}
}

_lastModifierType = maxLevelModifier.modifierType;
_lastLevel = highestLevel;
_forceUpdate = false;
Expand Down
20 changes: 12 additions & 8 deletions CVRSuperMario64/Components/CVRSM64Mario.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public class CVRSM64Mario : MonoBehaviour {
[NonSerialized] private bool _wasPickedUp;
[NonSerialized] private bool _initializedByRemote;
[NonSerialized] private bool _isDying;
[NonSerialized] private bool _isNuked;

// Bypasses
[NonSerialized] private bool _wasBypassed;
Expand Down Expand Up @@ -401,7 +402,7 @@ private void OnDisable() {

public void ContextFixedUpdateSynced(List<CVRSM64Mario> marios) {

if (!_enabled || !_initialized) return;
if (!_enabled || !_initialized || _isNuked) return;

// Janky remote sync check
if (!IsMine() && !_initializedByRemote) {
Expand Down Expand Up @@ -470,10 +471,7 @@ public void ContextFixedUpdateSynced(List<CVRSM64Mario> marios) {
// Check for deaths, so we delete the prop
if (!_isDying && IsDead()) {
_isDying = true;
Invoke(nameof(DeleteMario), 15f);
#if DEBUG
MelonLogger.Msg($"One of our Marios died, the prop will be deleted in 15 seconds...");
#endif
Invoke(nameof(SetMarioAsNuked), 15f);
}
}
else {
Expand Down Expand Up @@ -531,7 +529,7 @@ public void ContextFixedUpdateSynced(List<CVRSM64Mario> marios) {
}

public void ContextUpdateSynced() {
if (!_enabled || !_initialized) return;
if (!_enabled || !_initialized || _isNuked) return;

if (!IsMine() && !_initializedByRemote) return;

Expand Down Expand Up @@ -768,9 +766,15 @@ private bool IsDead() {
}
}

private void DeleteMario() {
private void SetMarioAsNuked() {
lock (_lock) {
spawnable.Delete();
_isNuked = true;
var deleteMario = Config.MeDeleteMarioAfterDead.Value;
#if DEBUG
MelonLogger.Msg($"One of our Marios died, it has been 15 seconds and we're going to " +
$"{(deleteMario ? "delete the mario" : "stopping its engine updates")}.");
#endif
if (deleteMario) spawnable.Delete();
}
}

Expand Down
12 changes: 8 additions & 4 deletions CVRSuperMario64/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ public static class Config {
internal static MelonPreferences_Entry<float> MeAudioPitch;
internal static MelonPreferences_Entry<float> MeAudioVolume;
internal static MelonPreferences_Entry<int> MeGameTickMs;
internal static MelonPreferences_Entry<int> MeIgnoreCollidersHigherThanPolygons;
internal static MelonPreferences_Entry<bool> MePlayRandomMusicOnMarioJoin;
internal static MelonPreferences_Entry<float> MeSkipFarMarioDistance;
internal static MelonPreferences_Entry<int> MeMaxMariosAnimatedPerPerson;
internal static MelonPreferences_Entry<int> MeMaxMeshColliderTotalTris;
internal static MelonPreferences_Entry<bool> MeDeleteMarioAfterDead;

public static void InitializeMelonPrefs() {

Expand All @@ -30,9 +31,6 @@ public static void InitializeMelonPrefs() {
MeGameTickMs = _melonCategory.CreateEntry("GameTickMs", 25,
description: "The game ticks frequency in Milliseconds.");

MeIgnoreCollidersHigherThanPolygons = _melonCategory.CreateEntry("IgnoreCollidersHigherThanPolygons", 10000,
description: "Ignore colliders with a poly count higher than.");

MePlayRandomMusicOnMarioJoin = _melonCategory.CreateEntry("PlayRandomMusicOnMarioJoin", true,
description: "Whether to play a random music when a mario joins or not.");
MePlayRandomMusicOnMarioJoin.OnEntryValueChanged.Subscribe((_, newValue) => {
Expand All @@ -44,6 +42,12 @@ public static void InitializeMelonPrefs() {

MeSkipFarMarioDistance = _melonCategory.CreateEntry("SkipFarMarioDistance", 5f,
description: "The max distance that we're going to calculate the mario animations for other people.");

MeMaxMeshColliderTotalTris = _melonCategory.CreateEntry("MaxMeshColliderTotalTris", 75000,
description: "The max total number of collision tris loaded from automatically generated static mesh colliders.");

MeDeleteMarioAfterDead = _melonCategory.CreateEntry("DeleteMarioAfterDead", true,
description: "Whether to automatically delete our marios after 15 seconds of being dead or not.");
}

}
76 changes: 54 additions & 22 deletions CVRSuperMario64/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ private static Vector3 ScalePoint(CapsuleCollider c, Vector3 point) {
internal static Interop.SM64Surface[] GetAllStaticSurfaces() {
var surfaces = new List<Interop.SM64Surface>();

var meshColliders = new List<MeshCollider>();

foreach (var obj in UnityEngine.Object.FindObjectsOfType<Collider>()) {

var cvrSM64ColliderStatic = obj.GetComponent<CVRSM64ColliderStatic>();
Expand All @@ -276,7 +278,49 @@ internal static Interop.SM64Surface[] GetAllStaticSurfaces() {
//MelonLogger.Msg($"[GoodCollider] {obj.name}");
#endif

GetTransformedSurfaces(obj, surfaces, surfaceType, terrainType, hasDedicatedComponent);
if (obj is MeshCollider meshCollider && !hasDedicatedComponent) {
// Let's do some more processing to the mesh colliders without dedicated components
meshColliders.Add(meshCollider);
}
else {
// Everything else, let's just add (probably a bad idea)
GetTransformedSurfaces(obj, surfaces, surfaceType, terrainType, hasDedicatedComponent);
}
}

// Ignore all meshes colliders with a null shared mesh, or non-readable
var nonReadableMeshColliders = meshColliders.Where(meshCollider => meshCollider.sharedMesh == null || !meshCollider.sharedMesh.isReadable).ToList();
#if DEBUG
foreach (var nonReadableMeshCollider in nonReadableMeshColliders) {
MelonLogger.Warning($"[MeshCollider] {nonReadableMeshCollider.name} Mesh is null or not readable, " +
"so we won't be able to use this as a collider for Mario :(");
}
#endif
meshColliders.RemoveAll(meshCollider => meshCollider.sharedMesh == null || !meshCollider.sharedMesh.isReadable);

// Sort the meshColliders list by the length of their triangles array in ascending order
meshColliders.Sort((a, b) => a.sharedMesh.triangles.Length.CompareTo(b.sharedMesh.triangles.Length));

// Add the mesh colliders until we reach the max mesh collider polygon limit
var totalMeshColliderTris = 0;
foreach (var meshCollider in meshColliders) {
var meshTrisCount = meshCollider.sharedMesh.triangles.Length / 3;
var newTotalMeshColliderTris = totalMeshColliderTris + meshTrisCount;
if (newTotalMeshColliderTris > Config.MeMaxMeshColliderTotalTris.Value) {
#if DEBUG
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} will be ignored because it exceeds the " +
$"maximum mesh collider total tris count. Tris: {meshTrisCount}, Total Tris: " +
$"{newTotalMeshColliderTris}/{Config.MeMaxMeshColliderTotalTris.Value}");
#endif
}
else {
GetTransformedSurfaces(meshCollider, surfaces, SM64SurfaceType.Default, SM64TerrainType.Grass, false);
#if DEBUG
MelonLogger.Msg($"[MeshCollider] {meshCollider.name} will be added. Tris: {meshTrisCount}, Total " +
$"Tris: {newTotalMeshColliderTris}/{Config.MeMaxMeshColliderTotalTris.Value}");
#endif
}
totalMeshColliderTris = newTotalMeshColliderTris;
}

return surfaces.ToArray();
Expand All @@ -293,24 +337,16 @@ internal static Interop.SM64Surface[] GetAllStaticSurfaces() {
break;
case MeshCollider meshCollider:

#if DEBUG
MelonLogger.Msg($"[MeshCollider] {meshCollider.name} Readable: {meshCollider.sharedMesh.isReadable}, SubMeshCount: {meshCollider.sharedMesh.subMeshCount}, TrisCount: {meshCollider.sharedMesh.triangles.Length}");
#endif

if (!meshCollider.sharedMesh.isReadable) {
MelonLogger.Warning(
$"[MeshCollider] {meshCollider.name} Mesh is not readable, so we won't be able to use this as a collider for Mario :(");
return surfaces;
}

if (!bypassPolygonLimit && meshCollider.sharedMesh.triangles.Length > Config.MeIgnoreCollidersHigherThanPolygons.Value) {
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} has {meshCollider.sharedMesh.triangles.Length} triangles, " +
$"which is more than the configured limit ({Config.MeIgnoreCollidersHigherThanPolygons.Value}), so this mesh will be ignored!");
if (meshCollider.sharedMesh == null || !meshCollider.sharedMesh.isReadable) {
#if DEBUG
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} Mesh is null or not readable, so we won't be able to use this as a collider for Mario :(");
#endif
return surfaces;
}

// Todo: Handle when meshes are too big (colliders stop working).
// Planes scaled to 60 60 60 will break. While 50 50 50 will work.
// Edit: Seems to be related how big each polygon is (cubes break sooner than planes(more polys))

TransformAndGetSurfaces(surfaces, meshCollider.sharedMesh, surfaceType, terrainType, x => meshCollider.transform.TransformPoint(x));
break;
Expand All @@ -337,14 +373,10 @@ internal static Interop.SM64Surface[] GetAllStaticSurfaces() {
break;
case MeshCollider meshCollider:

if (!meshCollider.sharedMesh.isReadable) {
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} Mesh is not readable, so we won't be able to use this as a collider for Mario :(");
return surfaces;
}

if (!bypassPolygonLimit && meshCollider.sharedMesh.triangles.Length > Config.MeIgnoreCollidersHigherThanPolygons.Value) {
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} has {meshCollider.sharedMesh.triangles.Length} triangles, " +
$"which is more than the configured limit ({Config.MeIgnoreCollidersHigherThanPolygons.Value}), so this mesh will be ignored!");
if (meshCollider.sharedMesh == null || !meshCollider.sharedMesh.isReadable) {
#if DEBUG
MelonLogger.Warning($"[MeshCollider] {meshCollider.name} Mesh is null or not readable, so we won't be able to use this as a collider for Mario :(");
#endif
return surfaces;
}

Expand Down

0 comments on commit 206d55b

Please sign in to comment.