Freak Posted June 8, 2019 Share Posted June 8, 2019 (edited) So Warfox and I have been working on this ever since my previous post here. Many additional features and bug fixes were added to the DnD initiative tracker, and we've added an entire new module (also for DnD) to track loot drops. We're up to a whopping 7 class files: Main.java Spoiler import initiativeDnD.DnD; import lootTableDnD.Loot; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JButton; import java.awt.GridLayout; import java.util.ArrayList; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; class Main { /* * Main entry point of program */ public static void main(String[] args) { Main main = new Main(); main.run(); } /* * Creates the JFrame that holds the Main menu */ public void run() { JFrame mainFrame = new JFrame("Main Menu"); mainFrame.setVisible(true); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setSize(500, 500); mainFrame.add(gameMenuPanel()); } /* * Generates the panel of game options and populates. */ protected JPanel gameMenuPanel() { JPanel panel = new JPanel(); panel.setLayout(new GridLayout()); panel.setVisible(true); ArrayList<JButton> gameButtons = this.gameChoicesButtons(); for (JButton game : gameButtons) { panel.add(game); game.addActionListener(new EventHandler()); } return panel; } /* * Generates a button for each game name. */ protected ArrayList<JButton> gameChoicesButtons() { ArrayList<JButton> games = new ArrayList<>(); ArrayList<String> gameNames = this.gameNames(); for (String game: gameNames) { games.add(new JButton(game)); } return games; } /* * Creates the list of game names. */ protected ArrayList<String> gameNames() { ArrayList<String> games = new ArrayList<>(); games.add("DnD Initiative"); games.add("DnD Loot"); return games; } /* * Class that will handle events within this class. */ private class EventHandler implements ActionListener { public void actionPerformed (ActionEvent e) { String choice = e.getActionCommand(); if (choice.equals("DnD Initiative")) { DnD.run(); }else if(choice.equals("DnD Loot")){ Loot.run(); } } } } initiativeDnD: DnD.java Spoiler package initiativeDnD; import javax.swing.JOptionPane; public class DnD { public static Mob head = null; public static int initiativeSpot = 0; public static void run(){ head = null; initiativeDnD.GUI myInterface = new initiativeDnD.GUI(); myInterface.pack(); myInterface.setVisible(true); myInterface.setResizable(true); } public static String genDisplayText(){ String displayText = ""; Mob tempMob = head; for(int i = 1; tempMob != null; i++){ if(tempMob.getName() == null){ break; } displayText += i + ": " + tempMob.getName() + "\t" + "( " + (tempMob.getHp()-tempMob.getDmg()) + " / " + tempMob.getHp() + " )"; if(i == initiativeSpot){ displayText += "***"; } displayText += "\n"; tempMob = tempMob.getNextMob(); } return displayText; } public static void damage(int num, int dmg, Mob thisMob){ num--; if(num == 0){ thisMob.addDmg(dmg); if(! thisMob.isAlive()){ JOptionPane.showMessageDialog(null, thisMob.getName() + " is dead!"); }else if(thisMob.getDmg() > thisMob.getHp()/2){ JOptionPane.showMessageDialog(null, thisMob.getName() + " is looking bloody! (Past half HP)"); } }else{ if(thisMob == null){ JOptionPane.showMessageDialog(null, "That was an invalid mob number."); }else if(thisMob.getNextMob() == null){ JOptionPane.showMessageDialog(null, "That was an invalid mob number."); }else{ damage(num, dmg, thisMob.getNextMob()); } } } } GUI.java Spoiler package initiativeDnD; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.FileReader; import java.io.PrintWriter; import java.util.Arrays; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; @SuppressWarnings("serial") public class GUI extends JFrame{ private Mob currentMob = null; private JMenuBar menuBar; private JMenu file; private JMenuItem save; private JMenuItem load; private JMenu window; private JMenuItem textSize; private JMenu textStyle; private JMenuItem plain; private JMenuItem bold; private JMenuItem italic; private JFileChooser chooser; private JButton add; private JButton damage; private JButton next; private JButton clear; private JTextArea display; private JScrollPane scrollPane; private Font theFont; public GUI(){ super("Initiative Tracker"); setLayout(new GridBagLayout()); GridBagConstraints c=new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; theFont = new Font("Calibri", Font.PLAIN, 12); /*---------------------------------- * Menu Bar */ menuBar = new JMenuBar(); setJMenuBar(menuBar); file = new JMenu("File"); menuBar.add(file); save = new JMenuItem("Save"); file.add(save); load = new JMenuItem("Load"); file.add(load); window = new JMenu("Window"); menuBar.add(window); textSize = new JMenuItem("Text Size"); window.add(textSize); textStyle = new JMenu("Text Style"); window.add(textStyle); plain = new JMenuItem("Plain"); textStyle.add(plain); bold = new JMenuItem("Bold"); textStyle.add(bold); italic = new JMenuItem("Italic"); textStyle.add(italic); chooser = new JFileChooser(); /*---------------------------------- * Display stuff */ display = new JTextArea(22, 30); display.setText("<Mob info will appear here>"); display.setEditable(false); display.setFont(theFont); c.gridx = 0; c.gridy = 0; c.gridwidth = 3; c.gridheight = 2; add(display, c); scrollPane = new JScrollPane(display); add(scrollPane, c); /*---------------------------------- * Button stuff */ add = new JButton("Add a mob"); add.setToolTipText("Add another enemy, NPC, or player character to the encounter."); c.gridx = 0; c.gridy = 3; c.gridwidth = 1; c.gridheight = 1; add(add, c); damage = new JButton("Do damage"); damage.setToolTipText("Record damage that was done to an enemy, NPC, or player character."); c.gridx = 2; c.gridy = 3; c.gridwidth = 1; c.gridheight = 1; add(damage, c); next = new JButton("Next ->"); next.setToolTipText("Skip to the next enemy, NPC, or player character in initiative."); c.gridx = 0; c.gridy = 2; c.gridwidth = 3; c.gridheight = 1; add(next, c); clear = new JButton("Clear"); next.setToolTipText("Delete this encounter."); c.gridx = 1; c.gridy = 3; c.gridwidth = 1; c.gridheight = 1; add(clear, c); /*--------------------------------- * event handlers and action listeners */ getRootPane().setDefaultButton(next); EventHandler handler = new EventHandler(); add.addActionListener(handler); damage.addActionListener(handler); next.addActionListener(handler); clear.addActionListener(handler); save.addActionListener(handler); load.addActionListener(handler); textSize.addActionListener(handler); plain.addActionListener(handler); bold.addActionListener(handler); italic.addActionListener(handler); } private class EventHandler implements ActionListener{ public void actionPerformed(ActionEvent event){ if(event.getSource()==add){ if(DnD.initiativeSpot == 0){ Mob newMob = new Mob(); newMob.setName(JOptionPane.showInputDialog("Enter the name: ").replaceAll(":", "")); //null pointer if they click cancel... boolean bad = false; do{ try{ newMob.setHp(Integer.parseInt(JOptionPane.showInputDialog("Enter the max HP: "))); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "HP value must be a number."); bad = true; continue; } bad = false; }while(bad); do{ try{ newMob.addInitiative(Integer.parseInt(JOptionPane.showInputDialog("Enter their initiative: "))); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "Initiative value must be a number."); bad = true; continue; } bad = false; }while(bad); if(DnD.head == null){ DnD.head = newMob; }else{ newMob.insertSelf(DnD.head, null); } display.setText(DnD.genDisplayText()); }else{ JOptionPane.showMessageDialog(null, "You may only add new participants at the top of initiative."); } }else if(event.getSource()==damage){ int n = 0, d = 0; boolean bad = false; do{ try{ n = Integer.parseInt(JOptionPane.showInputDialog("Mob number: ")); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "Mob number must be a positive integer."); bad = true; continue; } if(n<1){ JOptionPane.showMessageDialog(null, "Mob number must be a positive integer."); bad = true; continue; } bad = false; }while(bad); do{ try{ d = Integer.parseInt(JOptionPane.showInputDialog("Enter the amount of damage to be done: ")); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "Damage must be a positive integer."); bad = true; continue; } bad = false; }while(bad); DnD.damage(n, d, DnD.head); display.setText(DnD.genDisplayText()); }else if(event.getSource()==next){ if(DnD.head != null){ do{ if(currentMob == null){ currentMob = DnD.head; DnD.initiativeSpot++; }else{ if(currentMob.getNextMob() == null){ currentMob = null; DnD.initiativeSpot = 0; }else{ currentMob = currentMob.getNextMob(); DnD.initiativeSpot++; } } if(currentMob == null){ //ugh... break; } }while(!currentMob.isAlive()); display.setText(DnD.genDisplayText()); if(DnD.initiativeSpot == 0){ JOptionPane.showMessageDialog(null, "Top of initiative! You may now add new mobs to the encounter, or press Next again to keep playing."); }else{ JOptionPane.showMessageDialog(null, "It's " + currentMob.getName() + "'s turn!"); } } }else if(event.getSource()==clear){ if(JOptionPane.showConfirmDialog(null, "Are you SURE you want to clear?") == 0){ DnD.head = null; DnD.initiativeSpot = 0; display.setText(DnD.genDisplayText()); } }else if(event.getSource()==save){ if(chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION){ try{ PrintWriter writer = new PrintWriter(chooser.getSelectedFile()); Mob tempMob = DnD.head; while(tempMob != null){ writer.print(tempMob.getName()+":"+tempMob.getHp()+":"+tempMob.getDmg()+":"+Arrays.toString(tempMob.getInitiative())+"\n"); tempMob=tempMob.getNextMob(); } writer.close(); }catch(Exception e) { JOptionPane.showMessageDialog(null, e); } } }else if(event.getSource()==load){ JOptionPane.showMessageDialog(null, "Any unsaved progress will be lost."); if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){ try{ BufferedReader reader = new BufferedReader(new FileReader(chooser.getSelectedFile().getAbsolutePath())); String line; String lineArr[]; Mob newHead = new Mob(); Mob tempMob = newHead; while((line = reader.readLine()) != null){ lineArr = line.split(":"); tempMob.setName(lineArr[0]); tempMob.setHp(Integer.parseInt(lineArr[1])); tempMob.addDmg(Integer.parseInt(lineArr[2])); line = lineArr[3]; line = line.replaceAll("\\[", ""); line = line.replaceAll("\\]", ""); line = line.replaceAll(" ", ""); lineArr = line.split(","); for(int i = 0; i<lineArr.length; ++i){ tempMob.addInitiative(Integer.parseInt(lineArr[i])); } tempMob.setNextMob(new Mob()); tempMob = tempMob.getNextMob(); } reader.close(); DnD.head = newHead; display.setText(DnD.genDisplayText()); }catch(Exception e) { JOptionPane.showMessageDialog(null, e); } } }else if(event.getSource()==textSize){ try{ theFont = theFont.deriveFont(Float.parseFloat(JOptionPane.showInputDialog("Enter text size: "))); display.setFont(theFont); pack(); }catch(Exception e){ JOptionPane.showMessageDialog(null, "Improper input"); } }else if(event.getSource()==plain){ theFont = theFont.deriveFont(Font.PLAIN); display.setFont(theFont); }else if(event.getSource()==bold){ theFont = theFont.deriveFont(Font.BOLD); display.setFont(theFont); }else if(event.getSource()==italic){ theFont = theFont.deriveFont(Font.ITALIC); display.setFont(theFont); } } } } Mob.java Spoiler package initiativeDnD; import javax.swing.JOptionPane; public class Mob { private int hp; private String name = null; private int initiative[] = {}; private int dmgTaken = 0; private Mob nextMob = null; public Mob(){ } /*---------------------------------- * Getters */ public int getDmg(){ return dmgTaken; } public int getHp(){ return hp; } public boolean isAlive(){ if(dmgTaken < hp){ return true; }else{ return false; } } public String getName(){ return name; } public Mob getNextMob(){ return nextMob; } public int[] getInitiative(){ return initiative; } /*---------------------------------- * Setters */ public void setHp(int theHp){ hp = theHp; } public void addDmg(int dmg){ dmgTaken += dmg; if(dmgTaken > hp){ dmgTaken = hp; }else if(dmgTaken < 0){ dmgTaken = 0; } } public void addInitiative(int num){ int temp[] = initiative; initiative = new int[temp.length + 1]; for(int i = 0; i<temp.length; i++){ initiative[i] = temp[i]; } initiative[initiative.length - 1] = num; } public void setName(String theName){ name = theName; } public void setNextMob(Mob theNextMob){ nextMob = theNextMob; } public void insertSelf(Mob current, Mob last){ boolean bad; for(int i = 0;; i++){ if(this.getInitiative()[i] > current.getInitiative()[i]){ if(last == null){ this.nextMob = DnD.head; DnD.head = this; }else{ this.nextMob = current; last.setNextMob(this); } break; }else if(this.getInitiative()[i] < current.getInitiative()[i]){ if(current.nextMob == null){ current.setNextMob(this); }else{ insertSelf(current.nextMob, current); } break; }else{ bad = false; if(i+1 == this.getInitiative().length ){ do{ try{ this.addInitiative(Integer.parseInt(JOptionPane.showInputDialog(this.getName() + " must roll again for initiative:"))); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "Initiative value must be a number."); bad = true; continue; } bad = false; }while(bad); } if(i+1 == current.getInitiative().length){ do{ try{ current.addInitiative(Integer.parseInt(JOptionPane.showInputDialog(current.getName() + " must roll again for initiative:"))); }catch(NumberFormatException e){ JOptionPane.showMessageDialog(null, "Initiative value must be a number."); bad = true; continue; } bad = false; }while(bad); } } } } } lootTableDnD: Loot.java Spoiler package lootTableDnD; import java.io.BufferedReader; import java.io.FileReader; import javax.swing.JOptionPane; public class Loot { public static void run(){ int choice; lootTableDnD.GUI myInterface = null; /*Special rules are those used by Freak's friends. (Requires a loot table with 1000 items) D12 determines what you get D1000 determines what kind of item you get D20 decides number of coins (if platinum, then halved) D10 decides coin multiplier */ choice = JOptionPane.showConfirmDialog(null, "Would you like to use the special rules?"); if(choice == 0){ //Special rules myInterface = new lootTableDnD.GUI(true); myInterface.setVisible(true); myInterface.setResizable(false); }else if(choice == 1){ //Generic rules myInterface = new lootTableDnD.GUI(false); myInterface.setVisible(true); myInterface.setResizable(false); } } public static void getSpecialItem(String path, int reward, int hundreds, int tens, int ones, int coins, int multi){ int lootNum; String line = "", type = ""; boolean item = false; double multi2 = 1; if(reward == 1){ //Copper type = "Copper"; }else if(reward == 2){ //Silver type = "Silver"; }else if(reward == 3){ //Gold type = "Gold"; }else if(reward == 4){ //Platinum type = "Platinum"; multi2 = .5; }else if(reward == 5){ //Item + Copper type = "Copper"; item = true; }else if(reward == 6){ //Item + Silver type = "Silver"; item = true; }else if(reward == 7){ //Item + Gold type = "Gold"; item = true; }else if(reward == 8){ //Item + Platinum type = "Platinum"; multi2 = .5; item = true; }else if(reward == 9){ //Item item = true; coins = 0; }else if(reward == 10){ //Item item = true; coins = 0; }else if(reward == 11){ //Nothing JOptionPane.showMessageDialog(null, "Empty"); return; }else if(reward == 12){ //Nothing JOptionPane.showMessageDialog(null, "Empty"); return; } if(item){ if(hundreds == 0 && tens == 0 && ones == 0){ lootNum = 1000; }else{ lootNum = (hundreds*100)+(tens*10)+(ones); } try{ BufferedReader reader = new BufferedReader(new FileReader(path)); for(int i = 1; i<lootNum; ++i){ reader.readLine(); } line = reader.readLine(); reader.close(); }catch (Exception e){ JOptionPane.showMessageDialog(null, e); } Popup popup = new Popup(((int)(coins*multi*multi2))+" "+type, line); popup.setVisible(true); }else{ JOptionPane.showMessageDialog(null, "Coins: "+((int)(coins*multi*multi2))+" "+type); } } public static void getGenericItem(String path, int lootNum){ String line = ""; try{ BufferedReader reader = new BufferedReader(new FileReader(path)); for(int i = 1; i<lootNum; ++i){ reader.readLine(); } line = reader.readLine(); reader.close(); }catch (Exception e){ JOptionPane.showMessageDialog(null, e); } if(line == null){ JOptionPane.showMessageDialog(null, "There are fewer than "+lootNum+" items in the table."); }else{ Popup popup = new Popup("0", line); popup.setVisible(true); } } } GUI.java Spoiler package lootTableDnD; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.FileReader; import java.util.Random; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.filechooser.FileNameExtensionFilter; @SuppressWarnings("serial") public class GUI extends JDialog{ private JMenuBar menuBar; private JMenu file; private JMenuItem selectTable; private JMenuItem about; private JButton randomRolls; private JButton myRolls; private JLabel[] specialLabels; private JLabel genericLabel; private JTextField[] fields; private JFileChooser chooser; private boolean type; private String path = ""; public GUI(boolean t){ setLayout(new GridBagLayout()); GridBagConstraints c=new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; menuBar = new JMenuBar(); setJMenuBar(menuBar); file = new JMenu("File"); menuBar.add(file); selectTable = new JMenuItem("Select Loot Table"); file.add(selectTable); about = new JMenuItem("About"); menuBar.add(about); chooser = new JFileChooser(); chooser.setFileFilter(new FileNameExtensionFilter("CSV Files" , "csv")); type = t; if(t){ //Special GUI ------------------------------------------------- String labelText[] = { "<html><pre>Reward------d12: </pre></html>", "<html><pre>Hundreds----d10: </pre></html>", "<html><pre>Tens--------d10: </pre></html>", "<html><pre>Ones--------d10: </pre></html>", "<html><pre>Coins-------d20: </pre></html>", "<html><pre>Multiplier--d10: </pre></html>"}; specialLabels = new JLabel[6]; for(int i = 0; i<specialLabels.length; ++i){ specialLabels[i] = new JLabel(labelText[i]); c.gridx = 0; c.gridy = i; c.insets = new Insets(2,10,2,0); add(specialLabels[i], c); } fields = new JTextField[6]; for(int i = 0; i<fields.length; ++i){ fields[i] = new JTextField(5); c.gridx = 1; c.gridy = i; c.insets = new Insets(2,0,2,10); add(fields[i], c); } myRolls = new JButton("Get Loot"); c.gridx = 0; c.gridy = 6; c.gridwidth = 2; c.insets = new Insets(2,10,2,10); add(myRolls, c); randomRolls = new JButton("Random Loot"); c.gridx = 0; c.gridy = 7; c.gridwidth = 2; c.insets = new Insets(2,10,8,10); add(randomRolls, c); }else{ //Generic GUI ------------------------------------------------- genericLabel = new JLabel("Item number: "); c.gridx = 0; c.gridy = 0; c.insets = new Insets(2,10,2,0); add(genericLabel, c); fields = new JTextField[1]; fields[0] = new JTextField(5); c.gridx = 1; c.gridy = 0; c.insets = new Insets(2,0,2,10); add(fields[0], c); myRolls = new JButton("Get Loot"); c.gridx = 0; c.gridy = 1; c.gridwidth = 2; c.insets = new Insets(2,10,2,10); add(myRolls, c); randomRolls = new JButton("Random Loot"); c.gridx = 0; c.gridy = 2; c.gridwidth = 2; c.insets = new Insets(2,10,8,10); add(randomRolls, c); } pack(); /*--------------------------------- * event handlers and action listeners */ getRootPane().setDefaultButton(myRolls); EventHandler handler = new EventHandler(); randomRolls.addActionListener(handler); myRolls.addActionListener(handler); selectTable.addActionListener(handler); about.addActionListener(handler); } private class EventHandler implements ActionListener{ public void actionPerformed(ActionEvent event){ if(event.getSource()==myRolls){ if(path == ""){ JOptionPane.showMessageDialog(null, "First select a loot table."); }else{ if(type){ //Special rules boolean check = true; try{ //Check that entries are valid. if( (Integer.parseInt(fields[0].getText()) > 12 || Integer.parseInt(fields[0].getText()) < 1) || (Integer.parseInt(fields[1].getText()) > 9 || Integer.parseInt(fields[1].getText()) < 0) || (Integer.parseInt(fields[2].getText()) > 9 || Integer.parseInt(fields[2].getText()) < 0) || (Integer.parseInt(fields[3].getText()) > 9 || Integer.parseInt(fields[3].getText()) < 0) || (Integer.parseInt(fields[4].getText()) > 20 || Integer.parseInt(fields[4].getText()) < 1) || (Integer.parseInt(fields[5].getText()) > 10 || Integer.parseInt(fields[5].getText()) < 1) ){ JOptionPane.showMessageDialog(null, "Invalid entry. Make sure all values are within the bounds."); check = false; } }catch(Exception e){ JOptionPane.showMessageDialog(null, "Invalid entry: Make sure all values are integers."); check = false; } if(check){ Loot.getSpecialItem(path, Integer.parseInt(fields[0].getText()), Integer.parseInt(fields[1].getText()), Integer.parseInt(fields[2].getText()), Integer.parseInt(fields[3].getText()), Integer.parseInt(fields[4].getText()), Integer.parseInt(fields[5].getText())); } }else{ //Generic rules try{ Loot.getGenericItem(path, Integer.parseInt(fields[0].getText())); }catch(Exception e){ JOptionPane.showMessageDialog(null, "Invalid entry: Make sure all values are integers."); } } } }else if(event.getSource()==randomRolls){ if(path == ""){ JOptionPane.showMessageDialog(null, "First select a loot table."); }else{ Random rand = new Random(); if(type){ //Special rules fields[0].setText(Integer.toString(rand.nextInt(12)+1)); fields[1].setText(Integer.toString(rand.nextInt(10))); fields[2].setText(Integer.toString(rand.nextInt(10))); fields[3].setText(Integer.toString(rand.nextInt(10))); fields[4].setText(Integer.toString(rand.nextInt(20)+1)); fields[5].setText(Integer.toString(rand.nextInt(10)+1)); Loot.getSpecialItem(path, Integer.parseInt(fields[0].getText()), Integer.parseInt(fields[1].getText()), Integer.parseInt(fields[2].getText()), Integer.parseInt(fields[3].getText()), Integer.parseInt(fields[4].getText()), Integer.parseInt(fields[5].getText())); }else{ //Generic rules int lineCount = 0; try{ BufferedReader reader = new BufferedReader(new FileReader(path)); while((reader.readLine()) != null){ ++lineCount; } reader.close(); }catch(Exception e){ JOptionPane.showMessageDialog(null, e); } fields[0].setText(Integer.toString(rand.nextInt(lineCount)+1)); Loot.getGenericItem(path, Integer.parseInt(fields[0].getText())); } } }else if(event.getSource()==selectTable){ if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){ path = chooser.getSelectedFile().getAbsolutePath(); } }else if(event.getSource()==about){ JOptionPane.showMessageDialog(null, "This program automatically calculates rewards and grabs loot from a standardized loot table.\n\n" +"Loot table specificatinos:\n" +"* Must be .csv format.\n" +"* Must be formatted as: \"Name,Description,Value,Rarity,Weight,Category,Properties,Requirements,Author\"\n" +"* Loot tables may leave out any of those categories, but must contain the same or more commas.\n\n" +"Special rules:\n" +"* Loot tables must have exactly 1000 items.\n" +"* Uses many dice to determine loot (Documented in both the \"run\" and \"getSpecialItem\" methods of the Loot.java class)\n"); } } } } Popup.java Spoiler package lootTableDnD; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.border.Border; @SuppressWarnings("serial") public class Popup extends JFrame{ private JLabel coinsLabel; private JTextField coinsField; private JLabel nameLabel; private JTextField nameField; private JLabel descriptionLabel; private JTextArea descriptionArea; private JScrollPane descriptionScroll; private JLabel valueLabel; private JTextField valueField; private JLabel rarityLabel; private JTextField rarityField; private JLabel weightLabel; private JTextField weightField; private JLabel categoryLabel; private JTextField categoryField; private JLabel propertiesLabel; private JTextArea propertiesArea; private JScrollPane propertiesScroll; private JLabel requirementsLabel; private JTextArea requirementsArea; private JScrollPane requirementsScroll; private JLabel authorLabel; private JTextField authorField; private Font theFont; public Popup(String coinsLine, String itemLine){ super("Your loot"); setLayout(new GridBagLayout()); GridBagConstraints c=new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; theFont = new Font("Calibri", Font.PLAIN, 16); UIManager.put("TextField.font", theFont); UIManager.put("TextArea.font", theFont); theFont = new Font("Calibri", Font.BOLD, 16); UIManager.put("Label.font", theFont); int first = 0, second; while(true){ first = itemLine.indexOf("\"", first); second = itemLine.indexOf("\"", first+1); if(first < 0 || second < 0){ break; }else{ itemLine = itemLine.substring(0, first) + itemLine.substring(first, second).replaceAll(",", "") + itemLine.substring(second, itemLine.length()); first = second; } } String itemArr[] = (itemLine+",,,,,,,").replaceAll("\"", "").split(","); //I add commas to avoid ArrayIndexOutOfBoundsException later. try{ Integer.parseInt(coinsLine.replaceAll("\\s","")); }catch(Exception e){ coinsLabel = new JLabel("Coins: "); coinsLabel.setFont(theFont); c.gridx = 0; c.gridy = 0; c.insets = new Insets(10,10,60,10); add(coinsLabel, c); coinsField = new JTextField(coinsLine){@Override public void setBorder(Border border){}}; coinsField.setEditable(false); c.gridx = 1; c.gridy = 0; add(coinsField, c); } c.insets = new Insets(4,10,4,10); if(!itemArr[0].isEmpty()){ nameLabel = new JLabel("Item name: "); c.gridx = 0; c.gridy = 1; add(nameLabel, c); nameField = new JTextField(itemArr[0]){@Override public void setBorder(Border border){}}; nameField.setEditable(false); c.gridx = 1; c.gridy = 1; add(nameField, c); } if(!itemArr[1].isEmpty()){ descriptionLabel = new JLabel("Description:"); c.gridx = 0; c.gridy = 2; add(descriptionLabel, c); descriptionArea = new JTextArea(8,20); descriptionArea.setLineWrap(true); descriptionArea.setText(itemArr[1]); descriptionArea.setEditable(false); c.gridx = 0; c.gridy = 3; c.gridwidth = 2; add(descriptionArea, c); descriptionScroll = new JScrollPane(descriptionArea); add(descriptionScroll, c); } if(!itemArr[2].isEmpty()){ valueLabel = new JLabel("Value: "); c.gridx = 0; c.gridy = 4; c.gridwidth = 1; add(valueLabel, c); valueField = new JTextField(itemArr[2]){@Override public void setBorder(Border border){}}; valueField.setEditable(false); c.gridx = 1; c.gridy = 4; add(valueField, c); } if(!itemArr[3].isEmpty()){ rarityLabel = new JLabel("Rarity: "); c.gridx = 0; c.gridy = 5; add(rarityLabel, c); rarityField = new JTextField(itemArr[3]){@Override public void setBorder(Border border){}}; rarityField.setEditable(false); c.gridx = 1; c.gridy = 5; add(rarityField, c); } if(!itemArr[4].isEmpty()){ weightLabel = new JLabel("Weight: "); c.gridx = 0; c.gridy = 6; add(weightLabel, c); weightField = new JTextField(itemArr[4]){@Override public void setBorder(Border border){}}; weightField.setEditable(false); c.gridx = 1; c.gridy = 6; add(weightField, c); } if(!itemArr[5].isEmpty()){ categoryLabel = new JLabel("Category: "); c.gridx = 0; c.gridy = 7; add(categoryLabel,c); categoryField = new JTextField(itemArr[5]){@Override public void setBorder(Border border){}}; categoryField.setEditable(false); c.gridx = 1; c.gridy = 7; add(categoryField, c); } if(!itemArr[6].isEmpty()){ propertiesLabel = new JLabel("Properties: "); c.gridx = 0; c.gridy = 8; add(propertiesLabel, c); propertiesArea = new JTextArea(6, 20); propertiesArea.setLineWrap(true); propertiesArea.setText(itemArr[6]); propertiesArea.setEditable(false); c.gridx = 0; c.gridy = 9; c.gridwidth = 2; add(propertiesArea, c); propertiesScroll = new JScrollPane(propertiesArea); add(propertiesScroll, c); } if(!itemArr[7].isEmpty()){ requirementsLabel = new JLabel("Requirements: "); c.gridx = 0; c.gridy = 10; c.gridwidth = 1; add(requirementsLabel, c); requirementsArea = new JTextArea(4, 20); requirementsArea.setLineWrap(true); requirementsArea.setText(itemArr[7]); requirementsArea.setEditable(false); c.gridx = 0; c.gridy = 11; c.gridwidth = 2; add(requirementsArea, c); requirementsScroll = new JScrollPane(requirementsArea); add(requirementsScroll, c); } if(!itemArr[8].isEmpty()){ authorLabel = new JLabel("Author: "); c.insets = new Insets(10,10,4,10); c.gridx = 0; c.gridy = 12; c.gridwidth = 1; add(authorLabel, c); authorField = new JTextField(itemArr[8]){@Override public void setBorder(Border border){}}; authorField.setEditable(false); c.gridx = 1; c.gridy = 12; add(authorField, c); } pack(); } } As for what's changed, we now have a snazzy main menu where you can choose your module: Starting with the Initiative module, it still looks fairly similar, but now with an added toolbar at the top. You can change the text size and style under the window menu, and under File you have the option to save current encounters, and load older ones. This allows DMs to even set up encounters ahead of time, and load them up once the players reach them. Then you have the new module, which is the loot tracker which has 2 different GUIs depending on the ruleset you choose: Under the File menu, you have the option to open a .csv database which is your loot table. If you press About, then you will get this popup explaining the module: And when you use the module to get a piece of loot, you will see a popup like this: And the absolute best part of all is that if any of those fields were to be empty, such as an item that has no description or a weightless item such as a potion, then that field will be automatically omitted from the popup like so: Edited July 6, 2020 by Freak 1 Link to comment Share on other sites More sharing options...
WarFox Posted June 13, 2019 Share Posted June 13, 2019 (edited) New module added. Magic The Gathering Life Point Tracker. Here is the code for the class. I will get everything commented later on and edit this post. Spoiler import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JTextField; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JOptionPane; public class MTGLifeTracker implements ActionListener { private ArrayList<Player> players; private JFrame mainFrame; private JButton exitButton; private JButton damageButton; private JButton healButton; public void run () { players = new ArrayList<>(); setPlayers(); setLifePoints(); mainGUI(); } public JFrame mainGUI () { mainFrame = new JFrame("Magic The Gathering"); mainFrame.setVisible(true); mainFrame.setDefaultLookAndFeelDecorated(true); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.setLayout(new BorderLayout()); mainFrame.setSize(500, 500); mainFrame.add(titlePanel(), BorderLayout.NORTH); mainFrame.add(playerPanel(), BorderLayout.CENTER); mainFrame.add(gameOptionsPanel(), BorderLayout.SOUTH); return mainFrame; } private JPanel titlePanel() { JPanel panel = new JPanel(); JLabel label = new JLabel("Magic The Gather: Life Points Tracker"); panel.add(label); return panel; } private JPanel playerPanel () { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(players.size(), 2)); for (Player p : players) { JLabel playerLabel = new JLabel(p.getPlayerName()); panel.add(playerLabel); JLabel playerLifePoints = new JLabel(Integer.toString(p.getPlayerLifePoints())); panel.add(playerLifePoints); } return panel; } private JPanel gameOptionsPanel () { JPanel panel = new JPanel(); damageButton = new JButton("Damage Player"); damageButton.addActionListener(this); healButton = new JButton("Heal Player"); healButton.addActionListener(this); panel.add(damageButton); panel.add(healButton); return panel; } private void setPlayers () { String playerNames = JOptionPane.showInputDialog("Enter Player names (seperated by commas" + "\n" + "(ex) jim,john,tom"); String[] playerNamesSplit = playerNames.split(","); for (int i = 0; i < playerNamesSplit.length; i++) { Player p = new Player(playerNamesSplit[i]); players.add(p); } } private void setLifePoints() { int lifePoints = 0; try { lifePoints = Integer.parseInt(JOptionPane.showInputDialog("Enter life points (must be an integer)")); } catch (Exception e) { setLifePoints(); } for (Player p : players) { p.setPlayerLifePoints(lifePoints); } } private void doDamage () { String playerName = JOptionPane.showInputDialog("Enter player to damage"); int damage = Integer.parseInt(JOptionPane.showInputDialog("Damage to Player:")); for (Player p : players) { if (playerName.equals(p.getPlayerName())) { p.damagePlayer(damage); } } } private void doHeal () { String playerName = JOptionPane.showInputDialog("Enter player to heal"); int heal = Integer.parseInt(JOptionPane.showInputDialog("Point to add:")); for (Player p : players) { if (playerName.equals(p.getPlayerName())) { p.healPlayer(heal); } } } public void actionPerformed (ActionEvent e) { String event = e.getActionCommand(); if (event == "Damage Player") { doDamage(); } if (event == "Heal Player") { doHeal(); } mainFrame.dispose(); mainGUI(); } private class Player { private String playerName; private int playerLifePoints; public Player (String initPlayerName, int initPlayerLifePoints) { playerName = initPlayerName; playerLifePoints = initPlayerLifePoints; } public Player (String initPlayerName) { playerName = initPlayerName; } public void setPlayerName (String initPlayerName) { playerName = initPlayerName; } public void setPlayerLifePoints (int initPlayerLifePoints) { playerLifePoints = initPlayerLifePoints; } public String getPlayerName () { return playerName; } public int getPlayerLifePoints () { return playerLifePoints; } public void damagePlayer (int damageTaken) { playerLifePoints = playerLifePoints - damageTaken; } public void healPlayer (int healthGained) { playerLifePoints = playerLifePoints + healthGained; } public String toString () { return playerName; } } } Edited June 13, 2019 by WarFox 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now