package com.planet_ink.coffee_mud.Common;
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.core.exceptions.*;
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.Libraries.interfaces.XMLLibrary.XMLTag;
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.*;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptableObject;
/*
Copyright 2003-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 DefaultQuest implements Quest, Tickable, CMObject
{
@Override
public String ID()
{
return "DefaultQuest";
}
protected String name = "";
protected String author = "";
protected String displayName = "";
protected String startDate = "";
protected int duration = 450;// about // 30 // minutes
protected boolean expires = false;
protected String rawScriptParameter = "";
protected boolean durable = false;
protected int minWait = -1;
protected int minPlayers = -1;
protected String playerMask = "";
protected int runLevel = -1;
protected int maxWait = -1;
protected int waitRemaining = -1;
protected int ticksRemaining = -1;
protected long lastStartDateTime = System.currentTimeMillis();
private boolean stoppingQuest = false;
protected int spawn = SPAWN_NO;
private QuestState questState = new QuestState();
private boolean copy = false;
private boolean suspended = false;
public DVector internalFiles = null;
private int[] resetData = null;
protected final Map<String,Long> stepEllapsedTimes = new Hashtable<String,Long>();
protected final Map<String,Long> winners = new CaselessTreeMap<Long>();
// the unique name of the quest
@Override
public String name()
{
return name;
}
@Override
public void setName(final String newName)
{
name = newName;
}
// the author of the quest
@Override
public String author()
{
return author;
}
@Override
public void setAuthor(final String newName)
{
author = newName;
}
// the display name of the quest
@Override
public String displayName()
{
return displayName;
}
@Override
public void setDisplayName(final String newName)
{
displayName = newName;
}
@Override
public CMObject copyOf()
{
try
{
final Object O=this.clone();
return (CMObject)O;
}
catch(final CloneNotSupportedException e)
{
return newInstance();
}
}
@Override
public boolean suspended()
{
return suspended;
}
@Override
public void setSuspended(final boolean truefalse)
{
suspended = truefalse;
}
@Override
public CMObject newInstance()
{
try
{
return getClass().newInstance();
}
catch (final Exception e)
{
return new DefaultQuest();
}
}
@Override
public void initializeClass()
{
}
@Override
public Object getDesignatedObject(final String named)
{
final QCODES q=(QCODES)CMath.s_valueOf(QCODES.class, named.toUpperCase().trim());
final int code=(q==null)?-1:q.ordinal();
switch(code)
{
case 0:
return ID();
case 1:
return name();
case 2:
return "" + duration();
case 3:
return "" + minWait();
case 4:
return "" + minPlayers();
case 5:
return "" + playerMask();
case 6:
return "" + runLevel();
case 7:
return "" + startDate();
case 8:
return "" + startDate();
case 9:
return "" + waitInterval();
case 10:
return SPAWN_DESCS[getSpawn()];
case 11:
return displayName();
case 12:
break; // instructions should fall through
case 13:
return Boolean.toString(durable);
case 14:
return "" + author();
case 15:
return ""+(isCopy()?duration():0);
}
return questState.getStat(named);
}
@Override
public void internalQuestDelete()
{
if(isCopy())
return;
if((internalFiles!=null)&&(internalFiles.size()>0))
{
for(int i=0;i<internalFiles.size();i++)
{
final String filename=((String)internalFiles.elementAt(i,1)).toUpperCase();
final Vector<String> delThese=new Vector<String>();
boolean foundKey=false;
for(final Iterator<String> k=Resources.findResourceKeys(filename);k.hasNext();)
{
final String key=k.next();
if(key.startsWith("PARSEDPRG: ")&&(key.toUpperCase().endsWith(filename)))
{
foundKey = true;
delThese.addElement(key);
}
}
if(foundKey)
{
for(int d=0;d<delThese.size();d++)
Resources.removeResource(delThese.elementAt(d));
}
}
internalFiles.clear();
internalFiles=null;
}
}
// the unique name of the quest
@Override
public String startDate()
{
return startDate;
}
@Override
public void setStartDate(final String newDate)
{
final int x=newDate.indexOf('-');
if((x>0)
&&(CMath.isMathExpression(newDate.substring(0,x)))
&&(CMath.isMathExpression(newDate.substring(x+1))))
startDate=newDate;
}
@Override
public void setStartMudDate(final String newDate)
{
setStartDate(newDate);
if(startDate.equals(newDate))
startDate="MUDDAY "+startDate;
}
// the duration, in ticks
@Override
public int duration()
{
return duration;
}
@Override
public void setDuration(final int newTicks)
{
duration = newTicks;
}
@Override
public void setCopy(final boolean truefalse)
{
copy = truefalse;
}
@Override
public boolean isCopy()
{
return copy;
}
@Override
public void setSpawn(final int spawnFlag)
{
spawn = (spawnFlag < 0) ? 0 : spawnFlag;
}
@Override
public int getSpawn()
{
return spawn;
}
@Override
public int minPlayers()
{
return minPlayers;
}
@Override
public void setMinPlayers(final int players)
{
minPlayers = players;
}
@Override
public int runLevel()
{
return runLevel;
}
@Override
public void setRunLevel(final int level)
{
runLevel = level;
}
@Override
public String playerMask()
{
return playerMask;
}
@Override
public void setPlayerMask(final String mask)
{
playerMask = mask;
}
// the rest of the script. This may be semicolon-separated instructions,
// or a LOAD command followed by the quest script path.
@Override
public boolean setScript(final String parm, final boolean showErrors)
{
rawScriptParameter=parm;
name="";
author="";
displayName="";
startDate="";
duration=-1;
minWait=-1;
maxWait=-1;
minPlayers=-1;
spawn=SPAWN_NO;
playerMask="";
runLevel=-1;
internalFiles=null;
durable=false;
final List<Object> questScripts=parseLoadScripts(parm,new Vector<Object>(),new Vector<Object>(),showErrors);
if(questScripts.size()==0)
return false;
setVars(questScripts,0);
if(isCopy())
spawn=SPAWN_NO;
return true;
}
@Override
public String script()
{
return rawScriptParameter;
}
@Override
public void autostartup()
{
if(!resetWaitRemaining(0))
CMLib.threads().deleteTick(this,Tickable.TICKID_QUEST);
else
if(!running())
CMLib.threads().startTickDown(this,Tickable.TICKID_QUEST,1);
}
@Override
public void setVars(final List<?> script, final int startAtLine)
{
List<String> parsedLine=null;
String var=null;
String val=null;
final List<List<String>> setScripts=CMLib.quests().parseQuestCommandLines(script,"SET",startAtLine);
for(int v=0;v<setScripts.size();v++)
{
parsedLine=setScripts.get(v);
if(parsedLine.size()>1)
{
var=parsedLine.get(1).toUpperCase();
val=CMParms.combine(parsedLine,2);
if(isStat(var))
setStat(var,val);
}
}
}
@Override
public StringBuffer getResourceFileData(final String named, final boolean showErrors)
{
int index=-1;
if(internalFiles!=null)
{
index=internalFiles.indexOf(named.toUpperCase().trim());
if(index>=0)
return (StringBuffer)internalFiles.elementAt(index,2);
}
final StringBuffer buf=new CMFile(Resources.makeFileResourceName(named),null,showErrors?CMFile.FLAG_LOGERRORS:0).text();
return buf;
}
private void questifyScriptableBehavs(final PhysicalAgent E)
{
if(E==null)
return;
Behavior B=null;
for(final Enumeration<Behavior> e=E.behaviors();e.hasMoreElements();)
{
B=e.nextElement();
if(B instanceof ScriptingEngine)
((ScriptingEngine)B).registerDefaultQuest(this.name());
}
if((E instanceof Item)
&&((((Item)E).numBehaviors()>0)||(((Item)E).numScripts()>0))
&&(!CMLib.threads().isTicking(E, Tickable.TICKID_ITEM_BEHAVIOR)))
{
CMLib.threads().startTickDown(E,Tickable.TICKID_ITEM_BEHAVIOR,1);
}
}
private Enumeration<Room> getAppropriateRoomSet(final QuestState q)
{
if(q.roomGroup!=null)
return new IteratorEnumeration<Room>(q.roomGroup.iterator());
else
if(q.area!=null)
return q.area.getMetroMap();
return CMLib.map().rooms();
}
private final Enumeration<Room> getAppropriateRoomSet(final QuestState q, final Iterable<Room> useThese)
{
if(useThese == null)
return getAppropriateRoomSet(q);
return new IteratorEnumeration<Room>(useThese.iterator());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List sortSelect(final Environmental E,
final String str,
List choices,
final List choices0,
final List choices1,
final List choices2,
final List choices3)
{
final String mname=E.name().toUpperCase();
final String mdisp=E.displayText().toUpperCase();
final String mdesc=E.description().toUpperCase();
if(str.equalsIgnoreCase("any"))
{
choices=choices0;
choices0.add(E);
}
else
if(mname.equalsIgnoreCase(str))
{
choices=choices0;
choices0.add(E);
}
else
if(CMLib.english().containsString(mname,str))
{
if((choices==null)||(choices==choices2)||(choices==choices3))
choices=choices1;
choices1.add(E);
}
else
if(CMLib.english().containsString(mdisp,str))
{
if((choices==null)||(choices==choices3))
choices=choices2;
choices2.add(E);
}
else
if(CMLib.english().containsString(mdesc,str))
{
if(choices==null)
choices=choices3;
choices3.add(E);
}
return choices;
}
private TimeClock getMysteryTimeNowFromState()
{
TimeClock NOW=null;
if(questState.mysteryData==null)
return (TimeClock)CMLib.time().globalClock().copyOf();
if((questState.mysteryData.whereAt!=null)&&(questState.mysteryData.whereAt.getArea()!=null))
NOW=(TimeClock)questState.mysteryData.whereAt.getArea().getTimeObj().copyOf();
else
if((questState.mysteryData.whereHappened!=null)&&(questState.mysteryData.whereHappened.getArea()!=null))
NOW=(TimeClock)questState.mysteryData.whereHappened.getArea().getTimeObj().copyOf();
else
if((questState.room!=null)&&(questState.room.getArea()!=null))
NOW=(TimeClock)questState.room.getArea().getTimeObj().copyOf();
else
if(questState.area!=null)
NOW=(TimeClock)questState.area.getTimeObj().copyOf();
else
NOW=(TimeClock)CMLib.time().globalClock().copyOf();
return NOW;
}
@SuppressWarnings("unchecked")
public void parseQuestScriptWArgs(final List<?> script, List<Object> args)
{
if(args==null)
args=new Vector<Object>();
if(args.size()==0)
parseQuestScript(script, args, -1);
else
{
final List<Object> allArgs=new Vector<Object>();
for(int i=0;i<args.size();i++)
{
final Object O=args.get(i);
if(O instanceof List)
{
final List<Object> V=(List<Object>)O;
if(allArgs.size()==0)
{
for(int v=0;v<V.size();v++)
allArgs.add(new XVector<Object>(V.get(v)));
}
else
{
final List<Object> allArgsCopy=new XVector<Object>(allArgs);
allArgs.clear();
for(int aa=0;aa<allArgsCopy.size();aa++)
{
final List<Object> argSet=(List<Object>)allArgsCopy.get(aa);
for(int v=0;v<V.size();v++)
{
final List<Object> V2=new XVector<Object>(argSet);
V2.add(V.get(v));
allArgs.add(V2);
}
}
}
}
else
if(allArgs.size()==0)
allArgs.add(new XVector<Object>(O));
else
for(int aa=0;aa<allArgs.size();aa++)
((List<Object>)allArgs.get(aa)).add(O);
}
for(int a=0;a<allArgs.size();a++)
parseQuestScript(script, (List<Object>)allArgs.get(a),-1);
}
}
protected void errorOccurred(final QuestState q, final boolean quietFlag, final String msg)
{
if(!quietFlag)
Log.errOut("Quest",msg);
q.error=true;
}
private void sizeDownTo(final List<?> V, final int num)
{
if(num<0)
return;
if(num==0)
V.clear();
else
while(V.size()>num)
V.remove(CMLib.dice().roll(1,V.size(),-1));
}
protected void filterOutThoseInUse(final List<? extends Environmental> choices, final String choicesStr, final QuestState q, final boolean isQuiet, final boolean reselect)
{
if((choices!=null)&&(choices.size()>0))
{
final Set<String> inUseByWhom=new TreeSet<String>();
for(int c=choices.size()-1;c>=0;c--)
{
final Environmental E=choices.get(c);
if((E instanceof Physical) && (CMLib.flags().isCloaked((Physical)E)))
{
final Quest Q=CMLib.quests().objectInUse(E);
if((!reselect)
||(Q==null)
||(!(Q instanceof DefaultQuest))
||(!((DefaultQuest)Q).questState.reselectable.contains(E)))
choices.remove(c);
}
else
if((!reselect)&&(!q.reselectable.contains(E)))
{
final Quest Q=CMLib.quests().objectInUse(E);
if(Q!=null)
{
if((!(Q instanceof DefaultQuest))
||(!((DefaultQuest)Q).questState.reselectable.contains(E)))
{
choices.remove(c);
inUseByWhom.add(Q.name());
}
}
}
}
if((choices.size()==0)&&(!isQuiet))
errorOccurred(q,isQuiet,"Quest '"+name()+"', all choices were taken: '"+choicesStr+"' by: "+CMParms.toListString(inUseByWhom)+".");
}
}
protected List<String> parseFinalQuestScript(final List<?> script)
{
final Vector<String> finalScript=new Vector<String>();
for(int v=0;v<script.size();v++)
{
if(script.get(v) instanceof String)
finalScript.addElement((String)script.get(v));
else
if(script.get(v) instanceof List)
{
final int vs=v;
while((v<script.size())&&(script.get(v) instanceof List))
v++;
final int rnum=vs+CMLib.dice().roll(1,v-vs,-1);
if(rnum<script.size())
{
final List<?> V=(List<?>)script.get(rnum);
for(int v2=0;v2<V.size();v2++)
{
if(V.get(v2) instanceof String)
finalScript.addElement((String)V.get(v2));
}
}
}
}
return finalScript;
}
@SuppressWarnings("unchecked")
public void parseQuestScript(List<?> script, final List<Object> args, final int startLine)
{
script=parseFinalQuestScript(script);
final QuestState q=questState;
int vStart=startLine;
if(vStart<0)
vStart=0;
q.done=false;
if(vStart>=script.size())
return;
q.startLine=vStart;
for(int v=vStart;v<script.size();v++)
{
if(startLine>=0)
q.lastLine=v;
final String s=modifyStringFromArgs((String)script.get(v),args);
final Vector<String> p=CMParms.parse(s);
boolean isQuiet=q.beQuiet;
if(p.size()>0)
{
String cmd=p.elementAt(0).toUpperCase();
if(cmd.equals("<SCRIPT>"))
{
final StringBuffer jscript=new StringBuffer("");
while(((++v)<script.size())
&&(!((String)script.get(v)).trim().toUpperCase().startsWith("</SCRIPT>")))
jscript.append(((String)script.get(v))+"\n");
if(v>=script.size())
{
errorOccurred(q,false,"Quest '"+name()+"', <SCRIPT> command without </SCRIPT> found.");
break;
}
if(!CMSecurity.isApprovedJScript(jscript))
{
errorOccurred(q,false,"Quest '"+name()+"', <SCRIPT> not approved. Use MODIFY JSCRIPT to approve.");
break;
}
final Context cx = Context.enter();
try
{
final JScriptQuest scope = new JScriptQuest(this,q);
cx.initStandardObjects(scope);
scope.defineFunctionProperties(JScriptQuest.functions,
JScriptQuest.class,
ScriptableObject.DONTENUM);
cx.evaluateString(scope, jscript.toString(),"<cmd>", 1, null);
}
catch(final Exception e)
{
errorOccurred(q,false,"Quest '"+name()+"', JScript q.error: "+e.getMessage()+".");
Context.exit();
break;
}
Context.exit();
continue;
}
if(cmd.equals("QUIET"))
{
if(p.size()<2)
{
q.beQuiet=true;
continue;
}
isQuiet=true;
p.removeElementAt(0);
cmd=p.elementAt(0).toUpperCase();
}
if(cmd.equals("STEP"))
{
q.autoStepAfterDuration=false;
if((p.size()>1)&&(p.elementAt(1).equalsIgnoreCase("BREAK")))
{
q.lastLine=script.size();
q.done=true;
}
else
if((p.size()>1)&&(p.elementAt(1).equalsIgnoreCase("BACK")))
{
if(startLine>=0)
q.lastLine=q.startLine;
}
else
if((p.size()>1)&&(p.elementAt(1).equalsIgnoreCase("AUTO")))
{
if(startLine>=0)
q.lastLine=v+1;
q.autoStepAfterDuration=true;
}
else
{
if(startLine>=0)
q.lastLine=v+1;
}
return;
}
if(cmd.equals("RESET"))
{
if(q.room!=null)
CMLib.map().resetRoom(q.room, true);
else
if(q.roomGroup!=null)
{
for(int r=0;r<q.roomGroup.size();r++)
CMLib.map().resetRoom(q.roomGroup.get(r), true);
}
else
if(q.area!=null)
CMLib.map().resetArea(q.area);
else
{
errorOccurred(q,false,"Quest '"+name()+"', no resettable room, roomgroup, area, or areagroup set.");
break;
}
}
else
if(cmd.equals("SET"))
{
if(p.size()<2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unfound variable on set.");
break;
}
cmd=p.elementAt(1).toUpperCase();
if(cmd.equals("AREA"))
{
if(p.size()<3)
{
q.area=null;
continue;
}
try
{
q.area = (Area) getObjectIfSpecified(p, args, 2, 0);
q.envObject = q.area;
continue;
}
catch(final CMException ex)
{
q.area=null;
}
final Vector<String> names=new Vector<String>();
final Vector<Area> areas=new Vector<Area>();
if((p.size()>3)&&(p.elementAt(2).equalsIgnoreCase("any")))
{
for(int ip=3;ip<p.size();ip++)
names.addElement(p.elementAt(ip));
}
else
names.addElement(CMParms.combine(p,2));
for(int n=0;n<names.size();n++)
{
final String areaName=names.elementAt(n);
final int oldSize=areas.size();
if(areaName.equalsIgnoreCase("any"))
areas.addElement(CMLib.map().getRandomArea());
if(oldSize==areas.size())
{
for (final Enumeration<Area> e = CMLib.map().areas(); e.hasMoreElements(); )
{
final Area A2 = e.nextElement();
if (A2.Name().equalsIgnoreCase(areaName))
{
areas.addElement(A2);
break;
}
}
}
if(oldSize==areas.size())
{
for(final Enumeration<BoardableShip> e=CMLib.map().ships();e.hasMoreElements();)
{
final BoardableShip ship=e.nextElement();
final Area A2=(ship != null) ? ship.getShipArea() : null;
if(A2 != null)
{
if (A2.Name().equalsIgnoreCase(areaName))
{
areas.addElement(A2);
break;
}
}
}
}
if(oldSize==areas.size())
{
for(final Enumeration<Area> e=CMLib.map().areas();e.hasMoreElements();)
{
final Area A2=e.nextElement();
if(CMLib.english().containsString(A2.Name(),areaName))
{
areas.addElement(A2);
break;
}
}
}
if(oldSize==areas.size())
{
for(final Enumeration<BoardableShip> e=CMLib.map().ships();e.hasMoreElements();)
{
final BoardableShip ship=e.nextElement();
final Area A2=(ship != null) ? ship.getShipArea() : null;
if(A2 != null)
{
if(CMLib.english().containsString(A2.Name(),areaName))
{
areas.addElement(A2);
break;
}
}
}
}
}
if(areas.size()>0)
q.area=areas.elementAt(CMLib.dice().roll(1,areas.size(),-1));
if(q.area==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown area '"+CMParms.combine(p,2)+"'.");
break;
}
}
else
if(cmd.equals("AREAGROUP"))
{
q.area=null;
q.roomGroup=null;
if(p.size()<3)
continue;
final Vector<String> names=new Vector<String>();
final Vector<Area> areas=new Vector<Area>();
for(int ip=2;ip<p.size();ip++)
names.addElement(p.elementAt(ip));
for(int n=0;n<names.size();n++)
{
final String areaName=names.elementAt(n);
final int oldSize=areas.size();
if(areaName.equalsIgnoreCase("any"))
areas.addElement(CMLib.map().getRandomArea());
final boolean addAll=areaName.equalsIgnoreCase("all");
if(oldSize==areas.size())
{
if(addAll)
{
for (final Enumeration<Area> e = CMLib.map().areas(); e.hasMoreElements(); )
{
final Area A2=e.nextElement();
if(!areas.contains(A2))
areas.add(A2);
}
}
else
{
Area A2=CMLib.map().findArea(areaName);
if(A2 == null)
{
final BoardableShip ship=CMLib.map().findShip(areaName, true);
if(ship != null)
A2=ship.getShipArea();
}
if((A2!=null)&&(!areas.contains(A2)))
areas.add(A2);
}
}
}
if(areas.size()>0)
{
q.roomGroup=new Vector<Room>();
Room R=null;
for (final Area A : areas)
{
for(final Enumeration<Room> e2=A.getMetroMap();e2.hasMoreElements();)
{
R=e2.nextElement();
if(!q.roomGroup.contains(R))
q.roomGroup.add(R);
}
}
q.envObject=q.roomGroup;
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown areas '"+CMParms.combine(p,2)+"'.");
break;
}
}
else
if(cmd.equals("MOBTYPE"))
{
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
{
q.mob=null;
continue;
}
try
{
q.mob=(MOB)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
q.mob=null;
final List<MOB> choices=new ArrayList<MOB>(); // thread safe -- not building a group
final List<String> mobTypes=CMParms.parse(CMParms.combine(p,2).toUpperCase());
for(int t=0;t<mobTypes.size();t++)
{
final String mobType=mobTypes.get(t);
if(mobType.startsWith("-"))
continue;
if(q.mobGroup==null)
{
try
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
for(int i=0;i<R2.numInhabitants();i++)
{
final MOB M2=R2.fetchInhabitant(i);
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if(mobType.equalsIgnoreCase("any"))
choices.add(M2);
else
if((CMClass.classID(M2).toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().racialCategory().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().name().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getCurrentClass().name(M2.charStats().getCurrentClassLevel()).toUpperCase().indexOf(mobType)>=0))
choices.add(M2);
}
}
}
}
catch (final NoSuchElementException e)
{
}
}
else
{
try
{
for(final MOB M2 : q.mobGroup)
{
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if(mobType.equalsIgnoreCase("any"))
choices.add(M2);
else
if((CMClass.classID(M2).toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().racialCategory().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().name().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getCurrentClass().name(M2.charStats().getCurrentClassLevel()).toUpperCase().indexOf(mobType)>=0))
choices.add(M2);
}
}
}
catch (final NoSuchElementException e)
{
}
}
}
for(int t=0;t<mobTypes.size();t++)
{
String mobType=mobTypes.get(t);
if(!mobType.startsWith("-"))
continue;
mobType=mobType.substring(1);
for(int i=choices.size()-1;i>=0;i--)
{
final MOB M2=choices.get(i);
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if((CMClass.classID(M2).toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().racialCategory().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getMyRace().name().toUpperCase().indexOf(mobType)>=0)
||(M2.charStats().getCurrentClass().name(M2.charStats().getCurrentClassLevel()).toUpperCase().indexOf(mobType)>=0)
||(M2.name().toUpperCase().indexOf(mobType)>=0)
||(M2.displayText().toUpperCase().indexOf(mobType)>=0))
choices.remove(M2);
}
}
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
if(choices.size()>0)
q.mob=choices.get(CMLib.dice().roll(1,choices.size(),-1));
}
if(q.mob==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !mobtype '"+p+"'.");
break;
}
if(reselect)
q.reselectable.add(q.mob);
// why is this being done -- atm, this is a simple map mob, minding his own business.
questifyScriptableBehavs(q.mob);
if(q.room!=null)
q.room.bringMobHere(q.mob,false);
else
q.room=q.mob.location();
q.envObject=q.mob;
runtimeRegisterObject(q.mob);
if(q.room!=null)
{
q.area=q.room.getArea();
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
}
else
if(cmd.equals("MOBGROUP"))
{
q.mobGroup=null;
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
continue;
List<MOB> choices=null;
String mobName=CMParms.combine(p,2).toUpperCase();
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if(mask!=null)
mobName=CMParms.combine(p,2).toUpperCase();
try
{
choices=(List<MOB>)getObjectIfSpecified(p,args,2,1);
}
catch(final CMException ex)
{
if(mobName.length()==0)
mobName="ANY";
final boolean addAll=mobName.equalsIgnoreCase("all");
final List<MOB> choices0=new Vector<MOB>();
final List<MOB> choices1=new Vector<MOB>();
final List<MOB> choices2=new Vector<MOB>();
final List<MOB> choices3=new Vector<MOB>();
try
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
for(int i=0;i<R2.numInhabitants();i++)
{
final MOB M2=R2.fetchInhabitant(i);
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if(CMLib.masking().maskCheck(mask,M2,true))
{
if(addAll)
{
choices = choices0;
choices.add(M2);
}
else
choices=sortSelect(M2,mobName,choices,choices0,choices1,choices2,choices3);
}
}
}
}
}
catch (final NoSuchElementException e)
{
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
}
if((choices!=null)&&(choices.size()>0))
{
q.mobGroup=choices;
if(reselect)
q.reselectable.addAll(choices);
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !mobgroup '"+mobName+":"+maskStr+"'.");
break;
}
q.envObject=q.mobGroup;
}
else
if(cmd.equals("ITEMGROUP"))
{
q.itemGroup=null;
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
continue;
List<Item> choices=null;
String itemName=CMParms.combine(p,2).toUpperCase();
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if(mask!=null)
itemName=CMParms.combine(p,2).toUpperCase();
try
{
choices=(List<Item>)getObjectIfSpecified(p,args,2,1);
}
catch(final CMException ex)
{
final List<Item> choices0=new Vector<Item>();
final List<Item> choices1=new Vector<Item>();
final List<Item> choices2=new Vector<Item>();
final List<Item> choices3=new Vector<Item>();
if(itemName.length()==0)
itemName="ANY";
final boolean addAll=itemName.equalsIgnoreCase("all");
try
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
for(int i=0;i<R2.numItems();i++)
{
final Item I2=R2.getItem(i);
if(I2!=null)
{
if(CMLib.masking().maskCheck(mask,I2,true))
{
if(addAll)
{
choices = choices0;
choices.add(I2);
}
else
choices=sortSelect(I2,itemName,choices,choices0,choices1,choices2,choices3);
}
}
}
}
}
catch (final NoSuchElementException e)
{
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
}
if((choices!=null)&&(choices.size()>0))
{
if(reselect)
q.reselectable.addAll(choices);
q.itemGroup=choices;
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !itemgroup '"+itemName+":"+maskStr+"'.");
break;
}
q.envObject=q.itemGroup;
}
else
if(cmd.equals("ITEMTYPE"))
{
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
{
q.item=null;
continue;
}
try
{
q.item=(Item)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
q.item=null;
final List<Item> choices=new ArrayList<Item>();
final Vector<String> itemTypes=new Vector<String>();
for(int i=2;i<p.size();i++)
itemTypes.addElement(p.elementAt(i));
for(int t=0;t<itemTypes.size();t++)
{
final String itemType=itemTypes.elementAt(t).toUpperCase();
if(itemType.startsWith("-"))
continue;
try
{
if(q.itemGroup==null)
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
for(int i=0;i<R2.numItems();i++)
{
final Item I2=R2.getItem(i);
if((I2!=null))
{
if(itemType.equalsIgnoreCase("any"))
choices.add(I2);
else
if(CMClass.classID(I2).toUpperCase().indexOf(itemType)>=0)
choices.add(I2);
}
}
}
}
else
{
for(final Item I2 : q.itemGroup)
{
if((I2!=null))
{
if(itemType.equalsIgnoreCase("any"))
choices.add(I2);
else
if(CMClass.classID(I2).toUpperCase().indexOf(itemType)>=0)
choices.add(I2);
}
}
}
}
catch(final NoSuchElementException e)
{
}
}
for(int t=0;t<itemTypes.size();t++)
{
String itemType=itemTypes.elementAt(t);
if(!itemType.startsWith("-"))
continue;
itemType=itemType.substring(1);
for(int i=choices.size()-1;i>=0;i--)
{
final Item I2=choices.get(i);
if((CMClass.classID(I2).toUpperCase().indexOf(itemType)>=0)
||(I2.name().toUpperCase().indexOf(itemType)>=0)
||(I2.displayText().toUpperCase().indexOf(itemType)>=0))
choices.remove(I2);
}
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
if(choices.size()>0)
q.item=choices.get(CMLib.dice().roll(1,choices.size(),-1));
}
if(q.item==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !itemtype '"+p+"'.");
break;
}
questifyScriptableBehavs(q.item); // this really makes little sense, though is harmless
if(reselect)
q.reselectable.add(q.item);
if(q.room!=null)
q.room.moveItemTo(q.item,ItemPossessor.Expire.Never,ItemPossessor.Move.Followers);
else
if(q.item.owner() instanceof Room)
q.room=(Room)q.item.owner();
q.envObject=q.item;
if(q.room!=null)
{
q.area=q.room.getArea();
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
}
else
if(cmd.equals("PRESERVE"))
q.preserveState=CMath.parseIntExpression(p.elementAt(2));
else
if(cmd.equals("LOCALE")||cmd.equals("LOCALEGROUP")||cmd.equals("LOCALEGROUPAROUND"))
{
int range=0;
if(cmd.equals("LOCALE"))
{
try
{
q.room=(Room)getObjectIfSpecified(p,args,2,0);
if(q.room!=null)
{
q.area=q.room.getArea();
q.envObject=q.room;
}
continue;
}
catch(final CMException ex)
{
q.room=null;
}
}
else
if(cmd.equals("LOCALEGROUPAROUND"))
{
q.roomGroup=null;
if(p.size()<3)
continue;
range=CMath.parseIntExpression(p.elementAt(2));
if(range<=0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !localegrouparound #'"+(p.elementAt(2)+"'."));
break;
}
p.removeElementAt(2);
if(q.room==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', localegrouparound !room.");
break;
}
}
else
{
try
{
q.roomGroup=(List<Room>)getObjectIfSpecified(p,args,2,1);
q.envObject=q.roomGroup;
continue;
}
catch(final CMException ex)
{
q.roomGroup=null;
}
}
if(p.size()<3)
continue;
final Vector<String> names=new Vector<String>();
if((p.size()>3)&&(p.elementAt(2).equalsIgnoreCase("any")))
{
for(int ip=3;ip<p.size();ip++)
names.addElement(p.elementAt(ip));
}
else
names.addElement(CMParms.combine(p,2));
final List<Room> choices=new ArrayList<Room>();
List<Room> useThese=null;
if(range>0)
{
TrackingLibrary.TrackingFlags flags;
flags = CMLib.tracking().newFlags()
.plus(TrackingLibrary.TrackingFlag.AREAONLY);
useThese=CMLib.tracking().getRadiantRooms(q.room,flags,range);
}
for(int n=0;n<names.size();n++)
{
final String localeName=names.elementAt(n).toUpperCase();
try
{
final boolean addAll=(localeName.equalsIgnoreCase("any")
||localeName.equalsIgnoreCase("all"));
for(final Enumeration<Room> r=getAppropriateRoomSet(q, useThese);r.hasMoreElements();)
{
final Room R2=r.nextElement();
if(addAll||CMClass.classID(R2).toUpperCase().indexOf(localeName)>=0)
choices.add(R2);
else
{
final int dom=R2.domainType();
if((dom&Room.INDOORS)>0)
{
if(Room.DOMAIN_INDOORS_DESCS[dom-Room.INDOORS].indexOf(localeName)>=0)
choices.add(R2);
}
else
if(Room.DOMAIN_OUTDOOR_DESCS[dom].indexOf(localeName)>=0)
choices.add(R2);
}
}
}
catch(final NoSuchElementException e)
{
}
}
if(cmd.equalsIgnoreCase("LOCALEGROUP")||cmd.equalsIgnoreCase("LOCALEGROUPAROUND"))
{
if(choices.size()>0)
q.roomGroup=choices;
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !localegroup '"+CMParms.combine(p,2)+"'.");
break;
}
q.envObject=q.roomGroup;
}
else
{
if(choices.size()>0)
q.room=choices.get(CMLib.dice().roll(1,choices.size(),-1));
if(q.room==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !locale '"+CMParms.combine(p,2)+"'.");
break;
}
q.area=q.room.getArea();
q.envObject=q.room;
}
}
else
if(cmd.equals("ROOM")||cmd.equals("ROOMGROUP")||cmd.equals("ROOMGROUPAROUND"))
{
int range=0;
if(cmd.equals("ROOM"))
{
try
{
q.room=(Room)getObjectIfSpecified(p,args,2,0);
if(q.room!=null)
{
q.area=q.room.getArea();
q.envObject=q.room;
}
continue;
}
catch(final CMException ex)
{
q.room=null;
}
}
else
if(cmd.equals("ROOMGROUPAROUND"))
{
q.roomGroup=null;
if(p.size()<3)
continue;
range=CMath.s_parseIntExpression(p.elementAt(2));
if(range<=0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"' roomgrouparound #'"+(p.elementAt(2)+"'."));
break;
}
p.removeElementAt(2);
if(q.room==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', roomgrouparound !room.");
break;
}
}
else
{
try
{
q.roomGroup=(List<Room>)getObjectIfSpecified(p,args,2,1);
q.envObject=q.roomGroup;
continue;
}
catch(final CMException ex)
{
q.roomGroup=null;
}
}
if(p.size()<3)
continue;
List<Room> choices=null;
final List<Room> choices0=new Vector<Room>();
final List<Room> choices1=new Vector<Room>();
final List<Room> choices2=new Vector<Room>();
final List<Room> choices3=new Vector<Room>();
final Vector<String> names=new Vector<String>();
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if((p.size()>3)&&(p.elementAt(2).equalsIgnoreCase("any")))
{
for(int ip=3;ip<p.size();ip++)
names.addElement(p.elementAt(ip));
}
else
names.addElement(CMParms.combine(p,2));
List<Room> useThese=null;
if(range>0)
{
TrackingLibrary.TrackingFlags flags;
flags = CMLib.tracking().newFlags()
.plus(TrackingLibrary.TrackingFlag.AREAONLY);
useThese=CMLib.tracking().getRadiantRooms(q.room,flags,range);
}
for(int n=0;n<names.size();n++)
{
final String localeName=names.elementAt(n).toUpperCase();
try
{
final boolean addAll=localeName.equalsIgnoreCase("any")
||localeName.equalsIgnoreCase("all");
for(final Enumeration<Room> r=getAppropriateRoomSet(q, useThese);r.hasMoreElements();)
{
final Room R2=r.nextElement();
if(R2==null)
continue;
final String display=R2.displayText().toUpperCase();
final String desc=R2.description().toUpperCase();
if((mask!=null)&&(!CMLib.masking().maskCheck(mask,R2,true)))
continue;
if(addAll)
{
choices=choices0;
choices0.add(R2);
}
else
if(CMLib.map().getExtendedRoomID(R2).equalsIgnoreCase(localeName))
{
choices=choices0;
choices0.add(R2);
}
else
if(display.equals(localeName))
{
if((choices==null)||(choices==choices2)||(choices==choices3))
choices=choices1;
choices1.add(R2);
}
else
if(CMLib.english().containsString(display,localeName))
{
if((choices==null)||(choices==choices3))
choices=choices2;
choices2.add(R2);
}
else
if(CMLib.english().containsString(desc,localeName))
{
if(choices==null)
choices=choices3;
choices3.add(R2);
}
}
}
catch(final NoSuchElementException e)
{
}
}
if(cmd.equalsIgnoreCase("ROOMGROUP")||cmd.equalsIgnoreCase("ROOMGROUPAROUND"))
{
if((choices!=null)&&(choices.size()>0))
q.roomGroup=choices;
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !roomgroup '"+CMParms.combine(p,2)+"'.");
break;
}
q.envObject=q.roomGroup;
}
else
{
if((choices!=null)&&(choices.size()>0))
q.room=choices.get(CMLib.dice().roll(1,choices.size(),-1));
if(q.room==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !room '"+CMParms.combine(p,2)+"'.");
break;
}
q.area=q.room.getArea();
q.envObject=q.room;
}
}
else
if(cmd.equals("MOB"))
{
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
{
q.mob=null;
continue;
}
String mobName=CMParms.combine(p,2).toUpperCase();
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if(mask!=null)
mobName=CMParms.combine(p,2).toUpperCase();
try
{
q.mob=(MOB)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
q.mob=null;
List<MOB> choices=null;
final List<MOB> choices0=new Vector<MOB>();
final List<MOB> choices1=new Vector<MOB>();
final List<MOB> choices2=new Vector<MOB>();
final List<MOB> choices3=new Vector<MOB>();
if(mobName.length()==0)
mobName="ANY";
if(q.mobGroup!=null)
{
for(final MOB M2 : q.mobGroup)
{
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if(!CMLib.masking().maskCheck(mask,M2,true))
continue;
choices=sortSelect(M2,mobName,choices,choices0,choices1,choices2,choices3);
}
}
}
else
{
try
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
if(R2!=null)
{
for(int i=0;i<R2.numInhabitants();i++)
{
final MOB M2=R2.fetchInhabitant(i);
if((M2!=null)
&&(M2.isMonster())
&&((M2.amUltimatelyFollowing()==null)||(M2.amUltimatelyFollowing().isMonster())))
{
if(!CMLib.masking().maskCheck(mask,M2,true))
continue;
choices=sortSelect(M2,mobName,choices,choices0,choices1,choices2,choices3);
}
}
}
}
}
catch(final NoSuchElementException e)
{
}
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
if((choices!=null)&&(choices.size()>0))
q.mob=choices.get(CMLib.dice().roll(1,choices.size(),-1));
}
if(q.mob==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !mob '"+mobName+"'.");
break;
}
if(reselect)
q.reselectable.add(q.mob);
questifyScriptableBehavs(q.mob); // just wierd
if(q.room!=null)
q.room.bringMobHere(q.mob,false);
else
q.room=q.mob.location();
if(q.room!=null)
{
q.area=q.room.getArea();
q.envObject=q.mob;
runtimeRegisterObject(q.mob);
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
}
else
if(cmd.equals("ITEM"))
{
boolean reselect=false;
if((p.size()>2)&&(p.elementAt(2).equalsIgnoreCase("reselect")))
{
p.removeElementAt(2);
reselect=true;
}
if(p.size()<3)
{
q.item=null;
continue;
}
String itemName=CMParms.combine(p,2).toUpperCase();
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if(mask!=null)
itemName=CMParms.combine(p,2).toUpperCase();
try
{
q.item=(Item)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
q.item=null;
List<Item> choices=null;
final List<Item> choices0=new Vector<Item>();
final List<Item> choices1=new Vector<Item>();
final List<Item> choices2=new Vector<Item>();
final List<Item> choices3=new Vector<Item>();
if(itemName.trim().length()==0)
itemName="ANY";
try
{
if(q.itemGroup!=null)
{
for(final Item I2 : q.itemGroup)
{
if(I2!=null)
{
if(!CMLib.masking().maskCheck(mask,I2,true))
continue;
choices=sortSelect(I2,itemName,choices,choices0,choices1,choices2,choices3);
}
}
}
else
{
for(final Enumeration<Room> e=getAppropriateRoomSet(q);e.hasMoreElements();)
{
final Room R2=e.nextElement();
for(int i=0;i<R2.numItems();i++)
{
final Item I2=R2.getItem(i);
if(I2!=null)
{
if(!CMLib.masking().maskCheck(mask,I2,true))
continue;
choices=sortSelect(I2,itemName,choices,choices0,choices1,choices2,choices3);
}
}
}
}
}
catch(final NoSuchElementException e)
{
}
this.filterOutThoseInUse(choices, p.toString(), q, isQuiet, reselect);
if((choices!=null)&&(choices.size()>0))
q.item=choices.get(CMLib.dice().roll(1,choices.size(),-1));
}
if(q.item==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !item '"+itemName+"'.");
break;
}
if(reselect)
q.reselectable.add(q.item);
questifyScriptableBehavs(q.item); // here we go again
if(q.room!=null)
q.room.moveItemTo(q.item,ItemPossessor.Expire.Never,ItemPossessor.Move.Followers);
else
if(q.item.owner() instanceof Room)
q.room=(Room)q.item.owner();
q.envObject=q.item;
if(q.room!=null)
{
q.area=q.room.getArea();
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
}
else
if(cmd.equals("AGENT"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
try
{
q.mob=(MOB)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
if(p.size()>2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', agent syntax '"+CMParms.combine(p,2)+"'.");
break;
}
}
if(q.mob==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', agent !mob.");
break;
}
questifyScriptableBehavs(q.mob); // should be done to loaded or q-scripted mobs only
q.mysteryData.agent=q.mob;
q.mob=q.mysteryData.agent;
q.envObject=q.mob;
}
else
if(cmd.equals("FACTION"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(p.size()<3)
continue;
final String numStr=CMParms.combine(p,2);
Faction F=null;
try
{
F=(Faction)getObjectIfSpecified(p,args,2,0);
}
catch(final CMException ex)
{
if(numStr.equalsIgnoreCase("ANY"))
{
final int numFactions=CMLib.factions().numFactions();
final int whichFaction=CMLib.dice().roll(1,numFactions,-1);
int curFaction=0;
for(final Enumeration<Faction> e=CMLib.factions().factions();e.hasMoreElements();curFaction++)
{
F=e.nextElement();
if(curFaction==whichFaction)
break;
}
}
else
{
F=CMLib.factions().getFaction(numStr);
if(F==null)
F=CMLib.factions().getFactionByName(numStr);
}
}
if(F==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !faction #'"+numStr+"'.");
break;
}
q.mysteryData.faction=F;
}
else
if(cmd.equals("FACTIONGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(p.size()<3)
{
q.mysteryData.factionGroup=null;
continue;
}
try
{
q.mysteryData.factionGroup=(List<Faction>)getObjectIfSpecified(p,args,2,1);
}
catch(final CMException ex)
{
q.mysteryData.factionGroup=null;
String numStr=CMParms.combine(p,2);
Faction F=null;
if(q.mysteryData.faction!=null)
q.mysteryData.factionGroup.add(q.mysteryData.faction);
if(CMath.isMathExpression(numStr)||numStr.equalsIgnoreCase("ALL"))
{
final int numFactions=CMLib.factions().numFactions();
if(numStr.equalsIgnoreCase("ALL"))
numStr=""+numFactions;
int num=CMath.s_parseIntExpression(numStr);
if(num>=numFactions)
num=numFactions;
int tries=500;
while((q.mysteryData.factionGroup.size()<num)&&(--tries>0))
{
final int whichFaction=CMLib.dice().roll(1,numFactions,-1);
int curFaction=0;
for(final Enumeration<Faction> e=CMLib.factions().factions();e.hasMoreElements();curFaction++)
{
F=e.nextElement();
if(curFaction==whichFaction)
break;
}
if(!q.mysteryData.factionGroup.contains(F))
q.mysteryData.factionGroup.add(F);
}
}
else
{
for(int pi=2;pi<p.size();pi++)
{
F=CMLib.factions().getFaction(p.elementAt(pi));
if(F==null)
F=CMLib.factions().getFactionByName(p.elementAt(pi));
if(F==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !factiongroup '"+p.elementAt(pi)+"'.");
break;
}
if(!q.mysteryData.factionGroup.contains(F))
q.mysteryData.factionGroup.add(F);
}
if(q.error)
break;
}
}
if((q.mysteryData.factionGroup!=null)
&&(q.mysteryData.factionGroup.size()>0)
&&(q.mysteryData.faction==null))
q.mysteryData.faction=q.mysteryData.factionGroup.get(CMLib.dice().roll(1,q.mysteryData.factionGroup.size(),-1));
}
else
if(cmd.equals("AGENTGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(p.size()<3)
{
q.mysteryData.agentGroup=null;
continue;
}
try
{
q.mysteryData.agentGroup=(List<MOB>)getObjectIfSpecified(p,args,2,1);
if((q.mysteryData.agentGroup!=null)
&&(q.mysteryData.agentGroup.size()>0)
&&(q.mysteryData.agent==null))
q.mysteryData.agent=q.mysteryData.agentGroup.get(CMLib.dice().roll(1,q.mysteryData.agentGroup.size(),-1));
}
catch(final CMException ex)
{
q.mysteryData.agentGroup=null;
final String numStr=CMParms.combine(p,2).toUpperCase();
if(!CMath.isMathExpression(numStr))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !agentgroup #'"+numStr+"'.");
break;
}
if((q.mobGroup==null)||(q.mobGroup.size()==0))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !agentgroup mobgroup.");
break;
}
final List<MOB> V=new ArrayList<MOB>();
V.addAll(q.mobGroup);
q.mysteryData.agentGroup=new Vector<MOB>();
if(q.mysteryData.agent!=null)
q.mysteryData.agentGroup.add(q.mysteryData.agent);
int num=CMath.parseIntExpression(numStr);
if(num>=V.size())
num=V.size();
while((q.mysteryData.agentGroup.size()<num)&&(V.size()>0))
{
final int dex=CMLib.dice().roll(1,V.size(),-1);
final Object O=V.get(dex);
V.remove(dex);
q.mysteryData.agentGroup.add((MOB)O);
if(q.mysteryData.agent==null)
q.mysteryData.agent=(MOB)O;
}
questifyScriptableBehavs(q.mob);
}
q.mob=q.mysteryData.agent;
if(q.mysteryData.agentGroup!=null)
{
q.mobGroup=new Vector<MOB>();
q.mobGroup.addAll(q.mysteryData.agentGroup);
}
q.envObject=q.mysteryData.agentGroup;
}
else
if(cmd.equals("WHEREHAPPENEDGROUP")||cmd.equals("WHEREATGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(cmd.equals("WHEREHAPPENEDGROUP"))
{
try
{
q.mysteryData.whereHappenedGroup=(List<Room>)getObjectIfSpecified(p,args,2,1);
q.roomGroup=q.mysteryData.whereHappenedGroup;
q.mysteryData.whereHappened=((q.roomGroup==null)||(q.roomGroup.size()==0))?null:
(Room)q.roomGroup.get(CMLib.dice().roll(1,q.roomGroup.size(),-1));
q.envObject=q.mysteryData.whereHappenedGroup;
continue;
}
catch(final CMException ex)
{
q.mysteryData.whereHappenedGroup=null;
}
}
else
{
try
{
q.mysteryData.whereAtGroup=(List<Room>)getObjectIfSpecified(p,args,2,1);
q.roomGroup=q.mysteryData.whereAtGroup;
q.mysteryData.whereAt=((q.roomGroup==null)||(q.roomGroup.size()==0))?null:
(Room)q.roomGroup.get(CMLib.dice().roll(1,q.roomGroup.size(),-1));
q.envObject=q.mysteryData.whereAtGroup;
continue;
}
catch(final CMException ex)
{
q.mysteryData.whereAtGroup=null;
}
}
if(p.size()<3)
continue;
final String numStr=CMParms.combine(p,2).toUpperCase();
if(!CMath.isMathExpression(numStr))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !"+cmd.toLowerCase()+" #'"+numStr+"'.");
break;
}
if((q.roomGroup==null)||(q.roomGroup.size()==0))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !"+cmd.toLowerCase()+" roomGroup.");
break;
}
final List<Room> V=new ArrayList<Room>();
V.addAll(q.roomGroup);
final List<Room> V2=new Vector<Room>();
Room R=null;
if(cmd.equals("WHEREHAPPENEDGROUP"))
{
q.mysteryData.whereHappenedGroup=V2;
R=q.mysteryData.whereHappened;
}
else
{
q.mysteryData.whereAtGroup=null;
R=q.mysteryData.whereAt;
}
if(R!=null)
V2.add(R);
int num=CMath.parseIntExpression(numStr);
if(num>=V.size())
num=V.size();
while((V2.size()<num)&&(V.size()>0))
{
final int dex=CMLib.dice().roll(1,V.size(),-1);
final Room O=V.get(dex);
V.remove(dex);
if(!V2.contains(O))
V2.add(O);
if(R==null)
R=O;
}
q.roomGroup=new Vector<Room>();
q.roomGroup.addAll(V2);
q.room=R;
q.envObject=q.roomGroup;
if(cmd.equals("WHEREHAPPENEDGROUP"))
q.mysteryData.whereHappened=R;
else
q.mysteryData.whereAt=R;
}
else
if(cmd.equals("WHENHAPPENEDGROUP")||cmd.equals("WHENATGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
List<TimeClock> V2;
TimeClock TC=null;
if(cmd.equals("WHENHAPPENEDGROUP"))
{
try
{
q.mysteryData.whenHappenedGroup=(List<TimeClock>)getObjectIfSpecified(p,args,2,1);
V2=q.mysteryData.whenHappenedGroup;
if((V2!=null)&&(V2.size()>0))
q.mysteryData.whenHappened=V2.get(CMLib.dice().roll(1,V2.size(),-1));
continue;
}
catch(final CMException ex)
{
q.mysteryData.whenHappenedGroup=null;
}
}
else
{
try
{
q.mysteryData.whenAtGroup=(List<TimeClock>)getObjectIfSpecified(p,args,2,1);
V2=q.mysteryData.whenAtGroup;
if((V2!=null)&&(V2.size()>0))
q.mysteryData.whenAt=V2.get(CMLib.dice().roll(1,V2.size(),-1));
continue;
}
catch(final CMException ex)
{
q.mysteryData.whenAtGroup=null;
}
}
if(p.size()<3)
continue;
V2=new Vector<TimeClock>();
final TimeClock NOW=getMysteryTimeNowFromState();
if(cmd.equals("WHENHAPPENEDGROUP"))
{
q.mysteryData.whenHappenedGroup=V2;
TC=q.mysteryData.whenHappened;
}
else
{
q.mysteryData.whenAtGroup=V2;
TC=q.mysteryData.whenAt;
}
for(int pi=2;pi<p.size();pi++)
{
final String numStr=p.elementAt(pi);
if(!CMath.isMathExpression(numStr))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" !relative hour #: "+numStr+".");
break;
}
final TimeClock TC2=(TimeClock)NOW.copyOf();
TC2.tickTock(CMath.parseIntExpression(numStr));
V2.add(TC2);
}
if(q.error)
break;
if((V2.size()>0)&&(TC==null))
TC=V2.get(CMLib.dice().roll(1,V2.size(),-1));
if(cmd.equals("WHENHAPPENEDGROUP"))
q.mysteryData.whenHappened=TC;
else
q.mysteryData.whenAt=TC;
}
else
if(cmd.equals("WHENHAPPENED")
||cmd.equals("WHENAT"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(cmd.equals("WHENHAPPENED"))
{
try
{
q.mysteryData.whenHappened=(TimeClock)getObjectIfSpecified(p,args,2,0);
continue;
}
catch(final CMException ex)
{
q.mysteryData.whenHappened=null;
}
}
else
{
try
{
q.mysteryData.whenAt=(TimeClock)getObjectIfSpecified(p,args,2,0);
continue;
}
catch(final CMException ex)
{
q.mysteryData.whenAt=null;
}
}
if(p.size()<3)
continue;
final TimeClock NOW=getMysteryTimeNowFromState();
TimeClock TC=null;
final String numStr=CMParms.combine(p,2);
if(!CMath.isMathExpression(numStr))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" !relative hour #: "+numStr+".");
break;
}
TC=(TimeClock)NOW.copyOf();
TC.tickTock(CMath.parseIntExpression(numStr));
if(cmd.equals("WHENHAPPENED"))
q.mysteryData.whenHappened=TC;
else
q.mysteryData.whenAt=TC;
}
else
if(cmd.equals("MOTIVEGROUP")||cmd.equals("ACTIONGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
List<String> V2=null;
int num=-1;
if((p.size()>2)&&(CMath.isMathExpression(p.elementAt(2))))
{
num=CMath.s_parseIntExpression(p.elementAt(2));
p.removeElementAt(2);
}
if(cmd.equals("MOTIVEGROUP"))
{
try
{
q.mysteryData.motiveGroup=(List<String>)getObjectIfSpecified(p,args,2,1);
sizeDownTo(q.mysteryData.motiveGroup,num);
V2=q.mysteryData.motiveGroup;
if((V2!=null)&&(V2.size()>0))
q.mysteryData.motive=V2.get(CMLib.dice().roll(1,V2.size(),-1));
continue;
}
catch(final CMException ex)
{
q.mysteryData.motiveGroup=null;
}
}
else
{
try
{
q.mysteryData.actionGroup=(List<String>)getObjectIfSpecified(p,args,2,1);
sizeDownTo(q.mysteryData.actionGroup,num);
V2=q.mysteryData.actionGroup;
if((V2!=null)&&(V2.size()>0))
q.mysteryData.action=V2.get(CMLib.dice().roll(1,V2.size(),-1));
continue;
}
catch(final CMException ex)
{
q.mysteryData.actionGroup=null;
}
}
if(p.size()<3)
continue;
V2=new Vector<String>();
String Mstr=null;
if(cmd.equals("MOTIVEGROUP"))
{
q.mysteryData.motiveGroup=V2;
Mstr=q.mysteryData.motive;
}
else
{
q.mysteryData.actionGroup=V2;
Mstr=q.mysteryData.action;
}
if(Mstr!=null)
V2.add(Mstr);
for(int pi=2;pi<p.size();pi++)
{
if(!V2.contains(p.elementAt(pi)))
V2.add(p.elementAt(pi));
}
sizeDownTo(V2,num);
if((V2.size()>0)&&(Mstr==null))
Mstr=V2.get(CMLib.dice().roll(1,V2.size(),-1));
if(cmd.equals("MOTIVEGROUP"))
q.mysteryData.motive=Mstr;
else
q.mysteryData.action=Mstr;
}
else
if(cmd.equals("MOTIVE"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(p.size()<3)
continue;
try
{
q.mysteryData.motive=(String)getObjectIfSpecified(p,args,2,0);
continue;
}
catch(final CMException ex)
{
q.mysteryData.motive=null;
}
q.mysteryData.motive=CMParms.combine(p,2);
}
else
if(cmd.equals("ACTION"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(p.size()<3)
continue;
try
{
q.mysteryData.action=(String)getObjectIfSpecified(p,args,2,0);
continue;
}
catch(final CMException ex)
{
q.mysteryData.action=null;
}
q.mysteryData.action=CMParms.combine(p,2);
}
else
if(cmd.equals("WHEREHAPPENED")
||cmd.equals("WHEREAT"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(cmd.equals("WHEREHAPPENED"))
{
try
{
q.mysteryData.whereHappened=(Room)getObjectIfSpecified(p,args,2,0);
q.room=q.mysteryData.whereHappened;
q.envObject=q.room;
continue;
}
catch(final CMException ex)
{
q.mysteryData.whereHappened=null;
}
}
else
{
try
{
q.mysteryData.whereAt=(Room)getObjectIfSpecified(p,args,2,0);
q.room=q.mysteryData.whereAt;
q.envObject=q.room;
continue;
}
catch(final CMException ex)
{
q.mysteryData.whereAt=null;
}
}
if(p.size()>2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" syntax '"+CMParms.combine(p,2)+"'.");
break;
}
if(q.room==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" !room.");
break;
}
if(cmd.equals("WHEREHAPPENED"))
q.mysteryData.whereHappened=q.room;
else
q.mysteryData.whereAt=q.room;
q.envObject=q.room;
}
else
if(cmd.equals("TARGETGROUP")
||cmd.equals("TOOLGROUP"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
List<?> V2=null;
if(cmd.equals("TARGETGROUP"))
{
try
{
q.mysteryData.targetGroup=(List<Environmental>)getObjectIfSpecified(p,args,2,1);
V2=q.mysteryData.targetGroup;
if((V2!=null)&&(V2.size()>0))
{
if(V2.get(0) instanceof MOB)
{
q.mobGroup=(List<MOB>)V2;
q.mob=(MOB)V2.get(CMLib.dice().roll(1,V2.size(),-1));
q.envObject=q.mobGroup;
q.mysteryData.target=q.mob;
}
if(V2.get(0) instanceof Item)
{
q.itemGroup=(List<Item>)V2;
q.item=(Item)V2.get(CMLib.dice().roll(1,V2.size(),-1));
q.mysteryData.target=q.item;
q.envObject=q.itemGroup;
}
}
continue;
}
catch(final CMException ex)
{
q.mysteryData.targetGroup=null;
}
}
else
{
try
{
q.mysteryData.toolGroup=(List<Environmental>)getObjectIfSpecified(p,args,2,1);
V2=q.mysteryData.toolGroup;
if((V2!=null)&&(V2.size()>0))
{
if(V2.get(0) instanceof MOB)
{
q.mobGroup=(List<MOB>)V2;
q.mob=(MOB)V2.get(CMLib.dice().roll(1,V2.size(),-1));
q.envObject=q.mobGroup;
q.mysteryData.tool=q.mob;
}
if(V2.get(0) instanceof Item)
{
q.itemGroup=(List<Item>)V2;
q.item=(Item)V2.get(CMLib.dice().roll(1,V2.size(),-1));
q.envObject=q.itemGroup;
q.mysteryData.tool=q.item;
}
}
continue;
}
catch(final CMException ex)
{
q.mysteryData.toolGroup=null;
}
}
if(p.size()<3)
continue;
final String numStr=CMParms.combine(p,2).toUpperCase();
if(!CMath.isMathExpression(numStr))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !"+cmd.toLowerCase()+" #'"+numStr+"'.");
break;
}
if(((q.mobGroup==null)||(q.mobGroup.size()==0))
&&((q.itemGroup==null)||(q.itemGroup.size()==0)))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', !"+cmd.toLowerCase()+" mobgroup itemgroup.");
break;
}
final List<Environmental> V=new ArrayList<Environmental>();
if((q.mobGroup!=null)&&(q.mobGroup.size()>0))
V.addAll(q.mobGroup);
else
V.addAll(q.itemGroup);
V2=new Vector<Environmental>();
Environmental finalE=null;
if(cmd.equals("TARGETGROUP"))
{
q.mysteryData.targetGroup=(List<Environmental>)V2;
finalE=q.mysteryData.target;
}
else
{
q.mysteryData.toolGroup=(List<Environmental>)V2;
finalE=q.mysteryData.tool;
}
if(finalE!=null)
((List<Environmental>)V2).add(finalE);
int num=CMath.parseIntExpression(numStr);
if(num>=V.size())
num=V.size();
Object O;
while((V2.size()<num)&&(V.size()>0))
{
final int dex=CMLib.dice().roll(1,V.size(),-1);
O=V.get(dex);
V.remove(dex);
if(!V2.contains(O))
((List<Object>)V2).add(O);
if(finalE==null)
finalE=(Environmental)O;
}
if(finalE instanceof MOB)
{
q.mobGroup=new Vector<MOB>();
q.mobGroup.addAll((List<MOB>)V2);
q.mob=(MOB)finalE;
questifyScriptableBehavs(q.mob); // i just dont get it
}
else
if(finalE instanceof Item)
{
q.itemGroup=new Vector<Item>();
q.itemGroup.addAll((List<Item>)V2);
q.item=(Item)finalE;
questifyScriptableBehavs(q.item);
}
q.envObject=V2;
if(cmd.equals("TARGETGROUP"))
q.mysteryData.target=finalE;
else
q.mysteryData.tool=finalE;
}
else
if(cmd.equals("TARGET")
||cmd.equals("TOOL"))
{
if(q.mysteryData==null)
q.mysteryData=new MysteryData();
if(cmd.equals("TARGET"))
{
try
{
q.mysteryData.target=(Environmental)getObjectIfSpecified(p,args,2,0);
if(q.mysteryData.target instanceof MOB)
q.mob=(MOB)q.mysteryData.target;
if(q.mysteryData.target instanceof Item)
q.item=(Item)q.mysteryData.target;
q.envObject=q.mysteryData.target;
continue;
}
catch(final CMException ex)
{
q.mysteryData.target=null;
}
}
else
{
try
{
q.mysteryData.tool=(Environmental)getObjectIfSpecified(p,args,2,0);
if(q.mysteryData.tool instanceof MOB)
q.mob=(MOB)q.mysteryData.tool;
if(q.mysteryData.tool instanceof Item)
q.item=(Item)q.mysteryData.tool;
q.envObject=q.mysteryData.tool;
continue;
}
catch(final CMException ex)
{
q.mysteryData.tool=null;
}
}
if(p.size()>2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" syntax '"+CMParms.combine(p,2)+"'.");
break;
}
if((q.envObject instanceof List)
&&(((List<Object>)q.envObject).size()>0)
&&(((List<Object>)q.envObject).get(0) instanceof Environmental))
q.envObject=((List<Object>)q.envObject).get(CMLib.dice().roll(1,((List<Object>)q.envObject).size(),-1));
if(!(q.envObject instanceof Environmental))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', "+cmd.toLowerCase()+" !object.");
break;
}
if(cmd.equals("TARGET"))
q.mysteryData.target=(Environmental)q.envObject;
else
q.mysteryData.tool=(Environmental)q.envObject;
if(q.envObject instanceof MOB)
{
q.mob=(MOB)q.envObject;
questifyScriptableBehavs(q.mob); // useless, but harmless
}
else
if(q.envObject instanceof Item)
{
q.item=(Item)q.envObject;
questifyScriptableBehavs(q.item);
}
}
else
if(!isStat(cmd))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown variable '"+cmd+"'.");
break;
}
}
else
if(cmd.equals("IMPORT"))
{
if(p.size()<2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no IMPORT type.");
break;
}
cmd=p.elementAt(1).toUpperCase();
if(cmd.equals("MOBS"))
{
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no IMPORT MOBS file.");
break;
}
final StringBuffer buf=getResourceFileData(CMParms.combine(p,2), true);
if((buf==null)||(buf.length()<20))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',Unknown XML file: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
if(buf.substring(0,20).indexOf("<MOBS>")<0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', Invalid XML file: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
q.loadedMobs=new Vector<MOB>();
final String errorStr=CMLib.coffeeMaker().addMOBsFromXML(buf.toString(),q.loadedMobs,null);
if(errorStr.length()>0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',Error on import of: '"+CMParms.combine(p,2)+"' for '"+name()+"': "+errorStr+".");
break;
}
if(q.loadedMobs.size()<=0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',No mobs loaded: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
for(final MOB M : q.loadedMobs)
{
M.basePhyStats().setRejuv(PhyStats.NO_REJUV);
M.basePhyStats().setDisposition(M.basePhyStats().disposition()|PhyStats.IS_UNSAVABLE);
M.recoverPhyStats();
M.text();
CMLib.threads().deleteAllTicks(M);
}
}
else
if(cmd.equals("ITEMS"))
{
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no import filename!");
break;
}
final StringBuffer buf=getResourceFileData(CMParms.combine(p,2), true);
if((buf==null)||(buf.length()<20))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',Unknown XML file: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
if(buf.substring(0,20).indexOf("<ITEMS>")<0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',Invalid XML file: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
q.loadedItems=new Vector<Item>();
final String errorStr=CMLib.coffeeMaker().addItemsFromXML(buf.toString(),q.loadedItems,null);
if(errorStr.length()>0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',Error on import of: '"+CMParms.combine(p,2)+"' for '"+name()+"': "+errorStr+".");
break;
}
if(q.loadedItems.size()<=0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"',No items loaded: '"+CMParms.combine(p,2)+"' for '"+name()+"'.");
break;
}
for(final Item I : q.loadedItems)
{
I.basePhyStats().setRejuv(PhyStats.NO_REJUV);
I.basePhyStats().setDisposition(I.basePhyStats().disposition()|PhyStats.IS_UNSAVABLE);
I.recoverPhyStats();
I.text();
CMLib.threads().deleteTick(I,Tickable.TICKID_ITEM_BEHAVIOR);
}
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown import type '"+cmd+"'.");
break;
}
}
else
if(cmd.startsWith("LOAD="))
{
final boolean error=q.error;
final List<Object> args2=new Vector<Object>();
parseQuestScriptWArgs(parseLoadScripts(s,args,args2,true),args2);
if((!error)&&(q.error))
break;
}
else
if(cmd.equals("LOAD"))
{
if(p.size()<2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unfound type on load.");
break;
}
cmd=p.elementAt(1).toUpperCase();
if(cmd.equals("MOB")||cmd.equals("MOBGROUP"))
{
if(q.loadedMobs.size()==0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot load mob, no mobs imported.");
break;
}
int maxToLoad=Integer.MAX_VALUE;
if((p.size()>2)&&(CMath.isMathExpression(p.elementAt(2))))
{
maxToLoad=CMath.parseIntExpression(p.elementAt(2));
p.removeElementAt(2);
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no mob name to load!");
break;
}
String mobName=CMParms.combine(p,2);
final String maskStr=CMLib.quests().breakOutMaskString(s,p);
final MaskingLibrary.CompiledZMask mask=(maskStr.trim().length()==0)?null:CMLib.masking().maskCompile(maskStr);
if(mask!=null)
mobName=CMParms.combine(p,2).toUpperCase();
if(mobName.length()==0)
mobName="ANY";
final boolean addAll=mobName.equalsIgnoreCase("ALL")
||mobName.equalsIgnoreCase("ANY");
final List<MOB> choices=new ArrayList<MOB>(); // ok because is wholly temporary
for(int i=0;i<q.loadedMobs.size();i++)
{
final MOB M2=q.loadedMobs.get(i);
if((CMLib.masking().maskCheck(mask,M2,true))
&&(addAll
||(CMLib.english().containsString(M2.name(),mobName))
||(CMLib.english().containsString(M2.displayText(),mobName))
||(CMLib.english().containsString(M2.description(),mobName))))
choices.add((MOB)M2.copyOf());
}
if(choices.size()==0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no mob found to load '"+mobName+"'!");
break;
}
final List<MOB> mobsToDo=new Vector<MOB>(); // must remain vector for thread safety
if(cmd.equalsIgnoreCase("MOB"))
mobsToDo.add(choices.get(CMLib.dice().roll(1,choices.size(),-1)));
else
{
mobsToDo.addAll(choices);
q.mobGroup=mobsToDo;
}
while((mobsToDo.size()>maxToLoad)&&(maxToLoad>0))
mobsToDo.remove(CMLib.dice().roll(1,mobsToDo.size(),-1));
while((mobsToDo.size()<maxToLoad)&&(maxToLoad>0)&&(maxToLoad<Integer.MAX_VALUE))
mobsToDo.add((MOB)mobsToDo.get(CMLib.dice().roll(1,mobsToDo.size(),-1)).copyOf());
final Room choiceRoom=q.room;
for(int m=0;m<mobsToDo.size();m++)
{
q.mob=mobsToDo.get(m);
q.room=choiceRoom;
if(q.room==null)
{
if(q.roomGroup!=null)
q.room=q.roomGroup.get(CMLib.dice().roll(1,q.roomGroup.size(),-1));
else
if(q.area!=null)
q.room=q.area.getRandomMetroRoom();
else
q.room=CMLib.map().getRandomRoom();
}
if(q.room!=null)
{
q.mob.setStartRoom(null);
q.mob.basePhyStats().setRejuv(PhyStats.NO_REJUV);
q.mob.basePhyStats().setDisposition(q.mob.basePhyStats().disposition()|PhyStats.IS_UNSAVABLE);
q.mob.recoverPhyStats();
q.mob.text();
q.mob.bringToLife(q.room,true);
}
questifyScriptableBehavs(q.mob);
runtimeRegisterObject(q.mob);
if(q.room!=null)
{
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
if(q.mob!=null)
q.mob.setStartRoom(null); // necessary to tell qm to clean him UP!
}
q.envObject=mobsToDo;
if(q.room!=null)
q.area=q.room.getArea();
}
else
if(cmd.equals("ITEM")||cmd.equals("ITEMGROUP"))
{
if(q.loadedItems.size()==0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot load item, no items imported.");
break;
}
int maxToLoad=Integer.MAX_VALUE;
if((p.size()>2)&&(CMath.isMathExpression(p.elementAt(2))))
{
maxToLoad=CMath.parseIntExpression(p.elementAt(2));
p.removeElementAt(2);
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no item name to load!");
break;
}
final String itemName=CMParms.combine(p,2);
final List<Item> choices=new ArrayList<Item>(); // only ever picked from locally
for(int i=0;i<q.loadedItems.size();i++)
{
final Item I2=q.loadedItems.get(i);
if((itemName.equalsIgnoreCase("any"))
||(CMLib.english().containsString(I2.name(),itemName))
||(CMLib.english().containsString(I2.displayText(),itemName))
||(CMLib.english().containsString(I2.description(),itemName)))
{
final Item I3=(Item)I2.copyOf();
CMLib.threads().deleteTick(I3,Tickable.TICKID_ITEM_BEHAVIOR);
choices.add(I3);
}
}
if(choices.size()==0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', no item found to load '"+itemName+"'!");
break;
}
final List<Item> itemsToDo=new Vector<Item>(); // for thread safety, as this is global
if(cmd.equalsIgnoreCase("ITEM"))
itemsToDo.add(choices.get(CMLib.dice().roll(1,choices.size(),-1)));
else
{
itemsToDo.addAll(choices);
q.itemGroup=itemsToDo;
}
while((itemsToDo.size()>maxToLoad)&&(maxToLoad>0))
itemsToDo.remove(CMLib.dice().roll(1,itemsToDo.size(),-1));
while((itemsToDo.size()<maxToLoad)&&(maxToLoad>0)&&(maxToLoad<Integer.MAX_VALUE))
{
final Item I3=(Item)(itemsToDo.get(CMLib.dice().roll(1,itemsToDo.size(),-1))).copyOf();
CMLib.threads().deleteTick(I3,Tickable.TICKID_ITEM_BEHAVIOR);
itemsToDo.add(I3);
}
final Room choiceRoom=q.room;
for(int m=0;m<itemsToDo.size();m++)
{
q.item=itemsToDo.get(m);
q.room=choiceRoom;
if(q.room==null)
{
if(q.roomGroup!=null)
q.room=q.roomGroup.get(CMLib.dice().roll(1,q.roomGroup.size(),-1));
else
if(q.area!=null)
q.room=q.area.getRandomMetroRoom();
else
q.room=CMLib.map().getRandomRoom();
}
if(q.room!=null)
{
q.item.basePhyStats().setRejuv(PhyStats.NO_REJUV);
q.item.basePhyStats().setDisposition(q.item.basePhyStats().disposition()|PhyStats.IS_UNSAVABLE);
q.item.recoverPhyStats();
q.item.text();
q.room.addItem(q.item);
q.room.recoverRoomStats();
q.room.showHappens(CMMsg.MSG_OK_ACTION,null);
}
questifyScriptableBehavs(q.item);
runtimeRegisterObject(q.item);
}
if(q.room!=null)
q.area=q.room.getArea();
q.envObject=itemsToDo;
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown load type '"+cmd+"'.");
break;
}
}
else
if(cmd.equals("GIVE"))
{
if(p.size()<2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unfound type on give.");
break;
}
cmd=p.elementAt(1).toUpperCase();
if(cmd.equals("FOLLOWER"))
{
if(q.mob==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give follower, no mob set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give follower, follower name not given.");
break;
}
final String mobName=CMParms.combine(p,2);
final List<MOB> choices=new ArrayList<MOB>(); // only ever picked from locally
ReverseEnumeration<PreservedQuestObject> e;
for(e=new ReverseEnumeration<PreservedQuestObject>(q.worldObjects);e.hasMoreElements();)
{
final PreservedQuestObject PO=e.nextElement();
if((PO.obj!=q.mob)&&(PO.obj instanceof MOB))
{
final MOB M2=(MOB)PO.obj;
if((mobName.equalsIgnoreCase("any"))
||(CMLib.english().containsString(M2.name(),mobName))
||(CMLib.english().containsString(M2.displayText(),mobName))
||(CMLib.english().containsString(M2.description(),mobName)))
choices.add(M2);
}
}
if(choices.size()==0)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give follower, no mobs called '"+mobName+"' previously set in script.");
break;
}
final MOB M2=choices.get(CMLib.dice().roll(1,choices.size(),-1));
M2.setFollowing(q.mob);
}
else
if(cmd.equals("ITEM")||(cmd.equalsIgnoreCase("ITEMS")))
{
if((q.item==null)&&(q.itemGroup==null)&&(q.loadedItems==null))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give item(s), no item(s) set or loaded.");
break;
}
if((q.mob==null)&&(q.mobGroup==null))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give item(s), no mob set.");
break;
}
if(p.size()>2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give item(s), parameter unnecessarily given: '"+CMParms.combine(p,2)+"'.");
break;
}
final List<MOB> toSet=new Vector<MOB>();
if(q.mob!=null)
toSet.add(q.mob);
else
if(q.mobGroup!=null)
toSet.addAll(q.mobGroup);
final List<Item> itemSet=new Vector<Item>();
if(q.item!=null)
itemSet.add(q.item);
else
if(q.itemGroup!=null)
itemSet.addAll(q.itemGroup);
else
if(q.loadedItems!=null)
itemSet.addAll(q.loadedItems);
for(int i=0;i<toSet.size();i++)
{
final MOB M2=toSet.get(i);
runtimeRegisterObject(M2);
if(cmd.equals("ITEMS"))
{
for(int i3=0;i3<itemSet.size();i3++)
{
Item I3=itemSet.get(i3);
if(q.item==I3)
{
M2.moveItemTo(I3);
questifyScriptableBehavs(q.item);
q.item=(Item)q.item.copyOf();
questifyScriptableBehavs(q.item);
CMLib.threads().deleteTick(q.item, Tickable.TICKID_ITEM_BEHAVIOR); // because it may not be used
q.item.setOwner(null); // because the item copy is definitely nowhere
}
else
{
questifyScriptableBehavs(I3);
CMLib.threads().deleteTick(I3, Tickable.TICKID_ITEM_BEHAVIOR); // because it may not be used??
I3=(Item)I3.copyOf();
questifyScriptableBehavs(I3);
I3.setOwner(null); // because the i3 copy is nowhere
M2.moveItemTo(I3);
}
}
}
else
if(cmd.equals("ITEM"))
{
Item I3=itemSet.get(CMLib.dice().roll(1,itemSet.size(),-1));
questifyScriptableBehavs(I3);
if(q.item==I3)
{
M2.moveItemTo(I3);
q.item=(Item)q.item.copyOf();
q.item.setOwner(null);// because the copy is nowhere
questifyScriptableBehavs(q.item);
CMLib.threads().deleteTick(q.item, Tickable.TICKID_ITEM_BEHAVIOR); // because it may not be used
}
else
{
CMLib.threads().deleteTick(I3, Tickable.TICKID_ITEM_BEHAVIOR); // because it may not be used
I3=(Item)I3.copyOf();
I3.setOwner(null);// because the copy is nowhere
questifyScriptableBehavs(I3);
M2.moveItemTo(I3);
}
}
}
}
else
if(cmd.equals("ABILITY"))
{
if((q.mob==null)&&(q.mobGroup==null))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give ability, no mob set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give ability, ability name not given.");
break;
}
final Ability A3=CMClass.findAbility(p.elementAt(2));
if(A3==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give ability, ability name unknown '"+(p.elementAt(2))+".");
break;
}
final List<MOB> toSet=new Vector<MOB>();
if(q.mob!=null)
toSet.add(q.mob);
else
if(q.mobGroup!=null)
toSet.addAll(q.mobGroup);
for(int i=0;i<toSet.size();i++)
{
final MOB M2=toSet.get(i);
runtimeRegisterAbility(M2,A3.ID(),CMParms.combineQuoted(p,3),true);
}
}
else
if(cmd.equals("BEHAVIOR"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give behavior, no mob or item set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give behavior, behavior name not given.");
break;
}
final Behavior B=CMClass.getBehavior(p.elementAt(2));
if(B==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give behavior, behavior name unknown '"+(p.elementAt(2))+".");
break;
}
List<Object> toSet=new Vector<Object>();
if(q.envObject instanceof List)
toSet=(List<Object>)q.envObject;
else
if(q.envObject!=null)
toSet.add(q.envObject);
for(int i=0;i<toSet.size();i++)
{
final Environmental E2=(Environmental)toSet.get(i);
if(E2 instanceof PhysicalAgent)
runtimeRegisterBehavior((PhysicalAgent)E2,B.ID(),CMParms.combineQuoted(p,3),true);
if((E2 instanceof Item)
&&((((Item)E2).owner()==null)
||(!((Item)E2).owner().isContent((Item)E2))))
CMLib.threads().deleteTick(E2, Tickable.TICKID_ITEM_BEHAVIOR);
}
}
else
if(cmd.equals("STAT"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give stat, no mob or item set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give stat, stat name not given.");
break;
}
final String stat=p.elementAt(2);
final String val=CMParms.combineQuoted(p,3);
List<Environmental> toSet=new Vector<Environmental>();
if(q.envObject instanceof List)
toSet=(List<Environmental>)q.envObject;
else
if(q.envObject!=null)
toSet.add((Environmental)q.envObject);
for(int i=0;i<toSet.size();i++)
{
final Environmental E2=toSet.get(i);
if(stat.equalsIgnoreCase("KEYPLAYER") && (E2 instanceof Physical))
{
final Ability A=((Physical)E2).fetchEffect("QuestBound");
if(A!=null)
A.setStat("KEY",val);
}
else
runtimeRegisterStat(E2,stat,val,true);
}
}
else
if(cmd.equals("SCRIPT"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give script, no object set.");
break;
}
boolean proceed=true;
boolean savable=false;
String word=null;
String scope=CMStrings.replaceAll(name()," ","_").toUpperCase().trim();
while(proceed&&(p.size()>2))
{
word=p.elementAt(2);
proceed=false;
if(word.equalsIgnoreCase("SAVABLE"))
{
savable=true;
proceed=true;
}
else
if(word.equalsIgnoreCase("GLOBAL"))
{
scope="";
proceed=true;
}
else
if(word.equalsIgnoreCase("INDIVIDUAL")||word.equals("*"))
{
scope="*";
proceed=true;
}
if(proceed)
p.removeElementAt(2);
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give script, script not given.");
break;
}
final String val=CMParms.combineQuoted(p,2);
List<Environmental> toSet=new Vector<Environmental>();
if(q.envObject instanceof List)
toSet=(List<Environmental>)q.envObject;
else
if(q.envObject!=null)
toSet.add((Environmental)q.envObject);
for(int i=0;i<toSet.size();i++)
{
final Environmental E2=toSet.get(i);
if(E2 instanceof PhysicalAgent)
{
final ScriptingEngine S=(ScriptingEngine)CMClass.getCommon("DefaultScriptingEngine");
S.setSavable(savable);
S.registerDefaultQuest(name());
S.setVarScope(scope);
S.setScript(val);
((PhysicalAgent)E2).addScript(S);
runtimeRegisterObject(((PhysicalAgent)E2));
if((E2 instanceof Item)
&&((((Item)E2).owner()==null)
||(!((Item)E2).owner().isContent((Item)E2))))
CMLib.threads().deleteTick(E2, Tickable.TICKID_ITEM_BEHAVIOR); //OMG WHY?!?!/????!!
synchronized(questState)
{
questState.addons.addElement(new XVector<Object>(E2,S),Integer.valueOf(questState.preserveState));
}
}
}
}
else
if(cmd.equals("AFFECT"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give Effect, no mob, room or item set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give Effect, ability name not given.");
break;
}
final Ability A3=CMClass.findAbility(p.elementAt(2));
if(A3==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot give Effect, ability name unknown '"+(p.elementAt(2))+".");
break;
}
List<Object> toSet=new Vector<Object>();
if(q.envObject instanceof List)
toSet=(List<Object>)q.envObject;
else
if(q.envObject!=null)
toSet.add(q.envObject);
for(final Object o : toSet)
{
if(o instanceof PhysicalAgent)
runtimeRegisterEffect((PhysicalAgent)o,A3.ID(),CMParms.combineQuoted(p,3),true);
}
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown give type '"+cmd+"'.");
break;
}
}
else
if(cmd.equals("TAKE"))
{
if(p.size()<2)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unfound type on take.");
break;
}
cmd=p.elementAt(1).toUpperCase();
if(cmd.equals("ABILITY"))
{
if((q.mob==null)&&(q.mobGroup==null))
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take ability, no mob set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take ability, ability name not given.");
break;
}
final Ability A3=CMClass.findAbility(p.elementAt(2));
if(A3==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take ability, ability name unknown '"+(p.elementAt(2))+".");
break;
}
final List<MOB> toSet=new Vector<MOB>();
if(q.mob!=null)
toSet.add(q.mob);
else
if(q.mobGroup!=null)
toSet.addAll(q.mobGroup);
for(int i=0;i<toSet.size();i++)
{
final MOB M2=toSet.get(i);
runtimeRegisterAbility(M2,A3.ID(),CMParms.combineQuoted(p,3),false);
}
}
else
if(cmd.equals("BEHAVIOR"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take behavior, no mob or item set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take behavior, behavior name not given.");
break;
}
final Behavior B=CMClass.getBehavior(p.elementAt(2));
if(B==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take behavior, behavior name unknown '"+(p.elementAt(2))+".");
break;
}
List<Object> toSet=new Vector<Object>();
if(q.envObject instanceof List)
toSet=(List<Object>)q.envObject;
else
if(q.envObject!=null)
toSet.add(q.envObject);
for(int i=0;i<toSet.size();i++)
{
final Environmental E2=(Environmental)toSet.get(i);
if(E2 instanceof PhysicalAgent)
runtimeRegisterBehavior((PhysicalAgent)E2,B.ID(),CMParms.combineQuoted(p,3),false);
if((E2 instanceof Item)
&&((((Item)E2).owner()==null)
||(!((Item)E2).owner().isContent((Item)E2))))
CMLib.threads().deleteTick(E2, Tickable.TICKID_ITEM_BEHAVIOR);
}
}
else
if(cmd.equals("AFFECT"))
{
if(q.envObject==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take Effect, no mob, room or item set.");
break;
}
if(p.size()<3)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take Effect, ability name not given.");
break;
}
final Ability A3=CMClass.findAbility(p.elementAt(2));
if(A3==null)
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', cannot take Effect, ability name unknown '"+(p.elementAt(2))+".");
break;
}
List<Object> toSet=new Vector<Object>();
if(q.envObject instanceof List)
toSet=(List<Object>)q.envObject;
else
if(q.envObject!=null)
toSet.add(q.envObject);
for(final Object o : toSet)
{
if(o instanceof PhysicalAgent)
runtimeRegisterEffect((PhysicalAgent)o,A3.ID(),CMParms.combineQuoted(p,3),false);
}
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown take type '"+cmd+"'.");
break;
}
}
else
{
errorOccurred(q,isQuiet,"Quest '"+name()+"', unknown command '"+cmd+"'.");
break;
}
q.done=true;
}
}
}
public boolean spawnQuest(final String script, final List<?> baseVars, final boolean reTime)
{
final DefaultQuest Q2=(DefaultQuest)CMClass.getCommon("DefaultQuest");
Q2.setCopy(true);
Q2.setVars(baseVars,0);
Q2.setScript(script,true);
Quest Q=CMLib.quests().fetchQuest(Q2.name());
int append=1;
while((Q!=null)&&(Q!=Q2))
{
Q2.setName(name()+"#"+append);
append++;
Q=CMLib.quests().fetchQuest(Q2.name());
}
CMLib.quests().addQuest(Q2);
if(reTime)
{
Long ellapsed=stepEllapsedTimes.get(script);
if(ellapsed==null)
ellapsed=Long.valueOf(0);
stepEllapsedTimes.remove(script);
ellapsed=Long.valueOf(ellapsed.longValue()+(System.currentTimeMillis()-lastStartDateTime));
stepEllapsedTimes.put(script,ellapsed);
Q2.resetWaitRemaining(ellapsed.longValue());
if(Q2.startQuestOnTime())
{
stepEllapsedTimes.remove(script);
return true;
}
}
else
if(Q2.startQuestInternal())
return true;
Q2.enterDormantState();
return false;
}
@Override
public boolean startQuest()
{
if((!running())&&(!isCopy()))
CMLib.coffeeTables().bump(this,CoffeeTableRow.STAT_QUESTSTARTATTEMPT);
return startQuestInternal();
}
// this will execute the quest script. If the quest is running, it
// will call stopQuestInternal first to shut it down.
public boolean startQuestInternal()
{
if(running())
{
stopQuestInternal();
resetData=null;
}
final List<Object> args=new Vector<Object>();
questState=new QuestState();
final List<Object> baseScript=parseLoadScripts(script(),new Vector<Object>(),args,true);
if((!isCopy())&&(getSpawn()!=SPAWN_NO))
{
if(getSpawn()==SPAWN_FIRST)
spawnQuest(script(),baseScript,false);
else
if(getSpawn()==SPAWN_ANY)
{
final List<String> parsed=CMLib.quests().parseQuestSteps(parseFinalQuestScript(baseScript),0,false);
for(int p=0;p<parsed.size();p++)
spawnQuest(parsed.get(p),baseScript,true);
}
lastStartDateTime=System.currentTimeMillis();
enterDormantState();
return false; // always return false, since, per se, this quest is NOT started.
}
try
{
parseQuestScript(baseScript,args,0);
}
catch(final Exception t)
{
questState.error=true;
Log.errOut("DefaultQuest",t);
}
if(questState.error)
{
if(!questState.beQuiet)
{
int retry=0;
if((durable)&&(resetData==null))
retry=10;
else
if(resetData!=null)
retry=resetData[0];
Log.errOut("Quest","Errors starting '"
+name()
+"', quest not started"
+((retry>0)?", retry in "+retry+".":"."));
}
if((durable)&&(resetData==null))
{
resetQuest(10);
return false;
}
CMLib.coffeeTables().bump(this,CoffeeTableRow.STAT_QUESTFAILEDSTART);
}
else
if(!questState.done)
Log.errOut("Quest","Nothing parsed in '"+name()+"', quest not started.");
else
if(duration()<0)
{
Log.errOut("Quest","No duration, quest '"+name()+"' not started.");
questState.error=true;
}
if((!questState.error)&&(questState.done))
{
enterRunningState();
return true;
}
stopQuestInternal();
return false;
}
public void enterRunningState()
{
if(duration()>=0)
{
waitRemaining=-1;
if(duration()==0)
ticksRemaining=1;
else
if((resetData!=null)&&(resetData[1]>0))
ticksRemaining=resetData[1];
else
ticksRemaining=duration();
CMLib.threads().startTickDown(this,Tickable.TICKID_QUEST,1);
}
resetData=null;
lastStartDateTime=System.currentTimeMillis();
stepEllapsedTimes.remove(script());
}
public void cleanQuestStep()
{
stoppingQuest=true;
if(questState.worldObjects.size()>0)
{
synchronized(questState)
{
Enumeration<PreservedQuestObject> e;
PreservedQuestObject PO;
for(e=new ReverseEnumeration<PreservedQuestObject>(questState.worldObjects);e.hasMoreElements();)
{
PO=e.nextElement();
if(PO.preserveState>0)
{
PO.preserveState--;
continue;
}
questState.worldObjects.remove(PO);
if(PO.preserveState == Integer.MIN_VALUE)
continue;
PO.preserveState=Integer.MIN_VALUE;
final PhysicalAgent P=PO.obj;
if(P != null)
{
final Ability A=P.fetchEffect("QuestBound");
if(A!=null)
P.delEffect(A);
if(P instanceof Item)
{
if((CMath.bset(P.basePhyStats().disposition(),PhyStats.IS_UNSAVABLE))
&&(!((Item)P).amDestroyed()))
((Item)P).destroy();
}
else
if(P instanceof MOB)
{
final MOB M=(MOB)P;
final ScriptingEngine B=(ScriptingEngine)M.fetchBehavior("Scriptable");
if(B!=null)
B.endQuest(M,M,name());
final Room R=M.getStartRoom();
if((R==null)||(CMath.bset(M.basePhyStats().disposition(),PhyStats.IS_UNSAVABLE)))
{
M.setFollowing(null);
CMLib.tracking().wanderAway(M,true,false);
if(M.location()!=null)
M.location().delInhabitant(M);
M.setLocation(null);
M.destroy();
}
else
if((!M.amDead())
&&(!M.amDestroyed())
&&((M.location()!=R)||(!R.isInhabitant(M))))
{
M.setFollowing(null);
CMLib.tracking().wanderAway(M,false,true);
}
}
}
}
}
if((questState.addons.size()>0)
&&(stoppingQuest))
{
synchronized(questState)
{
for(int i=questState.addons.size()-1;i>=0;i--)
{
try
{
final Integer I=(Integer)questState.addons.elementAt(i,2);
if(I.intValue()>0)
{
questState.addons.setElementAt(i,2,Integer.valueOf(I.intValue()-1));
continue;
}
@SuppressWarnings("unchecked")
final List<Object> V=(List<Object>)questState.addons.elementAt(i,1);
questState.addons.removeElementAt(i);
if(V.size()<2)
continue;
final Environmental E=(Environmental)V.get(0);
final Object O=V.get(1);
if(O instanceof String)
{
final String stat=(String)O;
final String parms=(String)V.get(2);
if(CMStrings.contains(E.getStatCodes(),stat.toUpperCase().trim()))
E.setStat(stat,parms);
else
if((E instanceof MOB)&&CMStrings.contains(((Physical)E).basePhyStats().getStatCodes(),stat.toUpperCase().trim()))
{
((Physical)E).basePhyStats().setStat(stat.toUpperCase().trim(),parms);
((Physical)E).recoverPhyStats();
}
else
if((E instanceof MOB)&&(CMStrings.contains(CharStats.CODES.NAMES(),stat.toUpperCase().trim())))
{
((MOB)E).baseCharStats().setStat(CMParms.indexOf(CharStats.CODES.NAMES(),stat.toUpperCase().trim()),CMath.s_int(parms));
((MOB)E).recoverCharStats();
}
else
if((E instanceof MOB)&&CMStrings.contains(((MOB)E).baseState().getStatCodes(),stat))
{
((MOB)E).baseState().setStat(stat,parms);
((MOB)E).recoverMaxState();
((MOB)E).resetToMaxState();
}
}
else
if(O instanceof Behavior)
{
if(E instanceof PhysicalAgent)
{
final PhysicalAgent BB=(PhysicalAgent)E;
Behavior B=BB.fetchBehavior(((Behavior)O).ID());
if((E instanceof MOB)&&(B instanceof ScriptingEngine))
((ScriptingEngine)B).endQuest((PhysicalAgent)E,(MOB)E,name());
if((V.size()>2)&&(V.get(2) instanceof String))
{
if(B==null)
{
B=(Behavior)O;
BB.addBehavior(B);
}
B.setParms((String)V.get(2));
}
else
if(B!=null)
BB.delBehavior(B);
}
}
else
if(O instanceof ScriptingEngine)
{
final ScriptingEngine S=(ScriptingEngine)O;
if(!S.isSavable())
{
if(E instanceof MOB)
S.endQuest((PhysicalAgent)E,(MOB)E,name());
else
{
final MOB M=CMClass.getFactoryMOB(E.Name(), 1, CMLib.map().roomLocation(E));
S.endQuest((PhysicalAgent)E,M,name());
M.destroy();
}
((PhysicalAgent)E).delScript(S);
}
}
else
if(O instanceof Ability)
{
if((V.size()>2)
&&(V.get(2) instanceof Ability)
&&(E instanceof MOB))
{
Ability A=((MOB)E).fetchAbility(((Ability)O).ID());
if((V.size()>3)&&(V.get(3) instanceof String))
{
if(A==null)
{
A=(Ability)O;
((MOB)E).addAbility(A);
}
A.setMiscText((String)V.get(3));
}
else
if(A!=null)
((MOB)E).delAbility(A);
}
else
if(E instanceof Physical)
{
Ability A=((Physical)E).fetchEffect(((Ability)O).ID());
if((V.size()>2)&&(V.get(2) instanceof String))
{
if(A==null)
{
A=(Ability)O;
((Physical)E).addEffect(A);
}
A.setMiscText((String)V.get(2));
}
else
if(A!=null)
{
A.unInvoke();
((Physical)E).delEffect(A);
}
}
}
else
if(O instanceof Item)
((Item)O).destroy();
}
catch(final ArrayIndexOutOfBoundsException e)
{
// eat it
}
}
}
}
}
stoppingQuest=false;
}
// this will cause a quest to begin parsing its next "step".
// this will clear out unpreserved objects from previous
// step and resume quest script processing.
// if this is the LAST step, stopQuestInternal() is automatically called
@Override
public boolean stepQuest()
{
if((questState==null)||(stoppingQuest))
return false;
cleanQuestStep();
ticksRemaining=-1;
setDuration(-1);
final List<Object> args=new Vector<Object>();
final List<Object> script=parseLoadScripts(script(),new Vector<Object>(),args,true);
try
{
setVars(script,questState.lastLine);
parseQuestScript(script,args,questState.lastLine);
}
catch(final Exception t)
{
questState.error=true;
Log.errOut("DefaultQuest",t);
}
if(questState.error)
{
if(!questState.beQuiet)
Log.errOut("Quest","One or more errors in '"+name()+"', quest not started");
}
else
if(!questState.done)
{
// valid DONE state, when stepping over the end
}
else
if(duration()<0)
{
Log.errOut("Quest","No duration, quest '"+name()+"' not started.");
questState.error=true;
}
if((!questState.error)&&(questState.done)&&(duration()>=0))
{
enterRunningState();
return true;
}
stopQuestInternal();
return false;
}
@Override
public void resetQuest(final int firstPauseTicks)
{
if(stoppingQuest)
return;
// ticksRemaining of -1 is OK, it will grab duration
resetData=new int[]{firstPauseTicks,ticksRemaining};
stopQuest();
}
@Override
public void stopQuest()
{
if((!stoppingQuest)&&(running()))
CMLib.coffeeTables().bump(this,CoffeeTableRow.STAT_QUESTSUCCESS);
stopQuestInternal();
}
// this will stop executing of the quest script. It will clean up
// any objects or mobs which may have been loaded, restoring map
// mobs to their previous state.
public void stopQuestInternal()
{
if(stoppingQuest)
return;
// first set everything to complete!
synchronized(questState)
{
for(final PreservedQuestObject PO : questState.worldObjects)
PO.preserveState=0;
for(int q=0;q<questState.addons.size();q++)
questState.addons.setElementAt(q,2,Integer.valueOf(0));
questState.autoStepAfterDuration=false;
}
cleanQuestStep();
stoppingQuest=true;
if(!isCopy())
setScript(script(),true); // causes wait times/name to reload
enterDormantState();
stoppingQuest=false;
}
@Override
public boolean enterDormantState()
{
ticksRemaining=-1;
if((isCopy())||(!resetWaitRemaining(0)))
{
Resources.removeResource("VARSCOPE-"+name.toUpperCase().trim());
CMLib.quests().delQuest(this);
CMLib.threads().deleteTick(this,Tickable.TICKID_QUEST);
return false;
}
return true;
}
@Override
public boolean resetWaitRemaining(final long ellapsedTime)
{
if(resetData!=null)
{
waitRemaining=resetData[0];
resetData[0]*=2;
return true;
}
if(((minWait()<0)||(maxWait<0))
&&(startDate().trim().length()==0))
return false;
if(running())
return true;
if(startDate().length()>0)
{
if(startDate().toUpperCase().startsWith("MUDDAY"))
{
final String sd2=startDate().substring("MUDDAY".length()).trim();
final int x=sd2.indexOf('-');
if(x<0)
return false;
final int mudmonth=CMath.s_parseIntExpression(sd2.substring(0,x));
final int mudday=CMath.s_parseIntExpression(sd2.substring(x+1));
final TimeClock C=(TimeClock)CMClass.getCommon("DefaultTimeClock");
final TimeClock NOW=CMLib.time().globalClock();
C.setMonth(mudmonth);
C.setDayOfMonth(mudday);
C.setHourOfDay(0);
if((mudmonth<NOW.getMonth())
||((mudmonth==NOW.getMonth())&&(mudday<NOW.getDayOfMonth())))
C.setYear(NOW.getYear()+1);
else
C.setYear(NOW.getYear());
final long distance=C.deriveMillisAfter(NOW);
waitRemaining=(int)(distance/CMProps.getTickMillis());
}
else
{
final int x=startDate.indexOf('-');
if(x<0)
return false;
final int month=CMath.s_parseIntExpression(startDate.substring(0,x));
final int day=CMath.s_parseIntExpression(startDate.substring(x+1));
int year=Calendar.getInstance().get(Calendar.YEAR);
long distance=CMLib.time().string2Millis(month+"/"+day+"/"+year+" 12:00 AM");
final Calendar C=Calendar.getInstance();
final long today=CMLib.time().string2Millis((C.get(Calendar.MONTH)+1)+"/"+C.get(Calendar.DAY_OF_MONTH)+"/"+C.get(Calendar.YEAR)+" 12:00 AM");
while(distance<today)
distance=CMLib.time().string2Millis(month+"/"+day+"/"+(++year)+" 12:00 AM");
waitRemaining=(int)((distance-today)/CMProps.getTickMillis());
}
}
else
waitRemaining=(minWait+(CMLib.dice().roll(1,maxWait,0)))-(int)(ellapsedTime/CMProps.getTickMillis());
return true;
}
@Override
public int minWait()
{
return minWait;
}
@Override
public void setMinWait(final int wait)
{
minWait = wait;
}
@Override
public int waitInterval()
{
return maxWait;
}
@Override
public void setWaitInterval(final int wait)
{
maxWait = wait;
}
@Override
public int waitRemaining()
{
return waitRemaining;
}
public Quest getMainQuestObject()
{
Quest Q=this;
if(isCopy())
{
Quest Q2=null;
for(int q=0;q<CMLib.quests().numQuests();q++)
{
Q2=CMLib.quests().fetchQuest(q);
if((Q2!=null)&&(Q2.name().equals(name))&&(!isCopy()))
{
Q = Q2;
break;
}
}
}
return Q;
}
// if the quest has a winner, this is him.
@Override
public void declareWinner(String name)
{
if(name==null)
return;
name=name.trim();
if(name.length()==0)
return;
final Quest Q=getMainQuestObject();
boolean wasWinner = false;
boolean removeMe = false;
if(name.startsWith("-"))
{
name=name.substring(1);
removeMe=true;
}
final Map<String,Long> V=Q.getWinners();
if(V.remove(name) != null)
{
wasWinner = true;
}
if(removeMe)
{
if(wasWinner)
{
CMLib.database().DBUpdateQuest(Q);
}
}
else
{
Q.getWinners().put(name,Long.valueOf(System.currentTimeMillis()));
CMLib.database().DBUpdateQuest(Q);
}
}
@Override
public String getWinnerStr()
{
final Quest Q=getMainQuestObject();
final StringBuffer list=new StringBuffer("");
final Map<String,Long> V=Q.getWinners();
for(final String name : V.keySet())
{
final Long time=V.get(name);
list.append(name+"@"+time.longValue()+";");
}
return list.toString();
}
@Override
public void setWinners(final String list)
{
final Quest Q=getMainQuestObject();
final Map<String,Long> V=Q.getWinners();
V.clear();
final List<String> parts=CMParms.parseSemicolons(list, true);
for(final String part : parts)
{
if(part.trim().length()>0)
{
final int x=part.indexOf('@');
Long time=Long.valueOf(0);
String name=part.trim();
if(x>0)
{
name=part.substring(0,x).trim();
time=Long.valueOf(CMath.s_long(part.substring(x+1).trim()));
}
V.put(name,time);
}
}
}
// retrieve the list of previous winners
@Override
public Map<String, Long> getWinners()
{
final Quest Q=getMainQuestObject();
if(Q==this)
return winners;
return Q.getWinners();
}
// was a previous winner
@Override
public boolean wasWinner(final String name)
{
return whenLastWon(name) != null;
}
// was a previous winner
@Override
public Long whenLastWon(String name)
{
if(name==null)
return null;
name=name.trim();
if(name.length()==0)
return null;
final Quest Q=getMainQuestObject();
final Map<String,Long> V=Q.getWinners();
return V.get(name);
}
// informational
@Override
public boolean running()
{
return ticksRemaining >= 0;
}
@Override
public boolean stopping()
{
return stoppingQuest;
}
@Override
public boolean waiting()
{
return waitRemaining >= 0;
}
@Override
public int ticksRemaining()
{
return ticksRemaining;
}
@Override
public int minsRemaining()
{
return (int) (ticksRemaining * CMProps.getTickMillis() / 60000);
}
private int tickStatus = Tickable.STATUS_NOT;
@Override
public int getTickStatus()
{
return tickStatus;
}
@Override
public boolean tick(final Tickable ticking, final int tickID)
{
if(tickID!=Tickable.TICKID_QUEST)
return false;
if(CMSecurity.isDisabled(CMSecurity.DisFlag.QUESTS)
||(CMProps.getBoolVar(CMProps.Bool.MUDSHUTTINGDOWN))
||(!CMProps.getBoolVar(CMProps.Bool.MUDSTARTED))
||(suspended()))
return true;
tickStatus=Tickable.STATUS_START;
if(running())
{
tickStatus=Tickable.STATUS_ALIVE;
if(duration()>0)
ticksRemaining--;
if(ticksRemaining<0)
{
if((questState!=null)&&(questState.autoStepAfterDuration))
{
stepQuest();
}
else
{
CMLib.coffeeTables().bump(this,CoffeeTableRow.STAT_QUESTTIMESTOP);
stopQuest();
}
}
tickStatus=Tickable.STATUS_END;
}
else
{
if(startQuestOnTime())
{
CMLib.coffeeTables().bump(this,CoffeeTableRow.STAT_QUESTTIMESTART);
}
}
tickStatus=Tickable.STATUS_NOT;
return true;
}
protected boolean startQuestOnTime()
{
if((--waitRemaining)>=0)
return false;
boolean allowedToRun=true;
if(runLevel()>=0)
{
for(int q=0;q<CMLib.quests().numQuests();q++)
{
final Quest Q=CMLib.quests().fetchQuest(q);
if((!Q.name().equals(name))
&&(Q.running())
&&(Q.duration()!=0)
&&(Q.runLevel()<=runLevel())
&&(Q.runLevel()>=0))
{
allowedToRun = false;
break;
}
}
}
if(allowedToRun)
{
int numElligiblePlayers=0;
final boolean isMask=(playerMask.length()>0);
for(final Session S : CMLib.sessions().localOnlineIterable())
{
if((S.mob()!=null)
&&((!isMask) || CMLib.masking().maskCheck(playerMask,S.mob(),true)))
numElligiblePlayers++;
}
ticksRemaining=-1;
if((numElligiblePlayers>=minPlayers)||(duration()==0))
return startQuestInternal();
}
enterDormantState();
return false;
}
@Override
public void runtimeRegisterAbility(final MOB mob, final String abilityID, final String parms, final boolean give)
{
if(mob==null)
return;
runtimeRegisterObject(mob);
final Vector<Object> V=new Vector<Object>();
V.addElement(mob);
Ability A4=mob.fetchAbility(abilityID);
if(A4!=null)
{
V.addElement(A4);
V.addElement(A4);
V.addElement(A4.text());
if(give)
{
A4.setMiscText(parms);
A4.setProficiency(100);
}
else
mob.delAbility(A4);
}
else
if(!give)
return;
else
{
A4=CMClass.getAbility(abilityID);
if(A4==null)
return;
A4.setMiscText(parms);
V.addElement(A4);
V.addElement(A4);
A4.setProficiency(100);
A4.setSavable(false); // because, WHY WOULD IT BE SAVABLE?!
mob.addAbility(A4);
}
synchronized(questState)
{
questState.addons.addElement(V,Integer.valueOf(questState.preserveState));
}
}
@Override
public void runtimeRegisterObject(final PhysicalAgent P)
{
if(P==null)
return;
synchronized(questState)
{
for(final PreservedQuestObject PO : questState.worldObjects)
{
if(PO.obj==P)
{
if(PO.preserveState<questState.preserveState)
PO.preserveState=questState.preserveState;
questState.worldObjects.add(PO);
return;
}
if(PO.obj.amDestroyed())
questState.worldObjects.remove(PO);
}
questState.worldObjects.add(new PreservedQuestObject(P,questState.preserveState));
Ability A=P.fetchEffect("QuestBound");
if(A==null)
A=CMClass.getAbility("QuestBound");
A.setMiscText(""+this);
A.setSavable(false);
P.addNonUninvokableEffect(A);
}
}
@Override
public void runtimeRegisterEffect(final PhysicalAgent affected, final String abilityID, final String parms, final boolean give)
{
if(affected==null)
return;
runtimeRegisterObject(affected);
final Vector<Object> V=new Vector<Object>();
V.addElement(affected);
Ability A4=affected.fetchEffect(abilityID);
if(A4!=null)
{
V.addElement(A4);
V.addElement(A4.text());
if(give)
{
A4.makeLongLasting();
A4.setMiscText(parms);
}
else
affected.delEffect(A4);
}
else
if(!give)
return;
else
{
A4=CMClass.getAbility(abilityID);
if(A4==null)
return;
V.addElement(A4);
A4.setMiscText(parms);
if(affected instanceof MOB)
A4.startTickDown((MOB)affected,affected,99999);
else
A4.startTickDown(null,affected,99999);
A4.setSavable(false); // because, WHY WOULD IT BE SAVABLE?!
A4.makeLongLasting();
}
synchronized(questState)
{
questState.addons.addElement(V,Integer.valueOf(questState.preserveState));
}
}
@Override
public void runtimeRegisterBehavior(final PhysicalAgent behaving, final String behaviorID, final String parms, final boolean give)
{
if(behaving==null)
return;
runtimeRegisterObject(behaving);
final Vector<Object> V=new Vector<Object>();
V.addElement(behaving);
Behavior B=behaving.fetchBehavior(behaviorID);
if(B!=null)
{
V.addElement(B);
V.addElement(B.getParms());
if(give)
B.setParms(parms);
else
behaving.delBehavior(B);
}
else
if(!give)
{
return;
}
else
{
B=CMClass.getBehavior(behaviorID);
if(B==null)
return;
V.addElement(B);
B.setParms(parms);
B.setSavable(false); // because, WHY WOULD IT BE SAVABLE?!
behaving.addBehavior(B);
}
B.registerDefaultQuest(name());
synchronized(questState)
{
questState.addons.addElement(V,Integer.valueOf(questState.preserveState));
}
}
public void runtimeRegisterStat(final Environmental E, String stat, final String parms, final boolean give)
{
if(E==null)
return;
if(E instanceof PhysicalAgent)
runtimeRegisterObject((PhysicalAgent)E);
final Vector<Object> V=new Vector<Object>();
V.addElement(E);
stat=stat.toUpperCase().trim();
String oldVal="";
if(CMStrings.contains(E.getStatCodes(),stat))
oldVal=E.getStat(stat);
else
if((E instanceof Physical)&&CMStrings.contains(((Physical)E).basePhyStats().getStatCodes(),stat))
oldVal=((Physical)E).basePhyStats().getStat(stat);
else
if((E instanceof MOB)&&(CMStrings.contains(CharStats.CODES.NAMES(),stat)))
oldVal=""+((MOB)E).baseCharStats().getStat(CMParms.indexOf(CharStats.CODES.NAMES(),stat));
else
if((E instanceof MOB)&&CMStrings.contains(((MOB)E).baseState().getStatCodes(),stat))
oldVal=((MOB)E).baseState().getStat(stat);
V.addElement(stat);
V.addElement(oldVal);
if(!give)
return;
V.addElement(stat);
V.addElement(oldVal);
if(CMStrings.contains(E.getStatCodes(),stat))
E.setStat(stat,parms);
else
if((E instanceof Physical)&&CMStrings.contains(((Physical)E).basePhyStats().getStatCodes(),stat))
{
((Physical)E).basePhyStats().setStat(stat,parms);
((Physical)E).recoverPhyStats();
}
else
if((E instanceof MOB)&&(CMStrings.contains(CharStats.CODES.NAMES(),stat)))
{
((MOB)E).baseCharStats().setStat(CMParms.indexOf(CharStats.CODES.NAMES(),stat),CMath.s_int(parms));
((MOB)E).recoverCharStats();
}
else
if((E instanceof MOB)&&CMStrings.contains(((MOB)E).baseState().getStatCodes(),stat))
{
((MOB)E).baseState().setStat(stat,parms);
((MOB)E).recoverMaxState();
((MOB)E).resetToMaxState();
}
synchronized(questState)
{
questState.addons.addElement(V,Integer.valueOf(questState.preserveState));
}
}
public int getQuestThingIndex(final Iterator<? extends Environmental> i, final String name, final CMClass.CMObjectType type, final int[] num)
{
if(i==null)
return -1;
Environmental E;
if(name.startsWith("*"))
{
if(name.endsWith("*"))
{
final String iname=(name.length()>1)?name.substring(1,name.length()-1).toLowerCase():"";
for(;i.hasNext();)
{
E=i.next();
if(CMClass.isType(E,type))
{
switch(type)
{
case LOCALE:
if(CMLib.map().getExtendedRoomID((Room)E).toLowerCase().indexOf(iname)>=0)
return num[0];
break;
default:
if(E.Name().toLowerCase().indexOf(iname)>=0)
return num[0];
break;
}
num[0]++;
}
}
}
else
{
final String iname=name.substring(1).toLowerCase();
for(;i.hasNext();)
{
E=i.next();
if(CMClass.isType(E,type))
{
switch(type)
{
case LOCALE:
if(CMLib.map().getExtendedRoomID((Room)E).toLowerCase().endsWith(iname))
return num[0];
break;
default:
if(E.Name().toLowerCase().endsWith(iname))
return num[0];
break;
}
num[0]++;
}
}
}
}
else
if(name.endsWith("*"))
{
final String iname=name.substring(0,name.length()-1).toLowerCase();
for(;i.hasNext();)
{
E=i.next();
if(CMClass.isType(E,type))
{
switch(type)
{
case LOCALE:
if(CMLib.map().getExtendedRoomID((Room)E).toLowerCase().startsWith(iname))
return num[0];
break;
default:
if(E.Name().toLowerCase().startsWith(iname))
return num[0];
break;
}
num[0]++;
}
}
}
else
{
for(;i.hasNext();)
{
E=i.next();
if(CMClass.isType(E,type))
{
switch(type)
{
case LOCALE:
if(CMLib.map().getExtendedRoomID((Room)E).equalsIgnoreCase(name))
return num[0];
break;
default:
if(E.Name().equalsIgnoreCase(name))
return num[0];
break;
}
num[0]++;
}
}
}
return -1;
}
@Override
public int getQuestMobIndex(final String name)
{
final int[] num={1};
int x=-1;
synchronized(questState)
{
if(questState.worldObjects!=null)
x=getQuestThingIndex(PreservedQuestObject.getPOIter(questState.worldObjects),name,CMClass.CMObjectType.MOB,num);
if((x<0)&&(questState.mobGroup!=null))
x=getQuestThingIndex(questState.mobGroup.iterator(),name,CMClass.CMObjectType.MOB,num);
if((x<0)&&(questState.mysteryData!=null)&&(questState.mysteryData.agentGroup!=null))
x=getQuestThingIndex(questState.mysteryData.agentGroup.iterator(),name,CMClass.CMObjectType.MOB,num);
}
return x;
}
@Override
public int getQuestRoomIndex(final String roomID)
{
final int[] num={1};
int x=-1;
synchronized(questState)
{
if(questState.worldObjects!=null)
x=getQuestThingIndex(PreservedQuestObject.getPOIter(questState.worldObjects),roomID,CMClass.CMObjectType.LOCALE,num);
if((x<0)&&(questState.roomGroup!=null))
x=getQuestThingIndex(questState.roomGroup.iterator(),roomID,CMClass.CMObjectType.LOCALE,num);
if(questState.mysteryData!=null)
{
if((x<0)&&(questState.mysteryData.whereAtGroup!=null))
x=getQuestThingIndex(questState.mysteryData.whereAtGroup.iterator(),roomID,CMClass.CMObjectType.LOCALE,num);
if((x<0)&&(questState.mysteryData.whereHappenedGroup!=null))
x=getQuestThingIndex(questState.mysteryData.whereHappenedGroup.iterator(),roomID,CMClass.CMObjectType.LOCALE,num);
}
}
return x;
}
@Override
public int getQuestItemIndex(final String name)
{
final int[] num={1};
int x=-1;
synchronized(questState)
{
if(questState.worldObjects!=null)
x=getQuestThingIndex(PreservedQuestObject.getPOIter(questState.worldObjects),name,CMClass.CMObjectType.ITEM,num);
if((x<0)&&(questState.itemGroup!=null))
x=getQuestThingIndex(questState.itemGroup.iterator(),name,CMClass.CMObjectType.ITEM,num);
if(questState.mysteryData!=null)
{
if((x<0)&&(questState.mysteryData.toolGroup!=null))
x=getQuestThingIndex(questState.mysteryData.toolGroup.iterator(),name,CMClass.CMObjectType.ITEM,num);
}
}
return x;
}
@Override
public long getFlags()
{
return suspended()?FLAG_SUSPENDED:0;
}
@Override
public void setFlags(final long flags)
{
if(CMath.bset(flags,FLAG_SUSPENDED))
{
setSuspended(true);
}
}
public Environmental getQuestThing(final Iterator<? extends Environmental> e, final int dex, final CMClass.CMObjectType type, final int[] num)
{
if(e==null)
return null;
Environmental E;
for(;e.hasNext();)
{
E=e.next();
if(CMClass.isType(E,type))
{
if(dex==num[0])
return E;
num[0]++;
}
}
return null;
}
@Override
public MOB getQuestMob(final int i)
{
final int[] num={1};
Environmental E=null;
synchronized(questState)
{
if(questState.worldObjects!=null)
E=getQuestThing(PreservedQuestObject.getPOIter(questState.worldObjects),i,CMClass.CMObjectType.MOB,num);
if(E instanceof MOB)
return (MOB)E;
if(questState.mobGroup!=null)
E=getQuestThing(questState.mobGroup.iterator(),i,CMClass.CMObjectType.MOB,num);
if(E instanceof MOB)
return (MOB)E;
if((questState.mysteryData!=null)&&(questState.mysteryData.agentGroup!=null))
E=getQuestThing(questState.mysteryData.agentGroup.iterator(),i,CMClass.CMObjectType.MOB,num);
if(E instanceof MOB)
return (MOB)E;
}
return null;
}
@Override
public Item getQuestItem(final int i)
{
final int[] num={1};
Environmental E=null;
synchronized(questState)
{
if(questState.worldObjects!=null)
E=getQuestThing(PreservedQuestObject.getPOIter(questState.worldObjects),i,CMClass.CMObjectType.ITEM,num);
if(E instanceof Item)
return (Item)E;
if(questState.itemGroup!=null)
E=getQuestThing(questState.itemGroup.iterator(),i,CMClass.CMObjectType.ITEM,num);
if(E instanceof Item)
return (Item)E;
if((questState.mysteryData!=null)&&(questState.mysteryData.toolGroup!=null))
E=getQuestThing(questState.mysteryData.toolGroup.iterator(),i,CMClass.CMObjectType.ITEM,num);
if(E instanceof Item)
return (Item)E;
}
return null;
}
@Override
public Room getQuestRoom(final int i)
{
final int[] num={1};
Environmental E=null;
synchronized(questState)
{
if(questState.worldObjects!=null)
E=getQuestThing(PreservedQuestObject.getPOIter(questState.worldObjects),i,CMClass.CMObjectType.LOCALE,num);
if(E instanceof Room)
return (Room)E;
if(questState.roomGroup != null)
E=getQuestThing(questState.roomGroup.iterator(),i,CMClass.CMObjectType.LOCALE,num);
if(E instanceof Room)
return (Room)E;
if((questState.mysteryData!=null)&&(questState.mysteryData.whereAtGroup!=null))
E=getQuestThing(questState.mysteryData.whereAtGroup.iterator(),i,CMClass.CMObjectType.LOCALE,num);
if(E instanceof Room)
return (Room)E;
if((questState.mysteryData!=null)&&(questState.mysteryData.whereHappenedGroup!=null))
E=getQuestThing(questState.mysteryData.whereHappenedGroup.iterator(),i,CMClass.CMObjectType.LOCALE,num);
if(E instanceof Room)
return (Room)E;
}
return null;
}
@Override
public String getQuestMobName(final int i)
{
final MOB M=getQuestMob(i);
if(M!=null)
return M.name();
return "";
}
@Override
public String getQuestItemName(final int i)
{
final Item I=getQuestItem(i);
if(I!=null)
return I.name();
return "";
}
@Override
public String getQuestRoomID(final int i)
{
final Room R=getQuestRoom(i);
if(R!=null)
return CMLib.map().getExtendedRoomID(R);
return "";
}
@Override
public int getObjectInUseIndex(final String name)
{
synchronized(questState)
{
if(questState.worldObjects!=null)
{
for(int i=0;i<questState.worldObjects.size();i++)
{
final PhysicalAgent O=questState.worldObjects.get(i).obj;
if(O.name().equalsIgnoreCase(name))
return (i+1);
}
}
}
return -1;
}
@Override
public boolean isObjectInUse(final Environmental E)
{
if((questState.worldObjects!=null)&&(E!=null))
{
for(final PreservedQuestObject PO : questState.worldObjects)
{
if(PO.obj==E)
return true;
}
}
return false;
}
public List<Object> parseLoadScripts(String text, final List<?> oldArgs, final List<Object> args, final boolean showErrors)
{
final Vector<Object> script=new Vector<Object>();
if(text.trim().toUpperCase().startsWith("LOAD="))
{
String filename=null;
final Vector<String> V=CMParms.parse(text.trim().substring(5).trim());
if(V.size()>0)
{
filename=V.firstElement();
Vector<String> parms=null;
try
{
for(int v=1;v<V.size();v++)
{
parms=CMParms.parse(V.elementAt(v));
final Object O=getObjectIfSpecified(parms,oldArgs,0,1);
args.add((O==null)?"":O);
}
final StringBuffer buf=getResourceFileData(filename,showErrors);
if(buf!=null)
text=buf.toString();
}
catch(final CMException ex)
{
Log.errOut("DefaultQuest","'"+text+"' either has a space in the filename, or unknown parms.");
}
}
}
final int x=text.toLowerCase().indexOf(XMLLibrary.FILE_XML_BOUNDARY.toLowerCase());
if(x>=0)
{
final String xml=text.substring(x+XMLLibrary.FILE_XML_BOUNDARY.length()).trim();
text=text.substring(0,x);
if((xml.length()>0)&&(internalFiles==null))
{
final List<XMLLibrary.XMLTag> topXMLV=CMLib.xml().parseAllXML(xml);
for(int t=0;t<topXMLV.size();t++)
{
final XMLTag filePiece=topXMLV.get(t);
String name=null;
String data=null;
if(filePiece.tag().equalsIgnoreCase("FILE")&&(filePiece.contents()!=null))
{
for(int p=0;p<filePiece.contents().size();p++)
{
final XMLTag piece=filePiece.contents().get(p);
if(piece.tag().equalsIgnoreCase("NAME"))
name=piece.value();
if(piece.tag().equalsIgnoreCase("DATA"))
data=piece.value();
}
}
if((name!=null)&&(data!=null)&&(name.trim().length()>0)&&(data.trim().length()>0))
{
if(internalFiles==null)
internalFiles=new DVector(2);
internalFiles.addElement(name.toUpperCase().trim(),new StringBuffer(data));
}
}
}
}
List<Object> V=script;
while(text.length()>0)
{
int y=-1;
int yy=0;
while(yy<text.length())
{
if ((text.charAt(yy) == ';') && ((yy <= 0) || (text.charAt(yy - 1) != '\\')))
{
y = yy;
break;
}
else
if (text.charAt(yy) == '\n')
{
y = yy;
break;
}
else
if (text.charAt(yy) == '\r')
{
y = yy;
break;
}
else
yy++;
}
String cmd="";
if(y<0)
{
cmd=text.trim();
text="";
}
else
{
cmd=text.substring(0,y).trim();
text=text.substring(y+1).trim();
}
if((cmd.length()>0)&&(!cmd.startsWith("#")))
{
if(cmd.toUpperCase().startsWith("<OPTION>"))
{
V=new Vector<Object>();
script.add(V);
}
else
if(cmd.toUpperCase().startsWith("</OPTION>"))
V=script;
else
V.add(CMStrings.replaceAll(cmd,"\\;",";").trim());
}
}
return script;
}
private static final String VALID_ASTR_CODES="_&|";
private String modifyStringFromArgs(String s, final List<?> args)
{
int x=s.toUpperCase().indexOf('$');
while((x>=0)&&(x<s.length()-1))
{
int y=x+1;
if((y<s.length())&&(VALID_ASTR_CODES.indexOf(s.charAt(y))>=0))
y++;
while((y<s.length())&&(Character.isLetterOrDigit(s.charAt(y))))
y++;
try
{
String possObjName=(x+1>=y)?null:s.substring(x+1,y);
if((possObjName!=null)&&(possObjName.length()>0))
{
final char firstCode=possObjName.charAt(0);
if(VALID_ASTR_CODES.indexOf(firstCode)>=0)
possObjName=possObjName.substring(1);
final Object O=getObjectIfSpecified(CMParms.cleanParameterList(possObjName),args,0,0);
String replace=(O==null)?"null":O.toString();
if(O instanceof Room)
replace=((Room)O).displayText(null);
else
if(O instanceof Environmental)
replace=((Environmental)O).Name();
else
if(O instanceof TimeClock)
replace=((TimeClock)O).getShortTimeDescription();
switch(firstCode)
{
case '_':
replace=CMStrings.capitalizeAndLower(replace);
break;
case '&':
replace=CMLib.english().removeArticleLead(replace);
break;
case '|':
replace=CMLib.english().removeArticleLead(replace).trim().replace(' ','|');
break;
}
s=s.substring(0,x)+replace+s.substring(y);
}
}
catch (final CMException ex)
{
}
x=s.toUpperCase().indexOf('$',x+1);
}
return s;
}
private Object getObjectIfSpecified(final List<String> parms, final List<?> args, final int startp, final int object0vector1)
throws CMException
{
if(parms.size()-startp==0)
throw new CMException("Not specified");
final StringBuffer allParms=new StringBuffer(parms.get(startp));
for(int p=startp+1;p<parms.size();p++)
allParms.append(parms.get(p));
Object O=null;
final List<Object> V=new XVector<Object>();
int lastI=0;
String eval=null;
char code=' ';
for(int i=0;i<=allParms.length();i++)
{
eval=null;
if((i==allParms.length())
||((i<allParms.length())&&((allParms.charAt(i)=='+')||(allParms.charAt(i)=='-')||(allParms.charAt(i)=='#'))))
{
eval=allParms.substring(lastI,i).trim().toUpperCase();
lastI=i+1;
}
if(eval!=null)
{
if(eval.startsWith("ARG")&&CMath.isMathExpression(eval.substring(3)))
{
final int num=CMath.parseIntExpression(eval.substring(3));
if((num<=0)||(num>args.size()))
throw new CMException ("Not specified: "+eval);
O=args.get(num-1);
}
else
{
if(!questState.isStat(eval))
throw new CMException ("Not specified: "+eval);
O=questState.getStat(eval);
}
switch(code)
{
case '#':
{
int index=0;
if(CMath.isMathExpression(eval))
index=CMath.parseIntExpression(eval);
if((index>=0)&&(index<V.size()))
{
O=V.get(index);
V.clear();
V.add(O);
}
break;
}
case '-':
if(O instanceof List)
V.removeAll((List<?>)O);
else
if(O!=null)
V.remove(O);
break;
case '+':
case ' ':
if(O instanceof List)
V.addAll((List<?>)O);
else
if(O!=null)
V.add(O);
break;
}
if(i<allParms.length())
code=allParms.charAt(i);
}
}
switch(object0vector1)
{
case 0:
if(V.size()==0)
return null;
return V.get(CMLib.dice().roll(1,V.size(),-1));
case 1:
if(V.size()==0)
return null;
return V;
}
return null;
}
protected static String[] CCODES = null;
@Override
public String[] getStatCodes()
{
if(CCODES == null)
{
final String[] CCODES=new String[QCODES.values().length+MYSTERY_QCODES.values().length];
for(int i=0;i<QCODES.values().length;i++)
CCODES[i]=QCODES.values()[i].name();
for(int i=0;i<MYSTERY_QCODES.values().length;i++)
CCODES[QCODES.values().length+i]=MYSTERY_QCODES.values()[i].name();
DefaultQuest.CCODES = CCODES;
}
return CCODES;
}
@Override
public int getSaveStatIndex()
{
return getStatCodes().length;
}
protected int getCodeNum(final String code)
{
final String[] CCODES=getStatCodes();
for(int i=0;i<CCODES.length;i++)
{
if(code.equalsIgnoreCase(CCODES[i]))
return i;
}
return -1;
}
public boolean sameAs(final DefaultQuest E)
{
final String[] CCODES=getStatCodes();
for(int i=0;i<CCODES.length;i++)
{
if(!E.getStat(CCODES[i]).equals(getStat(CCODES[i])))
return false;
}
return true;
}
@Override
public void setStat(final String code, final String val)
{
switch(getCodeNum(code))
{
case 0:
break;
case 1:
setName(val);
break;
case 2:
setDuration(CMLib.time().parseTickExpression(val));
break;
case 3:
setMinWait(CMLib.time().parseTickExpression(val));
break;
case 4:
setMinPlayers(CMath.s_parseIntExpression(val));
break;
case 5:
setPlayerMask(val);
break;
case 6:
setRunLevel(CMath.s_parseIntExpression(val));
break;
case 7:
setStartDate(val);
break;
case 8:
setStartMudDate(val);
break;
case 9:
setWaitInterval(CMLib.time().parseTickExpression(val));
break;
case 10:
setSpawn(CMParms.indexOf(SPAWN_DESCS, val.toUpperCase().trim()));
break;
case 11:
setDisplayName(val);
break;
case 13:
durable = CMath.s_bool(val);
break;
case 14:
author = val;
break;
case 15:
{
final int ticks=CMLib.time().parseTickExpression(val);
if(ticks == 0)
this.setCopy(false);
else
{
this.setDuration(ticks);
this.setCopy(true);
}
}
break;
case 12: // instructions can and should fall through the default
default:
if((code.toUpperCase().trim().equalsIgnoreCase("REMAINING"))&&(running()))
ticksRemaining=CMLib.time().parseTickExpression(val);
else
questState.vars.put(code.toUpperCase().trim(), val);
break;
}
}
@Override
public boolean isStat(final String code)
{
if((getCodeNum(code)>=0)
||(questState.vars.containsKey(code)))
return true;
return false;
}
@Override
public String getStat(String code)
{
switch(getCodeNum(code))
{
case 0:
return "" + ID();
case 1:
return "" + name();
case 2:
return "" + duration();
case 3:
return "" + minWait();
case 4:
return "" + minPlayers();
case 5:
return "" + playerMask();
case 6:
return "" + runLevel();
case 7:
return "" + startDate();
case 8:
return "" + startDate();
case 9:
return "" + waitInterval();
case 10:
return SPAWN_DESCS[getSpawn()];
case 11:
return displayName();
case 13:
return Boolean.toString(durable);
case 14:
return author();
case 12: // instructions can and should fall through the default
default:
{
code=code.toUpperCase().trim();
if((code.equalsIgnoreCase("REMAINING"))&&(running()))
return ""+ticksRemaining;
if(questState.vars.containsKey(code) && (!questState.isStat(code)))
return questState.vars.get(code);
if(questState.isStat(code))
{
final Object O=questState.getStat(code);
if(O instanceof Room)
return ((Room)O).displayText(null);
if(O instanceof TimeClock)
return ((TimeClock)O).getShortTimeDescription();
if(O instanceof Environmental)
return ((Environmental)O).Name();
if(O instanceof List)
return ""+((List<?>)O).size();
if(O!=null)
return O.toString();
}
else
if(code.endsWith("_ROOMID")&&(questState.isStat(code.substring(0,code.length()-7))))
{
code=code.substring(0,code.length()-7);
Object O=questState.getStat(code);
if(O instanceof List)
{
if(((List<?>)O).size()>0)
O=((List<?>)O).get(CMLib.dice().roll(1,((List<?>)O).size(),-1));
}
if(O instanceof Environmental)
{
final Room R=CMLib.map().roomLocation((Environmental)O);
if(R!=null)
return CMLib.map().getExtendedRoomID(R);
}
}
else
if(code.endsWith("_CLASS")&&(questState.isStat(code.substring(0,code.length()-6))))
{
code=code.substring(0,code.length()-6);
Object O=questState.getStat(code);
if(O instanceof List)
{
if(((List<?>)O).size()>0)
O=((List<?>)O).get(CMLib.dice().roll(1,((List<?>)O).size(),-1));
}
if(O instanceof CMObject)
return ((CMObject)O).ID();
else
if(O!=null)
return O.getClass().getName();
}
return "";
}
}
}
@Override
public int compareTo(final CMObject o)
{
return CMClass.classID(this).compareToIgnoreCase(CMClass.classID(o));
}
/**
* Objects selected for use by a quest can be preserved or released from
* quest-state to quest-state. This object maps a world object in use
* to its quest-states remaining.
* @author Bo Zimmerman
*/
public static class PreservedQuestObject
{
public int preserveState;
public PhysicalAgent obj;
private static Converter<PreservedQuestObject, PhysicalAgent> converter = new Converter<PreservedQuestObject, PhysicalAgent>()
{
@Override
public PhysicalAgent convert(final PreservedQuestObject obj)
{
return obj.obj;
}
};
public PreservedQuestObject(final PhysicalAgent o, final int state)
{
this.obj = o;
this.preserveState = state;
}
public static Iterator<PhysicalAgent> getPOIter(final List<PreservedQuestObject> o)
{
final ConvertingIterator<PreservedQuestObject,PhysicalAgent> iter =
new ConvertingIterator<PreservedQuestObject,PhysicalAgent>(o.iterator(),converter);
return iter;
}
}
/**
* A quest state class maps the parse-state of a quest, since quest parsing
* is highly state dependent, but the state is not explicit in the script itself.
* @author Bo Zimmerman
*
*/
public static class QuestState implements Cloneable
{
public MysteryData mysteryData = new MysteryData();
public List<MOB> loadedMobs = new Vector<MOB>();
public List<Item> loadedItems = new Vector<Item>();
public Area area = null;
public Room room = null;
public MOB mob = null;
public List<MOB> mobGroup = null;
public List<Item> itemGroup = null;
public List<Room> roomGroup = null;
public Item item = null;
public Object envObject = null;
public boolean error = false;
public boolean done = false;
public boolean beQuiet = false;
public boolean autoStepAfterDuration = false;
public int preserveState = 0;
public int lastLine = 0;
public int startLine;
// contains a set of vectors, vectors are formatted as such:
// key 1=vector, below. key 2=preserveState
// 0=environmental item/mob/etc
// 1=Ability, 2=Ability (for an ability added)
// 1=Ability, 2=Ability, 3=String (for an ability modified)
// 1=Effect(for an Effect added)
// 1=Effect, 2=String (for an Effect modified)
// 1=Behavior (for an Behavior added)
// 1=Behavior, 2=String (for an Behavior modified)
public DVector addons = new DVector(2);
public Map<String, String> vars = new STreeMap<String, String>();
public List<PhysicalAgent> reselectable = new Vector<PhysicalAgent>();
public List<PreservedQuestObject> worldObjects = new SVector<PreservedQuestObject>();
public boolean isStat(String statName)
{
final int x=statName.indexOf('#');
if(x>=0)
statName=statName.substring(0,x);
final QOBJS q=(QOBJS)CMath.s_valueOf(QOBJS.class, statName.toUpperCase().trim());
if(q != null)
return true;
if(mysteryData!=null)
return mysteryData.isStat(statName);
return false;
}
public Object getStat(String statName)
{
final int x=statName.indexOf('#');
final String whichStr;
if(x>=0)
{
whichStr=statName.substring(x+1);
statName=statName.substring(0,x);
}
else
whichStr=null;
Object O=null;
final QOBJS q=(QOBJS)CMath.s_valueOf(QOBJS.class, statName.toUpperCase().trim());
final int code=(q==null)?-1:q.ordinal();
switch(code)
{
case 0:
O = loadedMobs;
break;
case 1:
O = loadedItems;
break;
case 2:
O = area;
break;
case 3:
O = room;
break;
case 4:
O = mobGroup;
break;
case 5:
O = itemGroup;
break;
case 6:
O = roomGroup;
break;
case 7:
O = item;
break;
case 8:
O = envObject;
break;
case 9:
O = new ConvertingList<PreservedQuestObject, PhysicalAgent>(worldObjects, PreservedQuestObject.converter);
break;
case 10:
O = mob;
break;
default:
if(mysteryData!=null)
O=mysteryData.getStat(statName);
break;
}
if(whichStr != null)
{
if(O instanceof List)
{
final List<?> V=(List<?>)O;
if(CMath.isInteger(whichStr)||(whichStr.length()==0))
{
final int whichNum=(whichStr.length()==0)?0:CMath.s_parseIntExpression(whichStr);
if((whichStr!=null)&&((whichNum<=0)||(whichNum>V.size())))
return ""+V.size();
if(whichStr!=null)
return V.get(whichNum-1);
}
else
if(whichStr.equals("?"))
return (V.size()>0)?V.get(CMLib.dice().roll(1, V.size(), -1)):O;
else
if(whichStr.equals("$"))
{
final StringBuilder str=new StringBuilder("");
for(final Object o : V)
{
if(o instanceof Room)
str.append("\"").append(CMLib.map().getExtendedRoomID((Room)o)).append("\" ");
else
if(o instanceof CMObject)
str.append("\"").append(((CMObject)o).name()).append("\" ");
else
str.append("\"").append(o.toString()).append("\" ");
}
return str.toString().trim();
}
}
else
if(whichStr.equals("$"))
{
final StringBuilder str=new StringBuilder("");
if(O instanceof Room)
str.append("\"").append(CMLib.map().getExtendedRoomID((Room)O)).append("\" ");
else
if(O instanceof CMObject)
str.append("\"").append(((CMObject)O).name()).append("\" ");
else
if(O != null)
str.append("\"").append(O.toString()).append("\" ");
return str.toString().trim();
}
}
return O;
}
}
/**
* MysteryData is a helper class for QuestState that stores quest
* state variables for the parsing of quests that make use of the
* "mystery" variables (mystery as in Sherlock Holmes, not as in
* unknown).
* @author Bo Zimmerman
*/
public static class MysteryData implements Cloneable
{
public List<Faction> factionGroup;
public Faction faction;
public MOB agent;
public List<MOB> agentGroup;
public Environmental target;
public List<Environmental> targetGroup;
public Environmental tool;
public List<Environmental> toolGroup;
public Room whereHappened;
public List<Room> whereHappenedGroup;
public Room whereAt;
public List<Room> whereAtGroup;
public String action;
public List<String> actionGroup;
public String motive;
public List<String> motiveGroup;
public TimeClock whenHappened;
public List<TimeClock> whenHappenedGroup;
public TimeClock whenAt;
public List<TimeClock> whenAtGroup;
public boolean isStat(final String statName)
{
return CMath.s_valueOf(Quest.MYSTERY_QCODES.class, statName.toUpperCase().trim()) != null;
}
public Object getStat(final String statName)
{
final MYSTERY_QCODES q=(MYSTERY_QCODES)CMath.s_valueOf(Quest.MYSTERY_QCODES.class, statName.toUpperCase().trim());
final int code=(q==null)?-1:q.ordinal();
switch(code)
{
case 0:
return faction;
case 1:
return factionGroup;
case 2:
return agent;
case 3:
return agentGroup;
case 4:
return action;
case 5:
return actionGroup;
case 6:
return target;
case 7:
return targetGroup;
case 8:
return motive;
case 9:
return motiveGroup;
case 10:
return whereHappened;
case 11:
return whereHappenedGroup;
case 12:
return whereAt;
case 13:
return whereAtGroup;
case 14:
return whenHappened;
case 15:
return whenHappenedGroup;
case 16:
return whenAt;
case 17:
return whenAtGroup;
case 18:
return tool;
case 19:
return toolGroup;
}
return null;
}
}
protected static class JScriptQuest extends ScriptableObject
{
@Override
public String getClassName()
{
return "JScriptQuest";
}
static final long serialVersionUID = 44;
Quest quest = null;
QuestState state = null;
public Quest quest()
{
return quest;
}
public QuestState setupState()
{
return state;
}
public JScriptQuest(final Quest Q, final QuestState S)
{
quest = Q;
state = S;
}
public static String[] functions = { "quest", "setupState", "toJavaString" };
public String toJavaString(final Object O)
{
return Context.toString(O);
}
}
}