loading...

Day 17 [D&D Character Sheet]

approachingapathy profile image Ephriam Henderson ・3 min read

Report

Today I finished the character sheet page, It will probably change in the future but this is good to continue development with.
Alt Text
I still need to add saving throws to the skills section. There are also places where data doesn't exist in the database yet. I'm happy enough that I consider it pretty far along to my first requirement.

After I finished that I worked on something else that interested me.
Alt Text
Alt Text
The character Writer will be a utility to help players think about character backstories. It will ask questions about a character appearance, personality, and history providing a few preselected choices and custom inputs (soon™). Eventually I'd like to be be able to save or output those choices somehow, far down the road they could even be used to provide suggestions for mechanical character building like selecting a class, and distributing stats.

Here's some front end code.

<div class="col-md bg-info d-flex h-100">
    <div class="d-flex align-items-center justify-content-center w-100">
        <div id="writer-container" class="d-flex flex-column">
            <h1 id="writer-question" class="text-center">
                Welcome to The Character Writer
            </h1>
            <br />
            <div id="writer-options" class="d-flex justify-content-around"></div>
            <div class="d-flex justify-content-around">
                <button id="prev-button" class="btn" hidden>Previous</button>
                <button id="next-button" class="btn">Next</button>
            </div>
        </div>
    </div>
</div>

The Writer class is the controller for this page. I use a class to interact with the writer page to keep the code contained and separate from any other logic I may write. The Writer functionality is stored in one object. This keeps code organized and the global scope clean.

class Writer {
            constructor(init) {
                this.$container = $("#writer-container");
                this.page = -1;
                this.$question = $("#writer-question");
                this.$options = $("#writer-options");
                this.questions = init.questions || [];
                this.choices = {};
                $("#next-button").on("click", e => this.advance());
                $("#prev-button").on("click", e => this.reverse());
                $("#writer-options").on("click", e => {
                    const $target = $(e.target);
                    if ($target.prop("tagName") == "BUTTON") {
                        this.choices[$target.attr("data-question")] = $target.attr(
                            "data-choice"
                        );
                        this.advance();
                    }
                    console.log(this.choices);
                });
            }

            _createOptionButtons() {
                return this.questions[this.page].options.map((option, index) => {
                    return $("<button>")
                        .addClass("btn myOption")
                        .attr("id", `option-${index}`)
                        .attr("data-choice", index)
                        .attr("data-question", this.page)
                        .text(option.text);
                });
            }

            advance() {
                console.log("Start");
                if (this.page < this.questions.length - 1) {
                    this.page++;
                    this.$container.attr("data-page", this.page);
                    this.$question.text(this.questions[this.page].question);
                    this.$options.empty();
                    let optionButtons = this._createOptionButtons();
                    this.$options.append(optionButtons);
                    if (this.page > 0) $("#prev-button").removeAttr("hidden");
                    if (this.page >= this.questions.length - 1)
                        $("#next-button").attr("hidden", true);
                }
            }

            reverse() {
                if (this.page > 0) {
                    this.page--;
                    this.$container.attr("data-page", this.page);
                    this.$question.text(this.questions[this.page].question);
                    this.$options.empty();
                    let optionButtons = this._createOptionButtons();
                    this.$options.append(optionButtons);
                    if (this.page < 1) $("#prev-button").attr("hidden", true);
                    if (this.page < this.questions.length - 1)
                        $("#next-button").removeAttr("hidden");
                }
            }
        }

I could improve this by refactoring the reverse and advance methods to move the repeated code into its own method. The code below could be moved into a new method that advance and reverse could call. I could also keep the nav buttons on the object rather than retrieving them from the DOM each time.

this.$container.attr("data-page", this.page);
this.$question.text(this.questions[this.page].question);
this.$options.empty();
let optionButtons = this._createOptionButtons();
this.$options.append(optionButtons);

Project

[100days] The DND Character Sheet App

This is the first project of my 100 days of coding This is an app to keep D&D character sheets.

Stack

I'll be using Node.js and building a full-stack Express app with MongoDB.

Requirements

Minimum Viable

  • Present a D&D Character Sheet
    • The sheet should display all the same info as the first page of the 5e Official sheet.
  • Users should be able to log in and create player-characters.
  • Users should be able to edit character sheets.
  • Users should be able to organize character sheets into groups (parties/tables)
  • Sheets should auto calculate basic stats like ability modifiers
    • Support Proficiency Bonuses

Cake

  • Extend character creation to allow the user to use any of the three common stat gen methods
    • Point Buy
    • Standard Array
    • Roll
  • Extend the character sheet to all the info in the 5e official sheet.
  • Allow for image uploads for character portraits.
  • Allow for…

The First project will be an app to keep D&D character sheets.

Stack

I'll be using Node.js and building a full-stack Express app with MongoDB.

Requirements

Minimum Viable

  • [ ] Investigate automating or finding a source of info for the data in the SRD.
  • [X] Present a D&D Character Sheet
    • [ ] The sheet should display all the same info as the first page of the 5e Official sheet.
  • [ ] Users should be able to log in and create player-characters.
  • [ ] Users should be able to edit character sheets.
  • [ ] Users should be able to organize character sheets into groups (parties/tables)
  • [ ] Sheets should auto calculate basic stats like ability modifiers.
    • [ ] Support Proficiency Bonuses

Cake

  • [ ] Extend character creation to allow the user to use any of the three common stat gen methods.
    • [ ] Point Buy
    • [ ] Standard Array
    • [ ] Roll
  • [ ] Extend the character sheet to all the info in the 5e official sheet.
  • [ ] Allow for image uploads for character portraits.
  • [ ] Allow for extended descriptions/backstories.
    • [ ] Characters should have nice full page backstories.
    • [ ] Preferably use a markdown editor.

Posted on by:

approachingapathy profile

Ephriam Henderson

@approachingapathy

I'm a Full-Stack Developer and recent Bootcamp Graduate. I'm most experienced with JavaScript, but I'm a python enthusiast and an all-around nerd. When I'm not coding I love anime, sci-fi, d&d.

Discussion

pic
Editor guide