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

Add ability to use Lazy GM's encounter difficulty system #192

Merged
merged 13 commits into from
Jun 28, 2023

Conversation

miscoined
Copy link
Contributor

@miscoined miscoined commented Jun 8, 2023

This adds a setting for XP system which currently has two options: DnD 5e (the default, current behavior), and DnD 5e Lazy GM, which uses a CR-based calculation.

Resolves #114 .

This also allows additional XP systems to be added in the future. I've gotten a Pathfinder 2E XP system working in the encounter builder which I'll be sending a PR along for when this one gets merged :)

I did my best to avoid any breaking API changes. Any existing integrations should still work provided the XP system is set to dnd5e, although this comes with the unfortunate effect of totalXp having a different meaning between XP systems. Any existing integrations which read the difficulty report will probably break if they're set to any other XP system.

BEGIN_COMMIT_OVERRIDE
feat: Adds the Lazy GM additional difficulty calculation method + a scaffold for future difficulty methods.
END_COMMIT_OVERRIDE

Kelly Stewart added 5 commits June 8, 2023 11:48
This doesn't currently do anything, but will be used for choosing different ways to calculate XP
for encounters.

Put it under "Encounters" in settings, but not in the builder part of the data, as this isn't
specific to the encounter builder.
This is to prepare for more customizable encounter XP systems.
- Move all XP-calculation related things to encounter-difficulty.ts
- Remove duplicated logic between encounter builder and other encounters
- Use DifficultyReport for XP-related calculations. In the future we can swap out the contents
  of this and how it's generated based on the current XP system.

Incidentally, this fixes some a discrepency between the encounter builder and other encounters:
- other encounters will now show 'Trivial' for encounters below the Easy XP threshold, same as
  the encounter builder
This alters the encounter builder, encounters, and encounter table to all use the Lazy GM's
(https://slyflourish.com/the_lazy_encounter_benchmark.html) system for benchmarking encounters.

- The encounter and encounter table now show CR for each creature rather than XP
- The encounter builder will show total XP as well as the CR threshold for deadly, and the total CR

BREAKING CHANGE: this changes the tracker difficulty result to not always populate `adjustedXp`.
Now, non-DnD5e systems will use `totalXp` for the total, while DnD 5e will use `adjustedXp`.
This alters the encounter builder, encounters, and encounter table to all use the Lazy GM's
(https://slyflourish.com/the_lazy_encounter_benchmark.html) system for benchmarking encounters.

- The encounter and encounter table now show CR for each creature rather than XP
- The encounter builder will show total XP as well as the CR threshold for deadly, and the total CR

BREAKING CHANGE: this changes the tracker difficulty result to not always populate `adjustedXp`.
Now, non-DnD5e systems will use `totalXp` for the total, while DnD 5e will use `adjustedXp`.
This alters the encounter builder, encounters, and encounter table to all use the Lazy GM's
(https://slyflourish.com/the_lazy_encounter_benchmark.html) system for benchmarking encounters.

- The encounter and encounter table now show CR for each creature rather than XP
- The encounter builder will show total XP as well as the CR threshold for deadly, and the total CR

BREAKING CHANGE: this changes the tracker difficulty result to not always populate `adjustedXp`.
Now, non-DnD5e systems will use `totalXp` for the total, while DnD 5e will use `adjustedXp`.
@valentine195
Copy link
Member

@miscoined I think this is a great start and I really appreciate the effort put in here. I'm thinking about how to make it easier to add in new systems later.

  1. I think a new folder structure, with a folder-per-system inside it and then the common utilities at the top level, would be easier to maintain and add onto.
  2. Possibly hard-typing the Threshold system and creating a new function that returns the threshold for a given difficulty would be more readable than calculating it in the Svelte component.
  3. Same for xp as above.
  4. I'm wondering if it would be better to make system-specific Svelte components anyway. As additional systems are added, this component will get massive.

I am also wondering if a difficulty service that the component interfaces with would be better, with standard methods. Then new systems would just need to hook into those. Thoughts?

@miscoined
Copy link
Contributor Author

Hey, thanks for the fast review, and for the feedback! I'm very much in the 'enthusiastic learner' category when it comes to JS/Svelte/Typescript, so apologies if I struggle with terminology a bit.

  1. Strong agree with a new folder structure. I started adding in the PF2e one today and yeah, at the very least a new file per-system is required.
  2. I'm not sure what you mean by 'hard-typing' here, sorry. Currently the difficulty threshold (e.g. "Deadly") for the actual XP amount comes directly from the difficulty report, but we'll still need to list out the budgets for the encounter builder.
  3. As above- I'm not sure what XP calculation you're referring to, afaict the only XP related calculations happening in the component is the conversion to string
  4. I was thinking about system-specific Svelte components as well. I think it depends a little on the expected use-cases; if it's mostly things that are more-or-less XP-based systems then I don't imagine there'll be much custom layout stuff required. My TTRPG experience here is pretty limited on the kinds of things that might come up here.

Terminology strikes again; by a difficulty service, are you referring to eg a base class that has a bunch of defined methods, and then every new system would be a subclass? if so then I think that could work well, but that could just be my OOP bias talking.

For now I'll have a look at at least separating out the different subsystems a bit.

A question, also; do I need to be careful about breaking changes to the API? I've been trying to keep it as untouched as possible, but it'd be good to know the likelihood of changes in the APIs difficulty reports breaking anyone's integrations.

@valentine195
Copy link
Member

valentine195 commented Jun 8, 2023

By a difficulty service, are you referring to eg a base class that has a bunch of defined methods, and then every new system would be a subclass? if so then I think that could work well, but that could just be my OOP bias talking.

Yes, essentially

2 / 3:

By hard typing, I mean: enforce type Threshold = [string, string][]; and move the threshold calculation to its own function outside the Svelte component:

export function getThresholds(difficulty: Difficulty): Threshold {
    switch (difficulty.system) ...
}

That will help declutter the Svelte component, although if we implement a difficulty service then this can wrap into that anyway.

Also rename the xpSystem setting to rpgSystem to allow for future
extensions for other purposes eg initiative. Still keep it in labelled
as "XP Tracker" in the UI though.

Delete encounter-difficulty.ts and put difficulty-related functions
under rpg-system instead. Also for now remove the lazy GM setting, to be re-added in a later
commit.
@miscoined
Copy link
Contributor Author

Hey! Added an RpgSystem class and an implementing Dnd5eRpgSystem to replace the current difficulty calculation logic. Am working on adding the Lazy GM's system back in now, just thought I'd give you an update on how it's looking.

Also add calls to formatDifficultyValue() in several places that I
initially forgot, and add an optional arg for whether the formatted
value should include units or not.
@miscoined
Copy link
Contributor Author

Added back in the Lazy GM system. Apologies for the messy commits also; let me know if you'd like me to just squash em all into one, or leave adding in the new system as a separate PR. I'm fairly new to working with pull requests, sorry!

@valentine195
Copy link
Member

@miscoined thanks! I glanced through the code on the web and it looks a lot more extensible, thanks.

I'll try to pull this code and do some testing.

- Add a getAdditionalCreatureDifficultyStats for what should be shown
  when a creature is added to the builder. This allows systems to show
  the stats that are relevant to their difficulty calculations.
- Fix some null issues that I missed when refactoring to use
  getFromCreatureOrBestiary. And also a spelling mistake in that method
  name.
- Move the method to convert CR num to string into utils so it can be
  used by both RPG systems
- Minor formatting fixes
@sigrunixia sigrunixia requested a review from valentine195 June 21, 2023 16:23
@valentine195
Copy link
Member

I’m going to try to review this today

@valentine195 valentine195 merged commit 2c39c7b into javalent:main Jun 28, 2023
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

Successfully merging this pull request may close these issues.

[Feature Request]: Allow other methods to calculate Deadly Encounters
3 participants