@Override public void setPermanentStat(int abilityCode, int value) { setStat(abilityCode, value); if (CharStats.CODES.isBASE(abilityCode)) setStat( CharStats.CODES.toMAXBASE(abilityCode), value - CMProps.getIntVar(CMProps.Int.BASEMAXSTAT)); }
@Override public String getNonBaseStatsAsString() { final StringBuffer str = new StringBuffer(""); final CharStats.CODES C = CharStats.CODES.instance(); for (final int x : C.all()) { if ((!C.isBase(x)) && (x != CharStats.STAT_GENDER)) str.append(stats[x] + ";"); } return str.toString(); }
@Override public void setNonBaseStatsFromString(String str) { final List<String> V = CMParms.parseSemicolons(str, false); final CharStats.CODES C = CharStats.CODES.instance(); for (final int x : C.all()) { if ((!C.isBase(x)) && (x != CharStats.STAT_GENDER) && (V.size() > 0)) { final long val = CMath.s_long(V.remove(0)); if ((val > Short.MAX_VALUE) || (val < Short.MIN_VALUE)) Log.errOut( "Value out of range", "Value out of range: " + val + " for " + x + " from " + str); stats[x] = (short) val; } } }
@Override public void setAllValues(int def) { if ((def > Short.MAX_VALUE) || (def < Short.MIN_VALUE)) Log.errOut("Value out of range", new CMException("Value out of range: " + def + " for all")); for (final int i : CharStats.CODES.ALLCODES()) stats[i] = (short) def; unwearableBitmap = 0; }
@Override public void affectCharStats(MOB affectedMOB, CharStats affectableStats) { super.affectCharStats(affectedMOB, affectableStats); for (final int i : CharStats.CODES.SAVING_THROWS()) affectableStats.setStat( i, affectableStats.getStat(i) + (affectableStats.getClassLevel(this))); }
@Override public int getCode(String abilityName) { final String[] DESCS = CODES.DESCS(); for (final int i : CharStats.CODES.ALLCODES()) { if (DESCS[i].startsWith(abilityName)) return i; } return -1; }
@Override public String getStat(String abilityName) { final int dex = CMParms.indexOfIgnoreCase(getStatCodes(), abilityName); if (dex >= 0) return Integer.toString(getStat(dex)); final String[] DESCS = CODES.DESCS(); for (final int i : CharStats.CODES.ALLCODES()) { if (DESCS[i].startsWith(abilityName)) return Integer.toString(getStat(i)); } return null; }
@Override public void setRacialStat(final int abilityCode, final int racialMax) { if ((!CharStats.CODES.isBASE(abilityCode)) || (getStat(abilityCode) == VALUE_ALLSTATS_DEFAULT)) setPermanentStat(abilityCode, racialMax); else { final int baseMax = CMProps.getIntVar(CMProps.Int.BASEMAXSTAT); int currMax = getStat(CharStats.CODES.toMAXBASE(abilityCode)) + baseMax; if (currMax <= 0) currMax = 1; int curStat = getStat(abilityCode); if (curStat > currMax * 7) { final String errorMsg = "Detected mob with " + curStat + "/" + currMax + " " + CharStats.CODES.ABBR(abilityCode); @SuppressWarnings({"unchecked", "rawtypes"}) Set<String> errs = (Set) Resources.getResource("SYSTEM_DEFCHARSTATS_ERRORS"); if (errs == null) { errs = new TreeSet<String>(); Resources.submitResource("SYSTEM_DEFCHARSTATS_ERRORS", errs); } if (!errs.contains(errorMsg)) { errs.add(errorMsg); final StringBuilder str = new StringBuilder(errorMsg); // ByteArrayOutputStream stream=new ByteArrayOutputStream(); // new Exception().printStackTrace(new PrintStream(stream)); // str.append("\n\r"+new String(stream.toByteArray())); Log.errOut("DefCharStats", str.toString()); } curStat = currMax * 7; } final int pctOfMax = Math.round(((float) curStat / (float) currMax) * racialMax); final int stdMaxAdj = Math.round((((float) (currMax - VALUE_ALLSTATS_DEFAULT)) / (float) currMax) * racialMax); final int racialStat = pctOfMax + stdMaxAdj; setStat(abilityCode, ((racialStat < 1) && (racialMax > 0)) ? 1 : racialStat); setStat(CharStats.CODES.toMAXBASE(abilityCode), racialMax - baseMax); } }
@Override public void setStat(String code, String val) { final int dex = CMParms.indexOfIgnoreCase(getStatCodes(), code); if (dex >= 0) setStat(dex, CMath.s_parseIntExpression(val)); else for (final int i : CharStats.CODES.ALLCODES()) { if (CODES.DESC(i).startsWith(code)) { setStat(dex, CMath.s_parseIntExpression(val)); return; } } }
@Override public void affectCharStats(MOB affected, CharStats affectableStats) { if ((whom != null) && (song != null)) { final Hashtable<Integer, Integer> H = getSongBenefits(song); for (final Enumeration<Integer> e = H.keys(); e.hasMoreElements(); ) { final Integer I = e.nextElement(); final String[] chk = stuff[I.intValue()]; if ((chk != null) && (chk[1].startsWith("c"))) { int ticks = H.get(I).intValue(); if (ticks > 50) ticks = 50; if (ticks <= 0) ticks = 1; final int stat = CMath.s_int(chk[2]); if (CharStats.CODES.isBASE(stat)) if (ticks > 5) ticks = 5; affectableStats.setStat( stat, affectableStats.getStat(stat) + ticks + getXLEVELLevel(invoker())); } } } }
public String builtPrompt(MOB mob) { StringBuffer buf = new StringBuffer("\n\r"); String prompt = mob.playerStats().getPrompt(); String promptUp = null; int c = 0; while (c < prompt.length()) if ((prompt.charAt(c) == '%') && (c < (prompt.length() - 1))) { switch (prompt.charAt(++c)) { case '-': if (c < (prompt.length() - 2)) { if (promptUp == null) promptUp = prompt.toUpperCase(); String promptSub = promptUp.substring(c + 1); Wearable.CODES wcodes = Wearable.CODES.instance(); boolean isFound = false; for (long code : wcodes.all()) if (promptSub.startsWith(wcodes.nameup(code))) { c += 1 + wcodes.nameup(code).length(); Item I = mob.fetchFirstWornItem(code); if (I != null) buf.append(I.name()); isFound = true; break; } if (!isFound) { CharStats.CODES ccodes = CharStats.CODES.instance(); for (int code : ccodes.all()) if (promptSub.startsWith(ccodes.name(code))) { c += 1 + ccodes.name(code).length(); buf.append(mob.charStats().getStat(code)); isFound = true; break; } if (!isFound) for (int code : ccodes.all()) if (promptSub.startsWith("BASE " + ccodes.name(code))) { buf.append(mob.baseCharStats().getStat(code)); c += 6 + ccodes.name(code).length(); isFound = true; break; } } if (!isFound) { for (String s : mob.envStats().getStatCodes()) if (promptSub.startsWith(s)) { c += 1 + s.length(); buf.append(mob.envStats().getStat(s)); isFound = true; break; } if (!isFound) for (String s : mob.baseEnvStats().getStatCodes()) if (promptSub.startsWith("BASE " + s)) { c += 6 + s.length(); buf.append(mob.baseEnvStats().getStat(s)); isFound = true; break; } } if (!isFound) { for (String s : mob.curState().getStatCodes()) if (promptSub.startsWith(s)) { c += 1 + s.length(); buf.append(mob.curState().getStat(s)); isFound = true; break; } if (!isFound) for (String s : mob.maxState().getStatCodes()) if (promptSub.startsWith("MAX " + s)) { c += 5 + s.length(); buf.append(mob.maxState().getStat(s)); isFound = true; break; } if (!isFound) for (String s : mob.baseState().getStatCodes()) if (promptSub.startsWith("BASE " + s)) { c += 6 + s.length(); buf.append(mob.baseState().getStat(s)); isFound = true; break; } } } break; case 'a': { buf.append( CMLib.factions() .getRangePercent( CMLib.factions().AlignID(), mob.fetchFaction(CMLib.factions().AlignID())) + "%"); c++; break; } case 'A': { Faction.FactionRange FR = CMLib.factions() .getRange( CMLib.factions().AlignID(), mob.fetchFaction(CMLib.factions().AlignID())); buf.append( (FR != null) ? FR.name() : "" + mob.fetchFaction(CMLib.factions().AlignID())); c++; break; } case 'B': { buf.append("\n\r"); c++; break; } case 'c': { buf.append(mob.inventorySize()); c++; break; } case 'C': { buf.append(mob.maxItems()); c++; break; } case 'd': { MOB victim = mob.getVictim(); if ((mob.isInCombat()) && (victim != null)) buf.append("" + mob.rangeToTarget()); c++; break; } case 'e': { MOB victim = mob.getVictim(); if ((mob.isInCombat()) && (victim != null) && (CMLib.flags().canBeSeenBy(victim, mob))) buf.append(victim.displayName(mob)); c++; break; } case 'E': { MOB victim = mob.getVictim(); if ((mob.isInCombat()) && (victim != null) && (!victim.amDead()) && (CMLib.flags().canBeSeenBy(victim, mob))) buf.append(victim.healthText(mob) + "\n\r"); c++; break; } case 'g': { buf.append( (int) Math.round( Math.floor( CMLib.beanCounter().getTotalAbsoluteNativeValue(mob) / CMLib.beanCounter() .getLowestDenomination( CMLib.beanCounter().getCurrency(mob))))); c++; break; } case 'G': { buf.append( CMLib.beanCounter() .nameCurrencyShort( mob, CMLib.beanCounter().getTotalAbsoluteNativeValue(mob))); c++; break; } case 'h': { buf.append("^<Hp^>" + mob.curState().getHitPoints() + "^</Hp^>"); c++; break; } case 'H': { buf.append("^<MaxHp^>" + mob.maxState().getHitPoints() + "^</MaxHp^>"); c++; break; } case 'I': { if ((CMLib.flags().isCloaked(mob)) && (((mob.envStats().disposition() & EnvStats.IS_NOT_SEEN) != 0))) buf.append("Wizinvisible"); else if (CMLib.flags().isCloaked(mob)) buf.append("Cloaked"); else if (!CMLib.flags().isSeen(mob)) buf.append("Undetectable"); else if (CMLib.flags().isInvisible(mob) && CMLib.flags().isHidden(mob)) buf.append("Hidden/Invisible"); else if (CMLib.flags().isInvisible(mob)) buf.append("Invisible"); else if (CMLib.flags().isHidden(mob)) buf.append("Hidden"); c++; break; } case 'K': case 'k': { MOB tank = mob; if ((tank.getVictim() != null) && (tank.getVictim().getVictim() != null) && (tank.getVictim().getVictim() != mob)) tank = tank.getVictim().getVictim(); if (((c + 1) < prompt.length()) && (tank != null)) switch (prompt.charAt(c + 1)) { case 'h': { buf.append(tank.curState().getHitPoints()); c++; break; } case 'H': { buf.append(tank.maxState().getHitPoints()); c++; break; } case 'm': { buf.append(tank.curState().getMana()); c++; break; } case 'M': { buf.append(tank.maxState().getMana()); c++; break; } case 'v': { buf.append(tank.curState().getMovement()); c++; break; } case 'V': { buf.append(tank.maxState().getMovement()); c++; break; } case 'e': { buf.append(tank.displayName(mob)); c++; break; } case 'E': { if ((mob.isInCombat()) && (CMLib.flags().canBeSeenBy(tank, mob))) buf.append(tank.healthText(mob) + "\n\r"); c++; break; } } c++; break; } case 'm': { buf.append("^<Mana^>" + mob.curState().getMana() + "^</Mana^>"); c++; break; } case 'M': { buf.append("^<MaxMana^>" + mob.maxState().getMana() + "^</MaxMana^>"); c++; break; } case 'r': { if (mob.location() != null) buf.append(mob.location().displayText()); c++; break; } case 'R': { if ((mob.location() != null) && CMSecurity.isAllowed(mob, mob.location(), "SYSMSGS")) buf.append(mob.location().roomID()); c++; break; } case 'v': { buf.append("^<Move^>" + mob.curState().getMovement() + "^</Move^>"); c++; break; } case 'V': { buf.append("^<MaxMove^>" + mob.maxState().getMovement() + "^</MaxMove^>"); c++; break; } case 'w': { buf.append(mob.envStats().weight()); c++; break; } case 'W': { buf.append(mob.maxCarry()); c++; break; } case 'x': { buf.append(mob.getExperience()); c++; break; } case 'X': { if (mob.getExpNeededLevel() == Integer.MAX_VALUE) buf.append("N/A"); else buf.append(mob.getExpNeededLevel()); c++; break; } case 'z': { if (mob.location() != null) buf.append(mob.location().getArea().name()); c++; break; } case 't': { if (mob.location() != null) buf.append( CMStrings.capitalizeAndLower( TimeClock.TOD_DESC[mob.location().getArea().getTimeObj().getTODCode()] .toLowerCase())); c++; break; } case 'T': { if (mob.location() != null) buf.append(mob.location().getArea().getTimeObj().getTimeOfDay()); c++; break; } case '@': { if (mob.location() != null) buf.append( mob.location().getArea().getClimateObj().weatherDescription(mob.location())); c++; break; } default: { buf.append("%" + prompt.charAt(c)); c++; break; } } } else buf.append(prompt.charAt(c++)); return buf.toString(); }
@Override public String[] getStatCodes() { return CharStats.CODES.NAMES(); }
@Override public int getMaxStat(int abilityCode) { final int baseMax = CMProps.getIntVar(CMProps.Int.BASEMAXSTAT); return baseMax + getStat(CharStats.CODES.toMAXBASE(abilityCode)); }
/* Copyright 2001-2016 Bo Zimmerman Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ public class DefaultCharStats implements CharStats { @Override public String ID() { return "DefaultCharStats"; } @Override public String name() { return ID(); } @Override public CMObject newInstance() { try { final DefaultCharStats newStats = getClass().newInstance(); if (newStats.myRace == null) newStats.myRace = CMClass.getRace("StdRace"); return newStats; } catch (final Exception e) { return new DefaultCharStats(); } } @Override public void initializeClass() {} // competency characteristics protected short[] stats = new short[CharStats.CODES.instance().total()]; protected CharClass[] myClasses = null; protected Integer[] myLevels = null; protected Race myRace; protected String raceName = null; protected String genderName = null; protected String displayClassName = null; protected String displayClassLevel = null; protected short[] bodyAlterations = null; protected long unwearableBitmap = 0; protected int[] breathables = null; protected String arriveStr = null; protected String leaveStr = null; protected Map<String, Integer> profAdj = null; @SuppressWarnings("unchecked") private static final DoubleFilterer<Item>[] emptyFiltererArray = new DoubleFilterer[0]; protected DoubleFilterer<Item>[] proficiencies = emptyFiltererArray; public DefaultCharStats() { reset(); } @Override public void setAllBaseValues(int def) { if ((def > Short.MAX_VALUE) || (def < Short.MIN_VALUE)) Log.errOut("Value out of range", new CMException("Value out of range: " + def + " for all")); for (final int i : CharStats.CODES.BASECODES()) stats[i] = (short) def; } @Override public void setAllValues(int def) { if ((def > Short.MAX_VALUE) || (def < Short.MIN_VALUE)) Log.errOut("Value out of range", new CMException("Value out of range: " + def + " for all")); for (final int i : CharStats.CODES.ALLCODES()) stats[i] = (short) def; unwearableBitmap = 0; } @Override public void reset() { setAllBaseValues(VALUE_ALLSTATS_DEFAULT); stats[STAT_GENDER] = 'M'; // myClasses; // never null myLevels = null; // myRace; // never null raceName = null; genderName = null; displayClassName = null; displayClassLevel = null; bodyAlterations = null; unwearableBitmap = 0; breathables = null; arriveStr = null; leaveStr = null; profAdj = null; proficiencies = emptyFiltererArray; setMyRace(CMClass.getRace("StdRace")); setCurrentClass(CMClass.getCharClass("StdCharClass")); } @Override public void copyInto(CharStats intoStats) { if (intoStats instanceof DefaultCharStats) { ((DefaultCharStats) intoStats).arriveStr = arriveStr; ((DefaultCharStats) intoStats).leaveStr = leaveStr; ((DefaultCharStats) intoStats).breathables = breathables; ((DefaultCharStats) intoStats).proficiencies = proficiencies; if (myClasses == null) ((DefaultCharStats) intoStats).myClasses = null; else if ((((DefaultCharStats) intoStats).myClasses != null) && (((DefaultCharStats) intoStats).myClasses.length == myClasses.length)) { for (int i = 0; i < myClasses.length; i++) ((DefaultCharStats) intoStats).myClasses[i] = myClasses[i]; } else ((DefaultCharStats) intoStats).myClasses = myClasses.clone(); if (myLevels == null) ((DefaultCharStats) intoStats).myLevels = null; else if ((((DefaultCharStats) intoStats).myLevels != null) && (((DefaultCharStats) intoStats).myLevels.length == myLevels.length)) { for (int i = 0; i < myLevels.length; i++) ((DefaultCharStats) intoStats).myLevels[i] = myLevels[i]; } else ((DefaultCharStats) intoStats).myLevels = myLevels.clone(); if (myRace != null) ((DefaultCharStats) intoStats).myRace = myRace; ((DefaultCharStats) intoStats).raceName = raceName; ((DefaultCharStats) intoStats).genderName = genderName; ((DefaultCharStats) intoStats).displayClassName = displayClassName; ((DefaultCharStats) intoStats).displayClassLevel = displayClassLevel; if (profAdj == null) ((DefaultCharStats) intoStats).profAdj = null; else ((DefaultCharStats) intoStats).profAdj = new TreeMap<String, Integer>(profAdj); if (bodyAlterations == null) ((DefaultCharStats) intoStats).bodyAlterations = null; else if ((((DefaultCharStats) intoStats).bodyAlterations != null) && (((DefaultCharStats) intoStats).bodyAlterations.length == bodyAlterations.length)) { for (int i = 0; i < bodyAlterations.length; i++) ((DefaultCharStats) intoStats).bodyAlterations[i] = bodyAlterations[i]; } else ((DefaultCharStats) intoStats).bodyAlterations = bodyAlterations.clone(); for (int i = 0; i < stats.length; i++) ((DefaultCharStats) intoStats).stats[i] = stats[i]; ((DefaultCharStats) intoStats).unwearableBitmap = unwearableBitmap; } else { intoStats.setMyClasses(getMyClassesStr()); intoStats.setMyLevels(getMyLevelsStr()); intoStats.setMyRace(getMyRace()); intoStats.setRaceName(raceName); intoStats.setRaceName(raceName); intoStats.setGenderName(genderName); intoStats.setArriveLeaveStr(arriveStr, leaveStr); intoStats.setDisplayClassName(displayClassName); intoStats.setDisplayClassLevel(displayClassLevel); intoStats.setBodyPartsFromStringAfterRace(getBodyPartsAsString()); intoStats.setWearableRestrictionsBitmap(unwearableBitmap); intoStats.setBreathables(breathables); intoStats.setItemProficiencies(proficiencies); } } @Override public void setMyClasses(String classes) { int x = classes.indexOf(';'); final ArrayList<CharClass> classV = new ArrayList<CharClass>(); CharClass C = null; while (x >= 0) { final String theClass = classes.substring(0, x).trim(); classes = classes.substring(x + 1); if (theClass.length() > 0) { C = CMClass.getCharClass(theClass); if (C == null) C = CMClass.getCharClass("StdCharClass"); classV.add(C); } x = classes.indexOf(';'); } if (classes.trim().length() > 0) { C = CMClass.getCharClass(classes.trim()); if (C == null) C = CMClass.getCharClass("StdCharClass"); classV.add(C); } myClasses = classV.toArray(new CharClass[0]); } @Override public void setMyLevels(String levels) { if ((levels.length() == 0) && (myClasses != null) && (myClasses.length > 0)) levels = "0"; int x = levels.indexOf(';'); final ArrayList<Integer> levelV = new ArrayList<Integer>(); while (x >= 0) { final String theLevel = levels.substring(0, x).trim(); levels = levels.substring(x + 1); if (theLevel.length() > 0) levelV.add(Integer.valueOf(CMath.s_int(theLevel))); x = levels.indexOf(';'); } if (levels.trim().length() > 0) levelV.add(Integer.valueOf(CMath.s_int(levels))); myLevels = levelV.toArray(new Integer[0]); } @Override public String getMyClassesStr() { if (myClasses == null) return "StdCharClass"; String classStr = ""; for (final CharClass myClasse : myClasses) classStr += ";" + myClasse.ID(); if (classStr.length() > 0) classStr = classStr.substring(1); return classStr; } @Override public String getMyLevelsStr() { if (myLevels == null) return ""; String levelStr = ""; for (final Integer myLevel : myLevels) levelStr += ";" + myLevel.intValue(); if (levelStr.length() > 0) levelStr = levelStr.substring(1); return levelStr; } @Override public String getArriveStr() { if (arriveStr == null) return myRace.arriveStr(); return arriveStr; } @Override public String getLeaveStr() { if (leaveStr == null) return myRace.leaveStr(); return leaveStr; } @Override public void setArriveLeaveStr(String arriveStr, String leaveStr) { this.arriveStr = arriveStr; this.leaveStr = leaveStr; } @Override public long getWearableRestrictionsBitmap() { return unwearableBitmap | this.getMyRace().forbiddenWornBits(); } @Override public void setWearableRestrictionsBitmap(long bitmap) { unwearableBitmap = bitmap; } @Override public int numClasses() { if (myClasses == null) return 0; return myClasses.length; } @Override public int combinedSubLevels() { if ((myClasses == null) || (myLevels == null) || (myClasses.length < 2)) return 0; int combined = 0; for (int i = 0; i < myLevels.length - 1; i++) combined += myLevels[i].intValue(); return combined; } public int combinedLevels() { if ((myClasses == null) || (myLevels == null)) return 0; int combined = 0; for (int i = 0; i < myLevels.length - 1; i++) combined += myLevels[i].intValue(); return combined; } @Override public void setDisplayClassName(String newName) { displayClassName = newName; } @Override public String displayClassName() { if (displayClassName != null) return displayClassName; return getCurrentClass().name(getCurrentClassLevel()); } @Override public void setDisplayClassLevel(String newLevel) { displayClassLevel = newLevel; } @Override public String displayClassLevel(MOB mob, boolean shortForm) { if (displayClassLevel != null) { if (shortForm) return displayClassName() + " " + displayClassLevel; return "level " + displayClassLevel + " " + displayClassName; } if (mob == null) return ""; final int classLevel = getClassLevel(getCurrentClass()); String levelStr = null; if (classLevel >= mob.phyStats().level()) levelStr = "" + mob.phyStats().level(); else levelStr = classLevel + "/" + mob.phyStats().level(); if (shortForm) return displayClassName() + " " + levelStr; return "level " + levelStr + " " + displayClassName(); } @Override public String displayClassLevelOnly(MOB mob) { if (mob == null) return ""; if (displayClassLevel != null) return displayClassLevel; final int classLevel = getClassLevel(getCurrentClass()); String levelStr = null; if (classLevel >= mob.phyStats().level()) levelStr = "" + mob.phyStats().level(); else levelStr = classLevel + "/" + mob.phyStats().level(); return levelStr; } @Override public String getNonBaseStatsAsString() { final StringBuffer str = new StringBuffer(""); final CharStats.CODES C = CharStats.CODES.instance(); for (final int x : C.all()) { if ((!C.isBase(x)) && (x != CharStats.STAT_GENDER)) str.append(stats[x] + ";"); } return str.toString(); } @Override public void setNonBaseStatsFromString(String str) { final List<String> V = CMParms.parseSemicolons(str, false); final CharStats.CODES C = CharStats.CODES.instance(); for (final int x : C.all()) { if ((!C.isBase(x)) && (x != CharStats.STAT_GENDER) && (V.size() > 0)) { final long val = CMath.s_long(V.remove(0)); if ((val > Short.MAX_VALUE) || (val < Short.MIN_VALUE)) Log.errOut( "Value out of range", "Value out of range: " + val + " for " + x + " from " + str); stats[x] = (short) val; } } } @Override public void setRaceName(String newRaceName) { raceName = newRaceName; } @Override public String raceName() { if (raceName != null) return raceName; if (myRace != null) return myRace.name(); return "MOB"; } @Override public CharClass getMyClass(int i) { if ((myClasses == null) || (i < 0) || (i >= myClasses.length)) return CMClass.getCharClass("StdCharClass"); return myClasses[i]; } @Override public int getClassLevel(String aClass) { if (myClasses == null) return -1; for (int i = 0; i < myClasses.length; i++) { if ((myClasses[i] != null) && (myClasses[i].ID().equals(aClass)) && (i < myLevels.length)) return myLevels[i].intValue(); } return -1; } @Override public int getClassLevel(CharClass aClass) { if ((myClasses == null) || (aClass == null)) return -1; for (int i = 0; i < myClasses.length; i++) { if ((myClasses[i] != null) && (myClasses[i].ID().equals(aClass.ID())) && (i < myLevels.length)) return myLevels[i].intValue(); } return -1; } @Override public void setClassLevel(CharClass aClass, int level) { if (aClass == null) return; if (myClasses == null) { myClasses = new CharClass[1]; myLevels = new Integer[1]; myClasses[0] = aClass; myLevels[0] = Integer.valueOf(level); } else { if ((level < 0) && (myClasses.length > 1)) { final CharClass[] oldClasses = myClasses; final Integer[] oldLevels = myLevels; final CharClass[] myNewClasses = new CharClass[oldClasses.length - 1]; final Integer[] myNewLevels = new Integer[oldClasses.length - 1]; for (int c = 0; c < myNewClasses.length; c++) { myNewClasses[c] = oldClasses[c]; if (c < oldLevels.length) myNewLevels[c] = oldLevels[c]; else myNewLevels[c] = Integer.valueOf(0); } myClasses = myNewClasses; myLevels = myNewLevels; } else if (getClassLevel(aClass) < 0) setCurrentClass(aClass); for (int i = 0; i < numClasses(); i++) { final CharClass C = getMyClass(i); if ((C == aClass) && (myLevels[i].intValue() != level)) { myLevels[i] = Integer.valueOf(level); break; } } } } @Override public boolean isLevelCapped(CharClass C) { if ((C == null) || (C.getLevelCap() < 0) || (C.getLevelCap() == Integer.MAX_VALUE)) return false; return getClassLevel(C) >= C.getLevelCap(); } @Override public void setCurrentClassLevel(int level) { final CharClass currentClass = getCurrentClass(); if (currentClass != null) setClassLevel(currentClass, level); } @Override public void setCurrentClass(CharClass aClass) { if (aClass == null) return; if (((myClasses == null) || (myLevels == null)) || ((numClasses() == 1) && (myClasses[0].ID().equals("StdCharClass")))) { myClasses = new CharClass[1]; myLevels = new Integer[1]; myClasses[0] = aClass; myLevels[0] = Integer.valueOf(0); return; } final int level = getClassLevel(aClass); if (level < 0) { final CharClass[] oldClasses = myClasses; final Integer[] oldLevels = myLevels; final CharClass[] myNewClasses = new CharClass[oldClasses.length + 1]; final Integer[] myNewLevels = new Integer[oldClasses.length + 1]; for (int c = 0; c < oldClasses.length; c++) { myNewClasses[c] = oldClasses[c]; myNewLevels[c] = oldLevels[c]; } myNewClasses[oldClasses.length] = aClass; myNewLevels[oldClasses.length] = Integer.valueOf(0); myClasses = myNewClasses; myLevels = myNewLevels; } else { if (myClasses[myClasses.length - 1] == aClass) return; final Integer oldI = Integer.valueOf(level); boolean go = false; final CharClass[] myNewClasses = myClasses.clone(); final Integer[] myNewLevels = myLevels.clone(); for (int i = 0; i < myNewClasses.length - 1; i++) { final CharClass C = getMyClass(i); if ((C == aClass) || (go)) { go = true; myNewClasses[i] = myNewClasses[i + 1]; myNewLevels[i] = myNewLevels[i + 1]; } } myNewClasses[myNewClasses.length - 1] = aClass; myNewLevels[myNewClasses.length - 1] = oldI; myClasses = myNewClasses; myLevels = myNewLevels; } } @Override public CharClass getCurrentClass() { return myClasses[myClasses.length - 1]; } @Override public Collection<CharClass> getCharClasses() { return Arrays.asList(myClasses); } @Override public int getCurrentClassLevel() { if (myLevels == null) return -1; return myLevels[myLevels.length - 1].intValue(); } @Override public Race getMyRace() { return myRace; } @Override public void setMyRace(Race newVal) { if (newVal != null) myRace = newVal; } @Override public int[] getBreathables() { return (breathables != null) ? breathables : myRace.getBreathables(); } @Override public void setBreathables(int[] newArray) { breathables = newArray; } @Override public int getBodyPart(int racialPartNumber) { int num = getMyRace().bodyMask()[racialPartNumber]; if ((num < 0) || (bodyAlterations == null)) return num; num += bodyAlterations[racialPartNumber]; if (num < 0) return 0; return num; } @Override public String getBodyPartsAsString() { final StringBuffer str = new StringBuffer(""); for (int i = 0; i < getMyRace().bodyMask().length; i++) str.append(getBodyPart(i) + ";"); return str.toString(); } @Override public void setBodyPartsFromStringAfterRace(String str) { final List<String> V = CMParms.parseSemicolons(str, true); bodyAlterations = null; for (int i = 0; i < getMyRace().bodyMask().length; i++) { if (V.size() <= i) break; final int val = CMath.s_int(V.get(i)); final int num = getMyRace().bodyMask()[i]; if (num != val) alterBodypart(i, val - num); } } @Override public int getBodypartAlteration(int racialPartNumber) { if (bodyAlterations == null) return 0; return bodyAlterations[racialPartNumber]; } @Override public void alterBodypart(int racialPartNumber, int deviation) { if (bodyAlterations == null) bodyAlterations = new short[Race.BODY_PARTS]; bodyAlterations[racialPartNumber] += deviation; } @Override public int ageCategory() { final int age = getStat(STAT_AGE); int cat = Race.AGE_INFANT; final int[] chart = getMyRace().getAgingChart(); if (age < chart[1]) return cat; while ((cat <= Race.AGE_ANCIENT) && (age >= chart[cat])) cat++; return cat - 1; } @Override public String ageName() { final int cat = ageCategory(); if (cat < Race.AGE_ANCIENT) return Race.AGE_DESCS[cat]; int age = getStat(STAT_AGE); final int[] chart = getMyRace().getAgingChart(); final int diff = chart[Race.AGE_ANCIENT] - chart[Race.AGE_VENERABLE]; age = age - chart[Race.AGE_ANCIENT]; final int num = (diff > 0) ? (int) Math.abs(Math.floor(CMath.div(age, diff))) : 0; if (num <= 0) return Race.AGE_DESCS[cat]; return Race.AGE_DESCS[cat] + " " + CMath.convertToRoman(num); } @Override public int getSave(int which) { switch (which) { case STAT_SAVE_PARALYSIS: return getStat(STAT_SAVE_PARALYSIS) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_STRENGTH), 2.0)); case STAT_SAVE_FIRE: return getStat(STAT_SAVE_FIRE) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_DEXTERITY), 2.0)); case STAT_SAVE_COLD: return getStat(STAT_SAVE_COLD) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_DEXTERITY), 2.0)); case STAT_SAVE_WATER: return getStat(STAT_SAVE_WATER) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_DEXTERITY), 2.0)); case STAT_SAVE_GAS: return getStat(STAT_SAVE_GAS) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_STRENGTH), 2.0)); case STAT_SAVE_MIND: return getStat(STAT_SAVE_MIND) + (int) Math.round( CMath.div( getStat(STAT_WISDOM) + getStat(STAT_INTELLIGENCE) + getStat(STAT_CHARISMA), 3.0)); case STAT_SAVE_GENERAL: return getStat(STAT_SAVE_GENERAL) + getStat(STAT_CONSTITUTION); case STAT_SAVE_JUSTICE: return getStat(STAT_SAVE_JUSTICE) + getStat(STAT_CHARISMA); case STAT_SAVE_ACID: return getStat(STAT_SAVE_ACID) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_DEXTERITY), 2.0)); case STAT_SAVE_ELECTRIC: return getStat(STAT_SAVE_ELECTRIC) + (int) Math.round(CMath.div(getStat(STAT_CONSTITUTION) + getStat(STAT_DEXTERITY), 2.0)); case STAT_SAVE_POISON: return getStat(STAT_SAVE_POISON) + getStat(STAT_CONSTITUTION); case STAT_SAVE_UNDEAD: return getStat(STAT_SAVE_UNDEAD) + getStat(STAT_WISDOM) + getStat(STAT_FAITH); case STAT_SAVE_DISEASE: return getStat(STAT_SAVE_DISEASE) + getStat(STAT_CONSTITUTION); case STAT_SAVE_MAGIC: return getStat(STAT_SAVE_MAGIC) + getStat(STAT_INTELLIGENCE); case STAT_SAVE_TRAPS: return getStat(STAT_SAVE_TRAPS) + getStat(STAT_DEXTERITY); case STAT_SAVE_OVERLOOKING: return getStat(STAT_SAVE_OVERLOOKING); case STAT_SAVE_DETECTION: return getStat(STAT_SAVE_DETECTION); case STAT_FAITH: return getStat(STAT_FAITH); case STAT_SAVE_BLUNT: return getStat(STAT_SAVE_BLUNT); case STAT_SAVE_PIERCE: return getStat(STAT_SAVE_PIERCE); case STAT_SAVE_SLASH: return getStat(STAT_SAVE_SLASH); case STAT_SAVE_SPELLS: return getStat(STAT_SAVE_SPELLS); case STAT_SAVE_PRAYERS: return getStat(STAT_SAVE_PRAYERS); case STAT_SAVE_SONGS: return getStat(STAT_SAVE_SONGS); case STAT_SAVE_CHANTS: return getStat(STAT_SAVE_CHANTS); } return getStat(which); } // create a new one of these @Override public CMObject copyOf() { final DefaultCharStats newOne = new DefaultCharStats(); if (myClasses != null) newOne.myClasses = myClasses.clone(); if (myRace != null) newOne.myRace = myRace; if (myLevels != null) newOne.myLevels = myLevels.clone(); if (bodyAlterations != null) newOne.bodyAlterations = bodyAlterations.clone(); if (profAdj != null) newOne.profAdj = new TreeMap<String, Integer>(profAdj); newOne.stats = stats.clone(); return newOne; } @Override public int getAbilityAdjustment(String ableID) { final Map<String, Integer> prof = this.profAdj; if (prof == null) return 0; final Integer value = prof.get(ableID); if (value == null) return 0; return value.intValue(); } @Override public void adjustAbilityAdjustment(String ableID, int newValue) { Map<String, Integer> prof = this.profAdj; if (prof == null) { prof = new TreeMap<String, Integer>(); this.profAdj = prof; } prof.put(ableID, Integer.valueOf(newValue)); } @Override public void setGenderName(String gname) { genderName = gname; } @Override public String genderName() { if (genderName != null) return genderName; switch (getStat(STAT_GENDER)) { case 'M': return CMLib.lang().L("male"); case 'F': return CMLib.lang().L("female"); default: return CMLib.lang().L("neuter"); } } @Override public String himher() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("him"); case 'F': return CMLib.lang().L("her"); default: return CMLib.lang().L("it"); } } @Override public String hisher() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("his"); case 'F': return CMLib.lang().L("her"); default: return CMLib.lang().L("its"); } } @Override public String heshe() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("he"); case 'F': return CMLib.lang().L("she"); default: return CMLib.lang().L("it"); } } @Override public String sirmadam() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("sir"); case 'F': return CMLib.lang().L("madam"); default: return CMLib.lang().L("sir"); } } @Override public String SirMadam() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("Sir"); case 'F': return CMLib.lang().L("Madam"); default: return CMLib.lang().L("Sir"); } } @Override public String HeShe() { final char c = ((genderName != null) && (genderName.length() > 0)) ? Character.toUpperCase(genderName.charAt(0)) : (char) getStat(STAT_GENDER); switch (c) { case 'M': return CMLib.lang().L("He"); case 'F': return CMLib.lang().L("She"); default: return CMLib.lang().L("It"); } } @Override public int getStat(int abilityCode) { if (abilityCode < stats.length) return stats[abilityCode]; return 0; } @Override public void setPermanentStat(int abilityCode, int value) { setStat(abilityCode, value); if (CharStats.CODES.isBASE(abilityCode)) setStat( CharStats.CODES.toMAXBASE(abilityCode), value - CMProps.getIntVar(CMProps.Int.BASEMAXSTAT)); } @Override public int getMaxStat(int abilityCode) { final int baseMax = CMProps.getIntVar(CMProps.Int.BASEMAXSTAT); return baseMax + getStat(CharStats.CODES.toMAXBASE(abilityCode)); } @Override public int getRacialStat(MOB mob, int statNum) { final CharStats copyStats = (CharStats) copyOf(); getMyRace().affectCharStats(mob, copyStats); for (int c = 0; c < numClasses(); c++) getMyClass(c).affectCharStats(mob, copyStats); return copyStats.getStat(statNum); } @Override public void setRacialStat(final int abilityCode, final int racialMax) { if ((!CharStats.CODES.isBASE(abilityCode)) || (getStat(abilityCode) == VALUE_ALLSTATS_DEFAULT)) setPermanentStat(abilityCode, racialMax); else { final int baseMax = CMProps.getIntVar(CMProps.Int.BASEMAXSTAT); int currMax = getStat(CharStats.CODES.toMAXBASE(abilityCode)) + baseMax; if (currMax <= 0) currMax = 1; int curStat = getStat(abilityCode); if (curStat > currMax * 7) { final String errorMsg = "Detected mob with " + curStat + "/" + currMax + " " + CharStats.CODES.ABBR(abilityCode); @SuppressWarnings({"unchecked", "rawtypes"}) Set<String> errs = (Set) Resources.getResource("SYSTEM_DEFCHARSTATS_ERRORS"); if (errs == null) { errs = new TreeSet<String>(); Resources.submitResource("SYSTEM_DEFCHARSTATS_ERRORS", errs); } if (!errs.contains(errorMsg)) { errs.add(errorMsg); final StringBuilder str = new StringBuilder(errorMsg); // ByteArrayOutputStream stream=new ByteArrayOutputStream(); // new Exception().printStackTrace(new PrintStream(stream)); // str.append("\n\r"+new String(stream.toByteArray())); Log.errOut("DefCharStats", str.toString()); } curStat = currMax * 7; } final int pctOfMax = Math.round(((float) curStat / (float) currMax) * racialMax); final int stdMaxAdj = Math.round((((float) (currMax - VALUE_ALLSTATS_DEFAULT)) / (float) currMax) * racialMax); final int racialStat = pctOfMax + stdMaxAdj; setStat(abilityCode, ((racialStat < 1) && (racialMax > 0)) ? 1 : racialStat); setStat(CharStats.CODES.toMAXBASE(abilityCode), racialMax - baseMax); } } @Override public void setStat(int abilityCode, int value) { if (abilityCode < stats.length) stats[abilityCode] = (short) value; } @Override public int getCode(String abilityName) { final String[] DESCS = CODES.DESCS(); for (final int i : CharStats.CODES.ALLCODES()) { if (DESCS[i].startsWith(abilityName)) return i; } return -1; } @Override public int compareTo(CMObject o) { return CMClass.classID(this).compareToIgnoreCase(CMClass.classID(o)); } @Override public int getSaveStatIndex() { return getStatCodes().length; } @Override public String getStat(String abilityName) { final int dex = CMParms.indexOfIgnoreCase(getStatCodes(), abilityName); if (dex >= 0) return Integer.toString(getStat(dex)); final String[] DESCS = CODES.DESCS(); for (final int i : CharStats.CODES.ALLCODES()) { if (DESCS[i].startsWith(abilityName)) return Integer.toString(getStat(i)); } return null; } @Override public String[] getStatCodes() { return CharStats.CODES.NAMES(); } @Override public boolean isStat(String code) { return CMParms.containsIgnoreCase(getStatCodes(), code); } @Override public void setStat(String code, String val) { final int dex = CMParms.indexOfIgnoreCase(getStatCodes(), code); if (dex >= 0) setStat(dex, CMath.s_parseIntExpression(val)); else for (final int i : CharStats.CODES.ALLCODES()) { if (CODES.DESC(i).startsWith(code)) { setStat(dex, CMath.s_parseIntExpression(val)); return; } } } @Override public DoubleFilterer<Item>[] getItemProficiencies() { return proficiencies; } @Override public void setItemProficiencies(DoubleFilterer<Item>[] newArray) { this.proficiencies = newArray; } @Override public void addItemProficiency(final String zapperMask) { final DoubleFilterer<Item>[] newerArray = Arrays.copyOf(this.proficiencies, this.proficiencies.length + 1); newerArray[newerArray.length - 1] = new DoubleFilterer<Item>() { final MaskingLibrary.CompiledZMask mask = CMLib.masking().getPreCompiledMask(zapperMask); @Override public DoubleFilterer.Result getFilterResult(Item obj) { return CMLib.masking().maskCheck(mask, obj, true) ? DoubleFilterer.Result.ALLOWED : DoubleFilterer.Result.NOTAPPLICABLE; } }; this.proficiencies = newerArray; } @Override public void addItemDeficiency(final String zapperMask) { final DoubleFilterer<Item>[] newerArray = Arrays.copyOf(this.proficiencies, this.proficiencies.length + 1); newerArray[newerArray.length - 1] = new DoubleFilterer<Item>() { final MaskingLibrary.CompiledZMask mask = CMLib.masking().getPreCompiledMask(zapperMask); @Override public DoubleFilterer.Result getFilterResult(Item obj) { return CMLib.masking().maskCheck(mask, obj, true) ? DoubleFilterer.Result.REJECTED : DoubleFilterer.Result.NOTAPPLICABLE; } }; this.proficiencies = newerArray; } }