updated to gradle project framework

This commit is contained in:
Josh Ashton
2023-05-01 14:43:37 -06:00
parent f4fcae1a16
commit c176832473
102 changed files with 654 additions and 201 deletions
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1682969422631</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
@@ -0,0 +1,2 @@
connection.project.dir=..
eclipse.preferences.version=1
+4
View File
@@ -0,0 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.source=17
+45
View File
@@ -0,0 +1,45 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/8.1.1/userguide/building_java_projects.html
* This project uses @Incubating APIs which are subject to change.
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:31.1-jre'
}
testing {
suites {
// Configure the built-in test suite
test {
// Use JUnit Jupiter test framework
useJUnitJupiter('5.9.1')
}
}
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
application {
// Define the main class for the application.
mainClass = 'dnd.App'
}
+13
View File
@@ -0,0 +1,13 @@
package dnd;
public class App {
public static void main(String[] args) {
GUImanager gui = new GUImanager();
gui.setVisible(true);
}
}
+37
View File
@@ -0,0 +1,37 @@
package dnd;
import java.awt.*;
public final class AppConstants {
private AppConstants() {}
// CONSTANTS FOR FILE MANAGEMENT.
public static final String OS = System.getProperty("os.name");
public static final String mainFilepath = System.getProperty("user.dir");
public static final String imgFilepath = System.getProperty("user.dir") + "/src/main/resources/img/";
public static final String fontFilepath = System.getProperty("user.dir") + "/src/main/resources/SanSalvi.ttf";
public static final String savesFilepath = System.getProperty("user.home") + "/Documents/saves";
// CONSTANTS FOR THEME.
public static final Color lightAccent = Color.decode("#EAF0CE");
public static final Color lightBrown = Color.decode("#EBBE9B");
public static final Color medBrown = Color.decode("#E4A677");
public static final Color darkBrown = Color.decode("#502419");
public static final Color darkestBrown = Color.decode("#1F0E0A");
public static final Color black = Color.BLACK;
public static final Font headerFont = new Font("SanSalvi", Font.BOLD, 45);
public static final Font subHeaderFont = new Font("SanSalvi", Font.PLAIN, 35);
public static final Font paragraphText = new Font("SanSalvi", Font.PLAIN, 20);
public static final Font userText = new Font("SanSalvi", Font.PLAIN, 15);
public static final Font buttonFont = new Font("SanSalvi", Font.PLAIN, 15);
}
+154
View File
@@ -0,0 +1,154 @@
package dnd;
public class Background {
int backgroundIndex;
private String name;
private boolean[] proficientStatus;
private String[] skills;
private String feature;
private String skillProficiencies;
/**
* @param name
* @param feature
*/
public Background(String name, boolean[] proficientStatus, String[] skills, String feature) {
this.name = name;
this.proficientStatus = proficientStatus;
this.skills = skills;
this.feature = feature;
skillProficiencies = null;
}
public void setAcolyte() {
name = "Acolyte";
proficientStatus[5] = true;
proficientStatus[14] = true;
skillProficiencies = skills[5] + ", " + skills[14];
feature = "Shelter of the Faithful" + "\nAs an acolyte, you command the respect of those who share your faith, and you can perform the religious ceremonies of your deity. You and your adventuring companions can expect to receive free healing and care at a temple, shrine, or other established presence of your faith, though you must provide any material components needed for spells. Those who share your religion will support you (but only you) at a modest lifestyle."
+ "\nYou might also have ties to a specific temple dedicated to your chosen deity or pantheon, and you have a residence there. This could be the temple where you used to serve, if you remain on good terms with it, or a temple where you have found a new home. While near your temple, you can call upon the priests for assistance, provided the assistance you ask for is not hazardous and you remain in good standing with your temple.";
}
public void setCharlatan() {
name = "Charlatan";
proficientStatus[4] = true;
proficientStatus[15] = true;
skillProficiencies = skills[4] + ", " + skills[15];
feature = "False Identity" + "\nYou have created a second identity that includes documentation, established acquaintances, and disguises that allow you to assume that persona. Additionally, you can forge documents including official papers and personal letters, as long as you have seen an example of the kind of document or the handwriting you are trying to copy.";
}
public void setCriminal() {
name = "Criminal";
proficientStatus[4] = true;
proficientStatus[16] = true;
skillProficiencies = skills[4] + ", " + skills[16];
feature = "Feature: Criminal Contact" + "\nYou have a reliable and trustworthy contact who acts as your liaison to a network of other criminals. You know how to get messages to and from your contact, even over great distances; specifically, you know the local messengers, corrupt caravan masters, and seedy sailors who can deliver messages for you.";
}
public void setSpy() {
name = "Spy";
proficientStatus[4] = true;
proficientStatus[16] = true;
skillProficiencies = skills[4] + ", " + skills[16];
feature = "Criminal Contact" + "\nYou have a reliable and trustworthy contact who acts as your liaison to a network of other criminals. You know how to get messages to and from your contact, even over great distances; specifically, you know the local messengers, corrupt caravan masters, and seedy sailors who can deliver messages for you.";
}
public void setEntertainer() {
name = "Entertainer";
proficientStatus[0] = true;
proficientStatus[12] = true;
skillProficiencies = skills[0] + ", " + skills[12];
feature = "By Popular Demand" + "\nYou can always find a place to perform, usually in an inn or tavern but possibly with a circus, at a theater, or even in a noble's court. At such a place, you receive free lodging and food of a modest or comfortable standard (depending on the quality of the establishment), as long as you perform each night. In addition, your performance makes you something of a local figure. When strangers recognize you in a town where you have performed, they typically take a liking to you.";
}
public void setFolkHero() {
name = "Folk Hero";
proficientStatus[1] = true;
proficientStatus[17] = true;
skillProficiencies = skills[1] + ", " + skills[17];
feature = "Rustic Hospitality" + "\nSince you come from the ranks of the common folk, you fit in among them with ease. You can find a place to hide, rest, or recuperate among other commoners, unless you have shown yourself to be a danger to them. They will shield you from the law or anyone else searching for you, though they will not risk their lives for you.";
}
public void setGladiator() {
name = "Gladiator";
proficientStatus[0] = true;
proficientStatus[12] = true;
skillProficiencies = skills[0] + ", " + skills[12];
feature = "By Popular Demand" + "\nYou can always find a place to perform in any place that features combat for entertainment — perhaps a gladiatorial arena or secret pit fighting club. At such a place, you receive free lodging and food of a modest or comfortable standard (depending on the quality of the establishment), as long as you perform each night. In addition, your performance makes you something of a local figure. When strangers recognize you in a town where you have performed, they typically take a liking to you.";
}
public void setGuildArtisan() {
name = "Guild Artisan";
proficientStatus[6] = true;
proficientStatus[13] = true;
skillProficiencies = skills[6] + ", " + skills[13];
feature = "Guild Membership" + "\nAs an established and respected member of a guild, you can rely on certain benefits that membership provides. Your fellow guild members will provide you with lodging and food if necessary, and pay for your funeral if needed. In some cities and towns, a guildhall offers a central place to meet other members of your profession, which can be a good place to meet potential patrons, allies, or hirelings."
+ "\nGuilds often wield tremendous political power. If you are accused of a crime, your guild will support you if a good case can be made for your innocence or the crime is justifiable. You can also gain access to powerful political figures through the guild, if you are a member in good standing. Such connections might require the donation of money or magic items to the guilds coffers."
+ "\nYou must pay dues of 5 gp per month to the guild. If you miss payments, you must make up back dues to remain in the guilds good graces.";
}
public void setGuildMerchant() {
name = "Guild Merchant";
proficientStatus[6] = true;
proficientStatus[13] = true;
skillProficiencies = skills[6] + ", " + skills[13];
feature = "Guild Membership" + "\nAs an established and respected member of a guild, you can rely on certain benefits that membership provides. Your fellow guild members will provide you with lodging and food if necessary, and pay for your funeral if needed. In some cities and towns, a guildhall offers a central place to meet other members of your profession, which can be a good place to meet potential patrons, allies, or hirelings."
+ "\nGuilds often wield tremendous political power. If you are accused of a crime, your guild will support you if a good case can be made for your innocence or the crime is justifiable. You can also gain access to powerful political figures through the guild, if you are a member in good standing. Such connections might require the donation of money or magic items to the guilds coffers."
+ "\nYou must pay dues of 5 gp per month to the guild. If you miss payments, you must make up back dues to remain in the guilds good graces.";
}
public void setGuildHermit() {
name = "Hermit";
proficientStatus[9] = true;
proficientStatus[14] = true;
skillProficiencies = skills[9] + ", " + skills[14];
feature = "Discovery" + "\nThe quiet seclusion of your extended hermitage gave you access to a unique and powerful discovery. The exact nature of this revelation depends on the nature of your seclusion. It might be a great truth about the cosmos, the deities, the powerful beings of the outer planes, or the forces of nature. It could be a site that no one else has ever seen. You might have uncovered a fact that has long been forgotten, or unearthed some relic of the past that could rewrite history. It might be information that would be damaging to the people who consigned you to exile, and hence the reason for your return to society."
+ "\nWork with your DM to determine the details of your discovery and its impact on the campaign.";
}
public void setKnight() {
name = "Knight";
proficientStatus[5] = true;
proficientStatus[11] = true;
skillProficiencies = skills[5] + ", " + skills[11];
feature = "Retainers" + "\nYou have the service of three retainers loyal to your family. These retainers can be attendants or messengers, and one might be a majordomo. Your retainers are commoners who can perform mundane tasks for you, but they do not fight for you, will not follow you into obviously dangerous areas (such as dungeons), and will leave if they are frequently endangered or abused.";
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the skillProficiencies
*/
public String getskillProficiences() {
return skillProficiencies;
}
/**
* @return the feature
*/
public String getDescription() {
return feature;
}
/**
* @return the proficientStatus
*/
public boolean[] getProficientStatus() {
return proficientStatus;
}
@Override
public String toString() {
return "Background: " + name + "\nSkill Proficiencies: " + skillProficiencies + "\nFeature: "
+ feature;
}
}
+91
View File
@@ -0,0 +1,91 @@
package dnd;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import static dnd.AppConstants.*;
public class BasicNavPanel extends JPanel {
private DefaultButton backButton;
private DefaultButton continueButton;
private int continueRequirement;
public BasicNavPanel(DefaultButton backButton, DefaultButton continueButton, int continueRequirement) {
super(new GridLayout(1, 2, 30, 0));
this.backButton = backButton;
if(continueButton == null) {
this.continueButton = null;
} else {
this.continueButton = continueButton;
}
this.continueRequirement = continueRequirement;
createNavPanel();
}
public int getContinueRequirement() {
return continueRequirement;
}
public void decreaseContinueRequirement(int value) {
continueRequirement -= value;
updateContinueRequirement();
}
public void increaseContinueRequirement(int value) {
continueRequirement += value;
updateContinueRequirement();
}
private void updateContinueRequirement() {
removeAll();
createNavPanel();
}
private void createNavPanel() {
setBackground(darkestBrown);
setBorder(new EmptyBorder(15, 150, 15, 150));
add(backButton);
if (continueRequirement == 0) {
if(continueButton != null) {
add(continueButton);
}
} else {
DefaultButton requiredStepsNeeds = new DefaultButton(Integer.toString(continueRequirement) + " Points Left");
requiredStepsNeeds.select();
requiredStepsNeeds.setBorder(new LineBorder(lightAccent, 1));
requiredStepsNeeds.setBorderPainted(true);
requiredStepsNeeds.setEnabled(false);
add(requiredStepsNeeds);
}
}
}
+170
View File
@@ -0,0 +1,170 @@
package dnd;
import javax.swing.*;
import java.awt.*;
import static dnd.AppConstants.*;
import static dnd.ImageManager.*;
public class BasicPanel extends JPanel {
private DefaultButton[] optionButtons;
private String[] options;
private InfoPanel infoPanel;
private int choiceIndex;
private String panelTitle;
private ImageManager images;
private int currentPanel;
public BasicPanel(JPanel navPanel, String[] options, String[] descriptions, String panelTitle, ImageManager images) {
super();
this.options = options;
this.panelTitle = panelTitle;
Rectangle[] basicBounds = new Rectangle[]{
new Rectangle(5, 5, 600, 400), // ImageInfo panel
new Rectangle(275, 10, 300, 35), // ImageInfo subheader
new Rectangle(275, 45, 300, 355), // ImageInfo text
new Rectangle(10, 45, 250, 355)
};
this.images = images;
infoPanel = new InfoPanel(options, descriptions, basicBounds, images);
currentPanel = Integer.parseInt(Character.toString(panelTitle.charAt(5)));
System.out.println("CurrentPanel: " + currentPanel);
choiceIndex = 0;
panelSetup();
createMasterPanel();
infoPanel.updateInfo(choiceIndex, getNextPortrait(choiceIndex));
add(navPanel, BorderLayout.SOUTH);
}
private JLabel getNextPortrait(int index) {
JLabel nextPortrait;
if(currentPanel == 1) {
nextPortrait = images.getRacePortrait(index);
System.out.println("next portrait for race.");
} else if(currentPanel == 2) {
nextPortrait = images.getClassPortrait(index);
System.out.println("next portrait for class.");
} else {
System.out.println("Returning null.");
nextPortrait = null;
}
return nextPortrait;
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private void createMasterPanel() {
JLabel title = new JLabel(panelTitle);
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
add(title, BorderLayout.NORTH);
JPanel panel = new JPanel();
panel.setOpaque(false);
panel.setLayout(null);
panel.add(infoPanel);
panel.add(createButtonPanel());
add(panel);
}
private JPanel createButtonPanel() {
JPanel buttonPanel = new JPanel(new GridLayout(options.length, 1, 0, 0));
buttonPanel.setBackground(lightBrown);
buttonPanel.setBounds(585, 45, 135, 355);
optionButtons = new DefaultButton[options.length];
for (int i = 0; i < optionButtons.length; i++) {
optionButtons[i] = createButton(options[i], i);
if (i == 0) {
optionButtons[i].select();
}
}
for (int i = 0; i < options.length; i++) {
buttonPanel.add(optionButtons[i]);
}
return buttonPanel;
}
private DefaultButton createButton(String holderName, int index) {
DefaultButton button = new DefaultButton(holderName);
button.addActionListener(e -> {
updateButtons(index);
});
return button;
}
private void updateButtons(int newIndex) {
optionButtons[choiceIndex].deSelect();
optionButtons[newIndex].select();
choiceIndex = newIndex;
if(currentPanel == 1 || currentPanel == 2) {
infoPanel.updateInfo(choiceIndex, getNextPortrait(choiceIndex));
} else {
System.out.println("No image chosen.");
infoPanel.updateInfo(choiceIndex);
}
}
public int getChoice() {
return choiceIndex;
}
}
+138
View File
@@ -0,0 +1,138 @@
package dnd;
import java.io.Serializable;
import dnd.species.*;
public class CharacterSheet implements Serializable {
private String name;
private int age;
private int heightFeet;
private int heightInch;
private int weight;
private String eyeColor;
private String hairColor;
private Race race;
private ClassTemplate chClass;
private String[] spells;
private String[] equipment;
private String alignment;
private String background;
private CharacterStats stats;
/*
* TODO: Need to add the following variables:
*
* - CharacterClass x1 var
* - ChosenSpells xN vars
* - Equipment xN vars
* - Description x3 vars
*
* TOTAL: Minimum 12, + N spells and N equipment
*
*/
public CharacterSheet(
String name,
int age,
int heightFeet,
int heightInch,
int weight,
String eyeColor,
String hairColor,
Race race,
ClassTemplate chClass,
String alignment,
String background,
CharacterStats stats
) {
this.name = name;
this.age = age;
this.heightFeet = heightFeet;
this.heightInch = heightInch;
this.weight = weight;
this.eyeColor = eyeColor;
this.hairColor = hairColor;
this.race = race;
this.chClass = chClass;
this.alignment = alignment;
this.background = background;
this.stats = stats;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getHeightFeet() {
return heightFeet;
}
public int getHeightInch() {
return heightInch;
}
public int getWeight() {
return weight;
}
public String getEyeColor() {
return eyeColor;
}
public String getHairColor() {
return hairColor;
}
public Race getRace() {
return race;
}
public ClassTemplate getCharacterClass() {
return chClass;
}
public CharacterStats getStats() {
return stats;
}
@Override
public String toString() {
String output = "Character name: " + name + "\nAge: " + age + "\nHeight: " + heightFeet + "\'" + heightInch + "\"" + "\nWeight: " + weight + "\nEye Color: " + eyeColor + "\nHair Color: " + hairColor + "\nRace: " + race.toString() + "\nClass: " + chClass.toString() + "\nStats: " + stats.toString();
return output;
}
}
+83
View File
@@ -0,0 +1,83 @@
package dnd;
import java.io.Serializable;
public class CharacterStats implements Serializable {
private Stats[] stats;
public CharacterStats() {
stats = new Stats[]{};
}
// TODO: Need to implement constructor, validates all proposed ability scores and creates new objects containing corresponding values.
public CharacterStats(int str, int dex, int con, int intel, int wis, int cha) {
this.stats = new Stats[]{
new Strength(str),
new Dexterity(dex),
new Constitution(con),
new Intelligence(intel),
new Wisdom(wis),
new Charisma(cha)
};
}
public CharacterStats(Strength str, Dexterity dex, Constitution con, Intelligence intel, Wisdom wis, Charisma cha) {
this.stats = new Stats[]{str, dex, con, intel, wis, cha};
}
// TODO: Need to implement ability score validation.
public boolean validateAbilityScore(int abilityScore) {
return false;
}
public Stats[] getStats() {
return stats;
}
/**
* Allows for access to a particular stat.
*
* @param index
* @return a specific stat
*/
public Stats getStats(int index) {
return stats[index];
}
public void increaseStat(int targetStat) {
stats[targetStat].increaseScore();
}
@Override
public String toString() {
String statsString = "";
for (int i = 0; i < stats.length; i++) {
statsString = statsString.concat(stats[i].getClass().getSimpleName() + ": " + stats[i].getScore() + " | ");
}
return statsString;
}
}
+57
View File
@@ -0,0 +1,57 @@
package dnd;
import java.io.Serializable;
public class Charisma extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Charisma(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
// TODO: Need description.
public String getDescription() {
return "Confidence, eloquence, and leadership.";
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
@@ -0,0 +1,235 @@
package dnd;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import static dnd.AppConstants.*;
public class ChooseAbilityScoresPanel extends JPanel {
private DefaultButton[] statInfoButtons;
private JLabel[] statLabels;
private String[] statOptions;
private InfoPanel infoPanel;
private BasicNavPanel basicNavPanel;
private int[] selectedStats;
private int selectedStatIndex;
public ChooseAbilityScoresPanel(BasicNavPanel basicNavPanel, String[] statOptions, String[] statDescriptions, int[] selectedStats, String panelTitle) {
super();
panelSetup();
this.statOptions = statOptions;
this.selectedStats = selectedStats;
this.statInfoButtons = new DefaultButton[statOptions.length];
statLabels = new JLabel[statOptions.length];
this.basicNavPanel = basicNavPanel;
Rectangle[] abilityScoreBounds = {
new Rectangle(520, 5, 200, 400), // ImageInfo panel
new Rectangle(5, 10, 200, 35), // ImageInfo subheader
new Rectangle(5, 45, 200, 355) // ImageInfo text
};
infoPanel = new InfoPanel(statOptions, statDescriptions, abilityScoreBounds);
infoPanel.updateInfo(0); // Default start with 0th element.
createMasterPanel(panelTitle);
add(basicNavPanel, BorderLayout.SOUTH);
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private void createMasterPanel(String panelTitle) {
JLabel title = new JLabel(panelTitle);
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
add(title, BorderLayout.NORTH);
JPanel panel = new JPanel();
panel.setOpaque(false);
panel.setLayout(null);
panel.add(createAbilityScorePanels());
panel.add(infoPanel);
add(panel);
}
private JPanel createAbilityScorePanels() {
JPanel mainAbilityPanel = new JPanel();
mainAbilityPanel.setBounds(5, 5, 505, 405);
mainAbilityPanel.setLayout(new GridLayout(2, 3, 10, 10));
mainAbilityPanel.setBackground(lightBrown);
for (int i = 0; i < statOptions.length; i++) {
mainAbilityPanel.add(createAbilityPanel(statOptions[i], i));
}
return mainAbilityPanel;
}
private JPanel createAbilityPanel(String ability, int statIndex) {
JPanel panel = new JPanel();
panel.setFont(paragraphText);
panel.setBackground(medBrown);
panel.setBorder(new LineBorder(darkestBrown, 4, true));
panel.setLayout(new BorderLayout(0, 0));
DefaultButton tmpButton = new DefaultButton(ability);
tmpButton.setFont(paragraphText);
tmpButton.setHorizontalAlignment(SwingConstants.CENTER);
tmpButton.addActionListener(e -> updateButtons(statIndex));
statInfoButtons[statIndex] = tmpButton;
panel.add(statInfoButtons[statIndex], BorderLayout.NORTH);
panel.add(createScorePanel(statIndex));
return panel;
}
private JPanel createScorePanel(int statIndex) {
JPanel subPanel = new JPanel();
JLabel scoreLabel = new JLabel("" + selectedStats[statIndex]);
scoreLabel.setFont(paragraphText);
scoreLabel.setHorizontalAlignment(SwingConstants.CENTER);
statLabels[statIndex] = scoreLabel;
DefaultButton increaseButton = new DefaultButton("+");
increaseButton.addActionListener(e -> increase(statIndex));
DefaultButton decreaseButton = new DefaultButton("-");
decreaseButton.addActionListener(e -> decrease(statIndex));
subPanel.add(decreaseButton);
subPanel.add(scoreLabel);
subPanel.add(increaseButton);
subPanel.setBackground(lightBrown);
return subPanel;
}
private int statCostCalculator(int statIndex, boolean isDecreasing) {
int cost = 0;
int currentStatValue = selectedStats[statIndex];
if (isDecreasing) {
if (currentStatValue <= 8) {
System.out.println("registered invalid decrease");
return -1;
}
if (currentStatValue < 14) {
cost = 1;
} else if (currentStatValue == 14 || currentStatValue == 15) {
cost = 2;
}
} else {
if (currentStatValue < 13) {
cost = 1;
} else if (currentStatValue == 13 || currentStatValue == 14) {
cost = 2;
} else {
System.out.println("registered invalid increase");
return -1;
}
}
return cost;
}
private void increase(int statIndex) {
int value = statCostCalculator(statIndex, false);
if (value == -1) {
return;
}
if (basicNavPanel.getContinueRequirement() - value >= 0) {
selectedStats[statIndex]++;
statLabels[statIndex].setText("" + selectedStats[statIndex]);
basicNavPanel.decreaseContinueRequirement(value);
}
}
private void decrease(int statIndex) {
int value = statCostCalculator(statIndex, true);
if (value == -1) {
return;
}
if (basicNavPanel.getContinueRequirement() + value <= 27) {
selectedStats[statIndex]--;
statLabels[statIndex].setText("" + selectedStats[statIndex]);
basicNavPanel.increaseContinueRequirement(value);
}
}
private void updateButtons(int newIndex) {
statInfoButtons[selectedStatIndex].deSelect();
statInfoButtons[newIndex].select();
selectedStatIndex = newIndex;
infoPanel.updateInfo(selectedStatIndex);
}
}
+37
View File
@@ -0,0 +1,37 @@
package dnd;
public interface ClassTemplate {
abstract String getDescription();
abstract String[] getProgression();
abstract String[] getClassFeatures();
abstract String getHitDie();
abstract int getHPatLv1();
abstract int getHPpastLv1();
abstract String[] getArmorProf();
abstract String[] getWeaponProf();
abstract String[] getToolProf();
abstract String[] getSavingThrows();
// TODO: Need to refresh on how saving throws work and how the character's class may impact a saving throw.
abstract String[] availableSkills();
abstract String[] startingEquipChoices();
abstract boolean advantageCheck(Stats abilityScore);
abstract boolean disadvantageCheck(Stats abilityScore);
// TODO: Spells and shit.
}
+90
View File
@@ -0,0 +1,90 @@
package dnd;
public class Cleric implements ClassTemplate {
private int HP;
private int level;
// TODO: This should be the type of die.
private int hitDie;
public Cleric(Stats[] stats, int level) {
}
// TODO: Need to figure out how to contain class progression information. Potentially a double String array, each row equals a level, each column a different thing. Should class features be a separate class, ie. BarbFeatures, BardFeatures, etc?
public String getDescription() {
// TODO Auto-generated method stub
return null;
}
public String[] getProgression() {
// TODO Auto-generated method stub
return null;
}
public String[] getClassFeatures() {
// TODO Auto-generated method stub
return null;
}
public String getHitDie() {
// TODO Auto-generated method stub
return null;
}
public int getHPatLv1() {
// TODO Auto-generated method stub
return 0;
}
public int getHPpastLv1() {
// TODO Auto-generated method stub
return 0;
}
public String[] getArmorProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getWeaponProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getToolProf() {
// TODO Auto-generated method stub
return null;
}
public String[] availableSkills() {
// TODO Auto-generated method stub
return null;
}
public String[] startingEquipChoices() {
// TODO Auto-generated method stub
return null;
}
public boolean advantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
public boolean disadvantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
@Override
public String[] getSavingThrows() {
// TODO Auto-generated method stub
return null;
}
}
+57
View File
@@ -0,0 +1,57 @@
package dnd;
import java.io.Serializable;
public class Constitution extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Constitution(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
// TODO: Need description.
public String getDescription() {
return "Health, stamina, vital force.";
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
+95
View File
@@ -0,0 +1,95 @@
package dnd;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import static dnd.AppConstants.*;
public class DefaultButton extends JButton {
private boolean selected;
public DefaultButton(String buttonLabel) {
super(buttonLabel);
applyDefaultButtonStyle();
applyCommon();
}
public void deSelect() {
selected = false;
applyDefaultButtonStyle();
}
public void select() {
selected = true;
applyFocusedButtonStyle();
}
private void applyDefaultButtonStyle() {
setBackground(medBrown);
setForeground(darkestBrown);
}
private void applyFocusedButtonStyle() {
setBackground(darkestBrown);
setForeground(lightAccent);
}
private void applyCommon() {
addMouseListener(
new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
applyFocusedButtonStyle();
}
@Override
public void mouseExited(MouseEvent e) {
if (!selected) {
applyDefaultButtonStyle();
}
}
}
);
setFocusPainted(false);
setFont(buttonFont);
setBorder(new EmptyBorder(3, 3, 3, 3));
repaint();
revalidate();
}
}
+300
View File
@@ -0,0 +1,300 @@
package dnd;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import static dnd.AppConstants.*;
public class DescriptionPanel extends JPanel {
private BasicNavPanel nav;
private String[] characteristics;
private String[] characteristicsHolder;
private String[] alignmentOptions;
private String[] alignmentDescriptions;
private String[] backgroundOptions;
private String[] backgroundDescriptions;
private String userBackground;
private DefaultButton[] alignmentButtons;
private DefaultButton[] backgroundButtons;
private int alignmentChoice;
private int backgroundChoice;
public DescriptionPanel(BasicNavPanel nav, String[] characteristics, String[] alignmentOptions, String[] alignmentDescriptions, String[] backgroundOptions, String[] backgroundDescriptions, String panelTitle) {
super();
this.nav = nav;
this.characteristics = characteristics;
this.alignmentOptions = alignmentOptions;
this.alignmentDescriptions = alignmentDescriptions;
this.backgroundOptions = backgroundOptions;
this.backgroundDescriptions = backgroundDescriptions;
panelSetup();
createPanel(panelTitle, nav);
}
public String[] getCharacteristics() {
return characteristics;
}
public int getAlignmentChoice() {
return alignmentChoice;
}
public int getBackgroundChoice() {
return backgroundChoice;
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
alignmentChoice = 0;
backgroundChoice = 0;
alignmentButtons = new DefaultButton[alignmentOptions.length];
backgroundButtons = new DefaultButton[backgroundOptions.length];
characteristicsHolder = new String[]{
"Name: ",
"Age: ",
"Height: ",
"Weight: ",
"Eyes: ",
"Hair: "
};
userBackground = "";
}
private void createPanel(String panelTitle, BasicNavPanel nav) {
add(createPanelTitle(panelTitle), BorderLayout.NORTH);
add(createBodyPanel(), BorderLayout.CENTER);
add(nav, BorderLayout.SOUTH);
}
private JLabel createPanelTitle(String panelTitle) {
JLabel title = new JLabel(panelTitle);
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
title.setBorder(new EmptyBorder(25, 25, 25, 25));
return title;
}
private JPanel createBodyPanel() {
JPanel bodyPanel = new JPanel(new GridBagLayout());
bodyPanel.setOpaque(false);
bodyPanel.add(createNamePanel());
bodyPanel.add(createFooterPanel());
return bodyPanel;
}
private JPanel createNamePanel() {
JPanel panel = new JPanel();
panel.setBackground(medBrown);
for (int i = 0; i < characteristicsHolder.length; i++) {
panel.add(createField(i));
}
return panel;
}
private JPanel createField(int index) {
JPanel panel = new JPanel();
panel.setOpaque(false);
JLabel label = new JLabel(characteristicsHolder[index]);
label.setFont(paragraphText);
label.setOpaque(false);
label.setForeground(darkestBrown);
JTextField field = new JTextField(10);
field.setFont(paragraphText);
field.setBackground(lightBrown);
field.setBorder(null);
panel.add(label);
panel.add(field);
return panel;
}
private JPanel createFooterPanel() {
JPanel panel = new JPanel(new GridLayout(1, 3));
panel.setOpaque(false);
panel.add(createSubPanel("Alignment"));
panel.add(createSubPanel("Background"));
panel.add(createTextBoxPanel());
return panel;
}
private JPanel createSubPanel(String labelName) {
JPanel panel = new JPanel(new BorderLayout(0, 0));
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
panel.setOpaque(false);
JLabel label = new JLabel(labelName);
label.setForeground(darkestBrown);
label.setFont(subHeaderFont);
label.setHorizontalAlignment(SwingConstants.CENTER);
JPanel innerPanel;
if(labelName.equals("Alignment")) {
innerPanel = new JPanel(new GridLayout(9, 1));
innerPanel.setOpaque(false);
createButtons(alignmentOptions, alignmentButtons, labelName);
for (int i = 0; i < alignmentButtons.length; i++) {
innerPanel.add(alignmentButtons[i]);
}
} else {
innerPanel = new JPanel(new GridLayout(9, 2));
innerPanel.setOpaque(false);
createButtons(backgroundOptions, backgroundButtons, labelName);
for (int i = 0; i < backgroundButtons.length; i++) {
innerPanel.add(backgroundButtons[i]);
}
}
panel.add(label);
panel.add(innerPanel);
return panel;
}
private JPanel createTextBoxPanel() {
JPanel panel = new JPanel(new BorderLayout(0, 0));
panel.setOpaque(false);
JLabel label = new JLabel("Enter a Description");
label.setFont(paragraphText);
label.setOpaque(false);
label.setForeground(darkestBrown);
JTextArea textArea = new JTextArea();
textArea.setForeground(darkestBrown);
textArea.setFont(userText);
textArea.setOpaque(false);
textArea.setBorder(new LineBorder(darkestBrown, 3));
panel.add(label);
panel.add(textArea);
return panel;
}
private void updateAlignmentButtons(int newIndex) {
alignmentButtons[alignmentChoice].deSelect();
alignmentButtons[newIndex].select();
alignmentChoice = newIndex;
}
private void updateBackgroundButtons(int newIndex) {
backgroundButtons[backgroundChoice].deSelect();
backgroundButtons[newIndex].select();
backgroundChoice = newIndex;
}
private void createButtons(String[] options, DefaultButton[] buttons, String type) {
boolean tmp = type.equals("Alignment");
for (int i = 0; i < options.length; i++) {
buttons[i] = createButton(options[i], tmp, i);
if(i == 0) {
buttons[i].select();
}
}
}
private DefaultButton createButton(String name, boolean isAlignmentElseBackground, int index) {
DefaultButton button = new DefaultButton(name);
if (isAlignmentElseBackground) {
button.addActionListener(e -> updateAlignmentButtons(index));
} else {
button.addActionListener(e -> updateBackgroundButtons(index));
}
return button;
}
}
+57
View File
@@ -0,0 +1,57 @@
package dnd;
import java.io.Serializable;
public class Dexterity extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Dexterity(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
// TODO: Need description.
public String getDescription() {
return "";
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
@@ -0,0 +1,63 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Character.Classes/Main.java to edit this template
*/
package dnd.DieRoller;
import javax.swing.*;
import java.util.Arrays;
public class DiceRoller {
public static void main(String[] args) {
JTextField diceNum = new JTextField();
JTextField diceMod = new JTextField();
String[] diceTypes = {"4", "6", "8", "10", "12", "20", "100"};
JComboBox diceSize = new JComboBox(diceTypes);
Object[] fields = {"Number of dice", diceNum, "Type of dice", diceSize, "Modifier", diceMod};
JOptionPane.showConfirmDialog(null, fields, "Dice Roller", JOptionPane.OK_CANCEL_OPTION);
int numberOfDice = Integer.parseInt(diceNum.getText());
int sizeOfDice = Integer.parseInt(diceSize.getSelectedItem().toString());
int modifier = Integer.parseInt(diceMod.getText());
int[] diceRolls = rollDice(numberOfDice, sizeOfDice);
int rollTotal = rollTotal(diceRolls, modifier);
String rollString = numberOfDice + "d" + sizeOfDice + modifierString(modifier) + "\nRolled: " + Arrays.toString(diceRolls) + "\nRoll Total";
if (modifier == 0)
rollString += ": " + rollTotal;
else
rollString += " with " + modifierString(modifier) + " modifier: " + rollTotal;
JOptionPane.showMessageDialog(null, rollString, "Dice Rolls", JOptionPane.INFORMATION_MESSAGE);
}
public static int[] rollDice(int numberOfDice, int sizeOfDice) {
int[] diceRolls = new int[numberOfDice];
for (int rolledDice = 0; rolledDice < diceRolls.length; rolledDice++) {
diceRolls[rolledDice] = (int) (Math.random() * sizeOfDice) + 1;
}
return diceRolls;
}
public static int rollTotal(int[] diceRolls, int modifier) {
int rollTotal = 0;
for (int index = 0; index < diceRolls.length; index++) {
rollTotal += diceRolls[index];
}
rollTotal += modifier;
return rollTotal;
}
public static String modifierString(int modifier) {
String modifierString = "";
if (modifier < 0)
modifierString += modifier;
if (modifier > 0)
modifierString += "+" + modifier;
return modifierString;
}
}
+99
View File
@@ -0,0 +1,99 @@
package dnd;
import java.io.Serializable;
public class Fighter implements ClassTemplate, Serializable {
private int HP;
private int level;
// TODO: This should be the type of die.
private int hitDie;
public Fighter() {
}
// TODO: Need to figure out how to contain class progression information. Potentially a double String array, each row equals a level, each column a different thing. Should class features be a separate class, ie. BarbFeatures, BardFeatures, etc?
public String getDescription() {
// TODO Auto-generated method stub
return null;
}
public String[] getProgression() {
// TODO Auto-generated method stub
return null;
}
public String[] getClassFeatures() {
// TODO Auto-generated method stub
return null;
}
public String getHitDie() {
// TODO Auto-generated method stub
return null;
}
public int getHPatLv1() {
// TODO Auto-generated method stub
return 0;
}
public int getHPpastLv1() {
// TODO Auto-generated method stub
return 0;
}
public String[] getArmorProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getWeaponProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getToolProf() {
// TODO Auto-generated method stub
return null;
}
public String[] availableSkills() {
// TODO Auto-generated method stub
return null;
}
public String[] startingEquipChoices() {
// TODO Auto-generated method stub
return null;
}
public boolean advantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
public boolean disadvantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
@Override
public String[] getSavingThrows() {
// TODO Auto-generated method stub
return null;
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
+100
View File
@@ -0,0 +1,100 @@
package dnd;
import java.awt.*;
import java.io.*;
import java.util.*;
import static dnd.AppConstants.*;
public class FileManager {
private String filepath;
private boolean returningUser;
private ArrayList<File> saveFiles;
private ArrayList<CharacterSheet> saves;
public FileManager() {
saveFiles = new ArrayList<>();
setSaveFiles();
loadFont();
}
public int getNumSaves() {
return saveFiles.size();
}
public boolean isReturningUser() {
return returningUser;
}
public CharacterSheet readSavedCharacter(int index) {
return readCharacter(saveFiles.get(index));
}
public void saveCharacter(CharacterSheet completedCharacter) {
writeCharacter(completedCharacter);
}
public ArrayList<CharacterSheet> getSaves() {
return saves;
}
// TODO: Need to implement.
public void deleteCharacter() {
}
private void loadFont() {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File(fontFilepath)));
} catch(IOException | FontFormatException e) {
System.out.println("Filepath of font not found: " + fontFilepath + " does not exist.");
}
}
private void setSaveFiles() {
File[] tmp = new File(savesFilepath).listFiles();
if(tmp != null) {
for(int i = 0; i < tmp.length; i++) {
saveFiles.add(tmp[i]);
}
returningUser = true;
} else {
returningUser = false;
}
saves = new ArrayList<>();
for(File file : saveFiles) {
saves.add(readCharacter(file));
}
}
private CharacterSheet readCharacter(File file) {
CharacterSheet sheet = null;
try {
FileInputStream fileIn = new FileInputStream(file.getPath());
ObjectInputStream in = new ObjectInputStream(fileIn);
sheet = (CharacterSheet) in.readObject();
in.close();
fileIn.close();
} catch (IOException | ClassNotFoundException e) {
System.out.println("No saved characters were found");
}
return sheet;
}
private void writeCharacter(CharacterSheet sheet) {
try(
FileOutputStream fileOut = new FileOutputStream(savesFilepath + sheet.getName() + ".dnd");
ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
) {
objOut.writeObject(sheet);
setSaveFiles();
} catch (IOException e) {
System.out.println("ERROR: ");
e.printStackTrace();
System.out.println("\nERROR: Unable to write character sheet object to \n" + filepath + "/.savedSheets");
}
}
}
+516
View File
@@ -0,0 +1,516 @@
package dnd;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import static dnd.AppConstants.*;
import dnd.species.*;
public class GUImanager extends JFrame {
private FileManager fileManager;
private ArrayList<CharacterSheet> saves;
private ArrayList<DefaultButton> savesButtons;
private static JPanel[] panels;
private int lastPanel;
private int currentPanel;
private int nextPanel;
private String[] raceOptions;
private String[] raceDescriptions;
private String[] classOptions;
private String[] classDescriptions;
private int raceChoice;
private int classChoice;
private String[] statOptions;
private String[] statDescriptions;
private String[] characteristics;
private String[] alignmentOptions;
private String[] alignmentDescriptions;
private String[] backgroundOptions;
private String[] backgroundDescriptions;
private int[] selectedStats;
public GUImanager() {
super("D&D Character Builder");
fileManager = new FileManager();
frameSetup();
setupPanelInfo();
ImageManager images = new ImageManager();
this.panels = new JPanel[]{
new MainMenuPanel(createNewCharacterButton(), createRandomCharacterButton(), createLoadButton()),
new BasicPanel(createNavPanel(), raceOptions, raceDescriptions, "Step 1: Choose Your Race", images), // To choose Race.
new BasicPanel(createNavPanel(), classOptions, classDescriptions, "Step 2: Choose Your Class", images), // To choose Class.
new ChooseAbilityScoresPanel(createNavPanel(1), statOptions, statDescriptions, selectedStats, "Step 3: Choose Your Ability Scores"),
new DescriptionPanel(createNavPanel(), characteristics, alignmentOptions, alignmentDescriptions, backgroundOptions, backgroundDescriptions, "Step 4: Describe your character"),
new LoadCharacterPanel(createBackPanel(), loadableCharacters()),
new ViewCharacterPanel(createBackPanel(), new CharacterSheet("Josh", 21, 5, 8, 180, "Brown", "Dark Brown", new Elf(), new Fighter(), "Neutral", "Nomad", new CharacterStats(9, 15, 12, 10, 13, 10)))
};
if (fileManager.isReturningUser()) {
this.currentPanel = 0;
} else {
this.currentPanel = 1;
}
this.lastPanel = currentPanel - 1;
this.nextPanel = currentPanel + 1;
add(panels[currentPanel]);
}
private void frameSetup() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setPreferredSize(new Dimension(750, 550));
setSize(getPreferredSize());
setResizable(false);
setLocationRelativeTo(null);
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception e) {
System.out.println("Error with cross platform look/feel in frameSetup().");
}
}
private void setupPanelInfo() {
raceOptions = new String[]{
"Dragonborn",
"Dwarf",
"Elf",
"Gnome",
"HalfElf",
"Halfling",
"Halforc",
"Human",
"Tiefling"
};
raceDescriptions = new String[]{
"Born of dragons, as their name proclaims, the dragonborn walk proudly through a world that greets them with fearful incomprehension." + "Shaped by draconic gods or the dragons themselves, dragonborn originally hatched from dragon eggs as a unique race, combining the best attributes of dragons and humanoids." + "Some dragonborn are faithful servants to true dragons, others form the ranks of soldiers in great wars, and still others find themselves adrift, with no clear calling in life.",
"By the numbers, dwarves are one of the best races in the Players Handbook. " + "" + "Their ability score increases are good, and their other racial traits make them durable and flexible enough to succeed in several classes.",
"A staple of fantasy fiction and folklore, Elves are a simple yet effective base race with subraces which are numerous and diverse enough that elves are usable in a variety of builds and character concepts. " + "Unfortunately, because the subraces differentiate the Elfs traits so much, its rare for more than one subrace to be viable in the same class unless youre using the Customizing Your Origins optional rules presented in Tashas Cauldron of Everything.",
"Gnomes have changed a lot throughout the history of Dungeons and Dragons. " + "At times theyve been monsters. " + "At times theyve been fey. " + "In general, DnD has always had trouble pinning down gnomes thematically in a way that distinguishes them from halflings, but I think 5th edition may have done the best job of any edition to date. " + "Gnomes have subraces which are very distinct from one another, and their traits offer some unique an interesting options.",
"The Half-Elf is among the most powerful races in the core rules. " + "Its a top-tier race option for several classes, and even for classes where the Half-Elf isnt a perfect fit its at least workable. " + "Two flexible ability increases and two free skill proficiencies are useful on essentially any character, plus you get Darkvision and a +2 Charisma increase.",
"Half-orcs are an easily-overlooked race. " + "Their racial traits tend to pigeon-hole them into simple martial builds, and in most official settings and works of fiction outside of D&D orcs have historically been portrayed barbaric savages, so even characters backstories tend to be forced into an incredibly narrow set of options. " + "Half-orcs dont get subraces, and unlike the half-elf we havent seen variants of any kind, so the race offers little flexibility.",
"Halflings are perhaps the most iconic small race in Dungeons and Dragons, dating back to its earliest editions. " + "Their mechanics have changed as much as any race, but they have consistently remained a staple option for players who enjoy playing thieves, rogues, or other stealthy characters.",
"Human come in two flavors: the standard human and the “variant” human. " + "The standard human receives +1 increases to each ability score, making it easy to fit into any build. " + "However, it lacks any other racial traits, which makes the standard human extremely bland. " + "It also lacks the numerical appeal of a +2 ability increase, so more focused races will frequently outpace the standard human in nearly every case.",
"Thanks to the variants presented in Sword Coast Adventurers Guide and the subraces presented in Mordenkainens Tome of Foes, the Tiefling has the longest list of subrace options of any published race, totaling an impressive 14 individual subraces and variants. " + "These options make tieflings diverse, flexible, and viable in an impressively large number of builds."
};
classOptions = new String[]{
"Artificer",
"Barbarian",
"Bard",
"Cleric",
"Druid",
"Fighter",
"Monk",
"Paladin",
"Ranger",
"Rogue",
"Sorcerer",
"Warlock",
"Wizard"
};
classDescriptions = new String[]{
"The Artificer is a class with a tool for every job and a solution to every problem. " + "They excel as a Support character, but make decent Defenders, Healers, and Strikers, too. " + "With the right infusions and spells, they can fill nearly any role in the party, making the Artificers versatility rival that of the Bard.",
"Barbarians are all about getting angry and dealing damage. " + "They have a ton of hit points, resistance to damage, and Rage gives a wonderful bonus to damage. " + "Barbarians dont get much in the way of skills, so generally theyre stuck as combat monsters, but they function equally well as a Defender and a Striker, and certain character options can even expand them into a limited Support role.",
"The Bard is fantastically versatile. " + "With access to every skill, expertise, full casting, and a decent set of proficiencies, the Bard can fill essentially every role in the party. " + "Subclasses like College of Lore are more of the classic supportive Bard, with improved magical options and support abilities, while College of Swords and College of Valor can serve as front-line melee characters who can bring their spellcasting and support capabilities into the heat of battle.",
"Clerics are among the most diverse and interesting classes in 5e DnD. " + "Because your choice of Divine Domain so greatly affects your capabilities, Clerics can fit a variety of roles and play styles. " + "More generally, Clerics are the best healers in the game, and have among the best support, utility, and divination options in the game. " + "However, they are by no means limited to healing and support roles. " + "Clerics have abundant offensive options, and can even be effective with weapons.",
"Druids are a very versatile class. " + "Between their available archetypes, theyre able to serve mixes roles as scouts, strikers, blaster, support casters, and controllers. " + "Their spell list has a lot of unique options. " + "There is a strong emphasis on area control spells, and most of the Druids best spells require Concentration.",
"The Fighter is a fantastic addition to any party. " + "While their skill and tool proficiencies are extremely limited, Fighters excel in combat. " + "They are durable, have great armor, and provide plenty of damage output. " + "Fighters get more Ability Score Increases than any other class, allowing them to easily explore feats without sacrificing crucial ability scores. " + "They also notably get more attacks than any other class, which can be a lot of fun.",
"The Monk is the iconic martial-artist, popular among those who prefer to punch things rather than stabbing them or setting them on fire (though stabbing things and setting them on fire is still a possibility for the Monk). " + "Monks are excellent Defenders and Strikers, and typically fill a role in party as a Fighter-equivalent or Rogue-equivalent depending on your subclass and proficiencies.",
"Paladins are the most durable, survivable, and self-sufficient class in the game. " + "As such, they both make excellent solo characters and are excellent additions to nearly any party regardless of existing capabilities. " + "In a party, they serve as a Defender, Face, and Striker. " + "They do have some healing and utility options, but not enough to replace a full spellcaster in most parties.",
"The Ranger is an interesting mix of Druid-style spellcasting, Fighter-style combat capabilities, and Rogue-style skills. " + "Themed around nature and exploration, the Ranger is a welcome asset in parties exploring untamed lands above or below ground. " + "The Ranger can fill the role of either a Fighter-equivalent or a Rogue-equivalent (sometimes both), and works well as a Scout and Striker, but trades the Fighters durability for better skills and improved damage output.",
"Rogues are the quintessential Face, Scout and Striker. " + "Sneak Attack allows them to do a huge pile of damage in a single attack, and their pile of skills allows them to easily handle locks, traps, guards, and many other challenges. " + "While a party can function just fine without a Rogue, its hard to compete with the sheer number of important skill and tool proficiencies offered by the Rogue.",
"Sorcerers are a challenge, but at the same time they can be less complex than most spellcasting classes. " + "The Sorcerers spell list allows them to serve as a Blaster, Controller, Striker, and Utility Caster, and sorcerers make one of the easiest Faces in the game due to their skill list and their dependence on Charisma.",
"The Warlock is likely the easiest of any spellcaster to play. " + "You get only a handful of spell slots at a time, and never have to juggle multiple spell slot levels. " + "Warlocks learn spells permanently, so you dont need to worry about changing your spells on a daily basis. " + "Warlocks also get the most powerful damage cantrip in the game, giving them a solid, reliable option for damage output in between your big spells.",
"The Wizard is the iconic arcane spellcaster, capable of doing all manner of fantastic tricks, and generally limited only by their spellbook and their spell slots. " + "A Wizard with a comprehensive spellbook can do essentially anything in the game, often as well as or better than a non-magical character who is built to do that thing. " + "A Wizard with Invisibility is as stealthy as a Rogue."
};
statOptions = new String[]{
"strength",
"Dexterity",
"Constitution",
"Intelligence",
"Widsom",
"Charisma"
};
statDescriptions = new String[]{
"A Strength check can model any attempt to lift, push, pull, or break something, to force your body through a space, or to otherwise apply brute force to a situation. You add your Strength modifier to your attack roll and your damage roll when attacking with a melee weapon Skills: Athletics",
"A Dexterity check can model any attempt to move nimbly, quickly, or quietly, or to keep from falling on tricky footing. You add your Dexterity modifier to your attack roll and your damage roll when attacking with a ranged weapon, or a melee weapon that has the finesse property. Skills: Acrobatics, Sleight of Hand, Stealth",
"Constitution checks are uncommon, and no skills apply to Constitution checks, because the endurance this ability represents is largely passive rather than involving a specific effort on the part of a character or monster. A Constitution check can model your attempt to push beyond normal limits, however. Your Constitution modifier contributes to your hit points. Typically, you add your Constitution modifier to each Hit Die you roll for your hit points.",
"An Intelligence check comes into play when you need to draw on logic, education, memory, or deductive reasoning. Skills: Arcana, History, Investigation, Nature, Religion",
"A Wisdom check might reflect an effort to read body language, understand someones feelings, notice things about the environment, or care for an injured person. Skills: Animal Handling, Insight, Medicine, Perception, Survival",
"A Charisma check might arise when you try to influence or entertain others, when you try to make an impression or tell a convincing lie, or when you are navigating a tricky social situation. Skills: Deception, Intimidation, Performance, Persuasion"
};
selectedStats = new int[]{8, 8, 8, 8, 8, 8};
characteristics = new String[]{
"Name",
"Age",
"Height",
"Weight",
"Eyes",
"Hair"
};
alignmentOptions = new String[]{
"Lawful Good",
"Neutral Good",
"Chaotic Good",
"Lawful Neutral",
"True Neutral",
"Chaotic Neutral",
"Lawful Evil",
"Neutral Evil",
"Chaotic Evil"
};
alignmentDescriptions = new String[]{
"Lawful Good (LG) creatures can be counted on to do the right thing as expected by society. Gold dragons and paladins are typically lawful good.",
"Neutral Good (NG) folk do the best they can to help others according to their needs. Many celestials are neutral good.",
"cChaotic Good (CG) creatures act as their conscience directs, with little regard for what others expect. Copper dragons and unicorns are typically chaotic good.",
"Lawful Neutral (LN) individuals act in accordance with law, tradition, or personal codes. Modrons and many wizards and monks are lawful neutral.",
"Neutral (N) is the alignment of those who prefer to steer clear of moral questions and dont take sides, doing what seems best at the time. Druids are traditionally neutral, as are typical townsfolk.",
"Chaotic Neutral (CN) creatures follow their whims, holding their personal freedom above all else. Many rogues and bards are chaotic neutral.",
"Lawful Evil (LE) creatures methodically take what they want, within the limits of a code of tradition, loyalty, or order. Devils and blue dragons are typically lawful evil.",
"Neutral Evil (NE) is the alignment of those who do whatever they can get away with, without compassion or qualms. Yugoloths are typically neutral evil.",
"Chaotic Evil (CE) creatures act with arbitrary violence, spurred by their greed, hatred, or bloodlust. Demons and red dragons are typically chaotic evil."
};
backgroundOptions = new String[]{
"Acolyte",
"Charlatan",
"Criminal",
"Entertainer",
"Folk Hero",
"Gladiator",
"Guild Artisan",
"Guild Merchant",
"Hermit",
"Knight",
"Noble",
"Outlander",
"Pirate",
"Sage",
"Sailor",
"Soldier",
"Spy",
"Urchin"
};
backgroundDescriptions = new String[]{
//Acolyte
"You have spent your life in the service of a temple to a specific god or pantheon of gods. You act as an intermediary between the realm of the holy and the mortal world, performing sacred rites and offering sacrifices in order to conduct worshipers into the presence of the divine. You are not necessarily a cleric—performing sacred rites is not the same thing as channeling divine power. Feature: Shelter of the Faithful Proficiencies: Insight, Religion",
//Charlatan
"You have always had a way with people. You know what makes them tick, you can tease out their hearts desires after a few minutes of conversation, and with a few leading questions you can read them like they were childrens books. Its a useful talent, and one that youre perfectly willing to use for your advantage. Feature: False Identity Proficiencies: Deception, Sleight of Hand",
//Criminal
"You are an experienced criminal with a history of breaking the law. You have spent a lot of time among other criminals and still have contacts within the criminal underworld. Youre far closer than most people to the world of murder, theft, and violence that pervades the underbelly of civilization, and you have survived up to this point by flouting the rules and regulations of society. Feature: Criminal Contact Proficiencies: Deception, Stealth",
//Entertainer
"You thrive in front of an audience. You know how to entrance them, entertain them, and even inspire them. Your poetics can stir the hearts of those who hear you, awakening grief or joy, laughter or anger. Your music raises their spirits or captures their sorrow. Your dance steps captivate, your humor cuts to the quick. Whatever techniques you use, your art is your life. Feature: By Popular Demand Proficiencies: Acrobatics, Performance",
//Folk Hero
"You come from a humble social rank, but you are destined for so much more. Already the people of your home village regard you as their champion, and your destiny calls you to stand against the tyrants and monsters that threaten the common folk everywhere. Feature: Rustic Hospitality Proficiencies: Animal Handling, Survival",
//Gladiator
"A gladiator is as much an entertainer as any minstrel or circus performer, trained to make the arts of combat into a spectacle the crowd can enjoy. This kind of flashy combat is your entertainer routine, though you might also have some skills as a tumbler or actor. Feature: By Popular Demand Proficiencies: Acrobatics, Performance",
//Guild Artisan
"You are a member of an artisans guild, skilled in a particular field and closely associated with other artisans. You are a well-established part of the mercantile world, freed by talent and wealth from the constraints of a feudal social order. You learned your skills as an apprentice to a master artisan, under the sponsorship of your guild, until you became a master in your own right. Feature: Guild Membership Proficiencies: Insight, Persuasion",
//Guild Merchant
"Instead of an artisans guild, you might belong to a guild of traders, caravan masters, or shopkeepers. You dont craft items yourself but earn a living by buying and selling the works of others (or the raw materials artisans need to practice their craft). Your guild might be a large merchant consortium (or family) with interests across the region. Perhaps you transported goods from one place to another, by ship, wagon, or caravan, or bought them from traveling traders and sold them in your own little shop. In some ways, the traveling merchants life lends itself to adventure far more than the life of an artisan. Feature: Guild Membership Proficiencies: Insight, Persuasion",
//Hermit
"You lived in seclusion — either in a sheltered community such as a monastery, or entirely alone — for a formative part of your life. In your time apart from the clamor of society, you found quiet, solitude, and perhaps some of the answers you were looking for. Feature: Discovery Proficiencies: Medicine, Religion",
//Knight
"A knighthood is among the lowest noble titles in most societies, but it can be a path to higher status. One of your commoner retainers is a noble who serves as your squire, aiding you in exchange for training on his or her own path to knighthood. Your two remaining retainers might include a groom to care for your horse and a servant who polishes your armor (and even helps you put it on). Feature: Retainers Proficiencies: History, Persuasion",
//Noble
"You understand wealth, power, and privilege. You carry a noble title, and your family owns land, collects taxes, and wields significant political influence. You might be a pampered aristocrat unfamiliar with work or discomfort, a former merchant just elevated to the nobility, or a disinherited scoundrel with a disproportionate sense of entitlement. Or you could be an honest, hard-working landowner who cares deeply about the people who live and work on your land, keenly aware of your responsibility to them. Feature: Position of Privilege Proficiencies: History, Persuasion",
//Outlander
"You grew up in the wilds, far from civilization and the comforts of town and technology. Youve witnessed the migration of herds larger than forests, survived weather more extreme than any city-dweller could comprehend, and enjoyed the solitude of being the only thinking creature for miles in any direction. The wilds are in your blood, whether you were a nomad, an explorer, a recluse, a hunter-gatherer, or even a marauder. Even in places where you dont know the specific features of the terrain, you know the ways of the wild. Feature: Wanderer Proficiencies: Athletics, Survival",
//Pirate
"You spent your youth under the sway of a dread pirate, a ruthless cutthroat who taught you how to survive in a world of sharks and lawlessness. Youve indulged in larceny on the high seas and sent more than one deserving soul to a briny grave. Fear and bloodshed are no strangers to you, and youve garnered a somewhat unsavory reputation in many a port town. Feature: Bad Reputation Proficiencies: Athletics, Perception",
//Sage
"You spent years learning the lore of the multiverse. You scoured manuscripts, studied scrolls, and listened to the greatest experts on the subjects that interest you. Your efforts have made you a master in your fields of study. Feature: Researcher Proficiencies: Arcana, History",
//Sailer
"You sailed on a seagoing vessel for years. In that time, you faced down mighty storms, monsters of the deep, and those who wanted to sink your craft to the bottomless depths. Your first love is the distant line of the horizon, but the time has come to try your hand at something new. Feature: Ship's Passage Proficiencies: Athletics, Perception",
//Soldier
"War has been your life for as long as you care to remember. You trained as a youth, studied the use of weapons and armor, learned basic survival techniques, including how to stay alive on the battlefield. You might have been part of a standing national army or a mercenary company, or perhaps a member of a local militia who rose to prominence during a recent war. Feature: Military Rank Proficiencies: Athletics, Intimidation",
//Spy
"Although your capabilities are not much different from those of a burglar or smuggler, you learned and practiced them in a very different context: as an espionage agent. You might have been an officially sanctioned agent of the crown, or perhaps you sold the secrets you uncovered to the highest bidder. Feature: Criminal Contact Proficiencies: Deception, Stealth",
//Urchin
"You grew up on the streets alone, orphaned, and poor. You had no one to watch over you or to provide for you, so you learned to provide for yourself. You fought fiercely over food and kept a constant watch out for other desperate souls who might steal from you. You slept on rooftops and in alleyways, exposed to the elements, and endured sickness without the advantage of medicine or a place to recuperate. Youve survived despite all odds, and did so through cunning, strength, speed, or some combination of each. Feature: City Secrets Proficiencies: Sleight of Hand, Stealth"
};
}
private BasicNavPanel createNavPanel() {
return new BasicNavPanel(createBackButton(), createContinueButton(), 0);
}
private BasicNavPanel createNavPanel(int continueRequirement) {
return new BasicNavPanel(createBackButton(), createContinueButton(), continueRequirement);
}
private BasicNavPanel createBackPanel() {
return new BasicNavPanel(createBackButton(0), null, 0);
}
private DefaultButton createBackButton() {
DefaultButton button = new DefaultButton("Back");
button.addActionListener(
e -> {
lastPanel--;
currentPanel--;
nextPanel--;
clearAndReset();
}
);
return button;
}
private DefaultButton createBackButton(int manualBackPoint) {
DefaultButton button = new DefaultButton("Back");
button.addActionListener(
e -> {
lastPanel = 0;
currentPanel = manualBackPoint;
nextPanel = 0;
clearAndReset();
}
);
return button;
}
private DefaultButton createContinueButton() {
DefaultButton button = new DefaultButton("Continue");
button.addActionListener(
e -> {
lastPanel++;
currentPanel++;
nextPanel++;
clearAndReset();
}
);
return button;
}
private DefaultButton createNewCharacterButton() {
DefaultButton button = createContinueButton();
button.setText("Create New Character");
button.addActionListener(
e -> {
lastPanel = 0;
currentPanel = 1;
nextPanel = 2;
clearAndReset();
}
);
return button;
}
// TODO: Need to implement.
private DefaultButton createRandomCharacterButton() {
DefaultButton button = new DefaultButton("Create Random Character");
button.addActionListener(
e -> {
createRandomCharacter();
lastPanel = currentPanel;
currentPanel = 3;
nextPanel = currentPanel + 1;
clearAndReset();
}
);
return button;
}
// TODO: Need to implement with exact indices and file manager logic.
private DefaultButton createSaveButton() {
DefaultButton button = new DefaultButton("Save");
button.addActionListener(
e -> {
lastPanel = currentPanel;
currentPanel = 6;
nextPanel = currentPanel + 1;
clearAndReset();
}
);
return button;
}
private DefaultButton createLoadButton() {
DefaultButton button = new DefaultButton("Load");
button.addActionListener(
e -> {
lastPanel = currentPanel;
currentPanel = 5;
clearAndReset();
}
);
return button;
}
private ArrayList<DefaultButton> loadableCharacters() {
saves = fileManager.getSaves();
savesButtons = new ArrayList<>();
for(int i = 0; i < saves.size(); i++) {
savesButtons.add(createLoadNCharacterButton(i));
}
for(int i = 0; i < saves.size(); i++) {
System.out.println(saves.get(i).toString());
}
return savesButtons;
}
private DefaultButton createLoadNCharacterButton(int index) {
if(index < 0) return new DefaultButton("INDEX OUT OF BOUNDS");
DefaultButton button = new DefaultButton(saves.get(index).getName());
button.addActionListener(
e -> {
lastPanel = currentPanel;
panels[6] = new ViewCharacterPanel(createBackPanel(), saves.get(index));
currentPanel = 6;
clearAndReset();
}
);
return button;
}
// TODO: Need to implement random character creation.
private void createRandomCharacter() {
System.out.println("Request to create random character. Need to implement.");
}
private void clearAndReset() {
getContentPane().removeAll();
add(panels[currentPanel]);
repaint();
revalidate();
pack();
}
}
+88
View File
@@ -0,0 +1,88 @@
package dnd;
import javax.imageio.*;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import static dnd.AppConstants.*;
public class ImageManager extends FileManager {
private static JLabel[][] racePortraits;
private static JLabel[][] classPortraits;
private static ArrayList<JLabel> savesPortraits;
public ImageManager() {
super();
racePortraits = new JLabel[9][];
classPortraits = new JLabel[12][];
savesPortraits = new ArrayList<>();
createPortraitArray(racePortraits, "race");
createPortraitArray(classPortraits, "class");
createSavesPortraits();
}
public JLabel getRacePortrait(int raceIndex) {
if(raceIndex < 1) return new JLabel();
return racePortraits[raceIndex][new Random().nextInt(racePortraits[raceIndex].length)];
}
public JLabel getClassPortrait(int classIndex) {
if(classIndex < 1) return new JLabel();
return classPortraits[classIndex][new Random().nextInt(classPortraits[classIndex].length)];
}
private void createSavesPortraits() {
File[] dir = new File(imgFilepath + "/saves/").listFiles();
for(File file : dir) {
JLabel holder = image(file);
holder.setOpaque(true);
holder.setBackground(lightBrown);
savesPortraits.add(holder);
}
}
private void createPortraitArray(JLabel[][] portraits, String category) {
File imgDir = new File(imgFilepath + category + "/");
File[] masterDir = imgDir.listFiles();
for(int i = 0; i < portraits.length; i++) {
File[] tmpDir = masterDir[i].listFiles();
portraits[i] = new JLabel[tmpDir.length];
int index = 0;
for(File file : tmpDir) {
portraits[i][index] = image(file);
portraits[i][index].setOpaque(true);
portraits[i][index].setBackground(lightBrown);
//portraits[i][index].setBounds(bounds[3]);
index++;
}
}
}
private JLabel image(File file) {
BufferedImage img;
Image finalImg;
JLabel picture;
try {
img = ImageIO.read(file);
finalImg = img.getScaledInstance(250, 375, Image.SCALE_SMOOTH);
} catch (IOException e) {
System.out.println("File " + file.getPath() + " does not exist.");
img = null;
finalImg = null;
picture = null;
return null;
}
picture = new JLabel(new ImageIcon(finalImg));
return picture;
}
}
+107
View File
@@ -0,0 +1,107 @@
package dnd;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import static dnd.AppConstants.*;
public class InfoPanel extends JPanel {
protected JTextArea[] descriptions;
protected Rectangle[] bounds;
protected String[] holderDescriptions;
protected String[] categoryHolder;
protected ImageManager images;
public InfoPanel(String[] categoryHolder, String[] holderDescriptions, Rectangle[] bounds) {
super();
this.categoryHolder = categoryHolder;
this.holderDescriptions = holderDescriptions;
this.bounds = bounds;
panelSetup();
createDescriptions();
}
public InfoPanel(String[] categoryHolder, String[] holderDescriptions, Rectangle[] bounds, ImageManager images) {
super();
this.categoryHolder = categoryHolder;
this.holderDescriptions = holderDescriptions;
this.bounds = bounds;
panelSetup();
createDescriptions();
}
public void updateInfo(int holderIndex) {
removeAll();
panelSetup();
add(descriptions[holderIndex]);
repaint();
revalidate();
}
protected void updateInfo(int holderIndex, JLabel portrait) {
removeAll();
panelSetup();
add(descriptions[holderIndex]);
add(portrait);
repaint();
revalidate();
}
private void panelSetup() {
setOpaque(false);
setBounds(bounds[0]);
setLayout(null);
JLabel subHeader = new JLabel("Description");
subHeader.setFont(subHeaderFont);
subHeader.setHorizontalAlignment(SwingConstants.LEFT);
subHeader.setBounds(bounds[1]);
subHeader.setForeground(darkestBrown);
add(subHeader);
}
private void createDescriptions() {
descriptions = new JTextArea[holderDescriptions.length];
for (int i = 0; i < holderDescriptions.length; i++) {
JTextArea tmpDesc = new JTextArea();
tmpDesc.setText(holderDescriptions[i]);
tmpDesc.setWrapStyleWord(true);
tmpDesc.setLineWrap(true);
tmpDesc.setOpaque(true);
tmpDesc.setEditable(false);
tmpDesc.setFocusable(false);
tmpDesc.setFont(paragraphText);
tmpDesc.setBounds(bounds[2]);
tmpDesc.setBorder(new EmptyBorder(5, 5, 5, 5));
tmpDesc.setBackground(medBrown);
tmpDesc.setForeground(darkestBrown);
descriptions[i] = tmpDesc;
}
}
}
+57
View File
@@ -0,0 +1,57 @@
package dnd;
import java.io.Serializable;
public class Intelligence extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Intelligence(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
// TODO: Need description.
public String getDescription() {
return "";
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
+66
View File
@@ -0,0 +1,66 @@
package dnd;
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
public class LoadCharacter extends JPanel {
public LoadCharacter() {
setBackground(new Color(205, 133, 63));
setLayout(new BorderLayout(0, 0));
JLabel lblNewLabel = new JLabel("Load a Character");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel.setFont(new Font("Bodoni 72 Oldstyle", Font.PLAIN, 31));
add(lblNewLabel, BorderLayout.NORTH);
JPanel loadCharacterMainPanel = new JPanel();
loadCharacterMainPanel.setOpaque(false);
add(loadCharacterMainPanel, BorderLayout.CENTER);
loadCharacterMainPanel.setLayout(null);
JPanel characterLoadPanel = new JPanel();
characterLoadPanel.setBackground(new Color(210, 180, 140));
characterLoadPanel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
characterLoadPanel.setBounds(54, 47, 340, 346);
loadCharacterMainPanel.add(characterLoadPanel);
characterLoadPanel.setLayout(new GridLayout(5, 1, 0, 0));
JButton characterSave1 = new JButton("Load Character 1");
characterLoadPanel.add(characterSave1);
JButton characterSave2 = new JButton("Load Character 2");
characterLoadPanel.add(characterSave2);
JButton characterSave3 = new JButton("Load Character 3");
characterLoadPanel.add(characterSave3);
JButton characterSave4 = new JButton("Load Character 4");
characterLoadPanel.add(characterSave4);
JButton characterSave5 = new JButton("Load Character 5");
characterLoadPanel.add(characterSave5);
JButton goBtn = new JButton("Go");
goBtn.setOpaque(true);
goBtn.setBackground(new Color(210, 105, 30));
goBtn.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
goBtn.setFont(new Font("Lucida Grande", Font.PLAIN, 30));
goBtn.setBounds(481, 261, 124, 50);
loadCharacterMainPanel.add(goBtn);
JButton goBack = new JButton("Go Back");
goBack.setOpaque(true);
goBack.setBackground(new Color(210, 105, 30));
goBack.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
goBack.setFont(new Font("Lucida Grande", Font.PLAIN, 30));
goBack.setBounds(481, 343, 124, 50);
loadCharacterMainPanel.add(goBack);
}
}
@@ -0,0 +1,68 @@
package dnd;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import static dnd.AppConstants.*;
public class LoadCharacterPanel extends JPanel {
private ArrayList<DefaultButton> savedCharacters;
public LoadCharacterPanel(JPanel nav, ArrayList<DefaultButton> savedCharacters) {
super();
panelSetup();
this.savedCharacters = savedCharacters;
createMasterPanel();
add(nav, BorderLayout.SOUTH);
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private void createMasterPanel() {
JLabel title = new JLabel("Load a Character");
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
JPanel panel = new JPanel();
panel.setOpaque(false);
panel.setLayout(null);
//panel.add(buttonPanel());
// TODO: Need to implement.
//panel.add(portraitPanel());
add(buttonPanel(), BorderLayout.NORTH);
}
private JPanel buttonPanel() {
JPanel panel = new JPanel(new GridLayout(savedCharacters.size(), 1, 0, 0));
panel.setOpaque(false);
panel.setBackground(lightBrown);
for(int i = 0; i < savedCharacters.size(); i++) {
panel.add(savedCharacters.get(i));
}
return panel;
}
}
+68
View File
@@ -0,0 +1,68 @@
package dnd;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import static dnd.AppConstants.*;
public class MainMenuPanel extends JPanel {
private DefaultButton newCharacter;
private DefaultButton randomCharacter;
private DefaultButton loadCharacter;
public MainMenuPanel(DefaultButton newCharacter, DefaultButton randomCharacter, DefaultButton loadCharacter) {
super();
panelSetup();
this.newCharacter = newCharacter;
this.randomCharacter = randomCharacter;
this.loadCharacter = loadCharacter;
add(createLabel(), BorderLayout.NORTH);
add(createControlPanel(), BorderLayout.CENTER);
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private JLabel createLabel() {
JLabel label = new JLabel("D&D Character Builder");
label.setFont(headerFont);
label.setForeground(darkestBrown);
label.setOpaque(false);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setBorder(new EmptyBorder(5, 5, 5, 5));
return label;
}
private JPanel createControlPanel() {
JPanel panel = new JPanel(new GridLayout(1, 2, 50, 0));
panel.setOpaque(false);
panel.setBorder(new EmptyBorder(25, 25, 25, 25));
JPanel subPanel = new JPanel(new GridLayout(2, 1, 0, 50));
subPanel.setOpaque(false);
subPanel.add(newCharacter);
subPanel.add(randomCharacter);
panel.add(subPanel);
panel.add(loadCharacter);
return panel;
}
}
+74
View File
@@ -0,0 +1,74 @@
package dnd;
/**
* Object stores information about a character's skills arrays. Firstly, the name of each skill, and secondly the value of each skill. When constructed, a private method is called
* which adds any proficiency bonus to each skill and then adds the ability score modifier to each skill.
*/
public class Skills {
// TODO: Prof bonus comes from the class, changes upon certain level thresholds.
private final int profBonus = 5;
// TODO: Need to verify skills are in correct order.
private String[] allSkillsText = {"Acrobatics", "Animal Handling", "Arcana", "Athletics", "Deception", "History", "Insight", "Intimidation", "Investigation", "Medicine", "Nature", "Perception", "Performance", "Persuasion", "Religion", "Sleight of Hand", "Stealth", "Survival"};
private Stats[] stats;
private int[] skills;
/**
* Default constructor for the Skills class. Should be constructed AFTER the user has generated their stats and chosen the skills they are proficient in.
*
* @param skills
* @param stats
*/
public Skills(int[] skills, Stats[] stats) {
this.skills = skills;
this.stats = stats;
setSkills();
}
/**
* Adds proficiency bonus to each element of the skills array, and then adds the corresponding AS modifier to each skill.
*/
private void setSkills() {
// TODO: Need to verify these are the correct ability scores for each skill.
int[] skillsAbilities = {1, 4, 3, 0, 5, 3, 4, 5, 3, 4, 3, 4, 5, 5, 3, 1, 4};
for (int i = 0; i < allSkillsText.length; i++) {
if (skills[i] == 1) {
skills[i] = profBonus;
}
skills[i] += stats[skillsAbilities[i]].getModifier();
}
}
/**
* Returns the value of each skill's score.
*
* @return int[] skills
*/
public int[] getSkills() {
return skills;
}
// TODO: Need to implement overloaded method to return one specific skill.
public int getSkill(String skill) {
return 0;
}
}
+56
View File
@@ -0,0 +1,56 @@
package dnd;
public abstract class Stats {
public int calcSavingThrow(int abilityScore) {
switch (abilityScore) {
case 1:
return -5;
case 2:
case 3:
return -4;
case 4:
case 5:
return -3;
case 6:
case 7:
return -2;
case 8:
case 9:
return -1;
case 10:
case 11:
return 0;
case 12:
case 13:
return 1;
case 14:
case 15:
return 2;
case 16:
case 17:
return 3;
case 18:
case 19:
return 4;
case 20:
return 5;
default:
return -42;
}
}
public abstract void increaseScore();
abstract int getScore();
abstract int getModifier();
abstract int getSavingThrow();
abstract String getDescription();
}
+69
View File
@@ -0,0 +1,69 @@
package dnd;
import java.io.Serializable;
public class Strength extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Strength(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public Strength(Strength str) {
this.abilityScore = str.getScore();
this.abilityScoreModifier = str.getModifier();
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
public String getDescription() {
return "Natural athleticism and bodily power.";
}
public int getMaxCarryWeight() {
return abilityScore * 15;
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
+41
View File
@@ -0,0 +1,41 @@
package dnd;
import dnd.species.*;
public class Tester {
public static void main(String[] args) {
FileManager filer = new FileManager();
filer.saveCharacter(createSheet());
CharacterSheet chFromFile = filer.readSavedCharacter(0);
System.out.println("chFromFile: \n" + chFromFile.toString());
}
public static CharacterSheet createSheet() {
String name = "Josh";
int age = 21;
int heightFeet = 5;
int heightInch = 8;
int weight = 180;
String eyeColor = "Brown";
String hairColor = "Dark Brown";
Race race = new Elf();
ClassTemplate chClass = new Fighter();
CharacterStats stats = new CharacterStats(9, 15, 12, 10, 13, 10);
String alignment = "Neutral";
String background = "Nomad";
CharacterSheet chTest = new CharacterSheet(name, age, heightFeet, heightInch, weight, eyeColor, hairColor, race, chClass, alignment, background, stats);
return chTest;
}
}
@@ -0,0 +1,77 @@
package dnd;
import java.awt.*;
import javax.swing.*;
import static dnd.AppConstants.*;
public class ViewCharacterPanel extends JPanel {
private CharacterSheet sheet;
public ViewCharacterPanel(JPanel nav, CharacterSheet sheet) {
super();
this.sheet = sheet;
panelSetup();
createMasterPanel();
add(nav, BorderLayout.SOUTH);
}
public void changeCharacter(CharacterSheet sheet) {
this.sheet = sheet;
repaint();
revalidate();
}
private void panelSetup() {
setBackground(lightBrown);
setLayout(new BorderLayout(0, 0));
}
private void createMasterPanel() {
JLabel title = new JLabel(sheet.getName());
title.setHorizontalAlignment(SwingConstants.CENTER);
title.setFont(headerFont);
title.setForeground(darkestBrown);
add(title, BorderLayout.NORTH);
add(createCharacteristicsPanel(), BorderLayout.CENTER);
}
private JPanel createCharacteristicsPanel() {
JPanel panel = new JPanel(new GridLayout(2, 4, 15, 15));
panel.setOpaque(false);
panel.add(new JLabel("Age: " + sheet.getAge()));
panel.add(new JLabel("Height: " + sheet.getHeightFeet() + "\'" + sheet.getHeightInch() + "\""));
panel.add(new JLabel("Weight: " + sheet.getWeight() + "lbs."));
panel.add(new JLabel("Eye Color: " + sheet.getEyeColor()));
panel.add(new JLabel("Hair Color: " + sheet.getHairColor()));
panel.add(new JLabel("Race: " + sheet.getRace().toString()));
panel.add(new JLabel("Class: " + sheet.getCharacterClass().toString()));
panel.add(new JLabel("Ability Scores: " + sheet.getStats().toString()));
return panel;
}
}
+57
View File
@@ -0,0 +1,57 @@
package dnd;
import java.io.Serializable;
public class Wisdom extends Stats implements Serializable {
private int abilityScore;
private int abilityScoreModifier;
public Wisdom(int abilityScore) {
this.abilityScore = abilityScore;
this.abilityScoreModifier = calcSavingThrow(abilityScore);
}
public int getScore() {
return abilityScore;
}
public int getModifier() {
return abilityScoreModifier;
}
public int getSavingThrow() {
return getModifier();
}
// TODO: Need description.
public String getDescription() {
return "";
}
@Override
public String toString() {
return "Ability Score: " + abilityScore + " | Modifier: " + abilityScoreModifier + " | Description: "
+ getDescription();
}
@Override
public void increaseScore() {
abilityScore++;
}
}
+90
View File
@@ -0,0 +1,90 @@
package dnd;
public class Wizard implements ClassTemplate {
private int HP;
private int level;
// TODO: This should be the type of die.
private int hitDie;
public Wizard(Stats[] stats, int level) {
}
// TODO: Need to figure out how to contain class progression information. Potentially a double String array, each row equals a level, each column a different thing. Should class features be a separate class, ie. BarbFeatures, BardFeatures, etc?
public String getDescription() {
// TODO Auto-generated method stub
return null;
}
public String[] getProgression() {
// TODO Auto-generated method stub
return null;
}
public String[] getClassFeatures() {
// TODO Auto-generated method stub
return null;
}
public String getHitDie() {
// TODO Auto-generated method stub
return null;
}
public int getHPatLv1() {
// TODO Auto-generated method stub
return 0;
}
public int getHPpastLv1() {
// TODO Auto-generated method stub
return 0;
}
public String[] getArmorProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getWeaponProf() {
// TODO Auto-generated method stub
return null;
}
public String[] getToolProf() {
// TODO Auto-generated method stub
return null;
}
public String[] availableSkills() {
// TODO Auto-generated method stub
return null;
}
public String[] startingEquipChoices() {
// TODO Auto-generated method stub
return null;
}
public boolean advantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
public boolean disadvantageCheck(Stats abilityScore) {
// TODO Auto-generated method stub
return false;
}
@Override
public String[] getSavingThrows() {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,33 @@
package dnd.deprecated;
import javax.swing.border.Border;
import java.awt.*;
public class RoundedBorder implements Border {
private int radius;
public RoundedBorder(int radius) {
this.radius = radius;
}
public Insets getBorderInsets(Component c) {
return new Insets(this.radius + 1, this.radius + 1, this.radius + 2, this.radius);
}
public boolean isBorderOpaque() {
return true;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
g.drawRoundRect(x, y, width - 1, height - 1, radius, radius);
}
}
@@ -0,0 +1,72 @@
package dnd.species;
public class Dragonborn implements Race {
private final int speed = 30;
private final int maxAge = 80;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Dragonborn() {
this.languages = new String[]{"Common", "Draconic"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{0, 0, 5};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
+72
View File
@@ -0,0 +1,72 @@
package dnd.species;
public class Dwarf implements Race {
private final int speed = 25;
private final int maxAge = 350;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Dwarf() {
this.languages = new String[]{"Common", "Dwarvish"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{2, 2};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
+82
View File
@@ -0,0 +1,82 @@
package dnd.species;
import java.io.Serializable;
public class Elf implements Race, Serializable {
private final int speed = 30;
private final int maxAge = 750;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Elf() {
this.languages = new String[]{"Common", "Elvish"};
this.skills = new String[]{};
}
@Override
public String getRace() {
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
return maxAge;
}
@Override
public int getSpeed() {
return speed;
}
@Override
public String[] getTraits() {
return traits;
}
@Override
public String[] getSkills() {
return skills;
}
@Override
public String[] getLanguages() {
return languages;
}
@Override
public String[] getProficiencies() {
return proficiencies;
}
@Override
public int[] getASI() {
return new int[]{1, 1};
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
+72
View File
@@ -0,0 +1,72 @@
package dnd.species;
public class Gnome implements Race {
private final int speed = 25;
private final int maxAge = 500;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Gnome() {
this.languages = new String[]{"Common", "Gnomish"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{3, 3};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
@@ -0,0 +1,77 @@
package dnd.species;
public class HalfElf implements Race {
private final int speed = 30;
private final int maxAge = 180;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
private int chosenASI;
//TODO HalfElf get's to increase 1 ASI of their choice to increase.
public HalfElf(String chosenLanguage, int chosenASI) {
this.languages = new String[]{"Common", "Elvish", chosenLanguage};
this.skills = new String[]{};
this.chosenASI = chosenASI;
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{5, 5, chosenASI};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
@@ -0,0 +1,72 @@
package dnd.species;
public class HalfOrc implements Race {
private final int speed = 30;
private final int maxAge = 75;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public HalfOrc() {
this.languages = new String[]{"Common", "Orc"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{0, 0, 2};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
@@ -0,0 +1,73 @@
package dnd.species;
public class Halfling implements Race {
private final int speed = 30;
private final int maxAge = 750;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Halfling() {
this.languages = new String[]{"Common", "Elvish"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{1, 1};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
+74
View File
@@ -0,0 +1,74 @@
package dnd.species;
public class Human implements Race {
private final int speed = 30;
private final int maxAge = 80;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Human(String chosenLanguage) {
this.languages = new String[]{"Common", chosenLanguage};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{0, 1, 2, 3, 4, 5};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
+47
View File
@@ -0,0 +1,47 @@
package dnd.species;
public interface Race {
String getRace();
int maxAge();
int getSpeed();
String[] getTraits();
String[] getSkills();
String[] getLanguages();
String[] getProficiencies();
int[] getASI();
// private ArrayList<String> traits;
// private ArrayList<String> skills;
// private ArrayList<String> laugnuage;
// //private Subrace subrase;
// private ArrayList<String> proficiencies;
// /**
// * @param raceName
// * @param ageRange
// * @param speed
// * @param traits
// * @param skills
// * @param laugnuage
// * @param proficiencies
// */
// public Race(String raceName, String ageRange, int speed, ArrayList<String> traits, ArrayList<String> skills,
// ArrayList<String> laugnuage, ArrayList<String> proficiencies) {
// this.raceName = raceName;
// this.ageRange = ageRange;
// this.speed = speed;
// this.traits = traits;
// this.skills = skills;
// this.laugnuage = laugnuage;
// this.proficiencies = proficiencies;
// }
}
@@ -0,0 +1,72 @@
package dnd.species;
public class Tiefling implements Race {
private final int speed = 30;
private final int maxAge = 85;
private String[] traits;
private String[] skills;
private String[] languages;
private String[] proficiencies;
public Tiefling() {
this.languages = new String[]{"Common", "Infernal"};
this.skills = new String[]{};
}
@Override
public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
@Override
public int maxAge() {
// TODO Auto-generated method stub
return maxAge;
}
@Override
public int getSpeed() {
// TODO Auto-generated method stub
return speed;
}
@Override
public String[] getTraits() {
// TODO Auto-generated method stub
return traits;
}
@Override
public String[] getSkills() {
// TODO Auto-generated method stub
return skills;
}
@Override
public String[] getLanguages() {
// TODO Auto-generated method stub
return languages;
}
@Override
public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies;
}
@Override
public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{3, 5, 5};
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName();
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package dndcharacterbuilder;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test void appHasAGreeting() {
App classUnderTest = new App();
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}
}