动态表情增加
This commit is contained in:
Binary file not shown.
@@ -7,15 +7,15 @@
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_genestealer\\compabilityeffect_injectgenes.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_genestealer\\compabilityeffect_extractgene.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_genestealer\\compabilityeffect_extractgene.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_genestealer\\compabilityeffect_extractgene.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_genestealer\\compproperties_abilityinjectgenes.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_genestealer\\compproperties_abilityinjectgenes.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_genestealer\\compproperties_abilityinjectgenes.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\verbs\\cleave\\verb_meleeattack_cleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\verbs\\cleave\\verb_meleeattack_cleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:verbs\\cleave\\verb_meleeattack_cleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
@@ -126,8 +126,7 @@
|
||||
"RelativeToolTip": "Abilities\\ARA_Genestealer\\CompProperties_AbilityInjectGenes.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-21T16:09:51.937Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-21T16:09:51.937Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
@@ -139,8 +138,7 @@
|
||||
"RelativeToolTip": "Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
|
||||
"ViewState": "AgIAADUAAAAAAAAAAAAewFwAAABVAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-21T16:09:29.065Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-21T16:09:29.065Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
@@ -150,7 +148,7 @@
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_Genestealer\\CompAbilityEffect_InjectGenes.cs",
|
||||
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Genestealer\\CompAbilityEffect_InjectGenes.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_Genestealer\\CompAbilityEffect_InjectGenes.cs",
|
||||
"ViewState": "AgIAAC0AAAAAAAAAAAAtwD4AAAAQAAAAAAAAAA==",
|
||||
"ViewState": "AgIAAC0AAAAAAAAAAAAtwF0AAAAMAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-21T16:08:53.903Z",
|
||||
"EditorCaption": ""
|
||||
@@ -165,8 +163,7 @@
|
||||
"RelativeToolTip": "Verbs\\Cleave\\Verb_MeleeAttack_Cleave.cs",
|
||||
"ViewState": "AgIAAG8AAAAAAAAAAAAhwI8AAABCAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-21T12:52:47.558Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-21T12:52:47.558Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
|
||||
@@ -42,6 +42,9 @@
|
||||
<HintPath>..\..\..\..\..\..\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="FacialAnimation">
|
||||
<HintPath>..\..\..\..\..\..\workshop\content\294100\1635901197\1.6\Assemblies\FacialAnimation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -317,6 +320,9 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Utils\BezierUtil.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="FacialAnimation\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 自定义清理任务,删除obj文件夹中的临时文件 -->
|
||||
<Target Name="CleanDebugFiles" AfterTargets="Build">
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
using RimWorld;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public static class FaceAnimationFileGenerator
|
||||
{
|
||||
private static readonly string OutputDirectory = "1.6/1.6/GeneratedDefs/FacialAnimation/";
|
||||
|
||||
static FaceAnimationFileGenerator()
|
||||
{
|
||||
GenerateAllFaceAnimationFiles();
|
||||
}
|
||||
|
||||
private static void GenerateAllFaceAnimationFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 获取模组根目录
|
||||
string modRootDir = GetModRootDirectory();
|
||||
if (string.IsNullOrEmpty(modRootDir))
|
||||
{
|
||||
Log.Error("Cannot find mod root directory");
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保输出目录存在
|
||||
string fullOutputDir = Path.Combine(modRootDir, OutputDirectory);
|
||||
Directory.CreateDirectory(fullOutputDir);
|
||||
|
||||
// 配置:种族和对应的抽象动画路径
|
||||
var raceConfigs = new Dictionary<string, List<string>>
|
||||
{
|
||||
{
|
||||
"ArachnaeNode_Race_Myrmecocystus",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_ShieldHead",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_WeaponSmith",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_Fighter",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_Facehugger",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_Smokepop",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_NeuroSwarm",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_Praetorian",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
},
|
||||
{
|
||||
"ArachnaeNode_Race_Skyraider",
|
||||
new List<string> { "1.6/1.6/Defs/AnimationDefs/FacialAnimation/ARA_JobAnim.xml" }
|
||||
}
|
||||
};
|
||||
|
||||
int totalFilesGenerated = 0;
|
||||
|
||||
foreach (var config in raceConfigs)
|
||||
{
|
||||
string raceDefName = config.Key;
|
||||
List<string> paths = config.Value;
|
||||
|
||||
// 检查种族是否存在
|
||||
if (DefDatabase<ThingDef>.GetNamedSilentFail(raceDefName) == null)
|
||||
{
|
||||
Log.Warning($"Race {raceDefName} not found, skipping face animation generation");
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string relativePath in paths)
|
||||
{
|
||||
string fullSourcePath = Path.Combine(modRootDir, relativePath);
|
||||
totalFilesGenerated += GenerateAnimationFilesForRace(fullSourcePath, raceDefName, fullOutputDir);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Message($"Generated {totalFilesGenerated} face animation files in {fullOutputDir}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error in FaceAnimationFileGenerator: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取模组根目录
|
||||
/// </summary>
|
||||
private static string GetModRootDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 通过查找当前程序集所在的模组来获取根目录
|
||||
var currentMod = LoadedModManager.RunningMods.FirstOrDefault(mod =>
|
||||
mod.assemblies.loadedAssemblies.Contains(typeof(FaceAnimationFileGenerator).Assembly));
|
||||
|
||||
if (currentMod != null)
|
||||
{
|
||||
return currentMod.RootDir;
|
||||
}
|
||||
|
||||
// 备选方法:通过反射获取
|
||||
var assembly = typeof(FaceAnimationFileGenerator).Assembly;
|
||||
string assemblyLocation = assembly.Location;
|
||||
if (!string.IsNullOrEmpty(assemblyLocation))
|
||||
{
|
||||
// 向上查找直到找到模组根目录
|
||||
DirectoryInfo dir = new FileInfo(assemblyLocation).Directory;
|
||||
while (dir != null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(dir.FullName, "About.xml")) ||
|
||||
File.Exists(Path.Combine(dir.FullName, "LoadFolders.xml")))
|
||||
{
|
||||
return dir.FullName;
|
||||
}
|
||||
dir = dir.Parent;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Error("Cannot determine mod root directory");
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error getting mod root directory: {ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int GenerateAnimationFilesForRace(string sourcePath, string raceDefName, string outputDir)
|
||||
{
|
||||
int filesGenerated = 0;
|
||||
|
||||
try
|
||||
{
|
||||
// 检查源文件是否存在
|
||||
if (!File.Exists(sourcePath))
|
||||
{
|
||||
Log.Warning($"Source animation file not found: {sourcePath}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(sourcePath);
|
||||
|
||||
XmlNodeList abstractDefNodes = xmlDoc.SelectNodes("//FacialAnimation.FaceAnimationDef[@Abstract='True']");
|
||||
|
||||
if (abstractDefNodes == null || abstractDefNodes.Count == 0)
|
||||
{
|
||||
Log.Message($"No abstract FaceAnimationDef found in: {sourcePath}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 为每个种族创建单独的文件
|
||||
string outputFile = Path.Combine(outputDir, $"ARA_{raceDefName}_JobAnim.xml");
|
||||
|
||||
using (StreamWriter writer = new StreamWriter(outputFile, false, Encoding.UTF8))
|
||||
{
|
||||
writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
|
||||
writer.WriteLine("<Defs>");
|
||||
|
||||
foreach (XmlNode abstractNode in abstractDefNodes)
|
||||
{
|
||||
string concreteXml = GenerateConcreteAnimationXml(abstractNode, raceDefName);
|
||||
if (!string.IsNullOrEmpty(concreteXml))
|
||||
{
|
||||
writer.WriteLine(concreteXml);
|
||||
filesGenerated++;
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine("</Defs>");
|
||||
}
|
||||
|
||||
Log.Message($"Generated {filesGenerated} animations for {raceDefName} in {outputFile}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error generating animation files for race {raceDefName}: {ex}");
|
||||
}
|
||||
|
||||
return filesGenerated;
|
||||
}
|
||||
|
||||
private static string GenerateConcreteAnimationXml(XmlNode abstractNode, string raceDefName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string abstractName = abstractNode.Attributes?["Name"]?.Value;
|
||||
if (string.IsNullOrEmpty(abstractName))
|
||||
{
|
||||
Log.Warning("Abstract FaceAnimationDef has no Name attribute");
|
||||
return null;
|
||||
}
|
||||
|
||||
string concreteDefName = $"{raceDefName}_{abstractName.Replace("ARA_", "")}";
|
||||
|
||||
// 创建XML字符串
|
||||
StringBuilder xmlBuilder = new StringBuilder();
|
||||
xmlBuilder.AppendLine($" <FacialAnimation.FaceAnimationDef ParentName=\"{abstractName}\" MayRequire=\"Nals.FacialAnimation\">");
|
||||
xmlBuilder.AppendLine($" <defName>{concreteDefName}</defName>");
|
||||
xmlBuilder.AppendLine($" <raceName>{raceDefName}</raceName>");
|
||||
|
||||
xmlBuilder.Append(" </FacialAnimation.FaceAnimationDef>");
|
||||
|
||||
return xmlBuilder.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error($"Error generating XML for {raceDefName}: {ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user