Compare commits

..
10 Commits
144 changed files with 2018 additions and 1188 deletions
+9
View File
@@ -0,0 +1,9 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
+5
View File
@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>dnd</name>
<comment>Project dnd created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1682969422633</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,13 @@
arguments=--init-script /Users/jashton/.cache/jdtls/config/org.eclipse.osgi/50/0/.cp/gradle/init/init.gradle
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/opt/homebrew/Cellar/openjdk/20/libexec/openjdk.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true
+58
View File
@@ -1,2 +1,60 @@
# Application # Application
CSIS 1410 - Group Project CSIS 1410 - Group Project
CURRENT TODO ITEMS:
**************** CONTENT ****************
- All PHB classes should be included.
**************** GUI ********************
- Finish GUI panels
PANELS:
- Race
Upload custom profile picture button.
- Description (needs positioning)
- Spells & Equipment
- Preview
- Load Character/View character
- Save as PDF / Print
DESCRIPTIONS:
- Class action scene pictures.
- Ability Scores description text.
- Class descriptions.
- Race descriptions.
*************** FILES ******************
NOTE: user.dir = /home/joshuaashton/Development/misc/dndApp/src
user.home = /home/joshuaashton
NOTE: user.dir is changed to exe directory by application launch4j. This creates an exe file from .jar.
see Inno Setup Compiler to package .exe and the JRE into a singular installer.
- Upload custom profile picture.
- Character sheet from selections.
- Load existing characters to edit.
- Save new characters.
- File directory based upon OS used.
- Export to PDF.
- Print
************** FINAL TOUCHES **********
- Generate a random character.
- Character levels.
- Spells.
- Dice roller.
+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'
}
@@ -1,10 +1,11 @@
package dnd;
public class App { public class App {
public static void main(String[] args) { public static void main(String[] args) {
FileManager data = new FileManager(); GUImanager gui = new GUImanager();
GUImanager gui = new GUImanager(data.isReturninguser());
gui.setVisible(true); 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);
}
@@ -1,3 +1,5 @@
package dnd;
public class Background { public class Background {
int backgroundIndex; int backgroundIndex;
@@ -1,9 +1,13 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import java.awt.*; import java.awt.*;
public class BasicNavPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
public class BasicNavPanel extends JPanel {
private DefaultButton backButton; private DefaultButton backButton;
private DefaultButton continueButton; private DefaultButton continueButton;
@@ -13,8 +17,17 @@ public class BasicNavPanel extends JPanel implements AppTheme {
super(new GridLayout(1, 2, 30, 0)); super(new GridLayout(1, 2, 30, 0));
this.backButton = backButton; this.backButton = backButton;
if(continueButton == null) {
this.continueButton = null;
} else {
this.continueButton = continueButton; this.continueButton = continueButton;
}
this.continueRequirement = continueRequirement; this.continueRequirement = continueRequirement;
createNavPanel(); createNavPanel();
@@ -56,8 +69,12 @@ public class BasicNavPanel extends JPanel implements AppTheme {
if (continueRequirement == 0) { if (continueRequirement == 0) {
if(continueButton != null) {
add(continueButton); add(continueButton);
}
} else { } else {
DefaultButton requiredStepsNeeds = new DefaultButton(Integer.toString(continueRequirement) + " Points Left"); DefaultButton requiredStepsNeeds = new DefaultButton(Integer.toString(continueRequirement) + " Points Left");
@@ -1,15 +1,22 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
public class BasicPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
import static dnd.ImageManager.*;
public class BasicPanel extends JPanel {
private DefaultButton[] optionButtons; private DefaultButton[] optionButtons;
private String[] options; private String[] options;
private ImageInfoPanel infoPanel; private InfoPanel infoPanel;
private int choiceIndex; private int choiceIndex;
private String panelTitle; private String panelTitle;
private ImageManager images;
private int currentPanel;
public BasicPanel(JPanel navPanel, String[] options, String[] descriptions, String panelTitle) { public BasicPanel(JPanel navPanel, String[] options, String[] descriptions, String panelTitle, ImageManager images) {
super(); super();
this.options = options; this.options = options;
@@ -24,17 +31,46 @@ public class BasicPanel extends JPanel implements AppTheme {
}; };
this.infoPanel = new ImageInfoPanel(options, descriptions, basicBounds, Integer.parseInt(Character.toString(panelTitle.charAt(5)))); this.images = images;
infoPanel.updateInfo(0); // Default start with 0th element.
infoPanel = new InfoPanel(options, descriptions, basicBounds, images);
currentPanel = Integer.parseInt(Character.toString(panelTitle.charAt(5)));
System.out.println("CurrentPanel: " + currentPanel);
choiceIndex = 0; choiceIndex = 0;
panelSetup(); panelSetup();
createMasterPanel(); createMasterPanel();
infoPanel.updateInfo(choiceIndex, getNextPortrait(choiceIndex));
add(navPanel, BorderLayout.SOUTH); 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() { private void panelSetup() {
setBackground(lightBrown); setBackground(lightBrown);
@@ -96,7 +132,9 @@ public class BasicPanel extends JPanel implements AppTheme {
private DefaultButton createButton(String holderName, int index) { private DefaultButton createButton(String holderName, int index) {
DefaultButton button = new DefaultButton(holderName); DefaultButton button = new DefaultButton(holderName);
button.addActionListener(e -> updateButtons(index)); button.addActionListener(e -> {
updateButtons(index);
});
return button; return button;
@@ -108,10 +146,21 @@ public class BasicPanel extends JPanel implements AppTheme {
optionButtons[newIndex].select(); optionButtons[newIndex].select();
choiceIndex = newIndex; choiceIndex = newIndex;
if(currentPanel == 1 || currentPanel == 2) {
infoPanel.updateInfo(choiceIndex, getNextPortrait(choiceIndex));
} else {
System.out.println("No image chosen.");
infoPanel.updateInfo(choiceIndex); infoPanel.updateInfo(choiceIndex);
} }
}
public int getChoice() { public int getChoice() {
return choiceIndex; 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;
}
}
@@ -1,4 +1,8 @@
public class CharacterStats { package dnd;
import java.io.Serializable;
public class CharacterStats implements Serializable {
private Stats[] stats; private Stats[] stats;
@@ -1,4 +1,8 @@
public class Charisma extends Stats { package dnd;
import java.io.Serializable;
public class Charisma extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
@@ -1,8 +1,12 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import java.awt.*; import java.awt.*;
public class ChooseAbilityScoresPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
public class ChooseAbilityScoresPanel extends JPanel {
private DefaultButton[] statInfoButtons; private DefaultButton[] statInfoButtons;
private JLabel[] statLabels; private JLabel[] statLabels;
@@ -30,7 +34,7 @@ public class ChooseAbilityScoresPanel extends JPanel implements AppTheme {
}; };
infoPanel = new InfoPanel(statOptions, statDescriptions, abilityScoreBounds, 3); infoPanel = new InfoPanel(statOptions, statDescriptions, abilityScoreBounds);
infoPanel.updateInfo(0); // Default start with 0th element. infoPanel.updateInfo(0); // Default start with 0th element.
createMasterPanel(panelTitle); createMasterPanel(panelTitle);
@@ -82,13 +86,13 @@ public class ChooseAbilityScoresPanel extends JPanel implements AppTheme {
private JPanel createAbilityPanel(String ability, int statIndex) { private JPanel createAbilityPanel(String ability, int statIndex) {
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setFont(paragraphFont); panel.setFont(paragraphText);
panel.setBackground(medBrown); panel.setBackground(medBrown);
panel.setBorder(new LineBorder(darkestBrown, 4, true)); panel.setBorder(new LineBorder(darkestBrown, 4, true));
panel.setLayout(new BorderLayout(0, 0)); panel.setLayout(new BorderLayout(0, 0));
DefaultButton tmpButton = new DefaultButton(ability); DefaultButton tmpButton = new DefaultButton(ability);
tmpButton.setFont(paragraphFont); tmpButton.setFont(paragraphText);
tmpButton.setHorizontalAlignment(SwingConstants.CENTER); tmpButton.setHorizontalAlignment(SwingConstants.CENTER);
tmpButton.addActionListener(e -> updateButtons(statIndex)); tmpButton.addActionListener(e -> updateButtons(statIndex));
@@ -107,7 +111,7 @@ public class ChooseAbilityScoresPanel extends JPanel implements AppTheme {
JPanel subPanel = new JPanel(); JPanel subPanel = new JPanel();
JLabel scoreLabel = new JLabel("" + selectedStats[statIndex]); JLabel scoreLabel = new JLabel("" + selectedStats[statIndex]);
scoreLabel.setFont(paragraphFont); scoreLabel.setFont(paragraphText);
scoreLabel.setHorizontalAlignment(SwingConstants.CENTER); scoreLabel.setHorizontalAlignment(SwingConstants.CENTER);
statLabels[statIndex] = scoreLabel; statLabels[statIndex] = scoreLabel;
@@ -1,3 +1,5 @@
package dnd;
public interface ClassTemplate { public interface ClassTemplate {
abstract String getDescription(); abstract String getDescription();
@@ -1,3 +1,5 @@
package dnd;
public class Cleric implements ClassTemplate { public class Cleric implements ClassTemplate {
private int HP; private int HP;
@@ -1,4 +1,8 @@
public class Constitution extends Stats { package dnd;
import java.io.Serializable;
public class Constitution extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
@@ -1,9 +1,13 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
public class DefaultButton extends JButton implements AppTheme { import static dnd.AppConstants.*;
public class DefaultButton extends JButton {
private boolean selected; private boolean selected;
@@ -1,9 +1,12 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.*;
import javax.swing.border.LineBorder;
import java.awt.*; import java.awt.*;
public class DescriptionPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
public class DescriptionPanel extends JPanel {
private BasicNavPanel nav; private BasicNavPanel nav;
private String[] characteristics; private String[] characteristics;
@@ -104,8 +107,6 @@ public class DescriptionPanel extends JPanel implements AppTheme {
private JPanel createBodyPanel() { private JPanel createBodyPanel() {
GridBagConstraints c = new GridBagConstraints();
JPanel bodyPanel = new JPanel(new GridBagLayout()); JPanel bodyPanel = new JPanel(new GridBagLayout());
bodyPanel.setOpaque(false); bodyPanel.setOpaque(false);
@@ -119,6 +120,7 @@ public class DescriptionPanel extends JPanel implements AppTheme {
private JPanel createNamePanel() { private JPanel createNamePanel() {
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setBackground(medBrown); panel.setBackground(medBrown);
for (int i = 0; i < characteristicsHolder.length; i++) { for (int i = 0; i < characteristicsHolder.length; i++) {
@@ -134,15 +136,18 @@ public class DescriptionPanel extends JPanel implements AppTheme {
private JPanel createField(int index) { private JPanel createField(int index) {
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setOpaque(false); panel.setOpaque(false);
JLabel label = new JLabel(characteristicsHolder[index]); JLabel label = new JLabel(characteristicsHolder[index]);
label.setFont(paragraphFont);
label.setFont(paragraphText);
label.setOpaque(false); label.setOpaque(false);
label.setForeground(darkestBrown); label.setForeground(darkestBrown);
JTextField field = new JTextField(10); JTextField field = new JTextField(10);
field.setFont(paragraphFont);
field.setFont(paragraphText);
field.setBackground(lightBrown); field.setBackground(lightBrown);
field.setBorder(null); field.setBorder(null);
@@ -156,6 +161,7 @@ public class DescriptionPanel extends JPanel implements AppTheme {
private JPanel createFooterPanel() { private JPanel createFooterPanel() {
JPanel panel = new JPanel(new GridLayout(1, 3)); JPanel panel = new JPanel(new GridLayout(1, 3));
panel.setOpaque(false); panel.setOpaque(false);
panel.add(createSubPanel("Alignment")); panel.add(createSubPanel("Alignment"));
panel.add(createSubPanel("Background")); panel.add(createSubPanel("Background"));
@@ -168,6 +174,7 @@ public class DescriptionPanel extends JPanel implements AppTheme {
private JPanel createSubPanel(String labelName) { private JPanel createSubPanel(String labelName) {
JPanel panel = new JPanel(new BorderLayout(0, 0)); JPanel panel = new JPanel(new BorderLayout(0, 0));
panel.setBorder(new EmptyBorder(5, 5, 5, 5)); panel.setBorder(new EmptyBorder(5, 5, 5, 5));
panel.setOpaque(false); panel.setOpaque(false);
@@ -219,13 +226,13 @@ public class DescriptionPanel extends JPanel implements AppTheme {
panel.setOpaque(false); panel.setOpaque(false);
JLabel label = new JLabel("Enter a Description"); JLabel label = new JLabel("Enter a Description");
label.setFont(paragraphFont); label.setFont(paragraphText);
label.setOpaque(false); label.setOpaque(false);
label.setForeground(darkestBrown); label.setForeground(darkestBrown);
JTextArea textArea = new JTextArea(); JTextArea textArea = new JTextArea();
textArea.setForeground(darkestBrown); textArea.setForeground(darkestBrown);
textArea.setFont(userTextFont); textArea.setFont(userText);
textArea.setOpaque(false); textArea.setOpaque(false);
textArea.setBorder(new LineBorder(darkestBrown, 3)); textArea.setBorder(new LineBorder(darkestBrown, 3));
@@ -243,8 +250,6 @@ public class DescriptionPanel extends JPanel implements AppTheme {
alignmentChoice = newIndex; alignmentChoice = newIndex;
System.out.println("Updating alignment to index " + newIndex + ", " + alignmentOptions[newIndex]);
} }
private void updateBackgroundButtons(int newIndex) { private void updateBackgroundButtons(int newIndex) {
@@ -254,9 +259,6 @@ public class DescriptionPanel extends JPanel implements AppTheme {
backgroundChoice = newIndex; backgroundChoice = newIndex;
System.out.println("Updating background to index " + newIndex + ", " + backgroundOptions[newIndex]);
} }
private void createButtons(String[] options, DefaultButton[] buttons, String type) { private void createButtons(String[] options, DefaultButton[] buttons, String type) {
@@ -1,4 +1,8 @@
public class Dexterity extends Stats { package dnd;
import java.io.Serializable;
public class Dexterity extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
@@ -2,7 +2,7 @@
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license * 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 * Click nbfs://nbhost/SystemFileSystem/Templates/Character.Classes/Main.java to edit this template
*/ */
package DieRoller; package dnd.DieRoller;
import javax.swing.*; import javax.swing.*;
import java.util.Arrays; import java.util.Arrays;
@@ -1,4 +1,8 @@
public class Fighter implements ClassTemplate { package dnd;
import java.io.Serializable;
public class Fighter implements ClassTemplate, Serializable {
private int HP; private int HP;
@@ -7,7 +11,7 @@ public class Fighter implements ClassTemplate {
// TODO: This should be the type of die. // TODO: This should be the type of die.
private int hitDie; private int hitDie;
public Fighter(Stats[] stats, int level) { public Fighter() {
} }
@@ -85,4 +89,11 @@ public class Fighter implements ClassTemplate {
return null; 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;
}
}
@@ -1,22 +1,38 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import java.awt.*; import java.awt.*;
public class InfoPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
public class InfoPanel extends JPanel {
protected JTextArea[] descriptions; protected JTextArea[] descriptions;
protected Rectangle[] bounds; protected Rectangle[] bounds;
protected String[] holderDescriptions; protected String[] holderDescriptions;
protected String[] categoryHolder; protected String[] categoryHolder;
protected int panelIndex; protected ImageManager images;
public InfoPanel(String[] categoryHolder, String[] holderDescriptions, Rectangle[] bounds, int panelIndex) { 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(); super();
this.categoryHolder = categoryHolder; this.categoryHolder = categoryHolder;
this.holderDescriptions = holderDescriptions; this.holderDescriptions = holderDescriptions;
this.bounds = bounds; this.bounds = bounds;
this.panelIndex = panelIndex;
panelSetup(); panelSetup();
@@ -76,7 +92,7 @@ public class InfoPanel extends JPanel implements AppTheme {
tmpDesc.setOpaque(true); tmpDesc.setOpaque(true);
tmpDesc.setEditable(false); tmpDesc.setEditable(false);
tmpDesc.setFocusable(false); tmpDesc.setFocusable(false);
tmpDesc.setFont(paragraphFont); tmpDesc.setFont(paragraphText);
tmpDesc.setBounds(bounds[2]); tmpDesc.setBounds(bounds[2]);
tmpDesc.setBorder(new EmptyBorder(5, 5, 5, 5)); tmpDesc.setBorder(new EmptyBorder(5, 5, 5, 5));
tmpDesc.setBackground(medBrown); tmpDesc.setBackground(medBrown);
@@ -1,4 +1,8 @@
public class Intelligence extends Stats { package dnd;
import java.io.Serializable;
public class Intelligence extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
+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;
}
}
@@ -1,3 +1,5 @@
package dnd;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.BevelBorder; import javax.swing.border.BevelBorder;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
@@ -5,7 +7,9 @@ import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
public class MainMenuPanel extends JPanel implements AppTheme { import static dnd.AppConstants.*;
public class MainMenuPanel extends JPanel {
private DefaultButton newCharacter; private DefaultButton newCharacter;
private DefaultButton randomCharacter; private DefaultButton randomCharacter;
@@ -1,3 +1,5 @@
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 * 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. * which adds any proficiency bonus to each skill and then adds the ability score modifier to each skill.
@@ -1,3 +1,5 @@
package dnd;
public abstract class Stats { public abstract class Stats {
public int calcSavingThrow(int abilityScore) { public int calcSavingThrow(int abilityScore) {
@@ -1,4 +1,8 @@
public class Strength extends Stats { package dnd;
import java.io.Serializable;
public class Strength extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
+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;
}
}
@@ -1,4 +1,8 @@
public class Wisdom extends Stats { package dnd;
import java.io.Serializable;
public class Wisdom extends Stats implements Serializable {
private int abilityScore; private int abilityScore;
private int abilityScoreModifier; private int abilityScoreModifier;
@@ -1,3 +1,5 @@
package dnd;
public class Wizard implements ClassTemplate { public class Wizard implements ClassTemplate {
private int HP; private int HP;
@@ -1,3 +1,5 @@
package dnd.deprecated;
import javax.swing.border.Border; import javax.swing.border.Border;
import java.awt.*; import java.awt.*;
@@ -1,3 +1,5 @@
package dnd.species;
public class Dragonborn implements Race { public class Dragonborn implements Race {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 80; private final int maxAge = 80;
@@ -1,3 +1,5 @@
package dnd.species;
public class Dwarf implements Race { public class Dwarf implements Race {
private final int speed = 25; private final int speed = 25;
private final int maxAge = 350; private final int maxAge = 350;
@@ -1,4 +1,8 @@
public class Elf implements Race { package dnd.species;
import java.io.Serializable;
public class Elf implements Race, Serializable {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 750; private final int maxAge = 750;
private String[] traits; private String[] traits;
@@ -14,57 +18,65 @@ public class Elf implements Race {
@Override @Override
public String getRace() { public String getRace() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName(); return this.getClass().getSimpleName();
} }
@Override @Override
public int maxAge() { public int maxAge() {
// TODO Auto-generated method stub
return maxAge; return maxAge;
} }
@Override @Override
public int getSpeed() { public int getSpeed() {
// TODO Auto-generated method stub
return speed; return speed;
} }
@Override @Override
public String[] getTraits() { public String[] getTraits() {
// TODO Auto-generated method stub
return traits; return traits;
} }
@Override @Override
public String[] getSkills() { public String[] getSkills() {
// TODO Auto-generated method stub
return skills; return skills;
} }
@Override @Override
public String[] getLanguages() { public String[] getLanguages() {
// TODO Auto-generated method stub
return languages; return languages;
} }
@Override @Override
public String[] getProficiencies() { public String[] getProficiencies() {
// TODO Auto-generated method stub
return proficiencies; return proficiencies;
} }
@Override @Override
public int[] getASI() { public int[] getASI() {
// TODO Auto-generated method stub
return new int[]{1, 1}; return new int[]{1, 1};
} }
@Override @Override
public String toString() { public String toString() {
// TODO Auto-generated method stub
return this.getClass().getSimpleName(); return this.getClass().getSimpleName();
} }
} }
@@ -1,3 +1,5 @@
package dnd.species;
public class Gnome implements Race { public class Gnome implements Race {
private final int speed = 25; private final int speed = 25;
private final int maxAge = 500; private final int maxAge = 500;
@@ -1,3 +1,5 @@
package dnd.species;
public class HalfElf implements Race { public class HalfElf implements Race {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 180; private final int maxAge = 180;
@@ -1,3 +1,5 @@
package dnd.species;
public class HalfOrc implements Race { public class HalfOrc implements Race {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 75; private final int maxAge = 75;
@@ -1,3 +1,5 @@
package dnd.species;
public class Halfling implements Race { public class Halfling implements Race {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 750; private final int maxAge = 750;
@@ -1,3 +1,5 @@
package dnd.species;
public class Human implements Race { public class Human implements Race {
private final int speed = 30; private final int speed = 30;
@@ -1,3 +1,5 @@
package dnd.species;
public interface Race { public interface Race {
String getRace(); String getRace();
@@ -1,3 +1,5 @@
package dnd.species;
public class Tiefling implements Race { public class Tiefling implements Race {
private final int speed = 30; private final int speed = 30;
private final int maxAge = 85; private final int maxAge = 85;
@@ -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");
}
}
+6
View File
@@ -0,0 +1,6 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
org.gradle.parallel=true
org.gradle.caching=true
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+245
View File
@@ -0,0 +1,245 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+92
View File
@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+17
View File
@@ -0,0 +1,17 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/8.1.1/userguide/multi_project_builds.html
* This project uses @Incubating APIs which are subject to change.
*/
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0'
}
rootProject.name = 'dnd'
include('app')
-28
View File
@@ -1,28 +0,0 @@
import java.awt.*;
public interface AppTheme {
public Color lightAccent = Color.decode("#EAF0CE");
public Color lightBrown = Color.decode("#EBBE9B");
public Color medBrown = Color.decode("#E4A677");
public Color darkBrown = Color.decode("#502419");
public Color darkestBrown = Color.decode("#1F0E0A");
public Color black = Color.BLACK;
public Color confirmationBlue = Color.decode("#296EB4");
public Color rejectionRed = Color.decode("#A23E48");
public Font headerFont = new Font("SanSalvi", Font.BOLD, 45);
public Font subHeaderFont = new Font("SanSalvi", Font.PLAIN, 35);
public Font paragraphFont = new Font("SanSalvi", Font.PLAIN, 20);
public Font userTextFont = new Font("SanSalvi", Font.PLAIN, 15);
public Font buttonFont = new Font("SanSalvi", Font.PLAIN, 15);
public String OS = System.getProperty("os.name");
}
-116
View File
@@ -1,116 +0,0 @@
import java.io.Serializable;
public class CharacterSheet implements Serializable {
private String name;
private int age;
private int heightFeet;
private int heightInch;
private int weight;
private String eye;
private String hair;
private Race race;
private CharacterStats stats;
/**
* @param name
* @param age
* @param heightFeet
* @param heightInch
* @param weight
* @param eye
* @param hair
*/
public CharacterSheet(String name, int age,
int heightFeet, int heightInch,
int weight, String eye, String hair,
Race race, CharacterStats stats) {
this.name = name;
this.age = age;
this.heightFeet = heightFeet;
this.heightInch = heightInch;
this.weight = weight;
this.eye = eye;
this.hair = hair;
this.race = race;
this.stats = stats;
}
/**
* Default constructor
*/
public CharacterSheet() {
this.name = "null";
this.age = 0;
this.heightFeet = 0;
this.heightInch = 0;
this.weight = 0;
this.eye = "null";
this.hair = "null";
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @return the heightFeet
*/
public int getHeightFeet() {
return heightFeet;
}
/**
* @return the heightInch
*/
public int getHeightInch() {
return heightInch;
}
/**
* @return the weigth
*/
public int getWeight() {
return weight;
}
/**
* @return the eye
*/
public String getEye() {
return eye;
}
/**
* @return the hair
*/
public String getHair() {
return hair;
}
public CharacterStats getStats() {
return stats;
}
@Override
public String toString() {
return "name: " + name + " | age: " + age + " | height: "
+ heightFeet + "\'" + heightInch + "\" | weight: "
+ weight + " | eye: " + eye + " | hair: " + hair
+ " | race: " + race.toString() + " | stats: " + stats.toString();
}
}
-12
View File
@@ -1,12 +0,0 @@
import java.awt.*;
public interface CustomTheme {
public Color background = null;
public Color foreground = null;
Color getBackground();
Color getForeground();
}
-8
View File
@@ -1,8 +0,0 @@
public class ExportPDF {
public ExportPDF() {
}
}
-115
View File
@@ -1,115 +0,0 @@
import java.awt.*;
import java.io.*;
public class FileManager {
private File[] savedCharacters;
public FileManager() {
findSavedCharacters();
loadFonts();
}
private void loadFonts() {
try {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("SanSalvi.ttf")));
} catch (IOException | FontFormatException e) {
//Handle exception
System.out.println("Error finding font.");
}
}
public boolean isReturninguser() {
if (savedCharacters == null) {
return false;
}
return savedCharacters.length > 0;
}
public CharacterSheet readCharacter(int index) {
CharacterSheet sheet = null;
try {
FileInputStream fileIn = new FileInputStream("/dndBuilder/" + savedCharacters[index].getPath() + ".dnd");
ObjectInputStream in = new ObjectInputStream(fileIn);
sheet = (CharacterSheet) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
} catch (ClassNotFoundException c) {
System.out.println("Saved characters not found");
c.printStackTrace();
}
return sheet;
}
public void saveCharacter(CharacterSheet completedCharacter) {
try {
FileOutputStream fileOut =
new FileOutputStream("/dndBuilder/" + completedCharacter.getName().hashCode() + ".dnd");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(completedCharacter);
out.close();
fileOut.close();
} catch (IOException i) {
i.printStackTrace();
}
findSavedCharacters();
}
public void deleteCharacter(int index) {
File[] tmp = new File[savedCharacters.length - 1];
for (int i = 0; i < savedCharacters.length; i++) {
if (i != index) {
tmp[i] = savedCharacters[i];
}
}
savedCharacters = tmp;
findSavedCharacters();
}
private void findSavedCharacters() {
savedCharacters = new File("/dndBuilder").listFiles();
}
}
-395
View File
@@ -1,395 +0,0 @@
import javax.swing.*;
import java.awt.*;
public class GUImanager extends JFrame {
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(boolean returningUser) {
super("D&D Character Builder");
frameSetup();
setupPanelInfo();
this.panels = new JPanel[]{
new MainMenuPanel(createNewCharacterButton(), createRandomCharacterButton(), createLoadButton()),
new BasicPanel(createNavPanel(), raceOptions, raceDescriptions, "Step 1: Choose Your Race"), // To choose Race.
new BasicPanel(createNavPanel(), classOptions, classDescriptions, "Step 2: Choose Your Class"), // 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")
};
/*
this.currentPanel = 0;
this.lastPanel = currentPanel - 1;
this.nextPanel = currentPanel + 1;*/
if (returningUser) {
this.currentPanel = 0;
} else {
this.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",
"Wisdom",
"Charisma"
};
statDescriptions = new String[]{
"Strength is a thing.",
"Dexterity is a thing",
"Constitution is a thing",
"Intelligence is a thing",
"Wisdom is a thing",
"Charisma is a thing"
};
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[]{
"LG - need description",
"NG - need description",
"cg - need description",
"ln - need description",
"tn - need description",
"cn - need description",
"le - need description",
"ne - need description",
"ce - need description"
};
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 - need description",
"Charlatan - need description",
"Criminal - need description",
"Entertainer - need description",
"Folk Hero - need description",
"Gladiator - need description",
"Guild Artisan - need description",
"Guild Merchant - need description",
"Hermit - need description",
"Knight - need description",
"Noble - need description",
"Outlander - need description",
"Pirate - need description",
"Sage - need description",
"Sailor - need description",
"Soldier - need description",
"Spy - need description",
"Urchin - need description"
};
}
private BasicNavPanel createNavPanel() {
return new BasicNavPanel(createBackButton(), createContinueButton(), 0);
}
private BasicNavPanel createNavPanel(int continueRequirement) {
return new BasicNavPanel(createBackButton(), createContinueButton(), continueRequirement);
}
private DefaultButton createBackButton() {
DefaultButton button = new DefaultButton("Back");
button.addActionListener(
e -> {
lastPanel--;
currentPanel--;
nextPanel--;
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");
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 = 3;
nextPanel = currentPanel + 1;
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();
}
}
-136
View File
@@ -1,136 +0,0 @@
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Objects;
import java.util.Random;
public class ImageInfoPanel extends InfoPanel implements AppTheme {
private JLabel[][] portraits;
private int lastIndex;
public ImageInfoPanel(String[] categoryHolder, String[] holderDescriptions, Rectangle[] bounds, int panelIndex) {
super(categoryHolder, holderDescriptions, bounds, panelIndex);
createPortraits();
}
@Override
public void updateInfo(int holderIndex) {
super.updateInfo(holderIndex, portraits[holderIndex][getNextPortrait(holderIndex)]);
}
private int getNextPortrait(int holderIndex) {
Random ran = new Random();
int bound = portraits[holderIndex].length;
int newIndex = ran.nextInt(bound);
/* while(newIndex == lastIndex) {
newIndex = ran.nextInt(bound);
}*/
lastIndex = newIndex;
return newIndex;
}
private void createPortraits() {
String category = "";
if (panelIndex == 1) {
category = "Races";
} else if (panelIndex == 2) {
category = "Classes";
}
portraits = new JLabel[categoryHolder.length][];
for (int i = 0; i < categoryHolder.length; i++) {
File imagesDir;
if (OS.startsWith("Windows")) {
imagesDir = new File("dndBuilder\\src\\Resources\\Img\\" + category + "\\" + categoryHolder[i].toLowerCase() + "\\");
} else if (OS.startsWith("Mac")) {
imagesDir = new File("dndBuilder/src/Resources/Img/" + category + "/" + categoryHolder[i].toLowerCase() + "/");
} else if (OS.startsWith("Linux")) {
imagesDir = new File("Img/" + category + "/" + categoryHolder[i].toLowerCase());
} else {
System.out.println("Unable to detect operating system.");
return;
}
File[] dir = imagesDir.listFiles();
portraits[i] = new JLabel[dir.length];
int index = 0;
for (File file : dir) {
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 (Exception e) {
System.out.println("Error reading file.");
img = null;
finalImg = null;
}
if (Objects.isNull(finalImg)) {
picture = new JLabel("ERROR: Image not found.");
} else {
picture = new JLabel(new ImageIcon(finalImg));
}
return picture;
}
}
-2
View File
@@ -1,2 +0,0 @@
public class LoadCharacterPanel {
}
-2
View File
@@ -1,2 +0,0 @@
public class PreviewCharacterSheet {
}
-277
View File
@@ -1,277 +0,0 @@
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class step4 extends JPanel implements AppTheme {
private JTextField nameTxtField;
private JTextField ageTextField;
private JTextField heightTxtField;
private JTextField weightTxtField;
private JTextField skinTxtField;
private JTextField eyesTxtField;
private JTextField hairTxtField;
/**
* Create the panel.
*/
public step4() {
createEntirePanel();
}
private void createEntirePanel() {
setBackground(new Color(222, 184, 135));
setBorder(new BevelBorder(BevelBorder.RAISED, new Color(160, 82, 45), new Color(165, 42, 42), new Color(0, 0, 0), null));
setLayout(new BorderLayout(0, 0));
JLabel lblNewLabel = createLbl();
add(lblNewLabel, BorderLayout.NORTH);
//Creates back and continue panel
JPanel backContPanel = createBackContinuePanel();
add(backContPanel, BorderLayout.SOUTH);
JPanel innerPanel = new JPanel();
innerPanel.setToolTipText("");
innerPanel.setOpaque(false);
add(innerPanel, BorderLayout.CENTER);
innerPanel.setLayout(null);
JPanel nameAndAlignment = new JPanel();
nameAndAlignment.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
nameAndAlignment.setBackground(new Color(210, 105, 30));
nameAndAlignment.setBounds(6, 6, 306, 114);
innerPanel.add(nameAndAlignment);
nameAndAlignment.setLayout(null);
JLabel nameLbl = new JLabel("Character Name: ");
nameLbl.setBounds(6, 6, 108, 16);
nameAndAlignment.add(nameLbl);
nameTxtField = new JTextField();
nameTxtField.setBounds(121, 1, 173, 26);
nameAndAlignment.add(nameTxtField);
nameTxtField.setColumns(10);
JLabel ageLbl = new JLabel("Age: ");
ageLbl.setBounds(6, 34, 32, 16);
nameAndAlignment.add(ageLbl);
ageTextField = new JTextField();
ageTextField.setBounds(61, 34, 64, 21);
nameAndAlignment.add(ageTextField);
ageTextField.setColumns(10);
JLabel heightLbl = new JLabel("Height: ");
heightLbl.setBounds(6, 62, 55, 16);
nameAndAlignment.add(heightLbl);
heightTxtField = new JTextField();
heightTxtField.setBounds(61, 57, 64, 26);
nameAndAlignment.add(heightTxtField);
heightTxtField.setColumns(10);
JLabel weightLbl = new JLabel("Weight:");
weightLbl.setBounds(6, 90, 61, 16);
nameAndAlignment.add(weightLbl);
weightTxtField = new JTextField();
weightTxtField.setBounds(61, 85, 64, 26);
nameAndAlignment.add(weightTxtField);
weightTxtField.setColumns(10);
JLabel skinLbl = new JLabel("Skin: ");
skinLbl.setBounds(131, 34, 35, 16);
nameAndAlignment.add(skinLbl);
skinTxtField = new JTextField();
skinTxtField.setBounds(165, 29, 130, 26);
nameAndAlignment.add(skinTxtField);
skinTxtField.setColumns(10);
JLabel eyesLbl = new JLabel("Eyes: ");
eyesLbl.setBounds(130, 62, 42, 16);
nameAndAlignment.add(eyesLbl);
eyesTxtField = new JTextField();
eyesTxtField.setBounds(164, 57, 130, 26);
nameAndAlignment.add(eyesTxtField);
eyesTxtField.setColumns(10);
JLabel hairLbl = new JLabel("Hair: ");
hairLbl.setBounds(127, 90, 39, 16);
nameAndAlignment.add(hairLbl);
hairTxtField = new JTextField();
hairTxtField.setBounds(164, 85, 130, 26);
nameAndAlignment.add(hairTxtField);
hairTxtField.setColumns(10);
JPanel alignmentPanel = new JPanel();
alignmentPanel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
alignmentPanel.setBackground(new Color(205, 133, 63));
alignmentPanel.setBounds(324, 6, 396, 114);
innerPanel.add(alignmentPanel);
alignmentPanel.setLayout(new BorderLayout(0, 0));
JLabel alignmentLbl = new JLabel("Alignment");
alignmentLbl.setFont(new Font("Lucida Grande", Font.PLAIN, 19));
alignmentLbl.setHorizontalAlignment(SwingConstants.CENTER);
alignmentPanel.add(alignmentLbl, BorderLayout.NORTH);
JPanel alignmentInnerPanel = new JPanel();
alignmentInnerPanel.setOpaque(false);
alignmentPanel.add(alignmentInnerPanel, BorderLayout.CENTER);
alignmentInnerPanel.setLayout(new GridLayout(3, 3, 0, 0));
JButton btnLawfulGood = new JButton("Lawful Good");
alignmentInnerPanel.add(btnLawfulGood);
JButton btnNuetralGood = new JButton("Neutral Good");
alignmentInnerPanel.add(btnNuetralGood);
JButton btnChaoticGood = new JButton("Chaotic Good");
alignmentInnerPanel.add(btnChaoticGood);
JButton btnLawfulNeutral = new JButton("Lawful Neutral");
alignmentInnerPanel.add(btnLawfulNeutral);
JButton btnTrueNeutral = new JButton("True Neutral");
alignmentInnerPanel.add(btnTrueNeutral);
JButton btnChaoticNeutral = new JButton("Chaotic Neutral");
alignmentInnerPanel.add(btnChaoticNeutral);
JButton btnLawfulEvil = new JButton("Lawful Evil");
alignmentInnerPanel.add(btnLawfulEvil);
JButton btnNeutralEvil = new JButton("Neutral Evil");
alignmentInnerPanel.add(btnNeutralEvil);
JButton btnChaoticEvil = new JButton("Chaotic Evil");
alignmentInnerPanel.add(btnChaoticEvil);
JPanel backgroundPanel = new JPanel();
backgroundPanel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
backgroundPanel.setBackground(new Color(210, 105, 30));
backgroundPanel.setBounds(6, 132, 306, 264);
innerPanel.add(backgroundPanel);
backgroundPanel.setLayout(new BorderLayout(0, 0));
JLabel backgroundLbl = new JLabel("Background");
backgroundLbl.setFont(new Font("Dialog", Font.PLAIN, 20));
backgroundLbl.setHorizontalAlignment(SwingConstants.CENTER);
backgroundPanel.add(backgroundLbl, BorderLayout.NORTH);
JPanel backgroundInnerPanel = new JPanel();
backgroundInnerPanel.setOpaque(false);
backgroundPanel.add(backgroundInnerPanel, BorderLayout.CENTER);
backgroundInnerPanel.setLayout(new GridLayout(9, 2, 0, 0));
JButton btnAcolyte = new JButton("Acolyte");
backgroundInnerPanel.add(btnAcolyte);
JButton btnCharlatan = new JButton("Charlatan");
backgroundInnerPanel.add(btnCharlatan);
JButton btnCriminal = new JButton("Criminal");
backgroundInnerPanel.add(btnCriminal);
JButton btnEntertainer = new JButton("Entertainer");
backgroundInnerPanel.add(btnEntertainer);
JButton btnFolkHero = new JButton("Folk Hero");
backgroundInnerPanel.add(btnFolkHero);
JButton btnGladiator = new JButton("Gladiator");
backgroundInnerPanel.add(btnGladiator);
JButton btnGuildArtisan = new JButton("Guild Artisan");
backgroundInnerPanel.add(btnGuildArtisan);
JButton btnGuildMerchant = new JButton("Guild Merchant");
backgroundInnerPanel.add(btnGuildMerchant);
JButton btnHermit = new JButton("Hermit");
backgroundInnerPanel.add(btnHermit);
JButton btnKnight = new JButton("Knight");
backgroundInnerPanel.add(btnKnight);
JButton btnNoble = new JButton("Noble");
backgroundInnerPanel.add(btnNoble);
JButton btnOutlander = new JButton("Outlander");
backgroundInnerPanel.add(btnOutlander);
JButton btnPirate = new JButton("Pirate");
backgroundInnerPanel.add(btnPirate);
JButton btnSage = new JButton("Sage");
backgroundInnerPanel.add(btnSage);
JButton btnSailor = new JButton("Sailor");
backgroundInnerPanel.add(btnSailor);
JButton btnSoldier = new JButton("Soldier");
backgroundInnerPanel.add(btnSoldier);
JButton btnSpy = new JButton("Spy");
backgroundInnerPanel.add(btnSpy);
JButton btnUrchin = new JButton("Urchin");
backgroundInnerPanel.add(btnUrchin);
JPanel panel = new JPanel();
panel.setBackground(new Color(205, 133, 63));
panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel.setBounds(324, 132, 396, 264);
panel.setLayout(new BorderLayout(0, 0));
JLabel lblDescription = new JLabel("Description");
lblDescription.setFont(new Font("Lucida Grande", Font.PLAIN, 20));
lblDescription.setHorizontalAlignment(SwingConstants.CENTER);
JTextArea textArea = new JTextArea();
textArea.setBackground(new Color(238, 232, 170));
panel.add(lblDescription, BorderLayout.NORTH);
panel.add(textArea, BorderLayout.CENTER);
innerPanel.add(panel);
}
private JPanel createBackContinuePanel() {
JPanel backContPanel = new JPanel();
backContPanel.setBackground(new Color(205, 133, 63));
JButton backBtn = new JButton("<--- Back ");
backBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
backContPanel.add(backBtn);
JButton continueBtn = new JButton("Continue --->");
continueBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
backContPanel.add(continueBtn);
return backContPanel;
}
/**
* @return
*/
private JLabel createLbl() {
JLabel titleLbl = new JLabel("Step 4: Description");
titleLbl.setHorizontalAlignment(SwingConstants.CENTER);
titleLbl.setFont(new Font("Bodoni 72 Oldstyle", Font.PLAIN, 33));
return titleLbl;
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More