foundryvtt / black-flag

The official repository for Kobold Press's "Black Flag" game system implementation in Foundry Virtual Tabletop.
MIT License
10 stars 5 forks source link

Create Spell Item Schema #12

Open akrigline opened 1 year ago

akrigline commented 1 year ago

Playtest Packet 2 describes "Spell"s which would be best implemented as an Item type. I'm going to bring some knowledge from the 5e system and make note of what shortcomings were felt by people who wanted to extend the spellcasting system

Compiling as much knowledge up front as I can about this topic because it will be a doozy.

Descriptive Text

description: HTML;
spellCircle: 'arcane' | 'divine' | 'primal' | 'wyrd'; // this selection should be extensible by modules
spellRing: number; (0 can represent cantrips, max of 9 should not be assumed, often this is expanded beyond 9)
spellSchool: 'one of the options'; // this should be extensible by modules

Origin

Something we were lacking in 5e was a way to mark where the spell came from. E.g. a Cleric/Druid might prepare different spells for each class, but there should be a way to differentiate them. Similarly, some items might have spells embedded in them, and ideally the system supports annotating this.

Components

5e ended up making these extensible by modules and turning them into checkboxes in the item sheet.

Target -- common item concept

A little convoluted and probably generalizable with other combat items.

Spells can affect specifically some kinds of things (all creatures, allies, enemies; sometimes also objects sometimes not objects, sometimes 'magical effects', only the caster, n creatures/allies/etcetcetc)

Then, they can affect a kind of area (within a cone/sphere/box/line, a specific selection of creatures within range)

And lastly, they have a range for when the origin of that kind of area begins (self, n ft)

target: {
  creatures: {
    number: number;
    type: 'allies' | 'any' | 'enemies' | 'self';
    alsoAffectsObjects: boolean;
  },
  area: {
    type: 'target' | 'cone' | 'sphere' | etc
  },
  range: {
    value: number;
    unit: 'ft' | 'mile' | etc; // remember metric is probably a thing
  }
}

Attacks or Saves -- common item concept

Complicated, there's probably different 'kinds' of attack rolls (weapon attack, spell attack at minimum), saves can target specific attributes, saves can be based on a specific ability score for the character.

Damage -- common item concept

Complicated, but worth building in the idea of damage types and damage groups early

Duration -- common item concept

duration: {
  type: 'instantaneous' | 'time' | 'other'

  // if time is the type
  timeValue?: number;
  timeUnit?: 'minutes' | 'hours' | 'days'; // etc.

  // if 'other' is the type
  // stuff like "until the start of your next turn" or "until the end of their next turn", etc...
  // unsure how to represent this, an enum?
}

Casting Time -- aka "Usage Time", common concept

For spells this is pretty clearly one of:

cpcodes commented 1 year ago

I don't know if you are entertaining feedback here, but as far as the duration data structure, it should probably be stored internally as rounds (or instant, which might be different than 0 rounds), then converted for display if necessary. Any spell that provides a duration in its stat block in minutes/hours/days/etc. would simply be converted in the data to rounds.

Also, for targets, how would you handle something like vampiric touch where there are two different targets that receive two different effects? I assume a primary and secondary effect (or just an array of effect entries with no hard coded limit of total number), each with their own target settings, but I just wanted to bring it up since you were brain storming.

cswendrowski commented 1 year ago

I don't know if you are entertaining feedback here

We are! Feel free to pitch ideas on Discord as well

Round based duration could work fine, although some GM's might change how long a round is - unsure here, @akrigline thoughts?

how would you handle something like vampiric touch where there are two different targets that receive two different effects?

I think it might make sense to have both self, for things that should apply to the source Actor, and targets, which is an array of targeted Actors

akrigline commented 1 year ago

I've never heard of alternate round timings, if it's a thing it's not common. I do wonder though if "duration" really means anything for a spell, or if there should always be an Active Effect for any spell which isn't instantaneous, and then that effect should store its expected duration?

The alternative is to either sync duration to a spell's effects on every change, or have the effect somehow inherit its duration from the parent spell.

Upcasting does sometimes affect duration, so that'd be a point in favor of putting it on the spell, and having the effect 'inherit' that at cast time. That would also allow some sort of metamagic mutation of spells to work... Hmmm.

akrigline commented 1 year ago

Also, for targets, how would you handle something like vampiric touch where there are two different targets that receive two different effects?

Vampiric Touch is an interesting one, Fire Shield, Shadow Blade, also

These could be thought of as Spells which grant Effects that grant "powers", where "power" is a generic "thing that can be done."

So the "Vampiric Touch" spell would have a target of self, but the effect it imparts could create a new 'power' which has the right targeting logic inside it.

akrigline commented 1 year ago

stored internally as rounds

There's one hiccup for this I just realized, there's a lot of mix and match in 5e between "until the start of your next turn" or "the end of their next turn" or etc etc etc, which is hard to express as a number of rounds, or even a number of turns.

I think something more than a simple number might be a good play, but I'm not sure how best to express that.

maybe "endTime" which describes this:

duration: {
  rounds: 1,
  endTime: 'end-of-target-turn',
}
cpcodes commented 1 year ago

I think that you might be on to something with the spells simply creating Active Effects that hold a duration. Having the expiration set in terms of rounds (or seconds, if @cswendrowski's concern about variable round durations bears out), with an additional hint for beginning or end of turn (and whose turn) as you specify should cover the vast majority of circumstances. The only remaining hiccup I see is when position in the initiative order changes. I know that in 5e, they very specifically left out the delay action and modified readying an action in order to make the turn order immutable. So long as BF keeps this philosophy, this is good, otherwise you might need to keep the initiative number with the effect as well so that it ends on time regardless of where the caster/target moves to in the initiative order.

akrigline commented 1 year ago

Updates for this, i've started knocking out the bits piecemeal:

Targeting Data Model: #15

Duration Data Model: #18

I'm working through "Usage Time" or "Activation Time" next