package com.planet_ink.coffee_mud.Libraries;
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.Libraries.interfaces.*;
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.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;
import java.io.IOException;
import java.util.*;
import org.mozilla.javascript.*;
/*
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 Quests extends StdLibrary implements QuestManager
{
@Override
public String ID()
{
return "Quests";
}
protected String holidayFilename="quests/holidays/holidays.quest";
protected String holidayDefinition="LOAD="+holidayFilename;
protected SVector<Quest> quests=new SVector<Quest>();
@Override
public Quest objectInUse(final Environmental E)
{
if(E==null)
return null;
for(int q=0;q<numQuests();q++)
{
final Quest Q=fetchQuest(q);
if(Q!=null)
{
if(Q.isObjectInUse(E))
return Q;
}
}
return null;
}
@Override
public int numQuests()
{
return quests.size();
}
@Override
public Quest fetchQuest(final int i)
{
try
{
return quests.elementAt(i);
}
catch (final Exception e)
{
}
return null;
}
@Override
public Quest fetchQuest(final String qname)
{
for(int i=0;i<numQuests();i++)
{
final Quest Q=fetchQuest(i);
if((Q!=null)&&(Q.name().equalsIgnoreCase(qname)))
return Q;
}
return null;
}
@Override
public Quest findQuest(final String qname)
{
Quest Q=fetchQuest(qname);
if(Q!=null)
return Q;
for(int i=0;i<numQuests();i++)
{
Q=fetchQuest(i);
if((Q.displayName().trim().length()>0)
&&(Q.displayName().equalsIgnoreCase(qname)))
return Q;
}
for(int i=0;i<numQuests();i++)
{
Q=fetchQuest(i);
if((Q.displayName().trim().length()>0)
&&(CMLib.english().containsString(Q.displayName(),qname)))
return Q;
}
return null;
}
@Override
public void addQuest(final Quest Q)
{
if(!quests.contains(Q))
{
quests.addElement(Q);
Q.autostartup();
}
}
@Override
public boolean shutdown()
{
for(int i=numQuests();i>=0;i--)
{
final Quest Q=fetchQuest(i);
delQuest(Q);
}
quests.clear();
return true;
}
@Override
public void delQuest(final Quest Q)
{
if(quests.contains(Q))
{
CMLib.coffeeTables().bump(Q,CoffeeTableRow.STAT_QUESTSTOP);
Q.stopQuest();
CMLib.threads().deleteTick(Q,Tickable.TICKID_QUEST);
Q.internalQuestDelete();
quests.removeElement(Q);
}
}
@Override
public synchronized void save()
{
CMLib.database().DBUpdateQuests(quests);
}
@Override
public Enumeration<Quest> enumQuests()
{
return quests.elements();
}
@Override
public Object getHolidayFile()
{
Quest Q=fetchQuest("holidays");
if((Q==null)
||(!Q.script().toUpperCase().trim().equalsIgnoreCase(holidayDefinition)))
{
Q=null;
final CMFile lF=new CMFile("//"+Resources.makeFileResourceName(holidayFilename),null);
final CMFile vF=new CMFile("::"+Resources.makeFileResourceName(holidayFilename),null);
if((lF.exists())&&(!vF.exists())&&(lF.canRead())&&(vF.canWrite()))
{
final byte[] O=lF.raw();
vF.saveRaw(O);
}
Q=(Quest)CMClass.getCommon("DefaultQuest");
Q.setScript(holidayDefinition,true);
addQuest(Q);
CMLib.database().DBUpdateQuest(Q);
Q=fetchQuest("holidays");
if(Q==null)
return "A quest named 'holidays', with the script definition '"+holidayDefinition+"' has not been created. Enter the following to create this quest:\n\r"
+"CREATE QUEST "+holidayDefinition+"\n\r"
+"SAVE QUESTS";
}
final CMFile F=new CMFile(Resources.makeFileResourceName(holidayFilename),null);
if((!F.exists())||(!F.canRead())||(!F.canWrite()))
{
return "The file '"+Resources.makeFileResourceName(holidayFilename)+"' does not exist, and is required for this feature.";
}
final List<String> V=Resources.getFileLineVector(F.text());
final List<String> steps=parseQuestSteps(V,0,true);
return steps;
}
@Override
@SuppressWarnings("unchecked")
public String listHolidays(final Area A, final String otherParms)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
return (String)resp;
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return "Unknown error.";
String areaName=A.Name().toUpperCase().trim();
if(otherParms.equalsIgnoreCase("ALL"))
areaName=null;
final StringBuffer str=new StringBuffer(L("^xDefined Quest Holidays^?\n\r"));
List<String> line=null;
String var=null;
List<String> V=null;
str.append("^H# "+CMStrings.padRight(L("Holiday Name"),20)+CMStrings.padRight(L("Area Name(s)"),50)+"^?\n\r");
for(int s=1;s<steps.size();s++)
{
final String step=steps.get(s);
V=Resources.getFileLineVector(new StringBuffer(step));
final List<List<String>> cmds=CMLib.quests().parseQuestCommandLines(V,"SET",0);
List<String> areaLine=null;
List<String> nameLine=null;
for(int v=0;v<cmds.size();v++)
{
line=cmds.get(v);
if(line.size()>1)
{
var=line.get(1).toUpperCase();
if (var.equals("AREAGROUP"))
{
areaLine = line;
}
if (var.equals("NAME"))
{
nameLine = line;
}
}
}
if(nameLine!=null)
{
boolean contains=true;//(areaName==null);
if(areaLine!=null)
{
if((!contains) && (areaName != null))
for(int l=2;l<areaLine.size();l++)
{
if(areaName.equalsIgnoreCase(areaLine.get(l)))
{
contains = true;
break;
}
}
}
else
{
areaLine=new XVector<String>("","","*special*");
contains=true;
}
if(contains)
{
final String name=CMParms.combine(nameLine,2);
str.append(CMStrings.padRight(""+s,3)+CMStrings.padRight(name,20)+CMStrings.padRight(CMParms.combineQuoted(areaLine,2),30)+"\n\r");
}
}
}
return str.toString();
}
protected void promptText(final MOB mob, final TriadList<String,String,Integer> sets, final String var, final int showNumber, final int showFlag, final String prompt, final String help, final boolean emptyOK)
throws java.io.IOException
{
final int index=sets.indexOfFirst(var);
final String oldVal=index>=0?(String)sets.get(index).second:"";
while((mob.session()!=null)&&(!mob.session().isStopped()))
{
final String newVAL=CMLib.genEd().prompt(mob,oldVal,showNumber,showFlag,prompt,emptyOK);
if(newVAL.equals("?"))
{
mob.tell(help);
continue;
}
else
if(index>=0)
sets.get(index).second = newVAL;
else
if(!newVAL.equals(oldVal))
sets.add(var,newVAL,Integer.valueOf(-1));
break;
}
}
@Override
@SuppressWarnings("unchecked")
public String createHoliday(final String named, final String areaName, final boolean save)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
return (String)resp;
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return "Unknown error.";
if(CMLib.quests().fetchQuest(named)!=null)
return "A quest called '"+named+"' already exists. Better to pick a new name.";
Vector<String> lineV=null;
String line=null;
String var=null;
String cmd=null;
String step=null;
for(int v=0;v<steps.size();v++)
{
step=steps.get(v);
final List<String> stepV=Resources.getFileLineVector(new StringBuffer(step));
for(int v1=0;v1<stepV.size();v1++)
{
line=stepV.get(v1);
lineV=CMParms.parse(line);
if(lineV.size()>1)
{
cmd=lineV.elementAt(0).toUpperCase();
var=lineV.elementAt(1).toUpperCase();
if(cmd.equals("SET")&&(var.equalsIgnoreCase("NAME")))
{
final String str=CMParms.combine(lineV,2);
if(str.equalsIgnoreCase(named))
return "A quest called '"+named+"' already exists. Better to pick a new name or modify the existing one.";
}
}
}
}
if(save)
{
final CMFile F=new CMFile(Resources.makeFileResourceName(holidayFilename),null);
F.saveText(getDefaultHoliData(named,areaName),true);
final Quest Q=fetchQuest("holidays");
if(Q!=null)
Q.setScript(holidayDefinition,true);
}
return "";
}
@Override
public StringBuffer getDefaultHoliData(final String named, final String area)
{
final StringBuffer newHoliday=new StringBuffer("");
newHoliday.append("\n\rSET NAME "+named+"\n\r");
newHoliday.append("SET WAIT 900+(1?100)\n\r");
newHoliday.append("SET INTERVAL 1\n\r");
newHoliday.append("SET DURATION 900\n\r");
newHoliday.append("SET PERSISTANCE TRUE\n\r");
newHoliday.append("SET AREAGROUP \""+area+"\"\n\r");
newHoliday.append("QUIET\n\r");
newHoliday.append("SET MOBGROUP RESELECT MASK=+INT 3\n\r");
newHoliday.append("GIVE BEHAVIOR MUDCHAT +(|"+named+")\\;9Happy "+named+" $n!\\;\n\r");
newHoliday.append("SET MOBGROUP RESELECT MASK=-JAVACLASS +GenShopkeeper +StdShopKeeper\n\r");
newHoliday.append("GIVE STAT PRICEMASKS 0.75 -MATERIAL +CLOTH\n\r");
newHoliday.append("STEP BREAK\n\r");
return newHoliday;
}
@Override
@SuppressWarnings("unchecked")
public String deleteHoliday(final int holidayNumber)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
return (String)resp;
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return "Unknown error.";
if((holidayNumber<=0)||(holidayNumber>=steps.size()))
return holidayNumber+" does not exist as a holiday -- enter LIST HOLIDAYS.";
String step=null;
final StringBuffer buf=new StringBuffer("");
steps.remove(holidayNumber);
for(int v=0;v<steps.size();v++)
{
step=steps.get(v);
buf.append(step+"\n\r");
}
final CMFile F=new CMFile(Resources.makeFileResourceName(holidayFilename),null);
F.saveText(buf);
final Quest Q=fetchQuest("holidays");
if(Q!=null)
Q.setScript(holidayDefinition,true);
return "Holiday deleted.";
}
@Override
@SuppressWarnings("unchecked")
public String getHolidayName(final int index)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
{
return "";
}
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return "";
if((index<0)||(index>=steps.size()))
return "";
Vector<String> lineV=null;
String line=null;
String var=null;
String cmd=null;
String step=null;
step=steps.get(index);
final List<String> stepV=Resources.getFileLineVector(new StringBuffer(step));
for(int v1=0;v1<stepV.size();v1++)
{
line=stepV.get(v1);
lineV=CMParms.parse(line);
if(lineV.size()>1)
{
cmd=lineV.elementAt(0).toUpperCase();
var=lineV.elementAt(1).toUpperCase();
if(cmd.equals("SET")&&(var.equalsIgnoreCase("NAME")))
return CMParms.combine(lineV,2);
}
}
return "";
}
@Override
@SuppressWarnings("unchecked")
public int getHolidayIndex(final String named)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
{
return -1;
}
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return -1;
Vector<String> lineV=null;
String line=null;
String var=null;
String cmd=null;
String step=null;
for(int v=1;v<steps.size();v++)
{
step=steps.get(v);
final List<String> stepV=Resources.getFileLineVector(new StringBuffer(step));
for(int v1=0;v1<stepV.size();v1++)
{
line=stepV.get(v1);
lineV=CMParms.parse(line);
if(lineV.size()>1)
{
cmd=lineV.elementAt(0).toUpperCase();
var=lineV.elementAt(1).toUpperCase();
if(cmd.equals("SET")&&(var.equalsIgnoreCase("NAME")))
{
final String str=CMParms.combine(lineV,2);
if(str.equalsIgnoreCase(named))
return v;
}
}
}
}
return -1;
}
public int startLineIndex(final List<String> V, String start)
{
start=start.toUpperCase().trim();
for(int v=0;v<V.size();v++)
{
if(V.get(v).toUpperCase().trim().startsWith(start))
return v;
}
return -1;
}
@Override
public HolidayData getEncodedHolidayData(final String dataFromStepsFile)
{
final List<String> stepV=Resources.getFileLineVector(new StringBuffer(dataFromStepsFile));
for(int v=0;v<stepV.size();v++)
stepV.set(v,CMStrings.replaceAll(stepV.get(v),"\\;",";"));
final TriadList<String,String,Integer> settings=new TriadVector<String,String,Integer>();
final TriadList<String,String,Integer> behaviors=new TriadVector<String,String,Integer>();
final TriadList<String,String,Integer> properties=new TriadVector<String,String,Integer>();
final TriadList<String,String,Integer> stats=new TriadVector<String,String,Integer>();
Vector<String> lineV=null;
String line=null;
String var=null;
String cmd=null;
int pricingMobIndex=-1;
final String[] SETTINGS={"NAME","WAIT","DATE","DURATION","EXPIRATION","MUDDAY","AREAGROUP","MOBGROUP"};
for(int v=0;v<stepV.size();v++)
{
line=stepV.get(v);
lineV=CMParms.parse(line);
if(lineV.size()>1)
{
cmd=lineV.elementAt(0).toUpperCase();
var=lineV.elementAt(1).toUpperCase();
if(cmd.equals("SET")&&(CMParms.indexOf(SETTINGS,var)>=0))
{
if(!settings.containsFirst(var))
{
String str=CMParms.combineQuoted(lineV,2);
if(str.toUpperCase().startsWith("ANY "))
str=str.substring(4);
if(str.toUpperCase().startsWith("RESELECT MASK="))
str=str.substring(14);
if(str.toUpperCase().startsWith("MASK="))
str=str.substring(5);
settings.add(var,str,Integer.valueOf(v));
}
else
if((var.equalsIgnoreCase("MOBGROUP"))
&&(pricingMobIndex<0)
&&(CMParms.combine(lineV,2).toUpperCase().indexOf("SHOPKEEPER")>0))
pricingMobIndex=v;
}
if(cmd.equals("GIVE")&&("BEHAVIOR".equalsIgnoreCase(var))&&(lineV.size()>2)&&(pricingMobIndex<0))
{
var=lineV.elementAt(2).toUpperCase();
behaviors.add(var,CMParms.combineQuoted(lineV,3),Integer.valueOf(v));
}
if(cmd.equals("GIVE")&&("AFFECT".equalsIgnoreCase(var))&&(lineV.size()>2)&&(pricingMobIndex<0))
{
var=lineV.elementAt(2).toUpperCase();
properties.add(var,CMParms.combineQuoted(lineV,3),Integer.valueOf(v));
}
if(cmd.equals("GIVE")&&("STAT".equalsIgnoreCase(var))&&(lineV.size()>2))
{
var=lineV.elementAt(2).toUpperCase();
if((pricingMobIndex<0)||(var.equals("PRICEMASKS")))
stats.add(var,CMParms.combineQuoted(lineV,3),Integer.valueOf(v));
}
}
}
final Integer pricingMobIndexI = Integer.valueOf(pricingMobIndex);
return new HolidayData()
{
@Override
public TriadList<String, String, Integer> settings()
{
return settings;
}
@Override
public TriadList<String, String, Integer> behaviors()
{
return behaviors;
}
@Override
public TriadList<String, String, Integer> properties()
{
return properties;
}
@Override
public TriadList<String, String, Integer> stats()
{
return stats;
}
@Override
public List<String> stepV()
{
return stepV;
}
@Override
public Integer pricingMobIndex()
{
return pricingMobIndexI;
}
};
}
@Override
@SuppressWarnings("unchecked")
public void modifyHoliday(final MOB mob, final int holidayNumber)
{
final Object resp=getHolidayFile();
if(resp instanceof String)
{
mob.tell((String)resp);
return;
}
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
{
mob.tell(L("Unknown error."));
return;
}
if((holidayNumber<=0)||(holidayNumber>=steps.size()))
{
mob.tell(L("@x1 does not exist as a holiday -- enter LIST HOLIDAYS.",""+holidayNumber));
return;
}
final String step=steps.get(holidayNumber);
final HolidayData encodedData=getEncodedHolidayData(step);
final TriadList<String,String,Integer> settings=encodedData.settings();
final TriadList<String,String,Integer> behaviors=encodedData.behaviors();
final TriadList<String,String,Integer> properties=encodedData.properties();
final TriadList<String,String,Integer> stats=encodedData.stats();
final int oldNameIndex=settings.indexOfFirst("NAME");
if((mob.isMonster())||(oldNameIndex<0))
return;
final String oldName=settings.get(oldNameIndex).second;
boolean ok=false;
int showFlag=-1;
if(CMProps.getIntVar(CMProps.Int.EDITORTYPE)>0)
showFlag=-999;
try
{
while((mob.session()!=null)&&(!mob.session().isStopped())&&(!ok))
{
int showNumber=0;
promptText(mob,settings,"NAME",++showNumber,showFlag,"Holiday Name","It's, well, a name.",false);
showNumber=promptDuration(mob,settings,showNumber,showFlag);
if(settings.indexOfFirst("AREAGROUP")>=0)
promptText(mob,settings,"AREAGROUP",++showNumber,showFlag,"Areas List (?)","Area names are space separated, and words grouped using double-quotes",false);
if(settings.indexOfFirst("MOBGROUP")>=0)
promptText(mob,settings,"MOBGROUP",++showNumber,showFlag,"Mask for mobs that apply (?)",CMLib.masking().maskHelp("\n\r","disallow"),false);
promptText(mob,properties,"MOOD",++showNumber,showFlag,"Mood setting (?)","NULL/Empty (to not use a Mood), or one of: FORMAL, POLITE, HAPPY, SAD, ANGRY, RUDE, MEAN, PROUD, GRUMPY, EXCITED, SCARED, LONELY",true);
promptText(mob,behaviors,"AGGRESSIVE",++showNumber,showFlag,"Aggressive setting (?)",CMLib.help().getHelpText("Aggressive",mob,true)+"\n\r\n\r** NULL/Empty (to not use Aggressive **",true);
showNumber=genPricing(mob,stats,++showNumber,showFlag);
showNumber=genMudChat(mob,"MUDCHAT",behaviors,++showNumber,showFlag);
showNumber=genBehaviors(mob,behaviors,++showNumber,showFlag);
showNumber=genProperties(mob,properties,++showNumber,showFlag);
if(showFlag<-900)
{
ok=true;
break;
}
if(showFlag>0)
{
showFlag=-1;
continue;
}
showFlag=CMath.s_int(mob.session().prompt(L("Edit which? "),""));
if(showFlag<=0)
{
showFlag=-1;
ok=true;
}
}
}
catch (final java.io.IOException e)
{
return;
}
if(ok)
{
final String err=alterHoliday(oldName, encodedData);
if(err.length()==0)
mob.tell(L("Holiday modified."));
else
mob.tell(err);
}
}
@Override
@SuppressWarnings("unchecked")
public String alterHoliday(final String oldName, final HolidayData newData)
{
final TriadList<String,String,Integer> settings=newData.settings();
final TriadList<String,String,Integer> behaviors=newData.behaviors();
final TriadList<String,String,Integer> properties=newData.properties();
final TriadList<String,String,Integer> stats=newData.stats();
//List stepV=(List)data.elementAt(4);
final int pricingMobIndex=newData.pricingMobIndex().intValue();
final int holidayNumber=getHolidayIndex(oldName);
final Object resp=getHolidayFile();
if(resp instanceof String)
return (String)resp;
List<String> steps=null;
if(resp instanceof List)
steps=(List<String>)resp;
else
return "Unknown error.";
String step = null;
List<String> stepV = null;
HolidayData encodedData = null;
final StringBuffer buf=new StringBuffer("");
for(int v=0;v<steps.size();v++)
{
step=steps.get(v);
if(v==holidayNumber)
{
encodedData=getEncodedHolidayData(step);
final TriadList<String,String,Integer> oldBehaviors=new TriadVector<String,String,Integer>(encodedData.behaviors());
final TriadList<String,String,Integer> oldProperties=new TriadVector<String,String,Integer>(encodedData.properties());
stepV=encodedData.stepV();
int index=startLineIndex(stepV,"SET NAME");
stepV.set(index,"SET NAME "+settings.get(settings.indexOfFirst("NAME")).second);
index=startLineIndex(stepV,"SET DURATION");
stepV.set(index,"SET DURATION "+settings.get(settings.indexOfFirst("DURATION")).second);
int intervalLine=startLineIndex(stepV,"SET MUDDAY");
if(intervalLine<0)
intervalLine=startLineIndex(stepV,"SET DATE");
if(intervalLine<0)
intervalLine=startLineIndex(stepV,"SET WAIT");
final int mudDayIndex=settings.indexOfFirst("MUDDAY");
final int dateIndex=settings.indexOfFirst("DATE");
final int waitIndex=settings.indexOfFirst("WAIT");
if(mudDayIndex>=0)
stepV.set(intervalLine,"SET MUDDAY "+(settings.get(mudDayIndex).second));
else
if(dateIndex>=0)
stepV.set(intervalLine,"SET DATE "+(settings.get(dateIndex).second));
else
stepV.set(intervalLine,"SET WAIT "+(settings.get(waitIndex).second));
index=settings.indexOfFirst("AREAGROUP");
if(index>=0)
{
index=startLineIndex(stepV,"SET AREAGROUP");
if(index>=0)
stepV.set(index,"SET AREAGROUP "+settings.get(settings.indexOfFirst("AREAGROUP")).second);
}
index=settings.indexOfFirst("MOBGROUP");
if(index>=0)
{
index=startLineIndex(stepV,"SET MOBGROUP");
stepV.set(index,"SET MOBGROUP RESELECT MASK="+settings.get(settings.indexOfFirst("MOBGROUP")).second);
}
if((pricingMobIndex>0)&&(stats.indexOfFirst("PRICEMASKS")>=0))
{
index=startLineIndex(stepV,"GIVE STAT PRICEMASKS");
final String s=stats.get(stats.indexOfFirst("PRICEMASKS")).second;
if(s.trim().length()==0)
{
if(index>=0)
stepV.remove(index);
}
else
{
if(index>=0)
stepV.set(index,"GIVE STAT PRICEMASKS "+s);
else
stepV.add(pricingMobIndex+1,"GIVE STAT PRICEMASKS "+s);
}
}
int mobGroupIndex=startLineIndex(stepV,"SET MOBGROUP");
index=behaviors.indexOfFirst("AGGRESSIVE");
if(index>=0)
{
index=startLineIndex(stepV,"GIVE BEHAVIOR AGGRESSIVE");
final String s=behaviors.get(behaviors.indexOfFirst("AGGRESSIVE")).second;
if(s.trim().length()==0)
{
if(index>=0)
stepV.remove(index);
}
else
{
if(index>=0)
stepV.set(index,"GIVE BEHAVIOR AGGRESSIVE "+s);
else
stepV.add(mobGroupIndex+1,"GIVE BEHAVIOR AGGRESSIVE "+s);
}
}
mobGroupIndex=startLineIndex(stepV,"SET MOBGROUP");
index=behaviors.indexOfFirst("MUDCHAT");
if(index>=0)
{
index=startLineIndex(stepV,"GIVE BEHAVIOR MUDCHAT");
final String s=behaviors.get(behaviors.indexOfFirst("MUDCHAT")).second;
if(s.trim().length()<2)
{
if(index>=0)
stepV.remove(index);
}
else
{
if(index>=0)
stepV.set(index,"GIVE BEHAVIOR MUDCHAT "+s);
else
stepV.add(mobGroupIndex+1,"GIVE BEHAVIOR MUDCHAT "+s);
}
}
mobGroupIndex=startLineIndex(stepV,"SET MOBGROUP");
index=properties.indexOfFirst("MOOD");
if(index>=0)
{
index=startLineIndex(stepV,"GIVE AFFECT MOOD");
final String s=properties.get(properties.indexOfFirst("MOOD")).second;
if(s.trim().length()==0)
{
if(index>=0)
stepV.remove(index);
}
else
{
if(index>=0)
stepV.set(index,"GIVE AFFECT MOOD "+s);
else
stepV.add(mobGroupIndex+1,"GIVE AFFECT MOOD "+s);
}
}
// look for newly missing stuff
for(int p=0;p<oldProperties.size();p++)
{
final String prop=oldProperties.get(p).first;
if(properties.indexOfFirst(prop)<0)
{
index=startLineIndex(stepV,"GIVE AFFECT "+prop);
if(index>=0)
stepV.remove(index);
}
}
// look for newly missing stuff
for(int p=0;p<oldBehaviors.size();p++)
{
final String behav=oldBehaviors.get(p).first;
if(behaviors.indexOfFirst(behav)<0)
{
index=startLineIndex(stepV,"GIVE BEHAVIOR "+behav);
if(index>=0)
stepV.remove(index);
}
}
// now changed/added stuff
for(int p=0;p<properties.size();p++)
{
final String prop=properties.get(p).first;
if(prop.equalsIgnoreCase("MOOD"))
continue;
mobGroupIndex=startLineIndex(stepV,"SET MOBGROUP");
index=startLineIndex(stepV,"GIVE AFFECT "+prop);
if(index>=0)
stepV.set(index,"GIVE AFFECT "+prop.toUpperCase().trim()+" "+(properties.get(p).second));
else
stepV.add(mobGroupIndex+1,"GIVE AFFECT "+prop.toUpperCase().trim()+" "+(properties.get(p).second));
}
// now changed/added stuff
for(int p=0;p<behaviors.size();p++)
{
final String behav=behaviors.get(p).first;
if(behav.equalsIgnoreCase("AGGRESSIVE")||behav.equalsIgnoreCase("MUDCHAT"))
continue;
mobGroupIndex=startLineIndex(stepV,"SET MOBGROUP");
index=startLineIndex(stepV,"GIVE BEHAVIOR "+behav);
if(index>=0)
stepV.set(index,"GIVE BEHAVIOR "+behav.toUpperCase().trim()+" "+(behaviors.get(p).second));
else
stepV.add(mobGroupIndex+1,"GIVE BEHAVIOR "+behav.toUpperCase().trim()+" "+(behaviors.get(p).second));
}
for(int v1=0;v1<stepV.size();v1++)
{
if(stepV.get(v1).trim().length()>0)
buf.append(CMStrings.replaceAll((stepV.get(v1)+"\n\r"),";","\\;"));
}
buf.append("\n\r");
}
else
buf.append(step+"\n\r");
}
final CMFile F=new CMFile(Resources.makeFileResourceName(holidayFilename),null);
F.saveText(buf);
final Quest Q=fetchQuest("holidays");
if(Q!=null)
Q.setScript(holidayDefinition,true);
return "";
}
protected int promptDuration(final MOB mob, final TriadList<String,String,Integer> settings, int showNumber,final int showFlag)
throws IOException
{
int mudDayIndex=settings.indexOfFirst("MUDDAY");
int dateIndex=settings.indexOfFirst("DATE");
int waitIndex=settings.indexOfFirst("WAIT");
int durationIndex=settings.indexOfFirst("DURATION");
if(durationIndex<0)
{
settings.add("DURATION","900",Integer.valueOf(-1));
durationIndex=settings.indexOfFirst("DURATION");
}
++showNumber;
if((showFlag<0)||(showFlag==showNumber))
{
final String[] TYPES={"RANDOM INTERVAL","MUD-DAY","RL-DAY"};
int typeIndex=0;
if(mudDayIndex>=0)
typeIndex=1;
else
if(dateIndex>=0)
typeIndex=2;
if((showFlag<=-999)||(showFlag==showNumber))
{
String newVal="?";
while(newVal.equals("?")&&((mob.session()!=null)&&(!mob.session().isStopped())))
{
newVal=CMLib.genEd().prompt(mob,TYPES[typeIndex],showNumber,showFlag,L("Schedule type"),CMParms.toListString(TYPES));
if(CMParms.indexOf(TYPES,newVal.toUpperCase().trim())<0)
{
newVal="?";
mob.tell(L("Not a valid entry. Try ?"));
continue;
}
typeIndex=CMParms.indexOf(TYPES,newVal.toUpperCase().trim());
if((typeIndex!=0)&&(waitIndex>=0))
settings.removeFirst("WAIT");
if((typeIndex!=1)&&(mudDayIndex>=0))
settings.removeFirst("MUDDAY");
if((typeIndex!=2)&&(dateIndex>=0))
settings.removeFirst("DATE");
if((typeIndex==0)&&(waitIndex<0))
settings.add("WAIT","100",Integer.valueOf(-1));
if((typeIndex==1)&&(mudDayIndex<0))
settings.add("MUDDAY","1-1",Integer.valueOf(-1));
if((typeIndex==2)&&(dateIndex<0))
settings.add("DATE","1-1",Integer.valueOf(-1));
if(showFlag==showNumber)
return showNumber;
break;
}
mudDayIndex=settings.indexOfFirst("MUDDAY");
dateIndex=settings.indexOfFirst("DATE");
waitIndex=settings.indexOfFirst("WAIT");
durationIndex=settings.indexOfFirst("DURATION");
}
else
mob.tell(L("@x1. Schedule type: @x2",""+showNumber,TYPES[typeIndex]));
}
if(mudDayIndex>=0)
promptText(mob,settings,"MUDDAY",++showNumber,showFlag,"Mud-Day (MONTH-DAY)","It's, well, a date in form month-day.",false);
else
if(dateIndex>=0)
promptText(mob,settings,"DATE",++showNumber,showFlag,"Real Life Date (MONTH-DAY)","It's, well, a date in form month-day.",false);
else
promptText(mob,settings,"WAIT",++showNumber,showFlag,"Interval Ticks (?): ","It's in ticks; where 150 ticks=1 mud hour. You can also make random interval by using ? operator where 1?5 means random number from 1-5. Make expressions like 100+((1?5)*10)",false);
promptText(mob,settings,"DURATION",++showNumber,showFlag,"Duration Ticks (?): ","It's in ticks; where 150 ticks=1 mud hour. You can also make random durations by using ? operator where 1?5 means random number from 1-5. Make expressions like 100+((1?5)*10)",false);
return showNumber;
}
protected int genBehaviors(final MOB mob, final TriadList<String,String,Integer> behaviors, int showNumber, final int showFlag)
throws IOException
{
for(int b=0;b<=behaviors.size();b++)
{
if((b<behaviors.size())
&&(behaviors.get(b).first.equalsIgnoreCase("MUDCHAT")
||behaviors.get(b).first.equalsIgnoreCase("AGGRESSIVE")))
continue;
if((showFlag>0)&&(showFlag!=showNumber))
{
if(b<behaviors.size())
showNumber++;
continue;
}
if(b==behaviors.size())
{
if((mob.session()!=null)&&(!mob.session().isStopped()))
{
if(((showFlag<=-999)&&CMLib.genEd().prompt(mob,false,showNumber,showFlag,L("Add new mob behavior")))
||(showNumber==showFlag))
{
behaviors.add("BehaviorID","",Integer.valueOf(behaviors.size()));
b-=1;
}
else
if(showFlag==-1)
mob.tell(L("@x1. Add new mob behavior",""+showNumber));
}
continue;
}
String behavior=behaviors.get(b).first;
String parms=behaviors.get(b).second;
mob.tell(L("@x1. Behavior: @x2: @x3",""+showNumber,behavior,parms));
if((showFlag==showNumber)||(showFlag<=-999))
{
behavior=CMLib.genEd().prompt(mob,behavior,showNumber,showFlag,L("Behavior ID (NULL to delete)"),true,toStringList(CMClass.behaviors()));
if(behavior.length()==0)
{
behaviors.remove(b);
b--;
if((showFlag==showNumber))
break;
showNumber--;
continue;
}
if(CMClass.getBehavior(behavior)==null)
{
mob.tell(L("Behavior '@x1' does not exist. Use ? for a list.",behavior));
b--;
showNumber--;
continue;
}
StringBuilder help=CMLib.help().getHelpText(behavior,mob,true);
if(help==null)
help=new StringBuilder("No help on '"+behavior+"'");
parms=CMLib.genEd().prompt(mob,parms,showNumber,showFlag,L("Behavior Parameters"),help.toString());
behaviors.get(b).first = behavior;
behaviors.get(b).second = parms;
}
showNumber++;
}
return showNumber;
}
protected int genProperties(final MOB mob, final TriadList<String,String,Integer> properties, int showNumber, final int showFlag)
throws IOException
{
for(int p=0;p<=properties.size();p++)
{
if((p<properties.size())
&&(properties.get(p).first.equalsIgnoreCase("MOOD")))
continue;
if((showFlag>0)&&(showFlag!=showNumber))
{
if(p<properties.size())
showNumber++;
continue;
}
if(p==properties.size())
{
if((mob.session()!=null)&&(!mob.session().isStopped()))
{
if(((showFlag<=-999)&&CMLib.genEd().prompt(mob,false,showNumber,showFlag,L("Add new mob property")))
||(showNumber==showFlag))
{
properties.add("AbilityID","",Integer.valueOf(properties.size()));
p-=1;
}
else
if(showFlag==-1)
mob.tell(L("@x1. Add new mob property",""+showNumber));
}
continue;
}
String propertyID=properties.get(p).first;
String parms=properties.get(p).second;
mob.tell(L("@x1. Effect: @x2: @x3",""+showNumber,propertyID,parms));
if((showFlag==showNumber)||(showFlag<=-999))
{
propertyID=CMLib.genEd().prompt(mob,propertyID,showNumber,showFlag,L("Ability ID (NULL to delete)"),true,toStringList(CMClass.abilities()));
if(propertyID.length()==0)
{
properties.remove(p);
p--;
if((showFlag==showNumber))
break;
showNumber--;
continue;
}
if(CMClass.getAbility(propertyID)==null)
{
mob.tell(L("Ability '@x1' does not exist. Use ? for a list.",propertyID));
p--;
showNumber--;
continue;
}
StringBuilder help=CMLib.help().getHelpText(propertyID,mob,true);
if(help==null)
help=new StringBuilder("No help on '"+propertyID+"'");
parms=CMLib.genEd().prompt(mob,parms,showNumber,showFlag,L("Ability Parameters"),help.toString());
properties.get(p).first =propertyID;
properties.get(p).second = parms;
}
showNumber++;
}
return showNumber;
}
public static String toStringList(final Enumeration<?> e)
{
if(!e.hasMoreElements())
return "";
final StringBuffer s=new StringBuffer("");
Object o=null;
for(;e.hasMoreElements();)
{
o=e.nextElement();
if(o instanceof CMObject)
s.append(", "+((CMObject)o).ID());
else
s.append(", "+o);
}
if(s.length()==0)
return "";
return s.toString().substring(2);
}
protected int genPricing(final MOB mob, final TriadList<String,String,Integer> stats, int showNumber, final int showFlag)
throws IOException
{
final int pndex=stats.indexOfFirst("PRICEMASKS");
final String priceStr=(pndex<0)?"":(String)stats.get(pndex).second;
final List<String> priceV=CMParms.parseCommas(priceStr,true);
for(int v=0;v<=priceV.size();v++)
{
if((showFlag>0)&&(showFlag!=showNumber))
{
if(v<priceV.size())
showNumber++;
continue;
}
if(v==priceV.size())
{
if((mob.session()!=null)&&(!mob.session().isStopped()))
{
if(((showFlag<=-999)&&CMLib.genEd().prompt(mob,false,showNumber,showFlag,L("Add new price factor")))
||(showNumber==showFlag))
{
priceV.add("1.0");
v-=1;
}
else
if(showFlag==-1)
mob.tell(L("@x1. Add new price factor.",""+showNumber));
}
continue;
}
final String priceLine=priceV.get(v);
double priceFactor=0.0;
String mask="";
final int x=priceLine.indexOf(' ');
if(x<0)
priceFactor=CMath.s_double(priceLine);
else
{
priceFactor=CMath.s_double(priceLine.substring(0,x));
mask=priceLine.substring(x+1).trim();
}
mob.tell(L("@x1. Price Factor: @x2%: @x3",""+showNumber,""+Math.round(priceFactor*100.0),mask));
if((showFlag==showNumber)||(showFlag<=-999))
{
priceFactor=CMLib.genEd().prompt(mob,priceFactor,showNumber,showFlag,L("Price Factor (enter 0 to delete)"));
if(priceFactor==0.0)
{
priceV.remove(v);
v--;
if((showFlag==showNumber))
break;
showNumber--;
continue;
}
mob.tell(L("@x1. Price Factor: @x2%: @x3",""+showNumber,""+Math.round(priceFactor*100.0),mask));
mask=CMLib.genEd().prompt(mob,mask,showNumber,showFlag,L("Item mask for this price"),CMLib.masking().maskHelp("\n\r","disallow"));
priceV.set(v,priceFactor+" "+mask);
}
showNumber++;
}
final String newVal=CMParms.toListString(priceV);
if(pndex>=0)
stats.get(pndex).second = newVal;
else
stats.add("PRICEMASKS",newVal,Integer.valueOf(stats.size()));
return showNumber;
}
@Override
public String breakOutMaskString(final String s, final List<String> p)
{
String mask="";
int x=s.toUpperCase().lastIndexOf("MASK=");
if(x>=0)
{
mask=s.substring(x+5).trim();
int i=0;
while((i<p.size())&&(p.get(i).toUpperCase().indexOf("MASK=")<0))
i++;
if(i<=p.size())
{
final String pp=p.get(i);
x=pp.toUpperCase().indexOf("MASK=");
if((x>0)&&(pp.substring(0,x).trim().length()>0))
{
p.set(i,pp.substring(0,x).trim());
i++;
}
while(i<p.size())
p.remove(i);
}
}
return mask.trim();
}
@Override
public List<List<String>> breakOutMudChatVs(final String MUDCHAT, final TriadList<String,String,Integer> behaviors)
{
final int mndex=behaviors.indexOfFirst(MUDCHAT);
String mudChatStr=(mndex<0)?"":(String)behaviors.get(mndex).second;
if(mudChatStr.startsWith("+"))
mudChatStr=mudChatStr.substring(1);
final List<String> rawMCV=CMParms.parseSemicolons(mudChatStr,true);
final List<List<String>> mudChatV=new Vector<List<String>>();
String s=null;
List<String> V=new Vector<String>();
mudChatV.add(V);
for(int r=0;r<rawMCV.size();r++)
{
s=rawMCV.get(r);
if(s.startsWith("(")&&s.endsWith(")"))
{
if(V.size()>0)
{
V=new Vector<String>();
mudChatV.add(V);
}
s=s.substring(1,s.length()-1);
}
V.add(s);
}
if(V.size()==0)
mudChatV.remove(V);
return mudChatV;
}
protected int genMudChat(final MOB mob, final String var, final TriadList<String,String,Integer> behaviors, int showNumber, final int showFlag)
throws IOException
{
final int mndex=behaviors.indexOfFirst(var);
final List<List<String>> mudChatV = breakOutMudChatVs(var,behaviors);
List<String> V = null;
String s=null;
for(int v=0;v<=mudChatV.size();v++)
{
if((showFlag>0)&&(showFlag!=showNumber))
{
if(v<mudChatV.size())
showNumber++;
continue;
}
if(v==mudChatV.size())
{
if((mob.session()!=null)&&(!mob.session().isStopped()))
{
if(((showFlag<=-999)&&CMLib.genEd().prompt(mob,false,showNumber,showFlag,L("Add new mud chat")))
||(showNumber==showFlag))
{
V=new Vector<String>();
V.add("match | these | words or phrases");
V.add("9say this");
mudChatV.add(V);
v-=1;
}
else
if(showFlag==-1)
mob.tell(L("@x1. Add new mud chat.",""+showNumber));
}
continue;
}
V=mudChatV.get(v);
String words=V.get(0);
mob.tell(L("@x1. MudChat for words: @x2",""+showNumber,words));
if((showFlag==showNumber)||(showFlag<=-999))
{
words=CMLib.genEd().prompt(mob,words,showNumber,showFlag,L("Enter matching words (| delimited, NULL to delete)\n\r"),true);
if(words.trim().length()==0)
{
mudChatV.remove(v);
if((showFlag==showNumber))
break;
showNumber--;
continue;
}
V.set(0,words);
for(int v1=1;v1<=V.size();v1++)
{
if(v1==V.size())
{
if((mob.session()!=null)&&(!mob.session().isStopped())
&&(mob.session().confirm(L("Add another thing to say (y/N)"),L("NO"))))
{
V.add("9say this");
v1-=1;
}
continue;
}
s=V.get(v1);
String newStr="?";
while((newStr.equals("?"))&&(mob.session()!=null)&&(!mob.session().isStopped()))
{
newStr=mob.session().prompt(L("Enter # Weight + thing to say (?) '@x1'\n\r: ",s),s);
if(newStr.equals("?"))
mob.tell(L("Enter a number followed by a phrase to say like 9thingtosay. Enter NULL to delete this thing to say."));
else
s=newStr;
}
if(s.trim().length()==0)
{
V.remove(v1);
v1--;
continue;
}
if(!Character.isDigit(s.charAt(0)))
s="9"+s;
V.set(v1,s);
}
}
showNumber++;
}
final StringBuffer finalVal=new StringBuffer("");
for(int v=0;v<mudChatV.size();v++)
{
V=mudChatV.get(v);
if(V.size()==0)
continue;
finalVal.append("("+(V.get(0))+");");
for(int v1=1;v1<V.size();v1++)
finalVal.append((V.get(v1))+";");
finalVal.append(";");
}
if(mndex>=0)
behaviors.get(mndex).second =(finalVal.toString().trim().length()==0)?"":("+"+finalVal.toString());
else
behaviors.add(var,(finalVal.toString().trim().length()==0)?"":("+"+finalVal.toString()),Integer.valueOf(behaviors.size()));
return showNumber;
}
@Override
public List<List<String>> parseQuestCommandLines(final List<?> script, String cmdOnly, final int startLine)
{
Vector<String> line=null;
String cmd=null;
boolean inScript=false;
final List<List<String>> lines=new Vector<List<String>>();
if(cmdOnly!=null)
cmdOnly=cmdOnly.toUpperCase().trim();
for(int v=startLine;v<script.size();v++)
{
line=CMParms.parse(((String)script.get(v)));
if(line.size()==0)
continue;
cmd=line.firstElement().toUpperCase().trim();
if(cmd.equals("</SCRIPT>")&&(inScript))
{
inScript=false;
continue;
}
if(cmd.equals("<SCRIPT>"))
{
inScript=true;
continue;
}
if(cmd.equals("STEP"))
return lines;
if((cmdOnly==null)||(cmdOnly.equalsIgnoreCase(cmd)))
lines.add(line);
}
return lines;
}
@Override
public List<String> parseQuestSteps(final List<String> script, final int startLine, final boolean rawLineInput)
{
Vector<String> line=null;
String cmd=null;
final Vector<String> parsed=new Vector<String>();
StringBuffer scr=new StringBuffer("");
boolean inScript=false;
String lineStr=null;
for(int v=startLine;v<script.size();v++)
{
lineStr=script.get(v).trim();
if(lineStr.trim().equalsIgnoreCase(XMLLibrary.FILE_XML_BOUNDARY))
{
if(scr.toString().trim().length()>0)
parsed.addElement(scr.toString());
scr=new StringBuffer((script.get(v))+"\n\r");
while((++v)<script.size())
scr.append((script.get(v))+"\n\r");
break;
}
line=CMParms.parse(lineStr.toUpperCase());
if(line.size()==0)
continue;
cmd=line.firstElement().trim();
if(rawLineInput)
scr.append((script.get(v))+"\n\r");
else
scr.append(CMStrings.replaceAll((script.get(v))+"\n\r",";","\\;"));
if(cmd.equals("</SCRIPT>")&&(inScript))
{
inScript=false;
continue;
}
if(cmd.equals("<SCRIPT>"))
{
inScript=true;
continue;
}
if(cmd.equals("STEP"))
{
parsed.addElement(scr.toString());
scr=new StringBuffer("");
}
}
if(scr.toString().trim().length()>0)
parsed.add(scr.toString().trim());
return parsed;
}
@Override
@SuppressWarnings("unchecked")
public DVector getQuestTemplate(final MOB mob, String fileToGet)
{
// user security doesn't matter, because this is read-only & system files.
final int fileOpenFlag=CMFile.FLAG_LOGERRORS|(CMSecurity.isAllowedAnywhere(mob, CMSecurity.SecFlag.CMDQUESTS)?CMFile.FLAG_FORCEALLOW:0);
final CMFile tempF=new CMFile(Resources.makeFileResourceName("quests/templates"),null,fileOpenFlag);
if((!tempF.exists())||(!tempF.isDirectory()))
return null;
final CMFile[] files=tempF.listFiles();
final DVector templatesDV=new DVector(5);
final boolean parsePages=(fileToGet!=null)&&(!fileToGet.endsWith("*"));
if((fileToGet!=null)&&(fileToGet.endsWith("*")))
fileToGet=fileToGet.substring(0,fileToGet.length()-1);
if(files.length==0)
return null;
for (final CMFile file : files)
{
if((file.getName().toUpperCase().endsWith(".QUEST"))
&&((fileToGet==null)||(file.getName().toUpperCase().startsWith(fileToGet.toUpperCase().trim()))))
{
final List<String> V=Resources.getFileLineVector(file.text());
String s=null;
boolean foundStart=false;
boolean foundQuestScript=false;
DVector pageDV=null;
StringBuffer script=null;
for(int v=0;v<V.size();v++)
{
s=V.get(v).trim();
if((foundQuestScript)&&(script!=null))
script.append(s+"\n\r");
else
if(s.startsWith("#"))
{
s=s.substring(1).trim();
if(s.startsWith("!"))
{
s=s.substring(1).trim();
if(s.startsWith("QUESTMAKER_START_SCRIPT"))
{
final String name=s.substring(23).trim();
foundStart=true;
script=new StringBuffer("");
templatesDV.addElement(name,"",file.getName(),new Vector<Object>(),script);
}
else
if(s.startsWith("QUESTMAKER_END_SCRIPT")&&(foundStart))
{
foundStart=false;
foundQuestScript=true;
continue;
}
else
if(s.startsWith("QUESTMAKER_PAGE")&&(foundStart))
{
if(!parsePages)
break;
final String name=s.substring(15).trim();
pageDV=new DVector(4);
pageDV.addElement(Integer.valueOf(QuestManager.QMCommand.$TITLE.ordinal()),name,"","");
((Vector<Object>)templatesDV.elementAt(templatesDV.size()-1,4)).addElement(pageDV);
}
else
if(s.trim().length()>0)
Log.errOut("Quests","Unrecognized meta-questmaker command: "+s);
}
else
if(s.startsWith("$")&&(foundStart))
{
if(parsePages)
{
final int x=s.indexOf('=');
if(x<0)
Log.errOut("Quests","Illegal QuestMaker variable syntax: "+s);
else
if(pageDV==null)
Log.errOut("Quests","QuestMaker syntax error, QUESTMAKER_PAGE not yet designated: "+s);
else
{
final int y=s.indexOf('=',x+1);
if(y>=0)
pageDV.addElement(s.substring(x+1,y).trim(),s.substring(0,x),s.substring(y+1),"");
else
pageDV.addElement(s.substring(x+1).trim(),s.substring(0,x),"","");
String cmd=(String)pageDV.elementAt(pageDV.size()-1,1);
int mask=0;
if(cmd.startsWith("(")&&cmd.endsWith(")"))
{
mask=mask|QuestManager.QM_COMMAND_OPTIONAL;
cmd=cmd.substring(1,cmd.length()-1);
}
final QMCommand command = (QMCommand)CMath.s_valueOf(QMCommand.class, cmd);
if(command == null)
{
Log.errOut("Quests","QuestMaker syntax error, '"+cmd+"' is an unknown command");
pageDV.removeElementsAt(pageDV.size()-1);
}
else
pageDV.setElementAt(pageDV.size()-1,1,Integer.valueOf(command.ordinal()|mask));
}
}
}
else
if(foundStart)
{
if(pageDV==null)
{
if(s.length()==0)
templatesDV.setElementAt(templatesDV.size()-1,2,((String)templatesDV.elementAt(templatesDV.size()-1,2))+"\n\r\n\r");
else
templatesDV.setElementAt(templatesDV.size()-1,2,((String)templatesDV.elementAt(templatesDV.size()-1,2))+s+" ");
}
else
if(parsePages)
{
if((pageDV.size()<2)
||(((Integer)pageDV.elementAt(pageDV.size()-1,1)).intValue()==QuestManager.QMCommand.$TITLE.ordinal())
||(((Integer)pageDV.elementAt(pageDV.size()-1,1)).intValue()==QuestManager.QMCommand.$LABEL.ordinal()))
{
if(s.length()==0)
{
if(((Integer)pageDV.elementAt(pageDV.size()-1,1)).intValue()==QuestManager.QMCommand.$TITLE.ordinal())
pageDV.addElement(Integer.valueOf(QuestManager.QMCommand.$LABEL.ordinal()),"",s,"");
else
pageDV.setElementAt(pageDV.size()-1,3,((String)pageDV.elementAt(pageDV.size()-1,3))+"\n\r\n\r");
}
else
pageDV.setElementAt(pageDV.size()-1,3,((String)pageDV.elementAt(pageDV.size()-1,3))+s+" ");
}
else
pageDV.addElement(Integer.valueOf(QuestManager.QMCommand.$LABEL.ordinal()),"",s,"");
}
}
}
}
}
}
if(templatesDV.size()==0)
return null;
final DVector sortedTemplatesDV=new DVector(5);
while(templatesDV.size()>0)
{
int maxRow=0;
for(int t=1;t<templatesDV.size();t++)
{
if(((String)templatesDV.elementAt(t,1)).compareTo((String)templatesDV.elementAt(maxRow,1))<0)
maxRow=t;
}
sortedTemplatesDV.addElement(templatesDV.elementAt(maxRow,1),
templatesDV.elementAt(maxRow,2),
templatesDV.elementAt(maxRow,3),
templatesDV.elementAt(maxRow,4),
templatesDV.elementAt(maxRow,5));
templatesDV.removeElementsAt(maxRow);
}
return sortedTemplatesDV;
}
protected String addXMLQuestMob(final MOB mob,
final int showFlag,
final DVector pageDV,
final String showValue,
final String parm1Fixed,
String lastLabel,
final boolean optionalEntry,
final int step,
final int showNumber)
throws IOException
{
MOB M=null;
final List<MOB> choices=new ArrayList<MOB>();
MOB baseM=((showValue!=null)?baseM=CMLib.coffeeMaker().getMobFromXML(showValue):null);
final StringBuffer choiceDescs=new StringBuffer("");
if(baseM!=null)
{
choices.add(baseM);
choiceDescs.append(baseM.name()+", ");
}
final Room R=mob.location();
if(R!=null)
for(int i=0;i<R.numInhabitants();i++)
{
M=R.fetchInhabitant(i);
if((M!=null)&&(M.isSavable()))
{
choices.add(M);
choiceDescs.append(M.name()+", ");
}
}
final List<MOB> newMobs=new ArrayList<MOB>();
for(final Enumeration<MOB> e=CMClass.mobTypes();e.hasMoreElements();)
{
M=e.nextElement();
if(M.isGeneric())
{
M=(MOB)M.copyOf();
newMobs.add(M);
M.setName(L("A NEW @x1",M.ID().toUpperCase()));
choices.add(M);
choiceDescs.append(M.name()+", ");
}
}
final MOB canMOB=CMClass.getFactoryMOB();
canMOB.setName(L("CANCEL"));
choiceDescs.append("CANCEL");
choices.add(canMOB);
String showName=showValue;
if(baseM!=null)
showName=CMLib.english().getContextName(choices,baseM);
lastLabel=((lastLabel==null)?"":lastLabel)+"\n\rChoices: "+choiceDescs.toString();
final GenericEditor.CMEval evaler = getQuestCommandEval(QMCommand.$MOBXML);
final String s=CMLib.genEd().prompt(mob,showName,showNumber,showFlag,parm1Fixed,optionalEntry,false,lastLabel,
evaler, choices.toArray());
canMOB.destroy();
if(s.equalsIgnoreCase("CANCEL"))
return null;
M=(MOB)CMLib.english().fetchEnvironmental(choices,s,false);
if((M!=null)&&(newMobs.contains(M)))
{
final Command C=CMClass.getCommand("Modify");
if(C!=null)
C.executeInternal(mob,0,M);
// modify it!
}
final String newValue=(M!=null)?CMLib.coffeeMaker().getMobXML(M).toString():showValue;
for(int n=0;n<newMobs.size();n++)
newMobs.get(n).destroy();
return newValue==null?"":newValue.trim();
}
protected String addXMLQuestItem(final MOB mob,
final int showFlag,
final DVector pageDV,
final String showValue,
final String parm1Fixed,
String lastLabel,
final boolean optionalEntry,
final int step,
final int showNumber)
throws IOException
{
Item I=null;
final List<Item> choices=new ArrayList<Item>();
Item baseI=((showValue!=null)?baseI=CMLib.coffeeMaker().getItemFromXML(showValue):null);
final StringBuffer choiceDescs=new StringBuffer("");
if(baseI!=null)
{
choices.add(baseI);
choiceDescs.append(baseI.name()+", ");
}
final Room R=mob.location();
if(R!=null)
for(int i=0;i<R.numItems();i++)
{
I=R.getItem(i);
if((I!=null)&&(I.container()==null)&&(I.isSavable()))
{
choices.add(I);
choiceDescs.append(I.name()+", ");
}
}
final List<String> allItemNames=new Vector<String>();
CMClass.addAllItemClassNames(allItemNames,true,false,false,CMProps.getIntVar(CMProps.Int.MUDTHEME));
final List<Item> newItems=new Vector<Item>();
for(int a=0;a<allItemNames.size();a++)
{
I=CMClass.getItem(allItemNames.get(a));
if((I!=null)&&(I.isGeneric()))
{
newItems.add(I);
I.setName(L("A NEW @x1",I.ID().toUpperCase()));
choices.add(I);
choiceDescs.append(I.name()+", ");
}
}
choiceDescs.append("CANCEL");
final Item canItem=CMClass.getItem("StdItem");
canItem.setName(L("CANCEL"));
choices.add(canItem);
String showName=showValue;
if(baseI!=null)
showName=CMLib.english().getContextName(choices,baseI);
lastLabel=((lastLabel==null)?"":lastLabel)+"\n\rChoices: "+choiceDescs.toString();
final GenericEditor.CMEval evaler = getQuestCommandEval(QMCommand.$ITEMXML);
final String s=CMLib.genEd().prompt(mob,showName,showNumber,showFlag,parm1Fixed,optionalEntry,false,lastLabel,
evaler, choices.toArray());
canItem.destroy();
if(s.equalsIgnoreCase("CANCEL"))
return null;
I=(Item)CMLib.english().fetchEnvironmental(choices,s,false);
if((I!=null)&&(newItems.contains(I)))
{
final Command C=CMClass.getCommand("Modify");
if(C!=null)
C.executeInternal(mob,0,I);
// modify it!
}
final String newValue=(I!=null)?CMLib.coffeeMaker().getItemXML(I).toString():showValue;
for(int n=0;n<newItems.size();n++)
newItems.get(n).destroy();
return (newValue==null)?"":newValue.trim();
}
@Override
public List<Quest> getPlayerPersistentQuests(final MOB player)
{
final Vector<Quest> qVec=new Vector<Quest>();
for(final Enumeration<ScriptingEngine> e=player.scripts();e.hasMoreElements();)
{
final ScriptingEngine SE=e.nextElement();
if(SE==null)
continue;
if(SE.defaultQuestName().length()>1)
{
final Quest Q=CMLib.quests().fetchQuest(SE.defaultQuestName());
if(Q==null)
{
SE.endQuest(player, player, SE.defaultQuestName());
player.delScript(SE);
}
else
qVec.add(Q);
}
}
return qVec;
}
@Override
@SuppressWarnings("unchecked")
public Quest questMaker(final MOB mob)
{
if(mob.isMonster())
return null;
final DVector questTemplates=getQuestTemplate(mob,null);
try
{
if((questTemplates==null)||(questTemplates.size()==0))
{
mob.tell(L("No valid quest templates found in resources/quests/templates!"));
return null;
}
int questIndex=-1;
while((questIndex<0)&&(mob.session()!=null)&&(!mob.session().isStopped()))
{
final String choice=mob.session().prompt(L("Select a quest template (?): "),"");
if(choice.equals("?"))
{
final StringBuffer fullList=new StringBuffer("\n\r^HCANCEL^N -- to cancel.\n\r");
for(int t=0;t<questTemplates.size();t++)
fullList.append("^H"+(String)questTemplates.elementAt(t,1)+"^N\n\r"+(String)questTemplates.elementAt(t,2)+"\n\r");
mob.tell(fullList.toString());
}
else
if((choice.length()==0)||(choice.equalsIgnoreCase("CANCEL")))
return null;
else
{
final StringBuffer list=new StringBuffer("");
for(int t=0;t<questTemplates.size();t++)
if(choice.equalsIgnoreCase((String)questTemplates.elementAt(t,1)))
questIndex=t;
else
list.append(((String)questTemplates.elementAt(t,1))+", ");
if(questIndex<0)
mob.tell(L("'@x1' is not a valid quest name, use ? for a list, or select from the following: @x2",choice,list.toString().substring(0,list.length()-2)));
}
}
if((mob.session()==null)||(mob.session().isStopped())||(questIndex<0))
return null;
final DVector qFDV=getQuestTemplate(mob,(String)questTemplates.elementAt(questIndex,3));
if((qFDV==null)||(qFDV.size()==0))
return null;
final String questTemplateName=(String)qFDV.elementAt(0,1);
final Vector<Object> qPages=(Vector<Object>)qFDV.elementAt(0,4);
mob.tell("^Z"+questTemplateName+"^.^N");
mob.tell((String)qFDV.elementAt(0,2));
for(int page=0;page<qPages.size();page++)
{
final DVector pageDV=(DVector)qPages.elementAt(page);
final String pageName=(String)pageDV.elementAt(0,2);
final String pageInstructions=(String)pageDV.elementAt(0,3);
mob.tell(L("\n\r\n\r^HPage #@x1: ^N@x2",""+(page+1),pageName));
mob.tell("^N"+pageInstructions);
boolean ok=false;
int showFlag=-999;
while((mob.session()!=null)&&(!mob.session().isStopped())&&(!ok))
{
int showNumber=0;
String lastLabel=null;
for(int step=1;step<pageDV.size();step++)
{
final Integer stepType=(Integer)pageDV.elementAt(step,1);
final String keyName=(String)pageDV.elementAt(step,2);
final String defValue=(String)pageDV.elementAt(step,3);
String parm1Fixed=CMStrings.capitalizeAndLower(keyName.replace('_',' '));
if(parm1Fixed.startsWith("$"))
parm1Fixed=parm1Fixed.substring(1);
final boolean optionalEntry=CMath.bset(stepType.intValue(),QuestManager.QM_COMMAND_OPTIONAL);
final int inputCode=stepType.intValue()&QuestManager.QM_COMMAND_MASK;
final QMCommand inputCommand = QMCommand.values()[inputCode];
switch(inputCommand)
{
case $TITLE:
break;
case $HIDDEN:
pageDV.setElementAt(step,4,defValue==null?"":defValue);
break;
case $LABEL:
lastLabel = defValue;
break;
case $EXPRESSION:
case $TIMEEXPRESSION:
case $UNIQUE_QUEST_NAME:
case $STRING:
case $LONG_STRING:
case $NAME:
case $ZAPPERMASK:
case $ROOMID:
{
final String showValue=(showFlag<-900)?defValue:(String)pageDV.elementAt(step,4);
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
if(inputCommand==QMCommand.$ZAPPERMASK)
lastLabel=(lastLabel==null?"":lastLabel)+"\n\r"+CMLib.masking().maskHelp("\n\r","disallows");
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,lastLabel,
evaler,null);
pageDV.setElementAt(step,4,s);
break;
}
case $AREA:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final StringBuffer label=new StringBuffer(((lastLabel==null)?"":lastLabel)+"\n\rChoices: ");
for(final Enumeration<Area> e=CMLib.map().areas();e.hasMoreElements();)
label.append("\""+e.nextElement().name()+"\" ");
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,label.toString(),
evaler,
null);
pageDV.setElementAt(step,4,s);
break;
}
case $EXISTING_QUEST_NAME:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final StringBuffer label=new StringBuffer(((lastLabel==null)?"":lastLabel)+"\n\rChoices: ");
for(int q=0;q<CMLib.quests().numQuests();q++)
label.append("\""+CMLib.quests().fetchQuest(q).name()+"\" ");
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,label.toString(),
evaler, null);
pageDV.setElementAt(step,4,s);
break;
}
case $ABILITY:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final StringBuffer label=new StringBuffer(((lastLabel==null)?"":lastLabel)+"\n\rChoices: ");
for(final Enumeration<Ability> e=CMClass.abilities();e.hasMoreElements();)
label.append(e.nextElement().ID()+" ");
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,label.toString(),
evaler, null);
pageDV.setElementAt(step,4,s);
break;
}
case $CHOOSE:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final String label=((lastLabel==null)?"":lastLabel)+"\n\rChoices: "+defValue;
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,label,
evaler,
CMParms.toStringArray(CMParms.parseCommas(defValue.toUpperCase(),true)));
pageDV.setElementAt(step,4,s);
break;
}
case $ITEMXML:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final String newValue=addXMLQuestItem(mob, showFlag, pageDV, showValue, parm1Fixed, lastLabel, optionalEntry, step, ++showNumber);
if(newValue!=null)
pageDV.setElementAt(step,4,newValue);
break;
}
case $ITEMXML_ZEROORMORE:
case $ITEMXML_ONEORMORE:
{
String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final Vector<String> itemXMLs=new Vector<String>();
int x=showValue.indexOf("</ITEM><ITEM>");
while(x>=0)
{
final String xml=showValue.substring(0,x+7).trim();
if(xml.length()>0)
itemXMLs.addElement(xml);
showValue=showValue.substring(x+7);
x=showValue.indexOf("</ITEM><ITEM>");
}
if(showValue.trim().length()>0)
itemXMLs.addElement(showValue.trim());
String newValue=null;
for(int i=0;i<=itemXMLs.size();i++)
{
showValue=(i<itemXMLs.size())?(String)itemXMLs.elementAt(i):"";
final boolean optional=(i==0)?optionalEntry:true;
final String thisValue=addXMLQuestItem(mob, showFlag, pageDV, showValue, parm1Fixed, lastLabel, optional, step, ++showNumber);
if(thisValue!=null)
{
if(newValue==null)
newValue="";
newValue+=thisValue;
if((thisValue.length()>0)
&&(i==itemXMLs.size()))
itemXMLs.addElement(thisValue);
}
}
if(newValue!=null)
pageDV.setElementAt(step,4,newValue);
break;
}
case $MOBXML:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final String newValue=addXMLQuestMob(mob, showFlag, pageDV, showValue, parm1Fixed, lastLabel, optionalEntry, step, ++showNumber);
if(newValue!=null)
pageDV.setElementAt(step,4,newValue);
break;
}
case $MOBXML_ONEORMORE:
{
String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final Vector<String> mobXMLs=new Vector<String>();
int x=showValue.indexOf("</MOB><MOB>");
while(x>=0)
{
final String xml=showValue.substring(0,x+6).trim();
if(xml.length()>0)
mobXMLs.addElement(xml);
showValue=showValue.substring(x+6);
x=showValue.indexOf("</MOB><MOB>");
}
if(showValue.trim().length()>0)
mobXMLs.addElement(showValue.trim());
String newValue=null;
for(int i=0;i<=mobXMLs.size();i++)
{
showValue=(i<mobXMLs.size())?(String)mobXMLs.elementAt(i):"";
final boolean optional=(i==0)?optionalEntry:true;
final String thisValue=addXMLQuestMob(mob, showFlag, pageDV, showValue, parm1Fixed, lastLabel, optional, step, ++showNumber);
if(thisValue!=null)
{
if(newValue==null)
newValue="";
newValue+=thisValue;
if((thisValue.length()>0)
&&(i==mobXMLs.size()))
mobXMLs.addElement(thisValue);
}
}
if(newValue!=null)
pageDV.setElementAt(step,4,newValue);
break;
}
case $FACTION:
{
final String showValue=(showFlag<-900)?"":(String)pageDV.elementAt(step,4);
final StringBuffer label=new StringBuffer(((lastLabel==null)?"":lastLabel)+"\n\rChoices: ");
for(final Enumeration<Faction> f=CMLib.factions().factions();f.hasMoreElements();)
label.append("\""+f.nextElement().name()+"\" ");
final GenericEditor.CMEval evaler = getQuestCommandEval(inputCommand);
final String s=CMLib.genEd().prompt(mob,showValue,++showNumber,showFlag,parm1Fixed,optionalEntry,false,label.toString(),
evaler, null);
pageDV.setElementAt(step,4,s);
break;
}
}
}
if(showFlag<-900)
{
ok=false;
showFlag=0;
mob.tell(L("\n\r^HNow verify this page's selections:^.^N"));
continue;
}
if(showFlag>0)
{
showFlag=-1;
continue;
}
final String what=mob.session().prompt(L("Edit which (enter 0 to cancel)? "),"");
if(what.trim().equals("0"))
{
if(mob.session().confirm(L("Are you sure you want to abort (y/N)? "),"N"))
{
mob.tell(L("Aborted."));
return null;
}
}
showFlag=CMath.s_int(what);
if(showFlag<=0)
{
showFlag=-1;
ok=true;
// all done
}
}
if((mob.session()==null)||(mob.session().isStopped()))
return null;
}
String name="";
String script=((StringBuffer)qFDV.elementAt(0,5)).toString();
String var=null;
String val=null;
for(int page=0;page<qPages.size();page++)
{
final DVector pageDV=(DVector)qPages.elementAt(page);
for(int v=0;v<pageDV.size();v++)
{
var=(String)pageDV.elementAt(v,2);
val=(String)pageDV.elementAt(v,4);
if(((Integer)pageDV.elementAt(v,1)).intValue()==QMCommand.$UNIQUE_QUEST_NAME.ordinal())
name=val;
script=CMStrings.replaceAll(script,var,val);
}
}
script=CMStrings.replaceAll(script,"$#AUTHOR",mob.Name());
if((mob.session()!=null)&&(!mob.session().isStopped())
&&(mob.session().confirm(L("Create the new quest: @x1 (y/N)? ",name),"N")))
{
final Quest Q=(Quest)CMClass.getCommon("DefaultQuest");
final CMFile newQF=new CMFile(Resources.makeFileResourceName("quests/"+name+".quest"),mob,CMFile.FLAG_LOGERRORS);
newQF.saveText(script);
Q.setScript("LOAD=quests/"+name+".quest",true);
if((Q.name().trim().length()==0)||(Q.duration()<0))
{
mob.tell(L("You must specify a VALID quest string. This one contained errors. Try AHELP QUESTS."));
return null;
}
CMLib.quests().addQuest(Q);
CMLib.quests().save();
return Q;
}
return null;
}
catch(final java.io.IOException e)
{
return null;
}
}
@Override
public GenericEditor.CMEval getQuestCommandEval(final QMCommand command)
{
switch(command)
{
case $TITLE:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // title
return str;
}
};
case $LABEL:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // label
return str;
}
};
case $EXPRESSION:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // expression
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an expression!");
}
if (!CMath.isMathExpression((String) str))
throw new CMException("Invalid mathematical expression. Use numbers,+,-,*,/,(), and ? only.");
return str;
}
};
case $UNIQUE_QUEST_NAME:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // quest name
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a quest name!");
}
for (int i = 0; i < ((String) str).length(); i++)
{
if ((!Character.isLetterOrDigit(((String) str).charAt(i))) && (((String) str).charAt(i) != '_'))
throw new CMException("Quest names may only contain letters, digits, or _ -- no spaces or special characters.");
}
if (CMLib.quests().fetchQuest(((String) str).trim()) != null)
throw new CMException("A quest of that name already exists. Enter another.");
return ((String) str).trim();
}
};
case $CHOOSE:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // choose
if ((choices == null) || (choices.length == 0))
throw new CMException("NO choices?!");
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a value!");
}
final int x = CMParms.indexOf(choices, ((String) str).toUpperCase().trim());
if (x < 0)
throw new CMException("That is not a valid option. Choices include: " + CMParms.toListString(choices));
return choices[x];
}
};
case $ITEMXML:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // itemxml
if ((choices == null) || (choices.length == 0))
throw new CMException("NO choices?!");
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
StringBuffer choiceNames = new StringBuffer("");
for (final Object choice : choices)
choiceNames.append(((Environmental) choice).Name() + ", ");
if (choiceNames.toString().endsWith(", "))
choiceNames = new StringBuffer(choiceNames.substring(0, choiceNames.length() - 2));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter one of the following: " + choiceNames.toString());
}
final Environmental[] ES = new Environmental[choices.length];
for (int e = 0; e < choices.length; e++)
ES[e] = (Environmental) choices[e];
final Environmental E = CMLib.english().fetchEnvironmental(Arrays.asList(ES), (String) str, false);
if (E == null)
throw new CMException("'" + str + "' was not found. You must enter one of the following: " + choiceNames.toString());
return CMLib.english().getContextName(ES, E);
}
};
case $STRING:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // string
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a value!");
}
return str;
}
};
case $ROOMID:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // roomid
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an room id(s), name(s), keyword ANY, or ANY MASK=...");
}
if (((String) str).trim().equalsIgnoreCase("ANY"))
return ((String) str).trim();
if (((String) str).trim().toUpperCase().startsWith("ANY MASK="))
return str;
if (CMStrings.contains(Quest.ROOM_REFERENCE_QCODES, ((String) str).toUpperCase().trim()))
return ((String) str).toUpperCase().trim();
if ((((String) str).indexOf(' ') > 0) && (((String) str).indexOf('\"') < 0))
throw new CMException(
"Multiple-word room names/ids must be grouped with double-quotes. If this represents several names, put each name in double-quotes as so: \"name1\" \"name2\" \"multi word name\".");
final Vector<String> V = CMParms.parse((String) str);
if (V.size() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an room id(s), name(s), keyword ANY, or ANY MASK=...");
}
String s = null;
for (int v = 0; v < V.size(); v++)
{
s = V.elementAt(v);
boolean found = false;
final Room R = CMLib.map().getRoom(s);
if (R != null)
found = true;
if (!found)
found = CMLib.map().findWorldRoomLiberally(null, s, "R", 50, 30000) != null;
if (!found)
throw new CMException("'" + (V.elementAt(v)) + "' is not a valid room name, id, or description.");
}
return str;
}
};
case $AREA:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // area
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an area name(s), keyword ANY, or ANY MASK=...");
}
if (((String) str).trim().equalsIgnoreCase("ANY"))
return ((String) str).trim();
if (((String) str).trim().toUpperCase().startsWith("ANY MASK="))
return str;
if ((((String) str).indexOf(' ') > 0) && (((String) str).indexOf('\"') < 0))
throw new CMException(
"Multiple-word area names/ids must be grouped with double-quotes. If this represents several names, put each name in double-quotes as so: \"name1\" \"name2\" \"multi word name\".");
final Vector<String> V = CMParms.parse((String) str);
if (V.size() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an area name(s), keyword ANY, or ANY MASK=...");
}
final StringBuffer returnStr = new StringBuffer("");
for (int v = 0; v < V.size(); v++)
{
final Area A = CMLib.map().findArea(V.elementAt(v));
if (A == null)
throw new CMException("'" + (V.elementAt(v)) + "' is not a valid area name.");
returnStr.append("\"" + A.name() + "\" ");
}
return returnStr.toString().trim();
}
};
case $MOBXML:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // mobxml
if ((choices == null) || (choices.length == 0))
throw new CMException("NO choices?!");
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
StringBuffer choiceNames = new StringBuffer("");
for (final Object choice : choices)
choiceNames.append(((Environmental) choice).Name() + ", ");
if (choiceNames.toString().endsWith(", "))
choiceNames = new StringBuffer(choiceNames.substring(0, choiceNames.length() - 2));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter one of the following: " + choiceNames.toString());
}
final Environmental[] ES = new Environmental[choices.length];
for (int e = 0; e < choices.length; e++)
ES[e] = (Environmental) choices[e];
final Environmental E = CMLib.english().fetchEnvironmental(Arrays.asList(ES), (String) str, false);
if (E == null)
throw new CMException("'" + str + "' was not found. You must enter one of the following: " + choiceNames.toString());
return CMLib.english().getContextName(ES, E);
}
};
case $NAME:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // designame
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a value!");
}
if (((String) str).trim().equalsIgnoreCase("ANY"))
return ((String) str).trim();
if (((String) str).trim().toUpperCase().startsWith("ANY MASK="))
return str;
if ((((String) str).indexOf(' ') > 0) && (((String) str).indexOf('\"') < 0))
throw new CMException("Multiple-word names must be grouped with double-quotes. If this represents several names, put each name in double-quotes as so: \"name1\" \"name2\" \"multi word name\".");
return str;
}
};
case $LONG_STRING:
return new GenericEditor.CMEval()
{
@Override
public Object eval(Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // string
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a value!");
}
str = CMStrings.replaceAll((String) str, "\n\r", " ");
str = CMStrings.replaceAll((String) str, "\r\n", " ");
str = CMStrings.replaceAll((String) str, "\n", " ");
str = CMStrings.replaceAll((String) str, "\r", " ");
return str;
}
};
case $MOBXML_ONEORMORE:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // mobxml_1ormore
final GenericEditor.CMEval evaler = getQuestCommandEval(QMCommand.$MOBXML);
return evaler.eval(str, choices, emptyOK);
}
};
case $ITEMXML_ZEROORMORE:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // itemxml_1ormore
final GenericEditor.CMEval evaler = getQuestCommandEval(QMCommand.$ITEMXML);
return evaler.eval(str, choices, true);
}
};
case $ITEMXML_ONEORMORE:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // itemxml_1ormore
final GenericEditor.CMEval evaler = getQuestCommandEval(QMCommand.$ITEMXML);
return evaler.eval(str, choices, emptyOK);
}
};
case $ZAPPERMASK:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // zappermask
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
final Vector<String> errors = new Vector<String>(1);
if (!CMLib.masking().syntaxCheck((String) str, errors))
throw new CMException("Mask Error: " + CMParms.toListString(errors));
return str;
}
};
case $ABILITY:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // ability
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
final StringBuffer list = new StringBuffer("");
for (final Enumeration<Ability> e = CMClass.abilities(); e.hasMoreElements();)
list.append(e.nextElement().ID() + ", ");
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an ability ID, choose from the following: " + list.toString());
}
Ability A = CMClass.getAbility((String) str);
if (A == null)
A = CMClass.findAbility((String) str);
if ((A.classificationCode() & Ability.ALL_DOMAINS) == Ability.DOMAIN_ARCHON)
A = null;
if (A == null)
throw new CMException("Invalid ability id, choose from the following: " + list.toString());
return A.ID();
}
};
case $EXISTING_QUEST_NAME:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // existing quest name
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a quest name!");
}
final Quest Q = CMLib.quests().fetchQuest(((String) str).trim());
if (Q == null)
throw new CMException("A quest of the name '" + ((String) str).trim() + "' does not exist. Enter another.");
return Q.name();
}
};
case $HIDDEN:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // hidden
return str;
}
};
case $FACTION:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // faction
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter a faction id!");
}
final Faction F = CMLib.factions().getFaction((String) str);
if (F == null)
throw new CMException("A faction of the name '" + ((String) str).trim() + "' does not exist. Enter another.");
return F.factionID();
}
};
case $TIMEEXPRESSION:
return new GenericEditor.CMEval()
{
@Override
public Object eval(final Object str, final Object[] choices, final boolean emptyOK) throws CMException
{ // timeexpression
if (!(str instanceof String))
throw new CMException("Bad type: " + ((str == null) ? "null" : str.getClass().getName()));
if (((String) str).trim().length() == 0)
{
if (emptyOK)
return "";
throw new CMException("You must enter an expression!");
}
if (!CMLib.time().isTickExpression((String) str))
throw new CMException("Invalid time mathematical expression. Use numbers,+,-,*,/,(), and ? only. You may add ticks, minutes, hours, days, mudhours, muddays, mudweeks, mudmonths, mudyears.");
return str;
}
};
}
return null;
}
}