Files
necromants-tome-7d2d-3-2/HarmonySrc/BoneSteedPatch.cs
T

124 lines
4.9 KiB
C#

using System.Collections.Generic;
using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
/// <summary>
/// Костяной скакун (1.6.0, 01.10.2026): мотоцикл из костей, призывается книгой, ездит на
/// кровавых сферах. Сущность necroBoneSteed в entityclasses.xml - наследник vehicleMotorcycle
/// со своей моделью (бандл necrobonesteed, собран из копии ванильного VMotorcycleP.prefab).
///
/// Топливо - кровавые сферы в четырёх ячейках модификаций, ремонт - костями: всё это в
/// BoneSteedFuelPatch. Здесь только запрет заправки канистрой (GetFuelItem).
///
/// Модель выросла из рипнутого префаба, и у неё те же две беды, что у оссуария: игровые теги
/// коллайдеров потеряны (без них на скакуна не сесть и по нему не попасть) и шейдер-заглушка.
/// Оба лечатся с ванильного мотоцикла - теги по путям объектов, шейдер у его материала.
/// </summary>
public static class BoneSteed
{
public const string EntityClassName = "necroBoneSteed";
public const string FuelItem = "resourceBloodSphere";
public const string ItemName = "necroBoneSteedPlaceable";
const string VanillaPrefab = "@:Entities/Vehicles/VMotorcycle/VMotorcycleP.prefab";
public static bool Is(Entity e)
{
return e != null && EntityClass.list.TryGetValue(e.entityClass, out EntityClass cls) &&
cls != null && cls.entityClassName == EntityClassName;
}
static Transform vanilla;
static Shader vanillaShader;
public static void FixModel(EntityVehicle ev)
{
if (vanilla == null)
{
vanilla = DataLoader.LoadAsset<Transform>(VanillaPrefab);
if (vanilla == null)
{
Debug.LogWarning("[NecromancerTome] BoneSteed: ванильный мотоцикл не найден - теги и шейдер не поправлены");
return;
}
foreach (Renderer r in vanilla.GetComponentsInChildren<Renderer>(true))
{
if (r.sharedMaterial != null && r.sharedMaterial.HasProperty("_RMOM"))
{
vanillaShader = r.sharedMaterial.shader;
break;
}
}
}
var byPath = new Dictionary<string, Transform>();
foreach (Transform t in vanilla.GetComponentsInChildren<Transform>(true))
byPath[PathOf(t, vanilla)] = t;
int tags = 0, mats = 0;
foreach (Transform t in ev.transform.GetComponentsInChildren<Transform>(true))
{
if (!byPath.TryGetValue(PathOf(t, ev.transform), out Transform src))
continue;
if (t.tag != src.tag || t.gameObject.layer != src.gameObject.layer)
{
t.tag = src.tag;
t.gameObject.layer = src.gameObject.layer;
tags++;
}
}
if (vanillaShader != null)
{
foreach (Renderer r in ev.transform.GetComponentsInChildren<Renderer>(true))
{
foreach (Material m in r.sharedMaterials)
{
if (m != null && m.HasProperty("_RMOM") && m.shader != vanillaShader)
{
m.shader = vanillaShader;
m.enableInstancing = true;
mats++;
}
}
}
}
Debug.Log("[NecromancerTome] BoneSteed: теги поправлены у " + tags + " объектов, шейдер '" +
(vanillaShader != null ? vanillaShader.name : "-") + "' поставлен " + mats + " материалам");
}
/// <summary>Путь объекта от корня префаба. Корень - пустая строка: у экземпляра корень
/// называется иначе (necroBoneSteedP(Clone)), чем у ванильного префаба.</summary>
static string PathOf(Transform t, Transform root)
{
if (t == root)
return "";
string p = t.name;
for (Transform x = t.parent; x != null && x != root; x = x.parent)
p = x.name + "/" + p;
return p;
}
}
[HarmonyPatch(typeof(EntityVehicle), nameof(EntityVehicle.PostInit))]
public static class Patch_EntityVehicle_PostInit_BoneSteed
{
public static void Postfix(EntityVehicle __instance)
{
if (BoneSteed.Is(__instance))
BoneSteed.FixModel(__instance);
}
}
/// <summary>Канистрой и вообще из рюкзака скакуна не заправить (указание 01.10): кровь
/// вставляется только в ячейки. Пустой предмет топлива прячет пункт «Заправить» в меню.</summary>
[HarmonyPatch(typeof(Vehicle), nameof(Vehicle.GetFuelItem))]
public static class Patch_Vehicle_GetFuelItem_BoneSteed
{
public static void Postfix(Vehicle __instance, ref string __result)
{
if (BoneSteed.Is(__instance.entity))
__result = "";
}
}
}