This commit is contained in:
2025-10-27 11:49:51 +08:00
parent 4b5287037e
commit 6e27852688
61 changed files with 685 additions and 32 deletions

View File

@@ -1,18 +1,34 @@
{
"Version": 1,
"WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_ejectorgans\\compabilityeffect_ejectorgans.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_ejectorgans\\compabilityeffect_ejectorgans.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\\thing\\\u793A\u8303.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing\\\u793A\u8303.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
},
{
"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|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\thing\\highaltitudeflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing\\highaltitudeflyover.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_terrainrestriction\\compabilityeffect_terrainrestriction .cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_terrainrestriction\\compabilityeffect_terrainrestriction .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\\thing\\thingclassflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing\\thingclassflyover.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\\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}"
},
{
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\compabilityeffect_randomhediff.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@@ -31,41 +47,87 @@
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "CompAbilityEffect_EjectOrgans.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
"RelativeToolTip": "Abilities\\ARA_EjectOrgans\\CompAbilityEffect_EjectOrgans.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAC4AAAAoAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-25T11:49:25.843Z",
"Title": "\u793A\u8303.md",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\\u793A\u8303.md",
"RelativeDocumentMoniker": "Thing\\\u793A\u8303.md",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\\u793A\u8303.md",
"RelativeToolTip": "Thing\\\u793A\u8303.md",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAAAkAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
"WhenOpened": "2025-10-27T03:36:17.112Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "CompAbilityEffect_ExtractGene.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
"RelativeDocumentMoniker": "Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
"RelativeToolTip": "Abilities\\ARA_Genestealer\\CompAbilityEffect_ExtractGene.cs",
"ViewState": "AgIAABEAAAAAAAAAAAAAwCgAAAApAAAAAAAAAA==",
"Title": "HighAltitudeFlyOver.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\HighAltitudeFlyOver.cs",
"RelativeDocumentMoniker": "Thing\\HighAltitudeFlyOver.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\HighAltitudeFlyOver.cs",
"RelativeToolTip": "Thing\\HighAltitudeFlyOver.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAACMAAAARAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-25T11:49:07.979Z",
"EditorCaption": ""
"WhenOpened": "2025-10-27T03:32:08.102Z"
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "CompAbilityEffect_TerrainRestriction .cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
"RelativeDocumentMoniker": "Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
"RelativeToolTip": "Abilities\\ARA_TerrainRestriction\\CompAbilityEffect_TerrainRestriction .cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwQAAAABAAAAAAAAAA==",
"Title": "ThingclassFlyOver.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\ThingclassFlyOver.cs",
"RelativeDocumentMoniker": "Thing\\ThingclassFlyOver.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing\\ThingclassFlyOver.cs*",
"RelativeToolTip": "Thing\\ThingclassFlyOver.cs*",
"ViewState": "AgIAAAcAAAAAAAAAAAAgwCEAAAAEAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-25T11:48:39.275Z",
"EditorCaption": ""
"WhenOpened": "2025-10-27T03:03:30.662Z"
},
{
"$type": "Document",
"DocumentIndex": 4,
"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"
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "Building_ArachnaeGravEngine.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs",
"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": "AgIAAHwAAAAAAAAAAAAgwJcAAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-24T02:30:45.288Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"Title": "CompHediffTerrainSpawn.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
"RelativeDocumentMoniker": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
"RelativeToolTip": "Hediffs\\ARA_HediffTerrainSpawn\\CompHediffTerrainSpawn.cs",
"ViewState": "AgIAAB0AAAAAAAAAAAAswE0AAABHAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-23T08:00:28.236Z"
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "CompAbilityEffect_RandomHediff.cs",
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs",
"RelativeDocumentMoniker": "Abilities\\CompAbilityEffect_RandomHediff.cs",
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\CompAbilityEffect_RandomHediff.cs",
"RelativeToolTip": "Abilities\\CompAbilityEffect_RandomHediff.cs",
"ViewState": "AgIAALoAAAAAAAAAAAAqwNcAAAAZAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-10-22T06:34:08.063Z"
}
]
}

View File

@@ -151,6 +151,7 @@
<Compile Include="Storyteller\IncidentWorker_CustomRaid.cs" />
<Compile Include="Storyteller\RaidWaveDef.cs" />
<Compile Include="Storyteller\RaidWavePoolDef.cs" />
<Compile Include="Thing\ThingclassFlyOver.cs" />
<Compile Include="Verbs\Verb_ShootWithOffset.cs" />
<Compile Include="Abilities\ARA_ShowTemperatureRange\CompAbilityEffect_AbilityShowTemperatureRange.cs" />
<Compile Include="Abilities\ARA_ShowTemperatureRange\CompProperties_AbilityShowTemperatureRange.cs" />

View File

@@ -0,0 +1,171 @@
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
[StaticConstructorOnStartup]
public class HighAltitudeFlyOver : FlyOver
{
// 超高空飞行物特有的字段
private Material cachedHighAltitudeShadowMaterial;
private bool useCustomShadowGraphic = true;
private float shadowIntensity = 0.6f; // 阴影强度
// 创建子类自己的 shadowPropertyBlock
private static MaterialPropertyBlock highAltitudeShadowPropertyBlock = new MaterialPropertyBlock();
// 静态构造器:预加载阴影材质
static HighAltitudeFlyOver()
{
// 可以在这里预加载特殊阴影材质
}
// 属性:重写阴影材质
protected new Material ShadowMaterial
{
get
{
if (cachedHighAltitudeShadowMaterial == null)
{
// 使用特殊的高空阴影材质
var skyfallerShadow = def.skyfaller?.shadow;
bool hasCustomShadow = skyfallerShadow != null && !skyfallerShadow.NullOrEmpty();
if (hasCustomShadow && useCustomShadowGraphic)
{
cachedHighAltitudeShadowMaterial = MaterialPool.MatFrom(
skyfallerShadow,
ShaderDatabase.Transparent,
Color.white);
}
else
{
// 默认使用圆形阴影
cachedHighAltitudeShadowMaterial = MaterialPool.MatFrom(
"Things/Skyfaller/SkyfallerShadowCircle",
ShaderDatabase.Transparent);
}
}
return cachedHighAltitudeShadowMaterial;
}
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref useCustomShadowGraphic, "useCustomShadowGraphic", true);
Scribe_Values.Look(ref shadowIntensity, "shadowIntensity", 0.6f);
}
// 重写绘制方法:只绘制阴影,不绘制主体
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
// 完全跳过主体绘制,只绘制阴影
DrawHighAltitudeShadow();
}
// 专门的高空阴影绘制方法
protected virtual void DrawHighAltitudeShadow()
{
Material shadowMaterial = ShadowMaterial;
if (shadowMaterial == null)
return;
Vector3 shadowPos = DrawPos;
shadowPos.y = AltitudeLayer.Shadows.AltitudeFor();
// 高空阴影的特殊参数
float shadowAlpha = CalculateHighAltitudeShadowAlpha();
float shadowScale = CalculateHighAltitudeShadowScale();
// 设置阴影属性 - 使用子类自己的 property block
highAltitudeShadowPropertyBlock.SetColor(ShaderPropertyIDs.Color,
new Color(1f, 1f, 1f, shadowAlpha * shadowIntensity));
Vector3 scale = new Vector3(shadowScale, 1f, shadowScale);
Matrix4x4 matrix = Matrix4x4.TRS(shadowPos, Quaternion.identity, scale);
// 绘制阴影
Graphics.DrawMesh(MeshPool.plane10, matrix, shadowMaterial,
0, null, 0, highAltitudeShadowPropertyBlock);
}
// 计算高空阴影透明度
protected virtual float CalculateHighAltitudeShadowAlpha()
{
// 高空阴影应该更淡
float baseAlpha = Mathf.Lerp(0.1f, 0.4f, currentProgress);
// 根据高度调整透明度(越高越淡)
float heightFactor = Mathf.Clamp(1f - (altitude / 100f), 0.1f, 1f);
return baseAlpha * heightFactor;
}
// 计算高空阴影大小
protected virtual float CalculateHighAltitudeShadowScale()
{
// 高空阴影应该更大(透视效果)
float baseScale = Mathf.Lerp(0.8f, 1.2f, currentProgress);
// 根据高度调整大小(越高越大)
float heightFactor = 1f + (altitude / 50f);
return baseScale * heightFactor;
}
// 重写 Tick 方法,可以添加高空特有的效果
protected override void Tick()
{
base.Tick();
// 高空特有的效果:更稀少的粒子效果
var motesPerCell = def.skyfaller?.motesPerCell;
bool hasMotes = motesPerCell != null && motesPerCell > 0;
if (Rand.MTBEventOccurs(2f, 1f, 1f) && hasMotes)
{
CreateHighAltitudeEffects();
}
}
// 高空特效(更稀疏)
protected virtual void CreateHighAltitudeEffects()
{
Vector3 effectPos = DrawPos;
effectPos.y = AltitudeLayer.Weather.AltitudeFor(); // 使用天气层高度
// 高空特有的粒子效果
FleckMaker.ThrowAirPuffUp(effectPos, base.Map);
// 偶尔生成云迹效果
if (Rand.Chance(0.1f))
{
FleckMaker.ThrowSmoke(effectPos, base.Map, 3f);
}
}
// 新的工具方法:创建超高空飞行物
public static HighAltitudeFlyOver MakeHighAltitudeFlyOver(ThingDef flyOverDef, IntVec3 start, IntVec3 end, Map map,
float speed = 1f, float height = 50f, ThingOwner contents = null) // 默认高度更高
{
HighAltitudeFlyOver flyOver = (HighAltitudeFlyOver)ThingMaker.MakeThing(flyOverDef);
flyOver.startPosition = start;
flyOver.endPosition = end;
flyOver.flightSpeed = speed;
flyOver.altitude = height;
// 超高空特有的设置
flyOver.playFlyOverSound = false; // 高空可能听不到声音
flyOver.createShadow = true;
if (contents != null)
{
flyOver.innerContainer.TryAddRangeOrTransfer(contents);
}
GenSpawn.Spawn(flyOver, start, map);
return flyOver;
}
}

View File

@@ -0,0 +1,313 @@
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
[StaticConstructorOnStartup]
public class FlyOver : ThingWithComps, IThingHolder
{
// 核心字段
public ThingOwner innerContainer; // 内部物品容器
public IntVec3 startPosition; // 起始位置
public IntVec3 endPosition; // 结束位置
public float flightSpeed = 1f; // 飞行速度
public float currentProgress = 0f; // 当前进度 (0-1)
public float altitude = 10f; // 飞行高度
public float flightAngle = 0f; // 飞行角度
// 状态标志
private bool hasStarted = false;
private bool hasCompleted = false;
// 音效系统
private Sustainer flightSoundPlaying;
// 视觉效果
private Material cachedShadowMaterial;
private static MaterialPropertyBlock shadowPropertyBlock = new MaterialPropertyBlock();
// 配置字段
public bool spawnContentsOnImpact = false; // 是否在结束时生成内容物
public bool playFlyOverSound = true; // 是否播放飞越音效
public bool createShadow = true; // 是否创建阴影
// 属性
public override Vector3 DrawPos
{
get
{
// 线性插值计算当前位置
Vector3 start = startPosition.ToVector3();
Vector3 end = endPosition.ToVector3();
// 添加高度偏移
Vector3 basePos = Vector3.Lerp(start, end, currentProgress);
basePos.y = altitude;
return basePos;
}
}
public override Graphic Graphic
{
get
{
Thing thingForGraphic = GetThingForGraphic();
if (thingForGraphic == this)
{
return base.Graphic;
}
return thingForGraphic.Graphic.ExtractInnerGraphicFor(thingForGraphic);
}
}
protected Material ShadowMaterial
{
get
{
if (cachedShadowMaterial == null && createShadow)
{
cachedShadowMaterial = MaterialPool.MatFrom("Things/Skyfaller/SkyfallerShadowCircle", ShaderDatabase.Transparent);
}
return cachedShadowMaterial;
}
}
public FlyOver()
{
innerContainer = new ThingOwner<Thing>(this);
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
Scribe_Values.Look(ref startPosition, "startPosition");
Scribe_Values.Look(ref endPosition, "endPosition");
Scribe_Values.Look(ref flightSpeed, "flightSpeed", 1f);
Scribe_Values.Look(ref currentProgress, "currentProgress", 0f);
Scribe_Values.Look(ref altitude, "altitude", 10f);
Scribe_Values.Look(ref flightAngle, "flightAngle", 0f);
Scribe_Values.Look(ref hasStarted, "hasStarted", false);
Scribe_Values.Look(ref hasCompleted, "hasCompleted", false);
Scribe_Values.Look(ref spawnContentsOnImpact, "spawnContentsOnImpact", false);
}
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
if (!respawningAfterLoad)
{
// 计算飞行角度(从起点指向终点的方向)
Vector3 direction = (endPosition.ToVector3() - startPosition.ToVector3()).normalized;
flightAngle = Mathf.Atan2(direction.z, direction.x) * Mathf.Rad2Deg;
// 设置初始位置
base.Position = startPosition;
hasStarted = true;
// 开始飞行音效
if (playFlyOverSound && def.skyfaller?.floatingSound != null)
{
flightSoundPlaying = def.skyfaller.floatingSound.TrySpawnSustainer(
SoundInfo.InMap(new TargetInfo(startPosition, map), MaintenanceType.PerTick));
}
}
}
protected override void Tick()
{
base.Tick();
if (!hasStarted || hasCompleted)
return;
// 更新飞行进度
currentProgress += flightSpeed * 0.001f; // 调整速度系数
// 更新当前位置(用于碰撞检测等)
UpdatePosition();
// 维持飞行音效
flightSoundPlaying?.Maintain();
// 检查是否到达终点
if (currentProgress >= 1f)
{
CompleteFlyOver();
}
// 可选:生成飞行轨迹特效
if (Rand.MTBEventOccurs(0.5f, 1f, 1f) && def.skyfaller?.motesPerCell > 0)
{
CreateFlightEffects();
}
}
private void UpdatePosition()
{
// 更新物体的网格位置(用于碰撞检测等)
Vector3 currentWorldPos = Vector3.Lerp(startPosition.ToVector3(), endPosition.ToVector3(), currentProgress);
IntVec3 newPos = currentWorldPos.ToIntVec3();
if (newPos != base.Position && newPos.InBounds(base.Map))
{
base.Position = newPos;
}
}
private void CompleteFlyOver()
{
hasCompleted = true;
currentProgress = 1f;
// 生成内容物(如果需要)
if (spawnContentsOnImpact && innerContainer.Any)
{
SpawnContents();
}
// 播放完成音效
if (def.skyfaller?.impactSound != null)
{
def.skyfaller.impactSound.PlayOneShot(
SoundInfo.InMap(new TargetInfo(endPosition, base.Map)));
}
// 销毁自身
Destroy();
}
private void SpawnContents()
{
foreach (Thing thing in innerContainer)
{
if (thing != null && !thing.Destroyed)
{
GenPlace.TryPlaceThing(thing, endPosition, base.Map, ThingPlaceMode.Near);
}
}
innerContainer.Clear();
}
private void CreateFlightEffects()
{
// 在飞行轨迹上生成粒子效果
Vector3 effectPos = DrawPos;
effectPos.y = AltitudeLayer.MoteOverhead.AltitudeFor();
FleckMaker.ThrowSmoke(effectPos, base.Map, 1f);
// 可选:根据速度生成更多效果
if (flightSpeed > 2f)
{
FleckMaker.ThrowAirPuffUp(effectPos, base.Map);
}
}
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
// 获取绘制位置和旋转
Vector3 finalDrawPos = drawLoc;
float extraRotation = flightAngle;
// 绘制主体
Thing thingForGraphic = GetThingForGraphic();
Graphic.Draw(finalDrawPos, thingForGraphic.Rotation, thingForGraphic, extraRotation);
// 绘制阴影
DrawFlightShadow();
}
protected virtual void DrawFlightShadow()
{
Material shadowMaterial = ShadowMaterial;
if (shadowMaterial == null)
return;
Vector3 shadowPos = DrawPos;
shadowPos.y = AltitudeLayer.Shadows.AltitudeFor();
// 根据进度调整阴影大小和透明度
float shadowAlpha = Mathf.Lerp(0.3f, 1f, currentProgress);
float shadowScale = Mathf.Lerp(0.5f, 1.5f, currentProgress);
shadowPropertyBlock.SetColor(ShaderPropertyIDs.Color,
new Color(1f, 1f, 1f, shadowAlpha));
Vector3 scale = new Vector3(shadowScale, 1f, shadowScale);
Matrix4x4 matrix = Matrix4x4.TRS(shadowPos, Quaternion.identity, scale);
Graphics.DrawMesh(MeshPool.plane10, matrix, shadowMaterial,
0, null, 0, shadowPropertyBlock);
}
// IThingHolder 接口实现
public ThingOwner GetDirectlyHeldThings()
{
return innerContainer;
}
public void GetChildHolders(List<IThingHolder> outChildren)
{
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings());
}
private Thing GetThingForGraphic()
{
if (def.graphicData != null || !innerContainer.Any)
{
return this;
}
return innerContainer[0];
}
// 工具方法:创建飞越物体
public static FlyOver MakeFlyOver(ThingDef flyOverDef, IntVec3 start, IntVec3 end, Map map,
float speed = 1f, float height = 10f, ThingOwner contents = null)
{
FlyOver flyOver = (FlyOver)ThingMaker.MakeThing(flyOverDef);
flyOver.startPosition = start;
flyOver.endPosition = end;
flyOver.flightSpeed = speed;
flyOver.altitude = height;
if (contents != null)
{
flyOver.innerContainer.TryAddRangeOrTransfer(contents);
}
GenSpawn.Spawn(flyOver, start, map);
return flyOver;
}
//// 创建简单的飞越物体
//public void CreateSimpleFlyOver()
//{
// // 获取地图边界
// Map map = Find.CurrentMap;
// IntVec3 start = new IntVec3(0, 0, map.Size.z / 2); // 左边中间
// IntVec3 end = new IntVec3(map.Size.x, 0, map.Size.z / 2); // 右边中间
// // 创建飞越物体
// FlyOver.MakeFlyOver(ThingDefOf.FlyOverShip, start, end, map,
// speed: 1.5f, height: 15f);
//}
//// 创建带内容的飞越物体
//public void CreateFlyOverWithContents()
//{
// Map map = Find.CurrentMap;
// IntVec3 start = new IntVec3(map.Size.x / 2, 0, 0); // 上边中间
// IntVec3 end = new IntVec3(map.Size.x / 2, 0, map.Size.z); // 下边中间
// // 创建内容容器
// ThingOwner contents = new ThingOwner<Thing>();
// contents.TryAdd(ThingMaker.MakeThing(ThingDefOf.Steel, 20));
// FlyOver flyOver = FlyOver.MakeFlyOver(ThingDefOf.CargoFlyOver, start, end, map,
// speed: 1f, height: 12f, contents: contents);
// flyOver.spawnContentsOnImpact = true;
//}
}

View File

@@ -0,0 +1,76 @@
// 在其他文件中调用:
// 1. 简单飞越
public void CreateSimpleFlyOverExample()
{
FlyOver flyOver = FlyOverUtility.CreateFlyOver(
flyOverDef: ThingDefOf.FlyOverShip,
map: Find.CurrentMap,
startEdge: Rot4.West, // 从西边开始
endEdge: Rot4.East, // 到东边结束
speed: 1.5f,
altitude: 12f
);
}
// 2. 货运飞越
public void CreateCargoFlyOverExample()
{
var cargoItems = new List<(ThingDef, int)>
{
(ThingDefOf.Steel, 50),
(ThingDefOf.Plasteel, 20),
(ThingDefOf.Component, 5)
};
FlyOver cargo = FlyOverUtility.CreateCargoFlyOver(
map: Find.CurrentMap,
cargoItems: cargoItems,
startEdge: Rot4.North,
speed: 0.8f
);
}
// 3. 侦察飞越
public void CreateScoutFlyOverExample()
{
FlyOver scout = FlyOverUtility.CreateScoutFlyOver(
map: Find.CurrentMap,
startEdge: Rot4.South,
endEdge: Rot4.North
);
}
// 4. 轰炸飞越
public void CreateBombingRunExample()
{
IntVec3 target = new IntVec3(50, 0, 50); // 目标坐标
FlyOver bomber = FlyOverUtility.CreateBombingFlyOver(
map: Find.CurrentMap,
targetPosition: target,
bombDef: ThingDefOf.Bomb,
startEdge: Rot4.West
);
}
// 5. 使用参数对象
public void CreateWithParamsExample()
{
var flyOverParams = new FlyOverParams
{
flyOverDef = ThingDefOf.FlyOverShip,
map = Find.CurrentMap,
startEdge = Rot4.East,
endEdge = Rot4.West,
speed = 2f,
altitude = 15f,
contents = new List<Thing> { ThingMaker.MakeThing(ThingDefOf.Gold) },
spawnContents = true
};
// 可以轻松扩展FlyOverUtility来支持参数对象
FlyOver flyOver = FlyOverUtility.CreateFlyOverWithContents(
flyOverParams.flyOverDef,
flyOverParams.map,
flyOverParams.contents,
flyOverParams.spawnContents,
flyOverParams.startEdge,
flyOverParams.endEdge,
flyOverParams.speed,
flyOverParams.altitude
);
}