0

I'm trying to build a react app that exports a DnD 5e character sheet. There are different bonuses based on your selected race/species. I have a dropdown menu to select your race and I want to apply the bonus to the appropriate stat. The problem is that if I then select a different option it doesn't revert the stats. So if I click "Orc" I get a +1 to strength, but if I change it to "Elf", I get a +1 to intelligence but the +1 to strength sticks around and going back to "Orc" adds another +1 to strength. Any advice on setting these conditional bonuses?

Here is the function that assigns the stat values

    <div>
          {standardArray.map((stat, index) => {
            return (
              <div key={index}>
                <Text marginLeft={5}> {stat.name[index]}</Text>
                <Select
                  placeholder={stat.name[index]}
                  width="90%"
                  marginLeft={3}
                  marginBottom={3}
                  onChange={handleChange}
                  name={"playerStat" + [index]}
                >
                  Name: {stat.name}
                  {stat.value.map((value, index) => {
                    return (
                      <option key={index} value={value}>
                        {value}
                      </option>
                    );
                  })}
                </Select>
              </div>
            );
          })}
        </div>

This is the dropdown menu that calls the bonus function

    <Select
          placeholder="Choose a Species"
          color={"White"}
          marginLeft={3}
          marginRight={3}
          width="90%"
          onChange={handleSpeciesChange}
          value={state.playerSpecies}
          name="playerSpecies"
        >
          <option value="Orc">Orc</option>
          <option value="Elf">Elf</option>
          <option value="Human">Human</option>
        </Select>

This is the function that applies the bonus

  const speciesBonus = (value: string) => {
    if (value === "Orc") {
      const speciesBonus = 1;
      state.playerStat0 = parseInt(state.playerStat0) + speciesBonus;
    }
    if (value === "Elf") {
      const speciesBonus = 1;
      state.playerStat3 = parseInt(state.playerStat3) + speciesBonus;
    } else {
      state.playerStat0 = parseInt(state.playerStat0);
    }
  };


  [1]: https://i.sstatic.net/Ia3mceWk.png
  [2]: https://i.sstatic.net/Yjdc48hx.png
  [3]: https://i.sstatic.net/ICMR3tWk.png
3
  • 1
    Please edit your question and provide the code as text. Commented Sep 24, 2024 at 19:24
  • Okay I added all of what I think is the relevant code Commented Sep 24, 2024 at 19:36
  • As text, so it can be copied, modified, pasted into an answer. Can't do that with images. Commented Sep 24, 2024 at 19:37

2 Answers 2

0

I'm going to answer from a RPG perspective, as much as from a tech perspective.

Species selection impacts more than just base stats. You're going to want a record of which specie the character belongs to long-term, for things like racial abilities, or for some wild situations like Reincarnate.

Instead of directly updating the character's stats, add the selected specie as a data field that you store itself. Then use something similar your speciesBonus to determine the correct value to display for each stat, without actually updating it on the state.

As a side effect, doing this will solve your tech issue.

For completeness, though, your issue stems from the fact that your speciesBonus function only applies the new species bonus. If you wanted to update it with this same structure, you would need to change speciesBonus signature to accept both a current and previous species, so you could "undo" the previous selection's benefits.

Sign up to request clarification or add additional context in comments.

Comments

0

You could try to store the species bonuses in an object with key: speciesName, value: bonusesArray

const bonuses = {
  Orc: [1,0,0,0,0,-2],
  Elf: [0,1,0,0,0,0],
  // etc
};

Each time the user selects a species, you are going to:

  • check if a species was previously assigned. If so, remove the bonus for the old species
  • get the new species, and apply the bonus

For this you will need a state variable like "currentSelectedSpecies" to store the currently selected species.

I modified handleSpeciesChange to do that. I tried to only call setState once, so I got rid of the separate function.

Warning. I’ve not used setState before and none of this code is tested.

const handleSpeciesChange = (e) => {
  const {value} = e.target;
  const lastValue = state.currentSelectedSpecies;

  if (lastValue === value) return;

  // get current playerAttributes from state
  const attrs = ["0","1","2","3","4","5"].map(v => state[`playerAttribute${v}`]);

  // only remove the last species bonuses if one was picked
  if (lastValue) {
    lastBonuses = bonuses[lastValue];
    lastBonuses.forEach((b, i) => attrs[i] -= b);
  }
  
  newBonuses = bonuses[value];
  newBonuses.forEach((b, i) => attrs[i] += b);

  setState(prevState => ({
    ...prevState,
    playerAttribute0: attrs[0],
    playerAttribute1: attrs[1],
    playerAttribute2: attrs[2],
    playerAttribute3: attrs[3],
    playerAttribute4: attrs[4],
    playerAttribute5: attrs[5],
    currentSelectedSpecies: value
  }));
};

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.