Skip to content

Commit 1f9cd49

Browse files
authored
Prefabs (#95)
1 parent c249d97 commit 1f9cd49

File tree

4 files changed

+197
-5
lines changed

4 files changed

+197
-5
lines changed

src/Loader.cs

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,10 @@ public static class Loader
6161
{
6262
if (duringEnumCacheCreation)
6363
{
64-
UnitData.Type unitPrefabType = UnitData.Type.Scout;
6564
if (token["prefab"] != null)
6665
{
67-
string prefabId = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(token["prefab"]!.ToString());
68-
if (Enum.TryParse(prefabId, out UnitData.Type parsedType))
69-
unitPrefabType = parsedType;
66+
Registry.prefabNames.Add((int)(UnitData.Type)Registry.autoidx, CultureInfo.CurrentCulture.TextInfo.ToTitleCase(token["prefab"]!.ToString()));
7067
}
71-
PrefabManager.units.TryAdd((int)(UnitData.Type)Registry.autoidx, PrefabManager.units[(int)unitPrefabType]);
7268
}
7369
else
7470
{
@@ -458,6 +454,119 @@ public static void LoadAudioFile(Mod mod, Mod.File file)
458454
// TODO: issue #71
459455
}
460456

457+
public static void LoadPrefabInfoFile(Mod mod, Mod.File file)
458+
{
459+
try
460+
{
461+
var prefab = JsonSerializer.Deserialize<Visual.PrefabInfo>(file.bytes, new JsonSerializerOptions
462+
{
463+
Converters = { new Vector2Json() },
464+
PropertyNameCaseInsensitive = true,
465+
});
466+
if (prefab == null || prefab.type != Visual.PrefabType.Unit)
467+
return;
468+
469+
var baseUnit = PrefabManager.GetPrefab(UnitData.Type.Warrior, TribeData.Type.Imperius, SkinType.Default);
470+
if (baseUnit == null)
471+
return;
472+
473+
var unitInstance = GameObject.Instantiate(baseUnit);
474+
if (unitInstance == null)
475+
return;
476+
477+
var spriteContainer = unitInstance.transform.GetChild(0);
478+
var material = ClearExistingPartsAndExtractMaterial(spriteContainer);
479+
480+
var visualParts = ApplyVisualParts(prefab.visualParts, spriteContainer, material);
481+
482+
var svr = unitInstance.GetComponent<SkinVisualsReference>();
483+
svr.visualParts = visualParts.ToArray();
484+
485+
GameObject.DontDestroyOnLoad(unitInstance.gameObject);
486+
Registry.unitPrefabs.Add(prefab, unitInstance.GetComponent<Unit>());
487+
488+
Plugin.logger.LogInfo($"Registered prefab info from {mod.id} mod");
489+
}
490+
catch (Exception e)
491+
{
492+
Plugin.logger.LogError($"Error on loading prefab info from {mod.id} mod: {e.Message}");
493+
}
494+
}
495+
496+
private static Material? ClearExistingPartsAndExtractMaterial(Transform spriteContainer)
497+
{
498+
Material? material = null;
499+
for (int i = 0; i < spriteContainer.childCount; i++)
500+
{
501+
var child = spriteContainer.GetChild(i);
502+
if (child.gameObject.name == "Head")
503+
{
504+
var renderer = child.GetComponent<SpriteRenderer>();
505+
if (renderer != null)
506+
material = renderer.material;
507+
}
508+
GameObject.Destroy(child.gameObject);
509+
}
510+
return material;
511+
}
512+
513+
private static List<SkinVisualsReference.VisualPart> ApplyVisualParts(
514+
List<Visual.VisualPartInfo> partInfos,
515+
Transform spriteContainer,
516+
Material? material)
517+
{
518+
List<SkinVisualsReference.VisualPart> parts = new();
519+
520+
foreach (var info in partInfos)
521+
{
522+
parts.Add(CreateVisualPart(info, spriteContainer, material));
523+
}
524+
525+
return parts;
526+
}
527+
528+
private static SkinVisualsReference.VisualPart CreateVisualPart(
529+
Visual.VisualPartInfo info,
530+
Transform parent,
531+
Material? material)
532+
{
533+
var visualPartObj = new GameObject(info.gameObjectName);
534+
visualPartObj.transform.SetParent(parent);
535+
visualPartObj.transform.position = info.coordinates;
536+
visualPartObj.transform.localScale = info.scale;
537+
visualPartObj.transform.rotation = Quaternion.Euler(0f, 0f, info.rotation);
538+
539+
var outlineObj = new GameObject("Outline");
540+
outlineObj.transform.SetParent(visualPartObj.transform);
541+
outlineObj.transform.position = info.coordinates;
542+
outlineObj.transform.localScale = info.scale;
543+
outlineObj.transform.rotation = Quaternion.Euler(0f, 0f, info.rotation);
544+
545+
var visualPart = new SkinVisualsReference.VisualPart
546+
{
547+
DefaultSpriteName = info.baseName,
548+
visualPart = visualPartObj,
549+
outline = outlineObj,
550+
tintable = info.tintable
551+
};
552+
553+
var renderer = visualPartObj.AddComponent<SpriteRenderer>();
554+
renderer.material = material;
555+
renderer.sortingLayerName = "Units";
556+
renderer.sortingOrder = info.tintable ? 0 : 1;
557+
558+
visualPart.renderer = new SkinVisualsReference.RendererUnion { spriteRenderer = renderer };
559+
560+
var outlineRenderer = outlineObj.AddComponent<SpriteRenderer>();
561+
outlineRenderer.material = material;
562+
outlineRenderer.sortingLayerName = "Units";
563+
outlineRenderer.sortingOrder = -1;
564+
565+
visualPart.outlineRenderer = new SkinVisualsReference.RendererUnion { spriteRenderer = outlineRenderer };
566+
567+
return visualPart;
568+
}
569+
461570
public static void LoadGameLogicDataPatch(Mod mod, JObject gld, JObject patch)
462571
{
463572
try

src/Managers/Main.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,28 @@ private static void GameLogicData_Parse(GameLogicData __instance, JObject rootOb
3232
if (!fullyInitialized)
3333
{
3434
Load(rootObject);
35+
foreach (System.Collections.Generic.KeyValuePair<int, string> item in Registry.prefabNames)
36+
{
37+
UnitData.Type unitPrefabType = UnitData.Type.Scout;
38+
string prefabId = item.Value;
39+
if (Enum.TryParse(prefabId, out UnitData.Type parsedType))
40+
{
41+
unitPrefabType = parsedType;
42+
PrefabManager.units.TryAdd(item.Key, PrefabManager.units[(int)unitPrefabType]);
43+
}
44+
else
45+
{
46+
KeyValuePair<Visual.PrefabInfo, Unit> prefabInfo = Registry.unitPrefabs.FirstOrDefault(kv => kv.Key.name == prefabId);
47+
if (!EqualityComparer<Visual.PrefabInfo>.Default.Equals(prefabInfo.Key, default))
48+
{
49+
PrefabManager.units.TryAdd(item.Key, prefabInfo.Value);
50+
}
51+
else
52+
{
53+
PrefabManager.units.TryAdd(item.Key, PrefabManager.units[(int)unitPrefabType]);
54+
}
55+
}
56+
}
3557
foreach (Visual.SkinInfo skin in Registry.skinInfo)
3658
{
3759
if (skin.skinData != null)
@@ -286,6 +308,15 @@ private static void StartTurnAction_Execute(StartTurnAction __instance, GameStat
286308
}
287309
}
288310

311+
[HarmonyPrefix]
312+
[HarmonyPatch(typeof(Unit), nameof(Unit.CreateUnit))]
313+
private static bool Unit_CreateUnit(Unit __instance, UnitData unitData, TribeData.Type tribe, SkinType unitSkin)
314+
{
315+
Unit unit = PrefabManager.GetPrefab(unitData.type, tribe, unitSkin);
316+
if (unit == null) Console.Write("THIS FUCKING SHIT IS NULL WHAT THE FUCK");
317+
return true;
318+
}
319+
289320
internal static void Init()
290321
{
291322
stopwatch.Start();
@@ -359,6 +390,14 @@ internal static void Load(JObject gameLogicdata)
359390
);
360391
continue;
361392
}
393+
if (Regex.IsMatch(Path.GetFileName(file.name), @"^prefab(_.*)?\.json$"))
394+
{
395+
Loader.LoadPrefabInfoFile(
396+
mod,
397+
file
398+
);
399+
continue;
400+
}
362401

363402
switch (Path.GetExtension(file.name))
364403
{

src/Managers/Visual.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ public record SkinInfo(int idx, string id, SkinData? skinData);
3737
private static bool firstTimeOpeningPreview = true;
3838
private static UnitData.Type currentUnitTypeUI = UnitData.Type.None;
3939
private static TribeData.Type attackerTribe = TribeData.Type.None;
40+
public enum PrefabType
41+
{
42+
Unit,
43+
Improvement,
44+
Resource
45+
}
46+
public record PrefabInfo(PrefabType type, string name, List<VisualPartInfo> visualParts);
47+
public record VisualPartInfo(
48+
string gameObjectName,
49+
string baseName,
50+
float rotation = 0f,
51+
Vector2 coordinates = new Vector2(),
52+
Vector2 scale = new Vector2(),
53+
bool tintable = false
54+
);
55+
private static bool enableOutlines = false;
4056

4157
#region General
4258

@@ -105,6 +121,30 @@ private static void SpriteAtlasManager_DoSpriteLookup(ref SpriteAtlasManager.Spr
105121
#endregion
106122
#region Units
107123

124+
// lobotomy
125+
126+
[HarmonyPrefix]
127+
[HarmonyPatch(typeof(InteractionBar), nameof(InteractionBar.Show))]
128+
private static bool InteractionBar_Show(InteractionBar __instance, bool instant, bool force)
129+
{
130+
enableOutlines = true;
131+
return true;
132+
}
133+
134+
[HarmonyPrefix]
135+
[HarmonyPatch(typeof(UISpriteDuplicator), nameof(UISpriteDuplicator.CreateImage), typeof(SpriteRenderer), typeof(Transform), typeof(Transform), typeof(float), typeof(Vector2), typeof(bool))]
136+
private static bool UISpriteDuplicator_CreateImage(SpriteRenderer spriteRenderer, Transform source, Transform destination, float scale, Vector2 offset, bool forceFullAlpha)
137+
{
138+
return !(spriteRenderer.sortingOrder == -1 && !enableOutlines);
139+
}
140+
141+
[HarmonyPostfix]
142+
[HarmonyPatch(typeof(InteractionBar), nameof(InteractionBar.Show))]
143+
private static void InteractionBar_Show_Postfix(InteractionBar __instance, bool instant, bool force)
144+
{
145+
enableOutlines = false;
146+
}
147+
108148
[HarmonyPrefix]
109149
[HarmonyPatch(typeof(UIUnitRenderer), nameof(UIUnitRenderer.CreateUnit))]
110150
private static bool UIUnitRenderer_CreateUnit_Prefix(UIUnitRenderer __instance)

src/Registry.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public static class Registry
1414
internal static Dictionary<string, Mod> mods = new();
1515
public static Dictionary<string, Visual.PreviewTile[]> tribePreviews = new();
1616
public static Dictionary<string, Visual.SpriteInfo> spriteInfos = new();
17+
public static Dictionary<int, string> prefabNames = new();
18+
public static Dictionary<Visual.PrefabInfo, Unit> unitPrefabs = new();
19+
public static Dictionary<Visual.PrefabInfo, Resource> resourcePrefabs = new();
20+
public static Dictionary<Visual.PrefabInfo, Building> improvementsPrefabs = new();
1721
public static Dictionary<string, AssetBundle> assetBundles = new();
1822
public static List<TribeData.Type> customTribes = new();
1923
public static List<Visual.SkinInfo> skinInfo = new();

0 commit comments

Comments
 (0)