mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2026-01-01 14:17:31 +00:00
moved folders
This commit is contained in:
parent
3b103b685e
commit
44dd36271e
12 changed files with 65 additions and 16 deletions
135
PlapPlapForAll/Main.cs
Normal file
135
PlapPlapForAll/Main.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
using ABI_RC.Core;
|
||||
using ABI_RC.Core.Networking.API.Responses;
|
||||
using ABI_RC.Core.Networking.IO.Social;
|
||||
using MelonLoader;
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.GameEventSystem;
|
||||
using ABI.CCK.Components;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace NAK.PlapPlapForAll;
|
||||
|
||||
public class PlapPlapForAllMod : MelonMod
|
||||
{
|
||||
public static MelonLogger.Instance Logger;
|
||||
|
||||
public override void OnInitializeMelon()
|
||||
{
|
||||
Logger = LoggerInstance;
|
||||
CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(OnPlayerSetupStart);
|
||||
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(OnLocalAvatarLoaded);
|
||||
CVRGameEventSystem.Avatar.OnRemoteAvatarLoad.AddListener(OnRemoteAvatarLoaded);
|
||||
LoadAssetBundle();
|
||||
}
|
||||
|
||||
private static void OnPlayerSetupStart()
|
||||
{
|
||||
PlapPlapPrefab.SetActive(false);
|
||||
|
||||
// Remove ParentConstraint so we can reparent later
|
||||
ParentConstraint parentConstraint = PlapPlapPrefab.GetComponent<ParentConstraint>();
|
||||
if (parentConstraint) UnityEngine.Object.DestroyImmediate(parentConstraint);
|
||||
|
||||
// Remove lights to avoid interfering with avatar lights
|
||||
Light[] lights = PlapPlapPrefab.GetComponentsInChildren<Light>(true);
|
||||
foreach (Light light in lights) UnityEngine.Object.DestroyImmediate(light);
|
||||
|
||||
// Register the audio sources underneath to the Avatar mixer group
|
||||
AudioSource[] audioSources = PlapPlapPrefab.GetComponentsInChildren<AudioSource>(true);
|
||||
foreach (AudioSource audioSource in audioSources) audioSource.outputAudioMixerGroup = RootLogic.Instance.avatarSfx;
|
||||
|
||||
// Add StopHighlightPropagation to prevent plap plap from being highlighted
|
||||
StopHighlightPropagation stopHighlight = PlapPlapPrefab.AddComponent<StopHighlightPropagation>();
|
||||
stopHighlight.enabled = false; // marker only
|
||||
|
||||
Logger.Msg("Patched PlapPlap prefab!");
|
||||
}
|
||||
|
||||
private static void OnLocalAvatarLoaded(CVRAvatar avatar)
|
||||
=> OnAvatarLoaded(PlayerSetup.Instance, avatar.gameObject);
|
||||
private static void OnRemoteAvatarLoaded(CVRPlayerEntity playerEntity, CVRAvatar avatar)
|
||||
=> OnAvatarLoaded(playerEntity.PuppetMaster, avatar.gameObject);
|
||||
|
||||
private static void OnAvatarLoaded(PlayerBase player, GameObject avatarObject)
|
||||
{
|
||||
// Enforcing friends with benefits
|
||||
if (!Friends.FriendsWith(player.PlayerId))
|
||||
return;
|
||||
|
||||
// Ensure the avatar is NSFW
|
||||
UgcContentTags tags = player.AvatarMetadata.TagsData;
|
||||
if (tags is { Suggestive: false, Explicit: false })
|
||||
return;
|
||||
|
||||
// Ensure mature content is allowed by user settings
|
||||
if (!MetaPort.Instance.matureContentAllowed)
|
||||
return;
|
||||
|
||||
// Scan for DPS setups
|
||||
if (!DPS.ScanForDPS(avatarObject, out List<DPSOrifice> dpsOrifices, out bool foundPenetrator))
|
||||
return;
|
||||
|
||||
// If no penetrator found, attempt to find one via TPS
|
||||
if (!foundPenetrator) DPS.AttemptTPSHack(avatarObject);
|
||||
|
||||
// Setup PlapPlap for each found orifice
|
||||
if (dpsOrifices.Count != 0)
|
||||
{
|
||||
// Log found orifices
|
||||
// Logger.Msg($"Found {dpsOrifices.Count} DPS orifices on avatar '{avatarObject.name}' for player '{player.PlayerUsername}':");
|
||||
// foreach (DPSOrifice dpsOrifice in dpsOrifices) Logger.Msg($"- Orifice Type: {dpsOrifice.type}, DPS Light: {dpsOrifice.dpsLight.name}, Normal Light: {(dpsOrifice.normalLight != null ? dpsOrifice.normalLight.name : "None")}");
|
||||
|
||||
// Configure PlapPlap for each orifice
|
||||
Animator avatarAnimator = player.Animator;
|
||||
foreach (DPSOrifice dpsOrifice in dpsOrifices)
|
||||
{
|
||||
// Skip if this is already a plap plap setup
|
||||
if (PlapPlapTap.IsBuiltInPlapPlapSetup(dpsOrifice))
|
||||
continue;
|
||||
|
||||
PlapPlapTap.CreateFromOrifice(
|
||||
dpsOrifice,
|
||||
avatarAnimator,
|
||||
PlapPlapPrefab
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Asset Bundle Loading */
|
||||
|
||||
private const string PlapPlapAssetsName = "PlapPlapForAll.Resources.plap plap.assets";
|
||||
private const string PlapPlapPrefabName = "Assets/Noachi/Plap Plap/plap plap.prefab";
|
||||
|
||||
private static GameObject PlapPlapPrefab;
|
||||
|
||||
private void LoadAssetBundle()
|
||||
{
|
||||
LoggerInstance.Msg($"Loading required asset bundle...");
|
||||
using Stream resourceStream = MelonAssembly.Assembly.GetManifestResourceStream(PlapPlapAssetsName);
|
||||
using MemoryStream memoryStream = new();
|
||||
if (resourceStream == null) {
|
||||
LoggerInstance.Error($"Failed to load {PlapPlapAssetsName}!");
|
||||
return;
|
||||
}
|
||||
|
||||
resourceStream.CopyTo(memoryStream);
|
||||
AssetBundle assetBundle = AssetBundle.LoadFromStream(memoryStream);
|
||||
if (assetBundle == null) {
|
||||
LoggerInstance.Error($"Failed to load {PlapPlapAssetsName}! Asset bundle is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
PlapPlapPrefab = assetBundle.LoadAsset<GameObject>(PlapPlapPrefabName);
|
||||
if (PlapPlapPrefab == null) {
|
||||
LoggerInstance.Error($"Failed to load {PlapPlapPrefabName}! Prefab is null!");
|
||||
return;
|
||||
}
|
||||
PlapPlapPrefab.hideFlags |= HideFlags.DontUnloadUnusedAsset;
|
||||
LoggerInstance.Msg($"Loaded {PlapPlapPrefabName}!");
|
||||
|
||||
LoggerInstance.Msg("Asset bundle successfully loaded!");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue