Tournament Prize value?

Users who are viewing this thread

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!
 
Back
Top Bottom