Meshy-Figur Sylvara (20.709 Dreiecke, Lane-Fassung 4.999) mit zwei Sicheln als eigene Modelle, Clips leap/ultimate, 116 Credits. Skin-System: hero_skin als kosmetische Planungswahl, Blutmond als Varianten-Skin (skin_variant.py, AI_*_Blutmond, Dress mit Skin). Heldenfenster mit Reiter Ultimate & Skin, Befehlsplatz der Heldenkarte, Mondring. Ultimate zündet nicht im Sprungschritt. Kern 500/500, EditMode 30/30, PlayMode 15/15, Verify 718/0, Selbsttest 30/30, Fingerabdrücke unverändert; Balance 50 % wie Ringborke/Funkenlanze; Leistung gleich der Funkenlanze-Heldin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
3.1 KiB
C#
82 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Luneraria.View
|
|
{
|
|
/// <summary>
|
|
/// The shared material library (port of scripts/luneraria/view/lune_materials.gd). Models name
|
|
/// their surfaces (LN_*, ENV_*); Dress swaps them for one shared material per name and team,
|
|
/// so all buildings share a few materials (SRP batcher friendly). Team 0 Blau, 1 Rot, 2 neutral.
|
|
/// </summary>
|
|
public sealed class LuneMaterialSet : ScriptableObject
|
|
{
|
|
[Serializable]
|
|
public sealed class Entry
|
|
{
|
|
public string Key;
|
|
public Material Neutral;
|
|
public Material Blau;
|
|
public Material Rot;
|
|
}
|
|
|
|
public List<Entry> Entries = new List<Entry>();
|
|
Dictionary<string, Entry> _index;
|
|
|
|
public Material Get(string key, int team)
|
|
{
|
|
if (_index == null)
|
|
{
|
|
_index = new Dictionary<string, Entry>();
|
|
foreach (Entry entry in Entries)
|
|
_index[entry.Key] = entry;
|
|
}
|
|
if (!_index.TryGetValue(key, out Entry found))
|
|
return null;
|
|
Material team_material = team == 0 ? found.Blau : team == 1 ? found.Rot : null;
|
|
return team_material != null ? team_material : found.Neutral;
|
|
}
|
|
|
|
/// <summary>Material key of an imported slot material ("LN_Stone_Pale", "ENV_bark (Instance)" -> key).</summary>
|
|
public static string KeyOf(Material material)
|
|
{
|
|
if (material == null)
|
|
return "";
|
|
string name = material.name;
|
|
int cut = name.IndexOf(" (", StringComparison.Ordinal);
|
|
return cut < 0 ? name : name.Substring(0, cut);
|
|
}
|
|
|
|
/// <summary>H1: material key of a skin ("AI_Sylvara" + "blutmond" -> "AI_Sylvara_Blutmond").</summary>
|
|
public static string SkinKey(string key, string skin)
|
|
{
|
|
return key + "_" + char.ToUpperInvariant(skin[0]) + skin.Substring(1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Swaps every known surface below root for the shared material of the team; with a skin
|
|
/// (H1, heroes) its variant of a material is taken where one exists.
|
|
/// </summary>
|
|
public void Dress(GameObject root, int team, string skin = "")
|
|
{
|
|
foreach (Renderer renderer in root.GetComponentsInChildren<Renderer>(true))
|
|
{
|
|
Material[] materials = renderer.sharedMaterials;
|
|
bool changed = false;
|
|
for (int i = 0; i < materials.Length; i++)
|
|
{
|
|
Material shared = !string.IsNullOrEmpty(skin) ? Get(SkinKey(KeyOf(materials[i]), skin), team) : null;
|
|
if (shared == null)
|
|
shared = Get(KeyOf(materials[i]), team);
|
|
if (shared != null && shared != materials[i])
|
|
{
|
|
materials[i] = shared;
|
|
changed = true;
|
|
}
|
|
}
|
|
if (changed)
|
|
renderer.sharedMaterials = materials;
|
|
}
|
|
}
|
|
}
|
|
}
|