Jump to content

[Java] Game Tracker v2.0


Freak
 Share

Recommended Posts

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:

main-menu.png

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.

Initiative.png

Then you have the new module, which is the loot tracker which has 2 different GUIs depending on the ruleset you choose:

special.pngGeneric.png

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:

about.png

And when you use the module to get a piece of loot, you will see a popup like this:

popup.png

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:

popup2.png

Edited by Freak
  • I Like This! 1
Link to comment
Share on other sites

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 by WarFox
  • I Like This! 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...