diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index 7f0b94a..4bafd8d 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
index c10d955..229d196 100644
--- a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
+++ b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml
@@ -1814,4 +1814,4 @@
-->
-
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml
index cc400aa..263123a 100644
--- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml
+++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml
@@ -272,4 +272,33 @@
(0.6, 0.6, 0.6)
false
+
+
+ ARA_Hive_Cannot_Speak
+ 不会说话
+ 额,其实虫虫不会说话,你应该知道这点吧?
+ HediffWithComps
+ (0.6, 0.4, 0.8)
+ false
+ false
+
+
+ 0
+ false
+
+
+ Talking
+ 0
+
+
+
+
+
+
+
+ ARA_Praetorian_Base
+
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
index bdc429c..a2952b9 100644
--- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
+++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml
@@ -666,6 +666,7 @@
ARA_HiveMindDrone
ARA_HiveStrength_Low
+ ARA_Hive_Cannot_Speak
1.0
false
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_east.png
new file mode 100644
index 0000000..91d9db9
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_north.png
new file mode 100644
index 0000000..29669bf
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_south.png
new file mode 100644
index 0000000..f05e6ef
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair10_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_east.png
new file mode 100644
index 0000000..d44a10f
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_north.png
new file mode 100644
index 0000000..873d8a4
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_south.png
new file mode 100644
index 0000000..756777f
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair11_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_east.png
new file mode 100644
index 0000000..d9fca66
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_north.png
new file mode 100644
index 0000000..8c47bf3
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_south.png
new file mode 100644
index 0000000..4cce240
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair12_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_east.png
new file mode 100644
index 0000000..5c0ee0a
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_north.png
new file mode 100644
index 0000000..0ed9a42
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_south.png
new file mode 100644
index 0000000..aeed0c4
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair13_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_east.png
new file mode 100644
index 0000000..c7108d4
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_north.png
new file mode 100644
index 0000000..dd454f8
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_south.png
new file mode 100644
index 0000000..1ee9fbf
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair14_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_east.png
new file mode 100644
index 0000000..c7108d4
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_north.png
new file mode 100644
index 0000000..eee9f30
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_south.png
new file mode 100644
index 0000000..4c9f669
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair15_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_east.png
new file mode 100644
index 0000000..f280389
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_north.png
new file mode 100644
index 0000000..d59020c
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_south.png
new file mode 100644
index 0000000..5016edf
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair16_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_east.png
index b472941..f450105 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_east.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_north.png
index 16e0a9c..9568b43 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_north.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_south.png
index be86ba8..b940af7 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_south.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair1_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_east.png
index 111d47f..d893a17 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_east.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_north.png
index e96690d..191dcf2 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_north.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_south.png
index 9efc75d..da2bb20 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_south.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair2_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_east.png
index 5e490b5..5853cf8 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_east.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_north.png
index 120936a..78f51fa 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_north.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_south.png
index 63af54c..62cb634 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_south.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair3_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_east.png
new file mode 100644
index 0000000..f450105
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_north.png
new file mode 100644
index 0000000..01bef64
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_south.png
new file mode 100644
index 0000000..9b2840b
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair4_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_east.png
new file mode 100644
index 0000000..d2ed8dd
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_north.png
new file mode 100644
index 0000000..544104b
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_south.png
new file mode 100644
index 0000000..b5033eb
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair5_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_east.png
new file mode 100644
index 0000000..0f636f9
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_north.png
new file mode 100644
index 0000000..a64bf89
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_south.png
new file mode 100644
index 0000000..85bdaec
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair6_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_east.png
new file mode 100644
index 0000000..05a6134
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_north.png
new file mode 100644
index 0000000..3f66ca0
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_south.png
new file mode 100644
index 0000000..4d8494d
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair7_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_east.png
new file mode 100644
index 0000000..65017c3
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_north.png
new file mode 100644
index 0000000..adb3690
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_south.png
new file mode 100644
index 0000000..927ab40
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair8_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_east.png
new file mode 100644
index 0000000..8fd39d1
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_north.png
new file mode 100644
index 0000000..627ecf1
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_south.png
new file mode 100644
index 0000000..297cd9f
Binary files /dev/null and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair9_south.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_east.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_east.png
index c022b38..ff3ed69 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_east.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_east.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_north.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_north.png
index 3dee493..b480008 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_north.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_north.png differ
diff --git a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_south.png b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_south.png
index 71c8043..d7bf3bd 100644
Binary files a/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_south.png and b/Content/Textures/ArachnaeSwarm/Hair/ARA_ArachnaeNode_Hair_south.png differ
diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo
index 3e84bd5..6cc79f5 100644
Binary files a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo and b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo differ
diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
index b52e983..3a9bb06 100644
--- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
+++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json
@@ -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"
}
]
}
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index 2b11a57..ff222a7 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -151,6 +151,7 @@
+
diff --git a/Source/ArachnaeSwarm/Thing/HighAltitudeFlyOver.cs b/Source/ArachnaeSwarm/Thing/HighAltitudeFlyOver.cs
new file mode 100644
index 0000000..e6ff40b
--- /dev/null
+++ b/Source/ArachnaeSwarm/Thing/HighAltitudeFlyOver.cs
@@ -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;
+ }
+}
diff --git a/Source/ArachnaeSwarm/Thing/ThingclassFlyOver.cs b/Source/ArachnaeSwarm/Thing/ThingclassFlyOver.cs
new file mode 100644
index 0000000..8c4e7ed
--- /dev/null
+++ b/Source/ArachnaeSwarm/Thing/ThingclassFlyOver.cs
@@ -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(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 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();
+ // 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;
+ //}
+}
diff --git a/Source/ArachnaeSwarm/Thing/示范.md b/Source/ArachnaeSwarm/Thing/示范.md
new file mode 100644
index 0000000..4b0acc2
--- /dev/null
+++ b/Source/ArachnaeSwarm/Thing/示范.md
@@ -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 { 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
+ );
+}
\ No newline at end of file