package com.planet_ink.coffee_mud.Items.Basic;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.interfaces.EachApplicable.ApplyAffectPhyStats;
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.*;
/*
Copyright 2001-2019 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 StdItem implements Item
{
@Override
public String ID()
{
return "StdItem";
}
protected String name = "an ordinary item";
protected String displayText = L("a nondescript item sits here doing nothing.");
protected Object description = null;
protected int myUses = Integer.MAX_VALUE;
protected long myWornCode = Wearable.IN_INVENTORY;
protected String miscText = "";
protected Rideable riding = null;
protected String rawImageName = null;
protected String cachedImageName = null;
protected String secretIdentity = null;
protected boolean wornLogicalAnd = false;
protected long properWornBitmap = Wearable.WORN_HELD;
protected int baseGoldValue = 0;
protected int material = RawMaterial.RESOURCE_COTTON;
protected String[] xtraValues = null;
protected long dispossessionTime = 0;
protected short tickCtr = (short)(40+(hashCode()%40));
protected int tickStatus = Tickable.STATUS_NOT;
protected String databaseID = "";
protected boolean destroyed = false;
protected Item me = this;
protected PhyStats phyStats = (PhyStats) CMClass.getCommon("DefaultPhyStats");
protected PhyStats basePhyStats = (PhyStats) CMClass.getCommon("DefaultPhyStats");
protected volatile Container myContainer = null;
protected volatile ItemPossessor owner = null;
protected SVector<Ability> affects = null;
protected SVector<Behavior> behaviors = null;
protected SVector<ScriptingEngine> scripts = null;
@SuppressWarnings("rawtypes")
protected ApplyAffectPhyStats affectPhyStats = new ApplyAffectPhyStats(this);
public StdItem()
{
super();
//CMClass.bumpCounter(this,CMClass.CMObjectType.ITEM);//removed for mem & perf
if(basePhyStats == null)
basePhyStats = (PhyStats) CMClass.getCommon("DefaultPhyStats");
if(phyStats == null)
phyStats = (PhyStats) CMClass.getCommon("DefaultPhyStats");
basePhyStats().setWeight(1);
basePhyStats().setArmor(0);
xtraValues=CMProps.getExtraStatCodesHolder(this);
}
protected boolean abilityImbuesMagic()
{
return true;
}
// protected void finalize()
// {
// CMClass.unbumpCounter(this,CMClass.CMObjectType.ITEM); }//removed for mem
// & perf
@Override
public void initializeClass()
{
}
@Override
public boolean isGeneric()
{
return false;
}
@Override
public String Name()
{
return name;
}
@Override
public void setName(final String newName)
{
name = newName;
}
@Override
public String name()
{
if(phyStats().newName()!=null)
return phyStats().newName();
return Name();
}
@Override
public String displayText(final MOB viewerMob)
{
return displayText();
}
@Override
public String name(final MOB viewerMob)
{
return name();
}
@Override
public void setDatabaseID(final String id)
{
databaseID = id;
}
@Override
public boolean canSaveDatabaseID()
{
return true;
}
@Override
public String databaseID()
{
return databaseID;
}
@Override
public String image()
{
if(cachedImageName==null)
{
if((rawImageName!=null)&&(rawImageName.length()>0))
cachedImageName=rawImageName;
else
cachedImageName=CMLib.protocol().getDefaultMXPImage(this);
}
return cachedImageName;
}
@Override
public String rawImage()
{
if(rawImageName==null)
return "";
return rawImageName;
}
@Override
public void setImage(final String newImage)
{
if((newImage==null)||(newImage.trim().isEmpty()))
rawImageName=null;
else
rawImageName=newImage;
if((cachedImageName!=null)&&(!cachedImageName.equals(newImage)))
cachedImageName=null;
}
@Override
public PhyStats phyStats()
{
return phyStats;
}
@Override
public PhyStats basePhyStats()
{
return basePhyStats;
}
@SuppressWarnings("unchecked")
@Override
public void recoverPhyStats()
{
basePhyStats.copyInto(phyStats);
eachEffect(affectPhyStats);
if(((phyStats().ability()>0)&&abilityImbuesMagic())||(this instanceof MiscMagic))
phyStats().setDisposition(phyStats().disposition()|PhyStats.IS_BONUS);
if((owner()!=null)
&&(owner() instanceof MOB)
&&(CMLib.flags().isHidden(this)))
phyStats().setDisposition((int)(phyStats().disposition()&(PhyStats.ALLMASK-PhyStats.IS_HIDDEN)));
}
@Override
public void setBasePhyStats(final PhyStats newStats)
{
basePhyStats=(PhyStats)newStats.copyOf();
}
@Override
public CMObject newInstance()
{
try
{
return this.getClass().newInstance();
}
catch(final Exception e)
{
Log.errOut(ID(),e);
}
return new StdItem();
}
@Override
public boolean subjectToWearAndTear()
{
return false;
}
@SuppressWarnings("rawtypes")
protected void cloneFix(final Item I)
{
destroyed=false;
me=this;
basePhyStats=(PhyStats)I.basePhyStats().copyOf();
phyStats=(PhyStats)I.phyStats().copyOf();
affectPhyStats = new ApplyAffectPhyStats(this);
affects=null;
behaviors=null;
scripts=null;
for(final Enumeration<Behavior> e=I.behaviors();e.hasMoreElements();)
{
final Behavior B=e.nextElement();
if(B!=null)
addBehavior((Behavior)B.copyOf());
}
for(final Enumeration<ScriptingEngine> e=I.scripts();e.hasMoreElements();)
{
final ScriptingEngine SE=e.nextElement();
if(SE!=null)
addScript((ScriptingEngine)SE.copyOf());
}
Ability A;
for(final Enumeration<Ability> a=I.effects();a.hasMoreElements();)
{
A=a.nextElement();
if((A!=null)&&(!A.ID().equals("ItemRejuv")))
{
A=(Ability)A.copyOf();
addEffect(A);
if(A.canBeUninvoked())
{
A.unInvoke();
delEffect(A);
}
}
}
// an item copy isn't linked to until added somewhere...
owner=null;
}
@Override
public CMObject copyOf()
{
try
{
final StdItem E=(StdItem)this.clone();
//CMClass.bumpCounter(E,CMClass.CMObjectType.ITEM);//removed for mem & perf
E.xtraValues=(xtraValues==null)?null:(String[])xtraValues.clone();
E.cloneFix(this);
CMLib.catalog().newInstance(this);
return E;
}
catch(final CloneNotSupportedException e)
{
return this.newInstance();
}
}
@Override
public Rideable riding()
{
return riding;
}
@Override
public void setRiding(final Rideable ride)
{
if((ride!=null)&&(riding()!=null)&&(riding()==ride)&&(riding().amRiding(this)))
return;
if((riding()!=null)&&(riding().amRiding(this)))
riding().delRider(this);
riding=ride;
if((riding()!=null)&&(!riding().amRiding(this)))
riding().addRider(this);
}
@Override
public ItemPossessor owner()
{
return owner;
}
@Override
public void setOwner(final ItemPossessor E)
{
owner=E;
if((E!=null)&&(!(E instanceof Room)))
setExpirationDate(0);
recoverPhyStats();
}
@Override
public long expirationDate()
{
return dispossessionTime;
}
@Override
public void setExpirationDate(final long time)
{
dispossessionTime=time;
}
@Override
public boolean amDestroyed()
{
return destroyed;
}
@Override
public boolean amWearingAt(final long wornCode)
{
if(wornCode == 0)
return myWornCode == 0;
return (myWornCode & wornCode)==wornCode;
}
@Override
public boolean amBeingWornProperly()
{
if(this.myWornCode==0)
return false;
if(this.properWornBitmap==0)
return false;
if(this.wornLogicalAnd)
return this.myWornCode==this.properWornBitmap;
else
return (this.properWornBitmap & this.myWornCode) != 0;
}
@Override
public boolean fitsOn(final long wornCode)
{
if(wornCode<=0)
return true;
return ((properWornBitmap & wornCode)==wornCode);
}
@Override
public void wearEvenIfImpossible(final MOB mob)
{
for(final long code : Wearable.CODES.ALL_ORDERED())
{
if(fitsOn(code))
{
wearAt(code);
break;
}
}
}
@Override
public boolean wearIfPossible(final MOB mob, final long wearCode)
{
if(wearCode<=0)
return false;
if((fitsOn(wearCode))
&&(canWear(mob,wearCode)))
{
wearAt(wearCode);
return true;
}
return false;
}
@Override
public boolean wearIfPossible(final MOB mob)
{
for(final long code : Wearable.CODES.ALL_ORDERED())
{
if((code>0) && wearIfPossible(mob,code))
return true;
}
return false;
}
@Override
public void wearAt(final long wornCode)
{
if(wornCode==Wearable.IN_INVENTORY)
{
unWear();
return;
}
if(wornLogicalAnd)
setRawWornCode(properWornBitmap);
else
setRawWornCode(wornCode);
recoverPhyStats();
}
@Override
public long rawProperLocationBitmap()
{
return properWornBitmap;
}
@Override
public boolean rawLogicalAnd()
{
return wornLogicalAnd;
}
@Override
public void setRawProperLocationBitmap(final long newValue)
{
properWornBitmap=newValue;
}
@Override
public void setRawLogicalAnd(final boolean newAnd)
{
wornLogicalAnd=newAnd;
}
@Override
public boolean compareProperLocations(final Item toThis)
{
if(toThis.rawLogicalAnd()!=wornLogicalAnd)
return false;
if((toThis.rawProperLocationBitmap()|Wearable.WORN_HELD)==(properWornBitmap|Wearable.WORN_HELD))
return true;
return false;
}
@Override
public long whereCantWear(final MOB mob)
{
long couldHaveBeenWornAt=-1;
if(properWornBitmap==0)
return couldHaveBeenWornAt;
short layer=0;
short layerAtt=0;
if(this instanceof Armor)
{
layer=((Armor)this).getClothingLayer();
layerAtt=((Armor)this).getLayerAttributes();
}
final Wearable.CODES codes = Wearable.CODES.instance();
if(!wornLogicalAnd)
{
for(final long wornCode : codes.all())
{
if(wornCode != Wearable.IN_INVENTORY)
{
if(fitsOn(wornCode))
{
couldHaveBeenWornAt=wornCode;
if(mob.freeWearPositions(wornCode,layer,layerAtt)>0)
return 0;
}
}
}
return couldHaveBeenWornAt;
}
for(final long wornCode : codes.all())
{
if(wornCode != Wearable.IN_INVENTORY)
{
if((fitsOn(wornCode))
&&(mob.freeWearPositions(wornCode,layer,layerAtt)==0))
return wornCode;
}
}
return 0;
}
@Override
public boolean canWear(final MOB mob, final long where)
{
if(where==0)
return (whereCantWear(mob)==0);
if((rawProperLocationBitmap()&where)!=where)
return false;
return mob.freeWearPositions(where,(short)0,(short)0)>0;
}
@Override
public long rawWornCode()
{
return myWornCode;
}
@Override
public void setRawWornCode(final long newValue)
{
myWornCode=newValue;
}
@Override
public void unWear()
{
setRawWornCode(Wearable.IN_INVENTORY);
recoverPhyStats();
}
@Override
public int material()
{
return material;
}
@Override
public void setMaterial(final int newValue)
{
material=newValue;
}
@Override
public int value()
{
return baseGoldValue()+(10*phyStats().ability());
}
@Override
public int baseGoldValue()
{
return baseGoldValue;
}
@Override
public void setBaseValue(final int newValue)
{
baseGoldValue=newValue;
}
@Override
public String readableText()
{
return miscText;
}
@Override
public void setReadableText(final String text)
{
miscText = text;
}
@Override
public boolean isReadable()
{
return CMLib.flags().isReadable(this);
}
@Override
public void setReadable(final boolean truefalse)
{
CMLib.flags().setReadable(this, truefalse);
}
@Override
public void affectPhyStats(final Physical affected, final PhyStats affectableStats)
{
if(affected instanceof Room)
{
if((CMLib.flags().isLightSource(this))&&(CMLib.flags().isInDark(affected)))
affectableStats.setDisposition(affectableStats.disposition()-PhyStats.IS_DARK);
}
else
{
if(CMLib.flags().isLightSource(this))
{
if(rawWornCode()!=Wearable.IN_INVENTORY)
affectableStats.setDisposition(affectableStats.disposition()|PhyStats.IS_LIGHTSOURCE);
if(CMLib.flags().isInDark(affected))
affectableStats.setDisposition(affectableStats.disposition()-PhyStats.IS_DARK);
}
if((amWearingAt(Wearable.WORN_MOUTH))&&(affected instanceof MOB))
{
if(!(this instanceof Light))
affectableStats.setSensesMask(affectableStats.sensesMask()|PhyStats.CAN_NOT_SPEAK);
if((this instanceof Armor)&&(!CMath.bset(((Armor)this).getClothingLayer(),Armor.LAYERMASK_SEETHROUGH)))
affectableStats.setSensesMask(affectableStats.sensesMask()|PhyStats.CAN_NOT_TASTE);
}
final Item ultiCon=ultimateContainer(null);
if(((ultiCon==null)||(!ultiCon.amWearingAt(Wearable.WORN_FLOATING_NEARBY)))
&&((!(affected instanceof MOB))||(((MOB)affected).riding()!=this)))
affectableStats.setWeight(affectableStats.weight()+phyStats().weight());
}
final List<Ability> affects=this.affects;
if((affects!=null)&&(!affects.isEmpty()))
{
try
{
for(int a=0;a<affects.size();a++)
{
final Ability A=affects.get(a);
if((A!=null)&&(A.bubbleAffect()))
A.affectPhyStats(affected,affectableStats);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
@Override
public void affectCharStats(final MOB affectedMob, final CharStats affectableStats)
{
final List<Ability> affects=this.affects;
if((affects!=null)&&(!affects.isEmpty()))
{
try
{
for(int a=0;a<affects.size();a++)
{
final Ability A=affects.get(a);
if((A!=null)&&(A.bubbleAffect()))
A.affectCharStats(affectedMob,affectableStats);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
@Override
public void affectCharState(final MOB affectedMob, final CharState affectableMaxState)
{
final List<Ability> affects=this.affects;
if((affects!=null)&&(!affects.isEmpty()))
{
try
{
for(int a=0;a<affects.size();a++)
{
final Ability A=affects.get(a);
if((A!=null)&&(A.bubbleAffect()))
A.affectCharState(affectedMob,affectableMaxState);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
@Override
public void setMiscText(final String newText)
{
miscText=newText;
}
@Override
public String text()
{
return miscText;
}
@Override
public String miscTextFormat()
{
return CMParms.FORMAT_UNDEFINED;
}
@Override
public int compareTo(final CMObject o)
{
return CMClass.classID(this).compareToIgnoreCase(CMClass.classID(o));
}
@Override
public int getTickStatus()
{
return tickStatus;
}
@Override
public boolean tick(final Tickable ticking, final int tickID)
{
if(destroyed)
return false;
tickStatus=Tickable.STATUS_START;
if((--tickCtr)<=0)
{
tickCtr=(short)(10+CMLib.dice().roll(1, 100, 0));
final String itemReport = CMLib.flags().validCheck(this);
if(itemReport != null)
{
Log.warnOut("Destroy: "+itemReport);
this.destroy();
return false;
}
}
switch(tickID)
{
case Tickable.TICKID_ITEM_BEHAVIOR:
{
tickStatus=Tickable.STATUS_BEHAVIOR;
if(numBehaviors()>0)
{
eachBehavior(new EachApplicable<Behavior>()
{
@Override
public final void apply(final Behavior B)
{
B.tick(ticking,tickID);
}
});
}
tickStatus=Tickable.STATUS_SCRIPT;
if(numScripts()>0)
{
eachScript(new EachApplicable<ScriptingEngine>()
{
@Override
public final void apply(final ScriptingEngine S)
{
S.tick(ticking,tickID);
}
});
}
if((numBehaviors()==0)&&(numScripts()==0))
return false;
break;
}
case Tickable.TICKID_CLANITEM:
case Tickable.TICKID_ELECTRONICS:
case Tickable.TICKID_SPECIALCOMBAT:
case Tickable.TICKID_SPECIALMANEUVER:
break;
default:
{
tickStatus=Tickable.STATUS_AFFECT;
if(numEffects()>0)
{
eachEffect(new EachApplicable<Ability>()
{
@Override
public final void apply(final Ability A)
{
if(!A.tick(ticking,tickID))
A.unInvoke();
}
});
}
break;
}
}
tickStatus=Tickable.STATUS_NOT;
return !amDestroyed();
}
@Override
public Item ultimateContainer(final Physical stopAtC)
{
final Container C=container();
if(C==null)
return this;
else
if(C==stopAtC)
return C;
else
if(C==this)
return null;
else
return C.ultimateContainer(stopAtC);
}
@Override
public Container container()
{
return myContainer;
}
@Override
public String rawSecretIdentity()
{
return ((secretIdentity == null) ? "" : secretIdentity);
}
@Override
public String secretIdentity()
{
if((secretIdentity!=null)&&(secretIdentity.length()>0))
return secretIdentity+"\n\rLevel: "+phyStats().level()+tackOns();
return description()+"\n\rLevel: "+phyStats().level()+tackOns();
}
@Override
public void setSecretIdentity(final String newIdentity)
{
if((newIdentity==null)
||(newIdentity.trim().equalsIgnoreCase(description()))
||(newIdentity.isEmpty()))
secretIdentity=null;
else
secretIdentity=newIdentity;
}
@Override
public String displayText()
{
return displayText;
}
@Override
public void setDisplayText(final String newDisplayText)
{
displayText=newDisplayText;
}
@Override
public String description()
{
if(description == null)
return "";
else
if(description instanceof byte[])
{
final byte[] descriptionBytes=(byte[])description;
if(descriptionBytes.length==0)
return "";
if(CMProps.getBoolVar(CMProps.Bool.ITEMDCOMPRESS))
return CMLib.encoder().decompressString(descriptionBytes);
else
return CMStrings.bytesToStr(descriptionBytes);
}
else
return (String)description;
}
@Override
public String description(final MOB viewerMob)
{
return description();
}
@Override
public void setDescription(final String newDescription)
{
if(newDescription.isEmpty())
description=null;
else
if(CMProps.getBoolVar(CMProps.Bool.ITEMDCOMPRESS))
description=CMLib.encoder().compressString(newDescription);
else
description=newDescription;
}
@Override
public void setContainer(final Container newContainer)
{
if((newContainer!=this)
&&((newContainer==null)||(newContainer.container()!=this)))
myContainer=newContainer;
}
@Override
public int numberOfItems()
{
return 1;
}
@Override
public int usesRemaining()
{
return myUses;
}
@Override
public void setUsesRemaining(final int newUses)
{
myUses=newUses;
}
@Override
public boolean isSavable()
{
if(!CMLib.flags().isSavable(this))
return false;
if(container()!=null)
return container().isSavable();
return true;
}
@Override
public void setSavable(final boolean truefalse)
{
CMLib.flags().setSavable(this, truefalse);
}
protected boolean canWearComplete(final MOB mob, final long wearWhere)
{
if(!canWear(mob,wearWhere))
{
long cantWearAt=whereCantWear(mob);
if(wearWhere!=0)
cantWearAt = cantWearAt & wearWhere;
Item alreadyWearing=(cantWearAt==0)?null:mob.fetchFirstWornItem(cantWearAt);
final Wearable.CODES codes = Wearable.CODES.instance();
if(alreadyWearing!=null)
{
if((cantWearAt!=Wearable.WORN_HELD)&&(cantWearAt!=Wearable.WORN_WIELD))
{
final boolean amWearingOther = !alreadyWearing.amWearingAt(Item.IN_INVENTORY);
if(!CMLib.commands().postRemove(mob,alreadyWearing,false))
{
mob.tell(L("You are already wearing @x1 on your @x2.",alreadyWearing.name(),codes.name(cantWearAt)));
return false;
}
if(amWearingOther && alreadyWearing.amWearingAt(Item.IN_INVENTORY) && (!canWear(mob,wearWhere)))
return canWearComplete(mob, wearWhere);
alreadyWearing=mob.fetchFirstWornItem(cantWearAt);
if((alreadyWearing!=null)&&(!canWear(mob,0)))
{
mob.tell(L("You are already wearing @x1 on your @x2.",alreadyWearing.name(),codes.name(cantWearAt)));
return false;
}
}
else
{
final short layer=(this instanceof Armor)?((Armor)this).getClothingLayer():0;
final short layer2=(alreadyWearing instanceof Armor)?((Armor)alreadyWearing).getClothingLayer():0;
if((rawProperLocationBitmap() == alreadyWearing.rawProperLocationBitmap())
&&(rawLogicalAnd())
&&(alreadyWearing.rawLogicalAnd())
&&(layer == layer2)
&&(CMLib.commands().postRemove(mob,alreadyWearing,false)))
return true;
if(cantWearAt==Wearable.WORN_HELD)
mob.tell(L("You are already holding @x1.",alreadyWearing.name()));
else
if(cantWearAt==Wearable.WORN_WIELD)
mob.tell(L("You are already wielding @x1.",alreadyWearing.name()));
else
mob.tell(L("You are already wearing @x1 on your @x2.",alreadyWearing.name(),codes.name(cantWearAt)));
return false;
}
}
else
if(wearWhere!=0)
{
final StringBuilder locs=new StringBuilder("");
for(int i=0;i<codes.total();i++)
{
if((codes.get(i)&wearWhere)>0)
locs.append(", " + codes.name(i));
}
if(locs.length()==0)
mob.tell(L("You can't wear that there."));
else
mob.tell(L("You can't wear that on your @x1.",locs.toString().substring(1).trim()));
return false;
}
else
{
mob.tell(L("You don't have anywhere you can wear that."));
return false;
}
}
return true;
}
protected boolean alreadyWornMsg(final MOB mob, final Item thisItem)
{
if(!thisItem.amWearingAt(Wearable.IN_INVENTORY))
{
if(thisItem.amWearingAt(Wearable.WORN_WIELD))
mob.tell(L("@x1 is already being wielded.",thisItem.name()));
else
if(thisItem.amWearingAt(Wearable.WORN_HELD))
mob.tell(L("@x1 is already being held.",thisItem.name()));
else
if(thisItem.amWearingAt(Wearable.WORN_FLOATING_NEARBY))
mob.tell(L("@x1 is floating nearby.",thisItem.name()));
else
mob.tell(L("@x1is already being worn.",thisItem.name()));
return false;
}
return true;
}
@Override
public boolean okMessage(final Environmental myHost, final CMMsg msg)
{
// the order that these things are checked in should
// be holy, and etched in stone.
int num=numBehaviors();
MsgListener N=null;
for(int b=0;b<num;b++)
{
N=fetchBehavior(b);
if((N!=null)&&(!N.okMessage(this,msg)))
return false;
}
num=numScripts();
for(int s=0;s<num;s++)
{
N=fetchScript(s);
if((N!=null)&&(!N.okMessage(this,msg)))
return false;
}
num=numEffects();
for(int i=0;i<num;i++)
{
N=fetchEffect(i);
if((N!=null)&&(!N.okMessage(this,msg)))
return false;
}
final MOB mob=msg.source();
if(msg.tool()==this)
{
switch(msg.sourceMinor())
{
case CMMsg.TYP_THROW:
if(mob.isMine(this))
{
if((phyStats().weight()>(mob.maxCarry()/5))
&&(phyStats().weight()!=0))
{
mob.tell(L("@x1 is too heavy to throw.",name()));
return false;
}
if(!CMLib.flags().isDroppable(this))
{
mob.tell(L("You can't seem to let go of @x1.",name()));
return false;
}
}
break;
case CMMsg.TYP_POUR:
if(!(this instanceof Drink))
{
mob.tell(mob,this,null,L("You can't do that with <T-NAMESELF>."));
return false;
}
break;
default:
break;
}
return true;
}
else
if(!msg.amITarget(this))
return true;
else
if(msg.targetMinor()==CMMsg.NO_EFFECT)
return true;
else
if((CMath.bset(msg.targetMajor(),CMMsg.MASK_MAGIC))
&&(!CMLib.flags().isGettable(this))
&&((displayText().isEmpty())
||((msg.tool() instanceof Ability)
&&(((Ability)msg.tool()).abstractQuality()==Ability.QUALITY_MALICIOUS))))
{
mob.tell(L("Please don't do that."));
return false;
}
else
switch(msg.targetMinor())
{
case CMMsg.TYP_ENHANCE:
case CMMsg.TYP_REPAIR:
if(this instanceof Technical)
return true;
break;
case CMMsg.TYP_DAMAGE:
case CMMsg.TYP_WEAPONATTACK:
case CMMsg.TYP_ATTACKMISS:
if((this instanceof BoardableShip)
||((this instanceof Rideable)&&(((Rideable)this).rideBasis()==Rideable.RIDEABLE_WATER)))
return true;
break;
case CMMsg.TYP_EXPIRE:
case CMMsg.TYP_LOOK:
case CMMsg.TYP_EXAMINE:
case CMMsg.TYP_READ:
case CMMsg.TYP_WASREAD:
case CMMsg.TYP_QUIETMOVEMENT:
case CMMsg.TYP_NOISYMOVEMENT:
case CMMsg.TYP_HANDS:
case CMMsg.TYP_SPEAK:
case CMMsg.TYP_OK_ACTION:
case CMMsg.TYP_OK_VISUAL:
case CMMsg.TYP_DEATH:
case CMMsg.TYP_NOISE:
case CMMsg.TYP_EMOTE:
case CMMsg.TYP_SNIFF:
return true;
case CMMsg.TYP_SIT:
if((this instanceof DeadBody)
&&(mob.phyStats().height()<=0)
&&(mob.phyStats().weight()<=0))
return true;
//$FALL-THROUGH$
case CMMsg.TYP_SLEEP:
case CMMsg.TYP_MOUNT:
case CMMsg.TYP_DISMOUNT:
case CMMsg.TYP_ENTER:
if(this instanceof Rideable)
return true;
break;
case CMMsg.TYP_LIST:
if(CMLib.coffeeShops().getShopKeeper(this)!=null)
return true;
break;
case CMMsg.TYP_RELOAD:
if((this instanceof AmmunitionWeapon)
&&(((AmmunitionWeapon)this).requiresAmmunition()))
{
if(((AmmunitionWeapon)this).ammunitionRemaining()>=((AmmunitionWeapon)this).ammunitionCapacity())
{
mob.tell(L("@x1 is already loaded.",name()));
return false;
}
return true;
}
break;
case CMMsg.TYP_UNLOAD:
if((this instanceof AmmunitionWeapon)
&&(((AmmunitionWeapon)this).requiresAmmunition()))
{
if(((AmmunitionWeapon)this).ammunitionRemaining()<=0)
{
mob.tell(L("@x1 is not loaded.",name()));
return false;
}
return true;
}
break;
case CMMsg.TYP_HOLD:
if((!fitsOn(Wearable.WORN_HELD))||(properWornBitmap==0))
{
final StringBuilder str=new StringBuilder(L("You can't hold @x1.",name()));
if(fitsOn(Wearable.WORN_WIELD))
str.append(L("Try WIELDing it."));
else
if(properWornBitmap>0)
str.append(L("Try WEARing it."));
mob.tell(str.toString());
return false;
}
if(!alreadyWornMsg(msg.source(),this))
return false;
if(phyStats().level()>mob.phyStats().level())
{
mob.tell(L("That looks too advanced for you."));
return false;
}
if((!rawLogicalAnd())||(properWornBitmap==0))
{
if(!canWear(mob,Wearable.WORN_HELD))
{
final Item alreadyWearing=mob.fetchHeldItem();
if(alreadyWearing!=null)
{
if((!CMLib.commands().postRemove(mob,alreadyWearing,false))
||(!canWear(mob,Wearable.WORN_HELD)))
{
mob.tell(L("Your hands are full."));
return false;
}
}
else
{
mob.tell(L("You need hands to hold things."));
return false;
}
}
return true;
}
return canWearComplete(mob,0);
case CMMsg.TYP_WEAR:
if(properWornBitmap==0)
{
mob.tell(L("You can't wear @x1.",name()));
return false;
}
if(!alreadyWornMsg(msg.source(),this))
return false;
if(phyStats().level()>mob.phyStats().level())
{
mob.tell(L("That looks too advanced for you."));
return false;
}
return canWearComplete(mob,(msg.value()<=0)?0:((long)(1<<msg.value())/2));
case CMMsg.TYP_WIELD:
if((!fitsOn(Wearable.WORN_WIELD))||(properWornBitmap==0))
{
mob.tell(L("You can't wield @x1 as a weapon.",name()));
return false;
}
if(!alreadyWornMsg(msg.source(),this))
return false;
if(phyStats().level()>mob.phyStats().level())
{
mob.tell(L("That looks too advanced for you."));
return false;
}
if((!rawLogicalAnd())||(properWornBitmap==0))
{
if(!canWear(mob,Wearable.WORN_WIELD))
{
final Item alreadyWearing=mob.fetchFirstWornItem(Wearable.WORN_WIELD);
if(alreadyWearing!=null)
{
if(!CMLib.commands().postRemove(mob,alreadyWearing,false))
{
mob.tell(L("You are already wielding @x1.",alreadyWearing.name()));
return false;
}
}
else
{
mob.tell(L("You need hands to wield things."));
return false;
}
}
}
return canWearComplete(mob,0);
case CMMsg.TYP_PUSH:
case CMMsg.TYP_PULL:
if(msg.source().isMine(this))
{
mob.tell(L("You'll need to put that down first."));
return false;
}
if(!CMLib.flags().isGettable(this))
{
mob.tell(L("You can't move @x1.",name()));
return false;
}
return true;
case CMMsg.TYP_GET:
if((msg.tool()==null)||(msg.tool() instanceof MOB))
{
if((!CMLib.flags().canBeSeenBy(this,mob))
&&(!msg.sourceMajor(CMMsg.MASK_ALWAYS))
&&(amWearingAt(Wearable.IN_INVENTORY)))
{
mob.tell(L("You can't see that."));
return false;
}
if(riding()!=null)
{
mob.tell(L("@x1 is mounted to @x2.",name(msg.source()),riding().name(msg.source())));
return false;
}
if((mob.phyStats().level()<phyStats().level()-(10+(mob.phyStats().level()/5)))
&&(!(mob instanceof ShopKeeper))
&&(!mob.charStats().getMyRace().leveless())
&&(!mob.charStats().getCurrentClass().leveless()))
{
mob.tell(L("@x1 is too powerful to endure possessing it.",name()));
return false;
}
if((phyStats().weight()>(mob.maxCarry()-mob.phyStats().weight()))
&&(!mob.isMine(this))
&&(phyStats().weight()!=0))
{
mob.tell(L("@x1 is too heavy.",name()));
return false;
}
if((numberOfItems()>(mob.maxItems()-mob.numItems()))&&(!mob.isMine(this)))
{
mob.tell(L("You can't carry that many items."));
return false;
}
if(!CMLib.flags().isGettable(this))
{
mob.tell(L("You can't get @x1.",name()));
return false;
}
if((this instanceof Rideable)&&(((Rideable)this).numRiders()>0))
{
if((mob.riding()!=null)&&(mob.riding()==this))
mob.tell(L("You are @x1 @x2!",((Rideable)this).stateString(mob),name()));
else
mob.tell(L("Someone is @x1 @x2!",((Rideable)this).stateString(mob),name()));
return false;
}
return true;
}
if(this instanceof Container)
return true;
switch(msg.sourceMinor())
{
case CMMsg.TYP_BUY:
case CMMsg.TYP_BID:
case CMMsg.TYP_GET:
case CMMsg.TYP_GENERAL:
case CMMsg.TYP_REMOVE:
case CMMsg.TYP_SELL:
case CMMsg.TYP_VALUE:
case CMMsg.TYP_VIEW:
case CMMsg.TYP_GIVE:
return true;
}
break;
case CMMsg.TYP_REMOVE:
if((msg.tool()==null)||(msg.tool() instanceof MOB))
{
if((!CMLib.flags().canBeSeenBy(this,mob))
&&(!msg.sourceMajor(CMMsg.MASK_ALWAYS))
&&(amWearingAt(Wearable.IN_INVENTORY)))
{
mob.tell(L("You can't see that."));
return false;
}
if((!amWearingAt(Wearable.IN_INVENTORY))&&(!CMLib.flags().isRemovable(this)))
{
if(amWearingAt(Wearable.WORN_WIELD)||amWearingAt(Wearable.WORN_HELD))
{
mob.tell(L("You can't seem to let go of @x1.",name()));
return false;
}
mob.tell(L("You can't seem to remove @x1.",name()));
return false;
}
Item I=null;
final short layer=(this instanceof Armor)?((Armor)this).getClothingLayer():0;
short thislayer=0;
if(rawWornCode()>0)
for(int i=0;i<mob.numItems();i++)
{
I=mob.getItem(i);
if((I!=null)&&(I!=this)&&((I.rawWornCode()&rawWornCode())>0))
{
thislayer=(I instanceof Armor)?((Armor)I).getClothingLayer():0;
if(thislayer>layer)
{
mob.tell(mob,I,null,L("You must remove <T-NAME> first."));
return false;
}
}
}
return true;
}
if(this instanceof Container)
return true;
switch(msg.sourceMinor())
{
case CMMsg.TYP_BUY:
case CMMsg.TYP_BID:
case CMMsg.TYP_GET:
case CMMsg.TYP_GENERAL:
case CMMsg.TYP_REMOVE:
case CMMsg.TYP_SELL:
case CMMsg.TYP_VALUE:
case CMMsg.TYP_VIEW:
case CMMsg.TYP_GIVE:
return true;
}
break;
case CMMsg.TYP_DROP:
if(!mob.isMine(this))
{
mob.tell(L("You don't have that."));
return false;
}
if(!CMLib.flags().isDroppable(this))
{
mob.tell(L("You can't seem to let go of @x1.",name()));
return false;
}
return true;
case CMMsg.TYP_BUY:
case CMMsg.TYP_BID:
case CMMsg.TYP_SELL:
case CMMsg.TYP_VALUE:
case CMMsg.TYP_VIEW:
case CMMsg.TYP_ITEMGENERATED:
case CMMsg.TYP_ITEMSGENERATED:
return true;
case CMMsg.TYP_OPEN:
case CMMsg.TYP_CLOSE:
case CMMsg.TYP_LOCK:
case CMMsg.TYP_INSTALL:
case CMMsg.TYP_UNLOCK:
if(this instanceof Container)
return true;
break;
case CMMsg.TYP_PUT:
if(this instanceof Container)
return true;
if(CMath.bset(phyStats().sensesMask(), PhyStats.SENSE_INSIDEACCESSIBLE))
return true;
mob.tell(mob,this,null,L("You can't put things inside <T-NAME>."));
return false;
case CMMsg.TYP_DELICATE_HANDS_ACT:
case CMMsg.TYP_JUSTICE:
case CMMsg.TYP_WAND_USE:
case CMMsg.TYP_RECIPELEARNED:
case CMMsg.TYP_COLD: // free metal
case CMMsg.TYP_ACID: // slime
case CMMsg.TYP_FIRE: // lighting
case CMMsg.TYP_WATER: // rust
case CMMsg.TYP_CAST_SPELL:
case CMMsg.TYP_POISON: // for use poison
return true;
case CMMsg.TYP_EXTINGUISH:
{
final Ability A=fetchEffect("Burning");
if((A!=null)&&(!CMath.bset(A.abilityCode(), 2048))) // yes, magic numbers suck
return true;
break;
}
case CMMsg.TYP_CAUSESINK:
if(this instanceof BoardableShip)
return true;
break;
case CMMsg.TYP_FILL:
if(this instanceof Drink)
return true;
if(this instanceof Lantern)
return true;
break;
case CMMsg.TYP_POUR:
if(msg.tool() instanceof Drink)
return true;
break;
case CMMsg.TYP_EAT:
if(this instanceof Food)
return true;
break;
case CMMsg.TYP_DRINK:
if(this instanceof Drink)
return true;
break;
case CMMsg.TYP_ADVANCE:
if((this instanceof BoardableShip)
||((this instanceof Rideable)||(((Rideable)this).rideBasis()==Rideable.RIDEABLE_WATER)))
return true;
break;
case CMMsg.TYP_ACTIVATE:
case CMMsg.TYP_POWERCURRENT:
case CMMsg.TYP_DEACTIVATE:
if((this instanceof Electronics)||(this instanceof Software))
return true;
break;
case CMMsg.TYP_COLLISION:
if(this instanceof SpaceObject)
return true;
break;
case CMMsg.TYP_REWRITE:
if((isReadable())
&&(!(this instanceof Scroll))
&&(!(this instanceof Electronics)))
{
if(msg.targetMessage().trim().isEmpty())
{
if(this instanceof Electronics)
mob.tell(L("Enter what into @x1?",name()));
else
mob.tell(L("Write what on @x1?",name()));
return false;
}
if(readableText().startsWith("FILE="))
{
mob.tell(L("There's no more room to write on @x1.",name()));
return false;
}
return true;
}
return false;
case CMMsg.TYP_WRITE:
if(((isReadable())&&(!(this instanceof Scroll)))
||(this instanceof ElecPanel)
||(this instanceof Software))
{
if(msg.targetMessage().trim().isEmpty())
{
if(this instanceof Electronics)
mob.tell(L("Enter what into @x1?",name()));
else
mob.tell(L("Write what on @x1?",name()));
return false;
}
if(readableText().startsWith("FILE="))
{
mob.tell(L("There's no more room to write on @x1.",name()));
return false;
}
return true;
}
if(this instanceof Electronics)
mob.tell(L("You can't enter commands into @x1.",name()));
else
mob.tell(L("You can't write on @x1.",name()));
return false;
default:
break;
}
mob.tell(mob,this,null,L("You can't do that to <T-NAMESELF>."));
return false;
}
@Override
public void executeMsg(final Environmental myHost, final CMMsg msg)
{
// the order that these things are checked in should
// be holy, and etched in stone.
if(numBehaviors()>0)
{
eachBehavior(new EachApplicable<Behavior>()
{
@Override
public final void apply(final Behavior B)
{
B.executeMsg(me,msg);
}
});
}
if(numScripts()>0)
{
eachScript(new EachApplicable<ScriptingEngine>()
{
@Override
public final void apply(final ScriptingEngine S)
{
S.executeMsg(me,msg);
}
});
}
if(numEffects()>0)
{
eachEffect(new EachApplicable<Ability>()
{
@Override
public final void apply(final Ability A)
{
A.executeMsg(me, msg);
}
});
}
final MOB mob=msg.source();
if((msg.tool()==this)
&&(msg.sourceMinor()==CMMsg.TYP_THROW)
&&(mob!=null)
&&(msg.target()!=null))
{
final Room R=CMLib.map().roomLocation(msg.target());
if(mob.isMine(this))
{
mob.delItem(this);
if(!R.isContent(this))
R.addItem(this,ItemPossessor.Expire.Player_Drop);
if(!CMath.bset(msg.sourceMajor(),CMMsg.MASK_OPTIMIZE))
{
R.recoverRoomStats();
if(mob.location()!=R)
mob.location().recoverRoomStats();
}
}
unWear();
setContainer(null);
}
else
if(!msg.amITarget(this))
return;
else
switch(msg.targetMinor())
{
case CMMsg.TYP_SNIFF:
CMLib.commands().handleBeingSniffed(msg);
break;
case CMMsg.TYP_LOOK:
case CMMsg.TYP_EXAMINE:
CMLib.commands().handleBeingLookedAt(msg);
break;
case CMMsg.TYP_READ:
CMLib.commands().handleBeingRead(msg);
break;
case CMMsg.TYP_HOLD:
CMLib.commands().handleBeingHeld(msg);
break;
case CMMsg.TYP_WEAR:
CMLib.commands().handleBeingWorn(msg);
break;
case CMMsg.TYP_WIELD:
CMLib.commands().handleBeingWielded(msg);
break;
case CMMsg.TYP_GET:
CMLib.commands().handleBeingGetted(msg);
break;
case CMMsg.TYP_REMOVE:
CMLib.commands().handleBeingRemoved(msg);
break;
case CMMsg.TYP_DROP:
CMLib.commands().handleBeingDropped(msg);
break;
case CMMsg.TYP_WRITE:
if(isReadable() && (!(this instanceof Electronics)))
setReadableText((readableText()+" "+msg.targetMessage()).trim());
break;
case CMMsg.TYP_REWRITE:
if(isReadable() && (!(this instanceof Electronics)))
{
if((""+msg.targetMessage()).startsWith("DELETE "))
setReadableText("");
else
if(!CMath.isInteger(""+msg.targetMessage()))
setReadableText(""+msg.targetMessage().trim());
}
break;
case CMMsg.TYP_EXTINGUISH:
if(CMLib.flags().isOnFire(this))
{
final Ability A=fetchEffect("Burning");
if(A!=null)
{
A.setAbilityCode(0);
A.unInvoke();
delEffect(A);
}
}
break;
case CMMsg.TYP_EXPIRE:
case CMMsg.TYP_DEATH:
destroy();
break;
default:
break;
}
}
@Override
public int recursiveWeight()
{
return phyStats().weight();
}
@Override
public void stopTicking()
{
destroyed=true; // WHY?!?!?
CMLib.threads().deleteTick(this,-1);
}
@Override
public void destroy()
{
if((phyStats().sensesMask()&PhyStats.SENSE_UNDESTROYABLE)>0)
return;
myContainer=null;
CMLib.map().registerWorldObjectDestroyed(null,null,this);
try
{
CMLib.catalog().changeCatalogUsage(this, false);
}
catch (final Exception t)
{
}
delAllEffects(true);
delAllBehaviors();
delAllScripts();
CMLib.threads().deleteTick(this,Tickable.TICKID_ITEM_BEHAVIOR);
riding=null;
destroyed=true;
if(owner!=null)
{
if (owner instanceof Room)
{
final Room thisRoom=(Room)owner;
if(this instanceof Container)
{
for(int r=thisRoom.numItems()-1;r>=0;r--)
{
final Item thisItem = thisRoom.getItem(r);
if((thisItem!=null)
&&(!thisItem.amDestroyed())
&&(thisItem.container()!=null)
&&(thisItem.container()==this))
thisItem.destroy();
}
}
thisRoom.delItem(this);
}
else
if (owner instanceof MOB)
{
final MOB mob=(MOB)owner;
if(this instanceof Container)
{
for(int r=mob.numItems()-1;r>=0;r--)
{
final Item thisItem = mob.getItem(r);
if((thisItem!=null)
&&(!thisItem.amDestroyed())
&&(thisItem.container()==this))
thisItem.destroy();
}
}
mob.delItem(this);
}
}
myContainer=null;
rawImageName=null;
cachedImageName=null;
secretIdentity=null;
owner=null;
affects=null;
behaviors=null;
scripts=null;
}
@Override
public void removeFromOwnerContainer()
{
myContainer=null;
if(owner==null)
return;
if (owner instanceof Room)
{
final Room thisRoom=(Room)owner;
for(int r=thisRoom.numItems()-1;r>=0;r--)
{
final Item thisItem = thisRoom.getItem(r);
if((thisItem!=null)
&&(thisItem.container()!=null)
&&(thisItem.container()==this))
thisItem.removeFromOwnerContainer();
}
thisRoom.delItem(this);
}
else
if (owner instanceof MOB)
{
final MOB mob=(MOB)owner;
for(int r=mob.numItems()-1;r>=0;r--)
{
final Item thisItem = mob.getItem(r);
if((thisItem!=null)
&&(thisItem.container()!=null)
&&(thisItem.container()==this))
thisItem.removeFromOwnerContainer();
}
mob.delItem(this);
}
recoverPhyStats();
}
@Override
public void addNonUninvokableEffect(final Ability to)
{
if(to==null)
return;
if(fetchEffect(to.ID())!=null)
return;
if(affects==null)
affects=new SVector<Ability>(1);
to.makeNonUninvokable();
to.makeLongLasting();
affects.addElement(to);
to.setAffectedOne(this);
}
@Override
public void addEffect(final Ability to)
{
if(to==null)
return;
if(fetchEffect(to.ID())!=null)
return;
if(affects==null)
affects=new SVector<Ability>(1);
affects.addElement(to);
to.setAffectedOne(this);
}
@Override
public void delEffect(final Ability to)
{
if(affects==null)
return;
if(affects.remove(to))
to.setAffectedOne(null);
}
@Override
public void eachEffect(final EachApplicable<Ability> applier)
{
final List<Ability> affects=this.affects;
if((affects!=null)&&(!affects.isEmpty()))
{
try
{
for(int a=0;a<affects.size();a++)
{
final Ability A=affects.get(a);
if(A!=null)
applier.apply(A);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
@Override
public void delAllEffects(final boolean unInvoke)
{
final SVector<Ability> affects=this.affects;
if(affects==null)
return;
Ability keepThisOne=null;
for(int a=numEffects()-1;a>=0;a--)
{
final Ability A=fetchEffect(a);
if(A!=null)
{
if(unInvoke)
{
if(A.ID().equals("ItemRejuv"))
{
keepThisOne=A;
continue;
}
A.unInvoke();
}
A.setAffectedOne(null);
}
}
affects.clear();
if(keepThisOne != null)
{
affects.add(keepThisOne);
}
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<Ability> effects()
{
return (affects==null)?EmptyEnumeration.INSTANCE:affects.elements();
}
@Override
public int numEffects()
{
if(affects==null)
return 0;
return affects.size();
}
@Override
public Ability fetchEffect(final int index)
{
if(affects==null)
return null;
try
{
return affects.elementAt(index);
}
catch (final java.lang.ArrayIndexOutOfBoundsException x)
{
}
return null;
}
@Override
public Ability fetchEffect(final String ID)
{
if(affects==null)
return null;
for(final Enumeration<Ability> a=effects();a.hasMoreElements();)
{
final Ability A=a.nextElement();
if((A!=null)&&(A.ID().equals(ID)))
return A;
}
return null;
}
/** Manipulation of Behavior objects, which includes
* movement, speech, spellcasting, etc, etc.*/
@Override
public void addBehavior(final Behavior to)
{
if(to==null)
return;
if(behaviors==null)
behaviors=new SVector<Behavior>(1);
for(final Behavior B : behaviors)
{
if(B.ID().equals(to.ID()))
return;
}
// first one! so start ticking...
if(behaviors.isEmpty())
CMLib.threads().startTickDown(this,Tickable.TICKID_ITEM_BEHAVIOR,1);
to.startBehavior(this);
behaviors.addElement(to);
}
@Override
public void delAllBehaviors()
{
final boolean didSomething=(behaviors!=null)&&(!behaviors.isEmpty());
if(didSomething)
behaviors.clear();
behaviors=null;
if(didSomething && ((scripts==null)||(scripts.isEmpty())))
CMLib.threads().deleteTick(this,Tickable.TICKID_ITEM_BEHAVIOR);
}
@Override
public void delBehavior(final Behavior to)
{
if(behaviors==null)
return;
if(behaviors.remove(to))
{
to.endBehavior(this);
if(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))
CMLib.threads().deleteTick(this,Tickable.TICKID_ITEM_BEHAVIOR);
}
}
@Override
public int numBehaviors()
{
if(behaviors==null)
return 0;
return behaviors.size();
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<Behavior> behaviors()
{
return (behaviors==null)?EmptyEnumeration.INSTANCE:behaviors.elements();
}
@Override
public Behavior fetchBehavior(final int index)
{
if(behaviors==null)
return null;
try
{
return behaviors.elementAt(index);
}
catch(final java.lang.ArrayIndexOutOfBoundsException x)
{
}
return null;
}
@Override
public Behavior fetchBehavior(final String ID)
{
if(behaviors==null)
return null;
for(final Behavior B : behaviors)
{
if((B!=null)&&(B.ID().equalsIgnoreCase(ID)))
return B;
}
return null;
}
@Override
public void eachBehavior(final EachApplicable<Behavior> applier)
{
final List<Behavior> behaviors=this.behaviors;
if(behaviors!=null)
{
try
{
for(int a=0;a<behaviors.size();a++)
{
final Behavior B=behaviors.get(a);
if(B!=null)
applier.apply(B);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
/** Manipulation of the scripts list */
@Override
public void addScript(final ScriptingEngine S)
{
if(scripts==null)
scripts=new SVector<ScriptingEngine>(1);
if(S==null)
return;
if(!scripts.contains(S))
{
ScriptingEngine S2=null;
for(int s=0;s<scripts.size();s++)
{
S2=scripts.elementAt(s);
if((S2!=null)&&(S2.getScript().equalsIgnoreCase(S.getScript())))
return;
}
if(scripts.isEmpty())
CMLib.threads().startTickDown(this,Tickable.TICKID_ITEM_BEHAVIOR,1);
scripts.addElement(S);
}
}
@Override
public void delScript(final ScriptingEngine S)
{
if(scripts!=null)
{
if(scripts.remove(S))
{
if(scripts.isEmpty())
scripts=new SVector<ScriptingEngine>(1);
if(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))
CMLib.threads().deleteTick(this,Tickable.TICKID_ITEM_BEHAVIOR);
}
}
}
@Override
public void delAllScripts()
{
final boolean didSomething=(scripts!=null)&&(!scripts.isEmpty());
if(didSomething)
scripts.clear();
scripts=null;
if(didSomething && ((behaviors==null)||(behaviors.isEmpty())))
CMLib.threads().deleteTick(this,Tickable.TICKID_ITEM_BEHAVIOR);
}
@Override
public int numScripts()
{
return (scripts == null) ? 0 : scripts.size();
}
@SuppressWarnings("unchecked")
@Override
public Enumeration<ScriptingEngine> scripts()
{
return (scripts == null) ? EmptyEnumeration.INSTANCE : scripts.elements();
}
@Override
public ScriptingEngine fetchScript(final int x)
{
try
{
return scripts.elementAt(x);
}
catch (final Exception e)
{
}
return null;
}
@Override
public void eachScript(final EachApplicable<ScriptingEngine> applier)
{
final List<ScriptingEngine> scripts=this.scripts;
if(scripts!=null)
{
try
{
for(int a=0;a<scripts.size();a++)
{
final ScriptingEngine S=scripts.get(a);
if(S!=null)
applier.apply(S);
}
}
catch (final ArrayIndexOutOfBoundsException e)
{
}
}
}
protected String tackOns()
{
final StringBuilder identity=new StringBuilder("");
if(numEffects()>0)
identity.append("\n\rHas the following magical properties: ");
if(numEffects()>0)
{
eachEffect(new EachApplicable<Ability>()
{
@Override
public final void apply(final Ability A)
{
if(A.accountForYourself().length()>0)
identity.append("\n\r"+A.accountForYourself());
}
});
}
return identity.toString();
}
@Override
public int maxRange()
{
return 0;
}
@Override
public int minRange()
{
return 0;
}
protected static String[] CODES={"CLASS","USES","LEVEL","ABILITY","TEXT"};
@Override
public String getStat(final String code)
{
switch(getCodeNum(code))
{
case 0:
return ID();
case 1:
return "" + usesRemaining();
case 2:
return "" + basePhyStats().ability();
case 3:
return "" + basePhyStats().level();
case 4:
return text();
}
return "";
}
@Override
public void setStat(final String code, final String val)
{
switch(getCodeNum(code))
{
case 0:
return;
case 1:
setUsesRemaining(CMath.s_parseIntExpression(val));
break;
case 2:
basePhyStats().setLevel(CMath.s_parseIntExpression(val));
break;
case 3:
basePhyStats().setAbility(CMath.s_parseIntExpression(val));
break;
case 4:
setMiscText(val);
break;
}
}
@Override
public String L(final String str, final String... xs)
{
return CMLib.lang().fullSessionTranslation(str, xs);
}
protected String I(final String str)
{
return CMLib.lang().commandWordTranslation(str);
}
@Override
public int getSaveStatIndex()
{
return (xtraValues == null) ? getStatCodes().length : getStatCodes().length - xtraValues.length;
}
@Override
public String[] getStatCodes()
{
return CODES;
}
@Override
public boolean isStat(final String code)
{
return CMParms.indexOf(getStatCodes(), code.toUpperCase().trim()) >= 0;
}
protected int getCodeNum(final String code)
{
for(int i=0;i<CODES.length;i++)
{
if(code.equalsIgnoreCase(CODES[i]))
return i;
}
return -1;
}
@Override
public boolean sameAs(final Environmental E)
{
if(!(E instanceof StdItem))
return false;
final String[] codes=getStatCodes();
for(int i=0;i<codes.length;i++)
{
if(!E.getStat(codes[i]).equals(getStat(codes[i])))
return false;
}
return true;
}
}