11
This commit is contained in:
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using RimWorld;
|
using RimWorld;
|
||||||
@@ -66,14 +66,14 @@ namespace ArachnaeSwarm
|
|||||||
this.graceTicks--;
|
this.graceTicks--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.Props.hungerRelative && this.pawn.Starving())
|
if (this.Props.hungerRelative && IsHungry(this.pawn, this.myDebug))
|
||||||
{
|
{
|
||||||
int num = (int)(this.RandomGraceDays() * 60000f);
|
int num = (int)(this.RandomGraceDays() * 60000f);
|
||||||
this.hungerReset++;
|
this.hungerReset++;
|
||||||
this.graceTicks = num;
|
this.graceTicks = num;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.Props.healthRelative && this.pawn.Starving())
|
if (this.Props.healthRelative && IsInjured(this.pawn, this.myDebug))
|
||||||
{
|
{
|
||||||
int num2 = (int)(this.RandomGraceDays() * 60000f);
|
int num2 = (int)(this.RandomGraceDays() * 60000f);
|
||||||
this.healthReset++;
|
this.healthReset++;
|
||||||
@@ -350,7 +350,7 @@ namespace ArachnaeSwarm
|
|||||||
|
|
||||||
if (this.Props.animalThing)
|
if (this.Props.animalThing)
|
||||||
{
|
{
|
||||||
// 动物生成逻辑保持不变
|
// 鍔ㄧ墿鐢熸垚閫昏緫淇濇寔涓嶅彉
|
||||||
if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP)
|
if (this.Props.spawnMaxAdjacent > 0 && pawn.Map.mapPawns.AllPawns.Where(delegate(Pawn mP)
|
||||||
{
|
{
|
||||||
ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn;
|
ThingDef defToCompare = this.Props.animalThing ? this.Props.animalToSpawn?.race : this.Props.thingToSpawn;
|
||||||
@@ -394,7 +394,7 @@ namespace ArachnaeSwarm
|
|||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (PawnUtility.ShouldSendNotificationAbout(pawn) || PawnUtility.ShouldSendNotificationAbout(pawn))
|
if (PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||||
{
|
{
|
||||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.PositiveEvent, true);
|
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.PositiveEvent, true);
|
||||||
}
|
}
|
||||||
@@ -402,10 +402,10 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 重新设计物品生成逻辑:按优先级顺序尝试
|
// 閲嶆柊璁捐鐗╁搧鐢熸垚閫昏緫锛氭寜浼樺厛绾ч『搴忓皾璇?
|
||||||
bool success = TrySpawnItemWithPriority(pawn);
|
bool success = TrySpawnItemWithPriority(pawn);
|
||||||
|
|
||||||
// === 新增:如果配置了销毁随机部位,在成功生成物品后执行 ===
|
// === 鏂板锛氬鏋滈厤缃簡閿€姣侀殢鏈洪儴浣嶏紝鍦ㄦ垚鍔熺敓鎴愮墿鍝佸悗鎵ц ===
|
||||||
if (success && this.Props.destroyRandomBodyPart)
|
if (success && this.Props.destroyRandomBodyPart)
|
||||||
{
|
{
|
||||||
DestroyRandomBodyPart(pawn);
|
DestroyRandomBodyPart(pawn);
|
||||||
@@ -415,7 +415,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:销毁随机身体部位(参考 CompAbilityEffect_DestroyOwnBodyPart)
|
// 鏂板锛氶攢姣侀殢鏈鸿韩浣撻儴浣嶏紙鍙傝€?CompAbilityEffect_DestroyOwnBodyPart锛?
|
||||||
private void DestroyRandomBodyPart(Pawn pawn)
|
private void DestroyRandomBodyPart(Pawn pawn)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -426,7 +426,7 @@ namespace ArachnaeSwarm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有可以销毁的身体部位
|
// 鑾峰彇鎵€鏈夊彲浠ラ攢姣佺殑韬綋閮ㄤ綅
|
||||||
List<BodyPartRecord> possibleParts = GetDestroyableBodyParts(pawn);
|
List<BodyPartRecord> possibleParts = GetDestroyableBodyParts(pawn);
|
||||||
|
|
||||||
if (possibleParts.Count == 0)
|
if (possibleParts.Count == 0)
|
||||||
@@ -435,7 +435,7 @@ namespace ArachnaeSwarm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 随机选择一个部位
|
// 闅忔満閫夋嫨涓€涓儴浣?
|
||||||
BodyPartRecord partToDestroy = possibleParts.RandomElement();
|
BodyPartRecord partToDestroy = possibleParts.RandomElement();
|
||||||
|
|
||||||
if (partToDestroy == null)
|
if (partToDestroy == null)
|
||||||
@@ -444,10 +444,10 @@ namespace ArachnaeSwarm
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录部位名称
|
// 璁板綍閮ㄤ綅鍚嶇О
|
||||||
string partName = partToDestroy.def?.label ?? "未知部位";
|
string partName = partToDestroy.def?.label ?? "鏈煡閮ㄤ綅";
|
||||||
|
|
||||||
// 添加缺失部位hediff
|
// 娣诲姞缂哄け閮ㄤ綅hediff
|
||||||
pawn.health.AddHediff(HediffDefOf.MissingBodyPart, partToDestroy);
|
pawn.health.AddHediff(HediffDefOf.MissingBodyPart, partToDestroy);
|
||||||
|
|
||||||
Warn($"Destroyed {partName} on {pawn.LabelShort}", this.myDebug);
|
Warn($"Destroyed {partName} on {pawn.LabelShort}", this.myDebug);
|
||||||
@@ -458,7 +458,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:获取可以销毁的身体部位列表
|
// 鏂板锛氳幏鍙栧彲浠ラ攢姣佺殑韬綋閮ㄤ綅鍒楄〃
|
||||||
private List<BodyPartRecord> GetDestroyableBodyParts(Pawn pawn)
|
private List<BodyPartRecord> GetDestroyableBodyParts(Pawn pawn)
|
||||||
{
|
{
|
||||||
List<BodyPartRecord> destroyableParts = new List<BodyPartRecord>();
|
List<BodyPartRecord> destroyableParts = new List<BodyPartRecord>();
|
||||||
@@ -466,22 +466,25 @@ namespace ArachnaeSwarm
|
|||||||
if (pawn?.health?.hediffSet == null)
|
if (pawn?.health?.hediffSet == null)
|
||||||
return destroyableParts;
|
return destroyableParts;
|
||||||
|
|
||||||
// 获取所有身体部位
|
// 鑾峰彇鎵€鏈夎韩浣撻儴浣?
|
||||||
List<BodyPartRecord> allParts = pawn.RaceProps.body.AllParts;
|
List<BodyPartRecord> allParts = pawn.RaceProps.body.AllParts;
|
||||||
|
|
||||||
foreach (BodyPartRecord part in allParts)
|
foreach (BodyPartRecord part in allParts)
|
||||||
{
|
{
|
||||||
// 排除核心部位(避免死亡)
|
// 鎺掗櫎鏍稿績閮ㄤ綅锛堥伩鍏嶆浜★級
|
||||||
if (IsCriticalBodyPart(part))
|
if (IsCriticalBodyPart(part))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 排除已经缺失的部位
|
// 鎺掗櫎宸茬粡缂哄け鐨勯儴浣?
|
||||||
if (pawn.health.hediffSet.PartIsMissing(part))
|
if (pawn.health.hediffSet.PartIsMissing(part))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 排除已经有严重伤害的部位(可选)
|
// 鎺掗櫎宸茬粡鏈変弗閲嶄激瀹崇殑閮ㄤ綅锛堝彲閫夛級
|
||||||
if (pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(part))
|
if (pawn.health.hediffSet.PartOrAnyAncestorHasDirectlyAddedParts(part))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (PartOrAnyDescendantHasDirectlyAddedParts(pawn, part))
|
||||||
|
continue;
|
||||||
|
|
||||||
destroyableParts.Add(part);
|
destroyableParts.Add(part);
|
||||||
}
|
}
|
||||||
@@ -489,34 +492,34 @@ namespace ArachnaeSwarm
|
|||||||
return destroyableParts;
|
return destroyableParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:检查是否是关键身体部位
|
// 鏂板锛氭鏌ユ槸鍚︽槸鍏抽敭韬綋閮ㄤ綅
|
||||||
private bool IsCriticalBodyPart(BodyPartRecord part)
|
private bool IsCriticalBodyPart(BodyPartRecord part)
|
||||||
{
|
{
|
||||||
if (part == null)
|
if (part == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 根据标签判断是否为关键部位
|
// 鏍规嵁鏍囩鍒ゆ柇鏄惁涓哄叧閿儴浣?
|
||||||
if (part.def.tags != null)
|
if (part.def.tags != null)
|
||||||
{
|
{
|
||||||
// 这些标签通常表示关键部位
|
// 杩欎簺鏍囩閫氬父琛ㄧず鍏抽敭閮ㄤ綅
|
||||||
if (part.def.tags.Contains(BodyPartTagDefOf.ConsciousnessSource) || // 意识源(大脑)
|
if (part.def.tags.Contains(BodyPartTagDefOf.ConsciousnessSource) || // 鎰忚瘑婧愶紙澶ц剳锛?
|
||||||
part.def.tags.Contains(BodyPartTagDefOf.BloodPumpingSource) || // 血液泵源(心脏)
|
part.def.tags.Contains(BodyPartTagDefOf.BloodPumpingSource) || // 琛€娑叉车婧愶紙蹇冭剰锛?
|
||||||
part.def.tags.Contains(BodyPartTagDefOf.BreathingSource) || // 呼吸源(肺)
|
part.def.tags.Contains(BodyPartTagDefOf.BreathingSource) || // 鍛煎惛婧愶紙鑲猴級
|
||||||
part.def.tags.Contains(BodyPartTagDefOf.MetabolismSource) // 代谢源(肝脏)
|
part.def.tags.Contains(BodyPartTagDefOf.MetabolismSource) // 浠h阿婧愶紙鑲濊剰锛?
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据深度判断(深度较深的通常是内部器官)
|
// 鏍规嵁娣卞害鍒ゆ柇锛堟繁搴﹁緝娣辩殑閫氬父鏄唴閮ㄥ櫒瀹橈級
|
||||||
if (part.depth == BodyPartDepth.Inside && part.parent == null)
|
if (part.depth == BodyPartDepth.Inside && part.parent == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:按优先级顺序尝试生成物品
|
// 鏂板锛氭寜浼樺厛绾ч『搴忓皾璇曠敓鎴愮墿鍝?
|
||||||
private bool TrySpawnItemWithPriority(Pawn pawn)
|
private bool TrySpawnItemWithPriority(Pawn pawn)
|
||||||
{
|
{
|
||||||
Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null);
|
Thing thing = ThingMaker.MakeThing(this.Props.thingToSpawn, null);
|
||||||
@@ -527,51 +530,60 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
thing.stackCount = this.calculatedQuantity;
|
thing.stackCount = this.calculatedQuantity;
|
||||||
|
|
||||||
// 记录原始物品用于校验
|
|
||||||
ThingDef originalThingDef = thing.def;
|
ThingDef originalThingDef = thing.def;
|
||||||
int originalStackCount = thing.stackCount;
|
int originalStackCount = thing.stackCount;
|
||||||
|
|
||||||
// 按优先级顺序尝试生成
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
string spawnMethod = "";
|
string spawnMethod = "";
|
||||||
|
Thing spawnedThing = null;
|
||||||
|
int addedInventoryCount = 0;
|
||||||
|
|
||||||
// 优先级1: 尝试在pawn附近空地生成
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
success = TrySpawnAtNearbyEmptyCell(pawn, thing, ref spawnMethod);
|
success = TrySpawnAtNearbyEmptyCell(pawn, thing, ref spawnMethod, out spawnedThing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优先级2: 尝试在pawn脚底生成
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
success = TrySpawnAtPawnPosition(pawn, thing, ref spawnMethod);
|
success = TrySpawnAtPawnPosition(pawn, thing, ref spawnMethod, out spawnedThing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优先级3: 尝试放入pawn物品栏
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
success = TrySpawnInInventory(pawn, thing, ref spawnMethod);
|
success = TrySpawnInInventory(pawn, thing, ref spawnMethod, out spawnedThing, out addedInventoryCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成后校验
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
bool verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, spawnMethod);
|
bool verified = VerifySpawnSuccess(
|
||||||
|
pawn,
|
||||||
// 如果校验失败且不是在物品栏中生成的,尝试在物品栏中重新生成
|
originalThingDef,
|
||||||
|
originalStackCount,
|
||||||
|
spawnMethod,
|
||||||
|
spawnedThing,
|
||||||
|
addedInventoryCount
|
||||||
|
);
|
||||||
|
|
||||||
if (!verified && spawnMethod != "inventory")
|
if (!verified && spawnMethod != "inventory")
|
||||||
{
|
{
|
||||||
Warn($"Spawn verification failed for {spawnMethod}, attempting inventory fallback", this.myDebug);
|
Warn($"Spawn verification failed for {spawnMethod}, attempting inventory fallback", this.myDebug);
|
||||||
|
|
||||||
// 重新创建物品
|
|
||||||
Thing fallbackThing = ThingMaker.MakeThing(originalThingDef, null);
|
Thing fallbackThing = ThingMaker.MakeThing(originalThingDef, null);
|
||||||
fallbackThing.stackCount = originalStackCount;
|
fallbackThing.stackCount = originalStackCount;
|
||||||
|
|
||||||
success = TrySpawnInInventory(pawn, fallbackThing, ref spawnMethod);
|
success = TrySpawnInInventory(pawn, fallbackThing, ref spawnMethod, out spawnedThing, out addedInventoryCount);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
verified = VerifySpawnSuccess(pawn, originalThingDef, originalStackCount, "inventory_fallback");
|
spawnMethod = "inventory_fallback";
|
||||||
|
verified = VerifySpawnSuccess(
|
||||||
|
pawn,
|
||||||
|
originalThingDef,
|
||||||
|
originalStackCount,
|
||||||
|
spawnMethod,
|
||||||
|
spawnedThing,
|
||||||
|
addedInventoryCount
|
||||||
|
);
|
||||||
if (!verified)
|
if (!verified)
|
||||||
{
|
{
|
||||||
Warn("Inventory fallback also failed verification", this.myDebug);
|
Warn("Inventory fallback also failed verification", this.myDebug);
|
||||||
@@ -584,9 +596,14 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
if (PawnUtility.ShouldSendNotificationAbout(pawn))
|
if (PawnUtility.ShouldSendNotificationAbout(pawn))
|
||||||
{
|
{
|
||||||
Messages.Message(this.Props.spawnVerb.Translate(pawn.Named("PAWN"), thing.Named("THING")),
|
Thing messageThing = spawnedThing ?? thing;
|
||||||
spawnMethod == "inventory" || spawnMethod == "inventory_fallback" ? pawn : thing,
|
bool spawnedInInventory = spawnMethod == "inventory" || spawnMethod == "inventory_fallback";
|
||||||
MessageTypeDefOf.PositiveEvent, true);
|
Messages.Message(
|
||||||
|
this.Props.spawnVerb.Translate(pawn.Named("PAWN"), messageThing.Named("THING")),
|
||||||
|
spawnedInInventory ? pawn : messageThing,
|
||||||
|
MessageTypeDefOf.PositiveEvent,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Warn($"Successfully spawned {originalStackCount}x {originalThingDef.defName} via {spawnMethod}", this.myDebug);
|
Warn($"Successfully spawned {originalStackCount}x {originalThingDef.defName} via {spawnMethod}", this.myDebug);
|
||||||
return true;
|
return true;
|
||||||
@@ -597,9 +614,9 @@ namespace ArachnaeSwarm
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:尝试在附近空地生成
|
private bool TrySpawnAtNearbyEmptyCell(Pawn pawn, Thing thing, ref string spawnMethod, out Thing spawnedThing)
|
||||||
private bool TrySpawnAtNearbyEmptyCell(Pawn pawn, Thing thing, ref string spawnMethod)
|
|
||||||
{
|
{
|
||||||
|
spawnedThing = null;
|
||||||
IntVec3 spawnCell;
|
IntVec3 spawnCell;
|
||||||
if (TryFindSpawnCell(out spawnCell))
|
if (TryFindSpawnCell(out spawnCell))
|
||||||
{
|
{
|
||||||
@@ -607,19 +624,21 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
thing.SetForbidden(true, true);
|
thing.SetForbidden(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GenPlace.TryPlaceThing(thing, spawnCell, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
Thing resultingThing;
|
||||||
|
if (GenPlace.TryPlaceThing(thing, spawnCell, pawn.Map, ThingPlaceMode.Direct, out resultingThing, null, null, default(Rot4)))
|
||||||
{
|
{
|
||||||
spawnMethod = "nearby_cell";
|
spawnMethod = "nearby_cell";
|
||||||
|
spawnedThing = resultingThing;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:尝试在pawn位置生成
|
private bool TrySpawnAtPawnPosition(Pawn pawn, Thing thing, ref string spawnMethod, out Thing spawnedThing)
|
||||||
private bool TrySpawnAtPawnPosition(Pawn pawn, Thing thing, ref string spawnMethod)
|
|
||||||
{
|
{
|
||||||
|
spawnedThing = null;
|
||||||
IntVec3 pawnPosition = pawn.Position;
|
IntVec3 pawnPosition = pawn.Position;
|
||||||
if (pawnPosition.IsValid && pawnPosition.Walkable(pawn.Map))
|
if (pawnPosition.IsValid && pawnPosition.Walkable(pawn.Map))
|
||||||
{
|
{
|
||||||
@@ -627,54 +646,61 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
thing.SetForbidden(true, true);
|
thing.SetForbidden(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GenPlace.TryPlaceThing(thing, pawnPosition, pawn.Map, ThingPlaceMode.Direct, null, null, default(Rot4)))
|
Thing resultingThing;
|
||||||
|
if (GenPlace.TryPlaceThing(thing, pawnPosition, pawn.Map, ThingPlaceMode.Direct, out resultingThing, null, null, default(Rot4)))
|
||||||
{
|
{
|
||||||
spawnMethod = "pawn_position";
|
spawnMethod = "pawn_position";
|
||||||
|
spawnedThing = resultingThing;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:尝试在物品栏生成
|
private bool TrySpawnInInventory(Pawn pawn, Thing thing, ref string spawnMethod, out Thing spawnedThing, out int addedCount)
|
||||||
private bool TrySpawnInInventory(Pawn pawn, Thing thing, ref string spawnMethod)
|
|
||||||
{
|
{
|
||||||
|
spawnedThing = null;
|
||||||
|
addedCount = 0;
|
||||||
if (pawn.inventory == null)
|
if (pawn.inventory == null)
|
||||||
{
|
{
|
||||||
Warn($"Pawn {pawn.Label} does not have an inventory", this.myDebug);
|
Warn($"Pawn {pawn.Label} does not have an inventory", this.myDebug);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int before = CountDefInInventory(pawn, thing.def);
|
||||||
if (pawn.inventory.innerContainer.TryAdd(thing))
|
if (pawn.inventory.innerContainer.TryAdd(thing))
|
||||||
{
|
{
|
||||||
|
int after = CountDefInInventory(pawn, thing.def);
|
||||||
|
addedCount = Math.Max(0, after - before);
|
||||||
spawnMethod = "inventory";
|
spawnMethod = "inventory";
|
||||||
|
spawnedThing = pawn.inventory.innerContainer.FirstOrDefault(t => t.def == thing.def);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:生成后校验
|
private bool VerifySpawnSuccess(Pawn pawn, ThingDef thingDef, int expectedCount, string spawnMethod, Thing spawnedThing, int addedInventoryCount)
|
||||||
private bool VerifySpawnSuccess(Pawn pawn, ThingDef thingDef, int expectedCount, string spawnMethod)
|
|
||||||
{
|
{
|
||||||
bool verificationSuccess = false;
|
bool verificationSuccess = false;
|
||||||
|
|
||||||
switch (spawnMethod)
|
switch (spawnMethod)
|
||||||
{
|
{
|
||||||
case "nearby_cell":
|
case "nearby_cell":
|
||||||
case "pawn_position":
|
case "pawn_position":
|
||||||
case "inventory_fallback":
|
verificationSuccess =
|
||||||
// 检查地图上是否有生成的物品
|
spawnedThing != null &&
|
||||||
verificationSuccess = pawn.Map.listerThings.ThingsOfDef(thingDef)
|
spawnedThing.def == thingDef &&
|
||||||
.Any(t => t.stackCount >= expectedCount && t.Position.InHorDistOf(pawn.Position, 2f));
|
spawnedThing.Map == pawn.Map &&
|
||||||
|
spawnedThing.Position.InHorDistOf(pawn.Position, 2f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "inventory":
|
case "inventory":
|
||||||
// 检查物品栏中是否有生成的物品
|
case "inventory_fallback":
|
||||||
verificationSuccess = pawn.inventory.innerContainer.Any(t => t.def == thingDef && t.stackCount >= expectedCount);
|
verificationSuccess = addedInventoryCount >= expectedCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verificationSuccess)
|
if (!verificationSuccess)
|
||||||
{
|
{
|
||||||
Warn($"Spawn verification failed for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
Warn($"Spawn verification failed for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||||
@@ -683,10 +709,19 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
Warn($"Spawn verification successful for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
Warn($"Spawn verification successful for {thingDef.defName} via {spawnMethod}", this.myDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
return verificationSuccess;
|
return verificationSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int CountDefInInventory(Pawn pawn, ThingDef thingDef)
|
||||||
|
{
|
||||||
|
if (pawn?.inventory?.innerContainer == null || thingDef == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return pawn.inventory.innerContainer.Where(t => t.def == thingDef).Sum(t => t.stackCount);
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryFindSpawnCell(out IntVec3 result)
|
private bool TryFindSpawnCell(out IntVec3 result)
|
||||||
{
|
{
|
||||||
result = IntVec3.Invalid;
|
result = IntVec3.Invalid;
|
||||||
@@ -704,19 +739,19 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 修改这里:将半径从5减少到2,让生成位置更靠近pawn
|
// 淇敼杩欓噷锛氬皢鍗婂緞浠?鍑忓皯鍒?锛岃鐢熸垚浣嶇疆鏇撮潬杩憄awn
|
||||||
int searchRadius = 2;
|
int searchRadius = 2;
|
||||||
|
|
||||||
// 首先尝试在pawn的相邻单元格生成(半径为1)
|
// 棣栧厛灏濊瘯鍦╬awn鐨勭浉閭诲崟鍏冩牸鐢熸垚锛堝崐寰勪负1锛?
|
||||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null);
|
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, 1, null);
|
||||||
|
|
||||||
// 如果相邻单元格找不到合适位置,再尝试稍远一点(半径为2)
|
// 濡傛灉鐩搁偦鍗曞厓鏍兼壘涓嶅埌鍚堥€備綅缃紝鍐嶅皾璇曠◢杩滀竴鐐癸紙鍗婂緞涓?锛?
|
||||||
if (!result.IsValid)
|
if (!result.IsValid)
|
||||||
{
|
{
|
||||||
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null);
|
result = CellFinder.RandomClosewalkCellNear(this.pawn.Position, map, searchRadius, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果还是找不到,尝试pawn当前位置(作为最后手段)
|
// 濡傛灉杩樻槸鎵句笉鍒帮紝灏濊瘯pawn褰撳墠浣嶇疆锛堜綔涓烘渶鍚庢墜娈碉級
|
||||||
if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map))
|
if (!result.IsValid && this.pawn.Position.IsValid && this.pawn.Position.Walkable(map))
|
||||||
{
|
{
|
||||||
result = this.pawn.Position;
|
result = this.pawn.Position;
|
||||||
@@ -813,7 +848,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 整合的 Tools 方法 ===
|
// === 鏁村悎鐨?Tools 鏂规硶 ===
|
||||||
|
|
||||||
private void DestroyParentHediff(Hediff parentHediff, bool debug = false)
|
private void DestroyParentHediff(Hediff parentHediff, bool debug = false)
|
||||||
{
|
{
|
||||||
@@ -851,12 +886,86 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OkPawn(Pawn pawn)
|
private bool OkPawn(Pawn pawn)
|
||||||
{
|
{
|
||||||
return pawn != null && pawn.Map != null;
|
return pawn != null && pawn.Map != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsHungry(Pawn pawn, bool debug = false)
|
||||||
|
{
|
||||||
|
if (pawn == null)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Warn("pawn is null - IsHungry", debug);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool starving = pawn.needs.food != null && pawn.needs.food.CurCategory == HungerCategory.Starving;
|
||||||
|
if (debug && starving)
|
||||||
|
{
|
||||||
|
Warn(pawn.Label + " is hungry", debug);
|
||||||
|
}
|
||||||
|
return starving;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsInjured(Pawn pawn, bool debug = false)
|
||||||
|
{
|
||||||
|
if (pawn == null)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Warn("pawn is null - IsInjured", debug);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float injurySeverity = 0f;
|
||||||
|
List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
|
||||||
|
for (int i = 0; i < hediffs.Count; i++)
|
||||||
|
{
|
||||||
|
if (hediffs[i] is Hediff_Injury && !hediffs[i].IsPermanent())
|
||||||
|
{
|
||||||
|
injurySeverity += hediffs[i].Severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool injured = injurySeverity > 0f;
|
||||||
|
if (debug && injured)
|
||||||
|
{
|
||||||
|
Warn(pawn.Label + " is injured", debug);
|
||||||
|
}
|
||||||
|
return injured;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool PartOrAnyDescendantHasDirectlyAddedParts(Pawn pawn, BodyPartRecord part)
|
||||||
|
{
|
||||||
|
if (pawn?.health?.hediffSet == null || part == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pawn.health.hediffSet.HasDirectlyAddedPartFor(part))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.parts == null || part.parts.Count == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < part.parts.Count; i++)
|
||||||
|
{
|
||||||
|
if (PartOrAnyDescendantHasDirectlyAddedParts(pawn, part.parts[i]))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
private void Warn(string warning, bool debug = false)
|
private void Warn(string warning, bool debug = false)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -880,4 +989,5 @@ namespace ArachnaeSwarm
|
|||||||
private readonly int errorExponentialLimit = 20;
|
private readonly int errorExponentialLimit = 20;
|
||||||
private readonly int errorSpawnCount = 750;
|
private readonly int errorSpawnCount = 750;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user