Recent content by MitchPTI

  1. MitchPTI

    Suggestion General Make better use of PartyTroopUpgradeModel in party screen to determine upgrades available

    @Dejan My mod aims to give non-hero troops more individuality. Instead of just knowing that you have 5 Imperial Recruits for example, each one is given a name and always spawns into battle with the same body properties, equipment, etc. One feature of the mod is that troops can loot equipment from enemies they've killed. So one of your troops might kill an enemy cavalry unit and take their horse. If that happens, then that unit should be able to upgrade to a unit that requires a horse of that type even if I don't have any in my personal inventory.

    If I have a stack of 10 troops that can be upgraded to a cavalry unit and I only have 2 horses of the required type in my inventory, BUT 3 of those troops already have horses that they looted in previous battles, then the number of upgrades available should be 5, not 2. Right now I can't accomplish this without harmony. However, if there were methods like NumTroopsThatCanUpgradeFromTroopToTarget and NumRequiredItemsPartyHasForUpgrade in the PartyTroopUpgradeModel, then it would be very doable.

    Does that make sense?
  2. MitchPTI

    Suggestion General Make better use of PartyTroopUpgradeModel in party screen to determine upgrades available

    I've just discovered that the PartyTroopUpgradeModel exists and am extremely pleased with this, it's exactly the kind of thing I need for my mod. However, it only seems to be partially used in the party screen for determining number of upgrades available. In PartyCharacterVM.InitializeUpgrades...
  3. MitchPTI

    Discussion Suggestion Please make campaign time customisable

    This is kind of a big one, as I imagine a lot of people will want to make mods using the Gregorian/Julian calendar (as well as other real world calendars and custom ones for fantasy mods), but the length of weeks, seasons and years are locked as constants in CampaignTime. Simply changing these...
  4. MitchPTI

    Modify the flow of time - (modding help)

    Unfortunately, changing the flow of time is impossible without Harmony atm and kind of a ***** to do even with it. You would need to override the getters for a whole bunch of properties in the CampaignTime class, where TaleWorlds have inexplicably chosen to hardcode everything. Even then, there's a lot of logic littered throughout the codebase where they calculate things like age using the hardcoded values instead of those getters, which can cause all kinds of bugs. When I tried it, I would start a new campaign and the game would freeze up for a long time and then give me a tonne of notifications letting me know that basically everybody in Calradia had died of old age.
  5. MitchPTI

    e1.6.0-v1.2.7 Modding Changes

    I love it. I've stepped away from modding for a while for a variety of reasons, mostly being busy with other stuff, but this makes me keen to dive back in. I don't think a lot of the changes listed here actually affect my specific mod a whole lot, but just seeing all these changes provides a lot of confidence that feedback really is being listened to and acted upon if it's well considered, so might as well try offering some.
  6. MitchPTI

    [Quick Question] Tree-changing upgrades?

    Dynamically changing the upgrade paths available is definitely very doable via C#, it's just a matter of updating the UpgradeTargets property of the CharacterObject class. Adding more than 2 would be a lot more complex because you'd have to update the party screen to accommodate that.

    Edit: I would suggest that you:
    1. Expand the UpgradeTargets of your chosen characters to include all the possible upgrade paths you want.
    2. Create your own PartyTroopUpgradeModel implementation that determines which paths are available via the CanPartyUpgradeTroopToTarget method.
    3. To get around not being able to have more than 2 upgrades in the party screen, have some code (that runs upon opening the party screen or something) that sorts UpgradeTargets such that available upgrade paths are at the front of the array and thus actually show up in the party screen.

    You could have any number of potential upgrade paths, just so long as there's never more than 2 actually available to the player. If you want more than 2 available then you're out of luck unless you want to get into editing the party screen, which is no small feat.
  7. MitchPTI

    Suggestion General A Proposal For TaleWorlds to Provide an Open-Source Fork of Module Source Code

    Would love to see this. I've always thought it would be amazing if the code were on GitHub and we could submit pull requests for bugs we've fixed ourselves or changes we'd like to see to make modding easier, but obviously the volume of requests could get out of control pretty quickly and there'd be no guarantee as to the quality of them. Having a team of modding community leaders maintaining the fork would be an excellent solution to that. They could stand between the devs and the modding community at large, carefully reviewing all the pull requests thrown at them by individual modders and ensuring everything merges together without anything breaking, before submitting their own pull requests with all the approved changes to the devs with agreements in place about how often they can do so, what's in scope, etc.
  8. MitchPTI

    Discussion Suggestion Unseal CharacterObject or Replace Declarations with BasicCharacterObject

    So, for my mod it would be really useful if I could make my own subclass of CharacterObject, but unfortunately it's sealed. Right now I'm using a workaround where a separate class has the fields and methods I want to add and I map CharacterObject instances to instances of this class. I would be...
  9. MitchPTI

    How to calculate if party is in friendly territory?

    Have a look in the SettlementHelper class; you can call FindNearestSettlementToPoint and pass in the party's current position and then all you have to do is check relations with the settlement's faction. Be warned though, this method does iterate over all settlements so it could have a performance impact if you're planning to call it every tick or something (I would hope not).
  10. MitchPTI

    Tournament Prize value?

    The prize for a tournament is set in the constructor of the abstract class TournamentGame, which calls a private method called GetTournamentPrize. That method just defines a hardcoded list of options and chooses one at random with weighted probabilities. The simple, lazy way to change this would be to use a Harmony Prefix to replace the body of the GetTournamentPrize method with whatever you want, like so:

    C#:
    [HarmonyPatch(typeof(TournamentGame), "GetTournamentPrize")]
    public class TournamentPrizePatch
    {
        static bool Prefix(ref ItemObject __result) {
            // Put your logic here, set __result to your chosen item
            return false; // Skips the original method
        }
    }


    The non-Harmony way is a bit more complicated (warning, I haven't tested any of the following, just figuring it out and typing this up on the fly):

    1. Create a new class that extends TournamentGame and put your new options / logic in the constructor of that class. The default one used currently is FightTournamentGame, so I would recommend extending that so that you don't need to re-implement anything else. Unfortunately, while the TournamentGame constructor takes a prize parameter, the FightTournamentGame constructor does not, it just passes in null as the prize to the base constructor, so you can't pass your chosen prize up the constructor chain. You also can't just set the Prize property directly because the set method is private rather than protected. TaleWorlds really aren't keen on letting you change it I guess... That leaves Reflection as your only option:
    C#:
    [SaveableClass(1)]
    public class YourNewTournamentGame : FightTournamentGame
    {
        public YourNewTournamentGame(Town town) : base(town)
        {
            ItemObject prize = (ItemObject)null; // Do something else here instead to get your prize
    
            // Set the prize property via Reflection
            typeof(TournamentGame).GetProperty("Prize", BindingFlags.Instance | BindingFlags.NonPublic).SetValue((TournamentGame)this, prize);
        }
    }

    Alternatively, just copy paste what's in FightTournamentGame and extend TournamentGame directly so that you can pass the item into the base constructor, though I don't see much point to that. A single use of Reflection upon a tournament being created is certainly not going to have a performance impact.

    2. Create a new class that extends TournamentModel. Similarly to above, it's easiest to just extend the current default, aptly named DefaultTournamentModel. Thankfully there's no Reflection needed in this one, you just have to override a single method, which will create a tournament using your class above instead of FightTournamentGame.
    C#:
    public class YourNewTournamentModel : DefaultTournamentModel
    {
        public override TournamentGame CreateTournament(Town town)
        {
          return (TournamentGame) new YourNewTournamentGame(town);
        }
    }

    3. In your submodule class, add your new tournament model in OnGameStart:
    C#:
    protected override void OnGameStart(Game game, IGameStarter starterObject)
    {
        starterObject.AddModel((GameModel) new YourNewTournamentModel());
    }

    Hopefully that is then enough for your new tournament model to be used, however I have no idea if it'll just override the default model automatically or if you have to somehow remove the default one. I don't see a simple, publicly accessible way to remove the default one, so I would hope it just takes over automatically.

    An important consideration to doing it the non-Harmony way is that your new tournament game class has to be saveable, so if you're making a new mod just to do this, or adding this to a mod that doesn't currently have a SaveableTypeDefiner, then you're gonna have to set that up (read more here). If you've already got all that, just replace the 1 I put in the SaveableClass annotation with the appropriate number.

    I hope that helps!
  11. MitchPTI

    Detecting When Entering Map View/Screen

    I necro things a bit, but doing checks on application tick is realllllllllly dirty ...

    You can instead use
    Code:
    Game.Current.EventManager.RegisterEvent<TutorialContextChangedEvent>(new Action<TutorialContextChangedEvent>(Your_delegate));
    To check when the screen state is changed, for once the tutorial being useful at something.
    Then in your delegate do something like this
    Code:
    public void Your_delegate(TutorialContextChangedEvent eve)
            {
                if (eve.NewContext != TutorialContexts.MapWindow)
                    return;
                //---Mycode here---//
            }
    You can detect most of the game interface screen this way, except character screen that do not trigger the event correctly due to a bug.

    That's definitely infinitely better than what I offered. Since you've already necro'd, I might hijack this thread a bit and ask if you happen to have any knowledge around detecting key presses in a similar manner? Right now I'm trying to detect when a certain key is pressed while the party screen is open and I'm struggling tbh.
  12. MitchPTI

    Modding in C# feels incredibly boring and tedious.

    There's alot that needs improvement - defaulting to "private" instead of "protected", things that could be virtual that aren't, etc, but in general it's kinda amazing.

    The amount of private methods and sealed classes have kinda killed my ambitions, if it weren't for those I'd be loving it as much as you do.
  13. MitchPTI

    Detecting When Entering Map View/Screen

    This worked for me:

    Code:
    using SandBox.View.Map;
    using TaleWorlds.Engine.Screens;
    using TaleWorlds.MountAndBlade;
    
    namespace ExampleMod
    {
        public class ExampleSubModule : MBSubModuleBase
        {
            private bool _mapOpen = false;
    
            private void OnPushScreenEvent(ScreenBase screen)
            {
                if (!(screen is MapScreen))
                {
                    this._mapOpen = false;
                }
            }
    
            protected override void OnSubModuleLoad()
            {
                ScreenManager.OnPushScreen += new ScreenManager.OnPushScreenEvent(this.OnPushScreenEvent);
            }
    
            protected override void OnApplicationTick(float dt)
            {
                if (!_mapOpen && ScreenManager.TopScreen is MapScreen)
                {
                    this._mapOpen = true;
                    // Do stuff here
                }
            }
        }
    }
  14. MitchPTI

    Cultural Appropriate Name Generator

    The names the game uses can be found in spcultures.xml, for each culture there's a <male_names> and <female_names> tag containing them. I don't know if a generator would be possible that doesn't just pull from a pre-determined list, but if anybody did make one I'd be extremely interested.
Back
Top Bottom