1
This commit is contained in:
Binary file not shown.
@@ -3,56 +3,40 @@
|
||||
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
|
||||
"Documents": [
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\ara_aircrafthangar\\worldcomponent_aircraftmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_aircrafthangar\\worldcomponent_aircraftmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\thingclassflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\thingclassflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\ara_aircrafthangar\\compaircrafthangar.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_aircrafthangar\\compaircrafthangar.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\ara_aircrafthangar\\compabilityeffect_aircraftstrike.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_aircrafthangar\\compabilityeffect_aircraftstrike.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_aircrafthangar\\compabilityeffect_aircraftstrike.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\building_comps\\comprefuelablenutrition.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\comprefuelablenutrition.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_givehediffwithskillduration\\compabilityeffect_givehediffwithskillduration.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_givehediffwithskillduration\\compabilityeffect_givehediffwithskillduration.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\ara_sectorsurveillance\\compsectorsurveillance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_sectorsurveillance\\compsectorsurveillance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_showtemperaturerange\\compabilityeffect_abilityshowtemperaturerange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_showtemperaturerange\\compabilityeffect_abilityshowtemperaturerange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\thingclassflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\thingclassflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_showspawnablepawnslist\\compabilityeffect_abilityshowspawnablepawns.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_showspawnablepawnslist\\compabilityeffect_abilityshowspawnablepawns.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_spawnflyover\\compabilityeffect_spawnflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_spawnflyover\\compabilityeffect_spawnflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\flyover\\ara_spawnflyover\\compproperties_abilityspawnflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_spawnflyover\\compproperties_abilityspawnflyover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_aircrafthangar\\compaircrafthangar.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_aircrafthangar\\compaircrafthangar.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_groundstrafing\\compgroundstrafing.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_groundstrafing\\compgroundstrafing.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_flyoverescort\\compflyoverescort.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_flyoverescort\\compflyoverescort.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_aircrafthangar\\worldcomponent_aircraftmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_aircrafthangar\\worldcomponent_aircraftmanager.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_flyoverescort\\compproperties_flyoverescort.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_flyoverescort\\compproperties_flyoverescort.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_shipartillery\\compshipartillery.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_shipartillery\\compshipartillery.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
},
|
||||
{
|
||||
"AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\flyover\\ara_shipartillery\\compproperties_shipartillery.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:flyover\\ara_shipartillery\\compproperties_shipartillery.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
@@ -70,167 +54,112 @@
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CompAircraftHangar.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"ViewState": "AgIAAEoAAAAAAAAAAAAswFkAAAAdAAAAAAAAAA==",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "CompAbilityEffect_GiveHediffWithSkillDuration.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GiveHediffWithSkillDuration\\CompAbilityEffect_GiveHediffWithSkillDuration.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_GiveHediffWithSkillDuration\\CompAbilityEffect_GiveHediffWithSkillDuration.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GiveHediffWithSkillDuration\\CompAbilityEffect_GiveHediffWithSkillDuration.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_GiveHediffWithSkillDuration\\CompAbilityEffect_GiveHediffWithSkillDuration.cs",
|
||||
"ViewState": "AgIAAEsAAAAAAAAAAAAWwGAAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T06:31:52.619Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-29T14:40:47.422Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "CompRefuelableNutrition.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\CompRefuelableNutrition.cs",
|
||||
"RelativeDocumentMoniker": "Building_Comps\\CompRefuelableNutrition.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\CompRefuelableNutrition.cs",
|
||||
"RelativeToolTip": "Building_Comps\\CompRefuelableNutrition.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAUAAAAXAAAAAAAAAA==",
|
||||
"Title": "CompAbilityEffect_AbilityShowTemperatureRange.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_ShowTemperatureRange\\CompAbilityEffect_AbilityShowTemperatureRange.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAAArAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T06:31:46.148Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-29T14:40:43.525Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"DocumentIndex": 1,
|
||||
"Title": "CompAbilityEffect_AircraftStrike.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAbilityEffect_AircraftStrike.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_AircraftHangar\\CompAbilityEffect_AircraftStrike.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAbilityEffect_AircraftStrike.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_AircraftHangar\\CompAbilityEffect_AircraftStrike.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAACMAAAAAAAAAAAAAAA==",
|
||||
"ViewState": "AgIAAHYAAAAAAAAAAAAtwJcAAAArAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T06:30:49.523Z",
|
||||
"EditorCaption": ""
|
||||
"WhenOpened": "2025-10-29T11:22:34.783Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "WorldComponent_AircraftManager.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"ViewState": "AgIAAKsAAAAAAAAAAAAowBEAAAASAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T06:30:44.854Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "CompSectorSurveillance.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SectorSurveillance\\CompSectorSurveillance.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_SectorSurveillance\\CompSectorSurveillance.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SectorSurveillance\\CompSectorSurveillance.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_SectorSurveillance\\CompSectorSurveillance.cs",
|
||||
"ViewState": "AgIAAMYAAAAAAAAAAAAqwNUAAAARAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T02:30:42.063Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"Title": "CompGroundStrafing.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_GroundStrafing\\CompGroundStrafing.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_GroundStrafing\\CompGroundStrafing.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_GroundStrafing\\CompGroundStrafing.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_GroundStrafing\\CompGroundStrafing.cs",
|
||||
"ViewState": "AgIAAB0AAAAAAAAAAAAQwCYAAABFAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T16:19:23.118Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 6,
|
||||
"Title": "CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABYAAABOAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T14:51:14.836Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 7,
|
||||
"Title": "CompProperties_AbilitySpawnFlyOver.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompProperties_AbilitySpawnFlyOver.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_SpawnFlyOver\\CompProperties_AbilitySpawnFlyOver.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompProperties_AbilitySpawnFlyOver.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_SpawnFlyOver\\CompProperties_AbilitySpawnFlyOver.cs",
|
||||
"ViewState": "AgIAABgAAAAAAAAAAAAswDQAAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T13:51:12.201Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "ThingclassFlyOver.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ThingclassFlyOver.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ThingclassFlyOver.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ThingclassFlyOver.cs",
|
||||
"RelativeToolTip": "Flyover\\ThingclassFlyOver.cs",
|
||||
"ViewState": "AgIAAAkCAAAAAAAAAAAqwCYCAAB/AAAAAAAAAA==",
|
||||
"ViewState": "AgIAAC0CAAAAAAAAAAAawCUCAAANAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T09:09:22.03Z",
|
||||
"WhenOpened": "2025-10-29T14:17:06.867Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 9,
|
||||
"Title": "CompFlyOverEscort.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_FlyOverEscort\\CompFlyOverEscort.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_FlyOverEscort\\CompFlyOverEscort.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_FlyOverEscort\\CompFlyOverEscort.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_FlyOverEscort\\CompFlyOverEscort.cs",
|
||||
"ViewState": "AgIAAKYBAAAAAAAAAAAWwNEBAAAAAAAAAAAAAA==",
|
||||
"DocumentIndex": 4,
|
||||
"Title": "CompAbilityEffect_AbilityShowSpawnablePawns.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowSpawnablePawnsList\\CompAbilityEffect_AbilityShowSpawnablePawns.cs",
|
||||
"RelativeDocumentMoniker": "Abilities\\ARA_ShowSpawnablePawnsList\\CompAbilityEffect_AbilityShowSpawnablePawns.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_ShowSpawnablePawnsList\\CompAbilityEffect_AbilityShowSpawnablePawns.cs",
|
||||
"RelativeToolTip": "Abilities\\ARA_ShowSpawnablePawnsList\\CompAbilityEffect_AbilityShowSpawnablePawns.cs",
|
||||
"ViewState": "AgIAABYAAAAAAAAAAAAuwBYAAAArAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T07:30:55.268Z"
|
||||
"WhenOpened": "2025-10-29T14:40:40.237Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 10,
|
||||
"DocumentIndex": 6,
|
||||
"Title": "CompAircraftHangar.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_AircraftHangar\\CompAircraftHangar.cs",
|
||||
"ViewState": "AgIAABcAAAAAAAAAAAAQwCQAAAAnAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T11:39:22.563Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 5,
|
||||
"Title": "CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_SpawnFlyOver\\CompAbilityEffect_SpawnFlyOver.cs",
|
||||
"ViewState": "AgIAAFMDAAAAAAAAAAAawG8DAAAAAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T13:37:35.758Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 7,
|
||||
"Title": "WorldComponent_AircraftManager.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_AircraftHangar\\WorldComponent_AircraftManager.cs",
|
||||
"ViewState": "AgIAAJUAAAAAAAAAAAAowK4AAAAUAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-29T14:05:39.817Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 8,
|
||||
"Title": "CompProperties_FlyOverEscort.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_FlyOverEscort\\CompProperties_FlyOverEscort.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_FlyOverEscort\\CompProperties_FlyOverEscort.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_FlyOverEscort\\CompProperties_FlyOverEscort.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_FlyOverEscort\\CompProperties_FlyOverEscort.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABgAAAAPAAAAAAAAAA==",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAAAvAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T07:30:47.27Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 12,
|
||||
"Title": "CompProperties_ShipArtillery.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_ShipArtillery\\CompProperties_ShipArtillery.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_ShipArtillery\\CompProperties_ShipArtillery.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_ShipArtillery\\CompProperties_ShipArtillery.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_ShipArtillery\\CompProperties_ShipArtillery.cs",
|
||||
"ViewState": "AgIAAAAAAAAAAAAAAAAAAA8AAAAhAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T06:21:06.271Z"
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 11,
|
||||
"Title": "CompShipArtillery.cs",
|
||||
"DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_ShipArtillery\\CompShipArtillery.cs",
|
||||
"RelativeDocumentMoniker": "Flyover\\ARA_ShipArtillery\\CompShipArtillery.cs",
|
||||
"ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Flyover\\ARA_ShipArtillery\\CompShipArtillery.cs",
|
||||
"RelativeToolTip": "Flyover\\ARA_ShipArtillery\\CompShipArtillery.cs",
|
||||
"ViewState": "AgIAALEAAAAAAAAAAAAywNEAAABcAAAAAAAAAA==",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-10-28T06:21:04.222Z"
|
||||
"WhenOpened": "2025-10-29T12:59:07.753Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using RimWorld;
|
||||
using Verse;
|
||||
using RimWorld.Planet;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
@@ -30,40 +31,24 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (aircraftManager == null)
|
||||
{
|
||||
Log.Error("Aircraft manager not found!");
|
||||
Log.Error("AircraftManagerNotFound".Translate());
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查并消耗战机
|
||||
if (aircraftManager.TryUseAircraft(Props.requiredAircraftType, Props.aircraftsPerUse, parent.pawn.Faction, Props.aircraftCooldownTicks))
|
||||
{
|
||||
// 执行打击效果
|
||||
ExecuteStrikeEffect(target);
|
||||
|
||||
Messages.Message($"Aircraft strike initiated: {Props.requiredAircraftType.LabelCap}", MessageTypeDefOf.PositiveEvent);
|
||||
// 成功消耗战机,发送消息
|
||||
Messages.Message("AircraftStrikeInitiated".Translate(Props.requiredAircraftType.LabelCap), MessageTypeDefOf.PositiveEvent);
|
||||
Log.Message("AircraftStrikeSuccess".Translate(Props.aircraftsPerUse, Props.requiredAircraftType.LabelCap));
|
||||
}
|
||||
else
|
||||
{
|
||||
Messages.Message($"No available aircraft: {Props.requiredAircraftType.LabelCap}", MessageTypeDefOf.NegativeEvent);
|
||||
Messages.Message("NoAvailableAircraft".Translate(Props.requiredAircraftType.LabelCap), MessageTypeDefOf.NegativeEvent);
|
||||
Log.Warning("AircraftStrikeFailed".Translate(Props.requiredAircraftType.LabelCap, parent.pawn.Faction?.Name ?? "UnknownFaction".Translate()));
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecuteStrikeEffect(LocalTargetInfo target)
|
||||
{
|
||||
// 这里实现具体的打击效果
|
||||
// 例如:轰炸、空投、侦察等
|
||||
|
||||
// 示例:在目标位置创建爆炸效果
|
||||
GenExplosion.DoExplosion(
|
||||
target.Cell,
|
||||
parent.pawn.Map,
|
||||
radius: 3.5f,
|
||||
DamageDefOf.Bomb,
|
||||
instigator: parent.pawn,
|
||||
damAmount: 50
|
||||
);
|
||||
}
|
||||
|
||||
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
// 检查是否有可用的战机
|
||||
@@ -81,10 +66,97 @@ namespace ArachnaeSwarm
|
||||
if (aircraftManager != null)
|
||||
{
|
||||
int available = aircraftManager.GetAvailableAircraftCount(Props.requiredAircraftType, parent.pawn.Faction);
|
||||
return $"Available {Props.requiredAircraftType.LabelCap}: {available}";
|
||||
int onCooldown = aircraftManager.GetCooldownAircraftCount(Props.requiredAircraftType, parent.pawn.Faction);
|
||||
|
||||
// 使用符号显示飞机状态
|
||||
string availableSymbols = GetAircraftSymbols(available, "◆");
|
||||
string cooldownSymbols = GetAircraftSymbols(onCooldown, "◇");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("AvailableAircraft".Translate(Props.requiredAircraftType.LabelCap, availableSymbols));
|
||||
sb.AppendLine("CooldownAircraft".Translate(cooldownSymbols));
|
||||
sb.Append("CostPerUse".Translate(Props.aircraftsPerUse));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
return base.ExtraLabelMouseAttachment(target);
|
||||
}
|
||||
|
||||
// 生成飞机符号表示
|
||||
private string GetAircraftSymbols(int count, string symbol)
|
||||
{
|
||||
if (count <= 0) return "—"; // 无飞机时显示破折号
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int displayCount = count;
|
||||
|
||||
// 如果数量过多,用数字+符号表示
|
||||
if (count > 10)
|
||||
{
|
||||
return $"{count}{symbol}";
|
||||
}
|
||||
|
||||
// 直接显示符号
|
||||
for (int i = 0; i < displayCount; i++)
|
||||
{
|
||||
sb.Append(symbol);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
|
||||
{
|
||||
if (!base.Valid(target, throwMessages))
|
||||
return false;
|
||||
|
||||
// 检查战机可用性
|
||||
WorldComponent_AircraftManager aircraftManager = Find.World.GetComponent<WorldComponent_AircraftManager>();
|
||||
if (aircraftManager == null || !aircraftManager.HasAvailableAircraft(Props.requiredAircraftType, Props.aircraftsPerUse, parent.pawn.Faction))
|
||||
{
|
||||
if (throwMessages)
|
||||
{
|
||||
Messages.Message("NoAircraftForStrike".Translate(Props.requiredAircraftType.LabelCap), MessageTypeDefOf.RejectInput);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 鼠标悬停时的工具提示
|
||||
public override string ExtraTooltipPart()
|
||||
{
|
||||
WorldComponent_AircraftManager aircraftManager = Find.World.GetComponent<WorldComponent_AircraftManager>();
|
||||
|
||||
if (aircraftManager != null)
|
||||
{
|
||||
int available = aircraftManager.GetAvailableAircraftCount(Props.requiredAircraftType, parent.pawn.Faction);
|
||||
int onCooldown = aircraftManager.GetCooldownAircraftCount(Props.requiredAircraftType, parent.pawn.Faction);
|
||||
int total = available + onCooldown;
|
||||
|
||||
// 将冷却时间从 tick 转换为小时
|
||||
float cooldownHours = TicksToHours(Props.aircraftCooldownTicks);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("AircraftStatusTooltip".Translate());
|
||||
sb.AppendLine("• " + "TotalAircraft".Translate(total));
|
||||
sb.AppendLine("• " + "ReadyAircraft".Translate(available));
|
||||
sb.AppendLine("• " + "CooldownAircraft".Translate(onCooldown));
|
||||
sb.AppendLine("AircraftAbilityDescription".Translate(Props.requiredAircraftType.LabelCap, Props.aircraftsPerUse, cooldownHours.ToString("F1")));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
return base.ExtraTooltipPart();
|
||||
}
|
||||
|
||||
// 将 tick 转换为小时
|
||||
private float TicksToHours(int ticks)
|
||||
{
|
||||
// RimWorld 中 1 小时 = 2500 tick
|
||||
return ticks / 2500f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace ArachnaeSwarm
|
||||
// 起飞命令
|
||||
Command_Action launchCommand = new Command_Action
|
||||
{
|
||||
defaultLabel = "Launch Aircraft",
|
||||
defaultDesc = "Launch aircraft for orbital support",
|
||||
defaultLabel = "LaunchAircraft".Translate(),
|
||||
defaultDesc = "LaunchAircraftDesc".Translate(),
|
||||
icon = TexCommand.Attack,
|
||||
action = LaunchAircraft
|
||||
};
|
||||
@@ -40,7 +40,7 @@ namespace ArachnaeSwarm
|
||||
// 检查条件:建筑完好
|
||||
if (parent.HitPoints <= 0)
|
||||
{
|
||||
launchCommand.Disable("Hangar damaged");
|
||||
launchCommand.Disable("HangarDamaged".Translate());
|
||||
}
|
||||
|
||||
yield return launchCommand;
|
||||
@@ -53,15 +53,15 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (aircraftManager == null)
|
||||
{
|
||||
Log.Error("Aircraft manager not found!");
|
||||
Log.Error("AircraftManagerNotFound".Translate());
|
||||
return;
|
||||
}
|
||||
|
||||
// 立即向全局管理器注册战机(在创建 Skyfaller 之前)
|
||||
// 立即向全局管理器注册战机
|
||||
aircraftManager.AddAircraft(Props.aircraftDef, Props.aircraftCount, parent.Faction);
|
||||
|
||||
// 显示消息
|
||||
Messages.Message($"Aircraft launched: {Props.aircraftCount}x {Props.aircraftDef.LabelCap}", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("AircraftLaunched".Translate(Props.aircraftCount, Props.aircraftDef.LabelCap), MessageTypeDefOf.PositiveEvent);
|
||||
|
||||
// 创建起飞效果(仅视觉效果)
|
||||
if (Props.skyfallerLeaving != null)
|
||||
@@ -77,17 +77,39 @@ namespace ArachnaeSwarm
|
||||
|
||||
private void CreateTakeoffEffect()
|
||||
{
|
||||
// 创建起飞天空坠落者
|
||||
Skyfaller skyfaller = SkyfallerMaker.MakeSkyfaller(Props.skyfallerLeaving, parent);
|
||||
|
||||
// 设置起飞位置(建筑当前位置)
|
||||
IntVec3 takeoffPos = parent.Position;
|
||||
|
||||
// 生成 Skyfaller
|
||||
GenSpawn.Spawn(skyfaller, takeoffPos, parent.Map);
|
||||
|
||||
// 立即销毁原建筑(Skyfaller 只是视觉效果)
|
||||
parent.Destroy();
|
||||
try
|
||||
{
|
||||
// 创建 1 单位 Chemfuel 作为 Skyfaller 的内容物
|
||||
Thing chemfuel = ThingMaker.MakeThing(ThingDefOf.Chemfuel);
|
||||
chemfuel.stackCount = 1;
|
||||
|
||||
// 创建包含 Chemfuel 的 Skyfaller
|
||||
Skyfaller skyfaller = SkyfallerMaker.MakeSkyfaller(Props.skyfallerLeaving, chemfuel);
|
||||
|
||||
// 设置起飞位置(建筑当前位置)
|
||||
IntVec3 takeoffPos = parent.Position;
|
||||
|
||||
// 检查地图是否有效
|
||||
if (parent.Map == null)
|
||||
{
|
||||
Log.Error("TakeoffEffectMapNull".Translate());
|
||||
return;
|
||||
}
|
||||
|
||||
// 生成 Skyfaller
|
||||
GenSpawn.Spawn(skyfaller, takeoffPos, parent.Map);
|
||||
|
||||
Log.Message("TakeoffSkyfallerCreated".Translate(takeoffPos));
|
||||
|
||||
// 销毁原建筑
|
||||
parent.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Error("TakeoffEffectError".Translate(ex.Message));
|
||||
// 如果Skyfaller创建失败,直接销毁建筑
|
||||
parent.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
|
||||
@@ -8,55 +8,43 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
public class WorldComponent_AircraftManager : WorldComponent
|
||||
{
|
||||
private Dictionary<Faction, Dictionary<ThingDef, AircraftFactionData>> factionAircraftData =
|
||||
new Dictionary<Faction, Dictionary<ThingDef, AircraftFactionData>>();
|
||||
|
||||
// 使用列表而不是嵌套字典,更容易序列化
|
||||
private List<FactionAircraftData> allFactionAircraftData = new List<FactionAircraftData>();
|
||||
private List<AircraftCooldownEvent> cooldownEvents = new List<AircraftCooldownEvent>();
|
||||
|
||||
public WorldComponent_AircraftManager(World world) : base(world) { }
|
||||
|
||||
// 战机派系数据类
|
||||
private class AircraftFactionData : IExposable
|
||||
// 派系战机数据
|
||||
private class FactionAircraftData : IExposable
|
||||
{
|
||||
public int totalCount; // 总战机数量
|
||||
public int availableCount; // 可用战机数量
|
||||
public Faction faction;
|
||||
public ThingDef aircraftDef;
|
||||
public int totalCount;
|
||||
public int availableCount;
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_Values.Look(ref totalCount, "totalCount");
|
||||
Scribe_Values.Look(ref availableCount, "availableCount");
|
||||
Scribe_References.Look(ref faction, "faction");
|
||||
Scribe_Defs.Look(ref aircraftDef, "aircraftDef");
|
||||
Scribe_Values.Look(ref totalCount, "totalCount", 0);
|
||||
Scribe_Values.Look(ref availableCount, "availableCount", 0);
|
||||
}
|
||||
}
|
||||
|
||||
// 冷却事件类
|
||||
// 冷却事件
|
||||
private class AircraftCooldownEvent : IExposable
|
||||
{
|
||||
public Faction faction;
|
||||
public ThingDef aircraftDef;
|
||||
public int endTick;
|
||||
public int aircraftCount; // 冷却中的战机数量
|
||||
public int aircraftCount;
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_References.Look(ref faction, "faction");
|
||||
Scribe_Defs.Look(ref aircraftDef, "aircraftDef");
|
||||
Scribe_Values.Look(ref endTick, "endTick");
|
||||
Scribe_Values.Look(ref aircraftCount, "aircraftCount");
|
||||
}
|
||||
}
|
||||
|
||||
// 用于序列化的包装类
|
||||
private class SerializableFactionAircraftData : IExposable
|
||||
{
|
||||
public Faction faction;
|
||||
public ThingDef aircraftDef;
|
||||
public AircraftFactionData data;
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_References.Look(ref faction, "faction");
|
||||
Scribe_Defs.Look(ref aircraftDef, "aircraftDef");
|
||||
Scribe_Deep.Look(ref data, "data");
|
||||
Scribe_Values.Look(ref endTick, "endTick", 0);
|
||||
Scribe_Values.Look(ref aircraftCount, "aircraftCount", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,50 +52,25 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
base.ExposeData();
|
||||
|
||||
// 保存派系战机数据
|
||||
List<SerializableFactionAircraftData> serializableData = new List<SerializableFactionAircraftData>();
|
||||
// 使用简单的列表序列化
|
||||
Scribe_Collections.Look(ref allFactionAircraftData, "allFactionAircraftData", LookMode.Deep);
|
||||
Scribe_Collections.Look(ref cooldownEvents, "cooldownEvents", LookMode.Deep);
|
||||
|
||||
// 确保列表不为null
|
||||
if (allFactionAircraftData == null)
|
||||
allFactionAircraftData = new List<FactionAircraftData>();
|
||||
if (cooldownEvents == null)
|
||||
cooldownEvents = new List<AircraftCooldownEvent>();
|
||||
|
||||
// 调试日志
|
||||
if (Scribe.mode == LoadSaveMode.Saving)
|
||||
{
|
||||
// 将字典数据转换为可序列化的列表
|
||||
foreach (var factionPair in factionAircraftData)
|
||||
{
|
||||
foreach (var aircraftPair in factionPair.Value)
|
||||
{
|
||||
serializableData.Add(new SerializableFactionAircraftData
|
||||
{
|
||||
faction = factionPair.Key,
|
||||
aircraftDef = aircraftPair.Key,
|
||||
data = aircraftPair.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
Log.Message($"Saving aircraft data: {allFactionAircraftData.Count} faction entries, {cooldownEvents.Count} cooldown events");
|
||||
}
|
||||
|
||||
Scribe_Collections.Look(ref serializableData, "factionAircraftData", LookMode.Deep);
|
||||
|
||||
if (Scribe.mode == LoadSaveMode.LoadingVars)
|
||||
else if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
// 从序列化数据重建字典
|
||||
factionAircraftData.Clear();
|
||||
if (serializableData != null)
|
||||
{
|
||||
foreach (var item in serializableData)
|
||||
{
|
||||
if (item.faction != null && item.aircraftDef != null && item.data != null)
|
||||
{
|
||||
if (!factionAircraftData.ContainsKey(item.faction))
|
||||
{
|
||||
factionAircraftData[item.faction] = new Dictionary<ThingDef, AircraftFactionData>();
|
||||
}
|
||||
factionAircraftData[item.faction][item.aircraftDef] = item.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.Message($"Loaded aircraft data: {allFactionAircraftData.Count} faction entries, {cooldownEvents.Count} cooldown events");
|
||||
}
|
||||
|
||||
// 保存冷却事件 - 显式指定泛型类型
|
||||
Scribe_Collections.Look(ref cooldownEvents, "cooldownEvents", LookMode.Deep);
|
||||
}
|
||||
|
||||
public override void WorldComponentTick()
|
||||
@@ -122,35 +85,50 @@ namespace ArachnaeSwarm
|
||||
|
||||
if (currentTick >= cooldownEvent.endTick)
|
||||
{
|
||||
// 冷却结束,恢复战机可用性
|
||||
RestoreAircraftAfterCooldown(cooldownEvent);
|
||||
cooldownEvents.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取或创建派系战机数据
|
||||
private FactionAircraftData GetOrCreateFactionAircraftData(Faction faction, ThingDef aircraftDef)
|
||||
{
|
||||
var data = allFactionAircraftData.FirstOrDefault(x => x.faction == faction && x.aircraftDef == aircraftDef);
|
||||
if (data == null)
|
||||
{
|
||||
data = new FactionAircraftData
|
||||
{
|
||||
faction = faction,
|
||||
aircraftDef = aircraftDef,
|
||||
totalCount = 0,
|
||||
availableCount = 0
|
||||
};
|
||||
allFactionAircraftData.Add(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// 获取派系战机数据(可能为null)
|
||||
private FactionAircraftData GetFactionAircraftData(Faction faction, ThingDef aircraftDef)
|
||||
{
|
||||
return allFactionAircraftData.FirstOrDefault(x => x.faction == faction && x.aircraftDef == aircraftDef);
|
||||
}
|
||||
|
||||
// 添加战机到派系
|
||||
public void AddAircraft(ThingDef aircraftDef, int count, Faction faction)
|
||||
{
|
||||
if (faction == null)
|
||||
{
|
||||
Log.Error("Attempted to add aircraft to null faction");
|
||||
Log.Error("AddAircraftNullFaction".Translate());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!factionAircraftData.ContainsKey(faction))
|
||||
{
|
||||
factionAircraftData[faction] = new Dictionary<ThingDef, AircraftFactionData>();
|
||||
}
|
||||
|
||||
if (!factionAircraftData[faction].ContainsKey(aircraftDef))
|
||||
{
|
||||
factionAircraftData[faction][aircraftDef] = new AircraftFactionData();
|
||||
}
|
||||
|
||||
var data = factionAircraftData[faction][aircraftDef];
|
||||
var data = GetOrCreateFactionAircraftData(faction, aircraftDef);
|
||||
data.totalCount += count;
|
||||
data.availableCount += count;
|
||||
|
||||
Log.Message($"Added {count} {aircraftDef.LabelCap} to {faction.Name}. Total: {data.totalCount}, Available: {data.availableCount}");
|
||||
}
|
||||
|
||||
// 尝试使用战机
|
||||
@@ -159,10 +137,9 @@ namespace ArachnaeSwarm
|
||||
if (!HasAvailableAircraft(aircraftDef, count, faction))
|
||||
return false;
|
||||
|
||||
var data = factionAircraftData[faction][aircraftDef];
|
||||
var data = GetFactionAircraftData(faction, aircraftDef);
|
||||
data.availableCount -= count;
|
||||
|
||||
// 创建冷却事件
|
||||
AircraftCooldownEvent cooldownEvent = new AircraftCooldownEvent
|
||||
{
|
||||
faction = faction,
|
||||
@@ -173,86 +150,75 @@ namespace ArachnaeSwarm
|
||||
|
||||
cooldownEvents.Add(cooldownEvent);
|
||||
|
||||
Log.Message($"Used {count} {aircraftDef.LabelCap} from {faction.Name}. Available now: {data.availableCount}, Cooldown until: {cooldownEvent.endTick}");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否有可用战机
|
||||
public bool HasAvailableAircraft(ThingDef aircraftDef, int count, Faction faction)
|
||||
{
|
||||
return factionAircraftData.ContainsKey(faction) &&
|
||||
factionAircraftData[faction].ContainsKey(aircraftDef) &&
|
||||
factionAircraftData[faction][aircraftDef].availableCount >= count;
|
||||
var data = GetFactionAircraftData(faction, aircraftDef);
|
||||
return data != null && data.availableCount >= count;
|
||||
}
|
||||
|
||||
// 获取可用战机数量
|
||||
public int GetAvailableAircraftCount(ThingDef aircraftDef, Faction faction)
|
||||
{
|
||||
if (factionAircraftData.ContainsKey(faction) &&
|
||||
factionAircraftData[faction].ContainsKey(aircraftDef))
|
||||
{
|
||||
return factionAircraftData[faction][aircraftDef].availableCount;
|
||||
}
|
||||
return 0;
|
||||
var data = GetFactionAircraftData(faction, aircraftDef);
|
||||
return data?.availableCount ?? 0;
|
||||
}
|
||||
|
||||
// 获取总战机数量
|
||||
public int GetTotalAircraftCount(ThingDef aircraftDef, Faction faction)
|
||||
{
|
||||
if (factionAircraftData.ContainsKey(faction) &&
|
||||
factionAircraftData[faction].ContainsKey(aircraftDef))
|
||||
{
|
||||
return factionAircraftData[faction][aircraftDef].totalCount;
|
||||
}
|
||||
return 0;
|
||||
var data = GetFactionAircraftData(faction, aircraftDef);
|
||||
return data?.totalCount ?? 0;
|
||||
}
|
||||
|
||||
// 冷却结束后恢复战机
|
||||
private void RestoreAircraftAfterCooldown(AircraftCooldownEvent cooldownEvent)
|
||||
{
|
||||
if (cooldownEvent.faction != null &&
|
||||
factionAircraftData.ContainsKey(cooldownEvent.faction) &&
|
||||
factionAircraftData[cooldownEvent.faction].ContainsKey(cooldownEvent.aircraftDef))
|
||||
var data = GetFactionAircraftData(cooldownEvent.faction, cooldownEvent.aircraftDef);
|
||||
if (data != null)
|
||||
{
|
||||
var data = factionAircraftData[cooldownEvent.faction][cooldownEvent.aircraftDef];
|
||||
data.availableCount += cooldownEvent.aircraftCount;
|
||||
|
||||
// 可选:显示冷却结束消息
|
||||
if (cooldownEvent.aircraftDef != null)
|
||||
{
|
||||
Messages.Message($"{cooldownEvent.aircraftDef.LabelCap} cooldown ended", MessageTypeDefOf.PositiveEvent);
|
||||
Messages.Message("AircraftCooldownEnded".Translate(cooldownEvent.aircraftDef.LabelCap), MessageTypeDefOf.PositiveEvent);
|
||||
Log.Message($"Cooldown ended for {cooldownEvent.aircraftCount} {cooldownEvent.aircraftDef.LabelCap}. Available now: {data.availableCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取战机状态信息(用于调试或UI显示)
|
||||
public string GetAircraftStatus(Faction faction)
|
||||
{
|
||||
if (!factionAircraftData.ContainsKey(faction))
|
||||
return "No aircraft";
|
||||
|
||||
var status = new List<string>();
|
||||
foreach (var kvp in factionAircraftData[faction])
|
||||
{
|
||||
var data = kvp.Value;
|
||||
int inCooldown = data.totalCount - data.availableCount;
|
||||
status.Add($"{kvp.Key.LabelCap}: {data.availableCount}/{data.totalCount} (In cooldown: {inCooldown})");
|
||||
}
|
||||
|
||||
return string.Join("\n", status);
|
||||
}
|
||||
|
||||
// 获取冷却中的战机数量
|
||||
public int GetCooldownAircraftCount(ThingDef aircraftDef, Faction faction)
|
||||
{
|
||||
int totalCooldown = 0;
|
||||
foreach (var cooldownEvent in cooldownEvents)
|
||||
return cooldownEvents
|
||||
.Where(e => e.faction == faction && e.aircraftDef == aircraftDef)
|
||||
.Sum(e => e.aircraftCount);
|
||||
}
|
||||
|
||||
// 调试方法:显示当前状态
|
||||
public void DebugLogStatus()
|
||||
{
|
||||
Log.Message("=== Aircraft Manager Status ===");
|
||||
Log.Message($"Total faction entries: {allFactionAircraftData.Count}");
|
||||
|
||||
var factions = allFactionAircraftData.Select(x => x.faction).Distinct();
|
||||
foreach (var faction in factions)
|
||||
{
|
||||
if (cooldownEvent.faction == faction && cooldownEvent.aircraftDef == aircraftDef)
|
||||
Log.Message($"Faction: {faction?.Name ?? "Unknown"}");
|
||||
var factionData = allFactionAircraftData.Where(x => x.faction == faction);
|
||||
foreach (var data in factionData)
|
||||
{
|
||||
totalCooldown += cooldownEvent.aircraftCount;
|
||||
Log.Message($" {data.aircraftDef.LabelCap}: {data.availableCount}/{data.totalCount} available");
|
||||
}
|
||||
}
|
||||
return totalCooldown;
|
||||
|
||||
Log.Message($"Active cooldown events: {cooldownEvents.Count}");
|
||||
Log.Message("===============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
|
||||
Log.Message($"FlyOver Escort initialized: {Props.spawnIntervalTicks} ticks interval, max {Props.maxEscorts} escorts");
|
||||
Log.Message($"Safe distances - From Main: {Props.minSafeDistanceFromMain}, Between Escorts: {Props.minSafeDistanceBetweenEscorts}");
|
||||
}
|
||||
|
||||
public override void CompTick()
|
||||
@@ -97,8 +98,10 @@ namespace ArachnaeSwarm
|
||||
private void SpawnEscorts(FlyOver mainFlyOver)
|
||||
{
|
||||
int escortsToSpawn = Mathf.Min(Props.spawnCount, Props.maxEscorts - activeEscorts.Count);
|
||||
int successfulSpawns = 0;
|
||||
int maxAttempts = escortsToSpawn * 5; // 最多尝试5倍的数量
|
||||
|
||||
for (int i = 0; i < escortsToSpawn; i++)
|
||||
for (int attempt = 0; attempt < maxAttempts && successfulSpawns < escortsToSpawn; attempt++)
|
||||
{
|
||||
// 先生成视觉数据
|
||||
EscortVisualData visualData = GenerateEscortVisualData();
|
||||
@@ -106,12 +109,68 @@ namespace ArachnaeSwarm
|
||||
FlyOver escort = CreateEscort(mainFlyOver, visualData);
|
||||
if (escort != null)
|
||||
{
|
||||
activeEscorts.Add(escort);
|
||||
escortVisualData[escort] = visualData;
|
||||
|
||||
Log.Message($"Spawned escort #{i+1} for FlyOver at {mainFlyOver.DrawPos}, scale: {visualData.scale:F2}, maskAlpha: {visualData.heightMaskAlpha:F2}");
|
||||
// 检查安全距离
|
||||
if (IsSafeDistance(escort, mainFlyOver))
|
||||
{
|
||||
activeEscorts.Add(escort);
|
||||
escortVisualData[escort] = visualData;
|
||||
successfulSpawns++;
|
||||
|
||||
Log.Message($"Spawned escort #{successfulSpawns} for FlyOver at {mainFlyOver.DrawPos}, scale: {visualData.scale:F2}, maskAlpha: {visualData.heightMaskAlpha:F2}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不安全,销毁这个伴飞
|
||||
escort.Destroy();
|
||||
Log.Message($"Escort spawn attempt {attempt + 1}: Position too close to existing escort, trying again");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果已经生成足够数量,提前退出
|
||||
if (successfulSpawns >= escortsToSpawn)
|
||||
break;
|
||||
}
|
||||
|
||||
if (successfulSpawns < escortsToSpawn)
|
||||
{
|
||||
Log.Message($"Spawned {successfulSpawns}/{escortsToSpawn} escorts (some positions were too close to existing escorts)");
|
||||
}
|
||||
}
|
||||
|
||||
// 修改:分别检查与主飞行物和伴飞物的安全距离
|
||||
private bool IsSafeDistance(FlyOver newEscort, FlyOver mainFlyOver)
|
||||
{
|
||||
Vector3 newPos = newEscort.DrawPos;
|
||||
|
||||
// 检查与主FlyOver的距离
|
||||
if (Props.minSafeDistanceFromMain > 0)
|
||||
{
|
||||
float distToMain = Vector3.Distance(newPos, mainFlyOver.DrawPos);
|
||||
if (distToMain < Props.minSafeDistanceFromMain)
|
||||
{
|
||||
Log.Message($"Escort too close to main FlyOver: {distToMain:F1} < {Props.minSafeDistanceFromMain}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查与其他伴飞的距离
|
||||
if (Props.minSafeDistanceBetweenEscorts > 0)
|
||||
{
|
||||
foreach (FlyOver existingEscort in activeEscorts)
|
||||
{
|
||||
if (existingEscort == null || existingEscort.Destroyed)
|
||||
continue;
|
||||
|
||||
float distToEscort = Vector3.Distance(newPos, existingEscort.DrawPos);
|
||||
if (distToEscort < Props.minSafeDistanceBetweenEscorts)
|
||||
{
|
||||
Log.Message($"Escort too close to existing escort: {distToEscort:F1} < {Props.minSafeDistanceBetweenEscorts}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private EscortVisualData GenerateEscortVisualData()
|
||||
@@ -131,7 +190,6 @@ namespace ArachnaeSwarm
|
||||
return data;
|
||||
}
|
||||
|
||||
// 修改:添加 visualData 参数
|
||||
private FlyOver CreateEscort(FlyOver mainFlyOver, EscortVisualData visualData)
|
||||
{
|
||||
try
|
||||
@@ -275,7 +333,6 @@ namespace ArachnaeSwarm
|
||||
);
|
||||
}
|
||||
|
||||
// 修改:添加 visualData 参数
|
||||
private void SetupEscortProperties(FlyOver escort, FlyOver mainFlyOver, EscortVisualData visualData)
|
||||
{
|
||||
// 设置伴飞缩放 - 现在直接从参数获取
|
||||
|
||||
@@ -22,6 +22,10 @@ namespace ArachnaeSwarm
|
||||
public float verticalOffset = 2f; // 垂直偏移量(高度差)
|
||||
public bool useRandomOffset = true; // 是否使用随机偏移
|
||||
|
||||
// 修改:独立的安全距离配置
|
||||
public float minSafeDistanceFromMain = 8f; // 与主飞行物的最小安全距离(单元格)
|
||||
public float minSafeDistanceBetweenEscorts = 3f; // 伴飞物之间的最小安全距离(单元格)
|
||||
|
||||
// 飞行配置
|
||||
public float escortSpeedMultiplier = 1f; // 速度乘数(相对于主FlyOver)
|
||||
public float escortAltitudeOffset = 0f; // 高度偏移
|
||||
|
||||
@@ -36,6 +36,10 @@ namespace ArachnaeSwarm
|
||||
endPos = CalculateEndPosition(target, startPos);
|
||||
}
|
||||
|
||||
// 确保位置安全
|
||||
startPos = GetSafeMapPosition(startPos, parent.pawn.Map);
|
||||
endPos = GetSafeMapPosition(endPos, parent.pawn.Map);
|
||||
|
||||
Log.Message($"Final positions - Start: {startPos}, End: {endPos}");
|
||||
|
||||
// 验证位置是否有效
|
||||
@@ -57,10 +61,7 @@ namespace ArachnaeSwarm
|
||||
Log.Warning($"FlyOver start and end positions are the same: {startPos}. Adjusting end position.");
|
||||
IntVec3 randomOffset = new IntVec3(Rand.Range(-10, 11), 0, Rand.Range(-10, 11));
|
||||
endPos += randomOffset;
|
||||
if (!endPos.InBounds(parent.pawn.Map))
|
||||
{
|
||||
endPos = parent.pawn.Map.Center;
|
||||
}
|
||||
endPos = GetSafeMapPosition(endPos, parent.pawn.Map);
|
||||
}
|
||||
|
||||
// 根据类型创建不同的飞越物体
|
||||
@@ -71,15 +72,12 @@ namespace ArachnaeSwarm
|
||||
CreateStandardFlyOver(startPos, endPos);
|
||||
break;
|
||||
case FlyOverType.GroundStrafing:
|
||||
CreateGroundStrafingFlyOver(startPos, endPos);
|
||||
CreateGroundStrafingFlyOver(startPos, endPos, target.Cell);
|
||||
break;
|
||||
case FlyOverType.SectorSurveillance:
|
||||
CreateSectorSurveillanceFlyOver(startPos, endPos);
|
||||
break;
|
||||
}
|
||||
|
||||
// 显示效果消息
|
||||
ShowEffectMessage();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
@@ -87,39 +85,88 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:在目标选择时显示预览
|
||||
// 修复的预览绘制方法
|
||||
public override void DrawEffectPreview(LocalTargetInfo target)
|
||||
{
|
||||
base.DrawEffectPreview(target);
|
||||
|
||||
if (parent.pawn != null && parent.pawn.Map != null)
|
||||
{
|
||||
// 计算飞行路径
|
||||
IntVec3 startPos, endPos;
|
||||
if (Props.approachType == ApproachType.Perpendicular)
|
||||
Map map = parent.pawn.Map;
|
||||
|
||||
try
|
||||
{
|
||||
CalculatePerpendicularPath(target, out startPos, out endPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
startPos = CalculateStartPosition(target);
|
||||
endPos = CalculateEndPosition(target, startPos);
|
||||
}
|
||||
// 计算飞行路径
|
||||
IntVec3 startPos, endPos;
|
||||
if (Props.approachType == ApproachType.Perpendicular)
|
||||
{
|
||||
CalculatePerpendicularPath(target, out startPos, out endPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
startPos = CalculateStartPosition(target);
|
||||
endPos = CalculateEndPosition(target, startPos);
|
||||
}
|
||||
|
||||
// 根据不同类型显示不同的预览
|
||||
if (Props.enableGroundStrafing && Props.showStrafePreview)
|
||||
{
|
||||
DrawStrafingAreaPreview(startPos, endPos);
|
||||
// 确保位置在地图范围内
|
||||
startPos = GetSafeMapPosition(startPos, map);
|
||||
endPos = GetSafeMapPosition(endPos, map);
|
||||
|
||||
// 检查预览稳定性
|
||||
if (!IsPreviewStable(startPos, endPos, map))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据不同类型显示不同的预览
|
||||
if (Props.enableGroundStrafing && Props.showStrafePreview)
|
||||
{
|
||||
DrawStrafingAreaPreview(startPos, endPos, target.Cell);
|
||||
}
|
||||
else if (Props.enableSectorSurveillance && Props.showSectorPreview)
|
||||
{
|
||||
DrawSectorAreaPreview(startPos, endPos);
|
||||
}
|
||||
}
|
||||
else if (Props.enableSectorSurveillance && Props.showSectorPreview)
|
||||
catch (System.Exception)
|
||||
{
|
||||
DrawSectorAreaPreview(startPos, endPos);
|
||||
// 忽略预览绘制中的错误,避免影响游戏体验
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制地面扫射预览
|
||||
private void DrawStrafingAreaPreview(IntVec3 startPos, IntVec3 endPos)
|
||||
// 安全的位置计算方法
|
||||
private IntVec3 GetSafeMapPosition(IntVec3 pos, Map map)
|
||||
{
|
||||
if (map == null) return pos;
|
||||
|
||||
// 确保位置在地图范围内
|
||||
pos.x = Mathf.Clamp(pos.x, 0, map.Size.x - 1);
|
||||
pos.z = Mathf.Clamp(pos.z, 0, map.Size.z - 1);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// 预览绘制稳定性检查
|
||||
private bool IsPreviewStable(IntVec3 startPos, IntVec3 endPos, Map map)
|
||||
{
|
||||
if (map == null) return false;
|
||||
|
||||
// 检查位置是否有效
|
||||
if (!startPos.IsValid || !endPos.IsValid) return false;
|
||||
|
||||
// 检查位置是否在地图范围内
|
||||
if (!startPos.InBounds(map) || !endPos.InBounds(map)) return false;
|
||||
|
||||
// 检查距离是否合理(避免过短的路径)
|
||||
float distance = Vector3.Distance(startPos.ToVector3(), endPos.ToVector3());
|
||||
if (distance < 5f) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 修复:绘制地面扫射预览,现在接受目标单元格参数
|
||||
private void DrawStrafingAreaPreview(IntVec3 startPos, IntVec3 endPos, IntVec3 targetCell)
|
||||
{
|
||||
Map map = parent.pawn.Map;
|
||||
|
||||
@@ -131,7 +178,7 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
|
||||
// 只计算扫射影响区域的单元格
|
||||
List<IntVec3> strafeImpactCells = CalculateStrafingImpactCells(startPos, endPos, flightDirection);
|
||||
List<IntVec3> strafeImpactCells = CalculateStrafingImpactCells(targetCell, flightDirection);
|
||||
|
||||
// 绘制扫射影响区域的预览单元格
|
||||
foreach (IntVec3 cell in strafeImpactCells)
|
||||
@@ -146,11 +193,11 @@ namespace ArachnaeSwarm
|
||||
GenDraw.DrawLineBetween(startPos.ToVector3Shifted(), endPos.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
|
||||
// 绘制扫射范围边界
|
||||
DrawStrafingBoundaries(startPos, endPos, flightDirection);
|
||||
DrawStrafingBoundaries(targetCell, flightDirection);
|
||||
}
|
||||
|
||||
// 计算扫射影响区域的单元格
|
||||
private List<IntVec3> CalculateStrafingImpactCells(IntVec3 startPos, IntVec3 endPos, Vector3 flightDirection)
|
||||
// 修复:计算扫射影响区域的单元格,现在以目标单元格为中心
|
||||
private List<IntVec3> CalculateStrafingImpactCells(IntVec3 targetCell, Vector3 flightDirection)
|
||||
{
|
||||
List<IntVec3> cells = new List<IntVec3>();
|
||||
Map map = parent.pawn.Map;
|
||||
@@ -158,19 +205,16 @@ namespace ArachnaeSwarm
|
||||
// 计算垂直于飞行方向的方向
|
||||
Vector3 perpendicular = new Vector3(-flightDirection.z, 0f, flightDirection.x).normalized;
|
||||
|
||||
// 计算飞行路径的总长度
|
||||
float totalPathLength = startPos.DistanceTo(endPos);
|
||||
// 修复:以目标单元格为中心计算扫射区域
|
||||
Vector3 targetCenter = targetCell.ToVector3();
|
||||
|
||||
// 计算扫射区域的中心点(目标位置附近)
|
||||
Vector3 targetCenter = Vector3.Lerp(startPos.ToVector3(), endPos.ToVector3(), 0.5f);
|
||||
|
||||
// 计算扫射区域的起始和结束位置(基于扫射长度)
|
||||
// 计算扫射区域的起始和结束位置(基于扫射长度,以目标为中心)
|
||||
float strafeHalfLength = Props.strafeLength * 0.5f;
|
||||
Vector3 strafeStart = targetCenter - flightDirection * strafeHalfLength;
|
||||
Vector3 strafeEnd = targetCenter + flightDirection * strafeHalfLength;
|
||||
|
||||
// 沿着扫射区域计算单元格
|
||||
int steps = Mathf.CeilToInt(Props.strafeLength / 1f);
|
||||
// 使用整数步进避免浮点精度问题
|
||||
int steps = Mathf.Max(1, Mathf.CeilToInt(Props.strafeLength));
|
||||
for (int i = 0; i <= steps; i++)
|
||||
{
|
||||
float progress = (float)i / steps;
|
||||
@@ -181,7 +225,13 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
Vector3 offset = perpendicular * w;
|
||||
Vector3 cellPos = centerPoint + offset;
|
||||
IntVec3 cell = new IntVec3((int)cellPos.x, (int)cellPos.y, (int)cellPos.z);
|
||||
|
||||
// 使用更精确的单元格转换
|
||||
IntVec3 cell = new IntVec3(
|
||||
Mathf.RoundToInt(cellPos.x),
|
||||
Mathf.RoundToInt(cellPos.y),
|
||||
Mathf.RoundToInt(cellPos.z)
|
||||
);
|
||||
|
||||
if (cell.InBounds(map) && !cells.Contains(cell))
|
||||
{
|
||||
@@ -190,18 +240,18 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
Log.Message($"Strafing Area: Calculated {cells.Count} impact cells ({Props.strafeWidth * 2 + 1}x{Props.strafeLength})");
|
||||
Log.Message($"Strafing Area: Calculated {cells.Count} impact cells centered at {targetCell}");
|
||||
return cells;
|
||||
}
|
||||
|
||||
// 绘制扫射范围边界
|
||||
private void DrawStrafingBoundaries(IntVec3 startPos, IntVec3 endPos, Vector3 flightDirection)
|
||||
// 修复:绘制扫射范围边界,现在以目标单元格为中心
|
||||
private void DrawStrafingBoundaries(IntVec3 targetCell, Vector3 flightDirection)
|
||||
{
|
||||
Map map = parent.pawn.Map;
|
||||
Vector3 perpendicular = new Vector3(-flightDirection.z, 0f, flightDirection.x).normalized;
|
||||
|
||||
// 计算扫射区域的中心点
|
||||
Vector3 targetCenter = Vector3.Lerp(startPos.ToVector3(), endPos.ToVector3(), 0.5f);
|
||||
// 修复:以目标单元格为中心
|
||||
Vector3 targetCenter = targetCell.ToVector3();
|
||||
|
||||
// 计算扫射区域的起始和结束位置
|
||||
float strafeHalfLength = Props.strafeLength * 0.5f;
|
||||
@@ -214,20 +264,27 @@ namespace ArachnaeSwarm
|
||||
Vector3 endLeft = strafeEnd + perpendicular * Props.strafeWidth;
|
||||
Vector3 endRight = strafeEnd - perpendicular * Props.strafeWidth;
|
||||
|
||||
// 转换为 IntVec3
|
||||
IntVec3 startLeftCell = new IntVec3((int)startLeft.x, (int)startLeft.y, (int)startLeft.z);
|
||||
IntVec3 startRightCell = new IntVec3((int)startRight.x, (int)startRight.y, (int)startRight.z);
|
||||
IntVec3 endLeftCell = new IntVec3((int)endLeft.x, (int)endLeft.y, (int)endLeft.z);
|
||||
IntVec3 endRightCell = new IntVec3((int)endRight.x, (int)endRight.y, (int)endRight.z);
|
||||
// 转换为 IntVec3 并确保在地图范围内
|
||||
IntVec3 startLeftCell = GetSafeMapPosition(new IntVec3((int)startLeft.x, (int)startLeft.y, (int)startLeft.z), map);
|
||||
IntVec3 startRightCell = GetSafeMapPosition(new IntVec3((int)startRight.x, (int)startRight.y, (int)startRight.z), map);
|
||||
IntVec3 endLeftCell = GetSafeMapPosition(new IntVec3((int)endLeft.x, (int)endLeft.y, (int)endLeft.z), map);
|
||||
IntVec3 endRightCell = GetSafeMapPosition(new IntVec3((int)endRight.x, (int)endRight.y, (int)endRight.z), map);
|
||||
|
||||
// 绘制边界线
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), endLeftCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
GenDraw.DrawLineBetween(startRightCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), startRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
GenDraw.DrawLineBetween(endLeftCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
// 绘制边界线 - 只绘制在地图范围内的线段
|
||||
if (startLeftCell.InBounds(map) && endLeftCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), endLeftCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
|
||||
if (startRightCell.InBounds(map) && endRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startRightCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
|
||||
if (startLeftCell.InBounds(map) && startRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), startRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
|
||||
if (endLeftCell.InBounds(map) && endRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(endLeftCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Red, 0.2f);
|
||||
}
|
||||
|
||||
// 新增:绘制扇形区域预览 - 使用strafeWidth来近似扇形扫过的区域宽度
|
||||
// 绘制扇形区域预览
|
||||
private void DrawSectorAreaPreview(IntVec3 startPos, IntVec3 endPos)
|
||||
{
|
||||
Map map = parent.pawn.Map;
|
||||
@@ -268,10 +325,10 @@ namespace ArachnaeSwarm
|
||||
Map map = parent.pawn.Map;
|
||||
|
||||
// 计算飞行路径的总长度
|
||||
float totalPathLength = startPos.DistanceTo(endPos);
|
||||
float totalPathLength = Vector3.Distance(startPos.ToVector3(), endPos.ToVector3());
|
||||
|
||||
// 沿着飞行路径计算预览单元格
|
||||
int steps = Mathf.CeilToInt(totalPathLength / 1f);
|
||||
int steps = Mathf.Max(1, Mathf.CeilToInt(totalPathLength));
|
||||
for (int i = 0; i <= steps; i++)
|
||||
{
|
||||
float progress = (float)i / steps;
|
||||
@@ -282,7 +339,13 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
Vector3 offset = perpendicular * w;
|
||||
Vector3 cellPos = centerPoint + offset;
|
||||
IntVec3 cell = new IntVec3((int)cellPos.x, (int)cellPos.y, (int)cellPos.z);
|
||||
|
||||
// 使用精确的单元格转换
|
||||
IntVec3 cell = new IntVec3(
|
||||
Mathf.RoundToInt(cellPos.x),
|
||||
Mathf.RoundToInt(cellPos.y),
|
||||
Mathf.RoundToInt(cellPos.z)
|
||||
);
|
||||
|
||||
if (cell.InBounds(map) && !cells.Contains(cell))
|
||||
{
|
||||
@@ -305,17 +368,24 @@ namespace ArachnaeSwarm
|
||||
Vector3 endLeft = endPos.ToVector3() + perpendicular * Props.strafeWidth;
|
||||
Vector3 endRight = endPos.ToVector3() - perpendicular * Props.strafeWidth;
|
||||
|
||||
// 转换为 IntVec3
|
||||
IntVec3 startLeftCell = new IntVec3((int)startLeft.x, (int)startLeft.y, (int)startLeft.z);
|
||||
IntVec3 startRightCell = new IntVec3((int)startRight.x, (int)startRight.y, (int)startRight.z);
|
||||
IntVec3 endLeftCell = new IntVec3((int)endLeft.x, (int)endLeft.y, (int)endLeft.z);
|
||||
IntVec3 endRightCell = new IntVec3((int)endRight.x, (int)endRight.y, (int)endRight.z);
|
||||
// 转换为 IntVec3 并确保在地图范围内
|
||||
IntVec3 startLeftCell = GetSafeMapPosition(new IntVec3((int)startLeft.x, (int)startLeft.y, (int)startLeft.z), map);
|
||||
IntVec3 startRightCell = GetSafeMapPosition(new IntVec3((int)startRight.x, (int)startRight.y, (int)startRight.z), map);
|
||||
IntVec3 endLeftCell = GetSafeMapPosition(new IntVec3((int)endLeft.x, (int)endLeft.y, (int)endLeft.z), map);
|
||||
IntVec3 endRightCell = GetSafeMapPosition(new IntVec3((int)endRight.x, (int)endRight.y, (int)endRight.z), map);
|
||||
|
||||
// 绘制边界线
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), endLeftCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
GenDraw.DrawLineBetween(startRightCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), startRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
GenDraw.DrawLineBetween(endLeftCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
// 绘制边界线 - 只绘制在地图范围内的线段
|
||||
if (startLeftCell.InBounds(map) && endLeftCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), endLeftCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
|
||||
if (startRightCell.InBounds(map) && endRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startRightCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
|
||||
if (startLeftCell.InBounds(map) && startRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(startLeftCell.ToVector3Shifted(), startRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
|
||||
if (endLeftCell.InBounds(map) && endRightCell.InBounds(map))
|
||||
GenDraw.DrawLineBetween(endLeftCell.ToVector3Shifted(), endRightCell.ToVector3Shifted(), SimpleColor.Blue, 0.2f);
|
||||
}
|
||||
|
||||
// 预处理扫射目标单元格
|
||||
@@ -335,8 +405,8 @@ namespace ArachnaeSwarm
|
||||
return confirmedTargets;
|
||||
}
|
||||
|
||||
// 创建地面扫射飞越
|
||||
private void CreateGroundStrafingFlyOver(IntVec3 startPos, IntVec3 endPos)
|
||||
// 修复:创建地面扫射飞越,现在接受目标单元格参数
|
||||
private void CreateGroundStrafingFlyOver(IntVec3 startPos, IntVec3 endPos, IntVec3 targetCell)
|
||||
{
|
||||
ThingDef flyOverDef = Props.flyOverDef ?? DefDatabase<ThingDef>.GetNamedSilentFail("ARA_HiveCorvette");
|
||||
if (flyOverDef == null)
|
||||
@@ -363,9 +433,9 @@ namespace ArachnaeSwarm
|
||||
CompGroundStrafing strafingComp = flyOver.GetComp<CompGroundStrafing>();
|
||||
if (strafingComp != null)
|
||||
{
|
||||
// 计算扫射区域的所有单元格
|
||||
// 修复:计算扫射区域的所有单元格,以目标单元格为中心
|
||||
Vector3 flightDirection = (endPos.ToVector3() - startPos.ToVector3()).normalized;
|
||||
List<IntVec3> potentialTargetCells = CalculateStrafingImpactCells(startPos, endPos, flightDirection);
|
||||
List<IntVec3> potentialTargetCells = CalculateStrafingImpactCells(targetCell, flightDirection);
|
||||
|
||||
if (potentialTargetCells.Count > 0)
|
||||
{
|
||||
@@ -395,7 +465,7 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
|
||||
// 新增:创建扇形监视飞越
|
||||
// 创建扇形监视飞越
|
||||
private void CreateSectorSurveillanceFlyOver(IntVec3 startPos, IntVec3 endPos)
|
||||
{
|
||||
ThingDef flyOverDef = Props.flyOverDef ?? DefDatabase<ThingDef>.GetNamedSilentFail("ARA_HiveCorvette");
|
||||
@@ -420,9 +490,6 @@ namespace ArachnaeSwarm
|
||||
flyOver.playFlyOverSound = Props.playFlyOverSound;
|
||||
|
||||
Log.Message($"SectorSurveillance FlyOver created: {flyOver} from {startPos} to {endPos}");
|
||||
|
||||
// 注意:扇形监视的具体参数(角度、射程、发射次数等)在FlyOver的CompProperties_SectorSurveillance中定义
|
||||
// 这里只负责创建FlyOver,不传递具体参数
|
||||
}
|
||||
|
||||
// 计算垂直线进场路径
|
||||
@@ -471,27 +538,107 @@ namespace ArachnaeSwarm
|
||||
// 在指定方向上找到地图边缘
|
||||
private IntVec3 FindMapEdgeInDirection(Map map, IntVec3 fromPos, Vector3 direction)
|
||||
{
|
||||
// 计算最大搜索距离(地图对角线的一半)
|
||||
float maxDistance = Mathf.Sqrt(map.Size.x * map.Size.x + map.Size.z * map.Size.z) * 0.6f;
|
||||
|
||||
// 沿着方向逐步搜索,直到找到地图边界
|
||||
for (float distance = 10f; distance <= maxDistance; distance += 5f)
|
||||
// 确保方向向量有效
|
||||
if (direction == Vector3.zero)
|
||||
{
|
||||
IntVec3 testPos = fromPos + new IntVec3(
|
||||
Mathf.RoundToInt(direction.x * distance),
|
||||
0,
|
||||
Mathf.RoundToInt(direction.z * distance));
|
||||
direction = new Vector3(Rand.Range(-1f, 1f), 0, Rand.Range(-1f, 1f)).normalized;
|
||||
}
|
||||
|
||||
// 使用更精确的地图边界计算
|
||||
IntVec3 mapCenter = map.Center;
|
||||
IntVec3 mapSize = new IntVec3(map.Size.x, 0, map.Size.z);
|
||||
|
||||
// 计算与地图边界的交点
|
||||
Vector3 fromVec = fromPos.ToVector3();
|
||||
Vector3 dirNormalized = direction.normalized;
|
||||
|
||||
// 计算到各个边界的距离
|
||||
float tMin = float.MaxValue;
|
||||
IntVec3? bestEdgePos = null;
|
||||
|
||||
// 检查四个边界
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
float t = 0f;
|
||||
IntVec3 edgePos = IntVec3.Invalid;
|
||||
|
||||
if (!testPos.InBounds(map))
|
||||
switch (i)
|
||||
{
|
||||
// 找到边界,返回最近的有效位置
|
||||
IntVec3 edgePos = FindClosestValidPosition(testPos, map);
|
||||
Log.Message($"Found map edge at {edgePos} (direction: {direction}, distance: {distance})");
|
||||
return edgePos;
|
||||
case 0: // 左边界 (x = 0)
|
||||
if (Mathf.Abs(dirNormalized.x) > 0.001f)
|
||||
{
|
||||
t = (0 - fromVec.x) / dirNormalized.x;
|
||||
if (t > 0)
|
||||
{
|
||||
float z = fromVec.z + dirNormalized.z * t;
|
||||
if (z >= 0 && z < map.Size.z)
|
||||
{
|
||||
edgePos = new IntVec3(0, 0, Mathf.RoundToInt(z));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 右边界 (x = map.Size.x - 1)
|
||||
if (Mathf.Abs(dirNormalized.x) > 0.001f)
|
||||
{
|
||||
t = (map.Size.x - 1 - fromVec.x) / dirNormalized.x;
|
||||
if (t > 0)
|
||||
{
|
||||
float z = fromVec.z + dirNormalized.z * t;
|
||||
if (z >= 0 && z < map.Size.z)
|
||||
{
|
||||
edgePos = new IntVec3(map.Size.x - 1, 0, Mathf.RoundToInt(z));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 下边界 (z = 0)
|
||||
if (Mathf.Abs(dirNormalized.z) > 0.001f)
|
||||
{
|
||||
t = (0 - fromVec.z) / dirNormalized.z;
|
||||
if (t > 0)
|
||||
{
|
||||
float x = fromVec.x + dirNormalized.x * t;
|
||||
if (x >= 0 && x < map.Size.x)
|
||||
{
|
||||
edgePos = new IntVec3(Mathf.RoundToInt(x), 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // 上边界 (z = map.Size.z - 1)
|
||||
if (Mathf.Abs(dirNormalized.z) > 0.001f)
|
||||
{
|
||||
t = (map.Size.z - 1 - fromVec.z) / dirNormalized.z;
|
||||
if (t > 0)
|
||||
{
|
||||
float x = fromVec.x + dirNormalized.x * t;
|
||||
if (x >= 0 && x < map.Size.x)
|
||||
{
|
||||
edgePos = new IntVec3(Mathf.RoundToInt(x), 0, map.Size.z - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到最近的有效边界点
|
||||
if (edgePos.IsValid && edgePos.InBounds(map) && t > 0 && t < tMin)
|
||||
{
|
||||
tMin = t;
|
||||
bestEdgePos = edgePos;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没找到边界,使用随机边缘位置
|
||||
if (bestEdgePos.HasValue)
|
||||
{
|
||||
return bestEdgePos.Value;
|
||||
}
|
||||
|
||||
// 如果没找到合适的边界点,使用随机边缘位置
|
||||
Log.Warning($"Could not find map edge in direction {direction}, using random edge");
|
||||
return GetRandomMapEdgePosition(map);
|
||||
}
|
||||
@@ -510,7 +657,7 @@ namespace ArachnaeSwarm
|
||||
return GetMapEdgePosition(map, GetDirectionFromCasterToTarget(target));
|
||||
|
||||
case StartPosition.CustomOffset:
|
||||
return parent.pawn.Position + Props.customStartOffset;
|
||||
return GetSafeMapPosition(parent.pawn.Position + Props.customStartOffset, map);
|
||||
|
||||
case StartPosition.RandomMapEdge:
|
||||
return GetRandomMapEdgePosition(map);
|
||||
@@ -536,7 +683,7 @@ namespace ArachnaeSwarm
|
||||
break;
|
||||
|
||||
case EndPosition.CustomOffset:
|
||||
endPos = target.Cell + Props.customEndOffset;
|
||||
endPos = GetSafeMapPosition(target.Cell + Props.customEndOffset, map);
|
||||
break;
|
||||
|
||||
case EndPosition.FixedDistance:
|
||||
@@ -553,10 +700,10 @@ namespace ArachnaeSwarm
|
||||
break;
|
||||
}
|
||||
|
||||
return endPos;
|
||||
return GetSafeMapPosition(endPos, map);
|
||||
}
|
||||
|
||||
// 原有的辅助方法保持不变
|
||||
// 原有的辅助方法
|
||||
private IntVec3 GetOppositeMapEdgeThroughCenter(Map map, IntVec3 startPos)
|
||||
{
|
||||
IntVec3 center = map.Center;
|
||||
@@ -731,34 +878,6 @@ namespace ArachnaeSwarm
|
||||
Log.Message($"Standard FlyOver created: {flyOver} from {startPos} to {endPos}");
|
||||
}
|
||||
|
||||
private void ShowEffectMessage()
|
||||
{
|
||||
string message = GetFlyOverMessage();
|
||||
Messages.Message(message, parent.pawn, MessageTypeDefOf.NeutralEvent);
|
||||
}
|
||||
|
||||
private string GetFlyOverMessage()
|
||||
{
|
||||
switch (Props.flyOverType)
|
||||
{
|
||||
case FlyOverType.HighAltitude:
|
||||
return "HighAltitudeReconArrival".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.CargoDrop:
|
||||
return "CargoDropIncoming".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.BombingRun:
|
||||
return "BombingRunInitiated".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.Reconnaissance:
|
||||
return "ReconnaissanceFlyOver".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.GroundStrafing:
|
||||
return "GroundStrafingIncoming".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.SectorSurveillance:
|
||||
return "SectorSurveillanceActive".Translate(parent.pawn.LabelShort);
|
||||
case FlyOverType.Standard:
|
||||
default:
|
||||
return "FlyOverInitiated".Translate(parent.pawn.LabelShort);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新技能提示信息
|
||||
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
|
||||
{
|
||||
|
||||
@@ -575,7 +575,7 @@ namespace ArachnaeSwarm
|
||||
public float minShadowScale = 0.5f;
|
||||
public float maxShadowScale = 1.0f;
|
||||
public float defaultFadeInDuration = 1.5f;
|
||||
public float defaultFadeOutDuration = 1.5f;
|
||||
public float defaultFadeOutDuration = 0.5f;
|
||||
public float fadeOutStartProgress = 0.98f;
|
||||
|
||||
// 动态淡出配置
|
||||
|
||||
Reference in New Issue
Block a user