package com.planet_ink.coffee_mud.Commands; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.Abilities.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.*; import com.planet_ink.coffee_mud.Behaviors.interfaces.*; import com.planet_ink.coffee_mud.CharClasses.interfaces.*; import com.planet_ink.coffee_mud.Commands.interfaces.*; import com.planet_ink.coffee_mud.Common.interfaces.*; import com.planet_ink.coffee_mud.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Libraries.interfaces.*; import com.planet_ink.coffee_mud.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import java.util.*; /* * <p>Portions Copyright (c) 2003 Jeremy Vyska</p> * <p>Portions Copyright (c) 2004-2019 Bo Zimmerman</p> 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 Deviations extends StdCommand { public Deviations() { } private final String[] access = I(new String[] { "DEVIATIONS" }); @Override public String[] getAccessWords() { return access; } @Override public boolean canBeOrdered() { return true; } protected String mobHeader(final Faction useFaction) { final StringBuffer str=new StringBuffer(); str.append("\n\r"); str.append(CMStrings.padRight(L("Name"),20)+" "); str.append(CMStrings.padRight(L("Lvl"),4)+" "); str.append(CMStrings.padRight(L("Att"),5)+" "); str.append(CMStrings.padRight(L("Dmg"),5)+" "); str.append(CMStrings.padRight(L("Armor"),5)+" "); str.append(CMStrings.padRight(L("Speed"),5)+" "); str.append(CMStrings.padRight(L("Rejuv"),5)+" "); if(useFaction!=null) str.append(CMStrings.padRight(useFaction.name(),7)+" "); str.append(CMStrings.padRight(L("Money"),5)+" "); str.append(CMStrings.padRight(L("Worn"),5)); str.append("\n\r"); return str.toString(); } protected String itemHeader() { final StringBuffer str=new StringBuffer(); str.append("\n\r"); str.append(CMStrings.padRight(L("Name"),20)+" "); str.append(CMStrings.padRight(L("Type"),10)+" "); str.append(CMStrings.padRight(L("Lvl"),3)+"--"); str.append(CMStrings.padRight(L("Pwr"),4)+" "); str.append(CMStrings.padRight(L("Att"),5)+" "); str.append(CMStrings.padRight(L("Dmg"),5)+" "); str.append(CMStrings.padRight(L("Armor"),5)+" "); str.append(CMStrings.padRight(L("Value"),5)+" "); str.append(CMStrings.padRight(L("Rejuv"),5)+" "); str.append(CMStrings.padRight(L("Wght."),4)); str.append("\n\r"); return str.toString(); } public boolean alreadyDone(final Environmental E, final List<Environmental> itemsDone) { for(int i=0;i<itemsDone.size();i++) { if(itemsDone.get(i).sameAs(E)) return true; } return false; } private void delAllEffects(final Item I) { for(final Enumeration<Ability> a=I.effects();a.hasMoreElements();) { final Ability A=a.nextElement(); if((A!=null) &&(!A.isSavable())) { A.unInvoke(); I.delEffect(A); } } } private void fillCheckDeviations(final Room R, final String type, final List<Environmental> check) { if(type.equalsIgnoreCase("mobs")||type.equalsIgnoreCase("both")) { for(int m=0;m<R.numInhabitants();m++) { final MOB M=R.fetchInhabitant(m); if((M!=null)&&(M.isSavable())&&(!alreadyDone(M,check))) check.add(M); } } if(type.equalsIgnoreCase("items")||type.equalsIgnoreCase("both")) { for(int i=0;i<R.numItems();i++) { final Item I=R.getItem(i); if((I!=null) &&((I instanceof Armor)||(I instanceof Weapon)) &&(!alreadyDone(I,check))) { final Item checkI=(Item)I.copyOf(); CMLib.threads().deleteAllTicks(checkI); delAllEffects(checkI); checkI.setContainer(null); checkI.setOwner(null); checkI.recoverPhyStats(); if(!alreadyDone(checkI,check)) check.add(checkI); else checkI.destroy(); } } for(int m=0;m<R.numInhabitants();m++) { final MOB M=R.fetchInhabitant(m); if(M!=null) { for(int i=0;i<M.numItems();i++) { final Item I=M.getItem(i); if((I!=null) &&((I instanceof Armor)||(I instanceof Weapon)) &&(!alreadyDone(I,check))) { final Item checkI=(Item)I.copyOf(); CMLib.threads().deleteAllTicks(checkI); delAllEffects(checkI); checkI.setContainer(null); checkI.setOwner(null); checkI.recoverPhyStats(); if(!alreadyDone(checkI,check)) check.add(checkI); else checkI.destroy(); } } final ShopKeeper SK=CMLib.coffeeShops().getShopKeeper(M); if(SK!=null) { for(final Iterator<Environmental> i=SK.getShop().getStoreInventory();i.hasNext();) { final Environmental E2=i.next(); if(E2 instanceof Item) { final Item I=(Item)E2; if(((I instanceof Armor)||(I instanceof Weapon)) &&(!alreadyDone(I,check))) { final Item checkI=(Item)I.copyOf(); CMLib.threads().deleteAllTicks(checkI); delAllEffects(checkI); checkI.setContainer(null); checkI.setOwner(null); checkI.recoverPhyStats(); if(!alreadyDone(checkI,check)) check.add(checkI); else checkI.destroy(); } } } } } } } } protected String getDeviation(final int val, final Map<String, String> vals, final String key) { if(!vals.containsKey(key)) return " - "; final int val2=CMath.s_int(vals.get(key)); return getDeviation(val,val2); } protected String getDeviation(final double val, final double val2) { if(val==val2) return "0%"; final double oval=val2-val; final int pval=(int)Math.round(CMath.div((oval<0)?(oval*-1):oval,val2==0?1:val2)*100.0); if(oval>0) return "-"+pval+"%"; return "+"+pval+"%"; } public StringBuffer deviations(final MOB mob, final String rest) { final List<String> V=CMParms.parse(rest); if((V.size()==0) ||((!V.get(0).equalsIgnoreCase("mobs")) &&(!V.get(0).equalsIgnoreCase("items")) &&(!V.get(0).equalsIgnoreCase("both")))) return new StringBuffer("You must specify whether you want deviations on MOBS, ITEMS, or BOTH."); final String type=V.get(0).toLowerCase(); if(V.size()==1) return new StringBuffer("You must also specify a mob or item name, or the word room, or the word area."); final Room mobR=mob.location(); Faction useFaction=null; for(final Enumeration<Faction> e=CMLib.factions().factions();e.hasMoreElements();) { final Faction F=e.nextElement(); if(F.showInSpecialReported()) useFaction=F; } final String where=V.get(1).toLowerCase(); final Environmental E=mobR.fetchFromMOBRoomFavorsItems(mob,null,where,Wearable.FILTER_ANY); final List<Environmental> check=new ArrayList<Environmental>(); if(where.equalsIgnoreCase("room")) fillCheckDeviations(mobR,type,check); else if(where.equalsIgnoreCase("area")) { for(final Enumeration<Room> r=mobR.getArea().getFilledCompleteMap();r.hasMoreElements();) { final Room R=r.nextElement(); fillCheckDeviations(R,type,check); } } else if(where.equalsIgnoreCase("world")) { for(final Enumeration<Room> r=CMLib.map().roomsFilled();r.hasMoreElements();) { final Room R=r.nextElement(); fillCheckDeviations(R,type,check); } } else if(E==null) return new StringBuffer("'"+where+"' is an unknown item or mob name."); else if(type.equals("items") &&(!(E instanceof Weapon)) &&(!(E instanceof Armor))) return new StringBuffer("'"+where+"' is not a weapon or armor item."); else if(type.equals("mobs") &&(!(E instanceof MOB))) return new StringBuffer("'"+where+"' is not a MOB."); else if((!(E instanceof Weapon)) &&(!(E instanceof Armor)) &&(!(E instanceof MOB))) return new StringBuffer("'"+where+"' is not a MOB, or Weapon, or Item."); else if(E instanceof Item) check.add((Item)E.copyOf()); else check.add(E); final StringBuffer str=new StringBuffer(""); str.append(L("Deviations Report:\n\r")); final StringBuffer itemResults = new StringBuffer(); final StringBuffer mobResults = new StringBuffer(); for(int c=0;c<check.size();c++) { if(check.get(c) instanceof Item) { final Item I=(Item)check.get(c); Weapon W=null; final int maxRange; if(I instanceof Weapon) { W=(Weapon)I; maxRange=W.getRanges()[1]; } else maxRange=I.maxRange(); final Map<String,String> vals=CMLib.itemBuilder().timsItemAdjustments( I,I.phyStats().level(),I.material(), I.rawLogicalAnd()?2:1, (W==null)?0:W.weaponClassification(), maxRange, I.rawProperLocationBitmap()); itemResults.append(CMStrings.padRight(I.name(),20)+" "); itemResults.append(CMStrings.padRight(I.ID(),10)+" "); itemResults.append(CMStrings.padRight(""+I.phyStats().level(),4)+" "); itemResults.append(CMStrings.padRight(""+CMLib.itemBuilder().timsLevelCalculator(I),4)+" "); itemResults.append(CMStrings.padRight(""+getDeviation( I.basePhyStats().attackAdjustment(), vals,"ATTACK"),5)+" "); itemResults.append(CMStrings.padRight(""+getDeviation( I.basePhyStats().damage(), vals,"DAMAGE"),5)+" "); itemResults.append(CMStrings.padRight(""+getDeviation( I.basePhyStats().armor(), vals,"ARMOR"),5)+" "); itemResults.append(CMStrings.padRight(""+getDeviation( I.baseGoldValue(), vals,"VALUE"),5)+" "); itemResults.append(CMStrings.padRight( ""+(((I.phyStats().rejuv()==PhyStats.NO_REJUV)||(I.phyStats().rejuv()==0))?" - ":""+I.phyStats().rejuv()),5)+" "); if(I instanceof Weapon) itemResults.append(CMStrings.padRight(""+I.basePhyStats().weight(),4)); else itemResults.append(CMStrings.padRight(""+getDeviation( I.basePhyStats().weight(), vals, "WEIGHT"), 4)); /* if(I instanceof Armor) itemResults.append(CMStrings.padRight(""+((Armor)I).phyStats().height(),4)); else itemResults.append(CMStrings.padRight(" - ",4)+" "); */ itemResults.append("\n\r"); I.destroy(); // these are always copies, so all good } else { final MOB M=(MOB)check.get(c); mobResults.append(CMStrings.padRight(M.name(),20)+" "); mobResults.append(CMStrings.padRight(""+M.phyStats().level(),4)+" "); mobResults.append(CMStrings.padRight(""+getDeviation( M.basePhyStats().attackAdjustment(), CMLib.leveler().getLevelAttack(M)),5)+" "); mobResults.append(CMStrings.padRight(""+getDeviation( M.basePhyStats().damage(), CMLib.leveler().getLevelMOBDamage(M)),5)+" "); mobResults.append(CMStrings.padRight(""+getDeviation( M.basePhyStats().armor(), CMLib.leveler().getLevelMOBArmor(M)),5)+" "); mobResults.append(CMStrings.padRight(""+getDeviation( M.basePhyStats().speed(), CMLib.leveler().getLevelMOBSpeed(M)),5)+" "); mobResults.append(CMStrings.padRight(""+(((M.phyStats().rejuv()==PhyStats.NO_REJUV)||(M.phyStats().rejuv()==0))?" - ":""+M.phyStats().rejuv()) ,5)+" "); if(useFaction!=null) mobResults.append(CMStrings.padRight(""+(M.fetchFaction(useFaction.factionID())==Integer.MAX_VALUE?"N/A":""+M.fetchFaction(useFaction.factionID())),7)+" "); final double value = CMLib.beanCounter().getTotalAbsoluteNativeValue(M); final double[] range = CMLib.leveler().getLevelMoneyRange(M); if(value < range[0]) mobResults.append(CMStrings.padRight(""+getDeviation(value,range[0]),5)+" "); else if(value > range[1]) mobResults.append(CMStrings.padRight(""+getDeviation(value,range[1]),5)+" "); else mobResults.append(CMStrings.padRight("0%",5)+" "); int reallyWornCount = 0; for(int j=0;j<M.numItems();j++) { final Item Iw=M.getItem(j); if(!(Iw.amWearingAt(Wearable.IN_INVENTORY))) reallyWornCount++; } mobResults.append(CMStrings.padRight(""+reallyWornCount,5)+" "); mobResults.append("\n\r"); } } if(itemResults.length()>0) str.append(itemHeader()+itemResults.toString()); if(mobResults.length()>0) str.append(mobHeader(useFaction)+mobResults.toString()); return str; } @Override public boolean execute(final MOB mob, final List<String> commands, final int metaFlags) throws java.io.IOException { mob.tell(deviations(mob,CMParms.combine(commands,1)).toString()); return false; } @Override public boolean securityCheck(final MOB mob) { return CMSecurity.isAllowed(mob,mob.location(),CMSecurity.SecFlag.CMDITEMS) || CMSecurity.isAllowed(mob,mob.location(),CMSecurity.SecFlag.LISTADMIN) || CMSecurity.isAllowed(mob,mob.location(),CMSecurity.SecFlag.CMDMOBS); } }