This commit is contained in:
2025-10-24 19:00:37 +08:00
parent e7daa86280
commit 37f140be66
6 changed files with 148 additions and 82 deletions

Binary file not shown.

View File

@@ -11,7 +11,7 @@
<uiIconPath>ArachnaeSwarm/Building/ARA_HiveShip_Heart_Icon</uiIconPath>
<graphicData>
<graphicClass>Graphic_Single</graphicClass>
<texPath>ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal</texPath>
<texPath>ArachnaeSwarm/Weapon/ARA_Weapon_Empty</texPath>
<drawSize>(3.25,3.25)</drawSize>
<addTopAltitudeBias>true</addTopAltitudeBias>
</graphicData>
@@ -25,9 +25,9 @@
<!-- 应用 ModExtension -->
<modExtensions>
<li Class="ArachnaeSwarm.ArachnaeGravEngineExtension">
<inspectCommandTexPath>UI/Commands/Inspect</inspectCommandTexPath>
<orbTexPath>ArachnaeSwarm/Building/ARA_HiveShip_Heart</orbTexPath>
<cooldownTexPath>ArachnaeSwarm/Building/ARA_HiveShip_Heart</cooldownTexPath>
<baseTexPath>ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal</baseTexPath>
</li>
</modExtensions>
<size>(3,3)</size>

View File

@@ -38,12 +38,18 @@
<displayName>Humanoid Alien Races 2.0</displayName>
<steamWorkshopUrl>https://steamcommunity.com/sharedfiles/filedetails/?id=839005762</steamWorkshopUrl>
</li>
<li>
<packageId>Nals.FacialAnimation</packageId>
<displayName>[NL] Facial Animation - WIP</displayName>
<steamWorkshopUrl>https://steamcommunity.com/sharedfiles/filedetails/?id=1635901197</steamWorkshopUrl>
</li>
</modDependencies>
<loadAfter>
<li>brrainz.harmony</li>
<li>Ludeon.RimWorld</li>
<li>erdelf.HumanoidAlienRaces</li>
<li>Nals.FacialAnimation</li>
</loadAfter>
</ModMetaData>

View File

@@ -6,6 +6,10 @@
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\ara_building_refuelingvat\\building_refuelingvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_building_refuelingvat\\building_refuelingvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_hediffterrainspawn\\comphediffterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
@@ -22,12 +26,25 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 1,
"SelectedChildIndex": 2,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "Building_RefuelingVat.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"RelativeToolTip": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"ViewState": "AgIAAEQAAAAAAAAAAAAAAEABAAAQAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-24T06:16:14.743Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 0,
@@ -36,14 +53,14 @@
"RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
"RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs",
"ViewState": "AgIAAK0AAAAAAAAAAAAUwL4AAAANAAAAAAAAAA==",
"ViewState": "AgIAAHwAAAAAAAAAAAAgwJcAAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-24T02:30:45.288Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"DocumentIndex": 2,
"Title": "CompHediffTerrainSpawn.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
"RelativeDocumentMoniker": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
@@ -56,7 +73,7 @@
},
{
"$type": "Document",
"DocumentIndex": 2,
"DocumentIndex": 3,
"Title": "CompAbilityEffect_RandomHediff.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs",
"RelativeDocumentMoniker": "Abilities\\CompAbilityEffect_RandomHediff.cs",

View File

@@ -13,10 +13,14 @@ namespace ArachnaeSwarm
// 通过 ModExtension 暴露的纹理路径
private ArachnaeGravEngineExtension modExtension;
// 覆盖的纹理资源
private Texture2D customInspectCommandTex;
private CachedMaterial customOrbMat;
private Graphic customOnCooldownGraphic;
// 自定义图形组件
private Graphic customBaseGraphic; // 基座图形 - 始终静止
private Graphic customOrbGraphic; // 球体图形 - 正常状态下浮动
private Graphic customCooldownGraphic; // 冷却球体图形 - 冷却状态下静止
// 渲染相关的变量
private float orbFloatOffset = 0f;
private int lastTick = -1;
public ArachnaeGravEngineExtension ModExtension
{
@@ -30,64 +34,67 @@ namespace ArachnaeSwarm
}
}
// 重写 Graphic 属性以使用自定义纹理
public override Graphic Graphic
// 基座图形 - 始终静止
private Graphic CustomBaseGraphic
{
get
{
if (Find.TickManager.TicksGame >= cooldownCompleteTick)
if (customBaseGraphic == null)
{
return base.Graphic;
}
return CustomOnCooldownGraphic;
}
}
private Texture2D CustomInspectCommandTex
{
get
{
if (customInspectCommandTex == null && ModExtension?.inspectCommandTexPath != null)
{
customInspectCommandTex = ContentFinder<Texture2D>.Get(ModExtension.inspectCommandTexPath);
}
return customInspectCommandTex ?? ContentFinder<Texture2D>.Get("UI/Commands/Inspect");
}
}
private CachedMaterial CustomOrbMat
{
get
{
if (customOrbMat == null && ModExtension?.orbTexPath != null)
{
customOrbMat = new CachedMaterial(ModExtension.orbTexPath, ShaderDatabase.Cutout);
}
return customOrbMat ?? new CachedMaterial("Things/Building/GravEngine/GravEngine_Orb", ShaderDatabase.Cutout);
}
}
private Graphic CustomOnCooldownGraphic
{
get
{
if (customOnCooldownGraphic == null && ModExtension?.cooldownTexPath != null)
{
customOnCooldownGraphic = GraphicDatabase.Get<Graphic_Single>(
ModExtension.cooldownTexPath,
string basePath = ModExtension?.baseTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart_Pedestal";
customBaseGraphic = GraphicDatabase.Get<Graphic_Single>(
basePath,
ShaderDatabase.Cutout,
Vector2.one * 3f,
def.graphicData?.drawSize ?? Vector2.one * 3f,
Color.white);
}
return customOnCooldownGraphic ?? GraphicDatabase.Get<Graphic_Single>("Things/Building/GravEngine/GravEngine_Cooldown", ShaderDatabase.Cutout, Vector2.one * 3f, Color.white);
return customBaseGraphic;
}
}
// 球体图形 - 正常状态下浮动
private Graphic CustomOrbGraphic
{
get
{
if (customOrbGraphic == null)
{
string orbPath = ModExtension?.orbTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart";
customOrbGraphic = GraphicDatabase.Get<Graphic_Single>(
orbPath,
ShaderDatabase.Cutout,
Vector2.one * 2f,
Color.white);
}
return customOrbGraphic;
}
}
// 冷却球体图形 - 冷却状态下静止
private Graphic CustomCooldownGraphic
{
get
{
if (customCooldownGraphic == null)
{
string cooldownPath = ModExtension?.cooldownTexPath ?? "ArachnaeSwarm/Building/ARA_HiveShip_Heart_Cooldown";
customCooldownGraphic = GraphicDatabase.Get<Graphic_Single>(
cooldownPath,
ShaderDatabase.Cutout,
Vector2.one * 2f, // 注意:这里应该和球体大小一致,而不是基座大小
Color.white);
}
return customCooldownGraphic;
}
}
// 重写 Graphic 属性返回 null让基础渲染系统不工作
public override Graphic Graphic => null;
// 禁用检查系统 - 重写 Inspect 方法为空
public new void Inspect(bool silent = false)
{
// 完全禁用检查系统,不执行任何操作
// 虫群建筑不需要人类的研究检查流程
}
// 重写 GetGizmos 方法,移除检查相关的 gizmo
@@ -112,7 +119,6 @@ namespace ArachnaeSwarm
defaultLabel = "DEV: Spawn Arachnae Swarm",
action = delegate
{
// 虫群特有的调试功能
SpawnArachnaeSwarm();
}
};
@@ -142,7 +148,7 @@ namespace ArachnaeSwarm
{
return result;
}
return true; // 总是返回 true忽略检查限制
return true;
}
// 重写 GetInspectString 方法,移除检查相关的文本
@@ -169,40 +175,73 @@ namespace ArachnaeSwarm
// 虫群特有的方法
private void SpawnArachnaeSwarm()
{
// 虫群特有的生成逻辑
// 这里可以添加生成虫群单位的代码
Messages.Message("ArachnaeSwarmActivated".Translate(), this, MessageTypeDefOf.PositiveEvent);
}
// 重写 DrawAt 方法以完全控制绘制过程
// 完全重写 DrawAt 方法,实现自定义渲染系统
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
// 不调用 base.DrawAt而是直接绘制建筑主体
// 复制父类 Building 的 DrawAt 逻辑,但不包括 orb 的绘制
if (def.graphicData != null)
// 不调用基类的 DrawAt完全自定义渲染
// 更新浮动效果
UpdateFloatOffsets();
// 基础位置 - 底座始终静止
Vector3 baseDrawPos = drawLoc;
baseDrawPos.y += 0.03658537f; // 固定的高度偏移
// 球体位置 - 根据状态决定
Vector3 orbDrawPos = drawLoc;
orbDrawPos.y += 0.03658537f; // 基础高度偏移
orbDrawPos.z += 0.05f; // 球体稍微向前偏移,避免与底座重叠
// 始终绘制底座
CustomBaseGraphic.Draw(baseDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
// 根据状态绘制球体
if (Find.TickManager.TicksGame >= cooldownCompleteTick)
{
Graphic graphic = Graphic;
if (graphic != null)
{
graphic.Draw(drawLoc, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
}
// 正常状态:球体浮动
orbDrawPos.y += orbFloatOffset;
CustomOrbGraphic.Draw(orbDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
}
if (base.Spawned)
else
{
// 应用浮动效果(与父类相同)
// 冷却状态:球体静止,使用冷却贴图
CustomCooldownGraphic.Draw(orbDrawPos, flip ? base.Rotation.Opposite : base.Rotation, this, 0f);
}
}
// 更新浮动效果 - 只更新球体浮动
private void UpdateFloatOffsets()
{
int currentTick = Find.TickManager.TicksGame;
if (currentTick != lastTick)
{
// 只在非冷却状态下更新球体浮动
if (Find.TickManager.TicksGame >= cooldownCompleteTick)
{
// 使用 Mathf 替代 MathF
drawLoc.z += 0.5f * (1f + Mathf.Sin(Mathf.PI * 2f * (float)GenTicks.TicksGame / 500f)) * 0.3f;
// 球体浮动 - 上下浮动
orbFloatOffset = Mathf.Sin((float)currentTick / 100f) * 0.1f;
}
drawLoc.y += 0.03658537f;
Vector3 s = new Vector3(def.graphicData.drawSize.x, 1f, def.graphicData.drawSize.y);
// 只使用自定义的球体材质,不绘制默认 orb
Graphics.DrawMesh(MeshPool.plane10Back, Matrix4x4.TRS(drawLoc, base.Rotation.AsQuat, s), CustomOrbMat.Material, 0, null, 0);
else
{
// 冷却状态下球体不浮动
orbFloatOffset = 0f;
}
lastTick = currentTick;
}
}
// 重写额外的绘制阶段(如果需要)
public override void DrawExtraSelectionOverlays()
{
// 可以在这里添加选择时的额外效果
base.DrawExtraSelectionOverlays();
}
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
@@ -217,15 +256,19 @@ namespace ArachnaeSwarm
Find.ResearchManager.gravEngineInspected = true;
}
// 由于父类的私有字段无法访问,我们移除 UpdateSubstructureIfNeeded 的重写
// 如果需要修改子结构逻辑,可能需要通过其他方式
// 保存和加载自定义数据
public override void ExposeData()
{
base.ExposeData();
// 如果需要保存自定义状态,可以在这里添加
}
}
// ModExtension 定义,用于在 XML 中配置纹理路径
// 扩展 ModExtension 定义,添加基座纹理路径
public class ArachnaeGravEngineExtension : DefModExtension
{
public string inspectCommandTexPath;
public string orbTexPath;
public string cooldownTexPath;
public string baseTexPath; // 基座纹理路径 - 始终静止
public string orbTexPath; // 球体纹理路径 - 正常状态下浮动
public string cooldownTexPath; // 冷却球体纹理路径 - 冷却状态下静止
}
}