fix(possess): don't destroy caster in Apply; defer possession to OnJumpCompleted to prevent PawnFlyer NRE
- CompAbilityEffect_Possess.Apply now only logs; DoPossession runs after landing - Harden HediffComp_GestaltNode against null/destroyed pawn (tick/severity/overlord search/relations) - Fix GestaltOverseer Notify_PostRemovedByDeath message condition (only when overlord died/destroyed and hive node alive)
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -35,15 +35,21 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
CompGestalt comp = Pawn.TryGetComp<CompGestalt>();
|
var pawn = Pawn;
|
||||||
|
if (pawn == null)
|
||||||
|
{
|
||||||
|
return tracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompGestalt comp = pawn.TryGetComp<CompGestalt>();
|
||||||
if (comp != null)
|
if (comp != null)
|
||||||
{
|
{
|
||||||
return comp.GestaltTracker;
|
return comp.GestaltTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracker == null && NodeType == GestaltNodeType.OverlordNode)
|
if (tracker == null && NodeType == GestaltNodeType.OverlordNode)
|
||||||
{
|
{
|
||||||
tracker = new Pawn_GestaltTracker(Pawn);
|
tracker = new Pawn_GestaltTracker(pawn);
|
||||||
}
|
}
|
||||||
return tracker;
|
return tracker;
|
||||||
}
|
}
|
||||||
@@ -59,6 +65,12 @@ namespace ArachnaeSwarm
|
|||||||
public override void CompPostTick(ref float severityAdjustment)
|
public override void CompPostTick(ref float severityAdjustment)
|
||||||
{
|
{
|
||||||
base.CompPostTick(ref severityAdjustment);
|
base.CompPostTick(ref severityAdjustment);
|
||||||
|
|
||||||
|
var pawn = Pawn;
|
||||||
|
if (pawn == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (NodeType == GestaltNodeType.HiveNode)
|
if (NodeType == GestaltNodeType.HiveNode)
|
||||||
{
|
{
|
||||||
@@ -69,9 +81,9 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 定期寻找 OverlordNode
|
// 定期寻找 OverlordNode
|
||||||
if (Pawn.IsColonist &&
|
if (pawn.IsColonist &&
|
||||||
Pawn.Spawned &&
|
pawn.Spawned &&
|
||||||
!Pawn.Dead &&
|
!pawn.Dead &&
|
||||||
Find.TickManager.TicksGame % 250 == 0)
|
Find.TickManager.TicksGame % 250 == 0)
|
||||||
{
|
{
|
||||||
TryFindOverlord();
|
TryFindOverlord();
|
||||||
@@ -86,6 +98,12 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
if (NodeType != GestaltNodeType.HiveNode || parent == null)
|
if (NodeType != GestaltNodeType.HiveNode || parent == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var pawn = Pawn;
|
||||||
|
if (pawn?.health == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool isConnected = IsConnectedToOverlord();
|
bool isConnected = IsConnectedToOverlord();
|
||||||
|
|
||||||
@@ -103,7 +121,7 @@ namespace ArachnaeSwarm
|
|||||||
wasConnected = isConnected;
|
wasConnected = isConnected;
|
||||||
|
|
||||||
// 如果严重性改变,需要重新计算Pawn的能力
|
// 如果严重性改变,需要重新计算Pawn的能力
|
||||||
Pawn.health.Notify_HediffChanged(parent);
|
pawn.health.Notify_HediffChanged(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +136,12 @@ namespace ArachnaeSwarm
|
|||||||
public void TryFindOverlord()
|
public void TryFindOverlord()
|
||||||
{
|
{
|
||||||
// 如果已经有Overlord,更新连接状态并返回
|
// 如果已经有Overlord,更新连接状态并返回
|
||||||
|
var pawn = Pawn;
|
||||||
|
if (pawn == null || pawn.Dead || pawn.Destroyed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsConnectedToOverlord())
|
if (IsConnectedToOverlord())
|
||||||
{
|
{
|
||||||
UpdateSeverityBasedOnConnection();
|
UpdateSeverityBasedOnConnection();
|
||||||
@@ -125,7 +149,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果Pawn当前不在地图上,无法寻找Overlord
|
// 如果Pawn当前不在地图上,无法寻找Overlord
|
||||||
if (Pawn.Map == null)
|
if (pawn.Map == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,22 +158,23 @@ namespace ArachnaeSwarm
|
|||||||
Pawn bestOverlord = null;
|
Pawn bestOverlord = null;
|
||||||
float bestScore = -1f;
|
float bestScore = -1f;
|
||||||
|
|
||||||
foreach (Pawn pawn in Pawn.Map.mapPawns.FreeColonists)
|
foreach (Pawn candidate in pawn.Map.mapPawns.FreeColonists)
|
||||||
{
|
{
|
||||||
HediffComp_GestaltNode nodeComp = pawn.GetGestaltNodeComp();
|
HediffComp_GestaltNode nodeComp = candidate.GetGestaltNodeComp();
|
||||||
if (nodeComp?.NodeType == GestaltNodeType.OverlordNode &&
|
if (nodeComp?.NodeType == GestaltNodeType.OverlordNode &&
|
||||||
pawn != Pawn &&
|
candidate != pawn &&
|
||||||
!pawn.Dead &&
|
!candidate.Dead &&
|
||||||
!pawn.Downed)
|
!candidate.Downed &&
|
||||||
|
!candidate.Destroyed)
|
||||||
{
|
{
|
||||||
Pawn_GestaltTracker tracker = pawn.GestaltTracker();
|
Pawn_GestaltTracker tracker = candidate.GestaltTracker();
|
||||||
if (tracker != null && tracker.CanControlPawn(Pawn))
|
if (tracker != null && tracker.CanControlPawn(pawn))
|
||||||
{
|
{
|
||||||
float score = CalculateOverlordScore(pawn, tracker);
|
float score = CalculateOverlordScore(candidate, tracker);
|
||||||
if (score > bestScore)
|
if (score > bestScore)
|
||||||
{
|
{
|
||||||
bestScore = score;
|
bestScore = score;
|
||||||
bestOverlord = pawn;
|
bestOverlord = candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +183,11 @@ namespace ArachnaeSwarm
|
|||||||
// 找到合适的Overlord,建立关系并更新严重性
|
// 找到合适的Overlord,建立关系并更新严重性
|
||||||
if (bestOverlord != null)
|
if (bestOverlord != null)
|
||||||
{
|
{
|
||||||
Pawn.relations.AddDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, bestOverlord);
|
// Pawns being destroyed/vanished can temporarily have no relations tracker.
|
||||||
|
if (pawn.relations != null && ARA_PawnRelationDefOf.ARA_GestaltOverseer != null)
|
||||||
|
{
|
||||||
|
pawn.relations.AddDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, bestOverlord);
|
||||||
|
}
|
||||||
UpdateSeverityBasedOnConnection();
|
UpdateSeverityBasedOnConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,10 +217,16 @@ namespace ArachnaeSwarm
|
|||||||
// 当Hediff被移除时,如果连接到Overlord,需要断开连接
|
// 当Hediff被移除时,如果连接到Overlord,需要断开连接
|
||||||
if (NodeType == GestaltNodeType.HiveNode && IsConnectedToOverlord())
|
if (NodeType == GestaltNodeType.HiveNode && IsConnectedToOverlord())
|
||||||
{
|
{
|
||||||
Pawn overlord = Pawn.GetOverlord();
|
var pawn = Pawn;
|
||||||
|
if (pawn?.relations == null || ARA_PawnRelationDefOf.ARA_GestaltOverseer == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pawn overlord = pawn.GetOverlord();
|
||||||
if (overlord != null)
|
if (overlord != null)
|
||||||
{
|
{
|
||||||
Pawn.relations.RemoveDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, overlord);
|
pawn.relations.RemoveDirectRelation(ARA_PawnRelationDefOf.ARA_GestaltOverseer, overlord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overlord != null && hiveNode != null && (!overlord.Dead || overlord.Destroyed))
|
if (overlord != null && hiveNode != null && !hiveNode.Dead && (overlord.Dead || overlord.Destroyed))
|
||||||
{
|
{
|
||||||
Messages.Message("MessageGestaltLostControl".Translate(overlord, hiveNode) + ": " + hiveNode.LabelShortCap,
|
Messages.Message("MessageGestaltLostControl".Translate(overlord, hiveNode) + ": " + hiveNode.LabelShortCap,
|
||||||
new LookTargets(new Thing[] { overlord, hiveNode }), MessageTypeDefOf.NeutralEvent);
|
new LookTargets(new Thing[] { overlord, hiveNode }), MessageTypeDefOf.NeutralEvent);
|
||||||
|
|||||||
Reference in New Issue
Block a user