MnB2-Bannerlord-CommunityPatch icon indicating copy to clipboard operation
MnB2-Bannerlord-CommunityPatch copied to clipboard

Talk to other lords when encountering armies

Open dijidiji opened this issue 4 years ago • 1 comments

Currently it seems you can only talk to other lords in an army if you're part of their faction.

I'm a complete novice when it comes to programming, let alone modding, otherwise I'd attempt to fix it myself but I did find "game_menu_army_talk_to_other_members" within EncounterGameMenuBehavior.cs.

Perhaps this would be a starting point for someone to go off if they wanted to fix it? That is, assuming it is unintended behaviour and within the scope of this mod to fix.

dijidiji avatar Apr 11 '20 08:04 dijidiji

I have been looking for a way to fix this.

Use cases

The player will basically get a menu when interacting with an army of its faction and a conversation if the player isn't part of it (enemy or neutral).

Therefore, without the menu, the player will directly talk to the army's leader without having the option to talk to the other members.

Possible solution

So a quick fix is to allow this menu to pop up for each faction when encountering an army. Taleworlds implemented the menu in a way that the player can talk to other members (if any) of a friendly army. An attack/leave option is available when encountering a enemy army.

The DoMeetingInternal method in the TaleWorlds.CampaignSystem.PlayerEncounter class is responsible for this behaviour :

private void DoMeetingInternal()
{
  PartyBase party1 = this._encounteredParty;
  if (party1.IsSettlement)
  {
    foreach (PartyBase party2 in (IEnumerable<PartyBase>) MobileParty.MainParty.MapEvent.DefenderSide.Parties)
    {
      if (!party2.IsSettlement)
      {
        party1 = party2;
        break;
      }
    }
  }
  Campaign.Current.CurrentConversationContext = ConversationContext.PartyEncounter;
  this.EncounterState = PlayerEncounterState.Begin;
  this._stateHandled = true;
  if (PlayerEncounter.PlayerIsAttacker 
    && this._defenderParty.IsMobile
    && (this._defenderParty.MobileParty.Army != null
      && this._defenderParty.MobileParty.Army.LeaderParty == this._defenderParty.MobileParty)
    && (this._defenderParty.MobileParty.Army.LeaderParty.MapFaction == MobileParty.MainParty.MapFaction
      && !this._defenderParty.MobileParty.Army.LeaderParty.AttachedParties.Contains(MobileParty.MainParty)))
  {
    GameMenu.SwitchToMenu("army_encounter");
  }
  else
  {
    this._meetingDone = true;
    CampaignMission.OpenConversationMission(new ConversationCharacterData(CharacterObject.PlayerCharacter, PartyBase.MainParty, false, false, false, false), new ConversationCharacterData(party1.Leader, party1, false, false, false, false), "", "");
  }
}

We can see that the if opens the menu else opens the conversation. So by deleting the following condition :

this._defenderParty.MobileParty.Army.LeaderParty.MapFaction == MobileParty.MainParty.MapFaction

We should get what we want.

Issues

Unfortunatly, the game's implementation updates private fields of the PlayerEncounter class. These fields have either :

  • private setters
  • no getters

This project updates the implementation of the game by swapping the implementation of game methods with custom ones. Without having access to some getters and/or setters of the private fields, my solution cannot be implemented.

The contributors may have faced similar problems and may know a workaround ?

JoeFwd avatar Apr 14 '20 15:04 JoeFwd