zz暂存
This commit is contained in:
Binary file not shown.
@@ -173,6 +173,37 @@
|
||||
</spawnCategories>
|
||||
</AlienRace.AlienBackstoryDef>
|
||||
|
||||
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
|
||||
<defName>Arachnae_Node_BS_Adult_Skyraider</defName>
|
||||
<title>阿拉克涅空天种</title>
|
||||
<titleShort>空天种</titleShort>
|
||||
<description>[PAWN_nameDef]是一只阿拉克涅空天种督虫,空天种作为阿拉克涅督虫中的精锐,进化出了强大的飞行能力,是巢穴中无可争议的空中霸主。\n\n作为为数不多拥有飞行能力的虫族,她可以从空中掠袭猎物并将其带至千米高空之上俯冲投下,只留其余猎物在地面无助的挣扎。</description>
|
||||
<slot>Adulthood</slot>
|
||||
<workDisables>
|
||||
<li>Cleaning</li>
|
||||
<!-- <li>Hauling</li> -->
|
||||
<li>Mining</li>
|
||||
<li>PlantWork</li>
|
||||
<!-- <li>Animals</li> -->
|
||||
<!-- <li>Hunting</li> -->
|
||||
<li>Crafting</li>
|
||||
<li>Cooking</li>
|
||||
<li>Constructing</li>
|
||||
<li>Caring</li>
|
||||
<li>Social</li>
|
||||
<li>Artistic</li>
|
||||
<li>Intellectual</li>
|
||||
</workDisables>
|
||||
<skillGains>
|
||||
<Shooting>5</Shooting>
|
||||
<Melee>5</Melee>
|
||||
</skillGains>
|
||||
|
||||
<spawnCategories>
|
||||
<li>ArachnaeNode_spawnCategories_Skyraider</li>
|
||||
</spawnCategories>
|
||||
</AlienRace.AlienBackstoryDef>
|
||||
|
||||
<AlienRace.AlienBackstoryDef ParentName="ARA_BaseBackStory">
|
||||
<defName>Arachnae_Node_BS_Adult_Facehugger</defName>
|
||||
<title>阿拉克涅原虫种</title>
|
||||
|
||||
@@ -213,6 +213,29 @@
|
||||
</apparelTags>
|
||||
<apparelMoney>0</apparelMoney>
|
||||
</PawnKindDef>
|
||||
<PawnKindDef ParentName="ArachnaeNodeABasePawnKind">
|
||||
<defName>ArachnaeNode_Race_Skyraider</defName>
|
||||
<label>阿拉克涅空天种</label>
|
||||
<race>ArachnaeNode_Race_Skyraider</race>
|
||||
<defaultFactionType>PlayerColony</defaultFactionType>
|
||||
<invNutrition>0</invNutrition>
|
||||
<backstoryFiltersOverride>
|
||||
<li>
|
||||
<categories>
|
||||
<li>ArachnaeNode_spawnCategoriesA</li>
|
||||
<li>ArachnaeNode_spawnCategories_Fighter</li>
|
||||
</categories>
|
||||
</li>
|
||||
</backstoryFiltersOverride>
|
||||
<abilities>
|
||||
<li>ARA_BaseRace_Acid_Launcher</li>
|
||||
<li>ARA_AcidSprayBurst</li>
|
||||
<li>ARA_Toxic_Needle_Fire</li>
|
||||
</abilities>
|
||||
<apparelTags>
|
||||
</apparelTags>
|
||||
<apparelMoney>0</apparelMoney>
|
||||
</PawnKindDef>
|
||||
|
||||
<PawnKindDef Name="ARA_InsectKindBase" ParentName="AnimalKindBase" Abstract="True">
|
||||
<defaultFactionType>PlayerColony</defaultFactionType>
|
||||
|
||||
@@ -807,7 +807,7 @@
|
||||
</south>
|
||||
<north>
|
||||
<layerOffset>-0.275</layerOffset>
|
||||
</north>
|
||||
</north>
|
||||
<east>
|
||||
<layerOffset>-0.275</layerOffset>
|
||||
</east>
|
||||
@@ -911,7 +911,7 @@
|
||||
<offsets>
|
||||
<north>
|
||||
<layerOffset>-0.275</layerOffset>
|
||||
</north>
|
||||
</north>
|
||||
</offsets>
|
||||
</li>
|
||||
</bodyAddons>
|
||||
@@ -1004,7 +1004,7 @@
|
||||
<offsets>
|
||||
<north>
|
||||
<layerOffset>-0.275</layerOffset>
|
||||
</north>
|
||||
</north>
|
||||
</offsets>
|
||||
</li>
|
||||
</bodyAddons>
|
||||
@@ -1138,4 +1138,172 @@
|
||||
</li>
|
||||
</comps>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
|
||||
<AlienRace.ThingDef_AlienRace ParentName="ARA_NodeBase">
|
||||
<defName>ArachnaeNode_Race_Skyraider</defName>
|
||||
<label>阿拉克涅空天种</label>
|
||||
<description>阿拉克涅督虫中的精锐,进化出了强大的飞行能力,是巢穴中无可争议的空中霸主。\n\n作为为数不多拥有飞行能力的虫族,她可以从空中掠袭猎物并将其带至千米高空之上俯冲投下,只留其余猎物在地面无助的挣扎。</description>
|
||||
<alienRace>
|
||||
<generalSettings>
|
||||
<!-- 各种零件定义 -->
|
||||
<alienPartGenerator>
|
||||
<!-- 额外身体部件 -->
|
||||
<bodyAddons>
|
||||
<li>
|
||||
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Claw</path>
|
||||
<inFrontOfBody>true</inFrontOfBody>
|
||||
</li>
|
||||
<li>
|
||||
<path>ArachnaeSwarm/Things/ARA_HiveNode/Addons/ArachnaeNode_Race_Addons_Fighter_Tail</path>
|
||||
<inFrontOfBody>false</inFrontOfBody>
|
||||
<offsets>
|
||||
<north>
|
||||
<layerOffset>-0.275</layerOffset>
|
||||
</north>
|
||||
</offsets>
|
||||
</li>
|
||||
</bodyAddons>
|
||||
</alienPartGenerator>
|
||||
</generalSettings>
|
||||
<raceRestriction>
|
||||
<onlyEatRaceRestrictedFood>true</onlyEatRaceRestrictedFood>
|
||||
</raceRestriction>
|
||||
</alienRace>
|
||||
<comps>
|
||||
<!-- Add our new flight component here -->
|
||||
<li Class="ArachnaeSwarm.CompProperties_PawnFlight">
|
||||
<!-- ==================== -->
|
||||
<!-- 动画帧 (必需) -->
|
||||
<!-- ==================== -->
|
||||
|
||||
<!-- 动画帧的基础贴图路径和文件名前缀。 -->
|
||||
<flyingAnimationFramePathPrefix>Wula/Things/WULA_Mech_Flyer/WULA_Mech_Flyer_Flying_</flyingAnimationFramePathPrefix>
|
||||
|
||||
<!-- 动画的总帧数。 -->
|
||||
<flyingAnimationFrameCount>2</flyingAnimationFrameCount>
|
||||
|
||||
<!-- 动画中每一帧持续的游戏刻(ticks)数。数值越小,动画越快。 -->
|
||||
<ticksPerFrame>2</ticksPerFrame>
|
||||
|
||||
<!-- ==================== -->
|
||||
<!-- 渲染节点属性 -->
|
||||
<!-- ==================== -->
|
||||
|
||||
<!-- 附加动画的绘制尺寸。 -->
|
||||
<drawSize>1.35</drawSize>
|
||||
|
||||
<!-- 附加动画相对于其父节点的绘制偏移量 (X, Y, Z)。Y值控制渲染深度。 -->
|
||||
<offset>(0, 0.1, -0.2)</offset>
|
||||
|
||||
<!-- (可选) 附加动画是否继承 Pawn 的肤色。 -->
|
||||
<inheritColors>false</inheritColors>
|
||||
|
||||
<!-- (可选, 默认: Body) 附加动画要“贴”在哪个身体部分上。 -->
|
||||
<parentTagDef>Body</parentTagDef>
|
||||
|
||||
<!-- (可选, 默认: 85) 附加动画的基础渲染层级,用于精细深度控制。 -->
|
||||
<baseLayer>90</baseLayer>
|
||||
|
||||
<!-- ==================== -->
|
||||
<!-- 飞行力学 -->
|
||||
<!-- ==================== -->
|
||||
|
||||
<!-- (可选, 默认: 50) 起飞过程的持续时间(ticks)。 -->
|
||||
<takeoffDurationTicks>40</takeoffDurationTicks>
|
||||
|
||||
<!-- (可选, 默认: 50) 降落过程的持续时间(ticks)。 -->
|
||||
<landingDurationTicks>40</landingDurationTicks>
|
||||
|
||||
<!-- (可选, 默认: 5.0) 一次飞行的最大持续时间(秒)。 -->
|
||||
<maxFlightTimeSeconds>15</maxFlightTimeSeconds>
|
||||
|
||||
<!-- (可选, 默认: 2.0) 降落后的冷却时间(秒)。 -->
|
||||
<flightCooldownSeconds>10</flightCooldownSeconds>
|
||||
|
||||
<!-- (可选, 默认: 0.5) 当接到允许飞行的工作时,实际开始飞行的几率(0.0 到 1.0)。 -->
|
||||
<flightStartChanceOnJobStart>1.0</flightStartChanceOnJobStart>
|
||||
|
||||
<!-- ==================== -->
|
||||
<!-- 飞行视觉效果 (可选) -->
|
||||
<!-- ==================== -->
|
||||
|
||||
<!-- (可选) 自定义起飞时的“bobbing”(上下浮动)曲线。 -->
|
||||
<takeoffCurve>
|
||||
<points>
|
||||
<li>(0, 0)</li>
|
||||
<li>(0.5, 0.6)</li>
|
||||
<li>(1, 1)</li>
|
||||
</points>
|
||||
</takeoffCurve>
|
||||
|
||||
<!-- (可选) 自定义降落时的“bobbing”曲线。 -->
|
||||
<landingCurve>
|
||||
<points>
|
||||
<li>(0, 1)</li>
|
||||
<li>(0.5, 0.4)</li>
|
||||
<li>(1, 0)</li>
|
||||
</points>
|
||||
</landingCurve>
|
||||
|
||||
</li>
|
||||
|
||||
<!-- ... other components ... -->
|
||||
</comps>
|
||||
|
||||
<!-- 基础属性设置 -->
|
||||
<statBases>
|
||||
<!-- 移动速度 -->
|
||||
<MoveSpeed>4.5</MoveSpeed>
|
||||
|
||||
<!-- <RestRateMultiplier>1</RestRateMultiplier> -->
|
||||
<!-- <HungerRateMultiplier>1</HungerRateMultiplier> -->
|
||||
<!-- <EatingSpeed>5</EatingSpeed> -->
|
||||
<MaxNutrition>2</MaxNutrition>
|
||||
|
||||
<CarryingCapacity>100</CarryingCapacity>
|
||||
<MeatAmount>60</MeatAmount>
|
||||
<LeatherAmount>30</LeatherAmount>
|
||||
|
||||
<MeleeDodgeChance>1.25</MeleeDodgeChance>
|
||||
<MeleeHitChance>1.25</MeleeHitChance>
|
||||
|
||||
<!-- <NegotiationAbility>1</NegotiationAbility> -->
|
||||
<!-- <SellPriceFactor>1</SellPriceFactor> -->
|
||||
<!-- <SocialImpact>1</SocialImpact> -->
|
||||
<!-- <TradePriceImprovement>0.5</TradePriceImprovement> -->
|
||||
|
||||
<!-- 自带的甲壳可以防御外部攻击 -->
|
||||
<ArmorRating_Blunt>0.4</ArmorRating_Blunt>
|
||||
<ArmorRating_Sharp>0.4</ArmorRating_Sharp>
|
||||
<ArmorRating_Heat>0.3</ArmorRating_Heat>
|
||||
</statBases>
|
||||
|
||||
<tools>
|
||||
<li>
|
||||
<label>巨镰</label>
|
||||
<capacities>
|
||||
<li>Cut</li>
|
||||
</capacities>
|
||||
<power>20</power>
|
||||
<cooldownTime>2.5</cooldownTime>
|
||||
<linkedBodyPartsGroup>ARA_Sickles</linkedBodyPartsGroup>
|
||||
<!-- <ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable> -->
|
||||
<chanceFactor>0.5</chanceFactor>
|
||||
</li>
|
||||
</tools>
|
||||
|
||||
<race>
|
||||
<!-- 身体类型 -->
|
||||
<body>ArachnaeFighter_Body</body>
|
||||
<baseBodySize>0.85</baseBodySize>
|
||||
<baseHealthScale>2</baseHealthScale>
|
||||
<lifeExpectancy>5</lifeExpectancy>
|
||||
<lifeStageAges Inherit="False">
|
||||
<li>
|
||||
<def>ArachnaeNode_Myrmecocystus_Adult</def>
|
||||
<minAge>0</minAge>
|
||||
</li>
|
||||
</lifeStageAges>
|
||||
</race>
|
||||
</AlienRace.ThingDef_AlienRace>
|
||||
</Defs>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="15.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -137,6 +138,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HediffComp_Temperature.cs" />
|
||||
<Compile Include="CompPawnFlight.cs" />
|
||||
<Compile Include="CompProperties_PawnFlight.cs" />
|
||||
<Compile Include="HarmonyPatches.cs" />
|
||||
<Compile Include="PawnRenderNode_AnimatedAttachment.cs" />
|
||||
<Compile Include="DynamicPawnRenderNodeSetup_FlightWings.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Abilities\CompAbilityEffect_TrackingCharge.cs" />
|
||||
|
||||
127
Source/ArachnaeSwarm/CompPawnFlight.cs
Normal file
127
Source/ArachnaeSwarm/CompPawnFlight.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompPawnFlight : ThingComp
|
||||
{
|
||||
private enum FlightState { Grounded, TakingOff, Flying, Landing }
|
||||
|
||||
private FlightState flightState;
|
||||
private int flightTicks = -1;
|
||||
private int flightCooldownTicks;
|
||||
private int lerpTick;
|
||||
|
||||
private Dictionary<Rot4, List<Graphic>> cachedGraphics = new Dictionary<Rot4, List<Graphic>>();
|
||||
private PawnRenderNode_AnimatedAttachment activeWingNode;
|
||||
|
||||
private Pawn Pawn => (Pawn)parent;
|
||||
public CompProperties_PawnFlight Props => (CompProperties_PawnFlight)props;
|
||||
|
||||
public bool Flying => flightState != FlightState.Grounded; // Public property for Harmony patch
|
||||
public bool ShouldShowWings => flightState != FlightState.Grounded;
|
||||
|
||||
public override void CompTick()
|
||||
{
|
||||
base.CompTick();
|
||||
if (!parent.Spawned) return;
|
||||
|
||||
FlightState oldState = flightState;
|
||||
|
||||
switch (flightState)
|
||||
{
|
||||
case FlightState.TakingOff:
|
||||
lerpTick++;
|
||||
if (lerpTick >= Props.takeoffDurationTicks) { flightState = FlightState.Flying; lerpTick = 0; }
|
||||
break;
|
||||
case FlightState.Landing:
|
||||
lerpTick++;
|
||||
if (lerpTick >= Props.landingDurationTicks) { flightState = FlightState.Grounded; lerpTick = 0; flightCooldownTicks = (int)(Props.flightCooldownSeconds * 60f); }
|
||||
break;
|
||||
case FlightState.Flying:
|
||||
flightTicks++;
|
||||
if (flightTicks >= Props.maxFlightTimeSeconds * 60f) { flightState = FlightState.Landing; }
|
||||
break;
|
||||
case FlightState.Grounded:
|
||||
if (flightCooldownTicks > 0) { flightCooldownTicks--; }
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldState != flightState)
|
||||
{
|
||||
StateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void StateChanged()
|
||||
{
|
||||
Pawn.Drawer.renderer.SetAllGraphicsDirty();
|
||||
}
|
||||
|
||||
public void Notify_JobStarted(Job job)
|
||||
{
|
||||
bool isFlyingOrTakingOff = flightState == FlightState.Flying || flightState == FlightState.TakingOff;
|
||||
bool wantsToFly = (job.def.tryStartFlying || (job.def.ifFlyingKeepFlying && isFlyingOrTakingOff));
|
||||
if (wantsToFly && flightState == FlightState.Grounded && flightCooldownTicks <= 0 && Rand.Chance(Props.flightStartChanceOnJobStart))
|
||||
{
|
||||
flightState = FlightState.TakingOff;
|
||||
flightTicks = 0;
|
||||
lerpTick = 0;
|
||||
StateChanged();
|
||||
}
|
||||
else if (!wantsToFly && isFlyingOrTakingOff)
|
||||
{
|
||||
flightState = FlightState.Landing;
|
||||
lerpTick = 0;
|
||||
StateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void LinkToRenderNode(PawnRenderNode_AnimatedAttachment node)
|
||||
{
|
||||
activeWingNode = node;
|
||||
}
|
||||
|
||||
public int GetCurrentFrame(int totalFrames)
|
||||
{
|
||||
if (totalFrames == 0) return 0;
|
||||
int currentTickInAnim = (flightState == FlightState.Flying) ? flightTicks : lerpTick;
|
||||
return (currentTickInAnim / Props.ticksPerFrame) % totalFrames;
|
||||
}
|
||||
|
||||
public List<Graphic> GetGraphicsForRotation(Rot4 rot)
|
||||
{
|
||||
if (cachedGraphics.TryGetValue(rot, out var graphics)) return graphics;
|
||||
|
||||
var newGraphics = new List<Graphic>();
|
||||
bool isFemale = Pawn.gender == Gender.Female && !string.IsNullOrEmpty(Props.flyingAnimationFramePathPrefixFemale);
|
||||
string prefix = isFemale ? Props.flyingAnimationFramePathPrefixFemale : Props.flyingAnimationFramePathPrefix;
|
||||
string suffix = (rot == Rot4.North) ? "_north" : (rot == Rot4.South) ? "_south" : "_east";
|
||||
|
||||
if (rot == Rot4.West) suffix = "_east";
|
||||
|
||||
for (int i = 1; i <= Props.flyingAnimationFrameCount; i++)
|
||||
{
|
||||
string path = prefix + i + suffix;
|
||||
Color color = Props.inheritColors ? Pawn.story.SkinColor : Color.white;
|
||||
var graphic = GraphicDatabase.Get<Graphic_Single>(path, ShaderDatabase.Transparent, Vector2.one * Props.drawSize, color);
|
||||
newGraphics.Add(graphic);
|
||||
}
|
||||
|
||||
cachedGraphics[rot] = newGraphics;
|
||||
return newGraphics;
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref flightTicks, "flightTicks", -1);
|
||||
Scribe_Values.Look(ref flightCooldownTicks, "flightCooldownTicks", 0);
|
||||
Scribe_Values.Look(ref lerpTick, "lerpTick", 0);
|
||||
Scribe_Values.Look(ref flightState, "flightState", FlightState.Grounded);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Source/ArachnaeSwarm/CompProperties_PawnFlight.cs
Normal file
34
Source/ArachnaeSwarm/CompProperties_PawnFlight.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Verse;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_PawnFlight : CompProperties
|
||||
{
|
||||
// --- Animation ---
|
||||
public string flyingAnimationFramePathPrefix;
|
||||
public string flyingAnimationFramePathPrefixFemale;
|
||||
public int flyingAnimationFrameCount = 1;
|
||||
public int ticksPerFrame = 2;
|
||||
|
||||
// --- Render Node Properties (Defined directly here) ---
|
||||
public Vector3 offset = Vector3.zero;
|
||||
public float drawSize = 1f;
|
||||
public bool inheritColors = false;
|
||||
public PawnRenderNodeTagDef parentTagDef; // e.g., "Body"
|
||||
public float baseLayer = 85f;
|
||||
|
||||
// --- Flight Mechanics ---
|
||||
public int takeoffDurationTicks = 50;
|
||||
public int landingDurationTicks = 50;
|
||||
public float maxFlightTimeSeconds = 5f;
|
||||
public float flightCooldownSeconds = 2f;
|
||||
public float flightStartChanceOnJobStart = 0.5f;
|
||||
|
||||
public CompProperties_PawnFlight()
|
||||
{
|
||||
compClass = typeof(CompPawnFlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using RimWorld;
|
||||
using HarmonyLib; // Required for AccessTools
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class DynamicPawnRenderNodeSetup_FlightWings : DynamicPawnRenderNodeSetup
|
||||
{
|
||||
public override bool HumanlikeOnly => false;
|
||||
|
||||
public override IEnumerable<(PawnRenderNode node, PawnRenderNode parent)> GetDynamicNodes(Pawn pawn, PawnRenderTree tree)
|
||||
{
|
||||
CompPawnFlight flightComp = pawn.GetComp<CompPawnFlight>();
|
||||
if (flightComp != null && flightComp.ShouldShowWings)
|
||||
{
|
||||
// Create properties directly from CompProperties
|
||||
var nodeProps = new PawnRenderNodeProperties
|
||||
{
|
||||
nodeClass = typeof(PawnRenderNode_AnimatedAttachment),
|
||||
workerClass = AccessTools.TypeByName("Verse.PawnRenderNodeWorker_Flip"),
|
||||
parentTagDef = flightComp.Props.parentTagDef ?? PawnRenderNodeTagDefOf.Body,
|
||||
baseLayer = flightComp.Props.baseLayer
|
||||
};
|
||||
|
||||
// Create a new DrawData struct and set its offset, then assign it.
|
||||
DrawData drawData = new DrawData();
|
||||
typeof(DrawData).GetField("offset").SetValueDirect(__makeref(drawData), flightComp.Props.offset);
|
||||
nodeProps.drawData = drawData;
|
||||
|
||||
if (tree.ShouldAddNodeToTree(nodeProps))
|
||||
{
|
||||
var newNode = (PawnRenderNode_AnimatedAttachment)Activator.CreateInstance(
|
||||
nodeProps.nodeClass, pawn, nodeProps, tree
|
||||
);
|
||||
|
||||
flightComp.LinkToRenderNode(newNode);
|
||||
yield return (node: newNode, parent: null);
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
Source/ArachnaeSwarm/HarmonyPatches.cs
Normal file
70
Source/ArachnaeSwarm/HarmonyPatches.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using HarmonyLib;
|
||||
using Verse;
|
||||
using System.Reflection;
|
||||
using RimWorld;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public static class HarmonyPatches
|
||||
{
|
||||
private static readonly FieldInfo flightField = AccessTools.Field(typeof(Pawn), "flight");
|
||||
|
||||
static HarmonyPatches()
|
||||
{
|
||||
var harmony = new Harmony("com.arachnaeswarm.flightcomp");
|
||||
|
||||
harmony.Patch(AccessTools.Method(typeof(PawnComponentsUtility), nameof(PawnComponentsUtility.AddComponentsForSpawn)),
|
||||
postfix: new HarmonyMethod(typeof(HarmonyPatches), nameof(DisableVanillaFlightTracker)));
|
||||
|
||||
harmony.Patch(AccessTools.PropertyGetter(typeof(Pawn), nameof(Pawn.Flying)),
|
||||
postfix: new HarmonyMethod(typeof(HarmonyPatches), nameof(OverrideFlyingProperty)));
|
||||
|
||||
harmony.Patch(AccessTools.Method(typeof(Pawn), nameof(Pawn.ExposeData)),
|
||||
prefix: new HarmonyMethod(typeof(HarmonyPatches), nameof(PreventVanillaFlightTrackerSave_Prefix)),
|
||||
postfix: new HarmonyMethod(typeof(HarmonyPatches), nameof(PreventVanillaFlightTrackerSave_Postfix)));
|
||||
}
|
||||
|
||||
public static void DisableVanillaFlightTracker(Pawn pawn)
|
||||
{
|
||||
if (pawn.TryGetComp<CompPawnFlight>() != null)
|
||||
{
|
||||
flightField?.SetValue(pawn, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void OverrideFlyingProperty(Pawn __instance, ref bool __result)
|
||||
{
|
||||
var comp = __instance.TryGetComp<CompPawnFlight>();
|
||||
if (comp != null)
|
||||
{
|
||||
__result = comp.Flying;
|
||||
}
|
||||
}
|
||||
|
||||
// Correct fix: Use 'object' to store the instance, avoiding direct type reference at compile time.
|
||||
private static object tempFlightTracker;
|
||||
|
||||
public static void PreventVanillaFlightTrackerSave_Prefix(Pawn __instance)
|
||||
{
|
||||
if (__instance.TryGetComp<CompPawnFlight>() != null)
|
||||
{
|
||||
object flightTrackerInstance = flightField?.GetValue(__instance);
|
||||
if (flightTrackerInstance != null)
|
||||
{
|
||||
tempFlightTracker = flightTrackerInstance;
|
||||
flightField.SetValue(__instance, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void PreventVanillaFlightTrackerSave_Postfix(Pawn __instance)
|
||||
{
|
||||
if (tempFlightTracker != null)
|
||||
{
|
||||
flightField?.SetValue(__instance, tempFlightTracker);
|
||||
tempFlightTracker = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Source/ArachnaeSwarm/PawnRenderNode_AnimatedAttachment.cs
Normal file
38
Source/ArachnaeSwarm/PawnRenderNode_AnimatedAttachment.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class PawnRenderNode_AnimatedAttachment : PawnRenderNode
|
||||
{
|
||||
private CompPawnFlight flightComp;
|
||||
private List<Graphic> cachedGraphics;
|
||||
|
||||
public PawnRenderNode_AnimatedAttachment(Pawn pawn, PawnRenderNodeProperties props, PawnRenderTree tree) : base(pawn, props, tree)
|
||||
{
|
||||
flightComp = pawn.GetComp<CompPawnFlight>();
|
||||
}
|
||||
|
||||
public override Graphic GraphicFor(Pawn pawn)
|
||||
{
|
||||
if (flightComp == null) return null;
|
||||
|
||||
if (cachedGraphics == null)
|
||||
{
|
||||
cachedGraphics = flightComp.GetGraphicsForRotation(pawn.Rotation);
|
||||
}
|
||||
|
||||
if (cachedGraphics.NullOrEmpty()) return null;
|
||||
|
||||
int frame = flightComp.GetCurrentFrame(cachedGraphics.Count);
|
||||
return cachedGraphics[frame];
|
||||
}
|
||||
|
||||
// We might need to override this if west-facing graphics need to be flipped.
|
||||
// public override Mesh GetMesh(PawnDrawParms parms)
|
||||
// {
|
||||
// return base.GetMesh(parms);
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user