public void listAbilities(MOB mob, Session s, List<String> commands, String title, int ofType)
	{
		int domain=0;
		final WikiFlag wiki = this.getWikiFlagRemoved(commands);
		for(int i=1;i<commands.size();i++)
		{
			final String str=commands.get(i);
			if(domain<=0)
			{
				int x=CMParms.indexOf(Ability.DOMAIN_DESCS,str.toUpperCase().trim());
				if(x>=0)
				{
					domain = x << 5;
					String domainName=CMStrings.capitalizeAllFirstLettersAndLower(Ability.DOMAIN_DESCS[x].toLowerCase().replaceAll("_"," "));
					title=(domainName+" "+title).trim();
				}
				else
				{
					s.println("Unknown '"+str+"'");
					return;
				}
			}
		}
		if(wiki == WikiFlag.WIKILIST)
		{
			if(title.length()==0)
				title="Abilities";
			if(domain == 0)
				s.println("==="+title+"s===");
			else
				s.println("==="+title+"===");
			s.wraplessPrintln(CMLib.lister().reallyWikiList(mob, CMClass.abilities(), ofType|domain).toString());
		}
		else
		if(wiki == WikiFlag.WIKIHELP)
		{
			StringBuilder str=new StringBuilder("");
			for(final Enumeration<Ability> e=CMClass.abilities();e.hasMoreElements();)
			{
				final Ability A=e.nextElement();
				if((ofType>=0)&&(ofType!=Ability.ALL_ACODES))
				{
					if((A.classificationCode()&Ability.ALL_ACODES)!=ofType)
						continue;
				}
				if(domain>0)
				{
					if((A.classificationCode()&Ability.ALL_DOMAINS)!=domain)
						continue;
				}
				String domainID = Ability.DOMAIN_DESCS[(A.classificationCode()&Ability.ALL_DOMAINS)>>5].toLowerCase();
				String domainName = CMStrings.capitalizeAllFirstLettersAndLower(domainID.replaceAll("_"," "));
				StringBuilder availStr=new StringBuilder("");
				final PairList<String,Integer> avail=CMLib.ableMapper().getAvailabilityList(A, Integer.MAX_VALUE);
				for(int c=0;c<avail.size();c++)
				{
					CharClass C=CMClass.getCharClass(avail.getFirst(c));
					Integer I=avail.getSecond(c);
					availStr.append("[["+C.name()+"("+C.baseClass()+")|"+C.name(I.intValue())+"("+I.intValue()+")]] ");
				}
				StringBuilder allowsStr=new StringBuilder("");
				for(Iterator<String> i=CMLib.expertises().filterUniqueExpertiseIDList(CMLib.ableMapper().getAbilityAllowsList(A.ID()));i.hasNext();)
				{
					final String ID=i.next();
					ExpertiseDefinition def=CMLib.expertises().getDefinition(ID);
					if(def != null)
					{
						String name=def.name();
						int x=name.lastIndexOf(' ');
						if(CMath.isRomanNumeral(name.substring(x+1).trim()))
							name=name.substring(0, x).trim();
						allowsStr.append("[["+name+"(Expertise)|"+name+"]]").append(" ");
					}
					else
					{
						final Ability A2=CMClass.getAbilityPrototype(ID);
						if(A2!=null)
							allowsStr.append("[["+A2.ID()+"|"+A2.name()+"]]").append(" ");
						else
							allowsStr.append(ID).append(" ");
					}
				}
				final String cost=CMLib.help().getAbilityCostDesc(A, null);
				final String quality=CMLib.help().getAbilityQualityDesc(A);
				final String targets=CMLib.help().getAbilityTargetDesc(A);
				final String range=CMLib.help().getAbilityRangeDesc(A);
				StringBuilder help=CMLib.help().getHelpText(A.ID(),null,false,true);
				String usage="";
				String example="";
				String helpStr="";
				if(help==null)
					help=CMLib.help().getHelpText(A.name(),null,false,true);
				if((help!=null)&&(help.toString().startsWith("<ABILITY>")))
				{
					helpStr=help.toString().substring(9);
					while(helpStr.startsWith("Usage")||helpStr.startsWith("  "))
					{
						int end=helpStr.indexOf("\n");
						int start=helpStr.indexOf(":");
						if((end<0)||(start<0)||(start>end))
							break;
						usage += ((usage.length()>0) ? "\n\r" : "" ) + helpStr.substring(start+1,end).trim();
						helpStr=helpStr.substring(end+1).trim();
					}
					while(helpStr.startsWith("Example")||helpStr.startsWith("  "))
					{
						int end=helpStr.indexOf("\n");
						int start=helpStr.indexOf(":");
						if((end<0)||(start<0)||(start>end))
							break;
						example += ((example.length()>0) ? "\n\r" : "" ) + helpStr.substring(start+1,end).trim();
						helpStr=helpStr.substring(end+1).trim();
					}
				}
				str.append("{{SkillTemplate"
						+ "|Name="+A.name()
						+ "|Domain=[["+domainID+"(Domain)|"+domainName+"]]"
						+ "|Available="+availStr.toString()
						+ "|Allows="+allowsStr.toString()
						+ "|UseCost="+cost
						+ "|Quality="+quality
						+ "|Targets="+targets
						+ "|Range="+range
						+ "|Commands="+CMParms.toListString(A.triggerStrings())
						+ "|Usage="+CMStrings.replaceAllofAny(usage,"[]{}<>|".toCharArray(),"\"\"()()!".toCharArray())
						+ "|Examples="+example
						+ "|Description="+CMStrings.replaceAllofAny(helpStr,"[]{}<>|".toCharArray(),"()()()!".toCharArray())
						+ "}}\n\r");
			}
			s.wraplessPrintln(str.toString());
		}
		else
		{
			s.println("^H"+title+" Ability IDs:^N");
			s.wraplessPrintln(CMLib.lister().reallyList(mob, CMClass.abilities(), ofType|domain).toString());
		}
	}