diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 59b7d73..29adbd5 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/AbilityDefs/ARA_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml index cd192df..c72e24d 100644 --- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml @@ -26,6 +26,15 @@
  • ARA_Proj_EggSac
  • +
  • + Food + 4 + 食物不足 +
  • +
  • + ARA_Ovary + 卵巢受损或缺失,无法生育 +
  • @@ -59,6 +68,11 @@ 32 3 +
  • + Food + 0.5 + 食物不足 +
  • diff --git a/1.6/1.6/Defs/BodyAndPartDefs/ARA_Bodyparts.xml b/1.6/1.6/Defs/BodyAndPartDefs/ARA_Bodyparts.xml index 7a842ab..844e66b 100644 --- a/1.6/1.6/Defs/BodyAndPartDefs/ARA_Bodyparts.xml +++ b/1.6/1.6/Defs/BodyAndPartDefs/ARA_Bodyparts.xml @@ -14,7 +14,7 @@
  • ARA_Dorsum - 0.036 + 0
  • Torso
  • @@ -42,7 +42,7 @@
  • ARA_Sternum - 0.036 + 0
  • Torso
  • @@ -154,7 +154,7 @@
  • ARA_Tail - 0.025 + 0 Bottom Inside @@ -355,6 +355,7 @@ true
  • Hands
  • +
  • HeadClaw
  • @@ -410,6 +411,7 @@ true
  • Hands
  • +
  • HeadClaw
  • diff --git a/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml b/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml index 31c8b5c..27c43c8 100644 --- a/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml +++ b/1.6/1.6/Defs/Thing_building/ARA_InteractiveEggSac.xml @@ -33,6 +33,7 @@ true false +
  • 6 @@ -47,8 +48,13 @@
  • ARA_ArachnaeQueen
  • - 300 + 300 true + + Things/Building/Natural/Hive + Graphic_Random + 1.6 +
  • CocoonDestroyed diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 1ee6c58..115002f 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -73,7 +73,10 @@ + + + diff --git a/Source/ArachnaeSwarm/Building_Incubator.cs b/Source/ArachnaeSwarm/Building_Incubator.cs new file mode 100644 index 0000000..cb2e948 --- /dev/null +++ b/Source/ArachnaeSwarm/Building_Incubator.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using Verse; + +namespace ArachnaeSwarm +{ + public class Building_Incubator : Building + { + public CompSpawnPawnFromList SpawnComp => GetComp(); + + public override Graphic Graphic + { + get + { + if (SpawnComp != null && SpawnComp.IsHatching && SpawnComp.Props.hatchingGraphicData != null) + { + return SpawnComp.Props.hatchingGraphicData.Graphic; + } + return base.Graphic; + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/CompAbilityEffect_BodyPartCheck.cs b/Source/ArachnaeSwarm/CompAbilityEffect_BodyPartCheck.cs new file mode 100644 index 0000000..91ab139 --- /dev/null +++ b/Source/ArachnaeSwarm/CompAbilityEffect_BodyPartCheck.cs @@ -0,0 +1,49 @@ +using System.Linq; +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + public class CompProperties_AbilityBodyPartCheck : CompProperties_AbilityEffect + { + public BodyPartDef requiredPart; + public float minimumHealth = 0.8f; + public string failMessage = "Missing or damaged body part."; + + public CompProperties_AbilityBodyPartCheck() + { + compClass = typeof(CompAbilityEffect_BodyPartCheck); + } + } + + public class CompAbilityEffect_BodyPartCheck : CompAbilityEffect + { + public new CompProperties_AbilityBodyPartCheck Props => (CompProperties_AbilityBodyPartCheck)props; + + public override bool GizmoDisabled(out string reason) + { + Pawn caster = parent.pawn; + if (caster != null && caster.health != null && caster.health.hediffSet != null) + { + var part = caster.health.hediffSet.GetNotMissingParts() + .FirstOrDefault(p => p.def == Props.requiredPart); + + if (part == null) + { + reason = Props.failMessage; + return true; + } + + float partHealth = caster.health.hediffSet.GetPartHealth(part) / part.def.GetMaxHealth(caster); + if (partHealth < Props.minimumHealth) + { + reason = Props.failMessage; + return true; + } + } + + reason = null; + return false; + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/CompAbilityEffect_NeedCost.cs b/Source/ArachnaeSwarm/CompAbilityEffect_NeedCost.cs new file mode 100644 index 0000000..41613ba --- /dev/null +++ b/Source/ArachnaeSwarm/CompAbilityEffect_NeedCost.cs @@ -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; + } + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/CompProperties_SpawnPawnFromList.cs b/Source/ArachnaeSwarm/CompProperties_SpawnPawnFromList.cs index efef87f..c69bf18 100644 --- a/Source/ArachnaeSwarm/CompProperties_SpawnPawnFromList.cs +++ b/Source/ArachnaeSwarm/CompProperties_SpawnPawnFromList.cs @@ -13,6 +13,7 @@ namespace ArachnaeSwarm public bool destroyOnSpawn = false; public IntRange spawnCount = new IntRange(1, 1); public Type lordJob; + public GraphicData hatchingGraphicData; public CompProperties_SpawnPawnFromList() { diff --git a/Source/ArachnaeSwarm/CompSpawnPawnFromList.cs b/Source/ArachnaeSwarm/CompSpawnPawnFromList.cs index 07027e4..ce05723 100644 --- a/Source/ArachnaeSwarm/CompSpawnPawnFromList.cs +++ b/Source/ArachnaeSwarm/CompSpawnPawnFromList.cs @@ -13,6 +13,7 @@ namespace ArachnaeSwarm private int spawnUntilTick = -1; private PawnKindDef spawningPawnKind; private PawnKindDef selectedPawnKind; + public bool IsHatching => spawnUntilTick > 0; public override IEnumerable CompFloatMenuOptions(Pawn selPawn) { @@ -40,6 +41,7 @@ namespace ArachnaeSwarm } } + public void StartIncubation() { spawningPawnKind = selectedPawnKind; @@ -55,6 +57,8 @@ namespace ArachnaeSwarm } } + + private void SpawnPawn(PawnKindDef pawnKind) { try @@ -71,34 +75,38 @@ namespace ArachnaeSwarm return; } - Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction)); - if (pawn == null) + int count = Props.spawnCount.RandomInRange; + for (int i = 0; i < count; i++) { - Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}."); - return; - } - - if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null) - { - Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}."); - if (!pawn.Destroyed) + Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction)); + if (pawn == null) { - 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) - { - try + if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null) { - LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob); - Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map); - lord.AddPawn(pawn); + Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}."); + if (!pawn.Destroyed) + { + 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() { if (spawnUntilTick > 0) @@ -136,6 +145,7 @@ namespace ArachnaeSwarm base.PostExposeData(); Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1); Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind"); + Scribe_Defs.Look(ref selectedPawnKind, "selectedPawnKind"); } } } \ No newline at end of file diff --git a/Source/Documents/Project_Summary.md b/Source/Documents/Project_Summary.md new file mode 100644 index 0000000..605fe2a --- /dev/null +++ b/Source/Documents/Project_Summary.md @@ -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. 下一步计划 + +解决当前的编译错误,并成功构建项目,以便在游戏中进行最终的测试。 \ No newline at end of file