diff --git a/1.6/Assemblies/FCP_Enlist.dll b/1.6/Assemblies/FCP_Enlist.dll
index 0338185..df1ea99 100644
Binary files a/1.6/Assemblies/FCP_Enlist.dll and b/1.6/Assemblies/FCP_Enlist.dll differ
diff --git a/Common/Languages/English/Keyed/FCPToolsKeyed.xml b/Common/Languages/English/Keyed/FCPToolsKeyed.xml
index 40716f0..99b8881 100644
--- a/Common/Languages/English/Keyed/FCPToolsKeyed.xml
+++ b/Common/Languages/English/Keyed/FCPToolsKeyed.xml
@@ -29,4 +29,8 @@
Requires xenotype: {0}
Requires apparel: {0}
+
+ New Enemy
+ By enlisting with {ENLISTED_name}, you have become an enemy of {HOSTILE_name}. They are now hostile toward your colony.
+
\ No newline at end of file
diff --git a/Source/Enlist/Enlist.csproj b/Source/Enlist/Enlist.csproj
index 68e9fc3..2a1ad50 100644
--- a/Source/Enlist/Enlist.csproj
+++ b/Source/Enlist/Enlist.csproj
@@ -36,4 +36,11 @@
+
+
+ ..\..\1.6\Assemblies\FCP_Core.dll
+ False
+
+
+
\ No newline at end of file
diff --git a/Source/Enlist/FactionEnlistWorker.cs b/Source/Enlist/FactionEnlistWorker.cs
index a8ec431..809a51e 100644
--- a/Source/Enlist/FactionEnlistWorker.cs
+++ b/Source/Enlist/FactionEnlistWorker.cs
@@ -54,6 +54,27 @@ public class FactionEnlistWorker
factionOptions.factionsStorages[def] = factionStorage;
}
def.enlistedSoundDef?.PlayOneShotOnCamera();
+
+ Faction player = Faction.OfPlayer;
+ foreach (Faction faction in Find.FactionManager.AllFactionsListForReading)
+ {
+ if (faction == toEnlist || faction == player || faction.defeated || faction.IsPlayer) continue;
+
+ FactionRelation rel = toEnlist.RelationWith(faction, false);
+ if (rel == null || rel.kind != FactionRelationKind.Hostile) continue;
+ if (faction.HostileTo(player)) continue;
+
+ int goodwill = faction.GoodwillWith(player);
+ if (goodwill > -75)
+ {
+ faction.TryAffectGoodwillWith(player, -75 - goodwill, false, true);
+ }
+
+ Find.LetterStack.ReceiveLetter(
+ "FCP_Enemy_Of_Enlist_Faction".Translate(),
+ "FCP_Enemy_Of_Enlist_Faction_Desc".Translate(toEnlist.Named("ENLISTED"), faction.Named("HOSTILE")),
+ LetterDefOf.NegativeEvent);
+ }
}
diff --git a/Source/Enlist/WorldObjectCompEnlist.cs b/Source/Enlist/WorldObjectCompEnlist.cs
index 84df4e7..df6debd 100644
--- a/Source/Enlist/WorldObjectCompEnlist.cs
+++ b/Source/Enlist/WorldObjectCompEnlist.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
+using FCP.Core.Shuttles;
namespace FCP.Enlist;
@@ -493,7 +494,7 @@ public class WorldObjectCompEnlist : WorldObjectComp
{
defaultLabel = optionDef.shuttleServiceLabelKey.Translate(faction.Named("FACTION")),
defaultDesc = optionDef.shuttleServiceDescKey.Translate(faction.Named("FACTION")),
- icon = ContentFinder.Get(optionDef.shuttleServiceButtonIconTexPath),
+ icon = ContentFinder.Get(optionDef.shuttleServiceButtonIconTexPath, reportFailure: false) ?? BaseContent.BadTex,
action = delegate
{
StartChoosingShuttleDestination(caravan, optionDef);
@@ -692,7 +693,7 @@ public class WorldObjectCompEnlist : WorldObjectComp
Messages.Message("TransportPodDestinationBeyondMaximumRange".Translate(), MessageTypeDefOf.RejectInput, historical: false);
return false;
}
- IEnumerable source = GetTransportPodsFloatMenuOptionsAt(target.Tile, caravan);
+ IEnumerable source = GetTransportPodsFloatMenuOptionsAt(target.Tile, caravan, launchAction);
if (!source.Any())
{
if (Find.World.Impassable(target.Tile))
@@ -783,92 +784,63 @@ public class WorldObjectCompEnlist : WorldObjectComp
}
ExtractMoneyFromCaravan(caravan, curFactionEnlistOptionsDef.shuttleServiceCost, curFactionEnlistOptionsDef);
- // Try to get custom shuttle from faction using reflection
- TransportShipDef transportShipDef = null;
-
- if (parent.Faction?.def?.modExtensions != null)
+ // Get custom shuttle from faction extension - direct type access (no reflection)
+ FactionModExtension factionExtension = parent.Faction?.def?.GetModExtension();
+ TransportShipDef transportShipDef = factionExtension?.transportShipDef;
+
+ if (transportShipDef != null && transportShipDef.worldObject != null)
{
- foreach (var extension in parent.Faction.def.modExtensions)
+ // Create the shuttle thing - it's a Building with CompTransporter, not an ActiveTransporter
+ Thing shuttleThing = ThingMaker.MakeThing(transportShipDef.shipThing);
+ CompTransporter compTransporter = shuttleThing.TryGetComp();
+
+ if (compTransporter == null)
{
- if (extension.GetType().Name == "FactionModExtension")
- {
- var transportShipDefField = extension.GetType().GetField("transportShipDef");
- if (transportShipDefField != null)
- {
- transportShipDef = transportShipDefField.GetValue(extension) as TransportShipDef;
- break;
- }
- }
+ Log.Error($"[FCP Enlist] Shuttle thing {shuttleThing.def.defName} has no CompTransporter!");
+ TryLaunch(destinationTile, arrivalAction, caravan);
+ return;
}
- }
-
- Thing transportThing;
- ThingDef skyfallerDef;
- WorldObjectDef worldObjectDef;
-
- if (transportShipDef != null)
- {
- // Use custom shuttle
- transportThing = ThingMaker.MakeThing(transportShipDef.shipThing);
- skyfallerDef = transportShipDef.leavingSkyfaller;
- worldObjectDef = transportShipDef.worldObject;
- }
- else
- {
- // Fall back to drop pods
- transportThing = ThingMaker.MakeThing(ThingDefOf.ActiveDropPod);
- skyfallerDef = ThingDefOf.DropPodLeaving;
- worldObjectDef = WorldObjectDefOf.TravellingTransporters;
- }
-
- // Load the transport
- CompTransporter compTransporter = transportThing.TryGetComp();
- if (compTransporter != null)
- {
- compTransporter.GetDirectlyHeldThings().TryAddRangeOrTransfer(caravan.GetDirectlyHeldThings(), canMergeWithExistingStacks: true, destroyLeftover: true);
- }
-
- // Create the skyfaller
- Skyfaller skyfaller = (Skyfaller)SkyfallerMaker.MakeSkyfaller(skyfallerDef, transportThing);
- if (skyfaller is FlyShipLeaving flyShip)
- {
- flyShip.groupID = 1;
- flyShip.destinationTile = destinationTile;
- flyShip.arrivalAction = arrivalAction;
- flyShip.worldObjectDef = worldObjectDef;
- }
-
- // Create traveling world object
- WorldObject travelingPods = WorldObjectMaker.MakeWorldObject(worldObjectDef);
- travelingPods.Tile = base.parent.Tile;
- travelingPods.SetFaction(Faction.OfPlayer);
-
- // Set destination using reflection since we don't know the exact type
- var destTileField = travelingPods.GetType().GetField("destinationTile");
- if (destTileField != null)
- {
- destTileField.SetValue(travelingPods, destinationTile);
- }
-
- var arrivalActionField = travelingPods.GetType().GetField("arrivalAction");
- if (arrivalActionField != null)
- {
- arrivalActionField.SetValue(travelingPods, arrivalAction);
- }
-
- Find.WorldObjects.Add(travelingPods);
-
- // Add pods using reflection
- if (compTransporter != null)
- {
- var addPodMethod = travelingPods.GetType().GetMethod("AddPod");
- if (addPodMethod != null)
+
+ // Transfer caravan contents to shuttle's transporter
+ compTransporter.GetDirectlyHeldThings().TryAddRangeOrTransfer(
+ caravan.GetDirectlyHeldThings(),
+ canMergeWithExistingStacks: true,
+ destroyLeftover: true);
+
+ // Create the traveling world object - cast to TravellingTransporters for direct property access
+ TravellingTransporters travelingShuttle = (TravellingTransporters)WorldObjectMaker.MakeWorldObject(transportShipDef.worldObject);
+ travelingShuttle.Tile = parent.Tile;
+ travelingShuttle.SetFaction(Faction.OfPlayer);
+ travelingShuttle.destinationTile = destinationTile;
+
+ // Use custom arrival action that forces map loading to show shuttle landing
+ travelingShuttle.arrivalAction = arrivalAction ?? new TransportersArrivalAction_FormCaravan();
+ // Set the transport ship def (still need reflection for this private field)
+ var transportShipField = typeof(TravellingTransporters).GetField("transportShip",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ if (transportShipField != null)
{
- addPodMethod.Invoke(travelingPods, new object[] { compTransporter.GetDirectlyHeldThings().ToList(), true });
+ transportShipField.SetValue(travelingShuttle, transportShipDef);
}
+
+ Find.WorldObjects.Add(travelingShuttle);
+
+ // Wrap the cargo in ActiveTransporterInfo for AddTransporter
+ ActiveTransporterInfo transporterInfo = new ActiveTransporterInfo();
+ transporterInfo.innerContainer.TryAddRangeOrTransfer(
+ compTransporter.GetDirectlyHeldThings(),
+ canMergeWithExistingStacks: true,
+ destroyLeftover: false);
+
+ travelingShuttle.AddTransporter(transporterInfo, true);
+
+ caravan.Destroy();
+ return;
}
-
- caravan.Destroy();
+
+ // Fallback to drop pods
+ Log.Warning("[FCP Enlist] Failed to launch shuttle, falling back to drop pods");
+ TryLaunch(destinationTile, arrivalAction, caravan);
}
}
@@ -901,15 +873,19 @@ public class WorldObjectCompEnlist : WorldObjectComp
}
}
}
- private IEnumerable GetTransportPodsFloatMenuOptionsAt(int tile, Caravan caravan)
+ private IEnumerable GetTransportPodsFloatMenuOptionsAt(int tile, Caravan caravan, Action launchAction = null)
{
+ // Default to TryLaunch if no launchAction specified (for drop pods)
+ if (launchAction == null)
+ launchAction = TryLaunch;
+
bool anything = false;
if (!Find.World.Impassable(tile) && !Find.WorldObjects.AnySettlementBaseAt(tile) && !Find.WorldObjects.AnySiteAt(tile))
{
anything = true;
yield return new FloatMenuOption("FormCaravanHere".Translate(), delegate
{
- TryLaunch(tile, new TransportersArrivalAction_FormCaravan(), caravan);
+ launchAction(tile, new TransportersArrivalAction_FormCaravan(), caravan);
});
}
//List worldObjects = Find.WorldObjects.AllWorldObjects;
@@ -928,7 +904,7 @@ public class WorldObjectCompEnlist : WorldObjectComp
{
yield return new FloatMenuOption("TransportPodsContentsWillBeLost".Translate(), delegate
{
- TryLaunch(tile, null, caravan);
+ launchAction(tile, null, caravan);
});
}
}