Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DFU 1.2 #2652

Open
KABoissonneault opened this issue May 16, 2024 · 10 comments
Open

DFU 1.2 #2652

KABoissonneault opened this issue May 16, 2024 · 10 comments
Milestone

Comments

@KABoissonneault
Copy link
Collaborator

This is the issue for discussion of version 1.2 for DFU.

Version 1.1 was a bit ambitious. We had a few issues which had been left on hold for a few years really, and had to get out now that development returned to a more open state. I'm hoping 1.2 will be less held back by big changes needing to be merged. No matter what, I'm thinking we should wait a few months, then ship whatever we have at that point.

For this milestone, I've created a new branch on this repo: the 'release' branch. That branch matches the latest release of DFU, and changes only get sent there if we need to make a new minor release (for critical fixes). Whenever we make a new major release, master gets merged into release.

The purpose of this separate branch is mostly to free up master from being put on hold after each release. Now, we can safely merge experimental changes to master, and if we need a 1.1.2, then we can just make one from the release branch instead, without risking new regressions from whatever has been added in the meantime.

This means, PRs should now be safer to merge. If you have not noticed, we have lowered the "approved contributor" review requirement from 2 to 1 on PRs, so only one approval is required to merge. Ideally, I'd like if merging was left to the person in charge of releases (ie: me, as of now). PRs that only affect editor tools are an exception, they can be merged any time.

Now, for 1.2 itself. The task of clearing the PR backlog remains. Priority goes to the older ones, so if you have newer PRs you want to get through, you could help by reviewing the older ones :). For normal contributors, I'd appreciate if you left some details as to what was reviewed (code only, testing).

The big items for this version will be the larger mod systems that have been discussed for years but had to be left aside due to code freezes. My own plans are the following items:

  • Skills, "Actions", and Experience (SAE)
  • New "formula overrides" for gameplay features in UI windows
  • Character creation

Skills, Actions, and Experience (SAE) covers both custom skills and experience gain, with Player Actions being the new way of thinking about how to react to something the player does. This will involve expanding some DFU interfaces to support arbitrary skill identifiers, new "player action" events that mods can subscribe to (with default DFU handlers, for the classic experience gain), the ability to register new skills (and suppress classic ones), and updating classic UIs to support custom skills. The details of the implementation will be expanded further in a dedicated issue. I believe custom skills and changing experience gain is a major need for many mods. The goal is avoiding scenarios where a mod has to override an entire component just to react to a section of the code, as well as avoiding scenarios where multiple different mods react to the same event, awarding duplicated experience rewards.

UI Formula Overrides is a more minor but extensive goal. Some features are baked into UI windows, and mods wanting to tweak those features need to override the entire window. This creates conflicts with actual UI mods and localization mods. For example, Unleveled Spells overrides DaggerfallSpellBookWindow for the sole purpose of changing spell prices. I will make an issue trying to identify some features that could be extracted to a separate class (or just FormulaHelper, we'll see) with the normal formula override mechanics. Other modders will be able to add other features they'd like to see extracted on that issue.

Character creation is a massive one, and will probably require a few phases before it's complete. This is probably the biggest gap in our modding support, and might be even more necessary if SAE goes through. That's one area I don't have a concrete plan yet, but I know one thing: I don't want some simple shoehorned events everywhere in the code. This might include default class overrides, custom races, custom attribute rolls, maybe the ability to change the entire flow (not just override individual elements of the classic flow).

From now on, I'd like to see new modding features be more "planned", more extensible, more future-proof. Minimal changes can actually make the codebase more complicated in the long term, as everyone just shoves whatever they need in the immediate in as few lines as possible, and there's no consistency between the many features, even within a single class.

So, if you have a feature you need for your mod, try to think what you might need in the future, and what another mod might need to something similar but different.

Anyway, discussions below are welcome.

@KABoissonneault KABoissonneault added this to the DFU 1.2 milestone May 16, 2024
@Daneel53
Copy link

Hello,
I would like to ask officially to the team that is today in charge of DFU code to accept to introduce into DFU some code that will permit mods in other languages than English to use a grammar processor in order to produce better translated text in a grammatical point of view.

I wrote a document that explain everything to be clearer.

If the modification is accepted by the team and implemented in a future release of DFU, the French translation shall be the first to benefit of a grammar processor to ameliorate the French translation, it is already working on my PC. Then other translators may try, if they feel ready, to write a mod with their own grammar processor for their language, the French one being an example for them.
Grammar processors for DFU.pdf

You can contact me via my Discord account, it will be easier that through Github.

@KABoissonneault
Copy link
Collaborator Author

Seems valid, but we should probably track this as a separate issue

@Daneel53
Copy link

Daneel53 commented May 20, 2024

I agree. Can you transfer the above message, or must I create a new entry and remove the messages here?

@KABoissonneault
Copy link
Collaborator Author

Anyone can open issues, please do so

@Daneel53
Copy link

Done. We can clean the above messages.

@jpw1991
Copy link

jpw1991 commented Jun 1, 2024

Hello, I'd just like to throw my 2c in about the character creation stuff because I recently worked in this area for my Cheb's Necromancy mod.

My objective was pretty simple - to add a custom class to the character creation wizard's classes listbox. I encountered so many restrictions with the character creation wizard in terms of lack of public events and restrictive scope, that I was unable to do so. In the end my workaround was to create a clone of the wizard that adds my custom class, wait for the vanilla wizard to open then close it and open mine instead. I write about it in more detail here.

I'm happy you're planning to add more support for character creation.

Another thing - do you think adding Harmony to DFU would be a good idea? It'd also solve problems like this, although in a much broader sense because it'd touch on everything. I think it's messier but it opens a lot of potential for all kinds of changes without needing to give much thought to what people do.

@KABoissonneault
Copy link
Collaborator Author

KABoissonneault commented Jun 1, 2024

do you think adding Harmony to DFU would be a good idea

I really don't think so. Unlike all other modded projects, we're an actual open source project. This means two things. One, we can actually just modify the game itself to support mod features, which is much simpler. Two, DFU actively changes constantly, which makes solutions like Harmony unstable.
You can already do something similar through C# reflection. The thing is, I am not going to account for mods that break because they depend on DFU's internals. It's much more robust if DFU can design a public interface for mods to use, because then we know what not to break.

@hhorne
Copy link

hhorne commented Oct 27, 2024

I'm really interested in any details you may be willing to share about your intentions for the Forumla Overrides! I'm currently examining that section of code to help me learn how so many mods work. I recently hacked together an attack description mod, but to do it I needed to use overrides to catch certain values like hit location, ultimately also overriding CalculateAttackDamage as well as the best place to log the message.

One downside was that I had to copy the original implementations of needed formulas (minus the check for overrides) if I wanted to maintain their behavior and compose something on top of it, as trying to call the original FormulaHelper method would lead to an infinitely recursive call. I started looking more closely at FormulaHelpers to see what could make it easier for mods to build on top of without conflicting, like decoupling the default implementation from the main formula call.

Obviously a hit description mod would work best with some kind of event raised at the completion of an attack rather than overriding formulas though, which I also see the likes of referenced in this issue! Knowing there are already changes planned here makes me happy and I'll hold off on filing any PRs until I have a sense of what direction you want to move in at which point I'll happily contribute what I can.

@KABoissonneault
Copy link
Collaborator Author

Yeah sorry, when I envisioned DFU 1.2, I thought I would have a lot more time to get into this. I'm not sure how much time I'll have for implementation in the near future, but maybe it's worth writing out the plan if you think you'd be interested in implementing it, or at least comment on it

@hhorne
Copy link

hhorne commented Oct 27, 2024

No apologies needed, thank you for the quick response in fact! I didn't mean to say I was waiting or expecting any code or new implementations, more that I'm curious roughly what kind of changes you had in mind or what you viewed as priorities. Just coming in to this project, my view is more micro than macro right now and proposed changes may reflect that inexperience. However I also know what it's like to come back after even a month, look at an Issue/Story and struggle to recall details.

Keeping in mind that I haven't worked with Daggerfall Unity mods long enough to know what experienced modders really need and want, I'm happy to describe some rough ideas!

My first inclination was to decouple default formula implementations and make the existing calls a wrapper that checks for overrides or calls the default. This would grant the ability to modify the result by composing functions around the default formula. Useful for situations where you may want to look at and conditionally modify the result of the default behavior without redoing it entirely.

Example:

FormulaHelpers would start to look more like this

public static int CalculateStruckBodyPart()
{
    Func<int> del;
    if (TryGetOverride("CalculateStruckBodyPart", out del))
        return del();

    return CalculateStruckBodyPart_Default()
}

public static int CalculateStruckBodyPart_Default()
{
    int[] bodyParts = { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6 };
    return bodyParts[UnityEngine.Random.Range(0, bodyParts.Length)];
}

So that in a mod you might be able to do something like:

FormulaHelpers.RegisterOverride(mod, "CalculateStruckBodyPart", () =>
{
    // Use the default behavior without going into an infinite loop
    var result = FormulaHelpers.CalculateStruckBodyPart_Default();
    // Any additional/conditional logic would go here and `result` can be modified
    return result;
});

More useful though, a simple PlayerAttackEvent / EnemyAttackEvent with a small amount of information. ex:

public class AttackArgs
{
    public DaggerfallEntity Attacker { get; set; }
    public DaggerfallUnityItem Weapon { get; set; }
    public DaggerfallEntity Target { get; set; }
    public bool IsBackstab { get; set; }
    public bool IsCriticalHit { get; set; }
    public BodyParts BodyPartStruck { get; set; }
}

This enables someone track fun stuff like number of head strikes, print flavorful messages based on hits/subsets of hits, etc without having to create the formula overrides above, which is what I did in the hit description hack I worked up.

Hopefully this is somewhere in the right direction, and to be clear I'm offering to work on these changes and not requesting them from you. If these aren't quite right, whatever broad or general ideas you may have previously had are obviously welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants