/* * Initiative - A role playing utility to track turns * Copyright (C) 2002 Devon D Jones * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * PlayerCharacterOutput.java */ package gmgen.plugin; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.text.DecimalFormat; import java.util.Collection; import java.util.Collections; import java.util.StringTokenizer; import org.apache.commons.lang3.math.Fraction; import pcgen.base.lang.StringUtil; import pcgen.cdom.content.CNAbility; import pcgen.cdom.enumeration.Nature; import pcgen.cdom.util.CControl; import pcgen.cdom.util.ControlUtilities; import pcgen.core.AbilityCategory; import pcgen.core.Deity; import pcgen.core.Domain; import pcgen.core.Equipment; import pcgen.core.Globals; import pcgen.core.PCAlignment; import pcgen.core.PCCheck; import pcgen.core.PCClass; import pcgen.core.PCStat; import pcgen.core.PlayerCharacter; import pcgen.core.SettingsHandler; import pcgen.core.analysis.QualifiedName; import pcgen.core.display.CharacterDisplay; import pcgen.core.display.VisionDisplay; import pcgen.io.ExportHandler; import pcgen.io.exporttoken.EqToken; import pcgen.io.exporttoken.MovementToken; import pcgen.util.Delta; import pcgen.util.enumeration.AttackType; /* * TODO This needs to be merged with pcgen.core.display.CharacterDisplay */ public class PlayerCharacterOutput { private PlayerCharacter pc; private CharacterDisplay display; public PlayerCharacterOutput(PlayerCharacter pc) { this.pc = pc; this.display = pc == null ? null : pc.getDisplay(); } public String getAC() { return Integer.toString(display.calcACOfType("Total")); } public String getACFlatFooted() { return Integer.toString(display.calcACOfType("Flatfooted")); } public String getACTouch() { return Integer.toString(display.calcACOfType("Touch")); } public String getAlignmentLong() { PCAlignment pcAlignment = display.getPCAlignment(); return pcAlignment == null ? "" : pcAlignment.getDisplayName(); } public String getAlignmentShort() { PCAlignment pcAlignment = display.getPCAlignment(); return pcAlignment == null ? "" : pcAlignment.getKeyName(); } public String getBAB() { return Integer.toString(pc.baseAttackBonus()); } /** * TODO Much of this code is repeated in CRToken, Race, XMLCombatant and PlayerCharacterOutput * * @return An output version of the CR */ public String getCR() { Integer calcCR = display.calcCR(); float cr = calcCR == null ? -1 : calcCR; String retString = ""; String crAsString = Float.toString(cr); String decimalPlaceValue = crAsString.substring(crAsString.length() - 2); // If the CR is a fractional CR then we convert to a 1/x format if (cr > 0 && cr < 1) { Fraction fraction = Fraction.getFraction(cr);// new Fraction(CR); int denominator = fraction.getDenominator(); int numerator = fraction.getNumerator(); retString = numerator + "/" + denominator; } else if (cr >= 1 || cr == 0) { int newCr = -99; if (decimalPlaceValue.equals(".0")) { newCr = (int) cr; } if (newCr > -99) { retString = retString + newCr; } else { retString = retString + cr; } } return retString; } public String getClasses() { StringBuilder sb = new StringBuilder(); for (PCClass mClass : display.getClassSet()) { sb.append(mClass.getDisplayName()) .append(display.getLevel(mClass)).append(" "); } return sb.toString(); } /** * Retrieve the type of race the character is. */ public String getRaceType() { return display.getRaceType(); } public String getDeity() { Deity deity = display.getDeity(); if (deity != null) { return deity.getOutputName(); } return null; } public String getDomainName(Domain domain) { return domain.getDisplayName(); } public String getEquipmentList() { StringBuilder sb = new StringBuilder(); boolean firstLine = true; for (Equipment eq : pc.getEquipmentListInOutputOrder()) { if (!firstLine) { sb.append(", "); } firstLine = false; DecimalFormat formater = new DecimalFormat(); formater.setMaximumFractionDigits(1); formater.setMinimumFractionDigits(0); sb.append(formater.format(eq.getQty())).append(" ") .append(eq.getName()); } return sb.toString(); } public String getExportToken(String token) { try { StringWriter retWriter = new StringWriter(); BufferedWriter bufWriter = new BufferedWriter(retWriter); ExportHandler export = new ExportHandler(new File("")); export.replaceTokenSkipMath(pc, token, bufWriter); retWriter.flush(); try { bufWriter.flush(); } catch (IOException e) { // TODO - Handle Exception } return retWriter.toString(); } catch (Exception e) { System.out.println("Failure fetching token: " + token); return ""; } } public String getFeatList() { StringBuilder sb = new StringBuilder(); boolean firstLine = true; for (CNAbility cna : pc.getCNAbilities(AbilityCategory.FEAT, Nature.NORMAL)) { if (!firstLine) { sb.append(", "); } firstLine = false; sb.append(QualifiedName.qualifiedName(pc, Collections.singletonList(cna))); } return sb.toString(); } public String getGender() { return display.getGenderObject().toString(); } public String getHitDice() { return getExportToken("HITDICE"); } public String getHitPoints() { return Integer.toString(pc.hitPoints()); } public String getInitMiscMod() { String initiativeVar = ControlUtilities .getControlToken(Globals.getContext(), CControl.INITIATIVEMISC); if (initiativeVar == null) { PCStat dex = Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCStat.class, "DEX"); int statMod = pc.getStatModFor(dex); return "+" + (display.processOldInitiativeMod() - statMod); } return Delta.toString(((Number) pc.getGlobal(initiativeVar)).intValue()); } public String getInitStatMod() { String initiativeVar = ControlUtilities .getControlToken(Globals.getContext(), CControl.INITIATIVESTAT); if (initiativeVar == null) { PCStat dex = Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCStat.class, "DEX"); return "+" + pc.getStatModFor(dex); } return Delta .toString(((Number) pc.getGlobal(initiativeVar)).intValue()); } public String getInitTotal() { String initiativeVar = ControlUtilities .getControlToken(Globals.getContext(), CControl.INITIATIVE); if (initiativeVar == null) { return "+" + display.processOldInitiativeMod(); } return Delta .toString(((Number) pc.getGlobal(initiativeVar)).intValue()); } public String getMeleeTotal() { int tohitBonus = (int) pc.getTotalBonusTo("TOHIT", "TOHIT") + (int) pc.getTotalBonusTo("TOHIT", "TYPE.MELEE") + (int) pc.getTotalBonusTo("COMBAT", "TOHIT") + (int) pc.getTotalBonusTo("COMBAT", "TOHIT.MELEE"); return pc.getAttackString(AttackType.MELEE, tohitBonus); } public String getName() { return display.getName(); } public String getRaceName() { return display.getRace().getDisplayName(); } public String getRangedTotal() { int tohitBonus = (int) pc.getTotalBonusTo("TOHIT", "TOHIT") + (int) pc.getTotalBonusTo("TOHIT", "TYPE.RANGED") + (int) pc.getTotalBonusTo("COMBAT", "TOHIT") + (int) pc.getTotalBonusTo("COMBAT", "TOHIT.RANGED"); return pc.getAttackString(AttackType.MELEE, tohitBonus); } public String getRegion() { return display.getRegionString(); } public String getSaveFort() { return "+" + pc.getTotalCheck(Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCCheck.class, "FORT")); } public String getSaveRef() { return "+" + pc.getTotalCheck(Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCCheck.class, "REF")); } public String getSaveWill() { return "+" + pc.getTotalCheck(Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCCheck.class, "WILL")); } public String getSize() { return display.getSize(); } public String getSpecialAbilities() { return StringUtil.join(pc.getSpecialAbilityTimesList(), ", "); } public String getSpeed() { return MovementToken.getMovementToken(display); } public String getStat(PCStat stat) { return Integer.toString(pc.getTotalStatFor(stat)); } public String getStatMod(PCStat stat) { int returnValue; returnValue = pc.getStatModFor(stat); return (returnValue < 0) ? Integer.toString(returnValue) : "+" + returnValue; } public String getVision() { return VisionDisplay.getVision(display); } public String getWeaponToken(int weaponNo, String Token) { return getExportToken("WEAPON." + weaponNo + "." + Token); } public String getWeaponCritMult(int weaponNo) { return getWeaponToken(weaponNo, "MULT"); } public String getWeaponCritRange(int weaponNo) { return getWeaponToken(weaponNo, "CRIT"); } public String getWeaponDamage(int weaponNo) { return getWeaponToken(weaponNo, "DAMAGE"); } public String getWeaponHand(Equipment eq) { String location = eq.getLocation().getString(); final int start = location.indexOf('(') + 1; // move past the paren if (start > 0) { int end = location.indexOf(')', start); if (end > 0) { location = location.substring(start, end); } } return location; } public String getWeaponName(Equipment eq) { return eq.getOutputName() + eq.getAppliedName(); } public String getWeaponRange(Equipment eq) { return EqToken.getRange(pc, eq).toString() + Globals.getGameModeUnitSet().getDistanceUnit(); } public String getWeaponSize(Equipment eq) { return eq.getSize(); } public String getWeaponSpecialProperties(Equipment eq) { return eq.getSpecialProperties(pc); } public String getWeaponToHit(int weaponNo) { return getWeaponToken(weaponNo, "TOTALHIT"); } public String getWeaponType(Equipment eq) { String types = getWeaponType(eq, true); if (eq.isDouble()) { types += ('/' + getWeaponType(eq, false)); } return types; } private String getWeaponType(Equipment eq, boolean primary) { StringBuilder sb = new StringBuilder(); StringTokenizer aTok = new StringTokenizer(SettingsHandler.getGame().getWeaponTypes(), "|", false); while (aTok.countTokens() >= 2) { final String aType = aTok.nextToken(); final String abbrev = aTok.nextToken(); if (eq.isType(aType, true)) { sb.append(abbrev); } } return sb.toString(); } public String getUnarmedAttack() { return getExportToken("WEAPONH.TOTALHIT"); } public String getUnarmedDamage() { return getExportToken("WEAPONH.DAMAGE"); } public String getUnarmedCritRange() { return getExportToken("WEAPONH.CRIT"); } public String getUnarmedCritMult() { return getExportToken("WEAPONH.MULT"); } public Collection<PCStat> getUnmodifiableStatList() { return display.getStatSet(); } }