diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 7ee2c616..4bb6ece8 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/Building_WULA_ArmedShuttleWithPocket.xml b/1.6/1.6/Defs/ThingDefs_Buildings/Building_WULA_ArmedShuttleWithPocket.xml index b5728ab4..ead296f8 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/Building_WULA_ArmedShuttleWithPocket.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/Building_WULA_ArmedShuttleWithPocket.xml @@ -102,7 +102,6 @@ Shuttle_PawnExit true -
  • 500 true diff --git a/MCP/vector_cache/knowledge_cache.json b/MCP/vector_cache/knowledge_cache.json index aab11e09..8b43e0b6 100644 --- a/MCP/vector_cache/knowledge_cache.json +++ b/MCP/vector_cache/knowledge_cache.json @@ -6209,5 +6209,1039 @@ ], "result": "--- 结果 1 (相似度: 1.000) ---\n文件路径: C:\\Steam\\steamapps\\common\\RimWorld\\Data\\dll1.6\\Verse\\Thing.txt\n\npublic class Thing : Entity, ISelectable, ILoadReferenceable, ISignalReceiver, IExposable, IEquatable\n{\n\tpublic ThingDef def;\n\n\tpublic int thingIDNumber = -1;\n\n\tprivate sbyte mapIndexOrState = -1;\n\n\tprivate IntVec3 positionInt = IntVec3.Invalid;\n\n\tprivate Rot4 rotationInt = Rot4.North;\n\n\tpublic int stackCount = 1;\n\n\tprotected Faction factionInt;\n\n\tprivate ThingDef stuffInt;\n\n\tprivate Graphic graphicInt;\n\n\tprotected Graphic styleGraphicInt;\n\n\tprivate int hitPointsInt = -1;\n\n\tpublic ThingOwner holdingOwner;\n\n\tpublic List questTags;\n\n\tpublic int spawnedTick = -1;\n\n\tpublic int despawnedTick = -1;\n\n\tpublic int? overrideGraphicIndex;\n\n\tpublic bool debugRotLocked;\n\n\tprivate bool beingTransportedOnGravship;\n\n\tprivate int tickDelta;\n\n\tprivate bool beenRevealed;\n\n\tpublic bool shouldHighlightCached;\n\n\tpublic int shouldHighlightCachedTick;\n\n\tpublic Color highlightColorCached;\n\n\tpublic int highlightColorCachedTick;\n\n\tprotected const sbyte UnspawnedState = -1;\n\n\tprivate const sbyte MemoryState = -2;\n\n\tprivate const sbyte DiscardedState = -3;\n\n\tprivate List tmpHolders;\n\n\tpublic static bool allowDestroyNonDestroyable = false;\n\n\tprivate static Dictionary facIDsCached = new Dictionary();\n\n\tprivate static List tmpDeteriorationReasons = new List();\n\n\tpublic static HashSet showingGizmosForRitualsTmp = new HashSet();\n\n\tprivate static List tmpIdeoNames = new List();\n\n\tpublic const float SmeltCostRecoverFraction = 0.25f;\n\n\tpublic virtual int HitPoints\n\t{\n\t\tget\n\t\t{\n\t\t\treturn hitPointsInt;\n\t\t}\n\t\tset\n\t\t{\n\t\t\thitPointsInt = value;\n\t\t}\n\t}\n\n\tpublic int MaxHitPoints => Mathf.RoundToInt(this.GetStatValue(StatDefOf.MaxHitPoints, applyPostProcess: true, 10));\n\n\tpublic virtual float MarketValue => this.GetStatValue(StatDefOf.MarketValue);\n\n\tpublic virtual float RoyalFavorValue => this.GetStatValue(StatDefOf.RoyalFavorValue);\n\n\tpublic virtual int? OverrideGraphicIndex => overrideGraphicIndex;\n\n\tpublic virtual Texture UIIconOverride => null;\n\n\tpublic bool EverSeenByPlayer\n\t{\n\t\tget\n\t\t{\n\t\t\treturn this.GetEverSeenByPlayer();\n\t\t}\n\t\tset\n\t\t{\n\t\t\tthis.SetEverSeenByPlayer(value);\n\t\t}\n\t}\n\n\tpublic virtual ThingStyleDef StyleDef\n\t{\n\t\tget\n\t\t{\n\t\t\treturn this.GetStyleDef();\n\t\t}\n\t\tset\n\t\t{\n\t\t\tstyleGraphicInt = null;\n\t\t\tthis.SetStyleDef(value);\n\t\t}\n\t}\n\n\tpublic Precept_ThingStyle StyleSourcePrecept\n\t{\n\t\tget\n\t\t{\n\t\t\treturn this.GetStyleSourcePrecept();\n\t\t}\n\t\tset\n\t\t{\n\t\t\tthis.SetStyleSourcePrecept(value);\n\t\t}\n\t}\n\n\tpublic bool FlammableNow\n\t{\n\t\tget\n\t\t{\n\t\t\tif (this.GetStatValue(StatDefOf.Flammability) < 0.01f)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (Spawned && !FireBulwark)\n\t\t\t{\n\t\t\t\tList thingList = Position.GetThingList(Map);\n\t\t\t\tif (thingList != null)\n\t\t\t\t{\n\t\t\t\t\tfor (int i = 0; i < thingList.Count; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (thingList[i].FireBulwark)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic virtual bool FireBulwark => def.Fillage == FillCategory.Full;\n\n\tpublic bool Destroyed\n\t{\n\t\tget\n\t\t{\n\t\t\tif (mapIndexOrState != -2)\n\t\t\t{\n\t\t\t\treturn mapIndexOrState == -3;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic bool Discarded => mapIndexOrState == -3;\n\n\tpublic bool Spawned\n\t{\n\t\tget\n\t\t{\n\t\t\tif (mapIndexOrState < 0 || Find.Maps == null)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (mapIndexOrState < Find.Maps.Count)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tLog.ErrorOnce($\"Thing {ThingID} is associated with invalid map index {mapIndexOrState}\", 64664487);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic bool SpawnedOrAnyParentSpawned => SpawnedParentOrMe != null;\n\n\tpublic Thing SpawnedParentOrMe\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif (ParentHolder != null)\n\t\t\t{\n\t\t\t\treturn ThingOwnerUtility.SpawnedParentOrMe(ParentHolder);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic int TickSpawned => spawnedTick;\n\n\tpublic int TickDeSpawned => despawnedTick;\n\n\tpublic Map Map\n\t{\n\t\tget\n\t\t{\n\t\t\tif (mapIndexOrState >= 0)\n\t\t\t{\n\t\t\t\treturn Find.Maps?[mapIndexOrState];\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic Map MapHeld\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn Map;\n\t\t\t}\n\t\t\tif (ParentHolder == null)\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn ThingOwnerUtility.GetRootMap(ParentHolder);\n\t\t}\n\t}\n\n\tpublic IntVec3 Position\n\t{\n\t\tget\n\t\t{\n\t\t\treturn positionInt;\n\t\t}\n\t\tset\n\t\t{\n\t\t\tif (value == positionInt)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\tif (def.AffectsRegions)\n\t\t\t\t{\n\t\t\t\t\tLog.Warning(\"Changed position of a spawned thing which affects regions. This is not supported.\");\n\t\t\t\t}\n\t\t\t\tDirtyMapMesh(Map);\n\t\t\t\tRegionListersUpdater.DeregisterInRegions(this, Map);\n\t\t\t\tMap.thingGrid.Deregister(this);\n\t\t\t\tMap.coverGrid.DeRegister(this);\n\t\t\t}\n\t\t\tpositionInt = value;\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\tMap.thingGrid.Register(this);\n\t\t\t\tMap.coverGrid.Register(this);\n\t\t\t\tMap.gasGrid.Notify_ThingSpawned(this);\n\t\t\t\tRegionListersUpdater.RegisterInRegions(this, Map);\n\t\t\t\tDirtyMapMesh(Map);\n\t\t\t\tif (def.AffectsReachability)\n\t\t\t\t{\n\t\t\t\t\tMap.reachability.ClearCache();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic IntVec3 PositionHeld\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn Position;\n\t\t\t}\n\t\t\tIntVec3 rootPosition = ThingOwnerUtility.GetRootPosition(ParentHolder);\n\t\t\tif (rootPosition.IsValid)\n\t\t\t{\n\t\t\t\treturn rootPosition;\n\t\t\t}\n\t\t\treturn Position;\n\t\t}\n\t}\n\n\tpublic Rot4 Rotation\n\t{\n\t\tget\n\t\t{\n\t\t\treturn rotationInt;\n\t\t}\n\t\tset\n\t\t{\n\t\t\tif (value == rotationInt || debugRotLocked)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Spawned && (def.size.x != 1 || def.size.z != 1))\n\t\t\t{\n\t\t\t\tif (def.AffectsRegions)\n\t\t\t\t{\n\t\t\t\t\tLog.Warning(\"Changed rotation of a spawned non-single-cell thing which affects regions. This is not supported.\");\n\t\t\t\t}\n\t\t\t\tRegionListersUpdater.DeregisterInRegions(this, Map);\n\t\t\t\tMap.thingGrid.Deregister(this);\n\t\t\t}\n\t\t\trotationInt = value;\n\t\t\tif (Spawned && (def.size.x != 1 || def.size.z != 1))\n\t\t\t{\n\t\t\t\tMap.thingGrid.Register(this);\n\t\t\t\tRegionListersUpdater.RegisterInRegions(this, Map);\n\t\t\t\tMap.gasGrid.Notify_ThingSpawned(this);\n\t\t\t\tif (def.AffectsReachability)\n\t\t\t\t{\n\t\t\t\t\tMap.reachability.ClearCache();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic bool Smeltable\n\t{\n\t\tget\n\t\t{\n\t\t\tif (this.IsRelic())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (def.smeltable)\n\t\t\t{\n\t\t\t\tif (def.MadeFromStuff)\n\t\t\t\t{\n\t\t\t\t\treturn Stuff.smeltable;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic bool BurnableByRecipe\n\t{\n\t\tget\n\t\t{\n\t\t\tif (def.burnableByRecipe)\n\t\t\t{\n\t\t\t\tif (def.MadeFromStuff)\n\t\t\t\t{\n\t\t\t\t\treturn Stuff.burnableByRecipe;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic IThingHolder ParentHolder => holdingOwner?.Owner;\n\n\tpublic Faction Faction => factionInt;\n\n\tpublic string ThingID\n\t{\n\t\tget\n\t\t{\n\t\t\tif (def.HasThingIDNumber)\n\t\t\t{\n\t\t\t\treturn def.defName + thingIDNumber;\n\t\t\t}\n\t\t\treturn def.defName;\n\t\t}\n\t\tset\n\t\t{\n\t\t\tthingIDNumber = IDNumberFromThingID(value);\n\t\t}\n\t}\n\n\tpublic IntVec2 RotatedSize\n\t{\n\t\tget\n\t\t{\n\t\t\tif (!rotationInt.IsHorizontal)\n\t\t\t{\n\t\t\t\treturn def.size;\n\t\t\t}\n\t\t\treturn new IntVec2(def.size.z, def.size.x);\n\t\t}\n\t}\n\n\tpublic virtual CellRect? CustomRectForSelector => null;\n\n\tpublic override string Label\n\t{\n\t\tget\n\t\t{\n\t\t\tif (stackCount > 1)\n\t\t\t{\n\t\t\t\treturn LabelNoCount + \" x\" + stackCount.ToStringCached();\n\t\t\t}\n\t\t\treturn LabelNoCount;\n\t\t}\n\t}\n\n\tpublic virtual string LabelNoCount => GenLabel.ThingLabel(this, 1);\n\n\tpublic override string LabelCap => Label.CapitalizeFirst(def);\n\n\tpublic virtual string LabelCapNoCount => LabelNoCount.CapitalizeFirst(def);\n\n\tpublic override string LabelShort => LabelNoCount;\n\n\tpublic virtual string LabelNoParenthesis => GenLabel.ThingLabel(this, 1, includeHp: false, includeQuality: false);\n\n\tpublic string LabelNoParenthesisCap => LabelNoParenthesis.CapitalizeFirst();\n\n\tpublic virtual ModContentPack ContentSource => def.modContentPack;\n\n\tpublic virtual bool IngestibleNow\n\t{\n\t\tget\n\t\t{\n\t\t\tif (this.IsBurning())\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn def.IsIngestible;\n\t\t}\n\t}\n\n\tpublic ThingDef Stuff => stuffInt;\n\n\tpublic Graphic DefaultGraphic\n\t{\n\t\tget\n\t\t{\n\t\t\tif (graphicInt == null)\n\t\t\t{\n\t\t\t\tif (def.graphicData == null)\n\t\t\t\t{\n\t\t\t\t\treturn BaseContent.BadGraphic;\n\t\t\t\t}\n\t\t\t\tgraphicInt = def.graphicData.GraphicColoredFor(this);\n\t\t\t}\n\t\t\treturn graphicInt;\n\t\t}\n\t}\n\n\tpublic virtual Graphic Graphic\n\t{\n\t\tget\n\t\t{\n\t\t\tThingStyleDef styleDef = StyleDef;\n\t\t\tif (styleDef?.Graphic != null)\n\t\t\t{\n\t\t\t\tif (styleGraphicInt == null)\n\t\t\t\t{\n\t\t\t\t\tif (styleDef.graphicData != null)\n\t\t\t\t\t{\n\t\t\t\t\t\tstyleGraphicInt = styleDef.graphicData.GraphicColoredFor(this);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstyleGraphicInt = styleDef.Graphic;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn styleGraphicInt;\n\t\t\t}\n\t\t\treturn DefaultGraphic;\n\t\t}\n\t}\n\n\tpublic virtual List InteractionCells => ThingUtility.InteractionCellsWhenAt(def, Position, Rotation, Map, allowFallbackCell: true);\n\n\tpublic virtual IntVec3 InteractionCell => ThingUtility.InteractionCellWhenAt(def, Position, Rotation, Map);\n\n\tpublic float AmbientTemperature\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn GenTemperature.GetTemperatureForCell(Position, Map);\n\t\t\t}\n\t\t\tif (ParentHolder != null)\n\t\t\t{\n\t\t\t\tfor (IThingHolder parentHolder = ParentHolder; parentHolder != null; parentHolder = parentHolder.ParentHolder)\n\t\t\t\t{\n\t\t\t\t\tif (ThingOwnerUtility.TryGetFixedTemperature(parentHolder, this, out var temperature))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn temperature;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (SpawnedOrAnyParentSpawned)\n\t\t\t{\n\t\t\t\treturn GenTemperature.GetTemperatureForCell(PositionHeld, MapHeld);\n\t\t\t}\n\t\t\tif (Tile.Valid)\n\t\t\t{\n\t\t\t\treturn GenTemperature.GetTemperatureAtTile(Tile);\n\t\t\t}\n\t\t\treturn 21f;\n\t\t}\n\t}\n\n\tpublic PlanetTile Tile\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn Map.Tile;\n\t\t\t}\n\t\t\tif (ParentHolder != null)\n\t\t\t{\n\t\t\t\treturn ThingOwnerUtility.GetRootTile(ParentHolder);\n\t\t\t}\n\t\t\treturn PlanetTile.Invalid;\n\t\t}\n\t}\n\n\tpublic virtual bool Suspended\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (ParentHolder != null)\n\t\t\t{\n\t\t\t\treturn ThingOwnerUtility.ContentsSuspended(ParentHolder);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic bool InCryptosleep\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (ParentHolder != null)\n\t\t\t{\n\t\t\t\treturn ThingOwnerUtility.ContentsInCryptosleep(ParentHolder);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic virtual string DescriptionDetailed => def.DescriptionDetailed;\n\n\tpublic virtual string DescriptionFlavor => def.description;\n\n\tpublic bool IsOnHoldingPlatform\n\t{\n\t\tget\n\t\t{\n\t\t\tif (ModsConfig.AnomalyActive)\n\t\t\t{\n\t\t\t\treturn ParentHolder is Building_HoldingPlatform;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic TerrainAffordanceDef TerrainAffordanceNeeded => def.GetTerrainAffordanceNeed(stuffInt);\n\n\tpublic bool BeingTransportedOnGravship => beingTransportedOnGravship;\n\n\tprotected virtual int MinTickIntervalRate => 1;\n\n\tprotected virtual int MaxTickIntervalRate => 15;\n\n\tprotected virtual int UpdateRateTickOffset => this.HashOffset();\n\n\tpublic virtual int UpdateRateTicks => GenTicks.GetCameraUpdateRate(this);\n\n\tpublic Vector3? DrawPosHeld\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Spawned)\n\t\t\t{\n\t\t\t\treturn DrawPos;\n\t\t\t}\n\t\t\treturn ThingOwnerUtility.SpawnedParentOrMe(ParentHolder)?.DrawPos;\n\t\t}\n\t}\n\n\tpublic virtual Vector3 DrawPos => this.TrueCenter();\n\n\tpublic virtual Vector2 DrawSize\n\t{\n\t\tget\n\t\t{\n\t\t\tif (def.graphicData != null)\n\t\t\t{\n\t\t\t\treturn def.graphicData.drawSize;\n\t\t\t}\n\t\t\treturn Vector2.one;\n\t\t}\n\t}\n\n\tpublic virtual Color DrawColor\n\t{\n\t\tget\n\t\t{\n\t\t\tif (Stuff != null)\n\t\t\t{\n\t\t\t\treturn def.GetColorForStuff(Stuff);\n\t\t\t}\n\t\t\tif (def.graphicData != null)\n\t\t\t{\n\t\t\t\treturn def.graphicData.color;\n\t\t\t}\n\t\t\treturn Color.white;\n\t\t}\n\t\tset\n\t\t{\n\t\t\tLog.Error($\"Cannot set instance color on non-ThingWithComps {LabelCap} at {Position}.\");\n\t\t}\n\t}\n\n\tpublic virtual Color DrawColorTwo\n\t{\n\t\tget\n\t\t{\n\t\t\tif (def.graphicData != null)\n\t\t\t{\n\t\t\t\treturn def.graphicData.colorTwo;\n\t\t\t}\n\t\t\treturn Color.white;\n\t\t}\n\t}\n\n\tpublic virtual IEnumerable DescriptionHyperlinks\n\t{\n\t\tget\n\t\t{\n\t\t\tif (def.descriptionHyperlinks != null)\n\t\t\t{\n\t\t\t\tfor (int i = 0; i < def.descriptionHyperlinks.Count; i++)\n\t\t\t\t{\n\t\t\t\t\tyield return def.descriptionHyperlinks[i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static int IDNumberFromThingID(string thingID)\n\t{\n\t\tstring value = Regex.Match(thingID, \"\\\\d+$\").Value;\n\t\tint result = 0;\n\t\ttry\n\t\t{\n\t\t\tCultureInfo invariantCulture = CultureInfo.InvariantCulture;\n\t\t\tresult = Convert.ToInt32(value, invariantCulture);\n\t\t}\n\t\tcatch (Exception ex)\n\t\t{\n\t\t\tLog.Error(\"Could not convert id number from thingID=\" + thingID + \", numString=\" + value + \" Exception=\" + ex);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic void DoTick()\n\t{\n\t\tif (Destroyed)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (def.tickerType == TickerType.Normal)\n\t\t{\n\t\t\tusing (ProfilerBlock.Scope(\"DoTick()\"))\n\t\t\t{\n\t\t\t\tusing (ProfilerBlock.Scope(\"Tick()\"))\n\t\t\t\t{\n\t\t\t\t\tTick();\n\t\t\t\t}\n\t\t\t\tif (Destroyed)\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttickDelta++;\n\t\t\t\tint num = Mathf.Min(Mathf.Max(UpdateRateTicks, MinTickIntervalRate), MaxTickIntervalRate);\n\t\t\t\tif (tickDelta >= num || GenTicks.IsTickInterval(UpdateRateTickOffset, num))\n\t\t\t\t{\n\t\t\t\t\tusing (ProfilerBlock.Scope(\"TickInterval()\"))\n\t\t\t\t\t{\n\t\t\t\t\t\tTickInterval(tickDelta);\n\t\t\t\t\t}\n\t\t\t\t\ttickDelta = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (Destroyed || !(this is IThingHolder thingHolder) || this is IThingHolderTickable { ShouldTickContents: false })\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (tmpHolders == null)\n\t\t{\n\t\t\ttmpHolders = new List(8);\n\t\t}\n\t\ttmpHolders.Add(thingHolder);\n\t\tthingHolder.GetChildHolders(tmpHolders);\n\t\tfor (int i = 0; i < tmpHolders.Count; i++)\n\t\t{\n\t\t\tThingOwner directlyHeldThings = tmpHolders[i].GetDirectlyHeldThings();\n\t\t\tif (directlyHeldThings != null)\n\t\t\t{\n\t\t\t\tdirectlyHeldThings.DoTick();\n\t\t\t\tif (Destroyed)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttmpHolders.Clear();\n\t}\n\n\tpublic virtual void PostMake()\n\t{\n\t\tThingIDMaker.GiveIDTo(this);\n\t\tif (def.useHitPoints)\n\t\t{\n\t\t\tHitPoints = Mathf.RoundToInt((float)MaxHitPoints * Mathf.Clamp01(def.startingHpRange.RandomInRange));\n\t\t}\n\t}\n\n\tpublic virtual void PostPostMake()\n\t{\n\t\tif (!def.randomStyle.NullOrEmpty() && Rand.Chance(def.randomStyleChance))\n\t\t{\n\t\t\tStyleDef = def.randomStyle.RandomElementByWeight((ThingStyleChance x) => x.Chance).StyleDef;\n\t\t}\n\t}\n\n\tpublic virtual void PostQualitySet()\n\t{\n\t}\n\n\tpublic string GetUniqueLoadID()\n\t{\n\t\treturn \"Thing_\" + ThingID;\n\t}\n\n\tpublic override void SpawnSetup(Map map, bool respawningAfterLoad)\n\t{\n\t\tif (Destroyed)\n\t\t{\n\t\t\tLog.Error(\"Spawning destroyed thing \" + this?.ToString() + \" at \" + Position.ToString() + \". Correcting.\");\n\t\t\tmapIndexOrState = -1;\n\t\t\tif (HitPoints <= 0 && def.useHitPoints)\n\t\t\t{\n\t\t\t\tHitPoints = 1;\n\t\t\t}\n\t\t}\n\t\tif (Spawned)\n\t\t{\n\t\t\tLog.Error(\"Tried to spawn already-spawned thing \" + this?.ToString() + \" at \" + Position.ToString());\n\t\t\treturn;\n\t\t}\n\t\tint num = Find.Maps.IndexOf(map);\n\t\tif (num < 0)\n\t\t{\n\t\t\tLog.Error(\"Tried to spawn thing \" + this?.ToString() + \", but the map provided does not exist.\");\n\t\t\treturn;\n\t\t}\n\t\tif (stackCount > def.stackLimit)\n\t\t{\n\t\t\tLog.Error(\"Spawned \" + this?.ToString() + \" with stackCount \" + stackCount + \" but stackLimit is \" + def.stackLimit + \". Truncating.\");\n\t\t\tstackCount = def.stackLimit;\n\t\t}\n\t\tmapIndexOrState = (sbyte)num;\n\t\tRegionListersUpdater.RegisterInRegions(this, map);\n\t\tif (!map.spawnedThings.TryAdd(this, canMergeWithExistingStacks: false))\n\t\t{\n\t\t\tLog.Error(\"Couldn't add thing \" + this?.ToString() + \" to spawned things.\");\n\t\t}\n\t\tmap.listerThings.Add(this);\n\t\tmap.thingGrid.Register(this);\n\t\tmap.gasGrid.Notify_ThingSpawned(this);\n\t\tmap.mapTemperature.Notify_ThingSpawned(this);\n\t\tif (map.IsPlayerHome)\n\t\t{\n\t\t\tEverSeenByPlayer = true;\n\t\t}\n\t\tif (Find.TickManager != null)\n\t\t{\n\t\t\tFind.TickManager.RegisterAllTickabilityFor(this);\n\t\t}\n\t\tDirtyMapMesh(map);\n\t\tif (def.drawerType != DrawerType.MapMeshOnly)\n\t\t{\n\t\t\tmap.dynamicDrawManager.RegisterDrawable(this);\n\t\t}\n\t\tmap.tooltipGiverList.Notify_ThingSpawned(this);\n\t\tif (def.CanAffectLinker)\n\t\t{\n\t\t\tmap.linkGrid.Notify_LinkerCreatedOrDestroyed(this);\n\t\t\tmap.mapDrawer.MapMeshDirty(Position, MapMeshFlagDefOf.Things, regenAdjacentCells: true, regenAdjacentSections: false);\n\t\t}\n\t\tif (!def.CanOverlapZones)\n\t\t{\n\t\t\tmap.zoneManager.Notify_NoZoneOverlapThingSpawned(this);\n\t\t}\n\t\tif (def.AffectsRegions)\n\t\t{\n\t\t\tmap.regionDirtyer.Notify_ThingAffectingRegionsSpawned(this);\n\t\t}\n\t\tif (def.pathCost != 0 || def.passability == Traversability.Impassable)\n\t\t{\n\t\t\tmap.pathing.RecalculatePerceivedPathCostUnderThing(this);\n\t\t}\n\t\tif (def.AffectsReachability)\n\t\t{\n\t\t\tmap.reachability.ClearCache();\n\t\t}\n\t\tmap.coverGrid.Register(this);\n\t\tif (def.category == ThingCategory.Item)\n\t\t{\n\t\t\tmap.listerHaulables.Notify_Spawned(this);\n\t\t\tmap.listerMergeables.Notify_Spawned(this);\n\t\t}\n\t\tmap.attackTargetsCache.Notify_ThingSpawned(this);\n\t\tmap.regionGrid.GetValidRegionAt_NoRebuild(Position)?.Room?.Notify_ContainedThingSpawnedOrDespawned(this);\n\t\tStealAIDebugDrawer.Notify_ThingChanged(this);\n\t\tif (this is IHaulDestination haulDestination)\n\t\t{\n\t\t\tmap.haulDestinationManager.AddHaulDestination(haulDestination);\n\t\t}\n\t\tif (this is IHaulSource source)\n\t\t{\n\t\t\tmap.haulDestinationManager.AddHaulSource(source);\n\t\t}\n\t\tif (this is IThingHolder && Find.ColonistBar != null)\n\t\t{\n\t\t\tFind.ColonistBar.MarkColonistsDirty();\n\t\t}\n\t\tif (def.category == ThingCategory.Item)\n\t\t{\n\t\t\tISlotGroupParent slotGroupParent = Position.GetSlotGroup(map)?.parent;\n\t\t\tif (slotGroupParent != null)\n\t\t\t{\n\t\t\t\tslotGroupParent.Notify_ReceivedThing(this);\n\t\t\t\tGenThing.TryDirtyAdjacentGroupContainers(slotGroupParent, map);\n\t\t\t}\n\t\t}\n\t\tif (def.receivesSignals)\n\t\t{\n\t\t\tFind.SignalManager.RegisterReceiver(this);\n\t\t}\n\t\tif (!BeingTransportedOnGravship)\n\t\t{\n\t\t\tdef.soundSpawned?.PlayOneShot(this);\n\t\t\tif (!respawningAfterLoad)\n\t\t\t{\n\t\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"Spawned\", this.Named(\"SUBJECT\"));\n\t\t\t\tspawnedTick = Find.TickManager.TicksGame;\n\t\t\t\tdespawnedTick = -1;\n\t\t\t\tif (AnomalyUtility.ShouldNotifyCodex(this, EntityDiscoveryType.Spawn, out var entries))\n\t\t\t\t{\n\t\t\t\t\tFind.EntityCodex.SetDiscovered(entries, def, this);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tFind.HiddenItemsManager.SetDiscovered(def);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmap.events.Notify_ThingSpawned(this);\n\t}\n\n\tpublic bool DeSpawnOrDeselect(DestroyMode mode = DestroyMode.Vanish)\n\t{\n\t\tbool flag = Current.ProgramState == ProgramState.Playing && Find.Selector.IsSelected(this);\n\t\tif (Spawned)\n\t\t{\n\t\t\tDeSpawn(mode);\n\t\t}\n\t\telse if (flag)\n\t\t{\n\t\t\tFind.Selector.Deselect(this);\n\t\t\tFind.MainButtonsRoot.tabs.Notify_SelectedObjectDespawned();\n\t\t}\n\t\treturn flag;\n\t}\n\n\tpublic override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)\n\t{\n\t\tif (Destroyed)\n\t\t{\n\t\t\tLog.Error(\"Tried to despawn \" + this.ToStringSafe() + \" which is already destroyed.\");\n\t\t\treturn;\n\t\t}\n\t\tif (!Spawned)\n\t\t{\n\t\t\tLog.Error(\"Tried to despawn \" + this.ToStringSafe() + \" which is not spawned.\");\n\t\t\treturn;\n\t\t}\n\t\tMap map = Map;\n\t\tmap.overlayDrawer.DisposeHandle(this);\n\t\tRegionListersUpdater.DeregisterInRegions(this, map);\n\t\tmap.spawnedThings.Remove(this);\n\t\tmap.listerThings.Remove(this);\n\t\tmap.thingGrid.Deregister(this);\n\t\tmap.coverGrid.DeRegister(this);\n\t\tif (def.receivesSignals)\n\t\t{\n\t\t\tFind.SignalManager.DeregisterReceiver(this);\n\t\t}\n\t\tmap.tooltipGiverList.Notify_ThingDespawned(this);\n\t\tif (def.CanAffectLinker)\n\t\t{\n\t\t\tmap.linkGrid.Notify_LinkerCreatedOrDestroyed(this);\n\t\t\tmap.mapDrawer.MapMeshDirty(Position, MapMeshFlagDefOf.Things, regenAdjacentCells: true, regenAdjacentSections: false);\n\t\t}\n\t\tif (Find.Selector.IsSelected(this))\n\t\t{\n\t\t\tFind.Selector.Deselect(this);\n\t\t\tFind.MainButtonsRoot.tabs.Notify_SelectedObjectDespawned();\n\t\t}\n\t\tDirtyMapMesh(map);\n\t\tif (def.drawerType != DrawerType.MapMeshOnly)\n\t\t{\n\t\t\tmap.dynamicDrawManager.DeRegisterDrawable(this);\n\t\t}\n\t\tmap.regionGrid.GetValidRegionAt_NoRebuild(Position)?.Room?.Notify_ContainedThingSpawnedOrDespawned(this);\n\t\tif (def.AffectsRegions)\n\t\t{\n\t\t\tmap.regionDirtyer.Notify_ThingAffectingRegionsDespawned(this);\n\t\t}\n\t\tif (def.pathCost != 0 || def.passability == Traversability.Impassable)\n\t\t{\n\t\t\tmap.pathing.RecalculatePerceivedPathCostUnderThing(this);\n\t\t}\n\t\tif (def.AffectsReachability)\n\t\t{\n\t\t\tmap.reachability.ClearCache();\n\t\t}\n\t\tFind.TickManager.DeRegisterAllTickabilityFor(this);\n\t\tmapIndexOrState = -1;\n\t\tif (def.category == ThingCategory.Item)\n\t\t{\n\t\t\tmap.listerHaulables.Notify_DeSpawned(this);\n\t\t\tmap.listerMergeables.Notify_DeSpawned(this);\n\t\t}\n\t\tmap.attackTargetsCache.Notify_ThingDespawned(this);\n\t\tmap.physicalInteractionReservationManager.ReleaseAllForTarget(this);\n\t\tif (this is IHaulEnroute thing)\n\t\t{\n\t\t\tmap.enrouteManager.Notify_ContainerDespawned(thing);\n\t\t}\n\t\tStealAIDebugDrawer.Notify_ThingChanged(this);\n\t\tif (this is IHaulDestination haulDestination)\n\t\t{\n\t\t\tmap.haulDestinationManager.RemoveHaulDestination(haulDestination);\n\t\t}\n\t\tif (this is IHaulSource source)\n\t\t{\n\t\t\tmap.haulDestinationManager.RemoveHaulSource(source);\n\t\t}\n\t\tif (this is IThingHolder && Find.ColonistBar != null)\n\t\t{\n\t\t\tFind.ColonistBar.MarkColonistsDirty();\n\t\t}\n\t\tif (def.category == ThingCategory.Item)\n\t\t{\n\t\t\tISlotGroupParent slotGroupParent = Position.GetSlotGroup(map)?.parent;\n\t\t\tif (slotGroupParent != null)\n\t\t\t{\n\t\t\t\tslotGroupParent.Notify_LostThing(this);\n\t\t\t\tGenThing.TryDirtyAdjacentGroupContainers(slotGroupParent, map);\n\t\t\t}\n\t\t}\n\t\tQuestUtility.SendQuestTargetSignals(questTags, \"Despawned\", this.Named(\"SUBJECT\"));\n\t\tspawnedTick = -1;\n\t\tdespawnedTick = Find.TickManager.TicksGame;\n\t\tmap.events.Notify_ThingDespawned(this);\n\t}\n\n\tpublic virtual void Kill(DamageInfo? dinfo = null, Hediff exactCulprit = null)\n\t{\n\t\tDestroy(DestroyMode.KillFinalize);\n\t}\n\n\tpublic virtual void Destroy(DestroyMode mode = DestroyMode.Vanish)\n\t{\n\t\tif (!allowDestroyNonDestroyable && !def.destroyable)\n\t\t{\n\t\t\tLog.Error(\"Tried to destroy non-destroyable thing \" + this);\n\t\t\treturn;\n\t\t}\n\t\tif (Destroyed)\n\t\t{\n\t\t\tLog.Error(\"Tried to destroy already-destroyed thing \" + this);\n\t\t\treturn;\n\t\t}\n\t\tbool spawned = Spawned;\n\t\tMap map = Map;\n\t\tif (StyleSourcePrecept != null)\n\t\t{\n\t\t\tStyleSourcePrecept.Notify_ThingLost(this, spawned);\n\t\t}\n\t\tif (Spawned)\n\t\t{\n\t\t\tDeSpawn(mode);\n\t\t}\n\t\telse if (Current.ProgramState == ProgramState.Playing && Find.Selector.IsSelected(this))\n\t\t{\n\t\t\tFind.Selector.Deselect(this);\n\t\t\tFind.MainButtonsRoot.tabs.Notify_SelectedObjectDespawned();\n\t\t}\n\t\tmapIndexOrState = -2;\n\t\tif (def.DiscardOnDestroyed)\n\t\t{\n\t\t\tDiscard();\n\t\t}\n\t\tCompExplosive compExplosive = this.TryGetComp();\n\t\tif (spawned)\n\t\t{\n\t\t\tList list = new List();\n\t\t\tGenLeaving.DoLeavingsFor(this, map, mode, list);\n\t\t\tcompExplosive?.AddThingsIgnoredByExplosion(list);\n\t\t\tNotify_KilledLeavingsLeft(list);\n\t\t}\n\t\tif (holdingOwner != null)\n\t\t{\n\t\t\tholdingOwner.Notify_ContainedItemDestroyed(this);\n\t\t}\n\t\tRemoveAllReservationsAndDesignationsOnThis();\n\t\tif (!(this is Pawn))\n\t\t{\n\t\t\tstackCount = 0;\n\t\t}\n\t\tif (mode != DestroyMode.QuestLogic)\n\t\t{\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"Destroyed\", this.Named(\"SUBJECT\"));\n\t\t}\n\t\tif (mode == DestroyMode.KillFinalize)\n\t\t{\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"Killed\", this.Named(\"SUBJECT\"), map.Named(\"MAP\"));\n\t\t}\n\t}\n\n\tpublic virtual void PreTraded(TradeAction action, Pawn playerNegotiator, ITrader trader)\n\t{\n\t}\n\n\tpublic virtual void PostGeneratedForTrader(TraderKindDef trader, PlanetTile forTile, Faction forFaction)\n\t{\n\t\tif (def.colorGeneratorInTraderStock != null)\n\t\t{\n\t\t\tthis.SetColor(def.colorGeneratorInTraderStock.NewRandomizedColor());\n\t\t}\n\t}\n\n\tpublic virtual float GetBeauty(bool outside)\n\t{\n\t\tif (!outside || !def.StatBaseDefined(StatDefOf.BeautyOutdoors))\n\t\t{\n\t\t\treturn this.GetStatValue(StatDefOf.Beauty);\n\t\t}\n\t\treturn this.GetStatValue(StatDefOf.BeautyOutdoors);\n\t}\n\n\tpublic virtual void Notify_MyMapRemoved()\n\t{\n\t\tif (def.receivesSignals)\n\t\t{\n\t\t\tFind.SignalManager.DeregisterReceiver(this);\n\t\t}\n\t\tif (StyleSourcePrecept != null)\n\t\t{\n\t\t\tStyleSourcePrecept.Notify_ThingLost(this);\n\t\t}\n\t\tif (!ThingOwnerUtility.AnyParentIs(this))\n\t\t{\n\t\t\tmapIndexOrState = -3;\n\t\t}\n\t\tThingOwner thingOwner = holdingOwner;\n\t\tif (thingOwner != null && thingOwner.Owner is Map)\n\t\t{\n\t\t\tholdingOwner = null;\n\t\t}\n\t\tRemoveAllReservationsAndDesignationsOnThis();\n\t}\n\n\tpublic virtual void Notify_LordDestroyed()\n\t{\n\t}\n\n\tpublic virtual void Notify_AbandonedAtTile(PlanetTile tile)\n\t{\n\t}\n\n\tpublic virtual void Notify_KilledLeavingsLeft(List leavings)\n\t{\n\t}\n\n\tpublic virtual void Notify_Studied(Pawn studier, float amount, KnowledgeCategoryDef category = null)\n\t{\n\t}\n\n\tpublic virtual void Notify_Unfogged()\n\t{\n\t\tif (!beenRevealed)\n\t\t{\n\t\t\tbeenRevealed = true;\n\t\t\tif (ModsConfig.AnomalyActive && AnomalyUtility.ShouldNotifyCodex(this, EntityDiscoveryType.Unfog, out var entries))\n\t\t\t{\n\t\t\t\tFind.EntityCodex.SetDiscovered(entries, def, this);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFind.HiddenItemsManager.SetDiscovered(def);\n\t\t\t}\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"Unfogged\", this);\n\t\t\tCompLetterOnRevealed compLetterOnRevealed = this.TryGetComp();\n\t\t\tif (compLetterOnRevealed != null)\n\t\t\t{\n\t\t\t\tFind.LetterStack.ReceiveLetter(compLetterOnRevealed.Props.label, compLetterOnRevealed.Props.text, compLetterOnRevealed.Props.letterDef, this);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void ForceSetStateToUnspawned()\n\t{\n\t\tmapIndexOrState = -1;\n\t}\n\n\tpublic void DecrementMapIndex()\n\t{\n\t\tif (mapIndexOrState <= 0)\n\t\t{\n\t\t\tLog.Warning(\"Tried to decrement map index for \" + this?.ToString() + \", but mapIndexOrState=\" + mapIndexOrState);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmapIndexOrState--;\n\t\t}\n\t}\n\n\tprivate void RemoveAllReservationsAndDesignationsOnThis()\n\t{\n\t\tif (def.category == ThingCategory.Mote)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tList maps = Find.Maps;\n\t\tfor (int i = 0; i < maps.Count; i++)\n\t\t{\n\t\t\tmaps[i].reservationManager.ReleaseAllForTarget(this);\n\t\t\tmaps[i].physicalInteractionReservationManager.ReleaseAllForTarget(this);\n\t\t\tif (this is IAttackTarget target)\n\t\t\t{\n\t\t\t\tmaps[i].attackTargetReservationManager.ReleaseAllForTarget(target);\n\t\t\t}\n\t\t\tmaps[i].designationManager.RemoveAllDesignationsOn(this);\n\t\t}\n\t}\n\n\tpublic virtual void ExposeData()\n\t{\n\t\tScribe_Defs.Look(ref def, \"def\");\n\t\tScribe_Values.Look(ref tickDelta, \"tickDelta\", 0);\n\t\tif (def.HasThingIDNumber)\n\t\t{\n\t\t\tstring value = ThingID;\n\t\t\tScribe_Values.Look(ref value, \"id\");\n\t\t\tif (Scribe.mode != LoadSaveMode.Saving)\n\t\t\t{\n\t\t\t\tThingID = value;\n\t\t\t}\n\t\t}\n\t\tScribe_Values.Look(ref mapIndexOrState, \"map\", -1);\n\t\tif (Scribe.mode == LoadSaveMode.LoadingVars && mapIndexOrState >= 0)\n\t\t{\n\t\t\tmapIndexOrState = -1;\n\t\t}\n\t\tScribe_Values.Look(ref positionInt, \"pos\", IntVec3.Invalid);\n\t\tScribe_Values.Look(ref rotationInt, \"rot\", Rot4.North);\n\t\tScribe_Values.Look(ref debugRotLocked, \"debugRotLocked\", defaultValue: false);\n\t\tif (def.useHitPoints)\n\t\t{\n\t\t\tScribe_Values.Look(ref hitPointsInt, \"health\", -1);\n\t\t}\n\t\tbool flag = def.tradeability != 0 && def.category == ThingCategory.Item;\n\t\tif (def.stackLimit > 1 || flag)\n\t\t{\n\t\t\tScribe_Values.Look(ref stackCount, \"stackCount\", 0, forceSave: true);\n\t\t}\n\t\tScribe_Defs.Look(ref stuffInt, \"stuff\");\n\t\tstring facID = ((factionInt != null) ? factionInt.GetUniqueLoadID() : \"null\");\n\t\tScribe_Values.Look(ref facID, \"faction\", \"null\");\n\t\tif (Scribe.mode == LoadSaveMode.LoadingVars)\n\t\t{\n\t\t\tif (facID == \"null\")\n\t\t\t{\n\t\t\t\tfactionInt = null;\n\t\t\t}\n\t\t\telse if (Find.World != null && Find.FactionManager != null)\n\t\t\t{\n\t\t\t\tfactionInt = Find.FactionManager.AllFactions.FirstOrDefault((Faction fa) => fa.GetUniqueLoadID() == facID);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfacIDsCached.SetOrAdd(this, facID);\n\t\t\t}\n\t\t}\n\t\tif (Scribe.mode == LoadSaveMode.ResolvingCrossRefs)\n\t\t{\n\t\t\tif (facID == \"null\" && facIDsCached.TryGetValue(this, out facID))\n\t\t\t{\n\t\t\t\tfacIDsCached.Remove(this);\n\t\t\t}\n\t\t\tif (facID != \"null\")\n\t\t\t{\n\t\t\t\tfactionInt = Find.FactionManager.AllFactions.FirstOrDefault((Faction fa) => fa.GetUniqueLoadID() == facID);\n\t\t\t}\n\t\t}\n\t\tif (Scribe.mode == LoadSaveMode.PostLoadInit)\n\t\t{\n\t\t\tfacIDsCached.Clear();\n\t\t}\n\t\tScribe_Collections.Look(ref questTags, \"questTags\", LookMode.Value);\n\t\tScribe_Values.Look(ref overrideGraphicIndex, \"overrideGraphicIndex\");\n\t\tScribe_Values.Look(ref spawnedTick, \"spawnedTick\", -1);\n\t\tScribe_Values.Look(ref despawnedTick, \"despawnedTick\", 0);\n\t\tScribe_Values.Look(ref beenRevealed, \"beenRevealed\", defaultValue: false);\n\t\tBackCompatibility.PostExposeData(this);\n\t}\n\n\tpublic virtual void PostMapInit()\n\t{\n\t}\n\n\tpublic void DrawNowAt(Vector3 drawLoc, bool flip = false)\n\t{\n\t\tDynamicDrawPhaseAt(DrawPhase.Draw, drawLoc, flip);\n\t}\n\n\tpublic void DynamicDrawPhase(DrawPhase phase)\n\t{\n\t\tif (def.drawerType != DrawerType.MapMeshOnly)\n\t\t{\n\t\t\tDynamicDrawPhaseAt(phase, DrawPos);\n\t\t}\n\t}\n\n\tpublic virtual void DynamicDrawPhaseAt(DrawPhase phase, Vector3 drawLoc, bool flip = false)\n\t{\n\t\tif (phase == DrawPhase.Draw)\n\t\t{\n\t\t\tDrawAt(drawLoc, flip);\n\t\t}\n\t}\n\n\tprotected virtual void DrawAt(Vector3 drawLoc, bool flip = false)\n\t{\n\t\tif (def.drawerType == DrawerType.RealtimeOnly || !Spawned)\n\t\t{\n\t\t\tGraphic.Draw(drawLoc, flip ? Rotation.Opposite : Rotation, this);\n\t\t}\n\t\tSilhouetteUtility.DrawGraphicSilhouette(this, drawLoc);\n\t}\n\n\tpublic virtual void Print(SectionLayer layer)\n\t{\n\t\tif (!def.dontPrint)\n\t\t{\n\t\t\tGraphic.Print(layer, this, 0f);\n\t\t}\n\t}\n\n\tpublic void DirtyMapMesh(Map map)\n\t{\n\t\tif (def.drawerType == DrawerType.RealtimeOnly)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tforeach (IntVec3 item in this.OccupiedRect())\n\t\t{\n\t\t\tmap.mapDrawer.MapMeshDirty(item, MapMeshFlagDefOf.Things);\n\t\t}\n\t}\n\n\tpublic virtual void DrawGUIOverlay()\n\t{\n\t\tif (Find.CameraDriver.CurrentZoom == CameraZoomRange.Closest)\n\t\t{\n\t\t\tQualityCategory qc;\n\t\t\tif (def.stackLimit > 1)\n\t\t\t{\n\t\t\t\tGenMapUI.DrawThingLabel(this, stackCount.ToStringCached());\n\t\t\t}\n\t\t\telse if (def.drawGUIOverlayQuality && this.TryGetQuality(out qc))\n\t\t\t{\n\t\t\t\tGenMapUI.DrawThingLabel(this, qc.GetLabelShort());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic virtual void DrawExtraSelectionOverlays()\n\t{\n\t\tif (def.specialDisplayRadius > 0.1f)\n\t\t{\n\t\t\tGenDraw.DrawRadiusRing(Position, def.specialDisplayRadius);\n\t\t}\n\t\tif (def.drawPlaceWorkersWhileSelected && def.PlaceWorkers != null)\n\t\t{\n\t\t\tfor (int i = 0; i < def.PlaceWorkers.Count; i++)\n\t\t\t{\n\t\t\t\tdef.PlaceWorkers[i].DrawGhost(def, Position, Rotation, Color.white, this);\n\t\t\t}\n\t\t}\n\t\tGenDraw.DrawInteractionCells(def, Position, rotationInt);\n\t}\n\n\tpublic virtual string GetInspectString()\n\t{\n\t\tStringBuilder stringBuilder = new StringBuilder();\n\t\tQuestUtility.AppendInspectStringsFromQuestParts(stringBuilder, this);\n\t\treturn stringBuilder.ToString();\n\t}\n\n\tpublic virtual string GetInspectStringLowPriority()\n\t{\n\t\tstring result = null;\n\t\ttmpDeteriorationReasons.Clear();\n\t\tfloat f = SteadyEnvironmentEffects.FinalDeteriorationRate(this, tmpDeteriorationReasons);\n\t\tif (tmpDeteriorationReasons.Count != 0)\n\t\t{\n\t\t\tresult = string.Format(\"{0}: {1} ({2})\", \"DeterioratingBecauseOf\".Translate(), tmpDeteriorationReasons.ToCommaList().CapitalizeFirst(), \"PerDay\".Translate(f.ToStringByStyle(ToStringStyle.FloatMaxTwo)));\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic virtual IEnumerable GetGizmos()\n\t{\n\t\tGizmo gizmo = ContainingSelectionUtility.SelectContainingThingGizmo(this);\n\t\tif (gizmo != null)\n\t\t{\n\t\t\tyield return gizmo;\n\t\t}\n\t\tshowingGizmosForRitualsTmp.Clear();\n\t\tforeach (Ideo ideo in Faction.OfPlayer.ideos.AllIdeos)\n\t\t{\n\t\t\tfor (int i = 0; i < ideo.PreceptsListForReading.Count; i++)\n\t\t\t{\n\t\t\t\tPrecept precept = ideo.PreceptsListForReading[i];\n\t\t\t\tif (!(precept is Precept_Ritual ritual) || (precept.def.mergeRitualGizmosFromAllIdeos && showingGizmosForRitualsTmp.Contains(ritual.sourcePattern)) || !ritual.ShouldShowGizmo(this))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tforeach (Gizmo item in ritual.GetGizmoFor(this))\n\t\t\t\t{\n\t\t\t\t\tyield return item;\n\t\t\t\t\tshowingGizmosForRitualsTmp.Add(ritual.sourcePattern);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tList activeRituals = Find.IdeoManager.GetActiveRituals(MapHeld);\n\t\tforeach (LordJob_Ritual item2 in activeRituals)\n\t\t{\n\t\t\tif (item2.selectedTarget == this)\n\t\t\t{\n\t\t\t\tyield return item2.GetCancelGizmo();\n\t\t\t}\n\t\t}\n\t\tif (ModsConfig.AnomalyActive)\n\t\t{\n\t\t\tGizmo gizmo2 = AnomalyUtility.OpenCodexGizmo(this);\n\t\t\tif (gizmo2 != null)\n\t\t\t{\n\t\t\t\tyield return gizmo2;\n\t\t\t}\n\t\t}\n\t\tif (DebugSettings.ShowDevGizmos && this.HasAttachment(ThingDefOf.Fire))\n\t\t{\n\t\t\tyield return new Command_Action\n\t\t\t{\n\t\t\t\tdefaultLabel = \"DEV: Extinguish\",\n\t\t\t\taction = delegate\n\t\t\t\t{\n\t\t\t\t\tthis.GetAttachment(ThingDefOf.Fire)?.Destroy();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\tpublic virtual IEnumerable GetFloatMenuOptions(Pawn selPawn)\n\t{\n\t\treturn Enumerable.Empty();\n\t}\n\n\tpublic virtual IEnumerable GetMultiSelectFloatMenuOptions(IEnumerable selPawns)\n\t{\n\t\treturn Enumerable.Empty();\n\t}\n\n\tpublic virtual IEnumerable GetInspectTabs()\n\t{\n\t\treturn def.inspectorTabsResolved;\n\t}\n\n\tpublic virtual string GetCustomLabelNoCount(bool includeHp = true)\n\t{\n\t\treturn GenLabel.ThingLabel(this, 1, includeHp);\n\t}\n\n\tpublic DamageWorker.DamageResult TakeDamage(DamageInfo dinfo)\n\t{\n\t\tif (Destroyed)\n\t\t{\n\t\t\treturn new DamageWorker.DamageResult();\n\t\t}\n\t\tif (dinfo.Amount == 0f)\n\t\t{\n\t\t\treturn new DamageWorker.DamageResult();\n\t\t}\n\t\tif (def.damageMultipliers != null)\n\t\t{\n\t\t\tfor (int i = 0; i < def.damageMultipliers.Count; i++)\n\t\t\t{\n\t\t\t\tif (def.damageMultipliers[i].damageDef == dinfo.Def)\n\t\t\t\t{\n\t\t\t\t\tint num = Mathf.RoundToInt(dinfo.Amount * def.damageMultipliers[i].multiplier);\n\t\t\t\t\tdinfo.SetAmount(num);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tPreApplyDamage(ref dinfo, out var absorbed);\n\t\tif (absorbed)\n\t\t{\n\t\t\treturn new DamageWorker.DamageResult();\n\t\t}\n\t\tbool spawnedOrAnyParentSpawned = SpawnedOrAnyParentSpawned;\n\t\tMap mapHeld = MapHeld;\n\t\tDamageWorker.DamageResult damageResult = dinfo.Def.Worker.Apply(dinfo, this);\n\t\tif (dinfo.Def.harmsHealth && spawnedOrAnyParentSpawned)\n\t\t{\n\t\t\tmapHeld.damageWatcher.Notify_DamageTaken(this, damageResult.totalDamageDealt);\n\t\t}\n\t\tif (dinfo.Instigator is Pawn pawn)\n\t\t{\n\t\t\tforeach (Hediff hediff in pawn.health.hediffSet.hediffs)\n\t\t\t{\n\t\t\t\thediff.Notify_PawnDamagedThing(this, dinfo, damageResult);\n\t\t\t}\n\t\t}\n\t\tif (dinfo.Def.ExternalViolenceFor(this))\n\t\t{\n\t\t\tif (dinfo.SpawnFilth)\n\t\t\t{\n\t\t\t\tGenLeaving.DropFilthDueToDamage(this, damageResult.totalDamageDealt);\n\t\t\t}\n\t\t\tif (dinfo.Instigator != null)\n\t\t\t{\n\t\t\t\tif (dinfo.Instigator is Pawn pawn2)\n\t\t\t\t{\n\t\t\t\t\tpawn2.records.AddTo(RecordDefOf.DamageDealt, damageResult.totalDamageDealt);\n\t\t\t\t}\n\t\t\t\tif (dinfo.Instigator.Faction == Faction.OfPlayer)\n\t\t\t\t{\n\t\t\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"TookDamageFromPlayer\", this.Named(\"SUBJECT\"), dinfo.Instigator.Named(\"INSTIGATOR\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"TookDamage\", this.Named(\"SUBJECT\"), dinfo.Instigator.Named(\"INSTIGATOR\"), mapHeld.Named(\"MAP\"));\n\t\t}\n\t\tif (!Destroyed && FlammableNow && dinfo.Def.igniteChanceByTargetFlammability != null && Rand.Chance(dinfo.Def.igniteChanceByTargetFlammability.Evaluate(this.GetStatValue(StatDefOf.Flammability))))\n\t\t{\n\t\t\tthis.TryAttachFire(Rand.Range(0.55f, 0.85f), dinfo.Instigator);\n\t\t}\n\t\tPostApplyDamage(dinfo, damageResult.totalDamageDealt);\n\t\treturn damageResult;\n\t}\n\n\tpublic virtual void PreApplyDamage(ref DamageInfo dinfo, out bool absorbed)\n\t{\n\t\tabsorbed = false;\n\t}\n\n\tpublic virtual void PostApplyDamage(DamageInfo dinfo, float totalDamageDealt)\n\t{\n\t}\n\n\tpublic virtual bool CanStackWith(Thing other)\n\t{\n\t\tif (Destroyed || other.Destroyed)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (def.category != ThingCategory.Item)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (this.IsRelic() || other.IsRelic())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (def == other.def)\n\t\t{\n\t\t\treturn Stuff == other.Stuff;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic virtual bool TryAbsorbStack(Thing other, bool respectStackLimit)\n\t{\n\t\tif (!CanStackWith(other))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tint num = ThingUtility.TryAbsorbStackNumToTake(this, other, respectStackLimit);\n\t\tif (def.useHitPoints)\n\t\t{\n\t\t\tHitPoints = Mathf.CeilToInt((float)(HitPoints * stackCount + other.HitPoints * num) / (float)(stackCount + num));\n\t\t}\n\t\tstackCount += num;\n\t\tother.stackCount -= num;\n\t\tif (Map != null)\n\t\t{\n\t\t\tDirtyMapMesh(Map);\n\t\t}\n\t\tStealAIDebugDrawer.Notify_ThingChanged(this);\n\t\tif (Spawned)\n\t\t{\n\t\t\tMap.listerMergeables.Notify_ThingStackChanged(this);\n\t\t}\n\t\tif (other.stackCount <= 0)\n\t\t{\n\t\t\tother.Destroy();\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic virtual Thing SplitOff(int count)\n\t{\n\t\tif (count <= 0)\n\t\t{\n\t\t\tthrow new ArgumentException(\"SplitOff with count <= 0\", \"count\");\n\t\t}\n\t\tif (count >= stackCount)\n\t\t{\n\t\t\tif (count > stackCount)\n\t\t\t{\n\t\t\t\tLog.Error(\"Tried to split off \" + count + \" of \" + this?.ToString() + \" but there are only \" + stackCount);\n\t\t\t}\n\t\t\tDeSpawnOrDeselect();\n\t\t\tholdingOwner?.Remove(this);\n\t\t\treturn this;\n\t\t}\n\t\tThing thing = ThingMaker.MakeThing(def, Stuff);\n\t\tthing.stackCount = count;\n\t\tstackCount -= count;\n\t\tif (Map != null)\n\t\t{\n\t\t\tDirtyMapMesh(Map);\n\t\t}\n\t\tif (Spawned)\n\t\t{\n\t\t\tMap.listerMergeables.Notify_ThingStackChanged(this);\n\t\t}\n\t\tif (def.useHitPoints)\n\t\t{\n\t\t\tthing.HitPoints = HitPoints;\n\t\t}\n\t\treturn thing;\n\t}\n\n\tpublic virtual IEnumerable SpecialDisplayStats()\n\t{\n\t\tif (Stuff != null)\n\t\t{\n\t\t\tyield return new StatDrawEntry(StatCategoryDefOf.BasicsImportant, \"Stat_Stuff_Name\".Translate(), Stuff.LabelCap, \"Stat_Stuff_Desc\".Translate(), 1100, null, new Dialog_InfoCard.Hyperlink[1]\n\t\t\t{\n\t\t\t\tnew Dialog_InfoCard.Hyperlink(Stuff)\n\t\t\t});\n\t\t}\n\t\tif (!ModsConfig.IdeologyActive || Find.IdeoManager.classicMode)\n\t\t{\n\t\t\tyield break;\n\t\t}\n\t\ttmpIdeoNames.Clear();\n\t\tStyleCategoryDef styleCategoryDef = StyleDef?.Category ?? def.dominantStyleCategory;\n\t\tif (styleCategoryDef == null)\n\t\t{\n\t\t\tyield break;\n\t\t}\n\t\tforeach (Ideo item in Find.IdeoManager.IdeosListForReading)\n\t\t{\n\t\t\tif (IdeoUtility.ThingSatisfiesIdeo(this, item))\n\t\t\t{\n\t\t\t\ttmpIdeoNames.Add(item.name.Colorize(item.Color));\n\t\t\t}\n\t\t}\n\t\tyield return new StatDrawEntry(StatCategoryDefOf.BasicsNonPawn, \"Stat_Thing_StyleDominanceCategory\".Translate(), styleCategoryDef.LabelCap, \"Stat_Thing_StyleDominanceCategoryDesc\".Translate() + \"\\n\\n\" + \"Stat_Thing_IdeosSatisfied\".Translate() + \":\" + \"\\n\" + tmpIdeoNames.ToLineList(\" - \"), 6005);\n\t}\n\n\tpublic virtual void Notify_ColorChanged()\n\t{\n\t\tgraphicInt = null;\n\t\tstyleGraphicInt = null;\n\t\tif (Spawned && (def.drawerType == DrawerType.MapMeshOnly || def.drawerType == DrawerType.MapMeshAndRealTime))\n\t\t{\n\t\t\tMap.mapDrawer.MapMeshDirty(Position, MapMeshFlagDefOf.Things);\n\t\t}\n\t}\n\n\tpublic virtual void Notify_Equipped(Pawn pawn)\n\t{\n\t}\n\n\tpublic virtual void Notify_Unequipped(Pawn pawn)\n\t{\n\t}\n\n\tpublic virtual void Notify_UsedVerb(Pawn pawn, Verb verb)\n\t{\n\t}\n\n\tpublic virtual void Notify_UsedWeapon(Pawn pawn)\n\t{\n\t}\n\n\tpublic virtual void Notify_DebugSpawned()\n\t{\n\t}\n\n\tpublic virtual void Notify_RecipeProduced(Pawn pawn)\n\t{\n\t}\n\n\tpublic virtual void Notify_SignalReceived(Signal signal)\n\t{\n\t}\n\n\tpublic virtual void Notify_Explosion(Explosion explosion)\n\t{\n\t}\n\n\tpublic virtual void Notify_BulletImpactNearby(BulletImpactData impactData)\n\t{\n\t}\n\n\tpublic virtual void Notify_ThingSelected()\n\t{\n\t}\n\n\tpublic virtual TipSignal GetTooltip()\n\t{\n\t\tstring text = LabelCap;\n\t\tif (def.useHitPoints)\n\t\t{\n\t\t\ttext = text + \"\\n\" + HitPoints + \" / \" + MaxHitPoints;\n\t\t}\n\t\treturn new TipSignal(text, thingIDNumber * 251235);\n\t}\n\n\tpublic virtual bool BlocksPawn(Pawn p)\n\t{\n\t\tif (def.passability == Traversability.Impassable)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\tif (def.IsFence && p.def.race.FenceBlocked)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void SetFactionDirect(Faction newFaction)\n\t{\n\t\tif (!def.CanHaveFaction)\n\t\t{\n\t\t\tLog.Error(\"Tried to SetFactionDirect on \" + this?.ToString() + \" which cannot have a faction.\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfactionInt = newFaction;\n\t\t}\n\t}\n\n\tpublic virtual void SetFaction(Faction newFaction, Pawn recruiter = null)\n\t{\n\t\tif (!def.CanHaveFaction)\n\t\t{\n\t\t\tLog.Error(\"Tried to SetFaction on \" + this?.ToString() + \" which cannot have a faction.\");\n\t\t\treturn;\n\t\t}\n\t\tFaction previous = factionInt;\n\t\tfactionInt = newFaction;\n\t\tif (Spawned && this is IAttackTarget t)\n\t\t{\n\t\t\tMap.attackTargetsCache.UpdateTarget(t);\n\t\t}\n\t\tQuestUtility.SendQuestTargetSignals(questTags, \"ChangedFaction\", this.Named(\"SUBJECT\"), newFaction.Named(\"FACTION\"));\n\t\tif (newFaction != Faction.OfPlayer)\n\t\t{\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"ChangedFactionToNonPlayer\", this.Named(\"SUBJECT\"), newFaction.Named(\"FACTION\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tQuestUtility.SendQuestTargetSignals(questTags, \"ChangedFactionToPlayer\", this.Named(\"SUBJECT\"), newFaction.Named(\"FACTION\"));\n\t\t}\n\t\tif (Spawned)\n\t\t{\n\t\t\tMap.events.Notify_ThingFactionChanged(previous, factionInt);\n\t\t}\n\t}\n\n\tpublic virtual AcceptanceReport ClaimableBy(Faction by)\n\t{\n\t\treturn false;\n\t}\n\n\tpublic virtual bool AdoptableBy(Faction by, StringBuilder reason = null)\n\t{\n\t\treturn false;\n\t}\n\n\tpublic bool FactionPreventsClaimingOrAdopting(Faction faction, bool forClaim, out string reason)\n\t{\n\t\treason = null;\n\t\tif (faction == null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (faction == Faction.OfInsects)\n\t\t{\n\t\t\tif (HiveUtility.AnyHivePreventsClaiming(this))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse if (faction == Faction.OfMechanoids)\n\t\t{\n\t\t\tforeach (IAttackTarget item in MapHeld.attackTargetsCache.TargetsHostileToFaction(Faction.OfPlayer))\n\t\t\t{\n\t\t\t\tif (item.Thing == null || item.Thing.Faction != faction)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (item.Thing is Pawn pawn)\n\t\t\t\t{\n\t\t\t\t\tif (GenHostility.IsActiveThreatToPlayer(pawn))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (forClaim)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason = \"MessageCannotClaimWhenPawnThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), pawn.Named(\"THREAT\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason = \"MessageCannotAdoptWhilePawnThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), pawn.Named(\"THREAT\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (forClaim)\n\t\t\t\t{\n\t\t\t\t\treason = \"MessageCannotClaimWhenThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), item.Named(\"THREAT\"));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treason = \"MessageCannotAdoptWhileThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), item.Named(\"THREAT\"));\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (faction == Faction.OfAncients && Spawned && !Map.IsPlayerHome && GenHostility.AnyHostileActiveThreatToPlayer(Map, countDormantPawnsAsHostile: true, canBeFogged: true))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (Spawned && faction != Faction.OfPlayer)\n\t\t\t{\n\t\t\t\tList list = Map.mapPawns.SpawnedPawnsInFaction(faction);\n\t\t\t\tfor (int i = 0; i < list.Count; i++)\n\t\t\t\t{\n\t\t\t\t\tif (list[i].RaceProps.ToolUser && GenHostility.IsPotentialThreat(list[i]))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (forClaim)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason = \"MessageCannotClaimWhenThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), list[i].Named(\"THREAT\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treason = \"MessageCannotAdoptWhileThreatsAreNear\".Translate(this.Named(\"CLAIMABLE\"), list[i].Named(\"THREAT\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void SetPositionDirect(IntVec3 newPos)\n\t{\n\t\tpositionInt = newPos;\n\t}\n\n\tpublic void SetStuffDirect(ThingDef newStuff)\n\t{\n\t\tstuffInt = newStuff;\n\t}\n\n\tpublic override string ToString()\n\t{\n\t\tif (def != null)\n\t\t{\n\t\t\treturn ThingID;\n\t\t}\n\t\treturn GetType().ToString();\n\t}\n\n\tpublic bool Equals(Thing other)\n\t{\n\t\tif (other == null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (def.category == ThingCategory.Mote)\n\t\t{\n\t\t\treturn this == other;\n\t\t}\n\t\tif (thingIDNumber == other.thingIDNumber)\n\t\t{\n\t\t\treturn def.Equals(other.def);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic override int GetHashCode()\n\t{\n\t\tif (thingIDNumber == -1)\n\t\t{\n\t\t\treturn base.GetHashCode();\n\t\t}\n\t\treturn thingIDNumber;\n\t}\n\n\tpublic virtual void Discard(bool silentlyRemoveReferences = false)\n\t{\n\t\tif (mapIndexOrState != -2)\n\t\t{\n\t\t\tLog.Warning(\"Tried to discard \" + this?.ToString() + \" whose state is \" + mapIndexOrState + \".\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmapIndexOrState = -3;\n\t\t}\n\t}\n\n\tpublic virtual void Notify_DefsHotReloaded()\n\t{\n\t\tgraphicInt = null;\n\t}\n\n\tpublic virtual IEnumerable ButcherProducts(Pawn butcher, float efficiency)\n\t{\n\t\tif (def.butcherProducts == null)\n\t\t{\n\t\t\tyield break;\n\t\t}\n\t\tfor (int i = 0; i < def.butcherProducts.Count; i++)\n\t\t{\n\t\t\tThingDefCountClass thingDefCountClass = def.butcherProducts[i];\n\t\t\tint num = GenMath.RoundRandom((float)thingDefCountClass.count * efficiency);\n\t\t\tif (num > 0)\n\t\t\t{\n\t\t\t\tThing thing = ThingMaker.MakeThing(thingDefCountClass.thingDef);\n\t\t\t\tthing.stackCount = num;\n\t\t\t\tyield return thing;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic virtual IEnumerable SmeltProducts(float efficiency)\n\t{\n\t\tList costListAdj = def.CostListAdjusted(Stuff);\n\t\tfor (int i = 0; i < costListAdj.Count; i++)\n\t\t{\n\t\t\tif (!costListAdj[i].thingDef.intricate && costListAdj[i].thingDef.smeltable)\n\t\t\t{\n\t\t\t\tint num = GenMath.RoundRandom((float)costListAdj[i].count * 0.25f);\n\t\t\t\tif (num > 0)\n\t\t\t\t{\n\t\t\t\t\tThing thing = ThingMaker.MakeThing(costListAdj[i].thingDef);\n\t\t\t\t\tthing.stackCount = num;\n\t\t\t\t\tyield return thing;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (def.smeltProducts != null)\n\t\t{\n\t\t\tfor (int i = 0; i < def.smeltProducts.Count; i++)\n\t\t\t{\n\t\t\t\tThingDefCountClass thingDefCountClass = def.smeltProducts[i];\n\t\t\t\tThing thing2 = ThingMaker.MakeThing(thingDefCountClass.thingDef);\n\t\t\t\tthing2.stackCount = thingDefCountClass.count;\n\t\t\t\tyield return thing2;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic float Ingested(Pawn ingester, float nutritionWanted)\n\t{\n\t\tif (Destroyed)\n\t\t{\n\t\t\tLog.Error(ingester?.ToString() + \" ingested destroyed thing \" + this);\n\t\t\treturn 0f;\n\t\t}\n\t\tif (!IngestibleNow)\n\t\t{\n\t\t\tLog.Error(ingester?.ToString() + \" ingested IngestibleNow=false thing \" + this);\n\t\t\treturn 0f;\n\t\t}\n\t\tingester.mindState.lastIngestTick = Find.TickManager.TicksGame;\n\t\tif (ingester.needs.mood != null)\n\t\t{\n\t\t\tList list = FoodUtility.ThoughtsFromIngesting(ingester, this, def);\n\t\t\tfor (int i = 0; i < list.Count; i++)\n\t\t\t{\n\t\t\t\tThought_Memory thought_Memory = ThoughtMaker.MakeThought(list[i].thought, list[i].fromPrecept);\n\t\t\t\tif (thought_Memory is Thought_FoodEaten thought_FoodEaten)\n\t\t\t\t{\n\t\t\t\t\tthought_FoodEaten.SetFood(this);\n\t\t\t\t}\n\t\t\t\tingester.needs.mood.thoughts.memories.TryGainMemory(thought_Memory);\n\t\t\t}\n\t\t}\n\t\tingester.needs.drugsDesire?.Notify_IngestedDrug(this);\n\t\tbool flag = FoodUtility.IsHumanlikeCorpseOrHumanlikeMeat(this, def);\n\t\tbool flag2 = FoodUtility.IsHumanlikeCorpseOrHumanlikeMeatOrIngredient(this);\n\t\tif (flag && ingester.IsColonist)\n\t\t{\n\t\t\tTaleRecorder.RecordTale(TaleDefOf.AteRawHumanlikeMeat, ingester);\n\t\t}\n\t\tif (flag2)\n\t\t{\n\t\t\tingester.mindState.lastHumanMeatIngestedTick = Find.TickManager.TicksGame;\n\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteHumanMeat, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\tif (flag)\n\t\t\t{\n\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteHumanMeatDirect, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t}\n\t\t}\n\t\telse if (ModsConfig.IdeologyActive && !FoodUtility.AcceptableCannibalNonHumanlikeMeatFood(def))\n\t\t{\n\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteNonCannibalFood, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t}\n\t\tif (def.ingestible.ateEvent != null)\n\t\t{\n\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(def.ingestible.ateEvent, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t}\n\t\tif (ModsConfig.IdeologyActive)\n\t\t{\n\t\t\tFoodKind foodKind = FoodUtility.GetFoodKind(this);\n\t\t\tif (foodKind != FoodKind.Any && !def.IsProcessedFood)\n\t\t\t{\n\t\t\t\tif (foodKind == FoodKind.Meat)\n\t\t\t\t{\n\t\t\t\t\tif (!flag2)\n\t\t\t\t\t{\n\t\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteMeat, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (!def.IsDrug && def.ingestible.CachedNutrition > 0f)\n\t\t\t\t{\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteNonMeat, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (FoodUtility.IsVeneratedAnimalMeatOrCorpseOrHasIngredients(this, ingester))\n\t\t\t{\n\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteVeneratedAnimalMeat, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t}\n\t\t\tif (def.thingCategories != null && def.thingCategories.Contains(ThingCategoryDefOf.PlantFoodRaw))\n\t\t\t{\n\t\t\t\tif (def.IsFungus)\n\t\t\t\t{\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteFungus, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteNonFungusPlant, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCompIngredients compIngredients = this.TryGetComp();\n\t\tif (compIngredients != null)\n\t\t{\n\t\t\tbool flag3 = false;\n\t\t\tbool flag4 = false;\n\t\t\tbool flag5 = false;\n\t\t\tbool flag6 = false;\n\t\t\tbool flag7 = false;\n\t\t\tfor (int j = 0; j < compIngredients.ingredients.Count; j++)\n\t\t\t{\n\t\t\t\tif (!flag3 && FoodUtility.GetMeatSourceCategory(compIngredients.ingredients[j]) == MeatSourceCategory.Humanlike)\n\t\t\t\t{\n\t\t\t\t\tingester.mindState.lastHumanMeatIngestedTick = Find.TickManager.TicksGame;\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteHumanMeatAsIngredient, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t\tflag3 = true;\n\t\t\t\t}\n\t\t\t\telse if (!flag4 && ingester.Ideo != null && compIngredients.ingredients[j].IsMeat && ingester.Ideo.IsVeneratedAnimal(compIngredients.ingredients[j].ingestible.sourceDef))\n\t\t\t\t{\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteVeneratedAnimalMeat, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t\tflag4 = true;\n\t\t\t\t}\n\t\t\t\tif (!flag5 && FoodUtility.GetMeatSourceCategory(compIngredients.ingredients[j]) == MeatSourceCategory.Insect)\n\t\t\t\t{\n\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteInsectMeatAsIngredient, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t\tflag5 = true;\n\t\t\t\t}\n\t\t\t\tif (ModsConfig.IdeologyActive && !flag6 && compIngredients.ingredients[j].thingCategories.Contains(ThingCategoryDefOf.PlantFoodRaw))\n\t\t\t\t{\n\t\t\t\t\tif (compIngredients.ingredients[j].IsFungus)\n\t\t\t\t\t{\n\t\t\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteFungusAsIngredient, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t\t\t\tflag6 = true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tflag7 = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ModsConfig.IdeologyActive && !flag6 && flag7)\n\t\t\t{\n\t\t\t\tFind.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.AteNonFungusMealWithPlants, ingester.Named(HistoryEventArgsNames.Doer)), canApplySelfTookThoughts: false);\n\t\t\t}\n\t\t}\n\t\tIngestedCalculateAmounts(ingester, nutritionWanted, out var numTaken, out var nutritionIngested);\n\t\tif (!ingester.Dead && ingester.needs.joy != null && Mathf.Abs(def.ingestible.joy) > 0.0001f && numTaken > 0)\n\t\t{\n\t\t\tingester.needs.joy.GainJoy((float)numTaken * def.ingestible.joy, def.ingestible.joyKind ?? JoyKindDefOf.Gluttonous);\n\t\t}\n\t\tfloat poisonChanceOverride;\n\t\tfloat chance = (FoodUtility.TryGetFoodPoisoningChanceOverrideFromTraits(ingester, this, out poisonChanceOverride) ? poisonChanceOverride : (this.GetStatValue(StatDefOf.FoodPoisonChanceFixedHuman) * FoodUtility.GetFoodPoisonChanceFactor(ingester)));\n\t\tif (ingester.RaceProps.Humanlike && Rand.Chance(chance))\n\t\t{\n\t\t\tFoodUtility.AddFoodPoisoningHediff(ingester, this, FoodPoisonCause.DangerousFoodType);\n\t\t}\n\t\tList hediffs = ingester.health.hediffSet.hediffs;\n\t\tfor (int k = 0; k < hediffs.Count; k++)\n\t\t{\n\t\t\thediffs[k].Notify_IngestedThing(this, numTaken);\n\t\t}\n\t\tingester.genes?.Notify_IngestedThing(this, numTaken);\n\t\tbool flag8 = false;\n\t\tif (numTaken > 0)\n\t\t{\n\t\t\tif (stackCount == 0)\n\t\t\t{\n\t\t\t\tLog.Error(this?.ToString() + \" stack count is 0.\");\n\t\t\t}\n\t\t\tif (numTaken == stackCount)\n\t\t\t{\n\t\t\t\tflag8 = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSplitOff(numTaken);\n\t\t\t}\n\t\t}\n\t\tPrePostIngested(ingester);\n\t\tif (flag8)\n\t\t{\n\t\t\tingester.carryTracker.innerContainer.Remove(this);\n\t\t}\n\t\tif (def.ingestible.outcomeDoers != null)\n\t\t{\n\t\t\tfor (int l = 0; l < def.ingestible.outcomeDoers.Count; l++)\n\t\t\t{\n\t\t\t\tdef.ingestible.outcomeDoers[l].DoIngestionOutcome(ingester, this, numTaken);\n\t\t\t}\n\t\t}\n\t\tif (flag8 && !Destroyed)\n\t\t{\n\t\t\tDestroy();\n\t\t}\n\t\tPostIngested(ingester);\n\t\treturn nutritionIngested;\n\t}\n\n\tprotected virtual void PrePostIngested(Pawn ingester)\n\t{\n\t}\n\n\tprotected virtual void PostIngested(Pawn ingester)\n\t{\n\t}\n\n\tprotected virtual void IngestedCalculateAmounts(Pawn ingester, float nutritionWanted, out int numTaken, out float nutritionIngested)\n\t{\n\t\tfloat num = FoodUtility.NutritionForEater(ingester, this);\n\t\tnumTaken = Mathf.CeilToInt(nutritionWanted / num);\n\t\tnumTaken = Mathf.Min(numTaken, stackCount);\n\t\tif (def.ingestible.maxNumToIngestAtOnce > 0)\n\t\t{\n\t\t\tnumTaken = Mathf.Min(numTaken, def.ingestible.maxNumToIngestAtOnce);\n\t\t}\n\t\tnumTaken = Mathf.Max(numTaken, 1);\n\t\tnutritionIngested = (float)numTaken * num;\n\t}\n\n\tpublic virtual bool PreventPlayerSellingThingsNearby(out string reason)\n\t{\n\t\treason = null;\n\t\treturn false;\n\t}\n\n\tpublic virtual void PreSwapMap()\n\t{\n\t\tbeingTransportedOnGravship = true;\n\t}\n\n\tpublic virtual void PostSwapMap()\n\t{\n\t\tbeingTransportedOnGravship = false;\n\t\tQuestUtility.SendQuestTargetSignals(questTags, \"SwappedMap\", this.Named(\"SUBJECT\"));\n\t}\n\n\tpublic void Notify_LeftBehind()\n\t{\n\t\tQuestUtility.SendQuestTargetSignals(questTags, \"LeftBehind\", this.Named(\"SUBJECT\"));\n\t\tif (!(this is IThingHolder thingHolder) || thingHolder.GetDirectlyHeldThings() == null)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tforeach (Thing item in (IEnumerable)thingHolder.GetDirectlyHeldThings())\n\t\t{\n\t\t\titem.Notify_LeftBehind();\n\t\t}\n\t}\n}\n\n", "timestamp": "2025-08-25 14:10:31,694" + }, + "MapPortal": { + "keywords": [ + "MapPortal" + ], + "question": "MapPortal class definition", + "embedding": [ + -0.004828896373510361, + 0.044337302446365356, + 0.01690523698925972, + -0.03522060811519623, + -0.003080573631450534, + 0.00954301469027996, + -0.020119035616517067, + 0.042238496243953705, + 0.028497867286205292, + 0.07752469182014465, + 0.04843653738498688, + -0.0265138391405344, + -0.04653449356555939, + 0.0222342386841774, + -0.00924786925315857, + 0.03735221177339554, + -0.0023529597092419863, + -0.09300339967012405, + -0.06053747236728668, + 0.02067653089761734, + 0.003947561141103506, + 0.03761456161737442, + 0.04168099910020828, + -0.04633772745728493, + 0.004304194822907448, + 0.0005006188293918967, + 0.01136307418346405, + 0.017741480842232704, + 0.027546845376491547, + -0.01890566200017929, + -0.009001915343105793, + -0.009116694331169128, + 0.03535178676247597, + -0.03177725523710251, + 0.051748715341091156, + 0.00955941155552864, + -0.025382449850440025, + 0.018118608742952347, + 0.0207913089543581, + 0.005185529589653015, + -0.03349893167614937, + 0.002933001145720482, + -0.017610304057598114, + 0.010912158526480198, + -0.010469441302120686, + 0.006845719181001186, + 0.015560688450932503, + -0.029563667252659798, + -0.061029378324747086, + -0.015905024483799934, + -0.012863392941653728, + 0.022283431142568588, + 0.03243312984704971, + 0.013174934312701225, + 0.01875809021294117, + 0.015626275911927223, + 0.028973378241062164, + -0.0341712050139904, + 0.005070751067250967, + 0.03456473350524902, + 0.01906963251531124, + -0.005070751067250967, + -0.0457802340388298, + -0.00038891471922397614, + 0.016569100320339203, + -0.010641608387231827, + -0.00427959905937314, + 0.000527776253875345, + -0.02100447006523609, + -0.03574531152844429, + 0.03394164890050888, + 0.036761920899152756, + -0.021758727729320526, + 0.031301744282245636, + -0.014814628288149834, + 0.013388094492256641, + -0.01142866164445877, + -0.03640118986368179, + -0.01872529648244381, + -0.026907365769147873, + -0.02085689641535282, + 0.022267034277319908, + -0.01895485259592533, + -0.013757025822997093, + -0.0028100241906940937, + 0.05263414978981018, + 0.0419105589389801, + -0.007776245009154081, + 0.00847721379250288, + 0.02033219486474991, + 0.040926743298769, + -0.010576020926237106, + 0.012527256272733212, + -0.016454320400953293, + 0.02789118140935898, + 0.014429300092160702, + -0.023873932659626007, + -0.04709198698401451, + 0.01702001504600048, + 0.04017248377203941, + -0.04013969004154205, + -0.025644801557064056, + -0.06634198874235153, + 0.0024185474030673504, + -0.031137773767113686, + 0.01506058219820261, + -0.03931984305381775, + 0.030727850273251534, + -0.011928767897188663, + -0.015396718867123127, + 0.01890566200017929, + -0.055651187896728516, + -0.0064644902013242245, + 0.08021379262208939, + -0.012806003913283348, + 0.03768014907836914, + 0.032941434532403946, + 0.008854343555867672, + 0.0025415243580937386, + 0.04295996204018593, + 0.023168863728642464, + 0.01407676562666893, + 0.011149914003908634, + -0.025448037311434746, + -0.0132569195702672, + 0.04440288990736008, + -0.017987433820962906, + -0.0035007449332624674, + -0.028874997049570084, + 0.004304194822907448, + -0.01406036876142025, + -0.007099871523678303, + 0.0032937335781753063, + 0.002031169831752777, + -0.0279567688703537, + -0.03564693033695221, + 0.03213798627257347, + -0.04384539648890495, + -0.0680144727230072, + -0.005587254650890827, + -0.08919931203126907, + 0.009895548224449158, + -0.008846145123243332, + 0.003756946884095669, + 0.006214437074959278, + 0.006144750397652388, + -0.01900404319167137, + -0.021906301379203796, + -0.008095985278487206, + -0.004357484634965658, + -0.0066653527319431305, + 0.006370208226144314, + -0.02831750176846981, + 0.04699360579252243, + 0.01405217032879591, + -0.05502810329198837, + 0.009969334118068218, + -0.04459965601563454, + -0.004759209230542183, + -0.05827469378709793, + -0.029694844037294388, + 0.004078736994415522, + -0.023775551468133926, + -0.04305834323167801, + 0.005128140561282635, + 0.003418760374188423, + 0.01854492910206318, + 0.04564905911684036, + -0.022267034277319908, + -0.05289650335907936, + 0.01867610588669777, + -0.01726596988737583, + -0.014355514198541641, + -0.010084113106131554, + 0.08336199820041656, + -0.05210945010185242, + 0.009411838836967945, + 0.06034070998430252, + 0.025726785883307457, + -0.05981600657105446, + 0.014568673446774483, + 0.009977532550692558, + 0.09254427999258041, + -0.01705280877649784, + 0.019282791763544083, + -0.030481895431876183, + -0.04650169983506203, + 0.04692801833152771, + -0.006710444111377001, + 0.0012625637464225292, + 0.03561413660645485, + -0.019676318392157555, + -0.011281088925898075, + 0.010059517808258533, + -0.0633249506354332, + -0.025743182748556137, + 0.0068703144788742065, + -0.023611580953001976, + -0.034728702157735825, + -0.03781132400035858, + 0.012863392941653728, + 0.0170856025069952, + 0.010862966999411583, + 0.012625637464225292, + 0.04361584037542343, + 0.004664927255362272, + 0.01406036876142025, + -0.02090608887374401, + 0.014945803210139275, + -0.0074974969029426575, + 0.02082410268485546, + 0.01402757503092289, + 0.00839522946625948, + -0.017364351078867912, + -0.031268950551748276, + -0.02816992811858654, + -0.012879789806902409, + -0.025661198422312737, + 0.011764798313379288, + -0.007349924650043249, + -0.04374701529741287, + 0.049617115408182144, + 0.02830110490322113, + 0.004146374296396971, + 0.029120950028300285, + 0.051584746688604355, + 0.00612015463411808, + 0.011830386705696583, + 0.003224046668037772, + 0.011887775734066963, + 0.001663263770751655, + 0.008731366135179996, + -0.006821123417466879, + 0.06411200016736984, + 0.023841138929128647, + -0.0076983594335615635, + -0.007727053947746754, + -0.015257344581186771, + -0.013470079749822617, + 0.0003492034156806767, + -0.004751010797917843, + 0.03909028694033623, + 0.0012851095525547862, + 0.004832995589822531, + 0.022070270031690598, + -0.060996584594249725, + -0.015281940810382366, + 0.030990201979875565, + 0.0712282732129097, + -0.047879040241241455, + 0.04905961826443672, + -0.008714969269931316, + 0.01895485259592533, + 0.011723806150257587, + 0.04843653738498688, + -0.013174934312701225, + -0.011699210852384567, + -0.003918866626918316, + 0.05214224383234978, + -0.002838718704879284, + -0.005464277695864439, + 0.014667055569589138, + -0.01902044005692005, + 0.017479129135608673, + -0.0227261483669281, + -0.010018525645136833, + 0.00664075743407011, + 0.04476362466812134, + -0.018184198066592216, + -0.06253790110349655, + -0.013699636794626713, + 0.0419105589389801, + 0.02098807319998741, + -0.023267246782779694, + -0.03725383058190346, + -0.03522060811519623, + 0.012650232762098312, + -0.006017673760652542, + 0.0048944843001663685, + -0.030826231464743614, + -0.012018950656056404, + -0.003041630843654275, + -0.012478064745664597, + 0.03643398359417915, + -0.004927278030663729, + 0.017364351078867912, + 0.02423466555774212, + 0.022168651223182678, + 0.015650872141122818, + -0.027841990813612938, + 0.036663539707660675, + -0.010116906836628914, + 0.0170036181807518, + -0.002180791925638914, + -0.00925606768578291, + 0.03410561755299568, + -0.03764735534787178, + 0.04348466172814369, + -0.01893845573067665, + 0.00477970577776432, + -0.053749144077301025, + 0.006915405858308077, + -0.0037630959413945675, + 0.027415670454502106, + 0.04856771230697632, + -0.015511497855186462, + -0.006443994119763374, + -0.1269778460264206, + 0.07699999213218689, + -0.10133303701877594, + 0.03218717873096466, + 0.0013189282035455108, + -0.03895910829305649, + 0.028858600184321404, + 0.006427597254514694, + -0.04154982417821884, + -0.006218536291271448, + 0.018200594931840897, + -0.008608389645814896, + 0.024808557704091072, + -0.0340072363615036, + 0.0008879963424988091, + 0.06594845652580261, + 0.007349924650043249, + 0.04499318078160286, + -0.01893845573067665, + 0.005345399957150221, + 0.005718430038541555, + -0.008391129784286022, + -0.03800808638334274, + 0.0034966457169502974, + 0.019938668236136436, + -0.013388094492256641, + 0.04063159599900246, + -0.04722316190600395, + 0.027481257915496826, + 0.026759792119264603, + 0.01895485259592533, + 0.0008726242231205106, + -0.03225276619195938, + 0.020283004269003868, + 0.05470016598701477, + 0.021758727729320526, + -0.008665778674185276, + 0.03879513964056969, + 0.05824190005660057, + 0.053322821855545044, + 0.038532789796590805, + 0.0207913089543581, + 0.013847208581864834, + -0.06388244777917862, + 0.0004988253931514919, + 0.046009790152311325, + 0.04112350568175316, + 0.02033219486474991, + -0.01898764632642269, + 0.027120525017380714, + 0.004861690104007721, + -0.055224865674972534, + -0.00427959905937314, + -0.005517567507922649, + 0.015191757120192051, + -0.0025661198887974024, + 0.047682277858257294, + 0.04738713428378105, + 0.015544291585683823, + -0.04837094992399216, + 0.01410136092454195, + -0.0676865354180336, + 0.024956129491329193, + -0.009157686494290829, + -0.03131813928484917, + 0.012806003913283348, + 0.0316624753177166, + -0.05417546257376671, + 0.05460178107023239, + 0.007300734054297209, + 0.006538276560604572, + 0.01715118996798992, + 0.030908215790987015, + -0.011026936583220959, + -0.0014787983382120728, + -0.04197614639997482, + -0.05227341875433922, + -0.008714969269931316, + -0.026776188984513283, + -0.0024021505378186703, + -0.0068621160462498665, + 0.02443142794072628, + -0.06237392872571945, + 0.018331769853830338, + 0.00848541222512722, + 0.014806429855525494, + 0.0009694686159491539, + 0.008928129449486732, + 0.0013875903096050024, + 0.0006174469599500299, + 0.002326314803212881, + 0.033138200640678406, + -0.025070909410715103, + 0.008739564567804337, + -0.0057389261201024055, + 0.06558772921562195, + -0.015724657103419304, + 0.03564693033695221, + 0.01142866164445877, + -0.0013732430525124073, + 0.007362222298979759, + -0.015240947715938091, + -0.008243557065725327, + -0.016421526670455933, + 0.00306417653337121, + 0.04292716830968857, + 0.0016089489217847586, + -0.047715071588754654, + 0.016036199405789375, + 0.014248933643102646, + -0.0018712998135015368, + 0.01887286826968193, + -0.0023017192725092173, + 0.0036052754148840904, + 0.01724957302212715, + -0.021955491974949837, + -0.02420187182724476, + -0.0036483174189925194, + 0.0725400298833847, + -0.005743025336414576, + 0.005066651850938797, + 0.019479554146528244, + 0.004714117851108313, + 0.03512222692370415, + 0.0024820854887366295, + -0.008780556730926037, + 0.05273253098130226, + 0.019200807437300682, + -0.03003917820751667, + 0.027727210894227028, + -0.0244150310754776, + -0.02989160642027855, + -0.010936753824353218, + -0.06499743461608887, + -0.007759848143905401, + -0.010010327212512493, + -0.021397996693849564, + -0.04896123707294464, + -0.07194973528385162, + 0.030727850273251534, + 0.010141502134501934, + 0.04204173386096954, + 0.02466098591685295, + 0.011781195178627968, + 0.011904172599315643, + 0.06168525665998459, + -0.0028633142355829477, + 0.03361371159553528, + 0.04128747433423996, + -0.03146571293473244, + -0.03356451913714409, + -0.007202352397143841, + 0.027743607759475708, + 0.03912308067083359, + -0.019463157281279564, + -0.012978171929717064, + -0.02607112191617489, + -0.004746911581605673, + 0.007522092666476965, + 0.011789393611252308, + -0.009141289629042149, + -0.07837733626365662, + -0.05296209082007408, + -0.03525340184569359, + 0.036663539707660675, + 0.06148849427700043, + 0.0035417373292148113, + 0.02238181233406067, + -0.05279812216758728, + -0.036532364785671234, + 0.031301744282245636, + 0.009444632567465305, + 0.04066438972949982, + -0.026972953230142593, + 0.012469866313040257, + 0.011559836566448212, + -0.009411838836967945, + -0.09195399284362793, + -0.0802793800830841, + 0.012535454705357552, + -0.05620868131518364, + 0.04115629941225052, + 0.009747975505888462, + -0.05420825630426407, + -0.00926426611840725, + -0.00607506325468421, + 0.023988710716366768, + -0.044337302446365356, + 0.0013445484219118953, + 0.034761495888233185, + 0.03518781438469887, + 0.023267246782779694, + -0.008300947025418282, + 0.03397444263100624, + 0.013748827390372753, + 0.005968483164906502, + -0.018167801201343536, + -0.05791396275162697, + 0.0045911408960819244, + -0.03718824312090874, + 0.0009115669527091086, + -0.05663500353693962, + -0.004886285867542028, + 0.04095953702926636, + 0.038663964718580246, + 0.034400761127471924, + -0.009198678657412529, + -0.014339116401970387, + 0.01038745604455471, + 0.0414186492562294, + 0.03528619557619095, + -0.014175147749483585, + -0.025628404691815376, + -0.029465286061167717, + -0.0017339754849672318, + -0.011592631228268147, + -0.0132569195702672, + -0.047813452780246735, + 0.049879465252161026, + 0.007149062119424343, + 0.01607719250023365, + 0.0265958234667778, + 0.00043067566002719104, + -0.019938668236136436, + 0.05240459367632866, + -0.042238496243953705, + -0.02270974963903427, + 0.02592354826629162, + -0.004328790120780468, + -0.0004760234151035547, + 0.015191757120192051, + 0.03548296168446541, + 0.09851276874542236, + -0.01667567901313305, + -0.03587648645043373, + 0.0003909643564838916, + 0.005468376912176609, + 0.027563242241740227, + -0.019971463829278946, + 0.025907151401042938, + -0.017807068303227425, + -0.02034859172999859, + -0.013912796974182129, + 0.003256840631365776, + 0.0012164473300799727, + 0.016380535438656807, + -0.04004130885004997, + 0.014806429855525494, + -0.022037476301193237, + 0.00841162633150816, + 0.057323671877384186, + 0.018069418147206306, + 0.006985093001276255, + 0.01323232427239418, + -0.022955704480409622, + -0.031055789440870285, + 0.011740203015506268, + -0.01888926513493061, + 0.018216991797089577, + -0.003756946884095669, + -0.030514689162373543, + -0.03358091786503792, + 0.011518844403326511, + -0.055487215518951416, + 0.02254578098654747, + -0.025300465524196625, + -0.006796528119593859, + 0.047846246510744095, + 0.06814564764499664, + -0.047846246510744095, + 0.011732004582881927, + 0.034400761127471924, + 0.004345186986029148, + -0.009846357628703117, + 0.029694844037294388, + -0.040238071233034134, + -0.0457802340388298, + -0.019381172955036163, + 0.02246379666030407, + 0.01682325266301632, + -0.016249358654022217, + -0.006222635507583618, + -0.0728679671883583, + 0.029366904869675636, + 0.006911306641995907, + -0.04912520945072174, + -0.0074933976866304874, + -0.034794289618730545, + 0.04440288990736008, + 0.010772784240543842, + -0.014503085985779762, + 0.016733068972826004, + 0.0018405555747449398, + 0.004150473512709141, + 0.0005656941211782396, + -0.025234878063201904, + 0.005583155434578657, + -0.02462819218635559, + 0.0037712943740189075, + 0.01395378913730383, + 0.03225276619195938, + 0.025841563940048218, + -0.01627395488321781, + -0.042697612196207047, + 0.023185262456536293, + -0.06020953506231308, + -0.0020219467114657164, + 0.030678659677505493, + 0.008382931351661682, + 0.010477639734745026, + 0.04099233075976372, + -0.004035694990307093, + 0.010584219358861446, + 0.03143291920423508, + -0.015790244564414024, + 0.03340055048465729, + -0.023218056187033653, + 0.03800808638334274, + 0.03535178676247597, + 0.06788329780101776, + -0.011674615554511547, + -0.01222391240298748, + -0.005800414830446243, + -0.012043545953929424, + 0.007681962568312883, + -0.013740628957748413, + 0.04328789934515953, + 0.04905961826443672, + -0.007198253180831671, + -0.014757238328456879, + 0.00427549984306097, + 0.017479129135608673, + -0.033007021993398666, + -0.005960284732282162, + -0.02236541546881199, + 0.02828470803797245, + -0.01706920564174652, + -0.040238071233034134, + -0.02284092642366886, + -0.044107746332883835, + -0.031301744282245636, + -0.005017461255192757, + 0.006398902740329504, + 0.030514689162373543, + 0.048239775002002716, + 0.03604045510292053, + -0.011018738150596619, + -0.02218504808843136, + -0.015823038294911385, + -0.03361371159553528, + -0.03577810525894165, + -0.0009868902852758765, + -0.04391098394989967, + -0.036565158516168594, + 0.002383704064413905, + 0.01620836742222309, + 0.026808982715010643, + -0.038434408605098724, + 0.03325297683477402, + 0.015437711030244827, + -0.019249998033046722, + -0.010059517808258533, + 0.002838718704879284, + 0.0016468667890876532, + -0.02846507355570793, + 0.00030206222436390817, + 0.00424680532887578, + -0.0009412863873876631, + -0.04194335266947746, + -0.08395229279994965, + -0.014839223586022854, + 0.05476575344800949, + -0.019512349739670753, + 0.04256643354892731, + 0.06503023207187653, + -0.02789118140935898, + -0.0281207375228405, + -0.01687244325876236, + -0.020102638751268387, + -0.009870952926576138, + -0.007304833270609379, + -0.06548934429883957, + 0.030957406386733055, + 0.011961561627686024, + -0.026907365769147873, + 0.09483985602855682, + -0.01869250275194645, + -0.027169715613126755, + -0.028842203319072723, + -0.025562817230820656, + -0.04377980902791023, + 0.0037487484514713287, + 0.014617864973843098, + 0.01898764632642269, + -0.04679684340953827, + -0.002229982754215598, + -0.019791096448898315, + 0.017823465168476105, + -0.014544078148901463, + 0.03141652047634125, + -0.025021718814969063, + 0.008100084029138088, + 0.030744247138500214, + 0.032613497227430344, + 0.02229982800781727, + 0.06470229476690292, + -0.0024103489704430103, + 0.014453895390033722, + 0.03407282382249832, + 0.007755748927593231, + -0.0373850055038929, + -0.032875847071409225, + 0.00018856472161132842, + 0.017364351078867912, + -0.008169771172106266, + 0.019873080775141716, + 0.014306322671473026, + 0.005271613597869873, + 0.017725083976984024, + 0.02626788429915905, + -0.012748614884912968, + 0.016495313495397568, + 0.08368994295597076, + -0.023103276267647743, + -0.057159703224897385, + -0.03620442375540733, + -0.07536029815673828, + -0.042140115052461624, + -0.018233388662338257, + 0.009108495898544788, + -0.027514051645994186, + -0.025103703141212463, + -0.01400297973304987, + -0.013707835227251053, + -0.018216991797089577, + 0.04309113696217537, + -0.02434944361448288, + 0.0314985066652298, + -0.03928704932332039, + -0.04686243087053299, + 0.1089412122964859, + 0.0191024262458086, + -0.045616265386343, + 0.04466524347662926, + 0.055388834327459335, + 0.08093525469303131, + 0.009338052943348885, + 0.05424105003476143, + -0.011469653807580471, + 0.059422481805086136, + -0.00211930344812572, + -0.0025374251417815685, + 0.020069845020771027, + 0.037057064473629, + 0.0036134738475084305, + 0.009174083359539509, + 0.000812160549685359, + -0.0380408801138401, + 0.02610391564667225, + 0.01141226477921009, + 0.019446760416030884, + -0.04273040592670441, + 0.04538670554757118, + -0.03905749320983887, + -0.007977107539772987, + 0.03745059296488762, + 0.0412546806037426, + 0.0184465479105711, + 0.019479554146528244, + -0.03708985820412636, + 0.0191024262458086, + 0.011633623391389847, + 0.013174934312701225, + 0.004009049851447344, + 0.031104980036616325, + -0.05069931223988533, + -0.003211749019101262, + 0.02259497158229351, + -0.012010752223432064, + -0.027612432837486267, + 0.02056175284087658, + -0.005919292569160461, + 0.03715544566512108, + 0.023955916985869408, + -0.013494675047695637, + 0.047879040241241455, + 0.014125957153737545, + -0.025415243580937386, + -0.0070629785768687725, + 0.020086241886019707, + 0.05099445953965187, + 0.010133303701877594, + 0.025612007826566696, + 0.002242280403152108, + -0.07621294260025024, + 0.021725933998823166, + -0.03879513964056969, + 0.02082410268485546, + 0.0063620093278586864, + -0.0023734557908028364, + -0.013166735880076885, + -0.023709964007139206, + -0.04735434055328369, + 0.023054085671901703, + 0.03522060811519623, + 0.0170856025069952, + -0.011797592043876648, + -0.03230195492506027, + -0.01713479310274124, + -0.04187776520848274, + -0.003252741415053606, + -0.010985944420099258, + 0.009157686494290829, + -0.011330279521644115, + 0.0415826179087162, + 0.013027362525463104, + 0.0016601893585175276, + -0.008665778674185276, + 0.01021528895944357, + -0.024037901312112808, + 0.001562832505442202, + 0.03176085650920868, + -0.018036624416708946, + 0.01854492910206318, + -0.02033219486474991, + -0.05584795027971268, + 0.003154359757900238, + -0.021496377885341644, + 0.04673125594854355, + -0.015544291585683823, + 0.001519790617749095, + -0.0038245844189077616, + 0.020135432481765747, + 0.00786642823368311, + -0.017397144809365273, + -0.0035950273741036654, + -0.012822400778532028, + -0.029547270387411118, + -0.033072613179683685, + 0.028547057881951332, + -0.022070270031690598, + -0.01698722131550312, + 0.0058373077772557735, + 0.04128747433423996, + -0.04696081206202507, + -0.030875422060489655, + 0.05778278782963753, + -0.0038040881045162678, + 0.03558134287595749, + 0.015987008810043335, + -0.04459965601563454, + -0.023103276267647743, + 0.00663665821775794, + 0.0064644902013242245, + -0.038368821144104004, + 0.0017339754849672318, + -0.057454850524663925, + -0.03407282382249832, + 0.009354449808597565, + 0.07581941038370132, + 0.002084459876641631, + -0.007735252380371094, + -0.026972953230142593, + 0.019577937200665474, + -0.04518994316458702, + 0.003172806231305003, + -0.025989137589931488, + 0.03627001494169235, + 0.002125452272593975, + -0.03303981572389603, + 0.01110072247684002, + 0.04541949927806854, + -0.019709112122654915, + 0.0368930958211422, + -0.0095512131229043, + 0.016364138573408127, + -0.011248295195400715, + 0.016085390001535416, + 0.03505663946270943, + 0.025120100006461143, + -0.0010401803301647305, + 0.0013804166810587049, + -0.028760218992829323, + -0.007747550494968891, + -8.429047738900408e-05, + -0.004845293238759041, + -0.012592843733727932, + 0.010051319375634193, + -0.014863818883895874, + 0.032875847071409225, + -0.022988498210906982, + 0.007300734054297209, + -0.07004769146442413, + 0.027645226567983627, + -0.0323183536529541, + -0.00604636874049902, + -0.002723940182477236, + -0.008600190281867981, + -0.06404641270637512, + -0.03902469947934151, + -0.010994142852723598, + -0.03817205876111984, + -0.027005746960639954, + -0.006275925785303116, + 0.00476740812882781, + 0.05060093104839325, + 0.011043333448469639, + -0.020217416808009148, + -0.04840374365448952, + -0.02810434065759182, + 0.05096166580915451, + -0.029580064117908478, + 0.012887988239526749, + 0.008837946690618992, + -0.058963365852832794, + 0.061258938163518906, + -0.021070057526230812, + 0.029284920543432236, + -0.0005218836013227701, + -0.012018950656056404, + -0.011772996746003628, + 0.034794289618730545, + 0.02989160642027855, + 0.005476575344800949, + 0.06794888526201248, + 0.0208732932806015, + -0.015552490018308163, + 0.01037105917930603, + 0.01713479310274124, + -0.027317289263010025, + -0.014855620451271534, + -0.016421526670455933, + -0.024759367108345032, + 0.006677650380879641, + 0.013076553121209145, + 0.004177118185907602, + -0.016372336074709892, + 0.0003599638876039535, + 0.03561413660645485, + 0.023332834243774414, + -0.05630706250667572, + -0.014962200075387955, + 0.011715607717633247, + -0.04299275577068329, + -0.014716246165335178, + -0.04279599338769913, + -0.0452883243560791, + -0.0009136165608651936, + -0.0021992383990436792, + 0.02239820919930935, + 0.013650445267558098, + -0.023857535794377327, + -0.03205600008368492, + 0.042140115052461624, + 0.02610391564667225, + 0.01513436809182167, + -0.057389263063669205, + 0.042697612196207047, + -0.04256643354892731, + 0.013724232092499733, + 0.008259953930974007, + 0.000707630068063736, + 0.032908640801906586, + 0.03254790976643562, + 0.029071759432554245, + 0.02843227982521057, + -0.07162179797887802, + -0.034892670810222626, + -0.04489479959011078, + -0.025677595287561417, + -0.03522060811519623, + 0.014183346182107925, + -0.032925039529800415, + 0.017183983698487282, + 0.009600403718650341, + 0.05768440663814545, + 0.0017657446442171931, + -0.007374519947916269, + -0.014839223586022854, + 0.04538670554757118, + 0.02067653089761734, + 0.04351745545864105, + -0.05020740628242493, + -0.021988285705447197, + -0.05476575344800949, + 0.0036298707127571106, + 0.008665778674185276, + 0.0026808984111994505, + -0.02443142794072628, + -0.03225276619195938, + -0.04741992801427841, + 0.0017411492299288511, + 0.015199955552816391, + 0.0377129428088665, + 0.025530023500323296, + -0.021512774750590324, + -0.017364351078867912, + 0.015495100989937782, + 0.08539522439241409, + 0.026825379580259323, + -0.03349893167614937, + -0.04007410258054733, + -0.10139862447977066, + 0.03627001494169235, + 0.0013988632708787918, + 0.015790244564414024, + -0.00608736090362072, + 0.02051256224513054, + -0.009600403718650341, + -0.051978275179862976, + -0.004064389504492283, + 0.0007060928619466722, + -0.03218717873096466, + -0.04574744030833244, + 0.00665305508300662, + 0.004074637778103352, + 0.03994292765855789 + ], + "result": "--- 结果 1 (相似度: 1.000) ---\n文件路径: C:\\Steam\\steamapps\\common\\RimWorld\\Data\\dll1.6\\RimWorld\\MapPortal.txt\n\npublic class MapPortal : Building, IThingHolder\n{\n\tprivate static readonly Texture2D ViewPocketMapTex = ContentFinder.Get(\"UI/Commands/ViewCave\");\n\n\tprivate static readonly Texture2D CancelEnterTex = ContentFinder.Get(\"UI/Designators/Cancel\");\n\n\tprivate static readonly Texture2D DefaultEnterTex = ContentFinder.Get(\"UI/Commands/EnterCave\");\n\n\tprotected Map pocketMap;\n\n\tpublic PocketMapExit exit;\n\n\tprotected bool beenEntered;\n\n\tpublic List leftToLoad;\n\n\tpublic PortalContainerProxy containerProxy;\n\n\tpublic bool notifiedCantLoadMore;\n\n\tpublic Map PocketMap\n\t{\n\t\tget\n\t\t{\n\t\t\tMap map = pocketMap;\n\t\t\tif (map != null && map.Parent?.HasMap == false)\n\t\t\t{\n\t\t\t\tpocketMap = null;\n\t\t\t}\n\t\t\treturn pocketMap;\n\t\t}\n\t}\n\n\tpublic bool PocketMapExists => PocketMap != null;\n\n\tpublic virtual bool AutoDraftOnEnter => false;\n\n\tprotected virtual Texture2D EnterTex => DefaultEnterTex;\n\n\tpublic virtual string EnterString => \"EnterPortal\".Translate(Label);\n\n\tpublic virtual string CancelEnterString => \"CommandCancelEnterPortal\".Translate();\n\n\tpublic virtual string EnteringString => \"EnteringPortal\".Translate(Label);\n\n\tpublic bool LoadInProgress\n\t{\n\t\tget\n\t\t{\n\t\t\tif (leftToLoad != null)\n\t\t\t{\n\t\t\t\treturn leftToLoad.Any();\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic bool AnyPawnCanLoadAnythingNow\n\t{\n\t\tget\n\t\t{\n\t\t\tif (!LoadInProgress)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!base.Spawned)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tIReadOnlyList allPawnsSpawned = base.Map.mapPawns.AllPawnsSpawned;\n\t\t\tfor (int i = 0; i < allPawnsSpawned.Count; i++)\n\t\t\t{\n\t\t\t\tif (allPawnsSpawned[i].CurJobDef == JobDefOf.HaulToPortal && ((JobDriver_HaulToPortal)allPawnsSpawned[i].jobs.curDriver).MapPortal == this)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (allPawnsSpawned[i].CurJobDef == JobDefOf.EnterPortal && ((JobDriver_EnterPortal)allPawnsSpawned[i].jobs.curDriver).MapPortal == this)\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int j = 0; j < allPawnsSpawned.Count; j++)\n\t\t\t{\n\t\t\t\tThing thing = allPawnsSpawned[j].mindState?.duty?.focus.Thing;\n\t\t\t\tif (thing != null && thing == this && allPawnsSpawned[j].CanReach(thing, PathEndMode.Touch, Danger.Deadly))\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int k = 0; k < allPawnsSpawned.Count; k++)\n\t\t\t{\n\t\t\t\tif (allPawnsSpawned[k].IsColonist && EnterPortalUtility.HasJobOnPortal(allPawnsSpawned[k], this))\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic override void ExposeData()\n\t{\n\t\tbase.ExposeData();\n\t\tMap map = pocketMap;\n\t\tif (map != null && map.Parent?.HasMap == false)\n\t\t{\n\t\t\tpocketMap = null;\n\t\t}\n\t\tScribe_References.Look(ref pocketMap, \"pocketMap\");\n\t\tScribe_References.Look(ref exit, \"exit\");\n\t\tScribe_Values.Look(ref beenEntered, \"beenEntered\", defaultValue: false);\n\t\tScribe_Collections.Look(ref leftToLoad, \"leftToLoad\", LookMode.Deep);\n\t\tif (Scribe.mode == LoadSaveMode.PostLoadInit)\n\t\t{\n\t\t\tleftToLoad?.RemoveAll((TransferableOneWay x) => x.AnyThing == null);\n\t\t}\n\t}\n\n\tpublic override void SpawnSetup(Map map, bool respawningAfterLoad)\n\t{\n\t\tbase.SpawnSetup(map, respawningAfterLoad);\n\t\tcontainerProxy = new PortalContainerProxy\n\t\t{\n\t\t\tportal = this\n\t\t};\n\t}\n\n\tprotected override void Tick()\n\t{\n\t\tbase.Tick();\n\t\tif (this.IsHashIntervalTick(60) && base.Spawned && LoadInProgress && !notifiedCantLoadMore && !AnyPawnCanLoadAnythingNow && leftToLoad[0]?.AnyThing != null)\n\t\t{\n\t\t\tnotifiedCantLoadMore = true;\n\t\t\tMessages.Message(\"MessageCantLoadMoreIntoPortal\".Translate(Label, Faction.OfPlayer.def.pawnsPlural, leftToLoad[0].AnyThing), this, MessageTypeDefOf.CautionInput);\n\t\t}\n\t}\n\n\tpublic void GetChildHolders(List outChildren)\n\t{\n\t}\n\n\tpublic ThingOwner GetDirectlyHeldThings()\n\t{\n\t\treturn containerProxy;\n\t}\n\n\tpublic void Notify_ThingAdded(Thing t)\n\t{\n\t\tSubtractFromToLoadList(t, t.stackCount);\n\t}\n\n\tpublic void AddToTheToLoadList(TransferableOneWay t, int count)\n\t{\n\t\tif (!t.HasAnyThing || count <= 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (leftToLoad == null)\n\t\t{\n\t\t\tleftToLoad = new List();\n\t\t}\n\t\tTransferableOneWay transferableOneWay = TransferableUtility.TransferableMatching(t.AnyThing, leftToLoad, TransferAsOneMode.PodsOrCaravanPacking);\n\t\tif (transferableOneWay != null)\n\t\t{\n\t\t\tfor (int i = 0; i < t.things.Count; i++)\n\t\t\t{\n\t\t\t\tif (!transferableOneWay.things.Contains(t.things[i]))\n\t\t\t\t{\n\t\t\t\t\ttransferableOneWay.things.Add(t.things[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (transferableOneWay.CanAdjustBy(count).Accepted)\n\t\t\t{\n\t\t\t\ttransferableOneWay.AdjustBy(count);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTransferableOneWay transferableOneWay2 = new TransferableOneWay();\n\t\t\tleftToLoad.Add(transferableOneWay2);\n\t\t\ttransferableOneWay2.things.AddRange(t.things);\n\t\t\ttransferableOneWay2.AdjustTo(count);\n\t\t}\n\t}\n\n\tpublic int SubtractFromToLoadList(Thing t, int count)\n\t{\n\t\tif (leftToLoad == null)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tTransferableOneWay transferableOneWay = TransferableUtility.TransferableMatchingDesperate(t, leftToLoad, TransferAsOneMode.PodsOrCaravanPacking);\n\t\tif (transferableOneWay == null)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tif (transferableOneWay.CountToTransfer <= 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\tint num = Mathf.Min(count, transferableOneWay.CountToTransfer);\n\t\ttransferableOneWay.AdjustBy(-num);\n\t\ttransferableOneWay.things.Remove(t);\n\t\tif (transferableOneWay.CountToTransfer <= 0)\n\t\t{\n\t\t\tleftToLoad.Remove(transferableOneWay);\n\t\t}\n\t\treturn num;\n\t}\n\n\tpublic void CancelLoad()\n\t{\n\t\tLord lord = base.Map.lordManager.lords.FirstOrDefault((Lord l) => l.LordJob is LordJob_LoadAndEnterPortal lordJob_LoadAndEnterPortal && lordJob_LoadAndEnterPortal.portal == this);\n\t\tif (lord != null)\n\t\t{\n\t\t\tbase.Map.lordManager.RemoveLord(lord);\n\t\t}\n\t\tleftToLoad.Clear();\n\t}\n\n\tpublic virtual bool IsEnterable(out string reason)\n\t{\n\t\treason = \"\";\n\t\treturn true;\n\t}\n\n\tpublic virtual Map GetOtherMap()\n\t{\n\t\tif (PocketMap == null)\n\t\t{\n\t\t\tGeneratePocketMap();\n\t\t}\n\t\treturn PocketMap;\n\t}\n\n\tpublic virtual IntVec3 GetDestinationLocation()\n\t{\n\t\treturn exit?.Position ?? IntVec3.Invalid;\n\t}\n\n\tpublic virtual void OnEntered(Pawn pawn)\n\t{\n\t\tNotify_ThingAdded(pawn);\n\t\tif (!beenEntered)\n\t\t{\n\t\t\tbeenEntered = true;\n\t\t\tif (!def.portal.enteredLetterLabel.NullOrEmpty())\n\t\t\t{\n\t\t\t\tFind.LetterStack.ReceiveLetter(def.portal.enteredLetterLabel, def.portal.enteredLetterText.Formatted(pawn.Named(\"PAWN\")), def.portal.enteredLetterDef, exit);\n\t\t\t}\n\t\t}\n\t\tif (Find.CurrentMap == base.Map)\n\t\t{\n\t\t\tdef.portal.traverseSound?.PlayOneShot(this);\n\t\t}\n\t\telse if (Find.CurrentMap == exit.Map)\n\t\t{\n\t\t\tdef.portal.traverseSound?.PlayOneShot(exit);\n\t\t}\n\t}\n\n\tpublic override IEnumerable GetGizmos()\n\t{\n\t\tforeach (Gizmo gizmo in base.GetGizmos())\n\t\t{\n\t\t\tyield return gizmo;\n\t\t}\n\t\tCommand_Action command_Action = new Command_Action();\n\t\tcommand_Action.action = delegate\n\t\t{\n\t\t\tDialog_EnterPortal window = new Dialog_EnterPortal(this);\n\t\t\tFind.WindowStack.Add(window);\n\t\t};\n\t\tcommand_Action.icon = EnterTex;\n\t\tcommand_Action.defaultLabel = EnterString + \"...\";\n\t\tcommand_Action.defaultDesc = \"CommandEnterPortalDesc\".Translate(Label);\n\t\tcommand_Action.Disabled = !IsEnterable(out var reason);\n\t\tcommand_Action.disabledReason = reason;\n\t\tyield return command_Action;\n\t\tif (LoadInProgress)\n\t\t{\n\t\t\tCommand_Action command_Action2 = new Command_Action();\n\t\t\tcommand_Action2.action = CancelLoad;\n\t\t\tcommand_Action2.icon = CancelEnterTex;\n\t\t\tcommand_Action2.defaultLabel = CancelEnterString;\n\t\t\tcommand_Action2.defaultDesc = \"CommandCancelEnterPortalDesc\".Translate();\n\t\t\tyield return command_Action2;\n\t\t}\n\t\tif (pocketMap != null)\n\t\t{\n\t\t\tyield return new Command_Action\n\t\t\t{\n\t\t\t\tdefaultLabel = \"CommandViewPocketMapLabel\".Translate(def.portal.pocketMapGenerator.label),\n\t\t\t\tdefaultDesc = \"CommandViewPocketMapDesc\".Translate(def.portal.pocketMapGenerator.label),\n\t\t\t\ticon = ViewPocketMapTex,\n\t\t\t\taction = delegate\n\t\t\t\t{\n\t\t\t\t\tCameraJumper.TryJumpAndSelect(exit);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate void GeneratePocketMap()\n\t{\n\t\tPocketMapUtility.currentlyGeneratingPortal = this;\n\t\tpocketMap = GeneratePocketMapInt();\n\t\tPocketMapUtility.currentlyGeneratingPortal = null;\n\t}\n\n\tprotected virtual Map GeneratePocketMapInt()\n\t{\n\t\treturn PocketMapUtility.GeneratePocketMap(new IntVec3(def.portal.pocketMapSize, 1, def.portal.pocketMapSize), def.portal.pocketMapGenerator, GetExtraGenSteps(), base.Map);\n\t}\n\n\tprotected virtual IEnumerable GetExtraGenSteps()\n\t{\n\t\treturn Enumerable.Empty();\n\t}\n}\n\n", + "timestamp": "2025-08-25 14:32:36,132" } } \ No newline at end of file diff --git a/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs b/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs deleted file mode 100644 index a79384b8..00000000 --- a/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs +++ /dev/null @@ -1,94 +0,0 @@ -using HarmonyLib; -using RimWorld; -using Verse; -using System.Reflection; -using System.Collections.Generic; -using System.Reflection.Emit; - -namespace WulaFallenEmpire -{ - [HarmonyPatch(typeof(Dialog_EnterPortal), "CalculateAndRecacheTransferables")] - public static class DialogEnterPortal_CalculateAndRecacheTransferables_Patch - { - // Transpiler 负责修改方法的 IL 代码 - public static IEnumerable Transpiler(IEnumerable instructions) - { - var codes = new List(instructions); - // 找到 Thing.Map 属性的 getter 方法 (MapPortal 继承自 Thing) - var mapPropertyGetter = AccessTools.PropertyGetter(typeof(Verse.Thing), "Map"); - // 找到我们自定义的静态方法,它将返回正确的 Map - var getShuttleMapMethod = AccessTools.Method(typeof(DialogEnterPortal_CalculateAndRecacheTransferables_Patch), nameof(GetShuttleMap)); - - Log.Message("[WULA-DEBUG] Transpiler for CalculateAndRecacheTransferables started."); - - for (int i = 0; i < codes.Count; i++) - { - // 查找对 Thing.Map 的 get 访问 - if (codes[i].opcode == OpCodes.Call && codes[i].operand is MethodInfo method && method == mapPropertyGetter) - { - Log.Message($"[WULA-DEBUG] Transpiler found Thing.Map getter at index {i}."); - // 替换为调用我们的静态方法 - yield return new CodeInstruction(OpCodes.Call, getShuttleMapMethod); - } - else - { - yield return codes[i]; - } - } - Log.Message("[WULA-DEBUG] Transpiler for CalculateAndRecacheTransferables finished."); - } - - // 这个静态方法将由 Transpiler 注入,用于返回正确的 Map - // 参数 portalInstance 是原始方法中对 MapPortal 实例的引用 - public static Map GetShuttleMap(MapPortal portalInstance) - { - if (portalInstance is ShuttlePortalAdapter adapter) - { - Log.Message($"[WULA-DEBUG] portalInstance is ShuttlePortalAdapter. adapter.shuttle: {adapter.shuttle?.def.defName ?? "null"}"); - if (adapter.shuttle != null) - { - // 确保 adapter.shuttle.Map 不为 null - if (adapter.shuttle.Map != null) - { - return adapter.shuttle.Map; - } - else - { - Log.Error($"[WULA] Shuttle {adapter.shuttle.def.defName} is not spawned on any map when trying to get its map."); - return null; // 返回 null,让后续代码处理 - } - } - } - - // 如果不是我们的适配器,或者适配器中的 shuttle 为空, - // 则尝试获取原始 MapPortal 的 Map。 - // 这里需要非常小心,因为 portalInstance 本身也可能是 null, - // 或者它继承自 Thing 的 Map 属性是 null。 - if (portalInstance == null) - { - Log.Error("[WULA] GetShuttleMap received a null portalInstance."); - return null; - } - - var originalMapGetter = AccessTools.PropertyGetter(typeof(Thing), "Map"); - if (originalMapGetter == null) - { - Log.Error("[WULA] Could not get Thing.Map getter via AccessTools."); - return null; - } - - Map result = null; - try - { - result = (Map)originalMapGetter.Invoke(portalInstance, null); - } - catch (System.Exception ex) - { - Log.Error($"[WULA] Error invoking original Thing.Map getter: {ex.Message}"); - } - - Log.Message($"[WULA-DEBUG] GetShuttleMap returning original Map. Result: {result?.ToString() ?? "null"}"); - return result; - } - } -} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs b/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs index e270a996..b806cba6 100644 --- a/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs +++ b/Source/WulaFallenEmpire/WULA_Shuttle/Building_ArmedShuttleWithPocket.cs @@ -7,6 +7,7 @@ using RimWorld.Planet; using UnityEngine; using Verse; using Verse.AI; +using Verse.AI.Group; using Verse.Sound; namespace WulaFallenEmpire @@ -16,91 +17,94 @@ namespace WulaFallenEmpire /// 结合了武装防御能力和口袋空间技术的复合型载具 /// [StaticConstructorOnStartup] - public class Building_ArmedShuttleWithPocket : Building_ArmedShuttle + public class Building_ArmedShuttleWithPocket : Building_ArmedShuttle, IThingHolder { #region 静态图标定义(使用原版MapPortal的图标) - + /// 取消进入图标 private static readonly Texture2D CancelEnterTex = ContentFinder.Get("UI/Designators/Cancel"); - + /// 默认进入图标 private static readonly Texture2D DefaultEnterTex = ContentFinder.Get("UI/Commands/LoadTransporter"); - + #endregion #region 口袋空间字段 - + /// 内部口袋地图实例 private Map pocketMap; - + /// 口袋地图是否已生成 private bool pocketMapGenerated; - + /// 内部空间大小 private IntVec2 pocketMapSize = new IntVec2(80, 80); - + /// 地图生成器定义 private MapGeneratorDef mapGenerator; - + /// 退出点定义 private ThingDef exitDef; - + /// 允许直接访问(无需骇入) private bool allowDirectAccess = true; - + /// 传送功能是否暂停(飞行时为 true) private bool transportDisabled = false; - + // 注意:我们不再使用自定义的innerContainer, // 所有物品都存储在CompTransporter.innerContainer中,保持简单和一致 - + + /// 新的口袋空间物品容器 + private PocketSpaceThingHolder pocketSpaceContainer; + /// 口袋地图退出点(模仿原版 MapPortal.exit) public Building_PocketMapExit exit; - + /// 是否已经进入过(模仿原版 MapPortal.beenEntered) protected bool beenEntered; - + /// 待加载物品列表(模仿原版 MapPortal.leftToLoad) public List leftToLoad; - + /// 是否已通知无法加载更多(模仿原版 MapPortal.notifiedCantLoadMore) public bool notifiedCantLoadMore; - + #endregion #region 属性 /// 获取内部口袋地图 public Map PocketMap => pocketMap; - + /// 口袋地图是否已生成 public bool PocketMapGenerated => pocketMapGenerated; - + /// 是否允许直接访问口袋空间 public bool AllowDirectAccess => allowDirectAccess; - + // 注意:我们不再提供InnerContainer属性,因为所有物品都在CompTransporter.innerContainer中 - + /// /// 获取进入按钮的图标 /// protected virtual Texture2D EnterTex => DefaultEnterTex; - + /// /// 获取进入按钮的文本 /// public virtual string EnterString => "WULA.PocketSpace.Enter".Translate(); - + /// /// 获取取消进入按钮的文本 /// public virtual string CancelEnterString => "WULA.PocketSpace.CancelEnter".Translate(); - + /// /// 获取进入中的文本 /// public virtual string EnteringString => "WULA.PocketSpace.Entering".Translate(); - + /// 加载是否正在进行(模仿原版 MapPortal.LoadInProgress) public bool LoadInProgress { @@ -113,7 +117,7 @@ namespace WulaFallenEmpire return false; } } - + /// 是否有Pawn可以加载任何东西(模仿原版 MapPortal.AnyPawnCanLoadAnythingNow) public bool AnyPawnCanLoadAnythingNow { @@ -134,12 +138,38 @@ namespace WulaFallenEmpire #endregion + #region IThingHolder 实现 (模仿 MapPortal) + + /// + /// 获取直接持有的物品(模仿 MapPortal.GetDirectlyHeldThings) + /// + public ThingOwner GetDirectlyHeldThings() + { + return pocketSpaceContainer.innerContainer; + } + + /// + /// 获取子持有者(模仿 MapPortal.GetChildHolders) + /// + public void GetChildHolders(List outChildren) + { + // 目前没有子持有者,留空 + } + + + /// + /// 实现IThingHolder.ParentHolder属性 + /// + public new IThingHolder ParentHolder => this; + + #endregion + #region 构造函数 public Building_ArmedShuttleWithPocket() { Log.Message("[WULA-DEBUG] Building_ArmedShuttleWithPocket constructor called"); - // 不再初始化innerContainer,只使用CompTransporter的容器 + pocketSpaceContainer = new PocketSpaceThingHolder(this); } #endregion @@ -158,7 +188,7 @@ namespace WulaFallenEmpire public override void ExposeData() { Log.Message($"[WULA-DEBUG] ExposeData called, mode: {Scribe.mode}"); - + base.ExposeData(); Scribe_Deep.Look(ref pocketMap, "pocketMap"); Scribe_Values.Look(ref pocketMapGenerated, "pocketMapGenerated", false); @@ -167,13 +197,12 @@ namespace WulaFallenEmpire Scribe_Defs.Look(ref exitDef, "exitDef"); Scribe_Values.Look(ref allowDirectAccess, "allowDirectAccess", true); Scribe_Values.Look(ref transportDisabled, "transportDisabled", false); - - // 不再序列化innerContainer,只使用CompTransporter的容器 - + Scribe_Deep.Look(ref pocketSpaceContainer, "pocketSpaceContainer", this); + if (Scribe.mode == LoadSaveMode.PostLoadInit) { Log.Message("[WULA-DEBUG] PostLoadInit: Validating components after load"); - + // 验证CompTransporter组件是否正常 CompTransporter transporter = this.GetComp(); if (transporter == null) @@ -190,7 +219,7 @@ namespace WulaFallenEmpire public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish) { Log.Message($"[WULA-DEBUG] DeSpawn called with mode: {mode}"); - + // 只在真正销毁时清理口袋地图,发射时保留 if (ShouldDestroyPocketMapOnDeSpawn(mode)) { @@ -199,10 +228,10 @@ namespace WulaFallenEmpire try { Log.Message("[WULA-DEBUG] Destroying pocket map due to shuttle destruction"); - + // 将口袋空间中的物品和人员转移到主地图 TransferAllFromPocketToMainMap(); - + // 销毁口袋地图 PocketMapUtility.DestroyPocketMap(pocketMap); pocketMap = null; @@ -217,37 +246,34 @@ namespace WulaFallenEmpire else { Log.Message("[WULA-DEBUG] Preserving pocket map during shuttle launch/transport"); - // 发射时暂停传送功能,但保留口袋空间 transportDisabled = true; if (pocketMap != null && exit != null) { - // 标记传送功能暂停 Log.Message("[WULA-DEBUG] Transport functionality disabled during flight"); } } - + base.DeSpawn(mode); } - + /// /// 判断是否应该在DeSpawn时销毁口袋地图 /// private bool ShouldDestroyPocketMapOnDeSpawn(DestroyMode mode) { - // 只在真正销毁时删除口袋空间 switch (mode) { - case DestroyMode.Vanish: // 发射时使用,保留口袋空间 + case DestroyMode.Vanish: return false; - case DestroyMode.Deconstruct: // 拆除,删除口袋空间 + case DestroyMode.Deconstruct: return true; - case DestroyMode.KillFinalize: // 被摧毁,删除口袋空间 + case DestroyMode.KillFinalize: return true; - case DestroyMode.Cancel: // 取消建造,删除口袋空间 + case DestroyMode.Cancel: return true; - case DestroyMode.Refund: // 退款,删除口袋空间 + case DestroyMode.Refund: return true; - case DestroyMode.FailConstruction: // 建造失败,删除口袋空间 + case DestroyMode.FailConstruction: return true; default: Log.Warning($"[WULA-WARNING] Unknown DestroyMode: {mode}, defaulting to preserve pocket map"); @@ -258,26 +284,24 @@ namespace WulaFallenEmpire public override string GetInspectString() { StringBuilder sb = new StringBuilder(base.GetInspectString()); - + if (pocketMapGenerated) { sb.AppendLine("WULA.PocketSpace.Status".Translate() + ": " + "WULA.PocketSpace.Ready".Translate()); - - // 显示主容器中的物品数量 + CompTransporter transporter = this.GetComp(); int mainContainerItems = transporter?.innerContainer?.Count ?? 0; - + if (mainContainerItems > 0) { sb.AppendLine($"容器物品: {mainContainerItems}"); } - - // 显示口袋空间中的物品和人员数量 + if (pocketMap != null) { int pocketItems = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable); int pawnCount = pocketMap.mapPawns.AllPawnsSpawned.Where(p => p.IsColonist).Count(); - + if (pocketItems > 0) { sb.AppendLine($"口袋空间物品: {pocketItems}"); @@ -287,8 +311,7 @@ namespace WulaFallenEmpire sb.AppendLine("WULA.PocketSpace.PawnCount".Translate(pawnCount)); } } - - // 在开发模式下显示详细调试信息 + if (Prefs.DevMode) { sb.AppendLine($"[Debug] {GetPocketSpaceDebugInfo()}"); @@ -298,7 +321,7 @@ namespace WulaFallenEmpire { sb.AppendLine("WULA.PocketSpace.Status".Translate() + ": " + "WULA.PocketSpace.NotGenerated".Translate()); } - + return sb.ToString().TrimEndNewlines(); } @@ -313,19 +336,19 @@ namespace WulaFallenEmpire { if (!allowDirectAccess) { - return false; // 需要特殊权限 + return false; } - + if (!Spawned) { return false; } - + if (transportDisabled) { - return false; // 飞行中禁用传送功能 + return false; } - + return true; } @@ -354,7 +377,7 @@ namespace WulaFallenEmpire // 传送玩家到口袋空间 List pawnsToTransfer = new List(); - + if (pawns != null) { pawnsToTransfer.AddRange(pawns.Where(p => p != null && p.Spawned && p.IsColonist)); @@ -375,16 +398,24 @@ namespace WulaFallenEmpire int transferredCount = 0; foreach (Pawn pawn in pawnsToTransfer) { - if (TransferPawnToPocketSpace(pawn)) + if (pawn.Spawned) + { + pawn.DeSpawn(); + } + if (pocketSpaceContainer.innerContainer.TryAdd(pawn)) { transferredCount++; } + else + { + Log.Warning($"[WULA-WARNING] Failed to add pawn {pawn.LabelShort} to pocketSpaceContainer."); + } } if (transferredCount > 0) { Messages.Message("WULA.PocketSpace.TransferSuccess".Translate(transferredCount), MessageTypeDefOf.PositiveEvent); - + // 切换到口袋地图 Current.Game.CurrentMap = pocketMap; Find.CameraDriver.JumpToCurrentMapLoc(pocketMap.Center); @@ -402,7 +433,7 @@ namespace WulaFallenEmpire { CreatePocketMap(); } - + if (pocketMap == null) { Messages.Message("WULA.PocketSpace.CreationFailed".Translate(), this, MessageTypeDefOf.RejectInput); @@ -425,14 +456,14 @@ namespace WulaFallenEmpire PocketMapUtility.currentlyGeneratingPortal = null; // 我们不是 MapPortal,但可以设为 null pocketMap = GeneratePocketMapInt(); PocketMapUtility.currentlyGeneratingPortal = null; - + if (pocketMap != null) { pocketMapGenerated = true; - + // 在口袋地图中心放置退出点 CreateExitPoint(); - + Log.Message($"[WULA] Successfully created pocket map of size {pocketMapSize} for armed shuttle"); } else @@ -445,7 +476,7 @@ namespace WulaFallenEmpire Log.Error($"[WULA] Exception creating pocket map: {ex}"); } } - + /// /// 生成口袋地图的内部实现(模仿 MapPortal.GeneratePocketMapInt) /// @@ -453,7 +484,7 @@ namespace WulaFallenEmpire { return PocketMapUtility.GeneratePocketMap(new IntVec3(pocketMapSize.x, 1, pocketMapSize.z), mapGenerator, GetExtraGenSteps(), this.Map); } - + /// /// 获取额外的生成步骤(模仿 MapPortal.GetExtraGenSteps) /// @@ -472,29 +503,13 @@ namespace WulaFallenEmpire try { // 在地图中心找一个合适的位置 - IntVec3 exitPos = pocketMap.Center; - - // 寻找可建造的位置 - if (!exitPos.Standable(pocketMap) || exitPos.GetThingList(pocketMap).Any(t => t.def.category == ThingCategory.Building)) - { - exitPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 5, - p => p.Standable(pocketMap) && !p.GetThingList(pocketMap).Any(t => t.def.category == ThingCategory.Building)); - } + IntVec3 exitPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 5, (IntVec3 c) => c.IsValid && c.Standable(pocketMap) && !c.Roofed(pocketMap)); if (exitPos.IsValid) { - // 创建退出点建筑 - Thing exitBuilding = ThingMaker.MakeThing(exitDef); - if (exitBuilding is Building_PocketMapExit exitPortal) - { - exitPortal.targetMap = this.Map; - exitPortal.targetPos = this.Position; - exitPortal.parentShuttle = this; - exit = exitPortal; // 设置 exit 引用,模仿原版 MapPortal - } - - GenPlace.TryPlaceThing(exitBuilding, exitPos, pocketMap, ThingPlaceMode.Direct); - Log.Message($"[WULA] Created exit point at {exitPos} in pocket map"); + exit = (Building_PocketMapExit)ThingMaker.MakeThing(exitDef); + GenPlace.TryPlaceThing(exit, exitPos, pocketMap, ThingPlaceMode.Direct); + Log.Message($"[WULA] Created exit point at {exitPos} in pocket map."); } else { @@ -517,7 +532,7 @@ namespace WulaFallenEmpire try { // 找一个安全的位置 - IntVec3 spawnPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 10, + IntVec3 spawnPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 10, p => p.Standable(pocketMap) && !p.GetThingList(pocketMap).Any(t => t is Pawn)); if (spawnPos.IsValid) @@ -531,7 +546,7 @@ namespace WulaFallenEmpire { Log.Error($"[WULA] Error transferring pawn {pawn?.LabelShort} to pocket space: {ex}"); } - + return false; } @@ -541,13 +556,13 @@ namespace WulaFallenEmpire private void TransferAllFromPocketToMainMap() { Log.Message("[WULA-DEBUG] TransferAllFromPocketToMainMap started"); - + if (pocketMap == null) { Log.Warning("[WULA-DEBUG] TransferAllFromPocketToMainMap: pocketMap is null, nothing to transfer"); return; } - + if (!Spawned) { Log.Error("[WULA-ERROR] TransferAllFromPocketToMainMap: Shuttle not spawned, cannot transfer items"); @@ -556,93 +571,34 @@ namespace WulaFallenEmpire try { - // 获取穿梭机的 CompTransporter - CompTransporter transporter = this.GetComp(); - if (transporter == null) - { - Log.Error("[WULA-ERROR] CompTransporter not found on shuttle! Cannot transfer items."); - return; - } - - Log.Message($"[WULA-DEBUG] Found CompTransporter with {transporter.innerContainer.Count} existing items"); - - // 转移所有殖民者 - List pawnsToTransfer = pocketMap.mapPawns.AllPawnsSpawned - .Where(p => p.IsColonist).ToList(); - - Log.Message($"[WULA-DEBUG] Found {pawnsToTransfer.Count} colonists to transfer"); - + // 转移所有殖民者到 pocketSpaceContainer + List pawnsToTransfer = pocketMap.mapPawns.AllPawnsSpawned.ToList(); + Log.Message($"[WULA-DEBUG] Found {pawnsToTransfer.Count} pawns to transfer from pocket map."); foreach (Pawn pawn in pawnsToTransfer) { if (pawn.Spawned) { - Log.Message($"[WULA-DEBUG] Transferring pawn: {pawn.LabelShort}"); pawn.DeSpawn(); - - // 直接放入穿梭机的容器,如果失败就放到地面 - if (!transporter.innerContainer.TryAdd(pawn)) - { - Log.Warning($"[WULA-WARNING] Container full, placing pawn {pawn.LabelShort} near shuttle"); - // 如果容器满了,放到穿梭机附近 - IntVec3 spawnPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 5, - p => p.Standable(this.Map) && !p.GetThingList(this.Map).Any(t => t is Pawn)); - - if (spawnPos.IsValid) - { - GenPlace.TryPlaceThing(pawn, spawnPos, this.Map, ThingPlaceMode.Near); - Log.Message($"[WULA-DEBUG] Placed pawn {pawn.LabelShort} at {spawnPos}"); - } - else - { - Log.Error($"[WULA-ERROR] Could not find valid position for pawn {pawn.LabelShort}"); - } - } - else - { - Log.Message($"[WULA-DEBUG] Successfully added pawn {pawn.LabelShort} to container"); - } } + pocketSpaceContainer.innerContainer.TryAdd(pawn); } - // 转移所有物品到穿梭机的容器 - List itemsToTransfer = pocketMap.listerThings.AllThings - .Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable).ToList(); - - Log.Message($"[WULA-DEBUG] Found {itemsToTransfer.Count} items to transfer"); - + // 转移所有物品到 pocketSpaceContainer + List itemsToTransfer = pocketMap.listerThings.AllThings.Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable).ToList(); + Log.Message($"[WULA-DEBUG] Found {itemsToTransfer.Count} items to transfer from pocket map."); foreach (Thing item in itemsToTransfer) { if (item.Spawned) { - Log.Message($"[WULA-DEBUG] Transferring item: {item.LabelShort} (stack: {item.stackCount})"); item.DeSpawn(); - - // 直接使用穿梭机的主容器 - if (!transporter.innerContainer.TryAdd(item)) - { - Log.Warning($"[WULA-WARNING] Container full, dropping item {item.LabelShort} near shuttle"); - // 如果容器满了,丢到穿梭机附近(玩家可以手动重新装载) - IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 3); - if (dropPos.IsValid) - { - GenPlace.TryPlaceThing(item, dropPos, this.Map, ThingPlaceMode.Near); - Messages.Message($"容器已满:{item.LabelShort} 被放置在穿梭机附近", this, MessageTypeDefOf.CautionInput); - Log.Message($"[WULA-DEBUG] Dropped item {item.LabelShort} at {dropPos}"); - } - else - { - Log.Error($"[WULA-ERROR] Could not find valid drop position for item {item.LabelShort}"); - } - } - else - { - Log.Message($"[WULA-DEBUG] Successfully added item {item.LabelShort} to container"); - } } + pocketSpaceContainer.innerContainer.TryAdd(item); } - - Log.Message($"[WULA-DEBUG] Transfer complete. Container now has {transporter.innerContainer.Count} total items"); - Log.Message($"[WULA-SUCCESS] Transferred {pawnsToTransfer.Count} pawns and {itemsToTransfer.Count} items from pocket space"); + + Log.Message($"[WULA] Transferred all pawns and items from pocket map to pocketSpaceContainer."); + + // 调用新的同步方法,将 pocketSpaceContainer 中的所有物品和 Pawn 转移到主地图的 CompTransporter + TransferPocketContainerToMainTransporter(); } catch (Exception ex) { @@ -652,102 +608,40 @@ namespace WulaFallenEmpire } /// - /// 手动同步口袋空间中的所有物品到穿梭机主容器 - /// 用于解决物品消失问题 + /// 将pocketSpaceContainer中的所有物品和Pawn转移到主地图的CompTransporter /// - public void SyncPocketItemsToMainContainer() + public void TransferPocketContainerToMainTransporter() { - Log.Message("[WULA-DEBUG] SyncPocketItemsToMainContainer started"); - - if (pocketMap == null || !pocketMapGenerated) - { - Log.Warning("[WULA-DEBUG] SyncPocketItemsToMainContainer: No pocket map to sync"); - return; - } - + Log.Message("[WULA-DEBUG] TransferPocketContainerToMainTransporter started."); + CompTransporter transporter = this.GetComp(); if (transporter == null) { - Log.Error("[WULA-ERROR] No CompTransporter found on shuttle, cannot sync items"); + Log.Error("[WULA-ERROR] CompTransporter not found on shuttle! Cannot transfer items from pocketSpaceContainer."); return; } - - Log.Message($"[WULA-DEBUG] Starting sync. Current container has {transporter.innerContainer.Count} items"); - - try + + List thingsToTransfer = pocketSpaceContainer.innerContainer.ToList(); + int transferredCount = 0; + + foreach (Thing t in thingsToTransfer) { - List itemsInPocket = pocketMap.listerThings.AllThings - .Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Spawned).ToList(); - - Log.Message($"[WULA-DEBUG] Found {itemsInPocket.Count} items in pocket space to check"); - - int syncedCount = 0; - int droppedCount = 0; - int skippedCount = 0; - - foreach (Thing item in itemsInPocket) + if (pocketSpaceContainer.innerContainer.Remove(t)) { - // 检查物品是否已经在主容器中 - if (!transporter.innerContainer.Contains(item)) + if (transporter.innerContainer.TryAdd(t)) { - Log.Message($"[WULA-DEBUG] Syncing item: {item.LabelShort} (not in main container)"); - - // 从口袋地图中移除 - IntVec3 originalPos = item.Position; - item.DeSpawn(); - - // 尝试添加到主容器 - if (transporter.innerContainer.TryAdd(item)) - { - syncedCount++; - Log.Message($"[WULA-DEBUG] Successfully synced item: {item.LabelShort}"); - } - else - { - Log.Warning($"[WULA-WARNING] Container full, dropping item: {item.LabelShort}"); - // 如果主容器满了,放到穿梭机附近(玩家可以手动装载) - IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 3); - if (dropPos.IsValid) - { - GenPlace.TryPlaceThing(item, dropPos, this.Map, ThingPlaceMode.Near); - droppedCount++; - Log.Message($"[WULA-DEBUG] Dropped item {item.LabelShort} at {dropPos}"); - } - else - { - // 如果找不到合适位置,重新放回口袋空间 - GenPlace.TryPlaceThing(item, originalPos, pocketMap, ThingPlaceMode.Near); - Log.Warning($"[WULA-WARNING] Could not find drop position, returned item {item.LabelShort} to pocket"); - } - } + transferredCount++; } else { - skippedCount++; - Log.Message($"[WULA-DEBUG] Item {item.LabelShort} already in main container, skipping"); + Log.Warning($"[WULA-WARNING] Failed to add {t.LabelShort} to main transporter container. Dropping on ground."); + GenPlace.TryPlaceThing(t, this.Position, this.Map, ThingPlaceMode.Near); } } - - string message = $"[WULA-SUCCESS] 同步完成: {syncedCount} 个物品已同步"; - if (droppedCount > 0) - { - message += $", {droppedCount} 个物品因容器已满被放置在附近"; - } - if (skippedCount > 0) - { - message += $", {skippedCount} 个物品已在容器中"; - } - - Log.Message(message); - Log.Message($"[WULA-DEBUG] Final container state: {transporter.innerContainer.Count} items"); - } - catch (Exception ex) - { - Log.Error($"[WULA-ERROR] Error syncing pocket items to main container: {ex}"); - Log.Error($"[WULA-ERROR] Stack trace: {ex.StackTrace}"); } + Log.Message($"[WULA] Transferred {transferredCount} items/pawns from pocketSpaceContainer to main transporter."); } - + /// /// 获取口袋空间状态信息(用于调试) /// @@ -757,11 +651,11 @@ namespace WulaFallenEmpire { return "Pocket space not initialized"; } - + CompTransporter transporter = this.GetComp(); int pocketItems = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable); int mainContainerItems = transporter?.innerContainer?.Count ?? 0; - + return $"Pocket: {pocketItems}, Main: {mainContainerItems}"; } @@ -775,7 +669,7 @@ namespace WulaFallenEmpire { yield return gizmo; } - + if (allowDirectAccess) { // 进入口袋空间按钮(模仿原版MapPortal) @@ -788,13 +682,13 @@ namespace WulaFallenEmpire enterCommand.icon = EnterTex; enterCommand.defaultLabel = EnterString + "..."; enterCommand.defaultDesc = "WULA.PocketSpace.EnterDesc".Translate(); - + // 检查是否可以进入(模仿原版MapPortal.IsEnterable) string reason; enterCommand.Disabled = !IsEnterable(out reason); enterCommand.disabledReason = reason; yield return enterCommand; - + } } @@ -804,138 +698,104 @@ namespace WulaFallenEmpire #endregion #region MapPortal兼容接口(使Dialog_EnterPortal能正常工作) - + /// - /// 检查是否可以进入(模仿原版MapPortal.IsEnterable) + /// 判断是否可以进入(模仿原版MapPortal.IsEnterable) /// public virtual bool IsEnterable(out string reason) { - if (!allowDirectAccess) - { - reason = "WULA.PocketSpace.AccessDenied".Translate(); - return false; - } - + reason = ""; if (!Spawned) { reason = "WULA.PocketSpace.NotSpawned".Translate(); return false; } - if (transportDisabled) { reason = "WULA.PocketSpace.TransportDisabled".Translate(); return false; } - - reason = ""; + if (!this.CanEnterPocketSpace()) + { + reason = "WULA.PocketSpace.CannotEnterReason".Translate(); + return false; + } return true; } - + /// - /// 获取目标地图(模仿原版MapPortal.GetOtherMap) + /// 获取另一个地图(模仿原版MapPortal.GetOtherMap) /// public virtual Map GetOtherMap() { - if (pocketMap == null) + if (PocketMap == null) { CreatePocketMap(); } - return pocketMap; + return PocketMap; } - + /// /// 获取目标位置(模仿原版MapPortal.GetDestinationLocation) /// public virtual IntVec3 GetDestinationLocation() { - if (exit != null) - { - return exit.Position; - } - return pocketMap?.Center ?? IntVec3.Invalid; + return exit?.Position ?? IntVec3.Invalid; } - + /// - /// 处理进入事件(模仿原版MapPortal.OnEntered) + /// 进入时回调(模仿原版MapPortal.OnEntered) /// public virtual void OnEntered(Pawn pawn) { - // 通知物品被添加(用于统计和管理) - Notify_ThingAdded(pawn); - - // 播放传送音效(如果存在) - if (Find.CurrentMap == this.Map) + // 将Pawn添加到口袋空间容器 + if (pawn.Spawned) { - // 可以在这里添加音效播放 - // def.portal?.traverseSound?.PlayOneShot(this); + pawn.DeSpawn(); + } + pocketSpaceContainer.innerContainer.TryAdd(pawn); + + if (!beenEntered) + { + beenEntered = true; + // 这里可以添加一些首次进入的信件/事件 + } + if (Find.CurrentMap == base.Map) + { + // def.portal.traverseSound?.PlayOneShot(this); // 暂时移除,避免NRE + } + else if (Find.CurrentMap == exit.Map) + { + // def.portal.traverseSound?.PlayOneShot(exit); // 暂时移除,避免NRE } } - + /// - /// 打开殖民者选择对话框(模仿原版Dialog_EnterPortal的功能) + /// 打开殖民者选择对话框(模仿原版Dialog_EnterPortal) /// private void OpenPawnSelectionDialog() { - // 获取所有可用的殖民者 - List availablePawns = Map.mapPawns.AllPawnsSpawned - .Where(p => p.IsColonist && !p.Downed && p.CanReach(this, PathEndMode.Touch, Danger.Deadly)) - .ToList(); - - if (availablePawns.Count == 0) - { - Messages.Message("WULA.PocketSpace.NoPawnsAvailable".Translate(), this, MessageTypeDefOf.RejectInput); - return; - } - - // 创建选项列表 - List options = new List(); - - // 添加单个殖民者选项 - foreach (Pawn pawn in availablePawns) - { - FloatMenuOption option = new FloatMenuOption( - $"{pawn.LabelShort}", - delegate - { - EnterPocketSpace(new List { pawn }); - } - ); - options.Add(option); - } - - // 添加“全部殖民者”选项 - if (availablePawns.Count > 1) - { - FloatMenuOption allOption = new FloatMenuOption( - "WULA.PocketSpace.AllColonists".Translate(availablePawns.Count), - delegate - { - EnterPocketSpace(availablePawns); - } - ); - options.Add(allOption); - } - - // 显示浮动菜单 - FloatMenu floatMenu = new FloatMenu(options); - Find.WindowStack.Add(floatMenu); + List pawns = CaravanFormingUtility.AllSendablePawns(this.Map, true, true, true, true, true, 0).ToList(); + List items = CaravanFormingUtility.AllReachableColonyItems(this.Map, true, true).ToList(); + + // 创建并显示对话框 + Dialog_EnterPortal window = new Dialog_EnterPortal(new global::WulaFallenEmpire.MapPortalAdapter(this)); // 使用适配器 + Find.WindowStack.Add(window); } - - #endregion - - #region 原版MapPortal的物品传送方法 - + /// - /// 通知有物品被添加(模仿原版 MapPortal.Notify_ThingAdded) + /// 通知物品被添加到此持有者(从IThingHolder继承,但现在由PocketSpaceThingHolder处理) /// public void Notify_ThingAdded(Thing t) { - SubtractFromToLoadList(t, t.stackCount); + // 这个方法现在由 PocketSpaceThingHolder 内部处理,这里只是为了满足IThingHolder接口 + // 或者,如果Building_ArmedShuttleWithPocket仍然需要实现IThingHolder,则可以将其转发 + // Log.Message($"[WULA] Building_ArmedShuttleWithPocket.Notify_ThingAdded called for {t.LabelCap}"); + // pocketSpaceContainer.innerContainer.Notify_ThingAdded(t); // 转发给内部容器 } - + /// - /// 添加到加载列表(模仿原版 MapPortal.AddToTheToLoadList) + /// 添加到待加载列表(模仿原版MapPortal.AddToTheToLoadList) /// public void AddToTheToLoadList(TransferableOneWay t, int count) { @@ -970,9 +830,9 @@ namespace WulaFallenEmpire transferableOneWay2.AdjustTo(count); } } - + /// - /// 从加载列表中减去(模仿原版 MapPortal.SubtractFromToLoadList) + /// 从待加载列表移除(模仿原版MapPortal.SubtractFromToLoadList) /// public int SubtractFromToLoadList(Thing t, int count) { @@ -998,75 +858,63 @@ namespace WulaFallenEmpire } return num; } - + /// - /// 取消加载(模仿原版 MapPortal.CancelLoad) + /// 取消加载(模仿原版MapPortal.CancelLoad) /// public void CancelLoad() { - // 简化版本,只清理列表 - if (leftToLoad != null) + Lord lord = base.Map.lordManager.lords.FirstOrDefault((Lord l) => l.LordJob is LordJob_LoadAndEnterPortal lordJob_LoadAndEnterPortal && lordJob_LoadAndEnterPortal.portal is global::WulaFallenEmpire.MapPortalAdapter adapter && adapter.shuttle == this); + if (lord != null) { - leftToLoad.Clear(); + base.Map.lordManager.RemoveLord(lord); } + leftToLoad.Clear(); } #endregion - - #region 穿梭机状态变化处理 - + + #region 生命周期方法 + /// - /// 更新口袋空间中退出点的目标位置(处理穿梭机位置变化) + /// 更新退出点目标 /// public void UpdateExitPointTarget() { - if (pocketMap == null || exit == null) return; - + if (exit == null) return; + if (base.Map == null) + { + Log.Warning("[WULA] UpdateExitPointTarget: Shuttle map is null, cannot update exit point target."); + return; + } + try { - // 如果退出点是我们的Building_PocketMapExit类型,更新其目标位置 - if (exit is Building_PocketMapExit pocketExit) - { - // 更新目标地图和位置 - if (this.Spawned) - { - // 穿梭机在地图上,更新目标位置 - if (pocketExit.targetMap != this.Map || pocketExit.targetPos != this.Position) - { - pocketExit.targetMap = this.Map; - pocketExit.targetPos = this.Position; - pocketExit.parentShuttle = this; - Log.Message($"[WULA] Updated pocket map exit target to shuttle location: {this.Map?.uniqueID} at {this.Position}"); - } - } - else - { - // 穿梭机不在地图上(可能在飞行中),记录警告但保持原有目标 - Log.Warning($"[WULA] Shuttle not spawned, pocket map exit target may be outdated. Current target: {pocketExit.targetMap?.uniqueID} at {pocketExit.targetPos}"); - } - } + exit.targetMap = base.Map; + exit.targetPos = base.Position; + Log.Message($"[WULA] Updated exit point target to map {base.Map.uniqueID} at position {base.Position}"); } catch (Exception ex) { Log.Error($"[WULA] Error updating exit point target: {ex}"); } } - + /// /// 重写Tick方法,定期检查穿梭机状态变化和物品同步 /// protected override void Tick() { base.Tick(); - + // 每隔一段时间检查退出点目标是否需要更新(处理穿梭机移动的情况) if (this.IsHashIntervalTick(2500) && pocketMapGenerated && exit != null) { UpdateExitPointTarget(); } - + // 定期检查并同步口袋空间中的物品(每5分钟检查一次) - if (this.IsHashIntervalTick(18000) && pocketMapGenerated && pocketMap != null) // 18000 ticks = 5 minutes + if (this.IsHashIntervalTick(18000) && pocketMapGenerated && pocketMap != null) { // 自动同步口袋空间中的物品到主容器 try @@ -1074,7 +922,7 @@ namespace WulaFallenEmpire int itemsInPocket = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Spawned); if (itemsInPocket > 0) { - SyncPocketItemsToMainContainer(); + TransferPocketContainerToMainTransporter(); if (Prefs.DevMode) { Log.Message($"[WULA] Auto-synced pocket items. Current status: {GetPocketSpaceDebugInfo()}"); @@ -1087,20 +935,20 @@ namespace WulaFallenEmpire } } } - + /// /// 重写 SpawnSetup,确保位置变化时更新退出点 /// public override void SpawnSetup(Map map, bool respawningAfterLoad) { - Log.Message($"[WULA-DEBUG] SpawnSetup called: map={map?.uniqueID}, respawning={respawningAfterLoad}"); - + Log.Message($"[WULA-DEBUG] Building_ArmedShuttleWithPocket.SpawnSetup START. Instance ID: {this.ThingID}, Map param: {map?.GetUniqueLoadID() ?? "null"}, Respawning: {respawningAfterLoad}"); + // 保存旧位置信息 Map oldMap = this.Map; IntVec3 oldPos = this.Position; - + base.SpawnSetup(map, respawningAfterLoad); - + // 验证关键组件 CompTransporter transporter = this.GetComp(); if (transporter == null) @@ -1111,92 +959,158 @@ namespace WulaFallenEmpire { Log.Message($"[WULA-DEBUG] CompTransporter found with {transporter.innerContainer?.Count ?? 0} items"); } - + // 更新退出点目标(处理穿梭机重新部署的情况) UpdateExitPointTarget(); - + // 如果是从飞行状态恢复,重新启用传送功能 if (transportDisabled) { Log.Message("[WULA-DEBUG] Re-enabling transport functionality after landing"); transportDisabled = false; - + // 如果有口袋空间,确保退出点正确连接到新地图 if (pocketMapGenerated && pocketMap != null && exit != null) { - Log.Message($"[WULA-DEBUG] Reconnecting pocket space exit to new map: {map?.uniqueID} at {this.Position}"); - // 退出点会在 UpdateExitPointTarget 中自动更新 + Log.Message($"[WULA-DEBUG] Reconnecting pocket space exit to new map: {map?.GetUniqueLoadID() ?? "null"} at {this.Position}"); } } - + // 从 ThingDef 中读取 portal 配置 if (def.HasModExtension()) { - var portalProps = def.GetModExtension(); - Log.Message($"[WULA-DEBUG] Loading portal properties from ThingDef"); - - if (portalProps.pocketMapGenerator != null) + if (this.Map == null) { - mapGenerator = portalProps.pocketMapGenerator; - Log.Message($"[WULA-DEBUG] Set mapGenerator: {mapGenerator.defName}"); + Log.Error($"[WULA-ERROR] Building_ArmedShuttleWithPocket {this.ThingID} Map is NULL after SpawnSetup!"); } - if (portalProps.exitDef != null) - { - exitDef = portalProps.exitDef; - Log.Message($"[WULA-DEBUG] Set exitDef: {exitDef.defName}"); - } - if (portalProps.pocketMapSize != IntVec2.Zero) - { - pocketMapSize = portalProps.pocketMapSize; - Log.Message($"[WULA-DEBUG] Set pocketMapSize: {pocketMapSize}"); - } - allowDirectAccess = portalProps.allowDirectAccess; - Log.Message($"[WULA-DEBUG] Set allowDirectAccess: {allowDirectAccess}"); + PocketMapProperties props = def.GetModExtension(); + pocketMapSize = props.pocketMapSize; + mapGenerator = props.mapGenerator; + exitDef = props.exitDef; + allowDirectAccess = props.allowDirectAccess; } - - // 初始化地图生成器和退出点定义(如果 XML 中没有配置) - if (mapGenerator == null) - { - mapGenerator = DefDatabase.GetNamed("AncientStockpile", false) - ?? DefDatabase.GetNamed("Base_Player", false) - ?? MapGeneratorDefOf.Base_Player; - Log.Message($"[WULA-DEBUG] Using fallback mapGenerator: {mapGenerator.defName}"); - } - - if (exitDef == null) - { - exitDef = DefDatabase.GetNamed("WULA_PocketMapExit", false) - ?? ThingDefOf.Door; - Log.Message($"[WULA-DEBUG] Using fallback exitDef: {exitDef.defName}"); - } - - // 如果位置发生了变化,记录日志 - if (oldMap != null && (oldMap != map || oldPos != this.Position)) - { - Log.Message($"[WULA-DEBUG] Shuttle moved from {oldMap?.uniqueID}:{oldPos} to {map?.uniqueID}:{this.Position}, updating pocket map exit target"); - } - - Log.Message($"[WULA-DEBUG] SpawnSetup completed successfully"); } - - #endregion + } + + public class PocketMapProperties : DefModExtension + { + public IntVec2 pocketMapSize = new IntVec2(80, 80); + public MapGeneratorDef mapGenerator; + public ThingDef exitDef; + public bool allowDirectAccess = true; } /// - /// 口袋空间属性配置类 + /// 适配器类,使Building_ArmedShuttleWithPocket能够作为MapPortal被Dialog_EnterPortal使用 /// - public class PocketMapProperties : DefModExtension + public class MapPortalAdapter : MapPortal { - /// 口袋地图生成器 - public MapGeneratorDef pocketMapGenerator; - - /// 退出点定义 - public ThingDef exitDef; - - /// 口袋地图大小 - public IntVec2 pocketMapSize = new IntVec2(13, 13); - - /// 允许直接访问 - public bool allowDirectAccess = true; + public Building_ArmedShuttleWithPocket shuttle; + + public MapPortalAdapter() { } // Scribe需要无参数构造函数 + + public MapPortalAdapter(Building_ArmedShuttleWithPocket shuttle) + { + this.shuttle = shuttle; + } + + public new Map PocketMap => shuttle?.PocketMap; + + public new bool PocketMapExists => shuttle?.PocketMap != null; // 修正 + + public new bool AutoDraftOnEnter => false; // 修正 + + protected new Texture2D EnterTex => ContentFinder.Get("UI/Commands/LoadTransporter"); // 修正 + + public new string EnterString => shuttle?.EnterString; + + public new string CancelEnterString => shuttle?.CancelEnterString; + + public new string EnteringString => shuttle?.EnteringString; + + public new bool LoadInProgress => shuttle?.LoadInProgress ?? false; + + public new bool AnyPawnCanLoadAnythingNow => shuttle?.AnyPawnCanLoadAnythingNow ?? false; + + public override void ExposeData() + { + base.ExposeData(); + Scribe_References.Look(ref shuttle, "shuttle"); + } + + public override void SpawnSetup(Map map, bool respawningAfterLoad) + { + // 适配器不应该被Spawn,此方法留空或报错 + Log.Error("MapPortalAdapter should not be spawned directly."); + } + + protected override void Tick() + { + // 适配器不应该Tick,此方法留空 + } + + public new ThingOwner GetDirectlyHeldThings() + { + return shuttle?.GetDirectlyHeldThings(); + } + + public new void GetChildHolders(List outChildren) + { + shuttle?.GetChildHolders(outChildren); + } + + public new void Notify_ThingAdded(Thing t) + { + shuttle?.Notify_ThingAdded(t); + } + + public new void AddToTheToLoadList(TransferableOneWay t, int count) + { + shuttle?.AddToTheToLoadList(t, count); + } + + public new int SubtractFromToLoadList(Thing t, int count) + { + return shuttle?.SubtractFromToLoadList(t, count) ?? 0; + } + + public new void CancelLoad() + { + shuttle?.CancelLoad(); + } + + public new bool IsEnterable(out string reason) + { + if (shuttle == null) + { + reason = "WULA.PocketSpace.AdapterError".Translate(); + return false; + } + return shuttle.IsEnterable(out reason); + } + + public new Map GetOtherMap() + { + return shuttle?.GetOtherMap(); + } + + public new IntVec3 GetDestinationLocation() + { + return shuttle?.GetDestinationLocation() ?? IntVec3.Invalid; + } + + public new void OnEntered(Pawn pawn) + { + shuttle?.OnEntered(pawn); + } + + public new IEnumerable GetGizmos() + { + // 适配器不直接提供Gizmo,Gizmo应该由shuttle提供 + return base.GetGizmos(); // 或者返回空的IEnumerable + } } + + #endregion // MapPortal兼容接口 + } \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs b/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs deleted file mode 100644 index 31c11371..00000000 --- a/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs +++ /dev/null @@ -1,366 +0,0 @@ -using RimWorld; -using Verse; -using System.Collections.Generic; -using UnityEngine; -using System.Reflection; - -namespace WulaFallenEmpire -{ - /// - /// 口袋空间传送门组件 - 只作为入口功能,附加在穿梭机上处理进入内部空间的逻辑 - /// - public class CompPocketMapPortal : ThingComp - { - /// 组件属性 - public CompProperties_PocketMapPortal Props => (CompProperties_PocketMapPortal)props; - - /// 父建筑(必须是穿梭机) - public Building_ArmedShuttleWithPocket ParentShuttle => parent as Building_ArmedShuttleWithPocket; - - /// MapPortal适配器,用于使用原版Dialog_EnterPortal - private ShuttlePortalAdapter portalAdapter; - - public override void PostSpawnSetup(bool respawningAfterLoad) - { - base.PostSpawnSetup(respawningAfterLoad); - - Log.Message($"[WULA-DEBUG] CompPocketMapPortal.PostSpawnSetup called. Parent: {parent?.def?.defName ?? "null"}"); - - // 检查父对象是否是穿梭机 - if (ParentShuttle == null) - { - Log.Error($"[WULA] CompPocketMapPortal attached to non-shuttle building: {parent?.def?.defName}"); - return; // Early exit if parent is not a shuttle - } - - // 创建MapPortal适配器,并设置其地图和位置信息 - portalAdapter = new ShuttlePortalAdapter(ParentShuttle); - // 确保 portalAdapter 的 shuttle 引用被正确设置 - if (portalAdapter != null) - { - portalAdapter.shuttle = ParentShuttle; - Log.Message($"[WULA-DEBUG] portalAdapter.shuttle set in PostSpawnSetup: {portalAdapter.shuttle?.def.defName ?? "null"}"); - } - } - - /// - /// 检查穿梭机是否可以进入(仅作为入口功能) - /// - public bool IsEnterable(out string reason) - { - if (ParentShuttle == null) - { - reason = "WULA.PocketSpace.NotSpawned".Translate(); - return false; - } - - if (!ParentShuttle.AllowDirectAccess) - { - reason = "WULA.PocketSpace.AccessDenied".Translate(); - return false; - } - - if (!ParentShuttle.Spawned) - { - reason = "WULA.PocketSpace.NotSpawned".Translate(); - return false; - } - - // 检查穿梭机的传送状态 - var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - - if (transportDisabledField != null) - { - bool transportDisabled = (bool)transportDisabledField.GetValue(ParentShuttle); - if (transportDisabled) - { - reason = "WULA.PocketSpace.TransportDisabled".Translate(); - return false; - } - } - - // 检查口袋地图是否存在 - if (ParentShuttle.PocketMap == null) - { - reason = "WULA.PocketSpace.NoTargetMap".Translate(); - return false; - } - - reason = ""; - return true; - } - - - /// - /// 获取组件额外的Gizmo按钮(根据口袋空间初始化状态显示不同按钮) - /// 重写CompGetGizmosExtra方法,这样RimWorld会自动调用并显示按钮 - /// - public override IEnumerable CompGetGizmosExtra() - { - if (ParentShuttle == null) yield break; - - // 检查口袋空间是否已初始化 - bool pocketMapExists = ParentShuttle.PocketMap != null; - - if (!pocketMapExists) - { - // 口袋空间未创建,显示初始化按钮 - Command_Action initializeCommand = new Command_Action(); - initializeCommand.action = delegate - { - // 创建口袋空间 - InitializePocketSpace(); - }; - initializeCommand.icon = ContentFinder.Get("UI/Commands/LoadTransporter"); - initializeCommand.defaultLabel = "WULA.PocketSpace.Initialize".Translate(); - initializeCommand.defaultDesc = "WULA.PocketSpace.InitializeDesc".Translate(); - - // 检查是否可以初始化 - if (!ParentShuttle.Spawned) - { - initializeCommand.Disabled = true; - initializeCommand.disabledReason = "WULA.PocketSpace.NotSpawned".Translate(); - } - - yield return initializeCommand; - } - else - { - // 穿梭机已创建,显示装载按钮(使用原版Dialog_EnterPortal) - Command_Action enterCommand = new Command_Action(); - enterCommand.action = delegate - { - // 使用和Building_PocketMapExit一模一样的Dialog_EnterPortal方法 - if (portalAdapter == null || portalAdapter.shuttle != ParentShuttle) - { - // 重新创建并设置适配器,确保其指向正确的穿梭机 - portalAdapter = new ShuttlePortalAdapter(ParentShuttle); - // 再次尝试设置 MapPortal 基类的地图和位置信息 - try - { - var mapField = typeof(Thing).GetField("mapIndexOrState", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - var positionField = typeof(Thing).GetField("positionInt", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - - if (mapField != null && positionField != null && ParentShuttle.Spawned) - { - mapField.SetValue(portalAdapter, (sbyte)ParentShuttle.Map.Index); // 显式转换为 sbyte - positionField.SetValue(portalAdapter, ParentShuttle.Position); - } - } - catch (System.Exception ex) - { - Log.Error($"[WULA] Error setting MapPortal base fields during Gizmo click: {ex.Message}"); - } - } - - if (portalAdapter != null) - { - Log.Message($"[WULA-DEBUG] Opening Dialog_EnterPortal with portalAdapter. Type: {portalAdapter.GetType().Name}. Shuttle: {portalAdapter.shuttle?.def.defName ?? "null"}"); - var dialog = new Dialog_EnterPortal(portalAdapter); - Find.WindowStack.Add(dialog); - } - else - { - Messages.Message("WULA.PocketSpace.AdapterError".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); - Log.Error("[WULA] Portal adapter is null after recreation attempt."); - } - }; - enterCommand.icon = ContentFinder.Get(Props.buttonIconPath); - enterCommand.defaultLabel = Props.enterButtonTextKey.Translate() + "..."; - enterCommand.defaultDesc = Props.enterButtonDescKey.Translate(); - - // 检查是否可以进入 - string reason; - enterCommand.Disabled = !IsEnterable(out reason); - enterCommand.disabledReason = reason; - yield return enterCommand; - - // 查看口袋地图按钮 - yield return new Command_Action - { - defaultLabel = "WULA.PocketSpace.SwitchTo".Translate(), - defaultDesc = "WULA.PocketSpace.SwitchToDesc".Translate(), - icon = ContentFinder.Get("UI/Commands/ViewCave"), - action = delegate - { - Current.Game.CurrentMap = ParentShuttle.PocketMap; - Find.CameraDriver.JumpToCurrentMapLoc(ParentShuttle.PocketMap.Center); - } - }; - } - } - - /// - /// 初始化口袋空间 - /// - private void InitializePocketSpace() - { - if (ParentShuttle == null || !ParentShuttle.Spawned) - { - Messages.Message("WULA.PocketSpace.CannotInitialize".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); - return; - } - - if (ParentShuttle.PocketMap != null) - { - Messages.Message("WULA.PocketSpace.AlreadyInitialized".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); - return; - } - - try - { - Log.Message("[WULA] Starting pocket space initialization via component"); - - // 使用穿梭机的SwitchToPocketSpace方法,它会自动创建口袋空间 - ParentShuttle.SwitchToPocketSpace(); - - if (ParentShuttle.PocketMap != null) - { - Messages.Message("WULA.PocketSpace.InitializeSuccess".Translate(), ParentShuttle, MessageTypeDefOf.PositiveEvent); - Log.Message("[WULA] Pocket space initialization completed successfully"); - } - else - { - Messages.Message("WULA.PocketSpace.InitializeFailed".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); - Log.Error("[WULA] Pocket space initialization failed"); - } - } - catch (System.Exception ex) - { - Log.Error($"[WULA] Error during pocket space initialization: {ex}"); - Messages.Message("WULA.PocketSpace.InitializeFailed".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); - } - } - - } - - /// - /// 口袋空间传送门组件属性 - /// - public class CompProperties_PocketMapPortal : CompProperties - { - /// 进入按钮文本键 - public string enterButtonTextKey = "WULA.PocketSpace.Enter"; - - /// 进入按钮描述键 - public string enterButtonDescKey = "WULA.PocketSpace.EnterDesc"; - - /// 按钮图标路径 - public string buttonIconPath = "UI/Commands/LoadTransporter"; - - public CompProperties_PocketMapPortal() - { - this.compClass = typeof(CompPocketMapPortal); - } - } - - /// - /// MapPortal适配器类,将Building_ArmedShuttleWithPocket适配为MapPortal接口 - /// 完全模仿Building_PocketMapExit的实现方式 - /// - public class ShuttlePortalAdapter : MapPortal - { - /// 关联的穿梭机 - public Building_ArmedShuttleWithPocket shuttle; - - /// - /// 默认构造函数(RimWorld组件系统要求) - /// - public ShuttlePortalAdapter() - { - // 在这里不初始化 shuttle,因为它将在 PostSpawnSetup 中设置 - } - - public ShuttlePortalAdapter(Building_ArmedShuttleWithPocket shuttle) - { - this.shuttle = shuttle; - } - - /// - /// 重写获取其他地图,返回口袋空间(模仿Building_PocketMapExit.GetOtherMap) - /// - public override Map GetOtherMap() - { - if (shuttle?.PocketMap == null) - { - // 如口袋空间还没创建,先创建它 - shuttle?.SwitchToPocketSpace(); - } - return shuttle?.PocketMap; - } - - /// - /// 重写获取目标位置,返回口袋空间中心(模仿Building_PocketMapExit.GetDestinationLocation) - /// - public override IntVec3 GetDestinationLocation() - { - return shuttle?.PocketMap?.Center ?? IntVec3.Invalid; - } - - /// - /// 重写是否可进入,检查穿梭机状态(模仿Building_PocketMapExit.IsEnterable) - /// - public override bool IsEnterable(out string reason) - { - if (shuttle == null || !shuttle.Spawned) - { - reason = "WULA.PocketSpace.NotSpawned".Translate(); - return false; - } - - if (!shuttle.AllowDirectAccess) - { - reason = "WULA.PocketSpace.AccessDenied".Translate(); - return false; - } - - // 检查穿梭机的传送状态 - var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled", - System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - - if (transportDisabledField != null) - { - bool transportDisabled = (bool)transportDisabledField.GetValue(shuttle); - if (transportDisabled) - { - reason = "WULA.PocketSpace.TransportDisabled".Translate(); - return false; - } - } - - reason = ""; - return true; - } - - /// - /// 重写进入事件,处理进入口袋空间(模仿Building_PocketMapExit.OnEntered) - /// - public override void OnEntered(Pawn pawn) - { - // 通知穿梭机有物品被添加(用于统计和管理) - shuttle?.Notify_ThingAdded(pawn); - - // 播放传送音效(如果存在) - if (Find.CurrentMap == shuttle?.Map) - { - // 可以在这里添加音效播放 - // def.portal?.traverseSound?.PlayOneShot(this); - } - } - /// 重写进入按钮文本 - /// - public override string EnterString => "WULA.PocketSpace.Enter".Translate(); - - /// - /// 重写进入按钮图标,使用装载按钮的贴图 - /// - protected override Texture2D EnterTex => ContentFinder.Get("UI/Commands/LoadTransporter"); - - // 移除了 new 关键字的 Map, Position, def 属性,因为它们在 MapPortal 基类中可能不是 virtual 的 - // 并且我们依赖 PostSpawnSetup 中的反射来设置 MapPortal 基类的私有字段 - // 这确保了 Dialog_EnterPortal 能够直接访问到正确的地图和位置信息。 - } -} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/PocketSpaceThingHolder.cs b/Source/WulaFallenEmpire/WULA_Shuttle/PocketSpaceThingHolder.cs new file mode 100644 index 00000000..291d1b22 --- /dev/null +++ b/Source/WulaFallenEmpire/WULA_Shuttle/PocketSpaceThingHolder.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using Verse; + +namespace WulaFallenEmpire +{ + /// + /// 用于武装穿梭机口袋空间的IThingHolder实现,与CompTransporter的容器分离 + /// + public class PocketSpaceThingHolder : IThingHolder, IExposable + { + /// 持有的物品容器 + public ThingOwner innerContainer; + + /// 该容器的拥有者(通常是Building_ArmedShuttleWithPocket) + private IThingHolder owner; + + /// 实现IThingHolder.ParentHolder属性 + public IThingHolder ParentHolder => owner; + + public PocketSpaceThingHolder() + { + innerContainer = new ThingOwner(this); + } + + public PocketSpaceThingHolder(IThingHolder owner) : this() + { + this.owner = owner; + } + + /// + /// 获取直接持有的物品 + /// + public ThingOwner GetDirectlyHeldThings() + { + return innerContainer; + } + + /// + /// 获取子持有者 + /// + public void GetChildHolders(List outChildren) + { + // 目前没有子持有者,留空 + } + + /// + /// 通知物品被添加 + /// + public void Notify_ThingAdded(Thing t) + { + // 这里可以添加逻辑来处理物品被添加到口袋空间的情况 + Log.Message($"[WULA] Item {t.LabelCap} added to pocket space container."); + } + + /// + /// 通知物品被移除 + /// + public void Notify_ThingRemoved(Thing t) + { + // 这里可以添加逻辑来处理物品被从口袋空间移除的情况 + Log.Message($"[WULA] Item {t.LabelCap} removed from pocket space container."); + } + + public void ExposeData() + { + Scribe_Deep.Look(ref innerContainer, "innerContainer", this); + // owner 通常在构造函数中设置,不需要序列化 + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 5a565947..9e17192e 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -96,7 +96,6 @@ - @@ -172,8 +171,8 @@ - +