package com.planet_ink.coffee_mud.Libraries;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
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.*;
/**
* <p>Portions Copyright (c) 2003 Jeremy Vyska</p>
* <p>Portions Copyright (c) 2004-2010 Bo Zimmerman</p>
* <p>Licensed under the Apache License, Version 2.0 (the "License");
* <p>you may not use this file except in compliance with the License.
* <p>You may obtain a copy of the License at
*
* <p> http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software
* <p>distributed under the License is distributed on an "AS IS" BASIS,
* <p>WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* <p>See the License for the specific language governing permissions and
* <p>limitations under the License.
*/
@SuppressWarnings("unchecked")
public class Factions extends StdLibrary implements FactionManager
{
public String ID(){return "Factions";}
public Hashtable factionSet = new Hashtable();
public Hashtable hashedFactionRanges=new Hashtable();
public Hashtable factionSet(){return factionSet;}
public void clearFactions()
{
factionSet.clear();
hashedFactionRanges.clear();
}
public void reloadFactions(String factionList)
{
Vector preLoadFactions=CMParms.parseSemicolons(factionList,true);
clearFactions();
for(int i=0;i<preLoadFactions.size();i++)
getFaction((String)preLoadFactions.elementAt(i));
}
public Hashtable rangeCodeNames(){ return hashedFactionRanges; }
public boolean isRangeCodeName(String key){ return rangeCodeNames().containsKey(key.toUpperCase());}
public boolean isFactionedThisWay(MOB mob, String rangeCodeName)
{
Faction F=(Faction)rangeCodeNames().get(rangeCodeName.toUpperCase());
if(F==null) return false;
Faction.FactionRange FR=(Faction.FactionRange)F.fetchRange(rangeCodeName.toUpperCase().trim());
if(FR==null) return false;
Faction.FactionRange FR2=F.fetchRange(mob.fetchFaction(F.factionID()));
if(FR2==null) return false;
return FR2.codeName().equalsIgnoreCase(FR.codeName());
}
public String rangeDescription(String rangeCodeName, String andOr)
{
Faction F=(Faction)rangeCodeNames().get(rangeCodeName.toUpperCase());
if(F==null) return "";
Faction.FactionRange FR=(Faction.FactionRange)F.fetchRange(rangeCodeName.toUpperCase().trim());
if(FR==null) return "";
Vector relevantFactions=new Vector();
for(Enumeration e=F.ranges();e.hasMoreElements();)
{
Faction.FactionRange FR2=(Faction.FactionRange)e.nextElement();
if(FR2.codeName().equalsIgnoreCase(FR.codeName()))
relevantFactions.addElement(FR2);
}
if(relevantFactions.size()==0) return "";
if(relevantFactions.size()==1)
return F.name()+" of "+((Faction.FactionRange)relevantFactions.firstElement()).name();
StringBuffer buf=new StringBuffer(F.name()+" of ");
for(int i=0;i<relevantFactions.size()-1;i++)
buf.append(((Faction.FactionRange)relevantFactions.elementAt(i)).name()+", ");
buf.append(andOr+((Faction.FactionRange)relevantFactions.lastElement()).name());
return buf.toString();
}
public Faction getFaction(String factionID)
{
if(factionID==null) return null;
Faction F=(Faction)factionSet.get(factionID.toUpperCase());
if(F!=null) return F;
CMFile FILE=new CMFile(Resources.makeFileResourceName(factionID),null,true);
if(!FILE.exists()) return null;
StringBuffer buf=FILE.text();
if((buf!=null)&&(buf.length()>0))
{
F=(Faction)CMClass.getCommon("DefaultFaction");
F.initializeFaction(buf,factionID);
for(Enumeration e=F.ranges();e.hasMoreElements();)
{
Faction.FactionRange FR=(Faction.FactionRange)e.nextElement();
String CodeName=(FR.codeName().length()>0)?FR.codeName().toUpperCase():FR.name().toUpperCase();
if(!hashedFactionRanges.containsKey(CodeName))
hashedFactionRanges.put(CodeName,F);
}
factionSet.put(factionID.toUpperCase(),F);
return F;
}
return null;
}
public Faction getFactionByRangeCodeName(String rangeCodeName)
{
if(hashedFactionRanges.containsKey(rangeCodeName.toUpperCase()))
return (Faction)hashedFactionRanges.get(rangeCodeName.toUpperCase());
return null;
}
public Faction getFactionByName(String factionNamed)
{
for(Enumeration e=factionSet.keys();e.hasMoreElements();)
{
Faction f=(Faction)factionSet.get(e.nextElement());
if(f.name().equalsIgnoreCase(factionNamed)) return f;
}
return null;
}
public boolean removeFaction(String factionID)
{
if(factionID==null)
{
for(Enumeration e=factionSet.keys();e.hasMoreElements();)
{
Faction f=(Faction)factionSet.get(e.nextElement());
removeFaction(f.factionID());
}
return true;
}
Faction F=getFactionByName(factionID);
if(F==null) F=getFaction(factionID);
if(F==null) return false;
Resources.removeResource(F.factionID());
factionSet.remove(F.factionID().toUpperCase());
return true;
}
public String listFactions()
{
StringBuffer msg=new StringBuffer();
msg.append("\n\r^.^N");
msg.append("+--------------------------------+-----------------------------------------+\n\r");
msg.append("| ^HFaction Name^N | ^HFaction INI Source File (Faction ID)^N |\n\r");
msg.append("+--------------------------------+-----------------------------------------+\n\r");
for(Enumeration e=factionSet.keys();e.hasMoreElements();)
{
Faction f=(Faction)factionSet.get(e.nextElement());
msg.append("| ");
msg.append(CMStrings.padRight(f.name(),30));
msg.append(" | ");
msg.append(CMStrings.padRight(f.factionID(),39));
msg.append(" |\n\r");
}
msg.append("+--------------------------------+-----------------------------------------+\n\r");
msg.append("\n\r");
return msg.toString();
}
public String name(){return "Factions";}
public long getTickStatus(){ return Tickable.STATUS_NOT;}
public String getName(String factionID) { Faction f=getFaction(factionID); if(f!=null) return f.name(); return ""; }
public int getMinimum(String factionID) { Faction f=getFaction(factionID); if(f!=null) return f.minimum(); return 0; }
public int getMaximum(String factionID) { Faction f=getFaction(factionID); if(f!=null) return f.maximum(); return 0; }
public int getPercent(String factionID, int faction) { Faction f=getFaction(factionID); if(f!=null) return f.asPercent(faction); return 0; }
public int getPercentFromAvg(String factionID, int faction) { Faction f=getFaction(factionID); if(f!=null) return f.asPercentFromAvg(faction); return 0; }
public Faction.FactionRange getRange(String factionID, int faction) { Faction f=getFaction(factionID); if(f!=null) return f.fetchRange(faction); return null; }
public Enumeration getRanges(String factionID) {
Faction f=getFaction(factionID);
if(f!=null) return f.ranges();
return null;
}
public double getRangePercent(String factionID, int faction)
{
Faction F=getFaction(factionID);
if(F==null) return 0.0;
return CMath.div((int)Math.round(CMath.div((faction - F.minimum()),(F.maximum() - F.minimum())) * 10000.0),100.0);
}
public int getTotal(String factionID) { Faction f=getFaction(factionID); if(f!=null) return (f.maximum()-f.minimum()); return 0; }
public int getRandom(String factionID) { Faction f=getFaction(factionID); if(f!=null) return f.randomFaction(); return 0; }
public String AlignID() { return "alignment.ini"; }
public void setAlignment(MOB mob, int newAlignment)
{
if(getFaction(AlignID())!=null)
mob.addFaction(AlignID(),getAlignThingie(newAlignment));
}
public void setAlignmentOldRange(MOB mob, int oldRange)
{
if(getFaction(AlignID())!=null)
{
if(oldRange>=650)
setAlignment(mob,Faction.ALIGN_GOOD);
else
if(oldRange>=350)
setAlignment(mob,Faction.ALIGN_NEUTRAL);
else
if(oldRange>=0)
setAlignment(mob,Faction.ALIGN_EVIL);
else{ /* a -1 value is the new norm */}
}
}
public boolean postChangeAllFactions(MOB mob, MOB victim, int amount, boolean quiet)
{
if((mob==null))
return false;
CMMsg msg=CMClass.getMsg(mob,victim,null,CMMsg.MASK_ALWAYS|CMMsg.TYP_FACTIONCHANGE,null,CMMsg.NO_EFFECT,null,CMMsg.NO_EFFECT,""+quiet);
msg.setValue(amount);
if(mob.location()!=null)
{
if(mob.location().okMessage(mob,msg))
mob.location().send(mob,msg);
else
return false;
}
return true;
}
public boolean postFactionChange(MOB mob,Environmental tool, String factionID, int amount)
{
if((mob==null))
return false;
CMMsg msg=CMClass.getMsg(mob,null,tool,CMMsg.MASK_ALWAYS|CMMsg.TYP_FACTIONCHANGE,null,CMMsg.NO_EFFECT,null,CMMsg.NO_EFFECT,factionID);
msg.setValue(amount);
if(mob.location()!=null)
{
if(mob.location().okMessage(mob,msg))
mob.location().send(mob,msg);
else
return false;
}
return true;
}
public boolean tick(Tickable ticking, int tickID)
{
if(CMLib.sessions().size()==0)
return true;
try
{
Session S=null;
MOB mob=null;
Faction F=null;
Faction.FactionChangeEvent CE=null;
DVector outSiders=new DVector(2);
DVector timers=new DVector(2);
for(Enumeration e=factionSet.elements();e.hasMoreElements();)
{
F=(Faction)e.nextElement();
CE=F.getChangeEvent("ADDOUTSIDER");
if(CE!=null) outSiders.addElement(CE,F);
CE=F.getChangeEvent("TIME");
if(CE!=null) timers.addElement(CE,F);
}
if((outSiders.size()==0)&&(timers.size()==0))
return true;
for(int s=0;s<CMLib.sessions().size();s++)
{
S=CMLib.sessions().elementAt(s);
mob=(!S.killFlag())?S.mob():null;
if(mob!=null)
{
for(int o=0;o<outSiders.size();o++)
{
CE=(Faction.FactionChangeEvent)outSiders.elementAt(o,1);
F=(Faction)outSiders.elementAt(o,2);
if((CE.applies(mob))&&(!F.hasFaction(mob)))
F.executeChange(mob,mob,CE);
}
for(int o=0;o<timers.size();o++)
{
CE=(Faction.FactionChangeEvent)timers.elementAt(o,1);
F=(Faction)timers.elementAt(o,2);
if((CE.applies(mob))&&(F.hasFaction(mob)))
F.executeChange(mob,mob,CE);
}
}
}
}catch(Exception e){}
return true;
}
public int getAlignPurity(int faction, int AlignEq)
{
int bottom=Integer.MAX_VALUE;
int top=Integer.MIN_VALUE;
int pct=getPercent(AlignID(),faction);
Enumeration e = getRanges(AlignID());
if(e!=null)
for(;e.hasMoreElements();)
{
Faction.FactionRange R=(Faction.FactionRange)e.nextElement();
if(R.alignEquiv()==AlignEq)
{
if(R.low()<bottom) bottom=R.low();
if(R.high()>top) top=R.high();
}
}
switch(AlignEq)
{
case Faction.ALIGN_GOOD:
return Math.abs(pct - getPercent(AlignID(),top));
case Faction.ALIGN_EVIL:
return Math.abs(getPercent(AlignID(),bottom) - pct);
case Faction.ALIGN_NEUTRAL:
return Math.abs(getPercent(AlignID(),(int)Math.round(CMath.div((top+bottom),2))) - pct);
default:
return 0;
}
}
// Please don't mock the name, I couldn't think of a better one. Sadly.
public int getAlignThingie(int AlignEq)
{
int bottom=Integer.MAX_VALUE;
int top=Integer.MIN_VALUE;
Enumeration e = getRanges(AlignID());
if(e==null) return 0;
for(;e.hasMoreElements();)
{
Faction.FactionRange R=(Faction.FactionRange)e.nextElement();
if(R.alignEquiv()==AlignEq) {
if(R.low()<bottom) bottom=R.low();
if(R.high()>top) top=R.high();
}
}
switch(AlignEq)
{
case Faction.ALIGN_GOOD:
return top;
case Faction.ALIGN_EVIL:
return bottom;
case Faction.ALIGN_NEUTRAL:
return (int)Math.round(CMath.div((top+bottom),2));
default:
return 0;
}
}
public int isFactionTag(String tag)
{
for(int i=0;i<Faction.TAG_NAMES.length;i++)
if(tag.equalsIgnoreCase(Faction.TAG_NAMES[i]))
return i;
else
if(Faction.TAG_NAMES[i].endsWith("*")&&tag.startsWith(Faction.TAG_NAMES[i].substring(0,Faction.TAG_NAMES[i].length()-1)))
return i;
return -1;
}
public int getAlignEquiv(String str)
{
if(str.equalsIgnoreCase(Faction.ALIGN_NAMES[Faction.ALIGN_GOOD]))
return Faction.ALIGN_GOOD;
else
if(str.equalsIgnoreCase(Faction.ALIGN_NAMES[Faction.ALIGN_NEUTRAL]))
return Faction.ALIGN_NEUTRAL;
else
if(str.equalsIgnoreCase(Faction.ALIGN_NAMES[Faction.ALIGN_EVIL]))
return Faction.ALIGN_EVIL;
else
return Faction.ALIGN_INDIFF;
}
private String getWordAffOrBehav(String ID)
{
if(CMClass.getBehavior(ID)!=null)
return "behavior";
if(CMClass.getAbility(ID)!=null)
return "ability";
return null;
}
public void modifyFaction(MOB mob, Faction me) throws IOException
{
if(mob.isMonster())
return;
boolean ok=false;
int showFlag=-1;
if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
showFlag=-999;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
{
int showNumber=0;
// name
me.setName(CMLib.genEd().prompt(mob,me.name(),++showNumber,showFlag,"Name"));
// ranges
++showNumber;
if(!me.ranges().hasMoreElements())
me.addRange("0;100;Sample Range;SAMPLE;");
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
StringBuffer list=new StringBuffer(showNumber+". Faction Division/Ranges List:\n\r");
list.append(CMStrings.padRight(" Code",16)+CMStrings.padRight("Name",21)+CMStrings.padRight("Min",11)+CMStrings.padRight("Max",11)+CMStrings.padRight("Align",6)+"\n\r");
for(Enumeration e=me.ranges();e.hasMoreElements();)
{
Faction.FactionRange FR=(Faction.FactionRange)e.nextElement();
list.append(CMStrings.padRight(" "+FR.codeName(),15)+" ");
list.append(CMStrings.padRight(FR.name(),20)+" ");
list.append(CMStrings.padRight(""+FR.low(),10)+" ");
list.append(CMStrings.padRight(""+FR.high(),10)+" ");
list.append(CMStrings.padRight(Faction.ALIGN_NAMES[FR.alignEquiv()],5)+"\n\r");
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().prompt("Enter a CODE to add, remove, or modify:","");
if(which.length()==0)
break;
which=which.trim().toUpperCase();
if(which.indexOf(' ')>=0)
{
mob.tell("Faction Range code names may not contain spaces.");
break;
}
Faction.FactionRange FR=me.fetchRange(which);
if(FR==null)
{
if(mob.session().confirm("Create a new range code named '"+which+"' (y/N): ","N"))
{
FR=me.addRange("0;100;Change My Name;"+which+";");
}
}
else
if(mob.session().choose("Would you like to M)odify or D)elete this range (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delRange(FR);
mob.tell("Range deleted.");
FR=null;
}
if(FR!=null)
{
String newName=mob.session().prompt("Enter a new name ("+FR.name()+")\n\r: ");
boolean error99=false;
if(newName.length()==0)
error99=true;
else
for(Enumeration e=me.ranges();e.hasMoreElements();)
{
Faction.FactionRange FR3=(Faction.FactionRange)e.nextElement();
if(FR3.name().equalsIgnoreCase(FR.name())&&(FR3!=FR))
{ mob.tell("A range already exists with that name!"); error99=true; break;}
}
if(error99)
mob.tell("(no change)");
else
FR.setName(newName);
newName=mob.session().prompt("Enter the low end of the range ("+FR.low()+")\n\r: ",""+FR.low());
if(!CMath.isInteger(newName))
mob.tell("(no change)");
else
FR.setLow(CMath.s_int(newName));
newName=mob.session().prompt("Enter the high end of the range ("+FR.high()+")\n\r: ",""+FR.high());
if((!CMath.isInteger(newName))||(CMath.s_int(newName)<FR.low()))
mob.tell("(no change)");
else
FR.setHigh(CMath.s_int(newName));
StringBuffer prompt=new StringBuffer("Select the 'virtue' (if any) of this range:\n\r");
StringBuffer choices=new StringBuffer("");
for(int r=0;r<Faction.ALIGN_NAMES.length;r++)
{
choices.append(""+r);
if(r==Faction.ALIGN_INDIFF)
prompt.append(r+") Not applicable\n\r");
else
prompt.append(r+") "+Faction.ALIGN_NAMES[r].toLowerCase()+"\n\r");
}
FR.setAlignEquiv(CMath.s_int(mob.session().choose(prompt.toString()+"Enter alignment equivalency or 0: ",choices.toString(),""+FR.alignEquiv())));
}
}
// show in score
me.setShowInScore(CMLib.genEd().prompt(mob,me.showInScore(),++showNumber,showFlag,"Show in 'Score'"));
// show in factions
me.setShowInFactionsCommand(CMLib.genEd().prompt(mob,me.showInFactionsCommand(),++showNumber,showFlag,"Show in 'Factions' command"));
// show in special reports
boolean alreadyReporter=false;
for(Enumeration e=CMLib.factions().factionSet().elements();e.hasMoreElements();)
{
Faction F2=(Faction)e.nextElement();
if(F2.showInSpecialReported()) alreadyReporter=true;
}
if(!alreadyReporter)
me.setShowInSpecialReported(CMLib.genEd().prompt(mob,me.showInSpecialReported(),++showNumber,showFlag,"Show in Reports"));
// show in editor
me.setShowInEditor(CMLib.genEd().prompt(mob,me.showInEditor(),++showNumber,showFlag,"Show in MOB Editor"));
// auto defaults
boolean error=true;
me.setAutoDefaults(CMParms.parseSemicolons(CMLib.genEd().prompt(mob,CMParms.toSemicolonList(me.autoDefaults()),++showNumber,showFlag,"Optional automatic assigned values with zapper masks (semicolon delimited).\n\r "),true));
// non-auto defaults
error=true;
if(!me.defaults().hasMoreElements())
me.setDefaults(CMParms.makeVector("0"));
++showNumber;
while(error&&(mob.session()!=null)&&(!mob.session().killFlag()))
{
error=false;
String newDefaults=CMLib.genEd().prompt(mob,CMParms.toSemicolonList(me.defaults()),showNumber,showFlag,"Other default values with zapper masks (semicolon delimited).\n\r ");
if((showFlag!=showNumber)&&(showFlag>-999)) break;
Vector V=CMParms.parseSemicolons(newDefaults,true);
if(V.size()==0)
{
mob.tell("This field may not be empty.");
error=true;
}
me.setDefaults(CMParms.parseSemicolons(newDefaults,true));
}
// choices and choice intro
me.setChoices(CMParms.parseSemicolons(CMLib.genEd().prompt(mob,CMParms.toSemicolonList(me.choices()),++showNumber,showFlag,"Optional new player value choices (semicolon-delimited).\n\r "),true));
if(me.choices().hasMoreElements())
me.setChoiceIntro(CMLib.genEd().prompt(mob,me.choiceIntro(),++showNumber,showFlag,"Optional choices introduction text. Filename"));
// rate modifier
String newModifier=CMLib.genEd().prompt(mob,CMath.toPct(me.rateModifier()),++showNumber,showFlag,"Rate modifier");
if((CMath.isNumber(newModifier))||(CMath.isPct(newModifier)))
me.setRateModifier(CMath.s_pct(newModifier));
// experience flag
boolean error2=true;
++showNumber;
while(error2&&(mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
error2=false;
StringBuffer nextPrompt=new StringBuffer("\n\r");
int myval=-1;
for(int i=0;i<Faction.EXPAFFECT_NAMES.length;i++)
{
if(me.experienceFlag().equalsIgnoreCase(Faction.EXPAFFECT_NAMES[i]))
myval=i;
nextPrompt.append(" "+(i+1)+") "+CMStrings.capitalizeAndLower(Faction.EXPAFFECT_NAMES[i].toLowerCase())+"\n\r");
}
if(myval<0){ me.setExperienceFlag("NONE"); myval=0;}
if((showFlag!=showNumber)&&(showFlag>-999))
{
mob.tell(showNumber+". Affect on experience: "+Faction.EXPAFFECT_NAMES[myval]);
break;
}
String prompt="Affect on experience: "+Faction.EXPAFFECT_NAMES[myval]+nextPrompt.toString()+"\n\rSelect a value: ";
int mynewval=CMLib.genEd().prompt(mob,myval+1,showNumber,showFlag,prompt);
if((showFlag!=showNumber)&&(showFlag>-999)) break;
if((mynewval<=0)||(mynewval>Faction.EXPAFFECT_NAMES.length))
{
mob.tell("That value is not valid.");
error2=true;
}
else
me.setExperienceFlag(Faction.EXPAFFECT_NAMES[mynewval-1]);
}
// factors by mask
++showNumber;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
StringBuffer list=new StringBuffer(showNumber+". Faction change adjustment Factors with Zapper Masks:\n\r");
list.append(" #) "+CMStrings.padRight("Zapper Mask",31)+CMStrings.padRight("Gain",6)+CMStrings.padRight("Loss",6)+"\n\r");
StringBuffer choices=new StringBuffer("");
int numFactors=0;
for(Enumeration e=me.factors();e.hasMoreElements();)
{
Object[] factor=(Object[])e.nextElement();
if(factor.length!=3)
me.delFactor(factor);
else
{
choices.append(((char)('A'+numFactors)));
list.append(" "+(((char)('A'+numFactors))+") "));
list.append(CMStrings.padRight((String)factor[2],30)+" ");
list.append(CMStrings.padRight(""+CMath.toPct(((Double)factor[0]).doubleValue()),5)+" ");
list.append(CMStrings.padRight(""+CMath.toPct(((Double)factor[1]).doubleValue()),5)+"\n\r");
numFactors++;
}
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().choose("Enter a # to remove, or modify, or enter 0 to Add:","0"+choices.toString(),"").trim().toUpperCase();
int factorNum=choices.toString().indexOf(which);
if((which.length()!=1)
||((!which.equalsIgnoreCase("0"))
&&((factorNum<0)||(factorNum>=numFactors))))
break;
Object[] factor=null;
if(!which.equalsIgnoreCase("0"))
{
factor=me.getFactor(factorNum);
if(factor!=null)
if(mob.session().choose("Would you like to M)odify or D)elete this range (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delFactor(factor);
mob.tell("Factor deleted.");
factor=null;
}
}
else
factor=me.addFactor(1.0,1.0,"");
if(factor!=null)
{
String mask=mob.session().prompt("Enter a new zapper mask ("+((String)factor[2])+")\n\r: "+((String)factor[2]));
double newHigh=((Double)factor[0]).doubleValue();
String newName=mob.session().prompt("Enter gain adjustment ("+CMath.toPct(newHigh)+"): ");
if((!CMath.isNumber(newName))&&(!CMath.isPct(newName)))
mob.tell("(no change)");
else
newHigh=CMath.s_pct(newName);
double newLow=((Double)factor[1]).doubleValue();
newName=mob.session().prompt("Enter loss adjustment ("+CMath.toPct(newLow)+"): ");
if((!CMath.isNumber(newName))&&(!CMath.isPct(newName)))
mob.tell("(no change)");
else
newLow=CMath.s_pct(newName);
me.delFactor(factor);
factor=me.addFactor(newHigh,newLow,mask);
}
}
// relations between factions
++showNumber;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
StringBuffer list=new StringBuffer(showNumber+". Cross-Faction Relations:\n\r");
list.append(" Faction"+CMStrings.padRight("",25)+"Percentage change\n\r");
for(Enumeration e=me.relationFactions();e.hasMoreElements();)
{
String key=(String)e.nextElement();
double value=me.getRelation(key);
Faction F=CMLib.factions().getFaction(key);
if(F!=null)
{
list.append(" "+CMStrings.padRight(F.name(),31)+" ");
list.append(CMath.toPct(value));
list.append("\n\r");
}
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().prompt("Enter a faction to add, remove, or modify relations:","");
if(which.length()==0)
break;
Faction theF=null;
for(Enumeration e=me.relationFactions();e.hasMoreElements();)
{
String key=(String)e.nextElement();
Faction F=CMLib.factions().getFaction(key);
if((F!=null)&&(F.name().equalsIgnoreCase(which)))
theF=F;
}
if(theF==null)
{
Faction possibleF=CMLib.factions().getFaction(which);
if(possibleF==null) possibleF=CMLib.factions().getFactionByName(which);
if(possibleF==null)
mob.tell("'"+which+"' is not a valid faction.");
else
if(mob.session().confirm("Create a new relation for faction '"+possibleF.name()+"' (y/N):","N"))
{
theF=possibleF;
me.addRelation(theF.factionID(),1.0);
}
}
else
if(mob.session().choose("Would you like to M)odify or D)elete this relation (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delRelation(theF.factionID());
mob.tell("Relation deleted.");
theF=null;
}
if(theF!=null)
{
String amount=CMath.toPct(me.getRelation(theF.factionID()));
String newName=mob.session().prompt("Enter a relation amount ("+amount+"): ",""+amount);
if((!CMath.isNumber(newName))&&(!CMath.isPct(newName)))
mob.tell("(no change)");
me.delRelation(theF.factionID());
me.addRelation(theF.factionID(),CMath.s_pct(newName));
}
}
// faction change triggers
++showNumber;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
StringBuffer list=new StringBuffer(showNumber+". Faction Change Triggers:\n\r");
list.append(" "+CMStrings.padRight("Type",15)
+" "+CMStrings.padRight("Direction",10)
+" "+CMStrings.padRight("Factor",10)
+" "+CMStrings.padRight("Flags",20)
+" Mask\n\r");
for(Enumeration e=me.changeEventKeys();e.hasMoreElements();)
{
Faction.FactionChangeEvent CE=(Faction.FactionChangeEvent)me.getChangeEvent((String)e.nextElement());
if(CE!=null)
{
list.append(" ");
list.append(CMStrings.padRight(CE.eventID(),15)+" ");
list.append(CMStrings.padRight(Faction.FactionChangeEvent.CHANGE_DIRECTION_DESCS[CE.direction()],10)+" ");
list.append(CMStrings.padRight(CMath.toPct(CE.factor()),10)+" ");
list.append(CMStrings.padRight(CE.flagCache(),20)+" ");
list.append(CE.zapper()+"\n\r");
}
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().prompt("Select a trigger ID to add, remove, or modify (?):","");
which=which.toUpperCase().trim();
if(which.length()==0) break;
if(which.equalsIgnoreCase("?"))
{
mob.tell("Valid triggers: \n\r"+me.ALL_CHANGE_EVENT_TYPES());
continue;
}
Faction.FactionChangeEvent CE=(Faction.FactionChangeEvent)me.getChangeEvent(which);
if(CE==null)
{
CE=me.addChangeEvent(which);
if(CE==null)
{
mob.tell("That ID is invalid. Try '?'.");
continue;
}
else
if(!mob.session().confirm("Create a new trigger using ID '"+which+"' (y/N): ","N"))
{
me.delChangeEvent(CE.eventID());
CE=null;
break;
}
}
else
if(mob.session().choose("Would you like to M)odify or D)elete this trigger (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delChangeEvent(CE.eventID());
mob.tell("Trigger deleted.");
CE=null;
}
if(CE!=null)
{
StringBuffer directions=new StringBuffer("Valid directions:\n\r");
StringBuffer cmds=new StringBuffer("");
for(int i=0;i<Faction.FactionChangeEvent.CHANGE_DIRECTION_DESCS.length;i++)
{
directions.append(((char)('A'+i))+") "+Faction.FactionChangeEvent.CHANGE_DIRECTION_DESCS[i]+"\n\r");
cmds.append((char)('A'+i));
}
String str=mob.session().choose(directions+"\n\rSelect a new direction ("+Faction.FactionChangeEvent.CHANGE_DIRECTION_DESCS[CE.direction()]+"): ",cmds.toString()+"\n\r","");
if((str.length()==0)||str.equals("\n")||str.equals("\r")||(cmds.toString().indexOf(str.charAt(0))<0))
mob.tell("(no change)");
else
CE.setDirection((cmds.toString().indexOf(str.charAt(0))));
}
if(CE!=null)
{
if(CE.factor()==0.0) CE.setFactor(1.0);
String amount=CMath.toPct(CE.factor());
String newName=mob.session().prompt("Enter the amount factor ("+amount+"): ",""+amount);
if((!CMath.isNumber(newName))&&(!CMath.isPct(newName)))
mob.tell("(no change)");
else
CE.setFactor(CMath.s_pct(newName));
}
if(CE!=null)
{
mob.tell("Valid flags include: "+CMParms.toStringList(Faction.FactionChangeEvent.FLAG_DESCS)+"\n\r");
String newFlags=mob.session().prompt("Enter new flag(s) ("+CE.flagCache()+"): "+CE.flagCache());
if((newFlags.length()==0)||(newFlags.equals(CE.flagCache())))
mob.tell("(no change)");
else
CE.setFlags(newFlags);
}
if(CE!=null)
{
String newFlags=mob.session().prompt("Zapper mask ("+CE.zapper()+"): "+CE.zapper());
if((newFlags.length()==0)||(newFlags.equals(CE.zapper())))
mob.tell("(no change)");
else
CE.setZapper(newFlags);
}
}
// Ability allowances
++showNumber;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
if((showFlag>0)&&(showFlag!=showNumber)) break;
StringBuffer list=new StringBuffer(showNumber+". Ability allowances:\n\r");
list.append(" #) "
+CMStrings.padRight("Ability masks",40)
+" "+CMStrings.padRight("Low value",10)
+" "+CMStrings.padRight("High value",10)
+"\n\r");
int numUsages=0;
StringBuffer choices=new StringBuffer("0\n\r");
for(Enumeration e=me.abilityUsages();e.hasMoreElements();)
{
Faction.FactionAbilityUsage CA=(Faction.FactionAbilityUsage)e.nextElement();
if(CA!=null)
{
list.append(" "+((char)('A'+numUsages)+") "));
list.append(CMStrings.padRight(CA.abilityFlags(),40)+" ");
list.append(CMStrings.padRight(CA.low()+"",10)+" ");
list.append(CMStrings.padRight(CA.high()+"",10)+" ");
list.append("\n\r");
choices.append((char)('A'+numUsages));
numUsages++;
}
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().choose("Select an allowance to remove or modify, or enter 0 to Add:",choices.toString(),"");
if(which.length()!=1)
break;
which=which.toUpperCase().trim();
Faction.FactionAbilityUsage CA=null;
if(!which.equalsIgnoreCase("0"))
{
int num=(which.charAt(0)-'A');
if((num<0)||(num>=numUsages))
break;
CA=(Faction.FactionAbilityUsage)me.getAbilityUsage(num);
if(CA==null)
{
mob.tell("That allowance is invalid..");
continue;
}
if(mob.session().choose("Would you like to M)odify or D)elete this allowance (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delAbilityUsage(CA);
mob.tell("Allowance deleted.");
CA=null;
}
}
else
if(!mob.session().confirm("Create a new allowance (y/N): ","N"))
{
continue;
}
else
CA=me.addAbilityUsage(null);
if(CA!=null)
{
boolean cont=false;
while((!cont)&&(!mob.session().killFlag()))
{
String newFlags=mob.session().prompt("Ability determinate masks or ? ("+CA.abilityFlags()+"): "+CA.abilityFlags());
if(newFlags.equalsIgnoreCase("?"))
{
StringBuffer vals=new StringBuffer("Valid masks: \n\r");
for(int i=0;i<Ability.ACODE_DESCS.length;i++)
vals.append(Ability.ACODE_DESCS[i]+", ");
for(int i=0;i<Ability.DOMAIN_DESCS.length;i++)
vals.append(Ability.DOMAIN_DESCS[i]+", ");
for(int i=0;i< Ability.FLAG_DESCS.length;i++)
vals.append(Ability.FLAG_DESCS[i]+", ");
vals.append(" * Any ABILITY ID (skill/prayer/spell/etc)");
mob.tell(vals.toString());
cont=false;
}
else
{
cont=true;
if((newFlags.length()==0)||(newFlags.equals(CA.abilityFlags())))
mob.tell("(no change)");
else
{
Vector unknowns=CA.setAbilityFlag(newFlags);
if(unknowns.size()>0)
for(int i=unknowns.size()-1;i>=0;i--)
if(CMClass.getAbility((String)unknowns.elementAt(i))!=null)
unknowns.removeElementAt(i);
if(unknowns.size()>0)
{
mob.tell("The following are unknown masks: '"+CMParms.toStringList(unknowns)+"'. Please correct them.");
cont=false;
}
}
}
}
String newName=mob.session().prompt("Enter the minimum value to use the ability ("+CA.low()+"): ",""+CA.low());
if((!CMath.isInteger(newName))||(CA.low()==CMath.s_int(newName)))
mob.tell("(no change)");
else
CA.setLow(CMath.s_int(newName));
newName=mob.session().prompt("Enter the maximum value to use the ability ("+CA.high()+"): ",""+CA.high());
if((!CMath.isInteger(newName))||(CA.high()==CMath.s_int(newName)))
mob.tell("(no change)");
else
CA.setHigh(CMath.s_int(newName));
if(CA.high()<CA.low()) CA.setHigh(CA.low());
}
}
// Affects/Behaviors
++showNumber;
while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
{
if((showFlag>0)&&(showFlag!=showNumber)) break;
StringBuffer list=new StringBuffer(showNumber+". Effects/Behaviors:\n\r");
list.append(" #) "
+CMStrings.padRight("Ability/Behavior ID",25)
+" "+CMStrings.padRight("MOB Mask",20)
+" "+CMStrings.padRight("Parameters",20)
+"\n\r");
int numAffBehavs=0;
StringBuffer choices=new StringBuffer("0\n\r");
Vector IDs=new Vector();
String ID=null;
for(Enumeration e=me.affectsBehavs();e.hasMoreElements();)
{
ID=(String)e.nextElement();
String[] parms=me.getAffectBehav(ID);
list.append(" "+((char)('A'+numAffBehavs)+") "));
list.append(CMStrings.padRight(ID,25)+" ");
list.append(CMStrings.padRight(parms[1]+"",20)+" ");
list.append(CMStrings.padRight(parms[0]+"",20)+" ");
list.append("\n\r");
choices.append((char)('A'+numAffBehavs));
IDs.addElement(ID);
numAffBehavs++;
}
mob.tell(list.toString());
if((showFlag!=showNumber)&&(showFlag>-999)) break;
String which=mob.session().choose("Select an ability/behavior ID to remove or modify, or enter 0 to Add:",choices.toString(),"");
if(which.length()!=1)
break;
which=which.toUpperCase().trim();
if(!which.equalsIgnoreCase("0"))
{
int num=(which.charAt(0)-'A');
if((num<0)||(num>=IDs.size()))
break;
ID=(String)IDs.elementAt(num);
String type=getWordAffOrBehav(ID);
if(mob.session().choose("Would you like to M)odify or D)elete this "+type+" (M/d): ","MD","M").toUpperCase().startsWith("D"))
{
me.delAffectBehav(ID);
mob.tell(CMStrings.capitalizeAndLower(type)+" deleted.");
ID=null;
}
}
else
{
boolean cont=true;
while((cont)&&(!mob.session().killFlag()))
{
cont=false;
ID=mob.session().prompt("Enter a new Ability or Behavior ID or ?: ");
if(ID.equalsIgnoreCase("?"))
{
StringBuffer vals=new StringBuffer("Valid IDs: \n\r");
vals.append(CMParms.toStringList(CMClass.abilities()));
mob.tell(vals.toString());
cont=true;
}
else
{
if((ID.length()==0)||(me.getAffectBehav(ID)!=null))
{
mob.tell("(nothing done)");
ID=null;
break;
}
String type=getWordAffOrBehav(ID);
if(type==null)
{
mob.tell("'"+ID+" is neither a valid behavior ID or ability ID. Use ? for a list.");
cont=true;
}
else
if(!mob.session().confirm("Create a new "+type+" (y/N): ","N"))
{
ID=null;
break;
}
else
me.addAffectBehav(ID,"","");
}
}
}
if(ID!=null)
{
String type=getWordAffOrBehav(ID);
String[] oldData=me.getAffectBehav(ID);
String[] newData=new String[2];
boolean cont=true;
while((cont)&&(!mob.session().killFlag()))
{
cont=false;
String mask=mob.session().prompt("Enter a new Zapper Mask or ? ("+oldData[1]+")\n\r: ");
if(mask.equalsIgnoreCase("?"))
{
mob.tell(CMLib.masking().maskHelp("\n\r","disallow"));
cont=true;
}
else
if(!mask.equals(oldData[1]))
newData[1]=mask;
}
cont=true;
while((cont)&&(!mob.session().killFlag()))
{
cont=false;
String parms=mob.session().prompt("Enter new "+type+" parameters for "+ID+" or ? ("+oldData[0]+")\n\r: ");
if(parms.equalsIgnoreCase("?"))
{
mob.tell(CMLib.help().getHelpText(ID,mob,true).toString());
cont=true;
}
else
if(!parms.equals(oldData[0]))
newData[0]=parms;
}
if((newData[0]==null)&&(newData[1]!=null))
newData[0]=oldData[0];
else
if((newData[0]!=null)&&(newData[1]==null))
newData[1]=oldData[1];
if((newData[0]!=null)&&(newData[1]!=null))
{
me.delAffectBehav(ID);
me.addAffectBehav(ID,newData[0],newData[1]);
}
}
}
if(showFlag<-900){ ok=true; break;}
if(showFlag>0){ showFlag=-1; continue;}
showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
if(showFlag<=0)
{
showFlag=-1;
ok=true;
}
}
String errMsg=resaveFaction(me);
if(errMsg.length()>0)
mob.tell(errMsg);
}
public String resaveFaction(Faction F)
{
if((F.factionID().length()>0)&&(CMLib.factions().getFaction(F.factionID())!=null))
{
Vector oldV=Resources.getFileLineVector(Resources.getFileResource(F.factionID(),true));
if(oldV.size()<10)
{
}
boolean[] defined=new boolean[Faction.TAG_NAMES.length];
for(int i=0;i<defined.length;i++) defined[i]=false;
for(int v=0;v<oldV.size();v++)
{
String s=(String)oldV.elementAt(v);
if(!(s.trim().startsWith("#")||s.trim().length()==0||(s.indexOf("=")<0)))
{
String tag=s.substring(0,s.indexOf("=")).trim().toUpperCase();
int tagRef=CMLib.factions().isFactionTag(tag);
if(tagRef>=0) defined[tagRef]=true;
}
}
boolean[] done=new boolean[Faction.TAG_NAMES.length];
for(int i=0;i<done.length;i++) done[i]=false;
int lastCommented=-1;
String CR="\n\r";
StringBuffer buf=new StringBuffer("");
for(int v=0;v<oldV.size();v++)
{
String s=(String)oldV.elementAt(v);
if(s.trim().length()==0)
{
if((lastCommented>=0)&&(!done[lastCommented]))
{
done[lastCommented]=true;
buf.append(F.getINIDef(Faction.TAG_NAMES[lastCommented],CR)+CR);
lastCommented=-1;
}
}
else
if(s.trim().startsWith("#")||(s.indexOf("=")<0))
{
buf.append(s+CR);
int x=s.indexOf("=");
if(x>=0)
{
s=s.substring(0,x).trim();
int first=s.length()-1;
for(;first>=0;first--)
if(!Character.isLetterOrDigit(s.charAt(first)))
break;
first=CMLib.factions().isFactionTag(s.substring(first).trim().toUpperCase());
if(first>=0) lastCommented=first;
}
}
else
{
String tag=s.substring(0,s.indexOf("=")).trim().toUpperCase();
int tagRef=CMLib.factions().isFactionTag(tag);
if(tagRef<0)
buf.append(s+CR);
else
if(!done[tagRef])
{
done[tagRef]=true;
buf.append(F.getINIDef(tag,CR)+CR);
}
}
}
if((lastCommented>=0)&&(!done[lastCommented]))
buf.append(F.getINIDef(Faction.TAG_NAMES[lastCommented],CR)+CR);
Resources.removeResource(F.factionID());
Resources.submitResource(F.factionID(),buf);
if(!Resources.saveFileResource(F.factionID()))
return "Faction File '"+F.factionID()+"' could not be modified. Make sure it is not READ-ONLY.";
}
else
return "Can not save a blank faction";
return "";
}
public int getAbilityFlagType(String strflag)
{
for(int i=0;i<Ability.ACODE_DESCS.length;i++)
if(Ability.ACODE_DESCS[i].equalsIgnoreCase(strflag))
return 1;
for(int i=0;i<Ability.DOMAIN_DESCS.length;i++)
if(Ability.DOMAIN_DESCS[i].equalsIgnoreCase(strflag))
return 2;
if(strflag.startsWith("!")) strflag=strflag.substring(1);
for(int i=0;i< Ability.FLAG_DESCS.length;i++)
if(Ability.FLAG_DESCS[i].equalsIgnoreCase(strflag))
return 3;
if(CMClass.getAbility(strflag)!=null)
return 0;
return -1;
}
}