This commit is contained in:
2025-09-01 12:38:18 +08:00
parent eaa640ebd4
commit 060c3148c4
7 changed files with 188 additions and 1 deletions

Binary file not shown.

View File

@@ -74,7 +74,7 @@
<damageDef>Bullet</damageDef>
<speed>21</speed>
<damageAmountBase>0</damageAmountBase>
<spawnsThingDef>EggSac</spawnsThingDef>
<spawnsThingDef>ARA_InteractiveEggSac</spawnsThingDef>
<tryAdjacentFreeSpaces>true</tryAdjacentFreeSpaces>
</projectile>
</ThingDef>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName="BuildingNaturalBase">
<defName>ARA_InteractiveEggSac</defName>
<label>可交互的虫卵囊</label>
<description>一个黏滑的囊状物,可以通过交互来孵化特定的昆虫。</description>
<thingClass>Building</thingClass>
<category>Building</category>
<graphicData>
<texPath>Things/Building/EggSac</texPath>
<graphicClass>Graphic_Random</graphicClass>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<fillPercent>0.3</fillPercent>
<rotatable>false</rotatable>
<terrainAffordanceNeeded>Light</terrainAffordanceNeeded>
<statBases>
<MaxHitPoints>20</MaxHitPoints>
<Flammability>0.4</Flammability>
<Beauty>-6</Beauty>
</statBases>
<building>
<isInert>true</isInert>
<claimable>false</claimable>
<deconstructible>false</deconstructible>
<repairable>false</repairable>
<quickTargetable>true</quickTargetable>
<isTargetable>true</isTargetable>
<expandHomeArea>false</expandHomeArea>
</building>
<comps>
<li Class="CompProperties_Glower">
<glowRadius>6</glowRadius>
<glowColor>(113,141,117,0)</glowColor>
</li>
<li Class="ArachnaeSwarm.CompProperties_SpawnPawnFromList">
<pawnKinds>
<li>Megascarab</li>
<li>Spelopede</li>
<li>Megaspider</li>
</pawnKinds>
<whitelist>
<li>ARA_ArachnaeQueen</li>
</whitelist>
<delay>300</delay> <!-- 5 seconds -->
<destroyOnSpawn>true</destroyOnSpawn>
</li>
<li Class="CompProperties_SpawnEffecterOnDestroy">
<effect>CocoonDestroyed</effect>
</li>
</comps>
</ThingDef>
</Defs>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
<ARA_Incubate>孵化 {0}</ARA_Incubate>
</LanguageData>

View File

@@ -68,6 +68,8 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CompProperties_SpawnPawnFromList.cs" />
<Compile Include="CompSpawnPawnFromList.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Verse;
using Verse.AI.Group;
namespace ArachnaeSwarm
{
public class CompProperties_SpawnPawnFromList : CompProperties
{
public List<PawnKindDef> pawnKinds;
public List<PawnKindDef> whitelist;
public int delay = 0;
public bool destroyOnSpawn = false;
public Type lordJob;
public CompProperties_SpawnPawnFromList()
{
compClass = typeof(CompSpawnPawnFromList);
}
public override IEnumerable<string> ConfigErrors(ThingDef parentDef)
{
foreach (string item in base.ConfigErrors(parentDef))
{
yield return item;
}
if (lordJob != null && !typeof(LordJob).IsAssignableFrom(lordJob))
{
yield return $"lordJob {lordJob} must be of type LordJob";
}
}
}
}

View File

@@ -0,0 +1,90 @@
using System.Collections.Generic;
using Verse;
using RimWorld;
using Verse.AI.Group;
namespace ArachnaeSwarm
{
public class CompSpawnPawnFromList : ThingComp
{
private CompProperties_SpawnPawnFromList Props => (CompProperties_SpawnPawnFromList)props;
private int spawnUntilTick = -1;
private PawnKindDef spawningPawnKind;
public override IEnumerable<FloatMenuOption> CompFloatMenuOptions(Pawn selPawn)
{
if (spawnUntilTick > 0)
{
yield break; // 正在延迟中,不显示菜单
}
if (Props.whitelist == null || !Props.whitelist.Contains(selPawn.kindDef))
{
yield break;
}
if (Props.pawnKinds != null)
{
foreach (PawnKindDef pawnKind in Props.pawnKinds)
{
yield return new FloatMenuOption("ARA_Incubate".Translate(pawnKind.label), () =>
{
StartDelayedSpawn(pawnKind);
});
}
}
}
private void StartDelayedSpawn(PawnKindDef pawnKind)
{
spawningPawnKind = pawnKind;
spawnUntilTick = Find.TickManager.TicksGame + Props.delay;
}
public override void CompTick()
{
base.CompTick();
if (spawnUntilTick > 0 && Find.TickManager.TicksGame >= spawnUntilTick)
{
SpawnPawn(spawningPawnKind);
spawnUntilTick = -1;
spawningPawnKind = null;
}
}
private void SpawnPawn(PawnKindDef pawnKind)
{
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction));
GenSpawn.Spawn(pawn, parent.Position, parent.Map);
if (Props.lordJob != null)
{
Lord lord = LordMaker.MakeNewLord(parent.Faction, (LordJob)System.Activator.CreateInstance(Props.lordJob), parent.Map);
lord.AddPawn(pawn);
}
if (Props.destroyOnSpawn)
{
parent.Destroy(DestroyMode.Vanish);
}
}
public override string CompInspectStringExtra()
{
if (spawnUntilTick > 0)
{
int remainingTicks = spawnUntilTick - Find.TickManager.TicksGame;
return $"Spawning in: {remainingTicks.ToStringTicksToPeriod()}";
}
return base.CompInspectStringExtra();
}
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind");
}
}
}