package plugin.jepcommands; import org.nfunk.jep.ParseException; import pcgen.core.GameMode; import pcgen.core.PlayerCharacter; import pcgen.core.SettingsHandler; import pcgen.core.VariableProcessor; import pcgen.util.PCGenCommand; import pcgen.util.PJEP; import java.util.Stack; /** * JEP command for class level (cl) * * eg. classlevel("Fighter") * eg. classlevel("Fighter", "APPLIEDAS=NONEPIC") * eg. classlevel("APPLIEDAS=NONEPIC") [in CLASS LST file only] * eg. classlevel() [in CLASS LST file only] */ public class ClassLevelCommand extends PCGenCommand { @Override public boolean checkNumberOfParameters(int arg0) { return arg0 >= 0 && arg0 <= 2; } /** * Constructor */ public ClassLevelCommand() { numberOfParameters = -1; } /** * Gets the name of the function handled by this class. * @return The name of the function. */ @Override public String getFunctionName() { return "CLASSLEVEL"; } @Override public boolean updateVariables(final PJEP jep) { boolean updated = false; if (jep.removeVariable("CL") != null) { updated = true; } String src = variableSource; if ((src == null) || !src.startsWith("CLASS:")) { return updated; } src = src.substring(6); PlayerCharacter pc = null; if (parent instanceof VariableProcessor) { pc = ((VariableProcessor) parent).getPc(); } else if (parent instanceof PlayerCharacter) { pc = (PlayerCharacter) parent; } if (pc == null) { return updated; } final Number result = new Double(pc.getClassLevelString(src, false)); jep.addVariable("CL", result.doubleValue()); return true; } /** * Runs classlevel on the inStack. The parameter is popped * off the {@code inStack}, and the variable's value is * pushed back to the top of {@code inStack}. * @param inStack the jep stack * @throws ParseException */ @SuppressWarnings("unchecked") //Uses JEP, which doesn't use generics @Override public void run(final Stack inStack) throws ParseException { // check the stack checkStack(inStack); // get the parameter from the stack int paramCount = curNumberOfParameters; String applied = null; String className = null; if (paramCount > 2) { throw new ParseException("Invalid number of parameters"); } if (paramCount >= 2) { String p2 = inStack.pop().toString(); if (p2.startsWith("APPLIEDAS=")) { applied = p2.substring(10); } } if (paramCount >= 1) { String p1 = inStack.pop().toString(); if (p1.startsWith("APPLIEDAS=")) { if (applied != null) { throw new ParseException( "Formula had two APPLIEDAS= entries"); } applied = p1.substring(10); } else { //Should be a class name className = p1; } } /* * If there was no parameter showing the class, and this is used in a * CLASS file, then use the class name */ if (className == null) { String src = variableSource; if (src.startsWith("CLASS:")) { className = src.substring(6); } } if (className == null) { throw new ParseException("Unable to determine class name"); } PlayerCharacter pc = getPC(); String cl = className; if (applied != null) { if ("NONEPIC".equalsIgnoreCase(applied)) { GameMode mode = SettingsHandler.getGame(); //Add 1 since game mode is inclusive, but BEFORELEVEL is not! int limit = mode.getMaxNonEpicLevel() + 1; if (limit == Integer.MAX_VALUE) { throw new ParseException("Game Mode has no EPIC limit"); } cl += ";BEFORELEVEL=" + limit; } else { throw new ParseException("Did not understand APPLIEDAS=" + applied); } } Double result = new Double(pc.getClassLevelString(cl, false)); inStack.push(result); } private PlayerCharacter getPC() throws ParseException { PlayerCharacter pc = null; if (parent instanceof VariableProcessor) { pc = ((VariableProcessor) parent).getPc(); } else if (parent instanceof PlayerCharacter) { pc = (PlayerCharacter) parent; } if (pc == null) { throw new ParseException("Invalid parent (no PC): " + parent.getClass().getName()); } return pc; } }