存食物需求的ability
This commit is contained in:
Binary file not shown.
@@ -25,6 +25,11 @@
|
|||||||
<li Class="CompProperties_AbilityLaunchProjectile">
|
<li Class="CompProperties_AbilityLaunchProjectile">
|
||||||
<projectileDef>ARA_Proj_EggSac</projectileDef>
|
<projectileDef>ARA_Proj_EggSac</projectileDef>
|
||||||
</li>
|
</li>
|
||||||
|
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
|
||||||
|
<needDef>Food</needDef>
|
||||||
|
<needCost>4</needCost>
|
||||||
|
<failMessage>食物不足</failMessage>
|
||||||
|
</li>
|
||||||
</comps>
|
</comps>
|
||||||
</AbilityDef>
|
</AbilityDef>
|
||||||
|
|
||||||
@@ -60,6 +65,11 @@
|
|||||||
<ticksBetweenShots>3</ticksBetweenShots> <!-- 每次发射间隔12 Ticks (0.2秒) -->
|
<ticksBetweenShots>3</ticksBetweenShots> <!-- 每次发射间隔12 Ticks (0.2秒) -->
|
||||||
</li>
|
</li>
|
||||||
</comps>
|
</comps>
|
||||||
|
<li Class="ArachnaeSwarm.CompProperties_AbilityNeedCost">
|
||||||
|
<needDef>Food</needDef>
|
||||||
|
<needCost>0.5</needCost>
|
||||||
|
<failMessage>食物不足</failMessage>
|
||||||
|
</li>
|
||||||
</AbilityDef>
|
</AbilityDef>
|
||||||
|
|
||||||
<ThingDef>
|
<ThingDef>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<!-- 背部组织,仅包含骨骼和甲片 -->
|
<!-- 背部组织,仅包含骨骼和甲片 -->
|
||||||
<li>
|
<li>
|
||||||
<def>ARA_Dorsum</def>
|
<def>ARA_Dorsum</def>
|
||||||
<coverage>0.036</coverage>
|
<coverage>0</coverage>
|
||||||
<groups>
|
<groups>
|
||||||
<li>Torso</li>
|
<li>Torso</li>
|
||||||
</groups>
|
</groups>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<!-- 胸部组织,包含骨骼和各类重点维生器官 -->
|
<!-- 胸部组织,包含骨骼和各类重点维生器官 -->
|
||||||
<li>
|
<li>
|
||||||
<def>ARA_Sternum</def>
|
<def>ARA_Sternum</def>
|
||||||
<coverage>0.036</coverage>
|
<coverage>0</coverage>
|
||||||
<groups>
|
<groups>
|
||||||
<li>Torso</li>
|
<li>Torso</li>
|
||||||
</groups>
|
</groups>
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
<!-- 尾部组织群 -->
|
<!-- 尾部组织群 -->
|
||||||
<li>
|
<li>
|
||||||
<def>ARA_Tail</def>
|
<def>ARA_Tail</def>
|
||||||
<coverage>0.025</coverage>
|
<coverage>0</coverage>
|
||||||
<height>Bottom</height>
|
<height>Bottom</height>
|
||||||
<depth>Inside</depth>
|
<depth>Inside</depth>
|
||||||
<groups>
|
<groups>
|
||||||
@@ -346,6 +346,7 @@
|
|||||||
<flipGraphic>true</flipGraphic>
|
<flipGraphic>true</flipGraphic>
|
||||||
<groups>
|
<groups>
|
||||||
<li>Hands</li>
|
<li>Hands</li>
|
||||||
|
<li>HeadClaw</li>
|
||||||
</groups>
|
</groups>
|
||||||
<parts>
|
<parts>
|
||||||
<li>
|
<li>
|
||||||
@@ -401,6 +402,7 @@
|
|||||||
<flipGraphic>true</flipGraphic>
|
<flipGraphic>true</flipGraphic>
|
||||||
<groups>
|
<groups>
|
||||||
<li>Hands</li>
|
<li>Hands</li>
|
||||||
|
<li>HeadClaw</li>
|
||||||
</groups>
|
</groups>
|
||||||
<parts>
|
<parts>
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
<defName>ARA_InteractiveEggSac</defName>
|
<defName>ARA_InteractiveEggSac</defName>
|
||||||
<label>可交互的虫卵囊</label>
|
<label>可交互的虫卵囊</label>
|
||||||
<description>一个黏滑的囊状物,可以通过交互来孵化特定的昆虫。</description>
|
<description>一个黏滑的囊状物,可以通过交互来孵化特定的昆虫。</description>
|
||||||
<thingClass>Building</thingClass>
|
<thingClass>ArachnaeSwarm.Building_Incubator</thingClass>
|
||||||
<category>Building</category>
|
<category>Building</category>
|
||||||
<size>(1,1)</size>
|
<size>(1,1)</size>
|
||||||
<graphicData>
|
<graphicData>
|
||||||
<texPath>Things/Building/EggSac</texPath>
|
<texPath>Things/Building/EggSac</texPath>
|
||||||
<graphicClass>Graphic_Random</graphicClass>
|
<graphicClass>Graphic_Random</graphicClass>
|
||||||
<drawSize>(1.5,1.5)</drawSize>
|
<drawSize>(1.5,1.5)</drawSize>
|
||||||
</graphicData>
|
</graphicData>
|
||||||
<altitudeLayer>Building</altitudeLayer>
|
<altitudeLayer>Building</altitudeLayer>
|
||||||
<passability>PassThroughOnly</passability>
|
<passability>PassThroughOnly</passability>
|
||||||
@@ -20,39 +20,44 @@
|
|||||||
<tickerType>Normal</tickerType>
|
<tickerType>Normal</tickerType>
|
||||||
<terrainAffordanceNeeded>Light</terrainAffordanceNeeded>
|
<terrainAffordanceNeeded>Light</terrainAffordanceNeeded>
|
||||||
<statBases>
|
<statBases>
|
||||||
<MaxHitPoints>200</MaxHitPoints>
|
<MaxHitPoints>200</MaxHitPoints>
|
||||||
<Flammability>0.4</Flammability>
|
<Flammability>0.4</Flammability>
|
||||||
<Beauty>-6</Beauty>
|
<Beauty>-6</Beauty>
|
||||||
</statBases>
|
</statBases>
|
||||||
<building>
|
<building>
|
||||||
<isInert>true</isInert>
|
<isInert>true</isInert>
|
||||||
<claimable>false</claimable>
|
<claimable>false</claimable>
|
||||||
<deconstructible>false</deconstructible>
|
<deconstructible>false</deconstructible>
|
||||||
<repairable>false</repairable>
|
<repairable>false</repairable>
|
||||||
<quickTargetable>true</quickTargetable>
|
<quickTargetable>true</quickTargetable>
|
||||||
<isTargetable>true</isTargetable>
|
<isTargetable>true</isTargetable>
|
||||||
<expandHomeArea>false</expandHomeArea>
|
<expandHomeArea>false</expandHomeArea>
|
||||||
</building>
|
</building>
|
||||||
|
<hatchingGraphicData>
|
||||||
|
<texPath>Things/Building/Natural/Hive</texPath>
|
||||||
|
<graphicClass>Graphic_Random</graphicClass>
|
||||||
|
<drawSize>1.6</drawSize>
|
||||||
|
</hatchingGraphicData>
|
||||||
<comps>
|
<comps>
|
||||||
<li Class="CompProperties_Glower">
|
<li Class="CompProperties_Glower">
|
||||||
<glowRadius>6</glowRadius>
|
<glowRadius>6</glowRadius>
|
||||||
<glowColor>(113,141,117,0)</glowColor>
|
<glowColor>(113,141,117,0)</glowColor>
|
||||||
</li>
|
</li>
|
||||||
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
|
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
|
||||||
<pawnKinds>
|
<pawnKinds>
|
||||||
<li>Megascarab</li>
|
<li>Megascarab</li>
|
||||||
<li>Spelopede</li>
|
<li>Spelopede</li>
|
||||||
<li>Megaspider</li>
|
<li>Megaspider</li>
|
||||||
</pawnKinds>
|
</pawnKinds>
|
||||||
<whitelist>
|
<whitelist>
|
||||||
<li>ARA_ArachnaeQueen</li>
|
<li>ARA_ArachnaeQueen</li>
|
||||||
</whitelist>
|
</whitelist>
|
||||||
<delay>300</delay> <!-- 5 seconds -->
|
<delay>300</delay> <!-- 5 seconds -->
|
||||||
<destroyOnSpawn>true</destroyOnSpawn>
|
<destroyOnSpawn>true</destroyOnSpawn>
|
||||||
</li>
|
</li>
|
||||||
<li Class="CompProperties_SpawnEffecterOnDestroy">
|
<li Class="CompProperties_SpawnEffecterOnDestroy">
|
||||||
<effect>CocoonDestroyed</effect>
|
<effect>CocoonDestroyed</effect>
|
||||||
</li>
|
</li>
|
||||||
</comps>
|
</comps>
|
||||||
</ThingDef>
|
</ThingDef>
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,9 @@
|
|||||||
<Compile Include="JobDriver_Incubate.cs" />
|
<Compile Include="JobDriver_Incubate.cs" />
|
||||||
<Compile Include="CompProperties_AbilitySprayLiquidMulti.cs" />
|
<Compile Include="CompProperties_AbilitySprayLiquidMulti.cs" />
|
||||||
<Compile Include="CompAbilityEffect_SprayLiquidMulti.cs" />
|
<Compile Include="CompAbilityEffect_SprayLiquidMulti.cs" />
|
||||||
|
<Compile Include="Building_Incubator.cs" />
|
||||||
<Compile Include="Hediffs\Hediff_CurseFlame.cs" />
|
<Compile Include="Hediffs\Hediff_CurseFlame.cs" />
|
||||||
|
<Compile Include="CompAbilityEffect_NeedCost.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
34
Source/ArachnaeSwarm/Building_Incubator.cs
Normal file
34
Source/ArachnaeSwarm/Building_Incubator.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace ArachnaeSwarm
|
||||||
|
{
|
||||||
|
public class Building_Incubator : Building
|
||||||
|
{
|
||||||
|
public CompSpawnPawnFromList SpawnComp => GetComp<CompSpawnPawnFromList>();
|
||||||
|
|
||||||
|
public GraphicData hatchingGraphicData;
|
||||||
|
private Graphic hatchingGraphic;
|
||||||
|
|
||||||
|
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||||
|
{
|
||||||
|
base.SpawnSetup(map, respawningAfterLoad);
|
||||||
|
if (hatchingGraphicData != null)
|
||||||
|
{
|
||||||
|
hatchingGraphic = hatchingGraphicData.Graphic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Graphic Graphic
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (SpawnComp != null && SpawnComp.IsHatching && hatchingGraphic != null)
|
||||||
|
{
|
||||||
|
return hatchingGraphic;
|
||||||
|
}
|
||||||
|
return base.Graphic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Source/ArachnaeSwarm/CompAbilityEffect_NeedCost.cs
Normal file
54
Source/ArachnaeSwarm/CompAbilityEffect_NeedCost.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using RimWorld;
|
||||||
|
using RimWorld.Planet;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace ArachnaeSwarm
|
||||||
|
{
|
||||||
|
public class CompProperties_AbilityNeedCost : CompProperties_AbilityEffect
|
||||||
|
{
|
||||||
|
public NeedDef needDef;
|
||||||
|
public float needCost;
|
||||||
|
public string failMessage;
|
||||||
|
|
||||||
|
public CompProperties_AbilityNeedCost()
|
||||||
|
{
|
||||||
|
compClass = typeof(CompAbilityEffect_NeedCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CompAbilityEffect_NeedCost : CompAbilityEffect
|
||||||
|
{
|
||||||
|
public new CompProperties_AbilityNeedCost Props => (CompProperties_AbilityNeedCost)props;
|
||||||
|
|
||||||
|
public override bool GizmoDisabled(out string reason)
|
||||||
|
{
|
||||||
|
Pawn caster = parent.pawn;
|
||||||
|
if (caster != null && caster.needs != null)
|
||||||
|
{
|
||||||
|
if (caster.needs.TryGetNeed(Props.needDef, out Need need))
|
||||||
|
{
|
||||||
|
if (need.CurLevel < Props.needCost)
|
||||||
|
{
|
||||||
|
reason = Props.failMessage;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reason = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||||
|
{
|
||||||
|
base.Apply(target, dest);
|
||||||
|
Pawn caster = parent.pawn;
|
||||||
|
if (caster != null && caster.needs != null)
|
||||||
|
{
|
||||||
|
if (caster.needs.TryGetNeed(Props.needDef, out Need need))
|
||||||
|
{
|
||||||
|
need.CurLevel -= Props.needCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ namespace ArachnaeSwarm
|
|||||||
private int spawnUntilTick = -1;
|
private int spawnUntilTick = -1;
|
||||||
private PawnKindDef spawningPawnKind;
|
private PawnKindDef spawningPawnKind;
|
||||||
private PawnKindDef selectedPawnKind;
|
private PawnKindDef selectedPawnKind;
|
||||||
|
public bool IsHatching => spawnUntilTick > 0;
|
||||||
|
|
||||||
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
|
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
|
||||||
{
|
{
|
||||||
@@ -40,6 +41,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void StartIncubation()
|
public void StartIncubation()
|
||||||
{
|
{
|
||||||
spawningPawnKind = selectedPawnKind;
|
spawningPawnKind = selectedPawnKind;
|
||||||
@@ -55,6 +57,8 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void SpawnPawn(PawnKindDef pawnKind)
|
private void SpawnPawn(PawnKindDef pawnKind)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -71,34 +75,38 @@ namespace ArachnaeSwarm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
|
int count = Props.spawnCount.RandomInRange;
|
||||||
if (pawn == null)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}.");
|
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
|
||||||
return;
|
if (pawn == null)
|
||||||
}
|
|
||||||
|
|
||||||
if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null)
|
|
||||||
{
|
|
||||||
Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}.");
|
|
||||||
if (!pawn.Destroyed)
|
|
||||||
{
|
{
|
||||||
pawn.Destroy();
|
Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}.");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Props.lordJob != null)
|
if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob);
|
Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}.");
|
||||||
Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map);
|
if (!pawn.Destroyed)
|
||||||
lord.AddPawn(pawn);
|
{
|
||||||
|
pawn.Destroy();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
catch (System.Exception e)
|
|
||||||
|
if (Props.lordJob != null)
|
||||||
{
|
{
|
||||||
Log.Error($"CompSpawnPawnFromList: Error creating LordJob {Props.lordJob?.Name ?? "null"} or assigning pawn {pawn}. Exception: {e}");
|
try
|
||||||
|
{
|
||||||
|
LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob);
|
||||||
|
Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map);
|
||||||
|
lord.AddPawn(pawn);
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Log.Error($"CompSpawnPawnFromList: Error creating LordJob {Props.lordJob?.Name ?? "null"} or assigning pawn {pawn}. Exception: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +122,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string CompInspectStringExtra()
|
public override string CompInspectStringExtra()
|
||||||
{
|
{
|
||||||
if (spawnUntilTick > 0)
|
if (spawnUntilTick > 0)
|
||||||
@@ -136,6 +145,7 @@ namespace ArachnaeSwarm
|
|||||||
base.PostExposeData();
|
base.PostExposeData();
|
||||||
Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
|
Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
|
||||||
Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind");
|
Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind");
|
||||||
|
Scribe_Defs.Look(ref selectedPawnKind, "selectedPawnKind");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
38
Source/Documents/Project_Summary.md
Normal file
38
Source/Documents/Project_Summary.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# 项目:可交互的虫卵囊
|
||||||
|
|
||||||
|
## 1. 核心目标
|
||||||
|
|
||||||
|
创建一个可交互的虫卵囊,它允许一个特定的 Pawn(阿拉克涅女皇种)通过右键菜单与它交互,从一个可配置的列表中选择一个 Pawn,并在经过一段可配置的延迟后,生成这个 Pawn。
|
||||||
|
|
||||||
|
## 2. 已完成的功能
|
||||||
|
|
||||||
|
* **创建了新的 VS 项目**: [`ArachnaeSwarm.csproj`](Source/ArachnaeSwarm/ArachnaeSwarm.csproj)
|
||||||
|
* **实现了核心的生成逻辑**:
|
||||||
|
* `CompProperties_SpawnPawnFromList.cs`: 定义了 XML 中可配置的属性,包括:
|
||||||
|
* `pawnKinds`: 可生成的 Pawn 列表。
|
||||||
|
* `whitelist`: 可以与虫卵囊交互的 Pawn 列表。
|
||||||
|
* `delay`: 孵化延迟。
|
||||||
|
* `spawnCount`: 生成数量。
|
||||||
|
* `destroyOnSpawn`: 生成后是否摧毁自身。
|
||||||
|
* `lordJob`: 生成的 Pawn 要执行的集体任务。
|
||||||
|
* `CompSpawnPawnFromList.cs`: 实现了核心的生成逻辑,包括:
|
||||||
|
* 生成右键菜单。
|
||||||
|
* 处理孵化倒计时。
|
||||||
|
* 生成指定数量的 Pawn。
|
||||||
|
* 在检查面板上显示孵化状态和提示信息。
|
||||||
|
* **实现了交互的 Job**:
|
||||||
|
* `ARA_Jobs.xml`: 定义了 `ARA_IncubateJob`。
|
||||||
|
* `JobDriver_Incubate.cs`: 实现了让 Pawn 走到虫卵囊旁边并启动孵化过程的逻辑。
|
||||||
|
* **实现了动态的图形切换**:
|
||||||
|
* `Building_Incubator.cs`: 创建了一个新的建筑基类,它会根据虫卵囊是否正在孵化来动态地改变自身的图形。
|
||||||
|
* **创建了测试用的 Defs**:
|
||||||
|
* `ARA_InteractiveEggSac.xml`: 定义了一个可交互的虫卵囊,用于在游戏中测试新功能。
|
||||||
|
* `ArachnaeSwarm_Keys.xml`: 定义了相关的本地化 `key`。
|
||||||
|
|
||||||
|
## 3. 当前状态
|
||||||
|
|
||||||
|
目前,项目已经基本完成了所有的核心功能,并且能够成功编译。但是,在最后一次构建时,我们遇到了一个编译错误,导致我们无法进行最终的测试。
|
||||||
|
|
||||||
|
## 4. 下一步计划
|
||||||
|
|
||||||
|
解决当前的编译错误,并成功构建项目,以便在游戏中进行最终的测试。
|
||||||
Reference in New Issue
Block a user