open-dm / api

A Laravel-based API for managing all things D&D
MIT License
3 stars 0 forks source link

Db Struct #14

Open devan1011 opened 4 years ago

devan1011 commented 4 years ago

This is not everything but I wanted to visualise the class and model structure. Feel free to remake in Draw.io

image

ghost commented 4 years ago

This made my brain hurt a lil bit.

But seems relatively correct, only problem is, we're still noobs, so we're bound to make mistakes with this.

I'd say its going to be really important (at least from a FE perspective) to keep the naming tight, and close to convention, as the naming and jargon is one of the most confusing aspects of DnD.

Oh let me just whip out my cantrip ???

Looks gud tho!

G-Bro commented 4 years ago

I just realised Monsters aren't characters. Monsters are more comparable to races.

If you have three orcs then they still use the same monster record in the table but have their own health.

So there has to be a separate Monster and MonsterCharacter class (where monster is the template for a monster character)

G-Bro commented 4 years ago

Or maybe MonsterSpecies and MonsterCharacter

G-Bro commented 4 years ago

@DanEvans485 are you suggesting that all Character classes use the same database table?

Same with all items?

devan1011 commented 4 years ago

Draw.io version

devan1011 commented 4 years ago

@DanEvans485 are you suggesting that all Character classes use the same database table?

Same with all items?

Yes are they not the same?

devan1011 commented 4 years ago

Just they use default values instead of custom ones like players

devan1011 commented 4 years ago

It's gotten out of hand The Plan

G-Bro commented 4 years ago

@DanEvans485 I've modelled everything we need (I think) for the Monster class https://www.draw.io/#G1pUeQyoH7rnbVNscC5p2PsKyAAtNVRImX

devan1011 commented 4 years ago

Cant access

G-Bro commented 4 years ago

https://drive.google.com/file/d/1pUeQyoH7rnbVNscC5p2PsKyAAtNVRImX/view?usp=sharing

devan1011 commented 4 years ago

So you don't think having armour and weapons as items would be good?

devan1011 commented 4 years ago

And I still think it'd be beneficial having monsters and characters as one table

G-Bro commented 4 years ago

I thought we agreed to keep item types separate, like armour, weapons, potions, rings etc.

Monsters are the classes. We can still have a single character table that has either a monster_id or a class_id and race_id

devan1011 commented 4 years ago

I thought we agreed to keep item types separate, like armour, weapons, potions, rings etc.

Separate classes same table I thought

devan1011 commented 4 years ago
class Item -> from items table
class Weapon extends Item
class Armour extends Item

class Character -> from characters table
class Monster extends Character
class Player extends Character
devan1011 commented 4 years ago

It's just too me they seem so similar. The only difference is Monsters are just made from a preset and never changed and characters do get changed. Why I put the template table on that diagram.

G-Bro commented 4 years ago

Monsters are not characters though. If you have three orc characters then they belong to one 'monster'. The monster is essentially the species of the character that provides the template that the character will be made from, so there is nothing to stop monster characters being characters.

You will have one record in the model table for 'orc' but if one orc character takes damage then that is applied to the orc character, not the monster.

As for armour, I think using item modifiers complicates things. The function below is how I calculate armour class in the current method, and I think this is massively simpler than using item modifiers with string commands

    public function getArmorClass(Character $character) {
        $armor_class = $this->base_armor;

        if ($this->apply_dex_modifier) {
            if ($this->dex_cap) {
                $armor_class += min(
                    $this->dex_cap,
                    $character->dexterity_modifier
                );
            } else {
                $armor_class += $character->dexterity_modifier;
            }
        }

        return $armor_class;
    }
devan1011 commented 4 years ago

How do you compute armour class. Like normally?

G-Bro commented 4 years ago

Each type of armour has a base AC

A shield grants you a further +2 AC

https://roll20.net/compendium/dnd5e/Armor#content

devan1011 commented 4 years ago

I'm gonna try something. If it fails or is too complicated then I agree with ^^ that struct

G-Bro commented 4 years ago

Cool. Sounds good. In that structure I think there is still a place for your modifiers, but I think the core mechanics of certain item types should be more strictly defined. Modifiers should be used for unique attributes IMO

devan1011 commented 4 years ago

My main reasoning for most of my opinions is to perhaps build the core of this software in away that isn't strictly locked down to D&D 5e (If we design the core well we could have the option to expand in the future), as well as db / class structure that has minimal duplicate logic.

G-Bro commented 4 years ago

Tabletop games are so complex and varied though that I don't think we can make a single system that works for two distinct games, if that's what you are suggesting. I really don't like the idea of storing logic in the database either, or formulas for logic. The more I think about it the less on board I am with this modifiers plan.

devan1011 commented 4 years ago

Ok up to you. Did you see what I put in slack? It's not really logic in the db more an address to some data on a model.

devan1011 commented 4 years ago

If this is my data (Would be in db ofc): image

This returns 14 which should be the ac if this was medium armour image

Where the bit in the middle would be something like this on the Modifier model image

More validation ofc

G-Bro commented 4 years ago

My alternative proposal would work like so:

Say you have a ring that grants +1 AC (ring of protection)

You could have a ring table, and a stats table. A join table from ring to stats would contain a pivot field called bonus.

So in this case the ring would have a structure along the lines of:

[
    'name' => 'Ring of Protection',
    'stat_modifiers' => [
        0 => [
            'code' => 'armor_class',
            'pivot' => [
                'bonus' => 1
            ]
        ]
    ]
]

then to apply those modifiers:

foreach ($character->rings as $ring) {
    foreach ($ring->stat_modifiers as $modifier) {
        $character->[$modifier->code] += $modifier->pivot->bonus;
    }
}
devan1011 commented 4 years ago

And in my case it'd look something like:

[
   'name' => 'Ring of Protection',
   'type' => 'ring',
   'modifiers' => [
     [
       'type' => 'stat',
       'name' => 'ac',
       'value' => 1,
     ]
   ],
]

Then to apply you'd do

function getAc() {
    return $this->base_ac + $this->active_items
        ->pluck('modifiers')
        ->where('type', 'stat')
        ->where('name', 'ac')
        ->sum('value');
}

I honestly think more generalised mods are the way to go but it's your project (And you're not shit at D&D) so your decision.

G-Bro commented 4 years ago

Yeah, looks like we had very similar plans after all. What would you propose the DB structure to be in your system? Because you have 'value' which can be numeric or a dot-notation string.

Perhaps it could be something like:

id skill_id bonus skill_modifier_id max min
1 6 (AC) 4 4 (DEX) 14 0

so then the logic becomes:

$character->[$modifer->code] += $modifier->pivot->bonus;
$character->[$modifer->code] += $character->[$modifier->pivot->skill_modifier->code];

$character->[$modifier->code] = clamp(current, $modifier->min, $modifier->max);

because there are several instances in DnD 5e where you apply modifiers that are +(n) + (ability modifier)

devan1011 commented 4 years ago

The cases where it relies on x attribute of the character I used to dot notation to define it. And like in the armour case I posted above you have two mods, one applies the base ac and the second applies the dex bonus. To me it seems like it worked but I can't be sure.

devan1011 commented 4 years ago

So in a case where that ring would apply a base ac of 1 and a bonus of the characters dex to a max of 4, it'd look like so

[
   'name' => 'Ring of Protection',
   'type' => 'ring',
   'modifiers' => [
     [
       'type' => 'stat',
       'name' => 'ac',
       'value' => 1,
     ],
     [
       'type' => 'stat',
       'name' => 'ac',
       'value' => 'character.skills.dex',
       'max' => 4,
     ]
   ],
]

Then to apply you'd do

function getAc() {
    return $this->base_ac + $this->active_items
        ->pluck('modifiers')
        ->where('type', 'stat')
        ->where('name', 'ac')
        ->sum('value');
}

As the ->sum('value') would go through the getter you wouldn't have to worry about the dot notation logic.

And if there is no character attached to the item ofc it'd default to 0

Db struct as described here maybe minus the ModifierType table.

ghost commented 4 years ago

When your side project looks more legit than your salaried job...

devan1011 commented 4 years ago

Yeah how much are you paying us @G-Bro ?

G-Bro commented 4 years ago

I might let you use it