This commit is contained in:
Tourswen
2025-09-06 13:39:07 +08:00
5 changed files with 33 additions and 34 deletions

Binary file not shown.

View File

@@ -249,7 +249,6 @@
<lifespanTicks>1200000</lifespanTicks>
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>6</spawnRadius>
</li>
@@ -425,7 +424,6 @@
</building>
<comps>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>3</spawnRadius>
</li>
@@ -482,7 +480,6 @@
</building>
<comps>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>6</spawnRadius>
</li>

View File

@@ -86,7 +86,6 @@
<spawnRadius>5</spawnRadius>
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>60</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>4.6</spawnRadius>
</li>
@@ -147,7 +146,6 @@
<spawnRadius>5</spawnRadius>
</li>
<li Class="ArachnaeSwarm.CompProperties_DelayedTerrainSpawn">
<delayTicks>15</delayTicks> <!-- 60 ticks = 1 second -->
<terrainToSpawn>ARA_InsectCreep</terrainToSpawn>
<spawnRadius>8</spawnRadius>
</li>

View File

@@ -3,55 +3,55 @@ using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// Spawns terrain around the parent thing instantly upon spawning.
/// Despite the class name, this component does NOT use any delay or Tick-based updates.
/// The logic runs only ONCE during the PostSpawnSetup phase for maximum performance.
/// There is no background counting or any process that continues after the spawn.
/// </summary>
public class CompDelayedTerrainSpawn : ThingComp
{
private CompProperties_DelayedTerrainSpawn Props => (CompProperties_DelayedTerrainSpawn)props;
private int ticksToSpawn;
private bool started;
/// <summary>
/// This is the ONLY time this component's logic runs. It is called by the game when the object is created on the map.
/// </summary>
/// <param name="respawningAfterLoad">True if loading from a save, which we will ignore.</param>
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
StartDelayedSpawn();
}
public override void CompTick()
{
base.CompTick();
if (started)
// We only run this logic for brand new objects, not for objects loaded from a save file.
if (!respawningAfterLoad)
{
ticksToSpawn--;
if (ticksToSpawn == 0)
{
DoTerrainSpawn();
}
DoTerrainSpawn();
}
}
private void StartDelayedSpawn()
{
started = true;
ticksToSpawn = Props.delayTicks;
}
/// <summary>
/// This method performs the one-time action of spawning terrain.
/// It includes strong safety checks to prevent errors if the object is not fully initialized.
/// </summary>
private void DoTerrainSpawn()
{
if (parent.Destroyed)
// Safety Check: We ensure the object and its map exist before trying to do anything.
// If these conditions are not met, the method does nothing and simply stops.
if (parent == null || parent.Destroyed || parent.Map == null || Props.terrainToSpawn == null)
{
return;
return; // Stop execution if anything is not ready.
}
if (Props.terrainToSpawn != null)
// The core logic: iterate through nearby cells and change their terrain.
foreach (IntVec3 current in GenRadial.RadialCellsAround(parent.Position, Props.spawnRadius, true))
{
foreach (IntVec3 current in GenRadial.RadialCellsAround(parent.Position, Props.spawnRadius, true))
if (current.InBounds(parent.Map) && current.Walkable(parent.Map))
{
if (current.InBounds(parent.Map) && current.Walkable(parent.Map))
{
parent.Map.terrainGrid.SetTerrain(current, Props.terrainToSpawn);
}
parent.Map.terrainGrid.SetTerrain(current, Props.terrainToSpawn);
}
}
}
// NOTICE: There is NO CompTick() method here. This component does not perform any updates after it has spawned.
// NOTICE: There is NO ExposeData() method for timers because there are NO timers to save.
}
}

View File

@@ -2,14 +2,18 @@ using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// Properties for the CompDelayedTerrainSpawn component.
/// The logic has been optimized to run instantly on spawn, so the 'delayTicks' field is no longer used.
/// </summary>
public class CompProperties_DelayedTerrainSpawn : CompProperties
{
public int delayTicks = 0;
public TerrainDef terrainToSpawn;
public float spawnRadius = 0f;
public CompProperties_DelayedTerrainSpawn()
{
// The component logic now runs instantly, but the class name is kept for compatibility.
compClass = typeof(CompDelayedTerrainSpawn);
}
}