Compare commits
10 commits
2c0fda0285
...
f0275dccf3
Author | SHA1 | Date | |
---|---|---|---|
f0275dccf3 | |||
af4ef66db5 | |||
ea688c8bec | |||
16559dfe5b | |||
6f7cf91d86 | |||
2c43db37b5 | |||
56f56ef938 | |||
e424692f58 | |||
41a1e75946 | |||
efd0696145 |
14 changed files with 173 additions and 152 deletions
8
.editorconfig
Normal file
8
.editorconfig
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# https://editorconfig.org/
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.cs]
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 4
|
18
Config.cs
18
Config.cs
|
@ -19,6 +19,7 @@ namespace CustomCosmeticLoader
|
||||||
public const string PROPERTY_IN_MAIN_MENU = "inMainMenu";
|
public const string PROPERTY_IN_MAIN_MENU = "inMainMenu";
|
||||||
public const string PROPERTY_IN_COSMETIC_MENU = "inCosmeticMenu";
|
public const string PROPERTY_IN_COSMETIC_MENU = "inCosmeticMenu";
|
||||||
public const string PROPERTY_IN_ALL_REPLAYS = "inAllReplays";
|
public const string PROPERTY_IN_ALL_REPLAYS = "inAllReplays";
|
||||||
|
public const string PROPERTY_SHOW_SKIN_IDS = "showSkinIds";
|
||||||
public const string PROPERTY_OVERRIDE_REPLAY_COSMETICS = "overrideReplayCosmetics";
|
public const string PROPERTY_OVERRIDE_REPLAY_COSMETICS = "overrideReplayCosmetics";
|
||||||
public const string PROPERTY_OTHER_PLAYERS = "otherPlayers";
|
public const string PROPERTY_OTHER_PLAYERS = "otherPlayers";
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ namespace CustomCosmeticLoader
|
||||||
public static bool inMainMenu = true;
|
public static bool inMainMenu = true;
|
||||||
public static bool inCosmeticMenu = false;
|
public static bool inCosmeticMenu = false;
|
||||||
public static bool inAllReplays = false;
|
public static bool inAllReplays = false;
|
||||||
|
public static bool showSkinIds = false;
|
||||||
public static bool overrideReplayCosmetics = false;
|
public static bool overrideReplayCosmetics = false;
|
||||||
public static Dictionary<string, string> otherPlayers = new Dictionary<string, string>();
|
public static Dictionary<string, string> otherPlayers = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
@ -85,6 +87,9 @@ namespace CustomCosmeticLoader
|
||||||
if (data[PROPERTY_IN_ALL_REPLAYS] != null)
|
if (data[PROPERTY_IN_ALL_REPLAYS] != null)
|
||||||
inAllReplays = data[PROPERTY_IN_ALL_REPLAYS].AsBool;
|
inAllReplays = data[PROPERTY_IN_ALL_REPLAYS].AsBool;
|
||||||
|
|
||||||
|
if (data[PROPERTY_SHOW_SKIN_IDS] != null)
|
||||||
|
showSkinIds = data[PROPERTY_SHOW_SKIN_IDS].AsBool;
|
||||||
|
|
||||||
if (data[PROPERTY_OVERRIDE_REPLAY_COSMETICS] != null)
|
if (data[PROPERTY_OVERRIDE_REPLAY_COSMETICS] != null)
|
||||||
overrideReplayCosmetics = data[PROPERTY_OVERRIDE_REPLAY_COSMETICS].AsBool;
|
overrideReplayCosmetics = data[PROPERTY_OVERRIDE_REPLAY_COSMETICS].AsBool;
|
||||||
|
|
||||||
|
@ -115,13 +120,14 @@ namespace CustomCosmeticLoader
|
||||||
{
|
{
|
||||||
JSONNode node = new JSONClass
|
JSONNode node = new JSONClass
|
||||||
{
|
{
|
||||||
{ PROPERTY_ENABLED, enabled ? "true" : "false" },
|
{ PROPERTY_ENABLED, new JSONData(enabled) },
|
||||||
{ PROPERTY_CURRENT_SKIN, currentSkin },
|
{ PROPERTY_CURRENT_SKIN, currentSkin },
|
||||||
{ PROPERTY_SKIN_NAME_TO_HIJACK, skinNameToHijack },
|
{ PROPERTY_SKIN_NAME_TO_HIJACK, skinNameToHijack },
|
||||||
{ PROPERTY_IN_MAIN_MENU, inMainMenu ? "true" : "false" },
|
{ PROPERTY_IN_MAIN_MENU, new JSONData(inMainMenu) },
|
||||||
{ PROPERTY_IN_COSMETIC_MENU, inCosmeticMenu ? "true" : "false" },
|
{ PROPERTY_IN_COSMETIC_MENU, new JSONData(inCosmeticMenu) },
|
||||||
{ PROPERTY_IN_ALL_REPLAYS, inAllReplays ? "true" : "false" },
|
{ PROPERTY_IN_ALL_REPLAYS, new JSONData(inAllReplays) },
|
||||||
{ PROPERTY_OVERRIDE_REPLAY_COSMETICS, overrideReplayCosmetics ? "true" : "false" },
|
{ PROPERTY_SHOW_SKIN_IDS, new JSONData(showSkinIds) },
|
||||||
|
{ PROPERTY_OVERRIDE_REPLAY_COSMETICS, new JSONData(overrideReplayCosmetics) },
|
||||||
};
|
};
|
||||||
|
|
||||||
JSONNode otherPlayersData = new JSONClass();
|
JSONNode otherPlayersData = new JSONClass();
|
||||||
|
@ -130,7 +136,7 @@ namespace CustomCosmeticLoader
|
||||||
|
|
||||||
node.Add(PROPERTY_OTHER_PLAYERS, otherPlayersData);
|
node.Add(PROPERTY_OTHER_PLAYERS, otherPlayersData);
|
||||||
|
|
||||||
File.WriteAllText(GetConfigPath(), node.ToString());
|
File.WriteAllText(GetConfigPath(), JsonHelper.FormatJson(node.ToString(), "\t"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ensureSkinSelected()
|
public static void ensureSkinSelected()
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using MIU;
|
using MIU;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -150,6 +149,20 @@ namespace CustomCosmeticLoader
|
||||||
return "Custom skins in all replays " + (Config.inAllReplays ? "enabled" : "disabled");
|
return "Custom skins in all replays " + (Config.inAllReplays ? "enabled" : "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ConsoleCommand(description = "Enable/disable showing the underlying skin ID in the cosmetic menu", paramsDescription = "[true/false]", hidden = true)]
|
||||||
|
public static string cclShowSkinIds(params string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length == 0)
|
||||||
|
return "cclShowSkinIds: " + (Config.showSkinIds ? "true" : "false");
|
||||||
|
|
||||||
|
if (args.Length != 1 || (args[0] != "true" && args[0] != "false"))
|
||||||
|
return "Requires a true or false argument";
|
||||||
|
|
||||||
|
Config.showSkinIds = args[0] == "true";
|
||||||
|
|
||||||
|
return "Skin IDs in cosmetic menu " + (Config.showSkinIds ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
|
||||||
[ConsoleCommand(description = "Enable/disable overriding a replay's cosmetics with your cosmetics", paramsDescription = "[true/false]", hidden = true)]
|
[ConsoleCommand(description = "Enable/disable overriding a replay's cosmetics with your cosmetics", paramsDescription = "[true/false]", hidden = true)]
|
||||||
public static string cclOverrideReplayCosmetics(params string[] args)
|
public static string cclOverrideReplayCosmetics(params string[] args)
|
||||||
{
|
{
|
||||||
|
|
34
JsonHelper.cs
Normal file
34
JsonHelper.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CustomCosmeticLoader
|
||||||
|
{
|
||||||
|
public class JsonHelper
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Code taken from: https://stackoverflow.com/a/57100143
|
||||||
|
*/
|
||||||
|
public static string FormatJson(string json, string indent = " ")
|
||||||
|
{
|
||||||
|
var indentation = 0;
|
||||||
|
var quoteCount = 0;
|
||||||
|
var escapeCount = 0;
|
||||||
|
|
||||||
|
var result =
|
||||||
|
from ch in json ?? string.Empty
|
||||||
|
let escaped = (ch == '\\' ? escapeCount++ : escapeCount > 0 ? escapeCount-- : escapeCount) > 0
|
||||||
|
let quotes = ch == '"' && !escaped ? quoteCount++ : quoteCount
|
||||||
|
let unquoted = quotes % 2 == 0
|
||||||
|
let colon = ch == ':' && unquoted ? ": " : null
|
||||||
|
let nospace = char.IsWhiteSpace(ch) && unquoted ? string.Empty : null
|
||||||
|
let lineBreak = ch == ',' && unquoted ? ch + Environment.NewLine + string.Concat(Enumerable.Repeat(indent, indentation)) : null
|
||||||
|
let openChar = (ch == '{' || ch == '[') && unquoted ? ch + Environment.NewLine + string.Concat(Enumerable.Repeat(indent, ++indentation)) : ch.ToString()
|
||||||
|
let closeChar = (ch == '}' || ch == ']') && unquoted ? Environment.NewLine + string.Concat(Enumerable.Repeat(indent, --indentation)) + ch : ch.ToString()
|
||||||
|
select colon ?? nospace ?? lineBreak ?? (
|
||||||
|
openChar.Length > 1 ? openChar : closeChar
|
||||||
|
);
|
||||||
|
|
||||||
|
return string.Concat(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
LICENSE
Normal file
19
LICENSE
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2023-present Terry Hearst
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -1,5 +1,4 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
29
Patches/CosmeticPanelPatches.cs
Normal file
29
Patches/CosmeticPanelPatches.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace CustomCosmeticLoader.Patches
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Override the marble cosmetic to be the hijacked marble if configured to appear in cosmetic menu.
|
||||||
|
*/
|
||||||
|
[HarmonyPatch(typeof(CosmeticPanel), nameof(CosmeticPanel.SelectCosmetic), new Type[] { typeof(Cosmetic), typeof(CosmeticType), typeof(bool) })]
|
||||||
|
internal class CosmeticPanelSelectCosmeticPatch
|
||||||
|
{
|
||||||
|
static void Postfix(Cosmetic c, CosmeticType ctype)
|
||||||
|
{
|
||||||
|
if (!Config.enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctype == CosmeticType.Skin && Config.inCosmeticMenu)
|
||||||
|
{
|
||||||
|
MarbleHolder holder = CosmeticPanel.cosmHolder;
|
||||||
|
if (Config.skinNameToHijack != "*")
|
||||||
|
holder.SetMarble(Shared.SkinToHijack);
|
||||||
|
Shared.ApplyCustomTexture(holder.currentMarble);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.showSkinIds)
|
||||||
|
CosmeticPanel.instance.CosmTitle.text += " (" + c.Id + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MIU;
|
using MIU;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace CustomCosmeticLoader.Patches
|
namespace CustomCosmeticLoader.Patches
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Hijack the marble of a ghost marble if it's in our custom player list, and apply the custom texture
|
||||||
|
*/
|
||||||
[HarmonyPatch(typeof(GhostRaceMarbleController), nameof(GhostRaceMarbleController.ApplyCosmetics))]
|
[HarmonyPatch(typeof(GhostRaceMarbleController), nameof(GhostRaceMarbleController.ApplyCosmetics))]
|
||||||
internal class GhostRaceMarbleControllerApplyCosmeticsPatch
|
internal class GhostRaceMarbleControllerApplyCosmeticsPatch
|
||||||
{
|
{
|
||||||
|
@ -28,7 +31,13 @@ namespace CustomCosmeticLoader.Patches
|
||||||
if (Config.skinNameToHijack != "*")
|
if (Config.skinNameToHijack != "*")
|
||||||
mHolder.SetMarble(Shared.SkinToHijack);
|
mHolder.SetMarble(Shared.SkinToHijack);
|
||||||
|
|
||||||
Shared.ApplyCustomTexture(mHolder.currentMarble, Config.skins[Config.otherPlayers[replayName]]);
|
Texture2D skin;
|
||||||
|
if (replayName == Player.Current.Name)
|
||||||
|
skin = Config.skins[Config.currentSkin];
|
||||||
|
else
|
||||||
|
skin = Config.skins[Config.otherPlayers[replayName]];
|
||||||
|
|
||||||
|
Shared.ApplyCustomTexture(mHolder.currentMarble, skin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MIU;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace CustomCosmeticLoader.Patches
|
namespace CustomCosmeticLoader.Patches
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Hijack the cosmetic of the marble in single player. This doesn't apply the custom texture, just swaps out the
|
* Hijack the cosmetic of the marble in single player, then apply the custom skin texture.
|
||||||
* marble with the designated marble to hijack.
|
|
||||||
*/
|
*/
|
||||||
[HarmonyPatch(typeof(MarbleController), nameof(MarbleController.ApplyMyCosmetics))]
|
[HarmonyPatch(typeof(MarbleController), nameof(MarbleController.ApplyMyCosmetics))]
|
||||||
internal class MarbleControllerApplyMyCosmeticsPatch
|
internal class MarbleControllerApplyMyCosmeticsPatch
|
||||||
|
@ -29,53 +24,9 @@ namespace CustomCosmeticLoader.Patches
|
||||||
MarbleHolder mHolder = __instance.MHolder;
|
MarbleHolder mHolder = __instance.MHolder;
|
||||||
string actualSkinId = mHolder.CosmeticSet.skin;
|
string actualSkinId = mHolder.CosmeticSet.skin;
|
||||||
mHolder.SetMarble(Shared.SkinToHijack);
|
mHolder.SetMarble(Shared.SkinToHijack);
|
||||||
|
Shared.ApplyCustomTexture(mHolder.currentMarble);
|
||||||
// Setting the skin id here allows others in multiplayer/replays to see your normal skin
|
// Setting the skin id here allows others in multiplayer/replays to see your normal skin
|
||||||
mHolder.CosmeticSet.skin = actualSkinId;
|
mHolder.CosmeticSet.skin = actualSkinId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Hijack the cosmetic of the marble when watching Replays. This doesn't apply the custom texture, just swaps out
|
|
||||||
* the marble with the designated marble to hijack. If overrideReplayCosmetics is enabled, we swap out all cosmetics
|
|
||||||
* to match our current configuration to view the replay that way.
|
|
||||||
*/
|
|
||||||
[HarmonyPatch(typeof(MarbleController), nameof(MarbleController.ApplyCosmetics))]
|
|
||||||
internal class MarbleControllerApplyCosmeticsPatch
|
|
||||||
{
|
|
||||||
static void Prefix(MarbleController __instance, ref ReplayCosmetics cosmetics)
|
|
||||||
{
|
|
||||||
// Actually, we can let this one run even if the custom skins are disabled
|
|
||||||
//if (!Config.enabled)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
if (Config.overrideReplayCosmetics)
|
|
||||||
{
|
|
||||||
cosmetics.Skin = CosmeticManager.MySkin.Id;
|
|
||||||
cosmetics.Trail = CosmeticManager.MyTrail.Id;
|
|
||||||
cosmetics.Respawn = CosmeticManager.MyRespawn.Id;
|
|
||||||
cosmetics.Hat = CosmeticManager.MyHat.Id;
|
|
||||||
cosmetics.Blast = CosmeticManager.MyBlast.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config.enabled || Config.skinNameToHijack == "*")
|
|
||||||
return;
|
|
||||||
|
|
||||||
string replayName = null;
|
|
||||||
|
|
||||||
GamePlayManager.Get().GetCurrentReplays(delegate (List<Replay> replays)
|
|
||||||
{
|
|
||||||
if (replays.Count > 0)
|
|
||||||
replayName = replays[0].Player;
|
|
||||||
});
|
|
||||||
|
|
||||||
Shared.Log("MarbleControllerApplyCosmeticsPatch Replay name: " + replayName);
|
|
||||||
|
|
||||||
if (Config.otherPlayers.ContainsKey(replayName) || replayName == Player.Current.Name)
|
|
||||||
cosmetics.Skin = Config.skinNameToHijack;
|
|
||||||
|
|
||||||
// HACK - call this early so that SetMarble is aware of it
|
|
||||||
// Normally it would be called right AFTER ApplyCosmetics
|
|
||||||
__instance.AddMode(MarbleController.ReplayMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +1,39 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using MIU;
|
using MIU;
|
||||||
using Parse.Common.Internal;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace CustomCosmeticLoader.Patches
|
namespace CustomCosmeticLoader.Patches
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Private fields/values for MarbleHolder to be used in the patches
|
||||||
|
*/
|
||||||
internal static class MarbleHolderValues
|
internal static class MarbleHolderValues
|
||||||
{
|
{
|
||||||
private static FieldInfo _mbcField = typeof(MarbleHolder).GetField("mbc", BindingFlags.NonPublic | BindingFlags.Instance);
|
internal static FieldInfo mbcField = typeof(MarbleHolder).GetField("mbc", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
public static FieldInfo MbcField
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _mbcField;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Applies the custom skin texture to the marble in both singleplayer and multiplayer, if the cosmetic chosen is the
|
* In multiplayer and Replays, hijack the current marble and set it to be the marble we're hijacking, then apply the skin
|
||||||
* one we're hijacking. In multiplayer, do some extra checks to only apply the custom texture to our marble
|
|
||||||
*/
|
*/
|
||||||
[HarmonyPatch(typeof(MarbleHolder), nameof(MarbleHolder.SetMarble))]
|
[HarmonyPatch(typeof(MarbleHolder), nameof(MarbleHolder.CheckSet))]
|
||||||
internal class MarbleHolderSetMarblePatch
|
internal class MarbleHolderCheckSetPatch
|
||||||
{
|
{
|
||||||
static void Postfix(MarbleHolder __instance, Cosmetic marbleObject)
|
static void Postfix(MarbleHolder __instance, Cosmetic.Set cs)
|
||||||
{
|
{
|
||||||
if (!Config.enabled)
|
if (!Config.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (marbleObject.Id != Config.skinNameToHijack && Config.skinNameToHijack != "*")
|
if (!NetworkManager.IsMultiplayer && !MarbleManager.Replaying)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Config.inCosmeticMenu && __instance == CosmeticPanel.cosmHolder)
|
// Don't hijack the soccer ball or zombie skins
|
||||||
|
if (cs.skin == "SoccerBall_V4" || cs.skin == "Zombie")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MarbleController controller = MarbleHolderValues.MbcField.GetValue(__instance) as MarbleController;
|
MarbleController controller = MarbleHolderValues.mbcField.GetValue(__instance) as MarbleController;
|
||||||
|
|
||||||
if (controller == null)
|
if (controller == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -52,78 +47,39 @@ namespace CustomCosmeticLoader.Patches
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!Config.otherPlayers.ContainsKey(controller.nickname))
|
if (Config.otherPlayers.ContainsKey(controller.nickname))
|
||||||
return;
|
skin = Config.skins[Config.otherPlayers[controller.nickname]];
|
||||||
skin = Config.skins[Config.otherPlayers[controller.nickname]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (MarbleManager.Replaying) // Should always be true
|
||||||
{
|
{
|
||||||
if (MarbleManager.Replaying)
|
string replayName = null;
|
||||||
|
|
||||||
|
GamePlayManager.Get().GetCurrentReplays(delegate (List<Replay> replays)
|
||||||
{
|
{
|
||||||
string replayName = null;
|
if (replays.Count > 0)
|
||||||
|
replayName = replays[0].Player;
|
||||||
|
});
|
||||||
|
|
||||||
GamePlayManager.Get().GetCurrentReplays(delegate (List<Replay> replays)
|
Shared.Log("MarbleHolderCheckSetPatch Replay name: " + replayName);
|
||||||
{
|
if (replayName == Player.Current.Name)
|
||||||
if (replays.Count > 0)
|
|
||||||
replayName = replays[0].Player;
|
|
||||||
});
|
|
||||||
|
|
||||||
Shared.Log("MarbleHolderSetMarblePatch Replay name: " + replayName);
|
|
||||||
if (replayName == Player.Current.Name)
|
|
||||||
{
|
|
||||||
skin = Config.skins[Config.currentSkin];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Config.otherPlayers.ContainsKey(replayName))
|
|
||||||
skin = Config.skins[Config.otherPlayers[replayName]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
skin = Config.skins[Config.currentSkin];
|
skin = Config.skins[Config.currentSkin];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Config.otherPlayers.ContainsKey(replayName))
|
||||||
|
skin = Config.skins[Config.otherPlayers[replayName]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin != null)
|
|
||||||
{
|
|
||||||
Shared.ApplyCustomTexture(__instance.currentMarble, skin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (skin == null)
|
||||||
* In multiplayer, hijack the current marble and set it to be the marble we're hijacking. Later, the actual texture
|
|
||||||
* will be replaced by the patch above
|
|
||||||
*/
|
|
||||||
[HarmonyPatch(typeof(MarbleHolder), nameof(MarbleHolder.CheckSet))]
|
|
||||||
internal class MarbleHolderCheckSetPatch
|
|
||||||
{
|
|
||||||
static void Postfix(MarbleHolder __instance, Cosmetic.Set cs)
|
|
||||||
{
|
|
||||||
if (!Config.enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!NetworkManager.IsMultiplayer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MarbleController controller = MarbleHolderValues.MbcField.GetValue(__instance) as MarbleController;
|
|
||||||
|
|
||||||
if (controller == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!controller.isMyClientMarble())
|
|
||||||
{
|
|
||||||
if (!Config.otherPlayers.ContainsKey(controller.nickname))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't hijack the soccer ball or zombie skins
|
|
||||||
if (cs.skin == "SoccerBall_V4" || cs.skin == "Zombie")
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__instance.SetMarble(Shared.SkinToHijack);
|
__instance.SetMarble(Shared.SkinToHijack);
|
||||||
|
Shared.ApplyCustomTexture(__instance.currentMarble, skin);
|
||||||
|
// Reset this to what it should be incase it's used later
|
||||||
__instance.CosmeticSet.skin = cs.skin;
|
__instance.CosmeticSet.skin = cs.skin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ namespace CustomCosmeticLoader.Patches
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Cosmetic skin = Config.skinNameToHijack == "*" ?
|
Cosmetic skin = Config.skinNameToHijack == "*" ?
|
||||||
(CosmeticManager.MySkin == null ? CosmeticManager.Skins[0] : CosmeticManager.MySkin) :
|
(CosmeticManager.MySkin ?? CosmeticManager.Skins[0]) :
|
||||||
Shared.SkinToHijack;
|
Shared.SkinToHijack;
|
||||||
Cosmetic hat = CosmeticManager.MyHat == null ? CosmeticManager.Hats[0] : CosmeticManager.MyHat;
|
Cosmetic hat = CosmeticManager.MyHat ?? CosmeticManager.Hats[0];
|
||||||
|
|
||||||
__instance.SetCosmetic(skin, hat);
|
__instance.SetCosmetic(skin, hat);
|
||||||
Shared.ApplyCustomTexture(__instance.cosmeticDisplay.gameObject);
|
Shared.ApplyCustomTexture(__instance.cosmeticDisplay.gameObject);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace CustomCosmeticLoader.Patches
|
namespace CustomCosmeticLoader.Patches
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using System;
|
using UnityEngine;
|
||||||
using System.Runtime.Remoting.Messaging;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace CustomCosmeticLoader
|
namespace CustomCosmeticLoader
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!--remove this property-->
|
<!-- Remove this property -->
|
||||||
<UserPropertiesNotSetUp>True</UserPropertiesNotSetUp>
|
<UserPropertiesNotSetUp>True</UserPropertiesNotSetUp>
|
||||||
<!--Insert path to MIUU game directory here-->
|
<!-- Insert path to MIUU game directory here -->
|
||||||
<GameDir></GameDir>
|
<GameDir></GameDir>
|
||||||
<!--Insert path to where your mod should build to (it will build to "out" directory by default)-->
|
<!-- Change path if you want to change to where the mod should build -->
|
||||||
<ModOutputDir>$(GameDir)\Mods\CustomCosmeticLoader</ModOutputDir>
|
<ModOutputDir>$(GameDir)\Mods\CustomCosmeticLoader</ModOutputDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Add table
Reference in a new issue