Skip to content

Commit

Permalink
Merge pull request #1028 from Bannerlord-Coop-Team/settlement-bug-fix
Browse files Browse the repository at this point in the history
Settlement Player Enter and Exit Fix
  • Loading branch information
garrettluskey authored Nov 9, 2024
2 parents c737a3e + d52c032 commit 2f9e8eb
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 195 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace GameInterface.Services.CampaignService.Patches;
internal class CompanionsCampaignBehaviorPatches
{
[HarmonyPrefix]
[HarmonyPatch("CreateCompanionAndAddToSettlement")]
[HarmonyPatch(nameof(CompanionsCampaignBehavior.CreateCompanionAndAddToSettlement))]
private static bool Prefix()
{
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
using Common.Logging;
using Common;
using Common.Logging;
using Common.Messaging;
using Common.Util;
using GameInterface.Services.MobileParties.Interfaces;
using GameInterface.Services.MobileParties.Messages.Behavior;
using GameInterface.Services.MobileParties.Patches;
using GameInterface.Services.ObjectManager;
using Serilog;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.CampaignSystem.ViewModelCollection.Party;

namespace GameInterface.Services.MobileParties.Handlers;

Expand All @@ -15,14 +23,14 @@ internal class SettlementExitEnterHandler : IHandler
private static readonly ILogger Logger = LogManager.GetLogger<SettlementExitEnterHandler>();

private readonly IMessageBroker messageBroker;
private readonly IMobilePartyInterface partyInterface;
private readonly IObjectManager objectManager;

public SettlementExitEnterHandler(
IMessageBroker messageBroker,
IMobilePartyInterface partyInterface)
IObjectManager objectManager)
{
this.messageBroker = messageBroker;
this.partyInterface = partyInterface;
this.objectManager = objectManager;

messageBroker.Subscribe<PartyEnterSettlement>(Handle);
messageBroker.Subscribe<PartyLeaveSettlement>(Handle);
Expand All @@ -42,25 +50,78 @@ private void Handle(MessagePayload<PartyEnterSettlement> obj)
{
var payload = obj.What;

partyInterface.EnterSettlement(payload.PartyId, payload.SettlementId);
if (objectManager.TryGetObject(payload.PartyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", payload.PartyId);
return;
}

if (objectManager.TryGetObject(payload.SettlementId, out Settlement settlement) == false)
{
Logger.Error("SettlementId not found: {id}", payload.SettlementId);
return;
}

EnterSettlementActionPatches.OverrideApplyForParty(mobileParty, settlement);
}

private void Handle(MessagePayload<PartyLeaveSettlement> obj)
{
var payload = obj.What;

partyInterface.LeaveSettlement(payload.PartyId);
if (objectManager.TryGetObject(payload.PartyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", payload.PartyId);
return;
}

LeaveSettlementActionPatches.OverrideApplyForParty(mobileParty);
}

private void Handle(MessagePayload<StartSettlementEncounter> obj)
{
var payload = obj.What;

partyInterface.StartPlayerSettlementEncounter(payload.PartyId, payload.SettlementId);
if (objectManager.TryGetObject(payload.PartyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", payload.PartyId);
return;
}

if (objectManager.TryGetObject(payload.SettlementId, out Settlement settlement) == false)
{
Logger.Error("SettlementId not found: {id}", payload.SettlementId);
return;
}

var settlementParty = settlement.Party;
if (settlementParty == null)
{
Logger.Error("Settlement {settlementName} did not have a party value", settlement.Name);
return;
}

if (PlayerEncounter.Current != null) return;

GameLoopRunner.RunOnMainThread(() =>
{
using (new AllowedThread())
{
PlayerEncounter.Start();
PlayerEncounter.Current.Init(mobileParty.Party, settlementParty, settlement);
}
}, blocking: true);
}

private void Handle(MessagePayload<EndSettlementEncounter> obj)
{
partyInterface.EndPlayerSettlementEncounter();
GameLoopRunner.RunOnMainThread(() =>
{
using (new AllowedThread())
{
PlayerEncounter.Finish(true);
Campaign.Current.SaveHandler.SignalAutoSave();
}
}, blocking: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,6 @@ namespace GameInterface.Services.MobileParties.Interfaces;
/// </summary>
internal interface IMobilePartyInterface : IGameAbstraction
{
/// <summary>
/// Starts a settlement encounter for the player, bypasses patch skip rules
/// </summary>
/// <param name="partyId">Party to enter settlement as StringId</param>
/// <param name="settlementId">Settlement to enter as StringId</param>
void StartPlayerSettlementEncounter(string partyId, string settlementId);
/// <summary>
/// Forces the player party to leave their current settlement encounter
/// </summary>
void EndPlayerSettlementEncounter();
/// <summary>
/// Forces party to enter settlement, bypasses patch skip rules
/// </summary>
/// <param name="partyId">Party to leave current settlement</param>
void LeaveSettlement(string partyId);
/// <summary>
/// Handles the initialization of a newly transfered party
/// </summary>
Expand All @@ -43,12 +28,6 @@ internal interface IMobilePartyInterface : IGameAbstraction
/// </summary>
/// <param name="ownerId">Owner to assign all parties</param>
void RegisterAllPartiesAsControlled(string ownerId);
/// <summary>
/// Forces party to enter settlement, bypasses patch skip rules
/// </summary>
/// <param name="partyId">Party to enter settlement as StringId</param>
/// <param name="settlementId">Settlement to enter as StringId</param>
void EnterSettlement(string partyId, string settlementId);
}

internal class MobilePartyInterface : IMobilePartyInterface
Expand Down Expand Up @@ -84,77 +63,4 @@ public void RegisterAllPartiesAsControlled(string ownerId)
controlledEntityRegistry.RegisterAsControlled(ownerId, party.Key);
}
}

public void StartPlayerSettlementEncounter(string partyId, string settlementId)
{
if (objectManager.TryGetObject(partyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", partyId);
return;
}

if (objectManager.TryGetObject(settlementId, out Settlement settlement) == false)
{
Logger.Error("SettlementId not found: {id}", settlementId);
return;
}

var settlementParty = settlement.Party;
if (settlementParty is null)
{
Logger.Error("Settlement {settlementName} did not have a party value", settlement.Name);
return;
}

if (PlayerEncounter.Current is not null) return;

GameLoopRunner.RunOnMainThread(() =>
{
using (new AllowedThread())
{
PlayerEncounter.Start();
PlayerEncounter.Current.Init(mobileParty.Party, settlementParty, settlement);
}
});
}

public void EndPlayerSettlementEncounter()
{
GameLoopRunner.RunOnMainThread(() =>
{
using (new AllowedThread())
{
PlayerEncounter.Finish(true);
Campaign.Current.SaveHandler.SignalAutoSave();
}
});
}

public void EnterSettlement(string partyId, string settlementId)
{
if (objectManager.TryGetObject(partyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", partyId);
return;
}

if (objectManager.TryGetObject(settlementId, out Settlement settlement) == false)
{
Logger.Error("SettlementId not found: {id}", settlementId);
return;
}

EnterSettlementActionPatches.OverrideApplyForParty(mobileParty, settlement);
}

public void LeaveSettlement(string partyId)
{
if (objectManager.TryGetObject(partyId, out MobileParty mobileParty) == false)
{
Logger.Error("PartyId not found: {id}", partyId);
return;
}

LeaveSettlementActionPatches.OverrideApplyForParty(mobileParty);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using HarmonyLib;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Settlements;

namespace GameInterface.Services.MobileParties.Patches;

Expand Down Expand Up @@ -36,9 +37,8 @@ public static void OverrideApplyForParty(MobileParty party)
{
using (new AllowedThread())
{
if (party.CurrentSettlement is null) return;
LeaveSettlementAction.ApplyForParty(party);
}
});
}, blocking: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ internal class ParallelRobustnessPatches
static bool ParallelCheckExitingSettlements(CampaignTickCacheDataStore __instance, int startInclusive, int endExclusive)
{
for (int index = startInclusive; index < endExclusive; ++index)
Campaign.Current.MobileParties[index].CheckExitingSettlementParallel(ref __instance._exitingSettlementCount, ref __instance._exitingSettlementMobilePartyList);
{
MobileParty mobileParty = Campaign.Current.MobileParties[index];

if (mobileParty.Party == null) continue;

mobileParty.CheckExitingSettlementParallel(ref __instance._exitingSettlementCount, ref __instance._exitingSettlementMobilePartyList);
}

return false;
}
Expand Down
Loading

0 comments on commit 2f9e8eb

Please sign in to comment.