├── src └── app │ ├── terminal │ ├── TerminalCommand.java │ ├── CommandMap.java │ ├── TerminalEventListener.java │ ├── MenuEvent.java │ ├── QueryEvent.java │ ├── SubmitEvent.java │ ├── CommandExecutor.java │ ├── TerminalDisplayComponent.java │ ├── TerminalKeylistener.java │ ├── PropertyHandler.java │ ├── TerminalIOComponent.java │ └── Terminal.java │ ├── core │ ├── items │ │ ├── Consumable.java │ │ ├── ItemEffect.java │ │ ├── DiceRoll.java │ │ ├── Weapon.java │ │ ├── Equippable.java │ │ ├── ItemBuilder.java │ │ ├── Item.java │ │ └── Armor.java │ ├── character │ │ ├── Attribute.java │ │ ├── Skill.java │ │ ├── Ability.java │ │ ├── CounterStat.java │ │ ├── Stat.java │ │ ├── Inventory.java │ │ ├── StatEditor.java │ │ ├── StatIO.java │ │ └── PlayerCharacter.java │ └── magic │ │ ├── SpellSlot.java │ │ ├── Spell.java │ │ └── SpellBook.java │ ├── io │ ├── MagicIO.java │ ├── PlayerCreator.java │ ├── PlayerLeveler.java │ ├── PlayerHealer.java │ ├── SpellBookIO.java │ ├── AbilityPointsIO.java │ ├── SpellIO.java │ ├── ItemBuilderIO.java │ ├── SkillIO.java │ ├── ItemIO.java │ ├── PropertiesHandler.java │ ├── SpellSlotIO.java │ ├── ReadWriteHandler.java │ └── InventoryIO.java │ ├── utils │ └── Message.java │ └── CharacterCommand.java ├── .idea ├── vcs.xml ├── kotlinc.xml ├── modules.xml ├── codeStyleSettings.xml ├── artifacts │ └── CharacterCommand_jar.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml └── uiDesigner.xml ├── .gitattributes ├── README.md ├── CharacterCommand.iml ├── .gitignore └── CODE_OF_CONDUCT.md /src/app/terminal/TerminalCommand.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | 4 | public interface TerminalCommand { 5 | void executeCommand(); 6 | } 7 | -------------------------------------------------------------------------------- /src/app/terminal/CommandMap.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.util.LinkedHashMap; 4 | 5 | public class CommandMap extends LinkedHashMap { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /src/app/terminal/TerminalEventListener.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | public interface TerminalEventListener { 4 | void submitActionPerformed(SubmitEvent e); 5 | void queryActionPerformed(QueryEvent e); 6 | void menuActionPerformed(MenuEvent e); 7 | } 8 | -------------------------------------------------------------------------------- /src/app/terminal/MenuEvent.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.awt.event.ActionEvent; 4 | 5 | public class MenuEvent extends ActionEvent { 6 | 7 | public MenuEvent(Object source, int id, String command) { 8 | super(source, id, command); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/terminal/QueryEvent.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.awt.event.ActionEvent; 4 | 5 | public class QueryEvent extends ActionEvent { 6 | 7 | public QueryEvent(Object source, int id, String command, String inputString) { 8 | super(source, id, command); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | -------------------------------------------------------------------------------- /src/app/terminal/SubmitEvent.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.awt.event.ActionEvent; 4 | 5 | public class SubmitEvent extends ActionEvent { 6 | public String inputString; 7 | 8 | public SubmitEvent(Object source, int id, String commandID, String inputString ) { 9 | super(source, id, commandID); 10 | this.inputString = inputString; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CharacterCommand 2 | ### A Command-Line D&D Character Manager 3 | Create, edit, save, and export multiple characters, all via a command-line interface! 4 | ### Featuring: 5 | - Items, Equipment, and Enchantments 6 | - Spell casting and learning 7 | - Skill training 8 | - Dice rolling 9 | - and more! 10 | 11 | ##### For a list of commands, enter: 'help' 12 | ##### For details, enter: 'help ' or ' --help' 13 | ___ 14 | -------------------------------------------------------------------------------- /CharacterCommand.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/artifacts/CharacterCommand_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/ 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/core/items/Consumable.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | 5 | public class Consumable extends Item{ 6 | private static final long serialVersionUID = CharacterCommand.VERSION; 7 | public Consumable(String name) { 8 | super(name); 9 | this.setConsumable(true); 10 | } 11 | 12 | public Consumable(String name, int count) { 13 | super(name, count); 14 | this.setConsumable(true); 15 | } 16 | 17 | public void use(int amount){ 18 | this.addCount(-amount); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/core/character/Attribute.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | 5 | public class Attribute extends Stat { 6 | private static final long serialVersionUID = CharacterCommand.VERSION; 7 | public static final String HP = "hp"; 8 | public static final String AC = "ac"; 9 | public static final String PB = "pb"; 10 | public static final String NAC ="nac"; 11 | 12 | public Attribute(){ 13 | super(); 14 | } 15 | public Attribute(String name, double baseVal){ 16 | super(name, baseVal); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/terminal/CommandExecutor.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | public class CommandExecutor { 4 | public void doCommand(Terminal terminal, String token){ 5 | TerminalCommand command = terminal.getCommandMap().get(token); 6 | if(command != null) { 7 | terminal.newLine(); 8 | command.executeCommand(); 9 | } else { 10 | terminal.newLine(); 11 | terminal.println("Command '"+token+"' not found"); 12 | } 13 | terminal.getCommandTokens().clear(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/terminal/TerminalDisplayComponent.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.awt.*; 4 | 5 | public class TerminalDisplayComponent extends TerminalIOComponent { 6 | public TerminalDisplayComponent(){ 7 | this.setEditable(false); 8 | this.setMargin(new Insets(5,5,5,5)); 9 | this.setBackground(new Color(33,33,33)); 10 | this.setForeground(new Color(245,245,245)); 11 | this.setCaretColor(new Color(245,245,245)); 12 | this.setFont(new Font("consolas", Font.PLAIN, 17)); 13 | this.setFocusable(false); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /src/app/core/items/ItemEffect.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.Stat; 5 | 6 | import java.io.Serializable; 7 | 8 | public class ItemEffect implements Serializable{ 9 | private static final long serialVersionUID = CharacterCommand.VERSION; 10 | private Stat target; 11 | private int bonus; 12 | 13 | public ItemEffect(Stat target, int bonus){ 14 | this.target = target; 15 | this.bonus= bonus; 16 | } 17 | 18 | public Stat getTarget() { 19 | return target; 20 | } 21 | public void setTarget(Stat target) { 22 | this.target = target; 23 | } 24 | 25 | public int getBonus() { 26 | return bonus; 27 | } 28 | public void setBonus(int bonus) { 29 | this.bonus = bonus; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/app/core/items/DiceRoll.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | 5 | import java.io.Serializable; 6 | import java.util.Random; 7 | 8 | public class DiceRoll implements Serializable{ 9 | private static final long serialVersionUID = CharacterCommand.VERSION; 10 | private int count; 11 | private int sides; 12 | 13 | public DiceRoll(int count, int sides){ 14 | this.count = count; 15 | this.sides = sides; 16 | } 17 | 18 | public int roll(){ 19 | int result=0; 20 | Random random = new Random(); 21 | for (int i=0; i, Serializable{ 8 | private static final long serialVersionUID = CharacterCommand.VERSION; 9 | private String spellName; 10 | private int spellLevel; 11 | protected boolean spellPrepared; 12 | 13 | public static final int CANTRIP = 0; 14 | public static final int MAX_LEVEL = 9; 15 | 16 | public Spell(String name, int level){ 17 | if(level > MAX_LEVEL){ 18 | level = MAX_LEVEL; 19 | } 20 | if(level < CANTRIP){ 21 | level = CANTRIP; 22 | } 23 | this.spellLevel = level; 24 | this.spellName = name; 25 | } 26 | 27 | public void prepare(){ 28 | this.spellPrepared = true; 29 | } 30 | 31 | public void unprep(){ 32 | this.spellPrepared = false; 33 | } 34 | 35 | public int getSpellLevel(){ 36 | return this.spellLevel; 37 | } 38 | 39 | public String getSpellName(){ 40 | return this.spellName; 41 | } 42 | 43 | public boolean isCantrip(){ 44 | if (spellLevel == Spell.CANTRIP){ 45 | return true; 46 | } else { 47 | return false; 48 | } 49 | } 50 | 51 | @Override 52 | public int compareTo(Spell spell) { 53 | return spellLevel - spell.getSpellLevel(); 54 | } 55 | 56 | @Override 57 | public String toString(){ 58 | String s; 59 | if (this.spellLevel == 0){ 60 | s = "Cantrip - "; 61 | } else { 62 | s = "Level "+this.spellLevel+" - "; 63 | } 64 | s += String.format("%s", this.spellName); 65 | if (spellPrepared){ 66 | s += " [Prepared]"; 67 | } 68 | return s; 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/app/utils/Message.java: -------------------------------------------------------------------------------- 1 | package app.utils; 2 | 3 | import app.terminal.Terminal; 4 | 5 | public class Message{ 6 | public static final String ERROR_NO_VALUE = "ERROR: No value given"; 7 | public static final String ERROR_ITEM_TYPE = "ERROR: Not a valid item type"; 8 | //public static final String ERROR_NO_LOAD = "\033[1;31mERROR: No active character\033[0m"; 9 | public static final String ERROR_NO_LOAD = "ERROR: No active character"; 10 | public static final String ERROR_SYNTAX = "ERROR: Syntax not recognized"; 11 | public static final String ERROR_NAN = "ERROR: Not a number"; 12 | public static final String ERROR_NOT_INT = "ERROR: Not an integer value"; 13 | public static final String ERROR_INPUT = "ERROR: Invalid input"; 14 | public static final String ERROR_NO_COMMAND = "ERROR: Command not found"; 15 | public static final String ERROR_NO_CHAR = "ERROR: Character not found"; 16 | public static final String ERROR_NO_ARG = "ERROR: Missing argument(s)"; 17 | public static final String ERROR_NOT_EQUIP = "ERROR: Item not equippable"; 18 | public static final String ERROR_NOT_CON = "ERROR: Item not consumable"; 19 | 20 | 21 | public static final String MSG_NOT_CAST = "Not a spellcaster"; 22 | public static final String MSG_NO_ITEM = "No item by that name"; 23 | public static final String MSG_NO_SPELL = "No spell by that name"; 24 | public static final String MSG_NO_SKILL = "No skill by that name"; 25 | public static final String MSG_NO_STAT = "No stat by that name"; 26 | 27 | public static void errorMessage(Terminal terminal, String message){ 28 | terminal.println(message); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/core/magic/SpellBook.java: -------------------------------------------------------------------------------- 1 | package app.core.magic; 2 | 3 | import app.CharacterCommand; 4 | 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.LinkedHashMap; 9 | 10 | public class SpellBook implements Serializable { 11 | private static final long serialVersionUID = CharacterCommand.VERSION; 12 | private LinkedHashMap spellIndex; 13 | private ArrayList spellList; 14 | 15 | public SpellBook(){ 16 | spellIndex = new LinkedHashMap(); 17 | spellList = new ArrayList(); 18 | } 19 | 20 | public boolean contains(Spell spell){ 21 | if(spellIndex.containsKey(spell.getSpellName().toLowerCase())){ 22 | return true; 23 | } else { 24 | return false; 25 | } 26 | } 27 | 28 | public boolean isEmpty(){ 29 | return spellIndex.isEmpty(); 30 | } 31 | 32 | public void learn(Spell spell){ 33 | String key = spell.getSpellName().toLowerCase(); 34 | if(!spellIndex.containsKey(key)){ 35 | spellIndex.put(key, spell); 36 | spellList.add(spellIndex.get(key)); 37 | Collections.sort(spellList); 38 | } 39 | } 40 | 41 | public void forget(Spell spell){ 42 | spellList.remove(spell); 43 | spellIndex.remove(spell.getSpellName().toLowerCase()); 44 | } 45 | 46 | public Spell get(String spellName){ 47 | return spellIndex.get(spellName.toLowerCase()); 48 | } 49 | 50 | public String toString(){ 51 | String newLine = System.lineSeparator(); 52 | String s="---- SPELLBOOK -----------------"; 53 | for(Spell spell:spellList){ 54 | s+=newLine+" "+spell; 55 | } 56 | return s+newLine+"--------------------------------"; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/app/terminal/TerminalKeylistener.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.awt.event.KeyEvent; 4 | import java.awt.event.KeyListener; 5 | 6 | public class TerminalKeylistener implements KeyListener { 7 | private TerminalIOComponent inputComponent; 8 | 9 | public TerminalKeylistener(TerminalIOComponent inputComponent){ 10 | this.inputComponent = inputComponent; 11 | } 12 | 13 | @Override 14 | public void keyTyped(KeyEvent e) { 15 | 16 | } 17 | 18 | @Override 19 | public void keyPressed(KeyEvent e) { 20 | if(inputComponent.getCaretPosition() < inputComponent.getLastPromptPos()){ 21 | inputComponent.setCaretPosition(inputComponent.getText().length()); 22 | } 23 | if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE){ 24 | if(inputComponent.getCaretPosition() <= inputComponent.getLastPromptPos()){ 25 | inputComponent.disableBackSpace(); 26 | } else { 27 | if(!inputComponent.isAllowBackSpace()){ 28 | inputComponent.enableBackSpace(); 29 | } 30 | } 31 | } 32 | if(e.getKeyCode() == KeyEvent.VK_ENTER){ 33 | if(inputComponent.isQuerying()){ 34 | inputComponent.fireEvent(new QueryEvent(inputComponent, 1, "query-event", inputComponent.getInput())); 35 | inputComponent.setQuerying(false); 36 | } else { 37 | inputComponent.fireEvent(new SubmitEvent(inputComponent, 1, "submit-event", inputComponent.getInput())); 38 | } 39 | } 40 | } 41 | 42 | @Override 43 | public void keyReleased(KeyEvent e) { 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/app/core/character/Ability.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | 5 | import java.io.Serializable; 6 | public class Ability extends Attribute implements Serializable{ 7 | private static final long serialVersionUID = CharacterCommand.VERSION; 8 | private double mod; 9 | public static final String[] ABILITY_NAMES = new String[]{"STR", "DEX", "CON", "INT", "WIS", "CHA"}; 10 | public static final String STR = "str"; 11 | public static final String DEX = "dex"; 12 | public static final String CON = "con"; 13 | public static final String INT = "int"; 14 | public static final String WIS = "wis"; 15 | public static final String CHA = "cha"; 16 | 17 | public Ability(){ 18 | super(); 19 | this.mod = getMod(); 20 | } 21 | 22 | public Ability(String name, double baseVal){ 23 | super(name, baseVal); 24 | this.mod=getMod(); 25 | } 26 | 27 | public double getMod(){ 28 | this.mod = Math.floor((this.getBaseVal() + this.getBonusVal() - 10) / 2); 29 | return mod; 30 | } 31 | 32 | @Override 33 | public String toString(){ 34 | return String.format("%s: %.0f (%+.0f)", this.getName(), this.getTotal(), this.getMod()); 35 | } 36 | 37 | @Override 38 | public String detailString() { 39 | String newLine = System.lineSeparator(); 40 | return String.format("---- %s"+ 41 | newLine+"Base value: %.0f"+ 42 | newLine+"Bonuses: %+.0f"+ 43 | newLine+"Ability Mod: %+.0f"+ 44 | newLine+"Total: %.0f (%+.0f)"+ 45 | newLine+"--------------------------------", 46 | this.getName(), 47 | this.getBaseVal(), 48 | this.getBonusVal(), 49 | this.getMod(), 50 | this.getTotal(), 51 | this.getMod() 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/core/character/CounterStat.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | 5 | public class CounterStat extends Stat { 6 | private static final long serialVersionUID = CharacterCommand.VERSION; 7 | private double currVal; 8 | 9 | public CounterStat(){ 10 | super(); 11 | this.currVal = this.getMaxVal(); 12 | } 13 | public CounterStat(String name, double baseVal){ 14 | super(name, baseVal); 15 | this.currVal = this.getMaxVal(); 16 | } 17 | 18 | public void countUp(){ 19 | if(this.currVal0){ 25 | this.currVal--; 26 | } 27 | } 28 | public void countUp(double amt){ 29 | if(this.currVal+amt0){ 37 | this.currVal -= amt; 38 | } else { 39 | this.currVal = 0; 40 | } 41 | } 42 | 43 | public void setCurrVal(double val){ 44 | this.currVal = val; 45 | } 46 | public double getCurrVal(){ 47 | return this.currVal; 48 | } 49 | 50 | public double getMaxVal(){ 51 | return this.getBaseVal(); 52 | } 53 | public void setMaxVal(double val){ 54 | this.setBaseVal(val); 55 | if(this.currVal>getMaxVal()){ 56 | this.currVal = getMaxVal(); 57 | } 58 | } 59 | 60 | @Override 61 | public String toString(){ 62 | return String.format("%s: %.0f/%.0f", this.getName(), this.getCurrVal(), this.getMaxVal()); 63 | } 64 | public String detailString() { 65 | String newLine = System.lineSeparator(); 66 | return String.format("---- %s" + 67 | newLine+"Current value: %.0f"+ 68 | newLine+"Max value: %.0f"+ 69 | newLine+"--------------------------------", 70 | this.getName(), 71 | this.currVal, 72 | this.getMaxVal() 73 | ); 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/app/io/PlayerCreator.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.Ability; 5 | import app.core.character.PlayerCharacter; 6 | 7 | public class PlayerCreator { 8 | public static void createCharacter() { 9 | String name; 10 | while (true) { 11 | name = CharacterCommand.terminal.queryString("Character name: ", false); 12 | if (CharacterCommand.isValidName(name)) { 13 | break; 14 | } 15 | } 16 | String raceName = CharacterCommand.terminal.queryString("Race: ", false); 17 | String className = CharacterCommand.terminal.queryString("Class: ", false); 18 | PlayerCharacter c = new PlayerCharacter(name, raceName, className); 19 | for (String key : c.getAbilities().keySet()) { 20 | Ability a = c.getAbilities().get(key); 21 | a.setBaseVal(CharacterCommand.terminal.queryInteger("Enter "+a.getName() + " score: ", false)); 22 | } 23 | if (CharacterCommand.terminal.queryYN("Spellcaster? [Y/N] : ")) { 24 | Ability spellAbility = null; 25 | while (spellAbility == null) { 26 | String abilityName = CharacterCommand.terminal.queryString("Spellcasting ability: ", false).toLowerCase(); 27 | spellAbility = c.getAbilities().get(abilityName); 28 | if (spellAbility == null) { 29 | CharacterCommand.terminal.println("ERROR: Ability not found"); 30 | } else { 31 | c.setSpellcaster(true); 32 | c.initMagicStats(spellAbility); 33 | } 34 | } 35 | } else { 36 | c.setSpellcaster(false); 37 | } 38 | c.updateStats(); 39 | CharacterCommand.characterList.put(c.getName().toLowerCase(), c); 40 | CharacterCommand.terminal.println("Created "+c.getName()); 41 | CharacterCommand.setActiveChar(c); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/core/items/Equippable.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | 6 | import java.util.ArrayList; 7 | 8 | public class Equippable extends Item { 9 | private static final long serialVersionUID = CharacterCommand.VERSION; 10 | private boolean equipped; 11 | private ArrayList effects; 12 | 13 | public Equippable(String name) { 14 | super(name); 15 | this.setEquipped(false); 16 | this.setEquippable(true); 17 | } 18 | 19 | public Equippable(String name, int count) { 20 | super(name, count); 21 | this.setEquipped(false); 22 | this.setEquippable(true); 23 | } 24 | 25 | @Override 26 | public void equip(PlayerCharacter c){ 27 | this.setEquipped(true); 28 | if(effects!=null){ 29 | for (ItemEffect e : effects){ 30 | if (e != null){ 31 | e.getTarget().addBonusVal(e.getBonus()); 32 | } 33 | } 34 | } 35 | } 36 | 37 | @Override 38 | public void dequip(PlayerCharacter c){ 39 | this.setEquipped(false); 40 | if(effects!=null){ 41 | for (ItemEffect e : effects){ 42 | if (e != null){ 43 | e.getTarget().addBonusVal(-e.getBonus()); 44 | } 45 | } 46 | } 47 | } 48 | @Override 49 | public boolean isEquipped() { 50 | return equipped; 51 | } 52 | public void setEquipped(boolean equipped) { 53 | this.equipped = equipped; 54 | } 55 | 56 | public ArrayList getEffects() { 57 | return effects; 58 | } 59 | public Equippable setEffects(ArrayList effects) { 60 | this.effects = effects; 61 | return this; 62 | } 63 | public void addEffect(ItemEffect effect) { 64 | if(this.effects==null){ 65 | this.effects = new ArrayList<>(); 66 | } 67 | this.effects.add(effect); 68 | } 69 | 70 | /*@Override 71 | public String toString(){ 72 | String s = String.format("%dx %s", this.getCount(), this.getName()); 73 | return s; 74 | }*/ 75 | } 76 | -------------------------------------------------------------------------------- /src/app/core/character/Stat.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | 5 | import java.io.Serializable; 6 | 7 | public class Stat implements Serializable { 8 | private static final long serialVersionUID = CharacterCommand.VERSION; 9 | private String name; 10 | private double baseVal; 11 | private double bonusVal; 12 | 13 | public Stat(){ 14 | this.name=null; 15 | this.baseVal = 0; 16 | this.bonusVal = 0; 17 | } 18 | public Stat(String name, double baseVal){ 19 | this.name=name; 20 | this.baseVal=baseVal; 21 | this.bonusVal = 0; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public double getBaseVal() { 32 | return baseVal; 33 | } 34 | public void setBaseVal(double baseVal) { 35 | this.baseVal = baseVal; 36 | } 37 | 38 | public double getBonusVal(){ 39 | return this.bonusVal; 40 | } 41 | public void setBonusVal(double val){ 42 | this.bonusVal = val; 43 | } 44 | public void addBonusVal(double val){ 45 | this.bonusVal += val; 46 | } 47 | public void decBonusVal(double val){ 48 | this.bonusVal -= val; 49 | } 50 | 51 | public void incrementBaseVal(){ 52 | this.baseVal++; 53 | } 54 | public void decrementBaseVal(){ 55 | this.baseVal--; 56 | } 57 | public void incrementBaseVal(double val){ 58 | this.baseVal+=val; 59 | } 60 | public void decrementBaseVal(double val){ 61 | this.baseVal-=val; 62 | } 63 | 64 | public double getTotal(){ 65 | return (this.baseVal+this.bonusVal); 66 | } 67 | 68 | @Override 69 | public String toString(){ 70 | return String.format("%s: %.0f", this.name, this.getTotal()); 71 | } 72 | 73 | public String detailString() { 74 | String newLine = System.lineSeparator(); 75 | return String.format("---- %s"+ 76 | newLine+"Base value: %.0f"+ 77 | newLine+"Bonuses: %+.0f"+ 78 | newLine+"Total: %.0f"+ 79 | newLine+"--------------------------------", 80 | this.name, 81 | this.baseVal, 82 | this.bonusVal, 83 | this.getTotal() 84 | ); 85 | } 86 | } 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/app/core/items/ItemBuilder.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Created by mshem_000 on 7/19/2017. 7 | */ 8 | public class ItemBuilder{ 9 | public String itemName; 10 | public String itemDescription; 11 | public Item.ItemType itemType = Item.ItemType.ITEM; 12 | public int itemCount = 1; 13 | public int itemValue; 14 | //public boolean equippable; 15 | //public boolean consumable; 16 | public Armor.ArmorType armorType; 17 | public int armorClass; 18 | public DiceRoll damage; 19 | 20 | private ArrayList itemEffects; 21 | 22 | public ItemBuilder(){ 23 | itemEffects = new ArrayList<>(); 24 | } 25 | 26 | public void addEffect(app.core.character.Stat target, int bonus){ 27 | itemEffects.add(new ItemEffect(target,bonus)); 28 | } 29 | 30 | public Armor toArmor(){ 31 | Armor armor = new Armor(itemName, itemCount); 32 | armor.setAC(armorClass) 33 | .setArmorType(armorType) 34 | .setValue(itemValue) 35 | .setDescription(itemDescription); 36 | armor.setEffects(itemEffects); 37 | return armor; 38 | } 39 | 40 | public Consumable toConsumable(){ 41 | Consumable consumable = new Consumable(itemName, itemCount); 42 | consumable.setDescription(itemDescription) 43 | .setValue(itemValue); 44 | return consumable; 45 | } 46 | 47 | public Equippable toEquippable(){ 48 | Equippable equippable = new Equippable(itemName, itemCount); 49 | equippable.setDescription(itemDescription) 50 | .setValue(itemValue); 51 | equippable.setEffects(itemEffects); 52 | return equippable; 53 | } 54 | 55 | public Item toItem(){ 56 | Item item = new Item(itemName, itemCount); 57 | item.setDescription(itemDescription) 58 | .setValue(itemValue); 59 | return item; 60 | } 61 | 62 | public Weapon toWeapon(){ 63 | Weapon weapon = new Weapon(itemName, itemCount); 64 | weapon.setDamage(damage) 65 | .setDescription(itemDescription) 66 | .setValue(itemValue); 67 | return weapon; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/app/io/PlayerLeveler.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.utils.Help; 6 | import app.utils.Message; 7 | 8 | import java.util.LinkedList; 9 | 10 | public class PlayerLeveler { 11 | public static void levelUp(PlayerCharacter activeChar) { 12 | LinkedList tokens = CharacterCommand.tokens; 13 | tokens.pop(); 14 | boolean help = false; 15 | if (tokens.isEmpty()) { 16 | activeChar.levelUp(); 17 | CharacterCommand.terminal.println( 18 | String.format("%s is now level %.0f", activeChar.getName(), activeChar.getLevel().getBaseVal()) 19 | ); 20 | } else { 21 | Integer level = null; 22 | while (!tokens.isEmpty()) { 23 | switch (tokens.peek()) { 24 | case "-l": 25 | case "--level": 26 | tokens.pop(); 27 | if (tokens.isEmpty()) { 28 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 29 | } else { 30 | level = CharacterCommand.getIntToken(); 31 | } 32 | break; 33 | case "--help": 34 | tokens.pop(); 35 | help = true; 36 | break; 37 | default: 38 | if (tokens.peek().startsWith("-")) { 39 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + tokens.pop() + "'"); 40 | } else { 41 | tokens.pop(); 42 | } 43 | break; 44 | } 45 | } 46 | if (!help) { 47 | if (level != null) { 48 | activeChar.levelUp(level); 49 | CharacterCommand.terminal.println(String.format( 50 | "%s is now level %.0f", activeChar.getName(), activeChar.getLevel().getBaseVal()) 51 | ); 52 | } else { 53 | Message.errorMessage(CharacterCommand.terminal, Message.ERROR_INPUT); 54 | } 55 | } else { 56 | CharacterCommand.terminal.println(Help.LEVELUP); 57 | } 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/app/terminal/PropertyHandler.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import java.io.*; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.util.Properties; 8 | 9 | public class PropertyHandler { 10 | private static final String PATH = "terminal-config.properties"; 11 | 12 | public static void initProperties(Terminal terminal){ 13 | 14 | Properties properties = terminal.getProperties(); 15 | OutputStream out = null; 16 | Path configPath = Paths.get("./"+PATH); 17 | if(!Files.exists(configPath)){ 18 | try{ 19 | out= new FileOutputStream(PATH); 20 | 21 | properties.setProperty("font-size", "16"); 22 | 23 | properties.store(out, null); 24 | } catch (IOException e){ 25 | //e.printStackTrace(); 26 | } finally { 27 | if(out != null){ 28 | try{ 29 | out.close(); 30 | } catch (IOException e){ 31 | //e.printStackTrace(); 32 | } 33 | } 34 | } 35 | } 36 | readProperties(terminal); 37 | } 38 | 39 | public static void readProperties(Terminal terminal){ 40 | Properties properties = terminal.getProperties(); 41 | InputStream in = null; 42 | try{ 43 | in = new FileInputStream(PATH); 44 | properties.load(in); 45 | 46 | try{ 47 | int fontSize = Integer.parseInt(properties.getProperty("font-size")); 48 | terminal.setFontSize(fontSize); 49 | } catch (NumberFormatException e){ 50 | //e.printStackTrace(); 51 | } 52 | 53 | 54 | 55 | } catch (IOException e) { 56 | //e.printStackTrace(); 57 | } finally { 58 | if (in != null){ 59 | try{ 60 | in.close(); 61 | } catch (IOException e) { 62 | //e.printStackTrace(); 63 | } 64 | } 65 | } 66 | } 67 | 68 | public static void writeProperties(Terminal terminal){ 69 | Properties properties = terminal.getProperties(); 70 | OutputStream out = null; 71 | try { 72 | out = new FileOutputStream(PATH); 73 | 74 | properties.setProperty("font-size", Integer.toString(terminal.getFontSize())); 75 | 76 | properties.store(out, null); 77 | } catch (IOException e){ 78 | //e.printStackTrace(); 79 | } finally { 80 | if(out != null){ 81 | try { 82 | out.close(); 83 | } catch (IOException e) { 84 | //e.printStackTrace(); 85 | } 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mshems@u.rochester.edu. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /src/app/core/items/Item.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | 6 | import java.io.Serializable; 7 | 8 | public class Item implements Serializable { 9 | 10 | private static final long serialVersionUID = CharacterCommand.VERSION; 11 | private String name; 12 | private int count; 13 | private String description=""; 14 | private Integer value; 15 | 16 | private boolean equipped = false; 17 | private boolean equippable; 18 | private boolean consumable; 19 | 20 | public enum ItemType {ARMOR, CONSUMABLE, EQUIPPABLE, ITEM, WEAPON, COIN}; 21 | 22 | public static final String[] types = new String[] { 23 | "item","consumable","equippable","weapon","armor","c","i","e","w","a" 24 | }; 25 | 26 | public Item(String name){ 27 | this.name = name; 28 | this.equippable = false; 29 | this.count = 1; 30 | } 31 | public Item(String name, int count){ 32 | this.name = name; 33 | this.equippable = false; 34 | this.count = count; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | public Item setName(String name) { 41 | this.name = name; 42 | return this; 43 | } 44 | 45 | public int getCount() { 46 | return count; 47 | } 48 | public Item setCount(int count) { 49 | this.count = count; 50 | return this; 51 | } 52 | 53 | public void addCount(int count){ 54 | this.count+=count; 55 | } 56 | 57 | public Integer getValue(){ 58 | return value; 59 | } 60 | public Item setValue(Integer value){ 61 | this.value = value; 62 | return this; 63 | } 64 | 65 | public String getDescription(){ 66 | return description; 67 | } 68 | public Item setDescription(String description){ 69 | this.description = description; 70 | return this; 71 | } 72 | 73 | public void equip(PlayerCharacter c){}; 74 | public void dequip(PlayerCharacter c){}; 75 | public void use(int amount){}; 76 | 77 | public boolean isEquippable() { 78 | return equippable; 79 | } 80 | public Item setEquippable(boolean equippable) { 81 | this.equippable = equippable; 82 | return this; 83 | } 84 | public boolean isEquipped(){ 85 | return equipped; 86 | } 87 | public boolean isConsumable(){ 88 | return consumable; 89 | } 90 | public Item setConsumable(boolean consumable){ 91 | this.consumable = consumable; 92 | return this; 93 | } 94 | 95 | public String toString(){ 96 | String s = String.format("%dx %s", this.getCount(), this.getName()); 97 | return s; 98 | } 99 | 100 | public static ItemType parseItemType(String s){ 101 | switch(s){ 102 | case"a": 103 | case "armor": 104 | return ItemType.ARMOR; 105 | case "c": 106 | case "consumable": 107 | return ItemType.CONSUMABLE; 108 | case "e": 109 | case "equippable": 110 | return ItemType.EQUIPPABLE; 111 | case "i": 112 | case "item": 113 | return ItemType.ITEM; 114 | case "w": 115 | case "weapon": 116 | return ItemType.WEAPON; 117 | case "currency": 118 | case "coin": 119 | return ItemType.COIN; 120 | default: 121 | return null; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/app/core/character/Inventory.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | import app.CharacterCommand; 3 | import app.core.items.Item; 4 | 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | import java.util.LinkedHashMap; 8 | 9 | public class Inventory implements Serializable { 10 | private static final long serialVersionUID = CharacterCommand.VERSION; 11 | private LinkedHashMap contents; 12 | private ArrayList currency; 13 | 14 | public static final int indexPL=0; 15 | public static final int indexGP=1; 16 | public static final int indexSP=2; 17 | public static final int indexCP=3; 18 | 19 | public Inventory(){ 20 | this.contents = new LinkedHashMap(); 21 | this.currency = new ArrayList(); 22 | currency.add(new Item("pp",0)); 23 | currency.add(new Item("gp",0)); 24 | currency.add(new Item("sp",0)); 25 | currency.add(new Item("cp",0)); 26 | } 27 | 28 | public void add(Item item){ 29 | this.contents.put(item.getName().toLowerCase(), item); 30 | } 31 | public void remove(Item item){ 32 | this.contents.remove(item.getName().toLowerCase()); 33 | } 34 | public Item get(String itemName){ 35 | return this.contents.get(itemName); 36 | } 37 | public Item getCurrency(int coin){ 38 | return this.currency.get(coin); 39 | } 40 | public void addCurrency(int coin, int amt){ 41 | this.currency.get(coin).addCount(amt); 42 | } 43 | public ArrayList getCurrency(){ 44 | return this.currency; 45 | } 46 | 47 | public LinkedHashMap getContents() { 48 | return contents; 49 | } 50 | 51 | public boolean contains(String key){ 52 | return this.contents.containsKey(key); 53 | } 54 | public boolean contains(Item i){ 55 | return this.contents.containsValue(i); 56 | } 57 | 58 | private boolean hasCurrency(){ 59 | for(Item i:currency){ 60 | if(i.getCount()!=0){ 61 | return true; 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | public static boolean isCurrency(String itemName){ 68 | switch(itemName){ 69 | case "pp": 70 | case "platinum": 71 | case "gp": 72 | case "gold": 73 | case "sp": 74 | case "silver": 75 | case "cp": 76 | case "copper": 77 | return true; 78 | default: 79 | return false; 80 | } 81 | } 82 | 83 | public String toString(){ 84 | //String s="\033[1;33mInventory: \033[0m"; 85 | String newLine = System.lineSeparator(); 86 | String s="---- INVENTORY -----------------"; 87 | if(hasCurrency()) { 88 | s+=newLine; 89 | for (Item i : currency) { 90 | if (i.getCount() != 0) { 91 | //s+=String.format("%s: %d ", i.getName(), i.getCount()); 92 | s += String.format(" %d%s ", i.getCount(), i.getName()); 93 | } 94 | } 95 | } 96 | if(!s.isEmpty()){ 97 | //s=newLine+s; 98 | } 99 | //s = "Inventory: "+s; 100 | if (contents.isEmpty() && !hasCurrency()){ 101 | s+=newLine+" Empty"; 102 | } else { 103 | for (Item item : contents.values()){ 104 | if (item.isEquipped()){ 105 | s += newLine+" e "+item; 106 | } else { 107 | s += newLine+" - "+item; 108 | } 109 | } 110 | } 111 | return s+newLine+"--------------------------------"; 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/app/core/character/StatEditor.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | import app.utils.Help; 5 | import app.utils.Message; 6 | 7 | public class StatEditor { 8 | public static void edit(PlayerCharacter pc) { 9 | CharacterCommand.tokens.pop(); 10 | if (!CharacterCommand.tokens.isEmpty()) { 11 | editParser(pc); 12 | } else { 13 | Stat stat = StatIO.getStatByName(pc); 14 | if (stat != null) { 15 | int val = CharacterCommand.terminal.queryInteger(stat.getName()+" value: ", false); 16 | //int val = getValidInt(stat.getName() + " value: "); 17 | stat.setBaseVal(val); 18 | pc.updateStats(); 19 | CharacterCommand.terminal.println("Updated " + stat.getName()); 20 | } 21 | } 22 | } 23 | 24 | private static void editParser(PlayerCharacter pc) { 25 | StringBuilder nameBuilder = new StringBuilder(); 26 | Integer bonus = null; 27 | Integer value = null; 28 | boolean help = false; 29 | while (!CharacterCommand.tokens.isEmpty()) { 30 | switch (CharacterCommand.tokens.peek()) { 31 | case "-v": 32 | case "--value": 33 | CharacterCommand.tokens.pop(); 34 | if (CharacterCommand.tokens.isEmpty()) { 35 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": stat value"); 36 | } else { 37 | value = CharacterCommand.getIntToken(); 38 | } 39 | break; 40 | case "-b": 41 | case "--bonus": 42 | CharacterCommand.tokens.pop(); 43 | if (CharacterCommand.tokens.isEmpty()) { 44 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": bonus"); 45 | } else { 46 | bonus = CharacterCommand.getIntToken(); 47 | } 48 | break; 49 | case "--help": 50 | help = true; 51 | break; 52 | default: 53 | if (CharacterCommand.tokens.peek().startsWith("-")) { 54 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 55 | } else { 56 | nameBuilder.append(CharacterCommand.tokens.pop()); 57 | nameBuilder.append(" "); 58 | } 59 | break; 60 | } 61 | } 62 | if (help) { 63 | CharacterCommand.terminal.println(Help.EDIT); 64 | } else { 65 | String statName = nameBuilder.toString().trim(); 66 | Stat stat = pc.getStat(statName); 67 | if (value != null) { 68 | if (stat != null) { 69 | if (bonus != null) { 70 | stat.setBonusVal(bonus); 71 | CharacterCommand.terminal.println("Updated " + stat.getName()); 72 | } 73 | stat.setBaseVal(value); 74 | pc.updateStats(); 75 | CharacterCommand.terminal.println("Updated " + stat.getName()); 76 | } else { 77 | CharacterCommand.terminal.println(Message.MSG_NO_STAT); 78 | } 79 | } else { 80 | CharacterCommand.terminal.println(Message.ERROR_INPUT); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/app/io/PlayerHealer.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.utils.Help; 6 | import app.utils.Message; 7 | 8 | public class PlayerHealer { 9 | public static void heal(PlayerCharacter activeChar) { 10 | String command = CharacterCommand.tokens.pop(); 11 | if (!CharacterCommand.tokens.isEmpty()) { 12 | heal(activeChar, command); 13 | } else { 14 | Integer amount; 15 | if (command.equals("heal")) { 16 | amount = CharacterCommand.terminal.queryInteger("HP gained: ", false); 17 | } else { 18 | amount = CharacterCommand.terminal.queryInteger("HP lost: ", false); 19 | } 20 | heal(activeChar, command, amount); 21 | } 22 | } 23 | 24 | private static void heal(PlayerCharacter activeChar, String command) { 25 | Integer amount = null; 26 | boolean healAll = false; 27 | boolean help = false; 28 | while (!CharacterCommand.tokens.isEmpty()) { 29 | switch (CharacterCommand.tokens.peek()) { 30 | case "-hp": 31 | case "--health": 32 | CharacterCommand.tokens.pop(); 33 | if (CharacterCommand.tokens.isEmpty()) { 34 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": amount"); 35 | } else { 36 | amount = CharacterCommand.getIntToken(); 37 | } 38 | break; 39 | case "--all": 40 | CharacterCommand.tokens.pop(); 41 | healAll = true; 42 | break; 43 | case "--help": 44 | CharacterCommand.tokens.pop(); 45 | help = true; 46 | break; 47 | default: 48 | if (CharacterCommand.tokens.peek().startsWith("-")) { 49 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 50 | } else { 51 | CharacterCommand.tokens.pop(); 52 | } 53 | break; 54 | } 55 | } 56 | if (help) { 57 | if (command.equals("heal")) { 58 | CharacterCommand.terminal.println(Help.HEAL); 59 | } 60 | if (command.equals("hurt")) { 61 | CharacterCommand.terminal.println(Help.HURT); 62 | } 63 | } else if (healAll) { 64 | healAll(activeChar, command); 65 | } else if (amount != null) { 66 | heal(activeChar, command, amount); 67 | } else { 68 | CharacterCommand.terminal.println(Message.ERROR_SYNTAX); 69 | } 70 | } 71 | 72 | private static void heal(PlayerCharacter activeChar, String command, int amount) { 73 | switch (command) { 74 | case "heal": 75 | activeChar.heal(amount); 76 | CharacterCommand.terminal.println(String.format("Gained %d HP", amount)); 77 | break; 78 | case "hurt": 79 | activeChar.hurt(amount); 80 | CharacterCommand.terminal.println(String.format("Lost %d HP", amount)); 81 | break; 82 | default: 83 | break; 84 | } 85 | } 86 | 87 | private static void healAll(PlayerCharacter activeChar, String command) { 88 | switch (command) { 89 | case "heal": 90 | activeChar.fullHeal(); 91 | CharacterCommand.terminal.println("HP fully restored"); 92 | break; 93 | case "hurt": 94 | activeChar.fullHurt(); 95 | CharacterCommand.terminal.println("No HP remaining"); 96 | break; 97 | default: 98 | break; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/app/core/character/StatIO.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | 3 | import app.CharacterCommand; 4 | import app.utils.Help; 5 | import app.utils.Message; 6 | 7 | public class StatIO { 8 | public static Stat getStatByName(PlayerCharacter pc) { 9 | Stat stat; 10 | while (true) { 11 | String statName = CharacterCommand.terminal.queryString("Stat name: ", false); 12 | if (statName.equalsIgnoreCase("cancel")) { 13 | return null; 14 | } else { 15 | stat = pc.getStat(statName); 16 | if (stat == null) { 17 | int matches = 0; 18 | for(String str:pc.getAllStats().keySet()){ 19 | if(str.startsWith(statName.toLowerCase())){ 20 | stat = pc.getAllStats().get(str); 21 | matches++; 22 | } 23 | } 24 | if(matches == 1){ 25 | return stat; 26 | } 27 | CharacterCommand.terminal.println(Message.MSG_NO_STAT); 28 | } else { 29 | return stat; 30 | } 31 | } 32 | } 33 | } 34 | public static void stats(PlayerCharacter pc) { 35 | CharacterCommand.tokens.pop(); 36 | if (!CharacterCommand.tokens.isEmpty()) { 37 | statsParser(pc); 38 | } else { 39 | CharacterCommand.terminal.println("view | edit | cancel"); 40 | //CharacterCommand.terminal.println("view | edit | cancel"); 41 | boolean exit = false; 42 | while (!exit) { 43 | //CharacterCommand.terminal.print("Action: "); 44 | //String action = scanner.nextLine().toLowerCase().trim(); 45 | String action = CharacterCommand.terminal.queryString("Action: ", false).toLowerCase(); 46 | switch (action) { 47 | case "v": 48 | case "view": 49 | Stat stat = getStatByName(pc); 50 | if (stat != null) { 51 | CharacterCommand.terminal.println(stat.detailString()); 52 | //CharacterCommand.terminal.println(stat.detailString()); 53 | } 54 | exit = true; 55 | break; 56 | case "e": 57 | case "edit": 58 | StatEditor.edit(pc); 59 | exit = true; 60 | break; 61 | case "cancel": 62 | exit = true; 63 | break; 64 | } 65 | } 66 | } 67 | } 68 | 69 | private static void statsParser(PlayerCharacter pc) { 70 | StringBuilder nameBuilder = new StringBuilder(); 71 | boolean help = false; 72 | boolean view = true; 73 | while (!CharacterCommand.tokens.isEmpty()) { 74 | switch (CharacterCommand.tokens.peek()) { 75 | case "-e": 76 | case "--edit": 77 | StatEditor.edit(pc); 78 | view = false; 79 | //tokens.pop(); 80 | break; 81 | case "--help": 82 | CharacterCommand.tokens.pop(); 83 | help = true; 84 | break; 85 | default: 86 | if (CharacterCommand.tokens.peek().startsWith("-")) { 87 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 88 | } else { 89 | nameBuilder.append(CharacterCommand.tokens.pop()); 90 | nameBuilder.append(" "); 91 | } 92 | break; 93 | } 94 | } 95 | if (help) { 96 | CharacterCommand.terminal.println(Help.STATS); 97 | } else { 98 | String statName = nameBuilder.toString().trim(); 99 | Stat stat = CharacterCommand.getActiveChar().getStat(statName); 100 | if (stat != null && view) { 101 | CharacterCommand.terminal.println(stat.detailString()); 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/app/io/SpellBookIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.core.magic.Spell; 6 | import app.utils.Help; 7 | import app.utils.Message; 8 | 9 | public class SpellBookIO { 10 | public static void learn(PlayerCharacter pc) { 11 | CharacterCommand.tokens.pop(); 12 | if (!CharacterCommand.tokens.isEmpty()) { 13 | learnParser(pc); 14 | } else { 15 | String spellName; 16 | int spellLevel; 17 | spellName = CharacterCommand.terminal.queryString("Spell name: ",false); 18 | spellLevel = CharacterCommand.terminal.queryInteger("Spell level: ",false); 19 | learnSpell(pc, new Spell(spellName, spellLevel)); 20 | } 21 | } 22 | 23 | private static void learnParser(PlayerCharacter pc) { 24 | StringBuilder nameBuilder = new StringBuilder(); 25 | Integer spellLevel = null; 26 | boolean learnmagic = false; 27 | boolean help = false; 28 | while (!CharacterCommand.tokens.isEmpty()) { 29 | switch (CharacterCommand.tokens.peek()) { 30 | case "-l": 31 | case "--level": 32 | CharacterCommand.tokens.pop(); 33 | if (CharacterCommand.tokens.isEmpty()) { 34 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 35 | spellLevel = null; 36 | } else { 37 | spellLevel = CharacterCommand.getIntToken(); 38 | } 39 | break; 40 | case "-m": 41 | case "--magic": 42 | CharacterCommand.tokens.pop(); 43 | learnmagic = true; 44 | break; 45 | case "--help": 46 | CharacterCommand.tokens.pop(); 47 | help = true; 48 | break; 49 | default: 50 | if (CharacterCommand.tokens.peek().startsWith("-")) { 51 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 52 | } else { 53 | nameBuilder.append(CharacterCommand.tokens.pop()); 54 | nameBuilder.append(" "); 55 | } 56 | break; 57 | } 58 | } 59 | if (learnmagic) { 60 | MagicIO.learnMagic(pc); 61 | } 62 | if (pc.isSpellcaster()) { 63 | if (spellLevel == null) { 64 | spellLevel = Spell.CANTRIP; //default level 65 | } 66 | if (help) { 67 | CharacterCommand.terminal.println(Help.LEARN); 68 | } else { 69 | String spellName = nameBuilder.toString().trim(); 70 | if (!spellName.isEmpty()) { 71 | Spell spell = new Spell(spellName, spellLevel); 72 | learnSpell(pc, spell); 73 | } 74 | } 75 | } else { 76 | CharacterCommand.terminal.println(Message.MSG_NOT_CAST); 77 | } 78 | } 79 | 80 | 81 | 82 | private static void learnSpell(PlayerCharacter pc, Spell spell) { 83 | pc.getSpellBook().learn(spell); 84 | if (spell.isCantrip()) { 85 | CharacterCommand.terminal.println("Learned cantrip " + spell.getSpellName()); 86 | } else { 87 | CharacterCommand.terminal.println("Learned level " + spell.getSpellLevel() + " spell " + spell.getSpellName()); 88 | } 89 | } 90 | 91 | public static void forget(PlayerCharacter pc) { 92 | CharacterCommand.tokens.pop(); 93 | if (!CharacterCommand.tokens.isEmpty()) { 94 | forgetParser(pc); 95 | } else { 96 | Spell spell = SpellIO.getSpellByName(pc); 97 | if (spell != null) { 98 | forgetSpell(pc, spell); 99 | } 100 | } 101 | } 102 | 103 | private static void forgetParser(PlayerCharacter pc) { 104 | StringBuilder nameBuilder = new StringBuilder(); 105 | boolean help = false; 106 | while (!CharacterCommand.tokens.isEmpty()) { 107 | switch (CharacterCommand.tokens.peek()) { 108 | case "--help": 109 | CharacterCommand.tokens.pop(); 110 | help = true; 111 | break; 112 | default: 113 | if (CharacterCommand.tokens.peek().startsWith("-")) { 114 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 115 | } else { 116 | nameBuilder.append(CharacterCommand.tokens.pop()); 117 | nameBuilder.append(" "); 118 | } 119 | break; 120 | } 121 | } 122 | if (help) { 123 | CharacterCommand.terminal.println(Help.FORGET); 124 | } else { 125 | Spell spell = pc.getSpell(nameBuilder.toString().trim()); 126 | if (spell != null) { 127 | forgetSpell(pc, spell); 128 | } else { 129 | CharacterCommand.terminal.println(Message.MSG_NO_SPELL); 130 | } 131 | } 132 | } 133 | 134 | private static void forgetSpell(PlayerCharacter pc, Spell spell) { 135 | pc.getSpellBook().forget(spell); 136 | if (spell.isCantrip()) { 137 | CharacterCommand.terminal.println("Forgot cantrip " + spell.getSpellName()); 138 | } else { 139 | CharacterCommand.terminal.println("Forgot level " + spell.getSpellLevel() + " spell " + spell.getSpellName()); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/app/io/AbilityPointsIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.CounterStat; 5 | import app.core.character.PlayerCharacter; 6 | import app.utils.Help; 7 | import app.utils.Message; 8 | 9 | public class AbilityPointsIO { 10 | public static void abilityPoints(PlayerCharacter pc) { 11 | CharacterCommand.tokens.pop(); 12 | if (!CharacterCommand.tokens.isEmpty()) { 13 | abilityPointsParser(pc); 14 | } else { 15 | CharacterCommand.terminal.println("use | get | set"); 16 | String action = CharacterCommand.terminal.queryString("Action: ",false).toLowerCase(); 17 | boolean exit = false; 18 | int amount; 19 | while (!exit) { 20 | switch (action) { 21 | case "u": 22 | case "use": 23 | amount = CharacterCommand.terminal.queryInteger("Ability Points to use: ", false); 24 | ((CounterStat) pc.getStat("ap")).countDown(amount); 25 | CharacterCommand.terminal.println("Used " + amount + " ability points"); 26 | exit = true; 27 | break; 28 | case "g": 29 | case "get": 30 | amount = CharacterCommand.terminal.queryInteger("Ability Points gained: ", false); 31 | ((CounterStat) pc.getStat("ap")).countUp(amount); 32 | CharacterCommand.terminal.println("Gained " + amount + " ability points"); 33 | exit = true; 34 | break; 35 | case "s": 36 | case "set": 37 | amount = CharacterCommand.terminal.queryInteger("Ability Points maximum: ", false); 38 | ((CounterStat) pc.getStat("ap")).setMaxVal(amount); 39 | CharacterCommand.terminal.println("Ability Point maximum now " + amount); 40 | exit = true; 41 | break; 42 | case "cancel": 43 | exit = true; 44 | break; 45 | } 46 | } 47 | } 48 | } 49 | 50 | private static void abilityPointsParser(PlayerCharacter pc) { 51 | boolean use = false; 52 | boolean get = false; 53 | boolean set = false; 54 | boolean help = false; 55 | boolean all = false; 56 | Integer count = 1; 57 | while (!CharacterCommand.tokens.isEmpty()) { 58 | switch (CharacterCommand.tokens.peek()) { 59 | case "-u": 60 | case "--use": 61 | CharacterCommand.tokens.pop(); 62 | use = true; 63 | get = false; 64 | set = false; 65 | break; 66 | case "-g": 67 | case "--get": 68 | CharacterCommand.tokens.pop(); 69 | get = true; 70 | use = false; 71 | set = false; 72 | break; 73 | case "-s": 74 | case "--set": 75 | CharacterCommand.tokens.pop(); 76 | set = true; 77 | get = false; 78 | use = false; 79 | break; 80 | case "-c": 81 | case "--count": 82 | CharacterCommand.tokens.pop(); 83 | if (CharacterCommand.tokens.isEmpty()) { 84 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": count"); 85 | } else { 86 | count = CharacterCommand.getIntToken(); 87 | } 88 | break; 89 | case "--all": 90 | CharacterCommand.tokens.pop(); 91 | all = true; 92 | break; 93 | case "--help": 94 | CharacterCommand.tokens.pop(); 95 | help = true; 96 | break; 97 | default: 98 | if (CharacterCommand.tokens.peek().startsWith("-")) { 99 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 100 | } 101 | break; 102 | } 103 | } 104 | if (help) { 105 | CharacterCommand.terminal.println(Help.AP); 106 | } else { 107 | if (count != null) { 108 | CounterStat ap = ((CounterStat) pc.getStat("ap")); 109 | if (use) { 110 | if (all) { 111 | ap.setCurrVal(0); 112 | CharacterCommand.terminal.println("Used all ability points"); 113 | } else { 114 | ap.countDown(count); 115 | CharacterCommand.terminal.println("Used " + count + " ability points"); 116 | } 117 | } else if (get) { 118 | if (all) { 119 | ap.setCurrVal(ap.getMaxVal()); 120 | CharacterCommand.terminal.println("Gained all ability points"); 121 | } else { 122 | ap.countUp(count); 123 | CharacterCommand.terminal.println("Gained " + count + " ability points"); 124 | } 125 | } else if (set) { 126 | ap.setMaxVal(count); 127 | CharacterCommand.terminal.println("Ability Point maximum now " + count); 128 | } else { 129 | CharacterCommand.terminal.println(Message.ERROR_SYNTAX); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/app/io/SpellIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.core.magic.Spell; 6 | import app.utils.Help; 7 | import app.utils.Message; 8 | 9 | public class SpellIO { 10 | public static Spell getSpellByName(PlayerCharacter pc) { 11 | Spell spell; 12 | while (true) { 13 | String spellName = CharacterCommand.terminal.queryString("Spell name: ", false); 14 | if (spellName.equalsIgnoreCase("cancel")) { 15 | return null; 16 | } else { 17 | spell = pc.getSpell(spellName); 18 | if (spell == null) { 19 | CharacterCommand.terminal.println(Message.MSG_NO_SPELL); 20 | } else { 21 | return spell; 22 | } 23 | } 24 | } 25 | } 26 | public static void spells(PlayerCharacter pc) { 27 | CharacterCommand.tokens.pop(); 28 | if (!CharacterCommand.tokens.isEmpty()) { 29 | switch (CharacterCommand.tokens.peek()) { 30 | case "--learn": 31 | SpellBookIO.learn(pc); 32 | break; 33 | case "--forget": 34 | SpellBookIO.forget(pc); 35 | break; 36 | case "--cast": 37 | cast(pc); 38 | break; 39 | case "--stats": 40 | CharacterCommand.terminal.println(pc.spellStatsToString()); 41 | break; 42 | case "--slots": 43 | SpellSlotIO.spellSlots(pc); 44 | break; 45 | case "--help": 46 | CharacterCommand.terminal.println(Help.SPELLS); 47 | break; 48 | default: 49 | CharacterCommand.terminal.println("Error: command syntax"); 50 | break; 51 | } 52 | } else { 53 | CharacterCommand.terminal.println("learn | forget | cast | book | slots | stats"); 54 | String action = CharacterCommand.terminal.queryString("Action: ", false); 55 | switch (action.toLowerCase()){ 56 | case "l": 57 | case "learn": 58 | SpellBookIO.learn(pc); 59 | break; 60 | case "f": 61 | case "forget": 62 | SpellBookIO.forget(pc); 63 | break; 64 | case "c": 65 | case "cast": 66 | cast(pc); 67 | break; 68 | case "b": 69 | case "book": 70 | CharacterCommand.terminal.println(pc.getSpellBook().toString()); 71 | break; 72 | case "slots": 73 | SpellSlotIO.spellSlots(pc); 74 | break; 75 | case "stats": 76 | CharacterCommand.terminal.println(pc.spellStatsToString()); 77 | break; 78 | } 79 | 80 | } 81 | } 82 | 83 | public static void cast(PlayerCharacter pc) { 84 | CharacterCommand.tokens.pop(); 85 | if (!CharacterCommand.tokens.isEmpty()) { 86 | castParser(pc); 87 | } else { 88 | Integer castLevel = -1; 89 | Spell spell = getSpellByName(pc); 90 | if (spell != null) { 91 | if (!spell.isCantrip()) { 92 | castLevel = CharacterCommand.terminal.queryInteger("Cast at level: ", false); 93 | } 94 | castSpell(pc, spell, spell.getSpellName(), castLevel); 95 | } 96 | } 97 | } 98 | 99 | private static void castParser(PlayerCharacter pc) { 100 | Spell spell; 101 | StringBuilder nameBuilder = new StringBuilder(); 102 | Integer castLevel = -1; 103 | boolean help = false; 104 | while (!CharacterCommand.tokens.isEmpty()) { 105 | switch (CharacterCommand.tokens.peek()) { 106 | case "-l": 107 | case "--level": 108 | CharacterCommand.tokens.pop(); 109 | if (CharacterCommand.tokens.isEmpty()) { 110 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 111 | castLevel = null; 112 | } else { 113 | castLevel = CharacterCommand.getIntToken(); 114 | } 115 | break; 116 | case "--help": 117 | help = true; 118 | CharacterCommand.tokens.pop(); 119 | break; 120 | default: 121 | if (CharacterCommand.tokens.peek().startsWith("-")) { 122 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 123 | } else { 124 | nameBuilder.append(CharacterCommand.tokens.pop()); 125 | nameBuilder.append(" "); 126 | } 127 | } 128 | } 129 | if (help) { 130 | CharacterCommand.terminal.println(Help.CAST); 131 | } else { 132 | String spellName = nameBuilder.toString().trim(); 133 | spell = pc.getSpell(spellName); 134 | castSpell(pc, spell, spellName, castLevel); 135 | } 136 | } 137 | 138 | private static void castSpell(PlayerCharacter pc, Spell spell, String spellName, Integer castLevel) { 139 | if (spell != null && castLevel != null) { 140 | if (castLevel == -1) { 141 | castLevel = spell.getSpellLevel(); 142 | } 143 | castLevel = pc.cast(spell, castLevel); 144 | if (spell.isCantrip()) { 145 | CharacterCommand.terminal.println("Cast '" + spell.getSpellName() + "' as a cantrip"); 146 | } else { 147 | if (castLevel < 0) { 148 | CharacterCommand.terminal.println("No level " + (-castLevel) + " spell slots remaining"); 149 | } else { 150 | CharacterCommand.terminal.println("Cast '" + spell.getSpellName() + "' at level " + castLevel); 151 | } 152 | } 153 | } else { 154 | if (spellName.equals("")) { 155 | CharacterCommand.terminal.println("ERROR: Missing argument: spell name"); 156 | } else if (spell == null) { 157 | CharacterCommand.terminal.println("No spell by that name"); 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/app/io/ItemBuilderIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.Inventory; 5 | import app.core.character.PlayerCharacter; 6 | import app.core.character.Stat; 7 | import app.core.items.Armor; 8 | import app.core.items.Item; 9 | import app.core.items.ItemBuilder; 10 | import app.utils.Message; 11 | 12 | public class ItemBuilderIO { 13 | public static void buildItem(PlayerCharacter pc, ItemBuilder itemBuilder){ 14 | inputItemInfo(itemBuilder); 15 | if(itemBuilder.itemName.equalsIgnoreCase("cancel")){ 16 | itemBuilder.itemType=null; 17 | return; 18 | } 19 | if(pc.getInventory().contains(itemBuilder.itemName.toLowerCase())){ 20 | if(itemBuilder.itemType == Item.ItemType.COIN){ 21 | int coinType = -1; 22 | switch (itemBuilder.itemName) { 23 | case "pp": 24 | case "platinum": 25 | coinType = Inventory.indexPL; 26 | break; 27 | case "gp": 28 | case "gold": 29 | coinType = Inventory.indexGP; 30 | break; 31 | case "sp": 32 | case "silver": 33 | coinType = Inventory.indexCP; 34 | break; 35 | case "cp": 36 | case "copper": 37 | coinType = Inventory.indexCP; 38 | break; 39 | } 40 | if(coinType!= -1) { 41 | InventoryIO.addDropCoin(pc, Inventory.indexCP, itemBuilder.itemCount, false, "add"); 42 | } 43 | } else { 44 | InventoryIO.addDropItem(pc, pc.getItem(itemBuilder.itemName.toLowerCase()), itemBuilder.itemCount, false, "add"); 45 | } 46 | itemBuilder.itemType = null; 47 | return; 48 | } 49 | 50 | CharacterCommand.terminal.println("item | equippable | weapon | armor | consumable | coin"); 51 | while (true) { 52 | String type = CharacterCommand.terminal.queryString("Item type: ", false); 53 | if (type.equals("cancel")) { 54 | itemBuilder.itemType = null; 55 | return; 56 | } 57 | itemBuilder.itemType = Item.parseItemType(type); 58 | if (itemBuilder.itemType != null) { 59 | break; 60 | } 61 | CharacterCommand.terminal.println(Message.ERROR_ITEM_TYPE); 62 | } 63 | 64 | /*inputItemInfo(itemBuilder); 65 | if(pc.getInventory().contains(itemBuilder.itemName.toLowerCase())){ 66 | if(itemBuilder.itemType == Item.ItemType.COIN){ 67 | int coinType = -1; 68 | switch (itemBuilder.itemName) { 69 | case "pp": 70 | case "platinum": 71 | coinType = Inventory.indexPL; 72 | break; 73 | case "gp": 74 | case "gold": 75 | coinType = Inventory.indexGP; 76 | break; 77 | case "sp": 78 | case "silver": 79 | coinType = Inventory.indexCP; 80 | break; 81 | case "cp": 82 | case "copper": 83 | coinType = Inventory.indexCP; 84 | break; 85 | } 86 | if(coinType!= -1) { 87 | InventoryIO.addDropCoin(pc, Inventory.indexCP, itemBuilder.itemCount, false, "add"); 88 | } 89 | } else { 90 | InventoryIO.addDropItem(pc, pc.getItem(itemBuilder.itemName.toLowerCase()), itemBuilder.itemCount, false, "add"); 91 | } 92 | itemBuilder.itemType = null; 93 | return; 94 | } 95 | */ 96 | switch (itemBuilder.itemType) { 97 | case ARMOR: 98 | 99 | CharacterCommand.terminal.println("light | medium | heavy | shield | other"); 100 | while (itemBuilder.armorType == null) { 101 | itemBuilder.armorType = Armor.parseType( 102 | CharacterCommand.terminal.queryString("Armor type: ", false) 103 | ); 104 | if (itemBuilder.armorType == null) { 105 | CharacterCommand.terminal.println("ERROR: Not a valid armor type"); 106 | } 107 | itemBuilder.armorClass = CharacterCommand.terminal.queryInteger("AC: ", false); 108 | } 109 | inputEffects(pc,itemBuilder); 110 | break; 111 | case COIN: 112 | //itemBuilder.itemName = CharacterCommand.terminal.queryString("Coin type: ",false); 113 | //itemBuilder.itemCount = CharacterCommand.terminal.queryInteger("Amount: ", false); 114 | InventoryIO.getCoins(pc, itemBuilder); 115 | return; 116 | case CONSUMABLE: 117 | case ITEM: 118 | //inputItemInfo(itemBuilder); 119 | break; 120 | case WEAPON: 121 | //inputItemInfo(itemBuilder); 122 | itemBuilder.damage = CharacterCommand.getDiceRoll("Weapon damage: "); 123 | inputEffects(pc, itemBuilder); 124 | break; 125 | case EQUIPPABLE: 126 | //inputItemInfo(itemBuilder); 127 | inputEffects(pc,itemBuilder); 128 | break; 129 | default: 130 | break; 131 | } 132 | } 133 | 134 | private static void inputItemInfo(ItemBuilder itemBuilder) { 135 | itemBuilder.itemName = CharacterCommand.terminal.queryString("Item name: ",false); 136 | if(!itemBuilder.itemName.equalsIgnoreCase("cancel")) { 137 | itemBuilder.itemCount = CharacterCommand.terminal.queryInteger("Count: ", false); 138 | } 139 | } 140 | 141 | private static void inputEffects(PlayerCharacter pc, ItemBuilder itemBuilder) { 142 | while (CharacterCommand.terminal.queryYN("Add effect? [Y/N] : ")) { 143 | String statName = CharacterCommand.terminal.queryString("Effect Target: ",false); 144 | if (!statName.equalsIgnoreCase("cancel")) { 145 | Stat target = pc.getStat(statName); 146 | if (target == null) { 147 | CharacterCommand.terminal.println("ERROR: Effect target not found"); 148 | } else { 149 | itemBuilder.addEffect(target, CharacterCommand.terminal.queryInteger("Stat Bonus: ", false)); 150 | } 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/app/core/items/Armor.java: -------------------------------------------------------------------------------- 1 | package app.core.items; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.Ability; 5 | import app.core.character.Stat; 6 | import app.core.character.Attribute; 7 | import app.core.character.PlayerCharacter; 8 | 9 | public class Armor extends Equippable{ 10 | private static final long serialVersionUID = CharacterCommand.VERSION; 11 | private Integer AC; 12 | public ArmorType armorType; 13 | 14 | public enum ArmorType {L_ARMOR, M_ARMOR, H_ARMOR, SHIELD, OTHER}; 15 | 16 | public Armor(String name){ 17 | super(name); 18 | } 19 | 20 | public Armor(String name, int count){ 21 | super(name, count); 22 | } 23 | 24 | public Armor setArmorType(ArmorType type){ 25 | this.armorType = type; 26 | return this; 27 | } 28 | public Armor setAC(int ac){ 29 | this.AC = ac; 30 | return this; 31 | } 32 | 33 | @Override 34 | public void equip(PlayerCharacter c){ 35 | if(getEffects()!=null){ 36 | for (ItemEffect e : this.getEffects()){ 37 | if (e != null){ 38 | e.getTarget().addBonusVal(e.getBonus()); 39 | } 40 | } 41 | } 42 | double dexMod = c.getAbilities().get(Ability.DEX).getMod(); 43 | Stat playerAC = c.getAttributes().get(Attribute.AC); 44 | if((AC!=null && armorType != null) || armorType == ArmorType.SHIELD){ 45 | switch (armorType){ 46 | case L_ARMOR: 47 | if(!c.isArmored()){ 48 | playerAC.setBaseVal(AC); 49 | playerAC.addBonusVal(dexMod); 50 | c.setArmored(true); 51 | this.setEquipped(true); 52 | //CharacterCommand.terminal.println(this.getName()+" equipped"); 53 | } else { 54 | //CharacterCommand.terminal.println("ERROR: Already wearing armor"); 55 | } 56 | break; 57 | case M_ARMOR: 58 | if(!c.isArmored()){ 59 | playerAC.setBaseVal(AC); 60 | if (dexMod < 2){ 61 | playerAC.addBonusVal(dexMod); 62 | } else { 63 | playerAC.addBonusVal(2); 64 | } 65 | c.setArmored(true); 66 | this.setEquipped(true); 67 | //CharacterCommand.terminal.println(this.getName()+" equipped"); 68 | } else { 69 | //CharacterCommand.terminal.println("ERROR: Already wearing armor"); 70 | } 71 | break; 72 | case H_ARMOR: 73 | if(!c.isArmored()){ 74 | playerAC.setBaseVal(AC); 75 | c.setArmored(true); 76 | this.setEquipped(true); 77 | //CharacterCommand.terminal.println(this.getName()+" equipped"); 78 | } else { 79 | //CharacterCommand.terminal.println("ERROR: Already wearing armor"); 80 | } 81 | break; 82 | case SHIELD: 83 | playerAC.addBonusVal(2); 84 | this.setEquipped(true); 85 | //CharacterCommand.terminal.println(this.getName()+" equipped"); 86 | break; 87 | case OTHER: 88 | playerAC.addBonusVal(AC); 89 | this.setEquipped(true); 90 | //CharacterCommand.terminal.println(this.getName()+" equipped"); 91 | break; 92 | } 93 | } 94 | } 95 | 96 | @Override 97 | public void dequip(PlayerCharacter c){ 98 | this.setEquipped(false); 99 | double dexMod = c.getAbilities().get(Ability.DEX).getMod(); 100 | Stat playerAC = c.getAttributes().get(Attribute.AC); 101 | if((AC!=null && armorType != null) || armorType == ArmorType.SHIELD){ 102 | switch (armorType){ 103 | case L_ARMOR: 104 | playerAC.setBaseVal(c.getAttributes().get(Attribute.NAC).getBaseVal()); 105 | playerAC.decBonusVal(dexMod); 106 | c.setArmored(false); 107 | //CharacterCommand.terminal.println(this.getName()+" dequipped"); 108 | break; 109 | case M_ARMOR: 110 | playerAC.setBaseVal(c.getAttributes().get(Attribute.NAC).getBaseVal()); 111 | if (dexMod < 2){ 112 | playerAC.decBonusVal(dexMod); 113 | } else { 114 | playerAC.decBonusVal(2); 115 | } 116 | c.setArmored(false); 117 | //CharacterCommand.terminal.println(this.getName()+" dequipped"); 118 | break; 119 | case H_ARMOR: 120 | playerAC.setBaseVal(c.getAttributes().get(Attribute.NAC).getBaseVal()); 121 | c.setArmored(false); 122 | //CharacterCommand.terminal.println(this.getName()+" dequipped"); 123 | break; 124 | case SHIELD: 125 | playerAC.decBonusVal(2); 126 | //CharacterCommand.terminal.println(this.getName()+" dequipped"); 127 | break; 128 | case OTHER: 129 | playerAC.decBonusVal(AC); 130 | //CharacterCommand.terminal.println(this.getName()+" dequipped"); 131 | break; 132 | } 133 | if(getEffects()!=null){ 134 | for (ItemEffect e : this.getEffects()){ 135 | if (e != null){ 136 | e.getTarget().decBonusVal(e.getBonus()); 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | @Override 144 | public String toString(){ 145 | String s = super.toString(); 146 | if((AC!=null && armorType != null) || armorType == ArmorType.SHIELD){ 147 | switch (armorType){ 148 | case L_ARMOR: 149 | s += " [Light]"; 150 | break; 151 | case M_ARMOR: 152 | s += " [Medium]"; 153 | break; 154 | case H_ARMOR: 155 | s += " [Heavy]"; 156 | break; 157 | case SHIELD: 158 | s += " [Shield]"; 159 | break; 160 | case OTHER: 161 | s += " [Other]"; 162 | break; 163 | } 164 | } 165 | return s; 166 | } 167 | 168 | public static ArmorType parseType(String s){ 169 | switch(s){ 170 | case"l": 171 | case "light": 172 | return ArmorType.L_ARMOR; 173 | case"m": 174 | case "medium": 175 | return ArmorType.M_ARMOR; 176 | case "h": 177 | case "heavy": 178 | return ArmorType.H_ARMOR; 179 | case "s": 180 | case "shield": 181 | return ArmorType.SHIELD; 182 | case "o": 183 | case "other": 184 | return ArmorType.OTHER; 185 | default: 186 | return null; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/app/io/SkillIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.core.character.Skill; 6 | import app.utils.Help; 7 | import app.utils.Message; 8 | 9 | public class SkillIO { 10 | 11 | public static void skills(PlayerCharacter pc) { 12 | CharacterCommand.tokens.pop(); 13 | String action; 14 | if (!CharacterCommand.tokens.isEmpty()) { 15 | skillsParser(pc); 16 | } else { 17 | Skill skill; 18 | boolean exit = false; 19 | while (!exit) { 20 | CharacterCommand.terminal.println("view | train | forget | expert | view all"); 21 | action = CharacterCommand.terminal.queryString("Action: ",false).toLowerCase(); 22 | switch (action) { 23 | case "v": 24 | case "view": 25 | skill = getSkillByName(pc); 26 | if (skill != null) { 27 | CharacterCommand.terminal.println(skill.toString()); 28 | } 29 | exit = true; 30 | break; 31 | case "t": 32 | case "train": 33 | skill = getSkillByName(pc); 34 | if (skill != null) { 35 | skill.train(pc); 36 | CharacterCommand.terminal.println("Gained proficiency in " + skill.getName()); 37 | } 38 | exit = true; 39 | break; 40 | case "f": 41 | case "forget": 42 | skill = getSkillByName(pc); 43 | if (skill != null) { 44 | skill.untrain(pc); 45 | CharacterCommand.terminal.println("Lost proficiency in " + skill.getName()); 46 | } 47 | exit = true; 48 | break; 49 | case "e": 50 | case "expert": 51 | skill = getSkillByName(pc); 52 | if (skill != null) { 53 | skill.expert(pc); 54 | CharacterCommand.terminal.println("Gained expertise in " + skill.getName()); 55 | } 56 | exit = true; 57 | break; 58 | case "va": 59 | case "viewall": 60 | case "view all": 61 | CharacterCommand.terminal.println(pc.skillsToString()); 62 | exit = true; 63 | break; 64 | case "cancel": 65 | exit = true; 66 | break; 67 | default: 68 | CharacterCommand.terminal.println(Message.ERROR_SYNTAX+"\nEnter 'cancel' to exit"); 69 | exit = false; 70 | break; 71 | } 72 | } 73 | } 74 | } 75 | 76 | private static void skillsParser(PlayerCharacter pc) { 77 | StringBuilder nameBuilder = new StringBuilder(); 78 | Skill skill; 79 | boolean expert = false; 80 | boolean forget = false; 81 | boolean train = false; 82 | boolean view = false; 83 | boolean viewAll = false; 84 | boolean help = false; 85 | 86 | while (!CharacterCommand.tokens.isEmpty()) { 87 | switch (CharacterCommand.tokens.peek()) { 88 | case "-e": 89 | case "--expert": 90 | expert = true; 91 | CharacterCommand.tokens.pop(); 92 | break; 93 | case "-t": 94 | case "--train": 95 | train = true; 96 | CharacterCommand.tokens.pop(); 97 | break; 98 | case "-f": 99 | case "--forget": 100 | forget = true; 101 | CharacterCommand.tokens.pop(); 102 | break; 103 | case "-v": 104 | case "--view": 105 | view = true; 106 | CharacterCommand.tokens.pop(); 107 | break; 108 | case "-va": 109 | case "--viewall": 110 | CharacterCommand.tokens.pop(); 111 | viewAll = true; 112 | break; 113 | case "--help": 114 | CharacterCommand.tokens.pop(); 115 | help = true; 116 | break; 117 | default: 118 | if (CharacterCommand.tokens.peek().startsWith("-")) { 119 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 120 | } else { 121 | nameBuilder.append(CharacterCommand.tokens.pop()); 122 | nameBuilder.append(" "); 123 | } 124 | break; 125 | } 126 | } 127 | if (help) { 128 | CharacterCommand.terminal.println(Help.SKILL); 129 | } else { 130 | String skillName = nameBuilder.toString().trim(); 131 | skill = pc.getSkill(skillName); 132 | if (viewAll) { 133 | CharacterCommand.terminal.println(pc.skillsToString()); 134 | } 135 | if (skill != null) { 136 | if (!forget) { 137 | if (expert) { 138 | skill.expert(pc); 139 | CharacterCommand.terminal.println("Gained expertise in " + skill.getName()); 140 | } else if (train) { 141 | skill.train(pc); 142 | CharacterCommand.terminal.println("Gained proficiency in " + skill.getName()); 143 | } 144 | } else { 145 | skill.untrain(pc); 146 | CharacterCommand.terminal.println("Lost proficiency in " + skill.getName()); 147 | } 148 | if (view) { 149 | CharacterCommand.terminal.println(skill.toString()); 150 | } 151 | } else { 152 | if (skillName.equals("") && !viewAll) { 153 | CharacterCommand.terminal.println("ERROR: Missing argument: skill name"); 154 | } else { 155 | if (!viewAll) { 156 | CharacterCommand.terminal.println("ERROR: No skill by that name"); 157 | //CharacterCommand.terminal.println(Message.ERROR_SYNTAX); 158 | } 159 | } 160 | } 161 | } 162 | } 163 | 164 | public static Skill getSkillByName(PlayerCharacter pc) { 165 | Skill skill; 166 | while (true) { 167 | String skillName = CharacterCommand.terminal.queryString("Skill name: ", false); 168 | if (skillName.equalsIgnoreCase("cancel")) { 169 | return null; 170 | } else { 171 | skill = pc.getSkill(skillName); 172 | if (skill == null) { 173 | int matches = 0; 174 | for(String str:pc.getSkillSet().keySet()){ 175 | if(str.startsWith(skillName.toLowerCase())){ 176 | skill = pc.getSkillSet().get(str); 177 | matches++; 178 | } 179 | } 180 | if(matches == 1){ 181 | return skill; 182 | } 183 | CharacterCommand.terminal.println(Message.MSG_NO_SKILL); 184 | } else { 185 | return skill; 186 | } 187 | } 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/app/io/ItemIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.core.items.Item; 6 | import app.utils.Help; 7 | import app.utils.Message; 8 | 9 | public class ItemIO { 10 | public static Item getItemByName(PlayerCharacter pc) { 11 | Item item; 12 | while (true) { 13 | String itemName = CharacterCommand.terminal.queryString("Item name: ", false); 14 | if (itemName.equalsIgnoreCase("cancel")) { 15 | return null; 16 | } else { 17 | for (Item coin : pc.getCurrency()) { 18 | if (coin.getName().equalsIgnoreCase(itemName)) { 19 | return coin; 20 | } 21 | } 22 | item = pc.getItem(itemName); 23 | if (item == null) { 24 | /*int matches = 0; 25 | for(String str:pc.getInventory().getContents().keySet()){ 26 | if(str.startsWith(itemName.toLowerCase())){ 27 | item = pc.getItem(str); 28 | matches++; 29 | } 30 | } 31 | if(matches == 1){ 32 | return item; 33 | }*/ 34 | CharacterCommand.terminal.println(Message.MSG_NO_ITEM); 35 | } else { 36 | return item; 37 | } 38 | } 39 | } 40 | } 41 | public static void use(PlayerCharacter pc) { 42 | CharacterCommand.tokens.pop(); 43 | if (!CharacterCommand.tokens.isEmpty()) { 44 | useParser(pc); 45 | } else { 46 | Item item = getItemByName(pc); 47 | if (item != null) { 48 | if (item.isConsumable()) { 49 | int amount = CharacterCommand.terminal.queryInteger("Amount: ", false); 50 | item.use(amount); 51 | CharacterCommand.terminal.println("Used " + amount + "x " + item.getName()); 52 | if (item.getCount() <= 0) { 53 | pc.removeItem(item); 54 | } 55 | } else { 56 | CharacterCommand.terminal.println(Message.ERROR_NOT_CON); 57 | } 58 | } 59 | } 60 | } 61 | 62 | private static void useParser(PlayerCharacter pc) { 63 | Item item; 64 | StringBuilder nameBuilder = new StringBuilder(); 65 | Integer amount = 1; //default 66 | boolean help = false; 67 | while (!CharacterCommand.tokens.isEmpty()) { 68 | switch (CharacterCommand.tokens.peek()) { 69 | case "-c": 70 | case "--count": 71 | CharacterCommand.tokens.pop(); 72 | if (CharacterCommand.tokens.isEmpty()) { 73 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": amount"); 74 | } else { 75 | amount = CharacterCommand.getIntToken(); 76 | } 77 | break; 78 | case "--help": 79 | help = true; 80 | CharacterCommand.tokens.pop(); 81 | break; 82 | default: 83 | if (CharacterCommand.tokens.peek().startsWith("-")) { 84 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 85 | } else { 86 | nameBuilder.append(CharacterCommand.tokens.pop()); 87 | nameBuilder.append(" "); 88 | } 89 | break; 90 | } 91 | } 92 | if (!help) { 93 | String itemName = nameBuilder.toString().trim(); 94 | item = pc.getItem(itemName); 95 | if (item != null && amount != null) { 96 | if (item.isConsumable()) { 97 | item.use(amount); 98 | CharacterCommand.terminal.println("Used " + amount + "x " + item.getName()); 99 | if (item.getCount() <= 0) { 100 | pc.removeItem(item); 101 | } 102 | } else { 103 | CharacterCommand.terminal.println(Message.ERROR_NOT_CON); 104 | } 105 | } else { 106 | CharacterCommand.terminal.println(Message.MSG_NO_ITEM); 107 | } 108 | } else { 109 | CharacterCommand.terminal.println(Help.USE); 110 | } 111 | } 112 | 113 | public static void equip(PlayerCharacter pc) { 114 | String command = CharacterCommand.tokens.pop(); 115 | if (!CharacterCommand.tokens.isEmpty()) { 116 | equipParser(pc, command); 117 | } else { 118 | Item item = getItemByName(pc); 119 | if (item != null) { 120 | if (item.isEquippable()) { 121 | if (command.equalsIgnoreCase("equip")) { 122 | if (!item.isEquipped()) { 123 | pc.equip(item); 124 | } else { 125 | CharacterCommand.terminal.println("ERROR: Item already equipped"); 126 | } 127 | } else { 128 | if (item.isEquipped()) { 129 | pc.dequip(item); 130 | } else { 131 | CharacterCommand.terminal.println("ERROR: Item not equipped"); 132 | } 133 | } 134 | } else { 135 | CharacterCommand.terminal.println(Message.ERROR_NOT_EQUIP); 136 | } 137 | } else { 138 | CharacterCommand.terminal.println(Message.MSG_NO_ITEM); 139 | } 140 | } 141 | } 142 | 143 | 144 | private static void equipParser(PlayerCharacter pc, String command) { 145 | Item item; 146 | StringBuilder nameBuilder = new StringBuilder(); 147 | boolean help = false; 148 | 149 | while (!CharacterCommand.tokens.isEmpty()) { 150 | if (CharacterCommand.tokens.peek().equals("--help")) { 151 | help = true; 152 | CharacterCommand.tokens.pop(); 153 | } 154 | nameBuilder.append(CharacterCommand.tokens.pop()); 155 | nameBuilder.append(" "); 156 | } 157 | if (!help) { 158 | String itemName = nameBuilder.toString().trim(); 159 | item = pc.getItem(itemName); 160 | if (item != null) { 161 | if (item.isEquippable()) { 162 | if (command.equalsIgnoreCase("equip")) { 163 | if (!item.isEquipped()) { 164 | pc.equip(item); 165 | CharacterCommand.terminal.println(item.getName()+" equipped"); 166 | } else { 167 | CharacterCommand.terminal.println("ERROR: Item already equipped"); 168 | } 169 | } else { 170 | if (item.isEquipped()) { 171 | pc.dequip(item); 172 | CharacterCommand.terminal.println(item.getName()+" dequipped"); 173 | } else { 174 | CharacterCommand.terminal.println("ERROR: Item not equipped"); 175 | } 176 | } 177 | } else { 178 | CharacterCommand.terminal.println(Message.ERROR_NOT_EQUIP); 179 | } 180 | } else { 181 | CharacterCommand.terminal.println(Message.MSG_NO_ITEM); 182 | } 183 | } else { 184 | if (command.equalsIgnoreCase("equip")) { 185 | CharacterCommand.terminal.println(Help.EQUIP); 186 | } else { 187 | CharacterCommand.terminal.println(Help.DEQUIP); 188 | } 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/app/io/PropertiesHandler.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.utils.Help; 5 | 6 | import java.io.*; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.nio.file.Paths; 10 | import java.util.Properties; 11 | 12 | public class PropertiesHandler{ 13 | private Path dataDir; 14 | private Path exportDir; 15 | private boolean viewAlways; 16 | private boolean resume; 17 | private String last; 18 | private Properties properties; 19 | 20 | 21 | public PropertiesHandler(){ 22 | this.properties = new Properties(); 23 | initProperties(); 24 | } 25 | 26 | private void initProperties() { 27 | OutputStream out = null; 28 | Path configPath = Paths.get("./config.properties"); 29 | if (!Files.exists(configPath)) { 30 | try { 31 | out = new FileOutputStream("config.properties"); 32 | 33 | properties.setProperty("dataDir", "./data"); 34 | properties.setProperty("exportDir", "./data"); 35 | properties.setProperty("viewAlways", "false"); 36 | properties.setProperty("resume", "false"); 37 | properties.setProperty("last", ""); 38 | 39 | properties.store(out, null); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } finally { 43 | if (out != null) { 44 | try { 45 | out.close(); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | } 52 | readProperties(); 53 | } 54 | 55 | private void readProperties(){ 56 | InputStream in = null; 57 | try{ 58 | in = new FileInputStream("config.properties"); 59 | properties.load(in); 60 | 61 | this.dataDir = Paths.get(properties.getProperty("dataDir", "./data")); 62 | this.exportDir = Paths.get(properties.getProperty("exportDir", "./data")); 63 | this.viewAlways = Boolean.parseBoolean(properties.getProperty("viewAlways", "false")); 64 | this.resume = Boolean.parseBoolean(properties.getProperty("resume", "false")); 65 | this.last = properties.getProperty("last", ""); 66 | 67 | } catch (IOException e) { 68 | e.printStackTrace(); 69 | } finally { 70 | if (in != null){ 71 | try{ 72 | in.close(); 73 | } catch (IOException e) { 74 | e.printStackTrace(); 75 | } 76 | } 77 | } 78 | } 79 | 80 | public void writeProperties(){ 81 | OutputStream out = null; 82 | try { 83 | out = new FileOutputStream("config.properties"); 84 | 85 | properties.setProperty("dataDir", dataDir.toString()); 86 | properties.setProperty("exportDir", exportDir.toString()); 87 | properties.setProperty("viewAlways", Boolean.toString(viewAlways)); 88 | properties.setProperty("resume", Boolean.toString(resume)); 89 | properties.setProperty("last", last); 90 | 91 | properties.store(out, null); 92 | } catch (IOException e){ 93 | e.printStackTrace(); 94 | } finally { 95 | if(out != null){ 96 | try { 97 | out.close(); 98 | } catch (IOException e) { 99 | e.printStackTrace(); 100 | } 101 | } 102 | } 103 | } 104 | 105 | public void prefs(){ 106 | String command = CharacterCommand.tokens.pop(); 107 | if(!CharacterCommand.tokens.isEmpty()){ 108 | prefs(command); 109 | } else { 110 | //TODO: prefs 111 | CharacterCommand.terminal.println("manual prefs editing placeholder -- use command arguments for now"); 112 | } 113 | } 114 | 115 | private void prefs(String command){ 116 | while(!CharacterCommand.tokens.isEmpty()) { 117 | switch (CharacterCommand.tokens.peek()) { 118 | case "-e": 119 | case "--export": 120 | CharacterCommand.tokens.pop(); 121 | if(!CharacterCommand.tokens.isEmpty()){ 122 | File exportFile = Paths.get(CharacterCommand.tokens.pop()).toFile(); 123 | if (exportFile.isDirectory()){ 124 | this.exportDir = exportFile.toPath(); 125 | } 126 | CharacterCommand.terminal.println("Set export directory to " + exportFile.toString()); 127 | } 128 | break; 129 | case "-d": 130 | case "--data": 131 | CharacterCommand.tokens.pop(); 132 | if(!CharacterCommand.tokens.isEmpty()){ 133 | File dataFile = Paths.get(CharacterCommand.tokens.pop()).toFile(); 134 | if (dataFile.isDirectory()){ 135 | this.dataDir = dataFile.toPath(); 136 | } 137 | CharacterCommand.terminal.println("Set data directory to " + dataFile.toString()); 138 | } 139 | break; 140 | case "-v": 141 | case "-va": 142 | case "--viewAlways": 143 | CharacterCommand.tokens.pop(); 144 | if(!CharacterCommand.tokens.isEmpty()){ 145 | String token = CharacterCommand.tokens.pop(); 146 | if (token.equalsIgnoreCase("true") || token.equalsIgnoreCase("false")){ 147 | this.viewAlways = Boolean.parseBoolean(token); 148 | CharacterCommand.terminal.println("Set 'viewAlways' to " + token); 149 | } else { 150 | CharacterCommand.terminal.println("ERROR: Argument must be 'true' or 'false'"); 151 | } 152 | } 153 | break; 154 | case "-r": 155 | case "--resume": 156 | CharacterCommand.tokens.pop(); 157 | if(!CharacterCommand.tokens.isEmpty()){ 158 | String token = CharacterCommand.tokens.pop(); 159 | if (token.equalsIgnoreCase("true") || token.equalsIgnoreCase("false")){ 160 | this.resume = Boolean.parseBoolean(token); 161 | CharacterCommand.terminal.println("Set 'resume' to " + token); 162 | } else { 163 | CharacterCommand.terminal.println("ERROR: Argument must be 'true' or 'false'"); 164 | } 165 | } 166 | break; 167 | case "--help": 168 | CharacterCommand.tokens.pop(); 169 | CharacterCommand.terminal.println(Help.PREFS); 170 | break; 171 | default: 172 | if (CharacterCommand.tokens.peek().startsWith("-")) { 173 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 174 | } else { 175 | CharacterCommand.tokens.pop(); 176 | } 177 | break; 178 | } 179 | } 180 | this.writeProperties(); 181 | } 182 | public Path getDataDir(){ 183 | return dataDir; 184 | } 185 | public Path getExportDir(){ 186 | return exportDir; 187 | } 188 | public boolean isViewAlways(){ 189 | this.viewAlways = Boolean.parseBoolean(properties.getProperty("viewAlways", "false")); 190 | return viewAlways; 191 | } 192 | public boolean isResume(){ 193 | return resume; 194 | } 195 | public String getLast(){ 196 | return last; 197 | } 198 | public void setLast(String last){ 199 | this.last = last; 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/app/terminal/TerminalIOComponent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Creator: Matthew Shems 3 | * 4 | */ 5 | 6 | package app.terminal; 7 | 8 | import javax.swing.*; 9 | import javax.swing.text.BadLocationException; 10 | import java.awt.*; 11 | import java.awt.event.ActionEvent; 12 | import java.awt.event.KeyEvent; 13 | import java.util.LinkedList; 14 | 15 | public class TerminalIOComponent extends JTextArea{ 16 | private TerminalEventListener listener; 17 | private boolean allowBackSpace; 18 | private boolean multiline; 19 | private boolean querying; 20 | private int lastPromptPos; 21 | private String currPrompt; 22 | private String defaultPrompt; 23 | private LinkedList history; 24 | private int historyPointer = 0; 25 | private static final int MAX_LINES = 256; 26 | private int fontSize = 17; 27 | 28 | private static final String USER_NAME = System.getProperty("user.name"); 29 | private static final String DEFAULT_PROMPT = USER_NAME+" ~ "; 30 | 31 | public TerminalIOComponent(){} 32 | 33 | public TerminalIOComponent(boolean multi){ 34 | this.addKeyListener(new TerminalKeylistener(this)); 35 | this.remapEnterKey(); 36 | this.remapArrows(); 37 | this.setMargin(new Insets(5,5,5,5)); 38 | this.setBackground(Terminal.background_color); 39 | this.setForeground(Terminal.foreground_color); 40 | this.setCaretColor(Terminal.highlight_color); 41 | this.setFont(new Font("consolas", Font.PLAIN, fontSize)); 42 | history = new LinkedList<>(); 43 | multiline = multi; 44 | defaultPrompt = DEFAULT_PROMPT; 45 | currPrompt = defaultPrompt; 46 | querying = false; 47 | allowBackSpace = false; 48 | } 49 | 50 | void start(){ 51 | this.setEditable(true); 52 | this.prompt(); 53 | this.advanceCaret(); 54 | } 55 | 56 | public String getInput(){ 57 | return this.getText().substring(lastPromptPos); 58 | } 59 | 60 | private boolean isOnNewLine(){ 61 | return (this.getText().endsWith(System.lineSeparator()) || this.getText().endsWith("\n")); 62 | } 63 | 64 | void newLine(){ 65 | if(multiline) { 66 | this.append(System.lineSeparator()); 67 | } else { 68 | this.clear(); 69 | } 70 | } 71 | 72 | void advance(){ 73 | if(this.getLineCount()>=MAX_LINES){ 74 | int linesToRemove = this.getLineCount()-MAX_LINES; 75 | try { 76 | this.replaceRange("", 77 | this.getLineStartOffset(0), 78 | this.getLineEndOffset(linesToRemove)); 79 | } catch (BadLocationException e){ 80 | //e.printStackTrace(); 81 | } 82 | } 83 | this.prompt(); 84 | this.advanceCaret(); 85 | } 86 | 87 | private void prompt(){ 88 | if(multiline){ 89 | if(this.isOnNewLine() || this.isClear()){ 90 | this.append(currPrompt); 91 | } else { 92 | this.append(System.lineSeparator() + currPrompt); 93 | } 94 | } else { 95 | this.setText(currPrompt); 96 | } 97 | } 98 | 99 | private void advanceCaret(){ 100 | this.lastPromptPos = getText().lastIndexOf(currPrompt) + currPrompt.length(); 101 | this.setCaretPosition(lastPromptPos); 102 | } 103 | 104 | void clear(){ 105 | this.setText(""); 106 | } 107 | 108 | private boolean isClear(){ 109 | return this.getText().isEmpty(); 110 | } 111 | 112 | void print(String s){ 113 | this.append(s); 114 | } 115 | 116 | void println(String s){ 117 | this.append(s+System.lineSeparator()); 118 | } 119 | 120 | void printCentered(String str){ 121 | int width = ((this.getWidth()/this.getColumnWidth())-str.length()); 122 | for(int i=0; i<(width-1)/2; i++){ 123 | str = " "+str+" "; 124 | } 125 | this.println(str); 126 | } 127 | 128 | void printRightAligned(String str){ 129 | int width = ((this.getWidth()/this.getColumnWidth())-str.length()); 130 | for(int i=0; i=25){ 138 | history.removeLast(); 139 | } 140 | history.addFirst(command); 141 | historyPointer = 0; 142 | } 143 | 144 | void fireEvent(SubmitEvent e){ 145 | if(listener!=null){ 146 | listener.submitActionPerformed(e); 147 | } 148 | } 149 | 150 | void fireEvent(QueryEvent e){ 151 | if(listener!=null){ 152 | listener.queryActionPerformed(e); 153 | } 154 | } 155 | 156 | void disableBackSpace(){ 157 | allowBackSpace = false; 158 | this.getInputMap().put(KeyStroke.getKeyStroke("BACK_SPACE"), "none"); 159 | } 160 | 161 | void enableBackSpace(){ 162 | allowBackSpace = true; 163 | this.getInputMap().put(KeyStroke.getKeyStroke("BACK_SPACE"), "delete-previous"); 164 | } 165 | 166 | private void remapEnterKey(){ 167 | this.getInputMap().put((KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), ""); 168 | } 169 | 170 | private void remapArrows(){ 171 | //LEFT ARROW 172 | this.getActionMap().put("leftArrowAction", new AbstractAction(){ 173 | @Override 174 | public void actionPerformed(ActionEvent e){ 175 | if(getCaretPosition() > lastPromptPos){ 176 | setCaretPosition(getCaretPosition()-1); 177 | } 178 | } 179 | }); 180 | this.getInputMap().put((KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), "leftArrowAction"); 181 | 182 | //RIGHT ARROW 183 | this.getActionMap().put("rightArrowAction", new AbstractAction(){ 184 | @Override 185 | public void actionPerformed(ActionEvent e){ 186 | if(getCaretPosition() < getText().length()){ 187 | setCaretPosition(getCaretPosition()+1); 188 | } 189 | } 190 | }); 191 | this.getInputMap().put((KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), "rightArrowAction"); 192 | 193 | 194 | //UP ARROW 195 | this.getActionMap().put("upArrowAction", new AbstractAction(){ 196 | @Override 197 | public void actionPerformed(ActionEvent e){ 198 | if(!history.isEmpty() && historyPointer < history.size()){ 199 | historyPointer++; 200 | setText(getText().substring(0,lastPromptPos)+history.get(historyPointer-1)); 201 | } 202 | } 203 | }); 204 | this.getInputMap().put((KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)), "upArrowAction"); 205 | 206 | //DOWN ARROW 207 | this.getActionMap().put("downArrowAction", new AbstractAction(){ 208 | @Override 209 | public void actionPerformed(ActionEvent e){ 210 | if(historyPointer > 1 ){ 211 | historyPointer--; 212 | setText(getText().substring(0,lastPromptPos)+history.get(historyPointer-1)); 213 | } else if(historyPointer == 1){ 214 | setText(getText().substring(0,lastPromptPos)+""); 215 | } 216 | } 217 | }); 218 | this.getInputMap().put((KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)), "downArrowAction"); 219 | } 220 | 221 | public int getFontSize() { 222 | return fontSize; 223 | } 224 | 225 | public void setFontSize(int fontSize) { 226 | this.fontSize = fontSize; 227 | this.setFont(new Font("consolas", Font.PLAIN, fontSize)); 228 | } 229 | 230 | public String getCurrPrompt() { 231 | return currPrompt; 232 | } 233 | 234 | public void setCurrPrompt(String currPrompt){ 235 | this.currPrompt = currPrompt; 236 | } 237 | 238 | public void resetPrompt(){ 239 | this.currPrompt = defaultPrompt; 240 | } 241 | 242 | public void setDefaultPrompt(String prompt){ 243 | this.defaultPrompt = prompt; 244 | } 245 | 246 | public int getLastPromptPos() { 247 | return lastPromptPos; 248 | } 249 | 250 | public boolean isAllowBackSpace() { 251 | return allowBackSpace; 252 | } 253 | 254 | public boolean isQuerying() { 255 | return querying; 256 | } 257 | 258 | public void setQuerying(boolean querying) { 259 | this.querying = querying; 260 | } 261 | 262 | public void setTerminalEventListener(TerminalEventListener listener){ 263 | this.listener = listener; 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/app/io/SpellSlotIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.core.magic.Spell; 6 | import app.core.magic.SpellSlot; 7 | import app.utils.Help; 8 | import app.utils.Message; 9 | 10 | public class SpellSlotIO { 11 | public static void spellSlots(PlayerCharacter pc) { 12 | CharacterCommand.tokens.pop(); 13 | if (!CharacterCommand.tokens.isEmpty()) { 14 | switch (CharacterCommand.tokens.peek()) { 15 | case "--charge": 16 | charge(pc); 17 | break; 18 | case "--set": 19 | setSlots(pc); 20 | break; 21 | case "--help": 22 | CharacterCommand.terminal.println(Help.SPELLSLOTS); 23 | break; 24 | default: 25 | CharacterCommand.terminal.println(Message.ERROR_INPUT); 26 | break; 27 | } 28 | } else { 29 | CharacterCommand.terminal.println("charge | set | view"); 30 | String action = CharacterCommand.terminal.queryString("Action: ", false); 31 | switch (action.toLowerCase()){ 32 | case "c": 33 | case "charge": 34 | charge(pc); 35 | break; 36 | case "s": 37 | case "set": 38 | setSlots(pc); 39 | break; 40 | case "v": 41 | case "view": 42 | CharacterCommand.terminal.println(pc.spellSlotsToString()); 43 | 44 | } 45 | } 46 | } 47 | 48 | private static void setSlots(PlayerCharacter pc) { 49 | CharacterCommand.tokens.pop(); 50 | if (!CharacterCommand.tokens.isEmpty()) { 51 | setSlotsParser(pc); 52 | } else { 53 | int level = CharacterCommand.terminal.queryInteger("Enter spell slot level: ", false); 54 | int max = CharacterCommand.terminal.queryInteger("Enter new spell slot maximum: ", false); 55 | pc.getSpellSlots()[level].setMaxVal(max); 56 | CharacterCommand.terminal.println("Maximum level " + level + " spell slots set to " + max); 57 | } 58 | } 59 | 60 | private static void setSlotsParser(PlayerCharacter pc) { 61 | Integer level = null; 62 | Integer max = null; 63 | boolean help = false; 64 | while (!CharacterCommand.tokens.isEmpty()) { 65 | switch (CharacterCommand.tokens.peek()) { 66 | case "-l": 67 | case "--level": 68 | CharacterCommand.tokens.pop(); 69 | if (CharacterCommand.tokens.isEmpty()) { 70 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 71 | } else { 72 | level = CharacterCommand.getIntToken(); 73 | if (level > Spell.MAX_LEVEL) { 74 | level = Spell.MAX_LEVEL; 75 | } 76 | if (level < Spell.CANTRIP) { 77 | level = Spell.CANTRIP; 78 | } 79 | } 80 | break; 81 | case "-m": 82 | case "--max": 83 | CharacterCommand.tokens.pop(); 84 | if (CharacterCommand.tokens.isEmpty()) { 85 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": count"); 86 | } else { 87 | max = CharacterCommand.getIntToken(); 88 | } 89 | break; 90 | case "--help": 91 | CharacterCommand.tokens.pop(); 92 | help = true; 93 | break; 94 | default: 95 | if (CharacterCommand.tokens.peek().startsWith("-")) { 96 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 97 | } else { 98 | CharacterCommand.tokens.pop(); 99 | } 100 | break; 101 | } 102 | } 103 | if (help) { 104 | CharacterCommand.terminal.println(Help.SETSLOTS); 105 | } else { 106 | if (level != null && max != null) { 107 | pc.getSpellSlots()[level].setMaxVal(max); 108 | CharacterCommand.terminal.println("Maximum level " + level + " spell slots set to " + max); 109 | } 110 | } 111 | } 112 | 113 | public static void charge(PlayerCharacter pc) { 114 | CharacterCommand.tokens.pop(); 115 | if (!CharacterCommand.tokens.isEmpty()) { 116 | chargeParser(pc); 117 | } else { 118 | int level = CharacterCommand.terminal.queryInteger("Enter spell slot level: ", false); 119 | int count = CharacterCommand.terminal.queryInteger("Enter number of slots to recharge: ", false); 120 | pc.getSpellSlots()[level].charge(count); 121 | CharacterCommand.terminal.println("Recharged " + count + " level " + level + " spell slots"); 122 | } 123 | } 124 | 125 | private static void chargeParser(PlayerCharacter pc) { 126 | boolean all = false; 127 | boolean help = false; 128 | Integer level = null; 129 | Integer count = null; 130 | while (!CharacterCommand.tokens.isEmpty()) { 131 | switch (CharacterCommand.tokens.peek()) { 132 | case "-l": 133 | case "--level": 134 | CharacterCommand.tokens.pop(); 135 | if (CharacterCommand.tokens.isEmpty()) { 136 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 137 | } else { 138 | level = CharacterCommand.getIntToken(); 139 | if (level > Spell.MAX_LEVEL) { 140 | level = Spell.MAX_LEVEL; 141 | } 142 | if (level < Spell.CANTRIP) { 143 | level = Spell.CANTRIP; 144 | } 145 | } 146 | break; 147 | case "-c": 148 | case "--count": 149 | CharacterCommand.tokens.pop(); 150 | if (CharacterCommand.tokens.isEmpty()) { 151 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": count"); 152 | } else { 153 | count = CharacterCommand.getIntToken(); 154 | } 155 | break; 156 | case "--all": 157 | CharacterCommand.tokens.pop(); 158 | all = true; 159 | break; 160 | case "--help": 161 | CharacterCommand.tokens.pop(); 162 | help = true; 163 | break; 164 | default: 165 | if (CharacterCommand.tokens.peek().startsWith("-")) { 166 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 167 | } else { 168 | CharacterCommand.tokens.pop(); 169 | } 170 | break; 171 | } 172 | } 173 | if (help) { 174 | CharacterCommand.terminal.println(Help.CHARGE); 175 | } else { 176 | if (level == null && count == null) { 177 | if (all) { 178 | for (SpellSlot s : pc.getSpellSlots()) { 179 | if (s.getMaxVal() > 0) { 180 | s.fullCharge(); 181 | } 182 | } 183 | CharacterCommand.terminal.println("All spell slots recharged"); 184 | } else { 185 | CharacterCommand.terminal.println(Message.ERROR_NO_VALUE); 186 | } 187 | } else if (level != null && count == null) { 188 | if (all) { 189 | pc.getSpellSlots()[level].fullCharge(); 190 | CharacterCommand.terminal.println("Level " + level + " spell slots fully recharged"); 191 | } else { 192 | pc.getSpellSlots()[level].charge(); 193 | CharacterCommand.terminal.println("Level " + level + " spell slot recharged"); 194 | } 195 | } 196 | if (level == null && count != null) { 197 | if (all) { 198 | for (SpellSlot s : pc.getSpellSlots()) { 199 | if (s.getMaxVal() > 0) { 200 | s.charge(count); 201 | } 202 | } 203 | CharacterCommand.terminal.println("Recharged " + count + " spell slots of each level known"); 204 | } else { 205 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": level"); 206 | } 207 | } else if (level != null && count != null) { 208 | pc.getSpellSlots()[level].charge(count); 209 | CharacterCommand.terminal.println("Recharged " + count + " level " + level + " spell slots"); 210 | } 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/app/terminal/Terminal.java: -------------------------------------------------------------------------------- 1 | package app.terminal; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.util.*; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | 8 | public class Terminal implements TerminalEventListener { 9 | private Dimension windowSize = new Dimension(850, 650); 10 | private TerminalIOComponent inputComponent; 11 | private TerminalIOComponent outputComponent; 12 | private JFrame frame; 13 | private LinkedBlockingQueue commandQueue; 14 | private LinkedList commandTokens; 15 | private CommandMap commandMap; 16 | private boolean dualDisplay; 17 | private CommandExecutor commandExecutor; 18 | 19 | private Properties properties; 20 | 21 | public static final Color background_color = new Color(33, 33, 33); 22 | public static final Color foreground_color = new Color(245, 245, 245); 23 | public static final Color highlight_color = new Color(220, 220, 220); 24 | 25 | public static final int LEFT_ALIGNED = 0; 26 | public static final int CENTERED = 1; 27 | public static final int RIGHT_ALIGNED = 2; 28 | 29 | public Terminal(String title) { 30 | this.dualDisplay = false; 31 | commandQueue = new LinkedBlockingQueue<>(); 32 | commandTokens = new LinkedList<>(); 33 | commandMap = new CommandMap(); 34 | commandExecutor = new CommandExecutor(); 35 | properties = new Properties(); 36 | addDefaultCommands(); 37 | initGUI(title); 38 | PropertyHandler.initProperties(this); 39 | } 40 | 41 | 42 | private void initGUI(String title) { 43 | frame = new JFrame(title); 44 | frame.setMinimumSize(windowSize); 45 | frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 46 | frame.setLayout(new BorderLayout()); 47 | 48 | /*if(dualDisplay){ 49 | inputComponent = new TerminalIOComponent(false); 50 | inputComponent.setTerminalEventListener(this); 51 | outputComponent = new TerminalDisplayComponent(); 52 | frame.add(inputComponent, BorderLayout.SOUTH); 53 | } else {*/ 54 | inputComponent = new TerminalIOComponent(true); 55 | inputComponent.setTerminalEventListener(this); 56 | outputComponent = inputComponent; 57 | //} 58 | 59 | JScrollPane scrollPane = new JScrollPane(outputComponent); 60 | scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 61 | frame.add(scrollPane, BorderLayout.CENTER); 62 | frame.pack(); 63 | } 64 | 65 | public synchronized void start() { 66 | frame.setVisible(true); 67 | inputComponent.start(); 68 | while (true) { 69 | try { 70 | wait(); 71 | if (!commandQueue.isEmpty()) { 72 | tokenize(commandQueue.take()); 73 | commandExecutor.doCommand(this, commandTokens.peek()); 74 | } 75 | inputComponent.advance(); 76 | } catch (InterruptedException e) { 77 | //e.printStackTrace(); 78 | break; 79 | } 80 | } 81 | } 82 | 83 | public void close(){ 84 | PropertyHandler.writeProperties(this); 85 | frame.setVisible(false); 86 | } 87 | 88 | private void tokenize(String command) { 89 | String[] input = command 90 | .trim() 91 | .split("\\s+"); 92 | Collections.addAll(commandTokens, input); 93 | } 94 | 95 | private synchronized String query(String queryPrompt) { 96 | String input = ""; 97 | inputComponent.setCurrPrompt(queryPrompt); 98 | inputComponent.advance(); 99 | inputComponent.setQuerying(true); 100 | synchronized (this) { 101 | try { 102 | this.wait(); 103 | input = inputComponent.getInput(); 104 | } catch (InterruptedException ex) { 105 | //ex.printStackTrace(); 106 | } 107 | } 108 | inputComponent.resetPrompt(); 109 | newLine(); 110 | return input.trim(); 111 | } 112 | 113 | public String queryString(String queryPrompt, boolean allowEmptyString) { 114 | while (true) { 115 | String input = query(queryPrompt); 116 | if (input.isEmpty() && allowEmptyString) { 117 | return input; 118 | } else if (!input.isEmpty()) { 119 | return input; 120 | } 121 | println("Empty input not allowed"); 122 | } 123 | } 124 | 125 | public boolean queryYN(String queryPrompt) { 126 | switch (query(queryPrompt).toLowerCase()) { 127 | case "y": 128 | case "yes": 129 | return true; 130 | default: 131 | return false; 132 | } 133 | } 134 | 135 | public Integer queryInteger(String queryPrompt, boolean allowNull) { 136 | while (true) { 137 | try { 138 | return Integer.parseInt(query(queryPrompt)); 139 | } catch (NumberFormatException e) { 140 | if (allowNull) { 141 | break; 142 | } 143 | println("Not an integer value"); 144 | } 145 | } 146 | return null; 147 | } 148 | 149 | public Double queryDouble(String queryPrompt, boolean allowNull) { 150 | while (true) { 151 | try { 152 | return Double.parseDouble(query(queryPrompt)); 153 | } catch (NumberFormatException e) { 154 | if (allowNull) { 155 | break; 156 | } 157 | println("Not a double value"); 158 | } 159 | } 160 | return null; 161 | } 162 | 163 | public Boolean queryBoolean(String queryPrompt, boolean allowNull) { 164 | while (true) { 165 | switch (query(queryPrompt).toLowerCase()) { 166 | case "t": 167 | case "true": 168 | return true; 169 | case "f": 170 | case "false": 171 | return false; 172 | default: 173 | if (allowNull) { 174 | return null; 175 | } 176 | println("Not a boolean value"); 177 | } 178 | } 179 | } 180 | 181 | public void newLine() { 182 | inputComponent.newLine(); 183 | } 184 | 185 | public void clear() { 186 | if (dualDisplay) { 187 | outputComponent.clear(); 188 | } else { 189 | inputComponent.clear(); 190 | } 191 | } 192 | 193 | public void printf(String format, Object... args) { 194 | outputComponent.print(String.format(format, args)); 195 | } 196 | 197 | public void print(String str) { 198 | outputComponent.print(str); 199 | } 200 | 201 | public void print(Integer n) { 202 | outputComponent.print(n.toString()); 203 | } 204 | 205 | public void print(Double d) { 206 | outputComponent.print(d.toString()); 207 | } 208 | 209 | public void print(Boolean b) { 210 | outputComponent.print(b.toString()); 211 | } 212 | 213 | public void print(Object o) { 214 | outputComponent.print(o.toString()); 215 | } 216 | 217 | public void println(String str) { 218 | outputComponent.println(str); 219 | } 220 | 221 | public void println(Integer n) { 222 | outputComponent.println(n.toString()); 223 | } 224 | 225 | public void println(Double d) { 226 | outputComponent.println(d.toString()); 227 | } 228 | 229 | public void println(Boolean b) { 230 | outputComponent.println(b.toString()); 231 | } 232 | 233 | public void println(Object o) { 234 | outputComponent.println(o.toString()); 235 | } 236 | 237 | public void println(String str, int PRINT_FORMAT) { 238 | switch (PRINT_FORMAT) { 239 | case Terminal.LEFT_ALIGNED: 240 | outputComponent.print(str); 241 | break; 242 | case Terminal.CENTERED: 243 | outputComponent.printCentered(str); 244 | break; 245 | case Terminal.RIGHT_ALIGNED: 246 | outputComponent.printRightAligned(str); 247 | break; 248 | default: 249 | outputComponent.print(str); 250 | break; 251 | } 252 | } 253 | 254 | public synchronized void submitActionPerformed(SubmitEvent e) { 255 | this.notifyAll(); 256 | try { 257 | commandQueue.put(e.inputString); 258 | inputComponent.updateHistory(e.inputString); 259 | } catch (InterruptedException ex) { 260 | //ex.printStackTrace(); 261 | } 262 | } 263 | 264 | public synchronized void queryActionPerformed(QueryEvent e) { 265 | this.notifyAll(); 266 | } 267 | 268 | public synchronized void menuActionPerformed(MenuEvent e) { 269 | this.notifyAll(); 270 | } 271 | 272 | public void addDefaultCommands() { 273 | commandMap.put("", () -> { 274 | }); 275 | commandMap.put("clear", this::clear); 276 | commandMap.put("terminal-config", this::config); 277 | } 278 | 279 | private void config() { 280 | commandTokens.pop(); 281 | switch (commandTokens.pop()) { 282 | case "font-size": 283 | if(!commandTokens.isEmpty()) { 284 | try { 285 | int fontSize = Integer.parseInt(commandTokens.pop()); 286 | setFontSize(fontSize); 287 | properties.setProperty("font-size", Integer.toString(fontSize)); 288 | } catch (NumberFormatException e){ 289 | e.printStackTrace(); 290 | } 291 | } 292 | break; 293 | default: 294 | break; 295 | } 296 | PropertyHandler.writeProperties(this); 297 | } 298 | 299 | public void removeDefaultCommands() { 300 | commandMap.remove(""); 301 | commandMap.remove("clear"); 302 | commandMap.remove("terminal-config"); 303 | } 304 | 305 | public void putCommand(String key, TerminalCommand command) { 306 | commandMap.put(key, command); 307 | } 308 | 309 | public void replaceCommand(String key, TerminalCommand command) { 310 | commandMap.replace(key, command); 311 | } 312 | 313 | public void removeCommand(String key, TerminalCommand command) { 314 | commandMap.remove(key, command); 315 | } 316 | 317 | public void removeCommand(String key) { 318 | commandMap.remove(key); 319 | } 320 | 321 | public TerminalCommand getCommand(String key) { 322 | return this.commandMap.get(key); 323 | } 324 | 325 | public CommandMap getCommandMap() { 326 | return commandMap; 327 | } 328 | 329 | public void setCommandExecutor(CommandExecutor commandExecutor) { 330 | this.commandExecutor = commandExecutor; 331 | } 332 | 333 | public TerminalIOComponent getInputComponent() { 334 | return inputComponent; 335 | } 336 | 337 | public TerminalIOComponent getOutputComponent() { 338 | return outputComponent; 339 | } 340 | 341 | public void setDefaultPrompt(String prompt) { 342 | inputComponent.setDefaultPrompt(prompt); 343 | inputComponent.setCurrPrompt(prompt); 344 | } 345 | 346 | public LinkedList getCommandTokens() { 347 | return commandTokens; 348 | } 349 | 350 | public Properties getProperties() { 351 | return this.properties; 352 | } 353 | 354 | public int getFontSize() { 355 | return outputComponent.getFontSize(); 356 | 357 | } 358 | 359 | public void setFontSize(int fontSize) { 360 | this.inputComponent.setFontSize(fontSize); 361 | this.outputComponent.setFontSize(fontSize); 362 | } 363 | } -------------------------------------------------------------------------------- /src/app/CharacterCommand.java: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import app.io.*; 4 | import app.core.character.*; 5 | import app.core.items.*; 6 | import app.core.magic.*; 7 | import app.terminal.CommandExecutor; 8 | import app.terminal.Terminal; 9 | import app.utils.*; 10 | 11 | import java.util.*; 12 | 13 | //@SuppressWarnings("unused") 14 | public class CharacterCommand { 15 | /** 16 | * version 0.2.4 17 | */ 18 | public static final long VERSION = 203L; 19 | private static final String splash = "CharacterCommand v0.2.4"; 20 | private static PlayerCharacter activeChar; 21 | public static LinkedHashMap characterList; 22 | public static String[] input; 23 | public static LinkedList tokens; 24 | public static PropertiesHandler propertiesHandler; 25 | public static ReadWriteHandler readWriteHandler; 26 | public static Terminal terminal; 27 | 28 | public static PlayerCharacter getActiveChar(){ 29 | return activeChar; 30 | } 31 | public static void setActiveChar(PlayerCharacter pc){ 32 | activeChar = pc; 33 | } 34 | public static boolean hasActiveChar(){ 35 | if(activeChar !=null){ 36 | return true; 37 | } 38 | return false; 39 | } 40 | public static void main(String[] args) { 41 | initApp(); 42 | 43 | terminal = new Terminal(splash); 44 | tokens = terminal.getCommandTokens(); 45 | 46 | terminal.setDefaultPrompt("CharacterCommand ~ "); 47 | if(activeChar!= null){ 48 | terminal.getOutputComponent().setCurrPrompt(activeChar.getName()+" @ CharacterCommand ~ "); 49 | } 50 | initCommands(); 51 | terminal.println(splash, Terminal.CENTERED); 52 | terminal.start(); 53 | } 54 | 55 | private static void initApp() { 56 | propertiesHandler = new PropertiesHandler(); 57 | readWriteHandler = new ReadWriteHandler(); 58 | ReadWriteHandler.checkDirs(); 59 | characterList = new LinkedHashMap<>(); 60 | readWriteHandler.importAll(false); 61 | if (propertiesHandler.isResume()) { 62 | String key = propertiesHandler.getLast(); 63 | if (characterList.containsKey(key)) { 64 | activeChar = characterList.get(key); 65 | } 66 | } 67 | //makeTestCharacter(); 68 | } 69 | 70 | public static void quit(){ 71 | boolean quit = terminal.queryYN("Are you sure? Unsaved data will be lost [Y/N] : "); 72 | if(quit){ 73 | closeApp(); 74 | System.exit(0); 75 | } 76 | } 77 | 78 | public static void closeApp(){ 79 | if (activeChar == null) { 80 | propertiesHandler.setLast(""); 81 | } else { 82 | propertiesHandler.setLast(activeChar.getName().toLowerCase()); 83 | } 84 | propertiesHandler.writeProperties(); 85 | } 86 | 87 | private static void initCommands(){ 88 | terminal.setCommandExecutor(new CommandExecutor(){ 89 | public void doCommand(Terminal terminal, String token) { 90 | if (activeChar != null || loadNotRequired(token)) { 91 | super.doCommand(terminal, token); 92 | } else { 93 | tokens.clear(); 94 | } 95 | if(activeChar!=null){ 96 | terminal.getOutputComponent().setCurrPrompt(activeChar.getName()+" @ CharacterCommand ~ "); 97 | } else { 98 | terminal.getOutputComponent().resetPrompt(); 99 | } 100 | } 101 | }); 102 | terminal.putCommand("import", ()->readWriteHandler.importCharacter()); 103 | 104 | terminal.putCommand("export", ()->readWriteHandler.export()); 105 | 106 | terminal.putCommand("load", ()->readWriteHandler.loadChar()); 107 | 108 | terminal.putCommand("list", ()->dispCharacterList()); 109 | 110 | terminal.putCommand("save",()->readWriteHandler.saveChar(true)); 111 | 112 | terminal.putCommand("prefs", ()->propertiesHandler.prefs()); 113 | 114 | terminal.putCommand("new", ()->PlayerCreator.createCharacter()); 115 | 116 | terminal.putCommand("view", ()->terminal.println(activeChar.toString())); 117 | terminal.putCommand("v", terminal.getCommand("view")); 118 | 119 | terminal.putCommand("inv", ()->terminal.println(activeChar.getInventory().toString())); 120 | terminal.putCommand("i", terminal.getCommand("inv")); 121 | 122 | terminal.putCommand("get", ()->InventoryIO.get(activeChar)); 123 | 124 | terminal.putCommand("add", ()->InventoryIO.addDrop(activeChar)); 125 | terminal.putCommand("drop", terminal.getCommand("add")); 126 | 127 | terminal.putCommand("equip", ()-> ItemIO.equip(activeChar)); 128 | terminal.putCommand("dequip", terminal.getCommand("equip")); 129 | 130 | terminal.putCommand("use", ()->ItemIO.use(activeChar)); 131 | 132 | terminal.putCommand("stats", ()->StatIO.stats(activeChar)); 133 | 134 | terminal.putCommand("stat", terminal.getCommand("stats")); 135 | 136 | terminal.putCommand("edit", ()->StatEditor.edit(activeChar)); 137 | 138 | terminal.putCommand("skills", ()->terminal.println(activeChar.skillsToString())); 139 | terminal.putCommand("skill", ()-> SkillIO.skills(activeChar)); 140 | 141 | terminal.putCommand("ap", ()-> AbilityPointsIO.abilityPoints(activeChar)); 142 | 143 | terminal.putCommand("spells", ()->terminal.println(activeChar.getSpellBook().toString())); 144 | terminal.putCommand("spell", ()-> SpellIO.spells(activeChar)); 145 | 146 | terminal.putCommand("spellslots", ()->terminal.println(activeChar.spellSlotsToString())); 147 | terminal.putCommand("spellslot", ()-> SpellSlotIO.spellSlots(activeChar)); 148 | 149 | terminal.putCommand("charge", ()->SpellSlotIO.charge(activeChar)); 150 | 151 | terminal.putCommand("cast", ()->SpellIO.cast(activeChar)); 152 | 153 | terminal.putCommand("learn", ()-> SpellBookIO.learn(activeChar)); 154 | 155 | terminal.putCommand("forget", ()->SpellBookIO.forget(activeChar)); 156 | 157 | terminal.putCommand("heal", ()->PlayerHealer.heal(activeChar)); 158 | terminal.putCommand("hurt", terminal.getCommand("heal")); 159 | 160 | terminal.putCommand("levelup", ()->PlayerLeveler.levelUp(activeChar)); 161 | terminal.putCommand("lvl", terminal.getCommand("levelup")); 162 | 163 | terminal.putCommand("help", ()->Help.helpMenu(terminal)); 164 | 165 | terminal.putCommand("quit", ()->quit()); 166 | terminal.putCommand("q", terminal.getCommand("quit")); 167 | 168 | terminal.putCommand("sq", ()->{ 169 | readWriteHandler.saveChar(false); 170 | closeApp(); 171 | System.exit(0); 172 | }); 173 | } 174 | 175 | private static boolean loadNotRequired(String token){ 176 | if(terminal.getCommand(token) == null){ 177 | return true; 178 | } 179 | switch (token.toLowerCase()){ 180 | case "import": 181 | case "load": 182 | case "list": 183 | case "prefs": 184 | case "new": 185 | case "quit": 186 | case "help": 187 | case "credits": 188 | case "terminal-config": 189 | return true; 190 | default: 191 | terminal.newLine(); 192 | terminal.println(Message.ERROR_NO_LOAD); 193 | return false; 194 | } 195 | } 196 | 197 | public static Integer getIntToken() { 198 | Integer n = null; 199 | try { 200 | if (tokens.isEmpty()) { 201 | terminal.println(Message.ERROR_NO_VALUE); 202 | } else { 203 | n = Integer.parseInt(tokens.pop()); 204 | } 205 | } catch (NumberFormatException e) { 206 | terminal.println(Message.ERROR_NOT_INT); 207 | } 208 | return n; 209 | } 210 | 211 | public static DiceRoll getDiceRoll(String message) { 212 | while (true) { 213 | String s = terminal.queryString(message, false); 214 | if (s.matches("(\\d+d\\d+)")) { 215 | String[] a = s.split("d"); 216 | return new DiceRoll(Integer.parseInt(a[0]), Integer.parseInt(a[1])); 217 | } else { 218 | if (s.equalsIgnoreCase("cancel")) { 219 | return null; 220 | } 221 | } 222 | } 223 | } 224 | 225 | public static DiceRoll toDiceRoll(String s) { 226 | if (s.matches("(\\d+d\\d+)")) { 227 | String[] a = s.split("d"); 228 | return new DiceRoll(Integer.parseInt(a[0]), Integer.parseInt(a[1])); 229 | } else { 230 | return null; 231 | } 232 | } 233 | 234 | private static void dispCharacterList() { 235 | if (!characterList.isEmpty()) { 236 | terminal.println("Characters:"); 237 | for (PlayerCharacter c : characterList.values()) { 238 | terminal.println("- " + c.getName()); 239 | } 240 | } else { 241 | terminal.println("No characters available"); 242 | } 243 | } 244 | 245 | public static boolean checkCaster(PlayerCharacter pc) { 246 | if (pc.isSpellcaster()) { 247 | return true; 248 | } else { 249 | terminal.println(Message.MSG_NOT_CAST); 250 | return false; 251 | } 252 | } 253 | 254 | public static boolean isValidName(String name) { 255 | if (name.isEmpty() || name.matches("\\s+") || name.matches(".*[^a-zA-Z0-9)(\\s+].*")) { 256 | terminal.println("Not a valid name"); 257 | return false; 258 | } else { 259 | return true; 260 | } 261 | } 262 | 263 | /** 264 | * TEST CHARACTER 265 | ******************************************************************************************************/ 266 | private static void makeTestCharacter() { 267 | PlayerCharacter frodo; 268 | frodo = new PlayerCharacter("Frodo Baggins", "Halfling", "Paladin"); 269 | frodo.addNewItem(new Consumable("Rations", 5)); 270 | 271 | /*create some enchanted items*/ 272 | Weapon sting = new Weapon("Sting"); 273 | sting.addEffect(new ItemEffect(frodo.getStat(Ability.STR), 2)); 274 | sting.setDamage(new DiceRoll(1, 8)); 275 | frodo.addNewItem(sting); 276 | sting.equip(frodo); 277 | Armor mith = new Armor("Mithril Chainmail"); 278 | mith.addEffect(new ItemEffect(frodo.getStat(Ability.CON), 2)); 279 | mith.setArmorType(Armor.ArmorType.L_ARMOR); 280 | mith.setAC(14); 281 | frodo.addNewItem(mith); 282 | mith.equip(frodo); 283 | Equippable ring = new Equippable("Ring of Power"); 284 | ring.addEffect(new ItemEffect(frodo.getStat(Attribute.HP), -5)); 285 | frodo.addNewItem(ring); 286 | 287 | /*learn a spell*/ 288 | frodo.getSpellBook().learn(new Spell("Invisibility", Spell.CANTRIP)); 289 | frodo.getSpellBook().learn(new Spell("Blight", 3)); 290 | 291 | /*get spellslots*/ 292 | SpellSlot[] spellSlots = new SpellSlot[]{ 293 | new SpellSlot(0, 0), 294 | new SpellSlot(1, 4), 295 | new SpellSlot(2, 3), 296 | new SpellSlot(3, 2), 297 | new SpellSlot(4, 0), 298 | new SpellSlot(5, 0), 299 | new SpellSlot(6, 0), 300 | new SpellSlot(7, 0), 301 | new SpellSlot(8, 0), 302 | new SpellSlot(9, 0) 303 | }; 304 | frodo.setSpellSlots(spellSlots); 305 | frodo.initMagicStats(frodo.getAbilities().get(Ability.WIS)); 306 | frodo.setSpellcaster(true); 307 | 308 | /*Add currency*/ 309 | frodo.addCurrency(Inventory.indexGP, 10); 310 | frodo.addCurrency(Inventory.indexSP, 35); 311 | frodo.addCurrency(Inventory.indexCP, 4); 312 | 313 | characterList.put("frodo baggins", frodo); 314 | activeChar = characterList.get("frodo baggins"); 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /src/app/io/ReadWriteHandler.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.PlayerCharacter; 5 | import app.utils.Help; 6 | import app.utils.Message; 7 | 8 | import java.io.*; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | public class ReadWriteHandler { 14 | public static void checkDirs(){ 15 | if (!Files.exists(CharacterCommand.propertiesHandler.getDataDir())){ 16 | try { 17 | Files.createDirectories(CharacterCommand.propertiesHandler.getDataDir()); 18 | } catch (IOException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | if (!Files.exists(CharacterCommand.propertiesHandler.getExportDir())){ 23 | try { 24 | Files.createDirectories(CharacterCommand.propertiesHandler.getExportDir()); 25 | } catch (IOException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | 31 | /**IMPORT**************************************************************************************************************/ 32 | public void importCharacter(){ 33 | CharacterCommand.tokens.pop(); 34 | String characterName=null; 35 | if(!CharacterCommand.tokens.isEmpty()){ 36 | if (CharacterCommand.tokens.contains("--help")){ 37 | CharacterCommand.terminal.println(Help.IMPORT); 38 | } else if (CharacterCommand.tokens.contains("--all")){ 39 | importAll(true); 40 | } else { 41 | StringBuilder nameBuilder = new StringBuilder(); 42 | while (!CharacterCommand.tokens.isEmpty()) { 43 | nameBuilder.append(CharacterCommand.tokens.pop()); 44 | nameBuilder.append(" "); 45 | } 46 | characterName = nameBuilder.toString().trim(); 47 | } 48 | } else { 49 | CharacterCommand.terminal.println("manual import placeholder -- use command arguments for now"); 50 | } 51 | if(characterName!=null){ 52 | Path charPath = Paths.get(CharacterCommand.propertiesHandler.getDataDir() + "/" + characterName + ".data"); 53 | if (Files.exists(charPath)){ 54 | File charFile = charPath.toFile(); 55 | try{ 56 | ObjectInputStream inStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(charFile))); 57 | PlayerCharacter playerCharacter = (PlayerCharacter) inStream.readObject(); 58 | inStream.close(); 59 | if (!CharacterCommand.characterList.containsKey(playerCharacter.getName().toLowerCase())){ 60 | CharacterCommand.characterList.put(playerCharacter.getName().toLowerCase(), playerCharacter); 61 | CharacterCommand.terminal.println("Imported "+playerCharacter.getName()); 62 | } else { 63 | CharacterCommand.terminal.println(playerCharacter.getName() + " already imported"); 64 | } 65 | } catch (IOException | ClassNotFoundException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | } 71 | 72 | public void importAll(boolean verbose) { 73 | for (File file : CharacterCommand.propertiesHandler.getDataDir().toFile().listFiles()){ 74 | if (file.getName().endsWith(".data")){ 75 | try{ 76 | ObjectInputStream inStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); 77 | PlayerCharacter playerCharacter = (PlayerCharacter) inStream.readObject(); 78 | inStream.close(); 79 | if (!CharacterCommand.characterList.containsKey(playerCharacter.getName().toLowerCase())){ 80 | CharacterCommand.characterList.put(playerCharacter.getName().toLowerCase(), playerCharacter); 81 | } 82 | if (verbose){ 83 | CharacterCommand.terminal.println(playerCharacter.getName() + " already imported"); 84 | } 85 | } catch (IOException | ClassNotFoundException e) { 86 | e.printStackTrace(); 87 | } 88 | } 89 | } 90 | if (verbose){ 91 | CharacterCommand.terminal.println("All characters imported"); 92 | } 93 | } 94 | 95 | /**IMPORT**************************************************************************************************************/ 96 | public boolean export(){ 97 | CharacterCommand.tokens.pop(); 98 | PlayerCharacter pc=null; 99 | String characterName=null; 100 | if(!CharacterCommand.tokens.isEmpty()){ 101 | if(CharacterCommand.tokens.contains("--help")){ 102 | CharacterCommand.terminal.println(Help.EXPORT); 103 | return true; 104 | } else if (CharacterCommand.tokens.contains("--all")){ 105 | exportAll(); 106 | return true; 107 | } else { 108 | StringBuilder nameBuilder = new StringBuilder(); 109 | while (!CharacterCommand.tokens.isEmpty()) { 110 | nameBuilder.append(CharacterCommand.tokens.pop()); 111 | nameBuilder.append(" "); 112 | } 113 | characterName = nameBuilder.toString().trim(); 114 | pc = CharacterCommand.characterList.get(characterName.toLowerCase()); 115 | 116 | } 117 | } else { 118 | pc = CharacterCommand.getActiveChar(); 119 | } 120 | if(pc!=null && CharacterCommand.characterList.containsKey(pc.getName().toLowerCase())){ 121 | Path path = Paths.get(CharacterCommand.propertiesHandler.getExportDir()+"/" + pc.getName() + ".txt"); 122 | try{ 123 | BufferedWriter writer = new BufferedWriter(new FileWriter(path.toString())); 124 | writer.write(pc.toTextFile()); 125 | writer.close(); 126 | CharacterCommand.terminal.println("Exported "+pc.getName()); 127 | } catch (IOException e) { 128 | e.printStackTrace(); 129 | } 130 | } else { 131 | CharacterCommand.terminal.println(Message.ERROR_NO_CHAR); 132 | } 133 | return true; 134 | } 135 | 136 | private void exportAll() { 137 | try{ 138 | Path path; 139 | 140 | for (PlayerCharacter pc: CharacterCommand.characterList.values()){ 141 | path = Paths.get(CharacterCommand.propertiesHandler.getExportDir() + "/" + pc.getName() + ".txt"); 142 | BufferedWriter writer = new BufferedWriter(new FileWriter(path.toString())); 143 | writer.write(pc.toTextFile()); 144 | writer.close(); 145 | } 146 | CharacterCommand.terminal.println("All characters exported"); 147 | } catch (IOException e) { 148 | e.printStackTrace(); 149 | } 150 | } 151 | 152 | /**SAVE****************************************************************************************************************/ 153 | public void saveChar(boolean verbose) { 154 | PlayerCharacter pc=null; 155 | String characterName; 156 | CharacterCommand.tokens.pop(); 157 | if(!CharacterCommand.tokens.isEmpty()){ 158 | if(CharacterCommand.tokens.contains("--help")){ 159 | CharacterCommand.terminal.println(Help.EXPORT); 160 | } else if (CharacterCommand.tokens.contains("--all")){ 161 | saveAll(); 162 | } else { 163 | StringBuilder nameBuilder = new StringBuilder(); 164 | while (!CharacterCommand.tokens.isEmpty()) { 165 | nameBuilder.append(CharacterCommand.tokens.pop()); 166 | nameBuilder.append(" "); 167 | } 168 | characterName = nameBuilder.toString().trim(); 169 | pc = CharacterCommand.characterList.get(characterName.toLowerCase()); 170 | } 171 | }else{ 172 | pc = CharacterCommand.getActiveChar(); 173 | } 174 | if(pc!=null && CharacterCommand.characterList.containsKey(pc.getName().toLowerCase())){ 175 | try{ 176 | Path path = Paths.get(CharacterCommand.propertiesHandler.getDataDir() +"/" + pc.getName() + ".data"); 177 | ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path.toString()))); 178 | out.writeObject(pc); 179 | out.close(); 180 | if(verbose) { 181 | CharacterCommand.terminal.println("Saved " + pc.getName()); 182 | } 183 | } catch (IOException e) { 184 | e.printStackTrace(); 185 | } 186 | } 187 | } 188 | 189 | private static void saveAll(){ 190 | try{ 191 | Path path; 192 | for(PlayerCharacter pc: CharacterCommand.characterList.values()){ 193 | path = Paths.get(CharacterCommand.propertiesHandler.getDataDir() + "/" + pc.getName() + ".data"); 194 | ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path.toString()))); 195 | out.writeObject(pc); 196 | out.close(); 197 | } 198 | CharacterCommand.terminal.println("Saved all characters"); 199 | } catch (IOException e) { 200 | e.printStackTrace(); 201 | } 202 | } 203 | 204 | 205 | /**LOAD****************************************************************************************************************/ 206 | public void loadChar(){ 207 | String command = CharacterCommand.tokens.pop(); 208 | if (!CharacterCommand.tokens.isEmpty()){ 209 | loadChar(command); 210 | } else { 211 | String characterName = CharacterCommand.terminal.queryString("Enter name of character to load, 'cancel', or 'new': ",false); 212 | if (characterName.equalsIgnoreCase("new")) { 213 | PlayerCreator.createCharacter(); 214 | } else if (!characterName.equalsIgnoreCase("cancel")) { 215 | int matches = 0; 216 | PlayerCharacter character=null; 217 | for(PlayerCharacter pc:CharacterCommand.characterList.values()){ 218 | if(pc.getName().toLowerCase().startsWith(characterName)){ 219 | character = pc; 220 | matches++; 221 | } 222 | } 223 | if(matches==1){ 224 | CharacterCommand.setActiveChar(character); 225 | CharacterCommand.terminal.println(CharacterCommand.getActiveChar().getName() + " loaded"); 226 | return; 227 | } 228 | if (CharacterCommand.characterList.get(characterName.toLowerCase()) != null) { 229 | CharacterCommand.setActiveChar(CharacterCommand.characterList.get(characterName)); 230 | CharacterCommand.terminal.println(CharacterCommand.getActiveChar().getName() + " loaded"); 231 | } else { 232 | CharacterCommand.terminal.println("ERROR: Character not found"); 233 | } 234 | } 235 | } 236 | } 237 | 238 | private void loadChar(String command){ 239 | String characterName = ""; 240 | while (!CharacterCommand.tokens.isEmpty()){ 241 | characterName += CharacterCommand.tokens.pop()+" "; 242 | } 243 | characterName = characterName.trim().toLowerCase(); 244 | int matches = 0; 245 | PlayerCharacter character=null; 246 | for(PlayerCharacter pc:CharacterCommand.characterList.values()){ 247 | if(pc.getName().toLowerCase().startsWith(characterName)){ 248 | character = pc; 249 | matches++; 250 | } 251 | } 252 | if(matches==1){ 253 | CharacterCommand.setActiveChar(character); 254 | CharacterCommand.terminal.println(CharacterCommand.getActiveChar().getName() + " loaded"); 255 | return; 256 | } 257 | if (CharacterCommand.characterList.get(characterName) != null) { 258 | CharacterCommand.setActiveChar(CharacterCommand.characterList.get(characterName)); 259 | CharacterCommand.terminal.println(CharacterCommand.getActiveChar().getName() + " loaded"); 260 | } else { 261 | CharacterCommand.terminal.println("ERROR: Character not found"); 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /src/app/core/character/PlayerCharacter.java: -------------------------------------------------------------------------------- 1 | package app.core.character; 2 | import app.CharacterCommand; 3 | import app.core.magic.Spell; 4 | import app.core.magic.SpellBook; 5 | import app.core.magic.SpellSlot; 6 | import app.core.items.Item; 7 | 8 | import java.io.Serializable; 9 | import java.util.ArrayList; 10 | import java.util.LinkedHashMap; 11 | 12 | @SuppressWarnings("unused") 13 | public class PlayerCharacter implements Serializable{ 14 | private static final long serialVersionUID = CharacterCommand.VERSION; 15 | 16 | private String name; 17 | private String className; 18 | private String raceName; 19 | private String description; 20 | //private String notes; 21 | 22 | private LinkedHashMap abilities; 23 | private LinkedHashMap attributes; 24 | private LinkedHashMap skills; 25 | private LinkedHashMap allStats; 26 | private LinkedHashMap magicStats; 27 | 28 | private Inventory inventory; 29 | private SpellBook spellBook; 30 | private SpellSlot[] spellSlots; 31 | private Ability spellAbility; 32 | 33 | private boolean unPrepOnCast; 34 | private boolean spellcaster; 35 | private boolean armored; 36 | 37 | public PlayerCharacter(String name, String raceName, String className){ 38 | this.name=name; 39 | this.className = className; 40 | this.raceName = raceName; 41 | inventory = new Inventory(); 42 | spellBook = new SpellBook(); 43 | initAbilities(); 44 | initAttributes(); 45 | initAllStats(); 46 | initSkills(); 47 | initSpellSlots(); 48 | unPrepOnCast = false; 49 | spellcaster = false; 50 | armored = false; 51 | } 52 | 53 | private void initAbilities(){ 54 | abilities = new LinkedHashMap<>(); 55 | for(String s:Ability.ABILITY_NAMES){ 56 | abilities.put(s.toLowerCase(), new Ability(s,10)); 57 | } 58 | } 59 | 60 | private void initAttributes(){ 61 | attributes = new LinkedHashMap<>(); 62 | attributes.put("lvl", new Stat("Level", 1)); 63 | attributes.put("hp",new CounterStat("Hit Points",10)); 64 | attributes.put("nac",new Stat("Natural Armor", 10)); 65 | attributes.put("ac",new Attribute("Armor Class",attributes.get("nac").getBaseVal() + abilities.get(Ability.DEX).getMod())); 66 | attributes.put("pb",new Stat ("Proficiency Bonus", 2)); 67 | attributes.put("ini", new Stat("Initiative", abilities.get(Ability.DEX).getMod())); 68 | attributes.put("spd", new Stat("Speed",30)); 69 | attributes.put("ap", new CounterStat("Ability Points", 0)); 70 | attributes.put("hitdice", new CounterStat("Hit Dice", 1)); 71 | attributes.put("pper",new Stat ("Passive Perception",10 + abilities.get(Ability.WIS).getMod() )); 72 | } 73 | 74 | private void initAllStats(){ 75 | this.allStats = new LinkedHashMap<>(); 76 | for(String s:this.abilities.keySet()){ 77 | allStats.put(s, this.abilities.get(s)); 78 | } 79 | for(String s:this.attributes.keySet()){ 80 | allStats.put(s, this.attributes.get(s)); 81 | } 82 | } 83 | 84 | private void initSpellSlots(){ 85 | this.spellSlots = new SpellSlot[]{ 86 | new SpellSlot(0,0), 87 | new SpellSlot(1,0), 88 | new SpellSlot(2,0), 89 | new SpellSlot(3,0), 90 | new SpellSlot(4,0), 91 | new SpellSlot(5,0), 92 | new SpellSlot(6,0), 93 | new SpellSlot(7,0), 94 | new SpellSlot(8,0), 95 | new SpellSlot(9,0) 96 | }; 97 | } 98 | 99 | private void initSkills(){ 100 | skills = new LinkedHashMap<>(); 101 | skills.put("str saves",new Skill("STR Saves",this.abilities.get(Ability.STR),this)); 102 | skills.put("athletics",new Skill("Athletics",this.abilities.get(Ability.STR),this)); 103 | skills.put("dex saves",new Skill("DEX Saves",this.abilities.get(Ability.DEX),this)); 104 | skills.put("acrobatics",new Skill("Acrobatics",this.abilities.get(Ability.DEX),this)); 105 | skills.put("sleight of hand",new Skill("Sleight of Hand",this.abilities.get(Ability.DEX),this)); 106 | skills.put("stealth",new Skill("Stealth",this.abilities.get(Ability.DEX),this)); 107 | skills.put("con saves",new Skill("CON Saves",this.abilities.get(Ability.CON),this)); 108 | skills.put("int saves",new Skill("INT Saves",this.abilities.get(Ability.INT),this)); 109 | skills.put("arcana",new Skill("Arcana",this.abilities.get(Ability.INT),this)); 110 | skills.put("history",new Skill("History",this.abilities.get(Ability.INT),this)); 111 | skills.put("investigation",new Skill("Investigation",this.abilities.get(Ability.INT),this)); 112 | skills.put("nature",new Skill("Nature",this.abilities.get(Ability.INT),this)); 113 | skills.put("religion",new Skill("Religion",this.abilities.get(Ability.INT),this)); 114 | skills.put("wis saves",new Skill("WIS Saves",this.abilities.get(Ability.WIS),this)); 115 | skills.put("animal handling",new Skill("Animal Handling",this.abilities.get(Ability.WIS),this)); 116 | skills.put("insight",new Skill("Insight",this.abilities.get(Ability.WIS),this)); 117 | skills.put("medicine",new Skill("Medicine",this.abilities.get(Ability.WIS),this)); 118 | skills.put("perception",new Skill("Perception",this.abilities.get(Ability.WIS),this)); 119 | skills.put("survival",new Skill("Survival",this.abilities.get(Ability.WIS),this)); 120 | skills.put("cha saves",new Skill("CHA Saves",this.abilities.get(Ability.CHA),this)); 121 | skills.put("deception",new Skill("Deception",this.abilities.get(Ability.CHA),this)); 122 | skills.put("intimidation",new Skill("Intimidation",this.abilities.get(Ability.CHA),this)); 123 | skills.put("performance",new Skill("Performance",this.abilities.get(Ability.CHA),this)); 124 | skills.put("persuasion",new Skill("Persuasion",this.abilities.get(Ability.CHA),this)); 125 | } 126 | 127 | public void initMagicStats(Ability spellAbility){ 128 | this.spellAbility = spellAbility; 129 | magicStats = new LinkedHashMap<>(); 130 | magicStats.put("ssdc", new Stat("Spell Save DC", 8 + attributes.get(Attribute.PB).getTotal()+spellAbility.getMod())); 131 | magicStats.put("sam", new Stat("Spell Attack Mod",attributes.get(Attribute.PB).getTotal()+spellAbility.getMod())); 132 | allStats.put("ssdc", magicStats.get("ssdc")); 133 | allStats.put("sam", magicStats.get("sam")); 134 | } 135 | 136 | 137 | private void updateProficiency(){ 138 | double lvl = attributes.get("lvl").getTotal(); 139 | double pb = Math.floor(lvl/4)+2; 140 | this.attributes.get(Attribute.PB).setBaseVal(pb); 141 | updateSkills(); 142 | updateStats(); 143 | } 144 | 145 | private void updateSkills(){ 146 | for(Skill skill:skills.values()){ 147 | skill.update(this); 148 | } 149 | } 150 | 151 | public void updateStats(){ 152 | attributes.get("ini").setBaseVal(abilities.get(Ability.DEX).getMod()); 153 | attributes.get("pper").setBaseVal(10 + abilities.get(Ability.WIS).getMod()); 154 | attributes.get("hitdice").setBaseVal(attributes.get("lvl").getTotal()); 155 | if(spellcaster){ 156 | magicStats.get("ssdc").setBaseVal(8 + attributes.get(Attribute.PB).getTotal() + spellAbility.getMod()); 157 | magicStats.get("sam").setBaseVal(attributes.get(Attribute.PB).getTotal() + spellAbility.getMod()); 158 | } 159 | } 160 | 161 | public void heal(int amt){ 162 | CounterStat hp = (CounterStat)this.attributes.get(Attribute.HP); 163 | hp.countUp(amt); 164 | } 165 | public void hurt(int amt){ 166 | CounterStat hp = (CounterStat)this.attributes.get(Attribute.HP); 167 | hp.countDown(amt); 168 | } 169 | public void fullHeal(){ 170 | CounterStat hp = (CounterStat)this.attributes.get(Attribute.HP); 171 | hp.setCurrVal(hp.getMaxVal()); 172 | } 173 | public void fullHurt(){ 174 | CounterStat hp = (CounterStat)this.attributes.get(Attribute.HP); 175 | hp.setCurrVal(0); 176 | } 177 | 178 | public void levelUp(){ 179 | attributes.get("lvl").incrementBaseVal(); 180 | updateProficiency(); 181 | } 182 | public void levelUp(int lvl){ 183 | attributes.get("lvl").setBaseVal(lvl); 184 | updateProficiency(); 185 | } 186 | 187 | public void equip(Item i){ 188 | i.equip(this); 189 | } 190 | 191 | public void dequip(Item i){ 192 | i.dequip(this); 193 | } 194 | 195 | public Integer cast(Spell spell, int lvl){ 196 | if(lvl > spell.getSpellLevel() || spell.isCantrip() || lvl <= 0){ 197 | lvl = spell.getSpellLevel(); 198 | } 199 | if(spellSlots[lvl].getCurrVal() > 0 && !spell.isCantrip() ){ 200 | spellSlots[lvl].countDown(); 201 | if(unPrepOnCast){ 202 | spell.unprep(); 203 | } 204 | } else if (spell.isCantrip()){ 205 | return Spell.CANTRIP; 206 | } else { 207 | return -lvl; 208 | } 209 | return lvl; 210 | } 211 | 212 | public void addNewItem(Item item){ 213 | this.inventory.add(item); 214 | } 215 | 216 | public void addCurrency(int coin, int amt){ 217 | this.inventory.addCurrency(coin, amt); 218 | } 219 | 220 | public void addDropItem(Item i, int amount){ 221 | if (i != null){ 222 | int c = i.getCount()+amount; 223 | if (c>0){ 224 | i.setCount(c); 225 | } else { 226 | if(i.isEquippable() && i.isEquipped()){ 227 | i.dequip(this); 228 | } 229 | this.inventory.remove(i); 230 | } 231 | } 232 | } 233 | 234 | public void removeItem(Item i){ 235 | if(i.isEquippable() && i.isEquipped()){ 236 | i.dequip(this); 237 | } 238 | this.inventory.remove(i); 239 | } 240 | 241 | public String spellStatsToString(){ 242 | //String newLine = System.lineSeparator(); 243 | return String.format("Spell Save DC: %.0f Spell Atk Mod: %.0f", magicStats.get("ssdc").getTotal(), magicStats.get("sam").getTotal()); 244 | 245 | } 246 | 247 | public String spellSlotsToString(){ 248 | String newLine = System.lineSeparator(); 249 | String s="---- SPELL SLOTS -------------- "; 250 | for(SpellSlot spellSlot:spellSlots){ 251 | if(spellSlot.getMaxVal()>0 && spellSlot.getLevel()>0){ 252 | s += newLine + spellSlot; 253 | } 254 | } 255 | return s+newLine+"-------------------------------"; 256 | } 257 | 258 | public String skillsToString(){ 259 | String newLine = System.lineSeparator(); 260 | String s = "---- SKILLS --------------------"; 261 | for(Skill skill:skills.values()){ 262 | switch(skill.getName().toLowerCase()){ 263 | // case "str saves": 264 | case "dex saves": 265 | case "con saves": 266 | case "wis saves": 267 | case "int saves": 268 | case "cha saves": 269 | s+=newLine; 270 | break; 271 | } 272 | s += newLine+" - "+skill; 273 | } 274 | return s+newLine+"--------------------------------"; 275 | } 276 | 277 | @Override 278 | public String toString(){ 279 | String newLine = System.lineSeparator(); 280 | //String s=String.format("\033[1;33m%s -- Level %.0f %s\033[0m\n", name, level.getTotal(), className); 281 | //String s=String.format("%s -- Level %.0f %s %s"+newLine, name, attributes.get("lvl").getTotal(), raceName, className); 282 | 283 | String s = "---- CHARACTER -----------------"+newLine; 284 | s+=String.format(" %s -- Level %.0f %s %s"+newLine, name, attributes.get("lvl").getTotal(), raceName, className); 285 | s+=String.format(" | %s %s"+newLine+" | INI: %+.0f SPD: %.0f PB: %+.0f PER: %.0f"+newLine, 286 | attributes.get("hp"), 287 | attributes.get("ac"), 288 | attributes.get("ini").getTotal(), 289 | attributes.get("spd").getTotal(), 290 | attributes.get("pb").getTotal(), 291 | attributes.get("pper").getTotal() 292 | ); 293 | int i=0; 294 | s+=" | "; 295 | for(String key:abilities.keySet()){ 296 | s+=(abilities.get(key))+" "; 297 | if (i == 2){ 298 | s+=newLine+" | "; 299 | } 300 | i++; 301 | } 302 | if(attributes.get("ap").getTotal()>0){ 303 | s+=newLine+" | "+attributes.get("ap")+" "; 304 | } 305 | if(spellcaster){ 306 | s+="\n | "+spellStatsToString(); 307 | } 308 | return s+newLine+"--------------------------------"; 309 | } 310 | 311 | public String toTextFile(){ 312 | String newLine = System.lineSeparator(); 313 | String s = this+newLine+skillsToString()+newLine+inventory; 314 | if(!spellBook.isEmpty()&&spellcaster){ 315 | s+=newLine+spellBook; 316 | s+=newLine+spellSlotsToString(); 317 | } 318 | return s; 319 | } 320 | 321 | public String getName(){ 322 | return name; 323 | } 324 | 325 | public void setName(String name){ 326 | this.name = name; 327 | } 328 | 329 | public String getClassName(){ 330 | return className; 331 | } 332 | 333 | public void setClassName(String className){ 334 | this.className = className; 335 | } 336 | 337 | public Stat getLevel(){ 338 | return attributes.get("lvl"); 339 | } 340 | 341 | public boolean isSpellcaster(){ 342 | return spellcaster; 343 | } 344 | 345 | public void setSpellcaster(boolean spellcaster){ 346 | this.spellcaster = spellcaster; 347 | } 348 | 349 | public LinkedHashMap getAbilities(){ 350 | return abilities; 351 | } 352 | 353 | public Ability getAbility(String abilityName){ 354 | return abilities.get(abilityName.toUpperCase()); 355 | } 356 | 357 | public LinkedHashMap getAttributes(){ 358 | return attributes; 359 | } 360 | 361 | public Skill getSkill(String skillName){ 362 | return this.skills.get(skillName.toLowerCase()); 363 | } 364 | 365 | public Item getItem(String itemName){ 366 | return this.inventory.get(itemName.toLowerCase()); 367 | } 368 | 369 | public Item getCurrency(int coin){ 370 | return this.inventory.getCurrency(coin); 371 | } 372 | 373 | public Inventory getInventory(){ 374 | return this.inventory; 375 | } 376 | 377 | public ArrayList getCurrency(){ 378 | return this.inventory.getCurrency(); 379 | } 380 | 381 | public Spell getSpell(String spellName){ 382 | return this.spellBook.get(spellName.toLowerCase()); 383 | } 384 | 385 | public SpellBook getSpellBook(){ 386 | return spellBook; 387 | } 388 | 389 | public SpellSlot[] getSpellSlots(){ 390 | return spellSlots; 391 | } 392 | 393 | public void setSpellSlots(SpellSlot[] spellSlots){ 394 | this.spellSlots = spellSlots; 395 | } 396 | 397 | public void setSpellAbility(Ability spellAbility){ 398 | this.spellAbility = spellAbility; 399 | } 400 | 401 | public boolean isUnPrepOnCast(){ 402 | return unPrepOnCast; 403 | } 404 | 405 | public void setUnPrepOnCast(boolean unPrepOnCast){ 406 | this.unPrepOnCast = unPrepOnCast; 407 | } 408 | 409 | public Stat getStat(String statName){ 410 | return this.allStats.get(statName.toLowerCase()); 411 | } 412 | 413 | public LinkedHashMap getAllStats() { 414 | return allStats; 415 | } 416 | 417 | public LinkedHashMap getSkillSet() { 418 | return skills; 419 | } 420 | 421 | public boolean isArmored(){ 422 | return armored; 423 | } 424 | 425 | public void setArmored(boolean armored){ 426 | this.armored = armored; 427 | } 428 | } 429 | -------------------------------------------------------------------------------- /src/app/io/InventoryIO.java: -------------------------------------------------------------------------------- 1 | package app.io; 2 | 3 | import app.CharacterCommand; 4 | import app.core.character.Inventory; 5 | import app.core.character.PlayerCharacter; 6 | import app.core.character.Stat; 7 | import app.core.items.*; 8 | import app.utils.Help; 9 | import app.utils.Message; 10 | 11 | public class InventoryIO { 12 | public static void addDrop(PlayerCharacter pc) { 13 | Item item; 14 | String addDrop = CharacterCommand.tokens.pop(); 15 | if (!CharacterCommand.tokens.isEmpty()) { 16 | addDrop(pc, addDrop); 17 | } else { 18 | Integer itemCount; 19 | item = ItemIO.getItemByName(pc); 20 | if(item==null){ 21 | return; 22 | } 23 | itemCount = CharacterCommand.terminal.queryInteger("Amount: ", false); 24 | //if (item != null) { 25 | switch (item.getName().toLowerCase()) { 26 | case "pp": 27 | case "platinum": 28 | addDropCoin(pc, Inventory.indexPL, itemCount, false, addDrop); 29 | break; 30 | case "gp": 31 | case "gold": 32 | addDropCoin(pc, Inventory.indexGP, itemCount, false, addDrop); 33 | break; 34 | case "sp": 35 | case "silver": 36 | addDropCoin(pc, Inventory.indexSP, itemCount, false, addDrop); 37 | break; 38 | case "cp": 39 | case "copper": 40 | addDropCoin(pc, Inventory.indexCP, itemCount, false, addDrop); 41 | break; 42 | default: 43 | addDropItem(pc, item, itemCount, false, addDrop); 44 | break; 45 | } 46 | //} 47 | } 48 | } 49 | 50 | private static void addDrop(PlayerCharacter pc, String command) { 51 | Item item = null; 52 | StringBuilder nameBuilder = new StringBuilder(); 53 | Integer itemCount = null; 54 | boolean dropAll = false; 55 | boolean help = false; 56 | while (!CharacterCommand.tokens.isEmpty()) { 57 | switch (CharacterCommand.tokens.peek()) { 58 | case "-c": 59 | case "-count": 60 | CharacterCommand.tokens.pop(); 61 | if (CharacterCommand.tokens.isEmpty()) { 62 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": count"); 63 | } else { 64 | itemCount = CharacterCommand.getIntToken(); 65 | } 66 | break; 67 | case "--all": 68 | CharacterCommand.tokens.pop(); 69 | dropAll = true; 70 | break; 71 | case "--help": 72 | CharacterCommand.tokens.pop(); 73 | help = true; 74 | break; 75 | default: 76 | if (CharacterCommand.tokens.peek().startsWith("-")) { 77 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 78 | } else { 79 | nameBuilder.append(CharacterCommand.tokens.pop()); 80 | nameBuilder.append(" "); 81 | } 82 | break; 83 | } 84 | } 85 | 86 | /*DEFAULT VALUES****************/ 87 | if (itemCount == null) { 88 | itemCount = 1; 89 | } 90 | 91 | if (!help) { 92 | String itemName = nameBuilder.toString().trim(); 93 | switch (itemName.toLowerCase()) { 94 | case "pp": 95 | case "platinum": 96 | addDropCoin(pc, Inventory.indexPL, itemCount, dropAll, command); 97 | break; 98 | case "gp": 99 | case "gold": 100 | addDropCoin(pc, Inventory.indexGP, itemCount, dropAll, command); 101 | break; 102 | case "sp": 103 | case "silver": 104 | addDropCoin(pc, Inventory.indexSP, itemCount, dropAll, command); 105 | break; 106 | case "cp": 107 | case "copper": 108 | addDropCoin(pc, Inventory.indexCP, itemCount, dropAll, command); 109 | break; 110 | default: 111 | item = pc.getItem(itemName); 112 | break; 113 | } 114 | if (item != null) { 115 | addDropItem(pc, item, itemCount, dropAll, command); 116 | } else { 117 | CharacterCommand.terminal.println(Message.MSG_NO_ITEM); 118 | } 119 | } else { 120 | if (command.equals("add")) { 121 | CharacterCommand.terminal.println(Help.ADD); 122 | } 123 | if (command.equals("drop")) { 124 | CharacterCommand.terminal.println(Help.DROP); 125 | } 126 | } 127 | } 128 | 129 | public static void addDropCoin(PlayerCharacter pc, int coinType, Integer itemCount, boolean dropAll, String command) { 130 | String itemName = ""; 131 | switch (coinType) { 132 | case Inventory.indexPL: 133 | itemName = "Platinum"; 134 | break; 135 | case Inventory.indexGP: 136 | itemName = "Gold"; 137 | break; 138 | case Inventory.indexSP: 139 | itemName = "Silver"; 140 | break; 141 | case Inventory.indexCP: 142 | itemName = "Copper"; 143 | break; 144 | } 145 | if (command.equals("drop") && !dropAll) { 146 | itemCount = -itemCount; 147 | CharacterCommand.terminal.println(String.format("Dropped %dx %s", -itemCount, itemName)); 148 | } 149 | if (dropAll) { 150 | pc.getCurrency(coinType).setCount(0); 151 | CharacterCommand.terminal.println(String.format("Dropped all %s", itemName)); 152 | } else { 153 | pc.addCurrency(coinType, itemCount); 154 | if (command.equals("add")) { 155 | CharacterCommand.terminal.println(String.format("Added %dx %s", itemCount, itemName)); 156 | } 157 | } 158 | } 159 | 160 | public static void addDropItem(PlayerCharacter pc, Item item, Integer itemCount, boolean dropAll, String command) { 161 | if (command.equals("drop") && !dropAll) { 162 | itemCount = -itemCount; 163 | CharacterCommand.terminal.println(String.format("Dropped %dx \"%s\"", -itemCount, item.getName())); 164 | } 165 | if (dropAll) { 166 | pc.removeItem(item); 167 | CharacterCommand.terminal.println(String.format("Dropped all \"%s\"", item.getName())); 168 | } else { 169 | pc.addDropItem(item, itemCount); 170 | if (command.equals("add")) { 171 | CharacterCommand.terminal.println(String.format("Added %dx \"%s\"", itemCount, item.getName())); 172 | } 173 | } 174 | } 175 | 176 | public static void get(PlayerCharacter pc) { 177 | CharacterCommand.tokens.pop(); 178 | if (!CharacterCommand.tokens.isEmpty()) { 179 | getParser(pc); 180 | } else { 181 | ItemBuilder itemBuilder = new ItemBuilder(); 182 | ItemBuilderIO.buildItem(pc, itemBuilder); 183 | if(itemBuilder.itemType!=null) { 184 | getItem(pc, itemBuilder); 185 | } 186 | } 187 | } 188 | 189 | private static void getParser(PlayerCharacter pc) { 190 | StringBuilder nameBuilder = new StringBuilder(); 191 | ItemBuilder itemBuilder = new ItemBuilder(); 192 | 193 | while (!CharacterCommand.tokens.isEmpty()) { 194 | switch (CharacterCommand.tokens.peek()) { 195 | case "-c": 196 | case "--count": 197 | CharacterCommand.tokens.pop(); 198 | if (CharacterCommand.tokens.isEmpty()) { 199 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": count"); 200 | return; 201 | } 202 | itemBuilder.itemCount = CharacterCommand.getIntToken(); 203 | break; 204 | case "--armor": 205 | CharacterCommand.tokens.pop(); 206 | itemBuilder.itemType = Item.ItemType.ARMOR; 207 | break; 208 | case "--consumable": 209 | CharacterCommand.tokens.pop(); 210 | itemBuilder.itemType = Item.ItemType.CONSUMABLE; 211 | break; 212 | case "--equippable": 213 | CharacterCommand.tokens.pop(); 214 | itemBuilder.itemType = Item.ItemType.EQUIPPABLE; 215 | break; 216 | case "--item": 217 | CharacterCommand.tokens.pop(); 218 | itemBuilder.itemType = Item.ItemType.ITEM; 219 | break; 220 | case "--weapon": 221 | CharacterCommand.tokens.pop(); 222 | itemBuilder.itemType = Item.ItemType.WEAPON; 223 | break; 224 | case "-t": 225 | case "--type": 226 | CharacterCommand.tokens.pop(); 227 | if (CharacterCommand.tokens.isEmpty()) { 228 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": type"); 229 | return; 230 | } 231 | itemBuilder.itemType = Item.parseItemType(CharacterCommand.tokens.pop()); 232 | if (itemBuilder.itemType == null) { 233 | CharacterCommand.terminal.println(Message.ERROR_ITEM_TYPE); 234 | return; 235 | } 236 | break; 237 | case "-d": 238 | case "--damage": 239 | CharacterCommand.tokens.pop(); 240 | if (CharacterCommand.tokens.isEmpty()) { 241 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": damage"); 242 | return; 243 | } 244 | itemBuilder.damage = CharacterCommand.toDiceRoll(CharacterCommand.tokens.pop()); 245 | break; 246 | case "-e": 247 | case "--enchant": 248 | case "--effect": 249 | CharacterCommand.tokens.pop(); 250 | Stat target; 251 | if (!CharacterCommand.tokens.isEmpty()) { 252 | target = pc.getStat(CharacterCommand.tokens.pop()); 253 | } else { 254 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": effect target"); 255 | return; 256 | } 257 | if (target != null) { 258 | Integer bonus = CharacterCommand.getIntToken(); 259 | if (bonus != null) { 260 | itemBuilder.addEffect(target, bonus); 261 | } else { 262 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": effect bonus"); 263 | return; 264 | } 265 | } else { 266 | CharacterCommand.terminal.println("ERROR: Effect target not found"); 267 | return; 268 | } 269 | break; 270 | case "-ac": 271 | case "--armorclass": 272 | CharacterCommand.tokens.pop(); 273 | itemBuilder.armorClass = CharacterCommand.getIntToken(); 274 | break; 275 | case "-at": 276 | case "--armortype": 277 | CharacterCommand.tokens.pop(); 278 | if (CharacterCommand.tokens.isEmpty()) { 279 | CharacterCommand.terminal.println("ERROR: No armor type specified"); 280 | return; 281 | } 282 | itemBuilder.armorType = Armor.parseType(CharacterCommand.tokens.peek().toLowerCase()); 283 | if (itemBuilder.armorType == null) { 284 | CharacterCommand.terminal.println("ERROR: Not a valid armor type"); 285 | return; 286 | } 287 | break; 288 | case "--help": 289 | CharacterCommand.tokens.pop(); 290 | CharacterCommand.terminal.println(Help.GET); 291 | return; 292 | default: 293 | if (CharacterCommand.tokens.peek().startsWith("-")) { 294 | CharacterCommand.terminal.println("ERROR: Invalid flag '" + CharacterCommand.tokens.pop() + "'"); 295 | } else { 296 | nameBuilder.append(CharacterCommand.tokens.pop()); 297 | nameBuilder.append(" "); 298 | } 299 | break; 300 | } 301 | } 302 | itemBuilder.itemName = nameBuilder.toString().trim(); 303 | if (itemBuilder.itemName.isEmpty()) { 304 | CharacterCommand.terminal.println(Message.ERROR_NO_ARG + ": item_name"); 305 | return; 306 | } 307 | if (Inventory.isCurrency(itemBuilder.itemName)) { 308 | getCoins(pc, itemBuilder); 309 | return; 310 | } 311 | getItem(pc, itemBuilder); 312 | } 313 | 314 | public static void getItem(PlayerCharacter pc, ItemBuilder itemBuilder) { 315 | switch (itemBuilder.itemType) { 316 | case ITEM: 317 | Item item = itemBuilder.toItem(); 318 | pc.addNewItem(item); 319 | break; 320 | case CONSUMABLE: 321 | Consumable consumable = itemBuilder.toConsumable(); 322 | pc.addNewItem(consumable); 323 | break; 324 | case EQUIPPABLE: 325 | Equippable equippable = itemBuilder.toEquippable(); 326 | pc.addNewItem(equippable); 327 | break; 328 | case WEAPON: 329 | Weapon weapon = itemBuilder.toWeapon(); 330 | pc.addNewItem(weapon); 331 | break; 332 | case ARMOR: 333 | Armor armor = itemBuilder.toArmor(); 334 | pc.addNewItem(armor); 335 | break; 336 | default: 337 | return; 338 | } 339 | CharacterCommand.terminal.println(String.format("Got %dx %s", itemBuilder.itemCount, itemBuilder.itemName)); 340 | } 341 | 342 | public static void getCoins(PlayerCharacter pc, ItemBuilder itemBuilder) { 343 | switch (itemBuilder.itemName.toLowerCase()) { 344 | case "pp": 345 | case "platinum": 346 | InventoryIO.addDropCoin(pc, Inventory.indexPL, itemBuilder.itemCount, false, "add"); 347 | break; 348 | case "gp": 349 | case "gold": 350 | InventoryIO.addDropCoin(pc, Inventory.indexGP, itemBuilder.itemCount, false, "add"); 351 | break; 352 | case "sp": 353 | case "silver": 354 | InventoryIO.addDropCoin(pc, Inventory.indexSP, itemBuilder.itemCount, false, "add"); 355 | break; 356 | case "cp": 357 | case "copper": 358 | InventoryIO.addDropCoin(pc, Inventory.indexCP, itemBuilder.itemCount, false, "add"); 359 | break; 360 | default: 361 | break; 362 | } 363 | } 364 | } 365 | --------------------------------------------------------------------------------