Updated Release Archive
Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
This commit is contained in:
BIN
nwn/nwnprc/DocGen/trunk/prc/Main.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/Main.class
Normal file
Binary file not shown.
169
nwn/nwnprc/DocGen/trunk/prc/Main.java
Normal file
169
nwn/nwnprc/DocGen/trunk/prc/Main.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package prc;
|
||||
|
||||
import prc.autodoc.ErrorPrinter;
|
||||
import prc.autodoc.Spinner;
|
||||
|
||||
/**
|
||||
* A menu class. Calls operations from classes in subpackages based on parameters
|
||||
*
|
||||
* @author heikki
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
/** Version number for public releases. Raise by one whenever doing a release. */
|
||||
private static final int releaseNum = 1;
|
||||
|
||||
/** A convenience object for printing both to log and System.err */
|
||||
public static ErrorPrinter err_pr = new ErrorPrinter();
|
||||
|
||||
/** A boolean determining whether to spam the user with progress information */
|
||||
public static boolean verbose = true;
|
||||
|
||||
/** A decorative spinner to look at while the program is loading big files */
|
||||
public static Spinner spinner = new Spinner();
|
||||
|
||||
/**
|
||||
* Ooh, a main method!
|
||||
*
|
||||
* @param args arguments, surprisingly enough
|
||||
*
|
||||
* @throws Throwable everything received from the classes called is passed on
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable{
|
||||
if(args.length == 0 || args[0].equals("--help"))
|
||||
readMe();
|
||||
|
||||
String toCall = args[0];
|
||||
String[] paramsToPass = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, paramsToPass, 0, paramsToPass.length);
|
||||
|
||||
if(toCall.equals("manual")){
|
||||
prc.autodoc.Main.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("2da")){
|
||||
prc.autodoc.Data_2da.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("codegen")){
|
||||
prc.utils.CodeGen.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("radials")){
|
||||
prc.utils.Radials.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("lssubrad")){
|
||||
prc.utils.ListSubradials.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("dupsubrad")){
|
||||
prc.utils.DuplicateSubradials.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("makedep")){
|
||||
prc.makedep.Main.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("upclsfeat")){
|
||||
prc.utils.AllClassFeatUpdater.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("lsentries")){
|
||||
prc.utils.List2daEntries.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("dupentries")){
|
||||
prc.utils.Duplicate2daEntryDetector.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("2datosql")){
|
||||
prc.utils.SQLMaker.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("spellbookmaker")){
|
||||
prc.utils.SpellbookMaker.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("amsspellbookmaker")){
|
||||
prc.utils.AMSSpellbookMaker.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("itempropmaker")){
|
||||
prc.utils.ItempropMaker.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("letoxml")){
|
||||
prc.utils.LetoListsGenerator.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("prec2dagen")){
|
||||
prc.utils.Precache2daGen.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("scrmrchgen")){
|
||||
prc.utils.ScrollMerchantGen.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("npcevol")){
|
||||
prc.utils.NPCEvolve.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("2damerge")){
|
||||
prc.utils.Data2daMerge.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("blank2da")){
|
||||
prc.utils.Blank2daRows.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("validator")){
|
||||
prc.utils.Validator.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("updatedescrft")){
|
||||
prc.utils.UpdateDes.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("scrollgen")){
|
||||
prc.utils.ScrollGen.main(paramsToPass);
|
||||
}
|
||||
else if(toCall.equals("buildscrhack")){
|
||||
prc.utils.BuildScrollHack.main(paramsToPass);
|
||||
}
|
||||
else{
|
||||
System.out.println("Unknown class: " + toCall);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the use instructions for this program and kills execution.
|
||||
*/
|
||||
private static void readMe(){
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n"+
|
||||
" java -jar prc.jar [--help] | tool [parameters]\n"+
|
||||
"\n"+
|
||||
"tool name of the tool to call. possible values:\n"+
|
||||
" 2da - Either verifies a single 2da file or compares two\n"+
|
||||
" 2damerge - Merges 2 directories of 2da files, and outputs to a third\n" +
|
||||
" blank2da - Blanks rows in a 2da\n" +
|
||||
" codegen - Autogenerates scripts (or other files)\n"+
|
||||
" dupentries - Seeks for duplicate entries in the given columns\n" +
|
||||
" of a given 2da\n"+
|
||||
" dupsubrad - Seeks through spells.2da and prints lines\n"+
|
||||
" containing duplicate subradial values\n"+
|
||||
" letoxml - Creates Leto XML lists from 2da and TLK\n" +
|
||||
" lsentries - Lists the unique entries in given columns of a\n" +
|
||||
" given 2da\n" +
|
||||
" lssubrad - Lists subradial IDs used in spells.2da\n" +
|
||||
" makedep - Builds include dependency lists\n" +
|
||||
" radials - Generates subradial FeatID values\n"+
|
||||
"\n" +
|
||||
" The following tools are also available, but almost certainly too\n" +
|
||||
" specialized for general use:\n" +
|
||||
" 2datosql - Creates a SQL file from 2das\n" +
|
||||
" itempropmaker - Creates the itemproperty cache item templates\n" +
|
||||
" manual - Generates the manual\n"+
|
||||
" npcevol - Alters packages based on logfile scores\n" +
|
||||
" upclsfeat - Updates base cls_feat_*.2da based on given templates\n" +
|
||||
" prec2dagen - Creates a 2da file that lists spells/feat.2da rows\n" +
|
||||
" that should be precached\n" +
|
||||
" scrmrchgen - Creates scroll merchant based on des_crft_scroll.2da\n" +
|
||||
" spellbookmaker - Creates and/or updates the new spellbooks data\n" +
|
||||
" amsspellbookmaker - Creates and/or updates the new AMS spellbooks data\n" +
|
||||
" validator - Performs a bunch of 2da integrity tests\n" +
|
||||
" updatedescrft - Updates des_crft_*.2da based on spells.2da\n" +
|
||||
" scrollgen - Create spell scrolls based on (iprp_)spells.2da\n" +
|
||||
"\n"+
|
||||
"parameters a list of parameters passed to the tool called\n"+
|
||||
"\n"+
|
||||
"--help prints this info you are reading\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Release number: " + releaseNum + "\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.class
Normal file
Binary file not shown.
71
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.java
Normal file
71
nwn/nwnprc/DocGen/trunk/prc/autodoc/ClassEntry.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a class entry.
|
||||
*/
|
||||
public class ClassEntry extends GenericEntry {
|
||||
/**
|
||||
* If <code>true</code>, this class is a base class.
|
||||
*/
|
||||
public final boolean isBase;
|
||||
|
||||
/**
|
||||
* List of BAB and saving throw values. Each list entry consists of the values
|
||||
* for the list indexth level. Order: BAB, Fort, Ref, Will.
|
||||
*/
|
||||
public final List<String[]> babSav;
|
||||
|
||||
/**
|
||||
* The list of this class's class and cross-class skills. First tuple member
|
||||
* cotnaints the class skills, the second cross-class skills.
|
||||
* Map keys are skill names.
|
||||
*/
|
||||
public final Tuple<TreeMap<String, GenericEntry>, TreeMap<String, GenericEntry>> skillList;
|
||||
|
||||
/**
|
||||
* Lists of this class's granted and selectable feats. First tuple member lists bonus feat
|
||||
* # at each level. First inner tuple member is the granted feats, second member is selectable feats.
|
||||
* Each list consists of the feats that are related to the list indexth level.
|
||||
* The map keys are feat names.
|
||||
*/
|
||||
public final Tuple<List<Integer>, Tuple<List<TreeMap<String, FeatEntry>>, List<TreeMap<String, FeatEntry>>>> featList;
|
||||
|
||||
/**
|
||||
* The alternate magic systems available to this class. Each list entry describes one
|
||||
* magic system (though there will probably never be more than one per class).
|
||||
* First member of the outer tuple is the (magic system name, magic system spell-equivalent name)
|
||||
* pair. Second member is a map keyed to spell-equivalent level, with values being maps of
|
||||
* spell-equivalent name to the spell entry.
|
||||
*/
|
||||
public final List<Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>>> magics;
|
||||
|
||||
/**
|
||||
* Create a new class entry.
|
||||
*
|
||||
* @param name The name of this class.
|
||||
* @param text The description of this class.
|
||||
* @param iconPath The path of this class's icon.
|
||||
* @param filePath The path of the html file that has been written for this class.
|
||||
* @param isBase If <code>true</code>, this class is a base class.
|
||||
* @param entryNum Index of the class in classes.2da.
|
||||
* @param babSav The BAB and saves of this class.
|
||||
* @param skillList The skills of this class.
|
||||
* @param featList The feats of this class.
|
||||
* @param magics The alternate magics of this class.
|
||||
*/
|
||||
public ClassEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, boolean isBase, List<String[]> babSav,
|
||||
Tuple<TreeMap<String, GenericEntry>, TreeMap<String, GenericEntry>> skillList,
|
||||
Tuple<List<Integer>, Tuple<List<TreeMap<String, FeatEntry>>, List<TreeMap<String, FeatEntry>>>> featList,
|
||||
List<Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>>> magics) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.isBase = isBase;
|
||||
this.babSav = babSav;
|
||||
this.skillList = skillList;
|
||||
this.featList = featList;
|
||||
this.magics = magics;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.class
Normal file
Binary file not shown.
1073
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.java
Normal file
1073
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_2da.java
Normal file
File diff suppressed because it is too large
Load Diff
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.class
Normal file
Binary file not shown.
278
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.java
Normal file
278
nwn/nwnprc/DocGen/trunk/prc/autodoc/Data_TLK.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static prc.Main.spinner;
|
||||
import static prc.Main.verbose;
|
||||
|
||||
/**
|
||||
* This class forms an interface for accessing TLK files in the
|
||||
* PRC automated manual generator.
|
||||
*/
|
||||
public class Data_TLK {
|
||||
private final HashMap<Integer, String> mainData = new HashMap<Integer, String>();
|
||||
private int highestEntry = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Data_TLK on the TLK file specified.
|
||||
*
|
||||
* @param filePath The path of the TLK file to be loaded
|
||||
* @throws IllegalArgumentException <code>filePath</code> does not filePath a TLK file
|
||||
* @throws TLKReadException reading the TLK file specified does not succeed
|
||||
*/
|
||||
public Data_TLK(String filePath) {
|
||||
// Some paranoia checking for bad parameters
|
||||
if (!filePath.toLowerCase().endsWith("tlk"))
|
||||
throw new IllegalArgumentException("Non-tlk filename passed to Data_TLK: " + filePath);
|
||||
|
||||
File baseFile = new File(filePath);
|
||||
if (!baseFile.exists())
|
||||
throw new IllegalArgumentException("Nonexistent file passed to Data_TLK: " + filePath);
|
||||
if (!baseFile.isFile())
|
||||
throw new IllegalArgumentException("Nonfile passed to Data_TLK: " + filePath);
|
||||
|
||||
|
||||
// Create a RandomAccessFile for reading the TLK. Read-only
|
||||
MappedByteBuffer reader = null;
|
||||
RandomAccessFile fileReader;
|
||||
try {
|
||||
fileReader = new RandomAccessFile(baseFile, "r");
|
||||
reader = fileReader.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileReader.length());
|
||||
} catch (IOException e) {
|
||||
throw new TLKReadException("Cannot access TLK file: " + filePath, e);
|
||||
}
|
||||
byte[] bytes4 = new byte[4],
|
||||
bytes8 = new byte[8];
|
||||
|
||||
// Drop the path from the filename
|
||||
String fileName = baseFile.getName();
|
||||
|
||||
// Tell the user what we are doing
|
||||
if (verbose) System.out.print("Reading TLK file: " + fileName + " ");
|
||||
|
||||
try {
|
||||
// Check the header
|
||||
reader.get(bytes4);
|
||||
if (!new String(bytes4).equals("TLK "))
|
||||
throw new TLKReadException("Wrong file type field in: " + fileName);
|
||||
|
||||
// Check the version
|
||||
reader.get(bytes4);
|
||||
if (!new String(bytes4).equals("V3.0"))
|
||||
throw new TLKReadException("Wrong TLK version number in: " + fileName);
|
||||
|
||||
// Skip the language ID
|
||||
reader.position(reader.position() + 4);
|
||||
|
||||
// Read the entrycount
|
||||
int stringCount = readLittleEndianInt(reader, bytes4);
|
||||
int stringOffset = readLittleEndianInt(reader, bytes4);
|
||||
|
||||
// Read the entry lengths
|
||||
int[] stringLengths = readStringLengths(reader, stringCount);
|
||||
|
||||
// Read the strings themselves
|
||||
readStrings(reader, stringLengths, stringOffset);
|
||||
|
||||
// Store the highest string for writing back later
|
||||
highestEntry = stringLengths.length;
|
||||
} catch (IOException e) {
|
||||
throw new TLKReadException("IOException while reading TLK file: " + fileName, e);
|
||||
} finally {
|
||||
try {
|
||||
fileReader.close();
|
||||
} catch (IOException e) {
|
||||
// No idea under what conditions closing a file could fail and not cause an Error to be thrown...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) System.out.println("- Done");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to get
|
||||
* @return the entry string or "Bad StrRef" if the entry wasn't in the TLK
|
||||
*/
|
||||
public String getEntry(int strRef) {
|
||||
if (strRef > 0x01000000) strRef -= 0x01000000;
|
||||
String toReturn = mainData.get(strRef);
|
||||
if (toReturn == null) toReturn = Main.badStrRef;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to get as a string
|
||||
* @return the entry string or "Bad StrRef" if the entry wasn't in the TLK
|
||||
* @throws NumberFormatException if <code>strRef</code> cannot be converted to an integer
|
||||
*/
|
||||
public String getEntry(String strRef) {
|
||||
try {
|
||||
return getEntry(Integer.parseInt(strRef));
|
||||
} catch (NumberFormatException e) {
|
||||
return Main.badStrRef;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given TLK entry.
|
||||
*
|
||||
* @param strRef the number of the entry to set
|
||||
* @param value the value of the entry to set
|
||||
*/
|
||||
public void setEntry(int strRef, String value) {
|
||||
if (strRef > 0x01000000) strRef -= 0x01000000;
|
||||
mainData.put(strRef, value);
|
||||
if (strRef > highestEntry)
|
||||
highestEntry = strRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the tlk file to the given XML.
|
||||
*
|
||||
* @param name the name of the resulting file, without extensions
|
||||
* @param path the path to the directory to save the file to
|
||||
* @param allowOverWrite Whether to allow overwriting existing files
|
||||
* @throws IOException if cannot overwrite, or the underlying IO throws one
|
||||
*/
|
||||
public void saveAsXML(String name, String path, boolean allowOverWrite) throws IOException {
|
||||
if (path == null || path.equals(""))
|
||||
path = "." + File.separator;
|
||||
if (!path.endsWith(File.separator))
|
||||
path += File.separator;
|
||||
|
||||
File file = new File(path + name + ".tlk.xml");
|
||||
if (file.exists() && !allowOverWrite)
|
||||
throw new IOException("File exists already: " + file.getAbsolutePath());
|
||||
|
||||
// Inform user
|
||||
if (verbose) System.out.print("Saving tlk file: " + name + " ");
|
||||
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
|
||||
//write the header
|
||||
writer.println("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
|
||||
writer.println("<!DOCTYPE tlk SYSTEM \"tlk2xml.dtd\">");
|
||||
writer.println("<tlk>");
|
||||
|
||||
//loop over each row and write it
|
||||
for (int row = 0; row < highestEntry; row++) {
|
||||
String data = mainData.get(row);
|
||||
if (data != null) {
|
||||
//replace with paired characters
|
||||
data = data.replace("&", "&"); //this must be before the others
|
||||
data = data.replace("<", "<");
|
||||
data = data.replace(">", ">");
|
||||
writer.println(" <entry id=\"" + row + "\" lang=\"en\" sex=\"m\">" + data + "</entry>");
|
||||
}
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
|
||||
//write the footer
|
||||
writer.println("</tlk>");
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
if (verbose) System.out.println("- Done");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the string lengths from this TLK's string data elements.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param stringCount number of strings in the TLK
|
||||
* @return an array of integers containing the lengths of the strings in this TLK
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private int[] readStringLengths(MappedByteBuffer reader, int stringCount) throws IOException {
|
||||
int[] toReturn = new int[stringCount];
|
||||
byte[] bytes4 = new byte[4];
|
||||
int curOffset = 20; // The number of bytes in the TLK header section
|
||||
|
||||
for (int i = 0; i < stringCount; i++) {
|
||||
// Skip everything up to the length
|
||||
curOffset += 32;
|
||||
reader.position(curOffset);
|
||||
// Read the value
|
||||
toReturn[i] = readLittleEndianInt(reader, bytes4);
|
||||
// Skip to the end of the record
|
||||
curOffset += 8;
|
||||
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the strings from the TLK into the hashmap.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param stringLengths an array of integers containing the lengths of the strings in this TLK
|
||||
* @param curOffset the offset to start reading from in the file
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private void readStrings(MappedByteBuffer reader, int[] stringLengths, int curOffset) throws IOException {
|
||||
StringBuffer buffer = new StringBuffer(200);
|
||||
reader.position(curOffset);
|
||||
|
||||
for (int i = 0; i < stringLengths.length; i++) {
|
||||
if (stringLengths[i] > 0) {
|
||||
// Read the specified number of bytes, convert them into chars
|
||||
// and put them in the buffer
|
||||
for (int j = 0; j < stringLengths[i]; j++)
|
||||
buffer.append((char) (reader.get() & 0xff));
|
||||
// Store the buffer contents
|
||||
mainData.put(i, buffer.toString());
|
||||
// Wipe the buffer for next round
|
||||
buffer.delete(0, buffer.length());
|
||||
}
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next 4 bytes into the given array from the TLK and then
|
||||
* writes them into an integer in inverse order.
|
||||
*
|
||||
* @param reader RandomAccessFile read from
|
||||
* @param readArray array of bytes read to. For efficiency of not having to create a new array every time
|
||||
* @return integer read
|
||||
* @throws IOException if there is an error while reading from <code>reader</code>
|
||||
*/
|
||||
private int readLittleEndianInt(MappedByteBuffer reader, byte[] readArray) throws IOException {
|
||||
int toReturn = 0;
|
||||
reader.get(readArray);
|
||||
for (int i = readArray.length - 1; i >= 0; i--) {
|
||||
// What's missing here is the implicit promotion of readArray[i] to
|
||||
// int. A byte is a signed element, and as such, has max value of 0x7f.
|
||||
toReturn = (toReturn << 8) | readArray[i] & 0xff;
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method, as usual
|
||||
*
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
Data_TLK test = new Data_TLK(args[0]);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.class
Normal file
Binary file not shown.
37
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.java
Normal file
37
nwn/nwnprc/DocGen/trunk/prc/autodoc/DomainEntry.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data structure for a domain entry.
|
||||
*/
|
||||
public class DomainEntry extends GenericEntry {
|
||||
|
||||
/**
|
||||
* This domain's domain power, if any
|
||||
*/
|
||||
public final FeatEntry grantedFeat;
|
||||
/**
|
||||
* The domain's spells. List of spell entry.
|
||||
*/
|
||||
public final List<SpellEntry> spells;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the domain
|
||||
* @param text Description of the domain
|
||||
* @param iconPath Path of the domain's icon
|
||||
* @param filePath Path where the html page for this domain will be written to
|
||||
* @param entryNum domains.2da index
|
||||
* @param grantedFeat Domain power feat
|
||||
* @param spells The domain spells
|
||||
*/
|
||||
public DomainEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, FeatEntry grantedFeat,
|
||||
List<SpellEntry> spells) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.grantedFeat = grantedFeat;
|
||||
this.spells = spells;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$2.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$2.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$3.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$3.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$4.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$4.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$5.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$5.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$6.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration$6.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.class
Normal file
Binary file not shown.
1844
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.java
Normal file
1844
nwn/nwnprc/DocGen/trunk/prc/autodoc/EntryGeneration.java
Normal file
File diff suppressed because it is too large
Load Diff
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.class
Normal file
Binary file not shown.
66
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.java
Normal file
66
nwn/nwnprc/DocGen/trunk/prc/autodoc/ErrorPrinter.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* A convenience class for printing errors to both log and System.err
|
||||
*/
|
||||
public class ErrorPrinter {
|
||||
private PrintWriter writer;
|
||||
private boolean isInit = false;
|
||||
|
||||
/**
|
||||
* Initializes the ErrorPrinter.
|
||||
* Attempts to open a log file by name of "errorlog" for writing. If this
|
||||
* fails, aborts the program.
|
||||
*/
|
||||
private void init() {
|
||||
try {
|
||||
writer = new PrintWriter(new FileOutputStream("errorlog", false), true);
|
||||
isInit = true;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error while creating error logger. Yes, it's ironic. Now debug");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the given string to both stderr and errorlog.
|
||||
*
|
||||
* @param toPrint string to write
|
||||
*/
|
||||
public void print(String toPrint) {
|
||||
if (!isInit)
|
||||
init();
|
||||
writer.print(toPrint);
|
||||
System.err.print(toPrint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given string to both stderr and errorlog. In addition, adds
|
||||
* a line terminator to the end of the string.
|
||||
*
|
||||
* @param toPrint string to write
|
||||
*/
|
||||
public void println(String toPrint) {
|
||||
if (!isInit)
|
||||
init();
|
||||
writer.println(toPrint);
|
||||
System.err.println(toPrint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given exception's stack trace to both stderr and errorlog.
|
||||
*
|
||||
* @param e exception to print
|
||||
*/
|
||||
public void printException(Exception e) {
|
||||
if (!isInit)
|
||||
init();
|
||||
e.printStackTrace(System.out);
|
||||
e.printStackTrace(writer);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.class
Normal file
Binary file not shown.
88
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.java
Normal file
88
nwn/nwnprc/DocGen/trunk/prc/autodoc/FeatEntry.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a feat or masterfeat entry.
|
||||
*/
|
||||
public class FeatEntry extends GenericEntry {
|
||||
/**
|
||||
* A list of masterfeat's children
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> childFeats = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of feats that have this feat as their prerequisite
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> requiredForFeats = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of this feat's AND prerequisites
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> andRequirements = new TreeMap<String, FeatEntry>();
|
||||
/**
|
||||
* A list of this feat's OR prerequisites
|
||||
*/
|
||||
public TreeMap<String, FeatEntry> orRequirements = new TreeMap<String, FeatEntry>();
|
||||
|
||||
/**
|
||||
* This feat's masterfeat, if any
|
||||
*/
|
||||
public FeatEntry master;
|
||||
/**
|
||||
* This feat's successor, if any
|
||||
*/
|
||||
public FeatEntry successor;
|
||||
|
||||
/**
|
||||
* Whether this feat is epic, as defined by feat.2da column PreReqEpic. For masterfeats, if any of the children are epic
|
||||
*/
|
||||
public boolean isEpic;
|
||||
/**
|
||||
* Whether all of a masterfeat's children are epic. This is used to determine which menus a link to it will be printed
|
||||
*/
|
||||
public boolean allChildrenEpic;
|
||||
/**
|
||||
* Whether the feat is a class-specific feat, as defined by feat.2da column ALLCLASSESCANUSE. For masterfeats, if any of the children are class-specific
|
||||
*/
|
||||
public boolean isClassFeat;
|
||||
/**
|
||||
* Whether all of a masterfeat's children are class-specific. This is used to determine which menus a link to it will be printed
|
||||
*/
|
||||
public boolean allChildrenClassFeat;
|
||||
/**
|
||||
* Whether this feat has a successor
|
||||
*/
|
||||
public boolean isSuccessor;
|
||||
|
||||
/**
|
||||
* The feat's subradials, if any. List of feat name, icon path tuples.
|
||||
*/
|
||||
public final List<Tuple<String, String>> subradials;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the feat/masterfeat
|
||||
* @param text Description of the feat
|
||||
* @param iconPath Path of the feat's icon
|
||||
* @param filePath Path where the html page for this feat will be written to
|
||||
* @param entryNum feat.2da / masterfeats.2da index
|
||||
* @param isEpic Whether the feat is an epic feat
|
||||
* @param isClassFeat Whether the feat is a class-specific feat
|
||||
* @param subradials List of this feat's subradials, if any
|
||||
*/
|
||||
public FeatEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, boolean isEpic, boolean isClassFeat,
|
||||
List<Tuple<String, String>> subradials) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.isEpic = isEpic;
|
||||
this.isClassFeat = isClassFeat;
|
||||
this.subradials = subradials;
|
||||
|
||||
master = null;
|
||||
successor = null;
|
||||
isSuccessor = false;
|
||||
allChildrenClassFeat = false;
|
||||
allChildrenEpic = false;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.class
Normal file
Binary file not shown.
57
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.java
Normal file
57
nwn/nwnprc/DocGen/trunk/prc/autodoc/GenericEntry.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* Data structure for a skill /domain / race / class / whatever that doesn't need
|
||||
* the extra fields used for feats & spells & skills
|
||||
*/
|
||||
public class GenericEntry implements Comparable<GenericEntry> {
|
||||
/**
|
||||
* The name of this entry.
|
||||
*/
|
||||
public final String name;
|
||||
|
||||
/**
|
||||
* The contents of this entry.
|
||||
*/
|
||||
public final String text;
|
||||
|
||||
/**
|
||||
* The path of the icon file attached to this entry.
|
||||
*/
|
||||
public final String iconPath;
|
||||
|
||||
/**
|
||||
* The path of the html file that has been written for this entry.
|
||||
*/
|
||||
public final String filePath;
|
||||
|
||||
/**
|
||||
* Index of the entry in whichever 2da defines it.
|
||||
*/
|
||||
public final int entryNum;
|
||||
|
||||
/**
|
||||
* @param name Name of the entry
|
||||
* @param text Content of the entry
|
||||
* @param iconPath Path of this entry's icon
|
||||
* @param filePath Path the generated file will be located in
|
||||
* @param entryNum Number of the
|
||||
*/
|
||||
public GenericEntry(String name, String text, String iconPath, String filePath, int entryNum) {
|
||||
this.name = name;
|
||||
this.text = text;
|
||||
this.iconPath = iconPath;
|
||||
this.filePath = filePath;
|
||||
this.entryNum = entryNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparable implementation. Uses the name fields for comparison.
|
||||
*
|
||||
* @param other GenericEntry to compare this one to
|
||||
* @return @see java.lang.Comparable#compareTo
|
||||
*/
|
||||
public int compareTo(GenericEntry other) {
|
||||
return name.compareTo(other.name);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Check.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Check.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Convert.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons$Convert.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.class
Normal file
Binary file not shown.
215
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.java
Normal file
215
nwn/nwnprc/DocGen/trunk/prc/autodoc/Icons.java
Normal file
@@ -0,0 +1,215 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.autodoc.Main.*;
|
||||
|
||||
/**
|
||||
* This class handles generating
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Icons {
|
||||
|
||||
/**
|
||||
* Visible from outside so that Main can wait on it.
|
||||
*/
|
||||
public static ExecutorService executor;
|
||||
//private static Timer timer;
|
||||
|
||||
private static boolean init = false;
|
||||
|
||||
private static HashSet<String> existingIcons = null;
|
||||
|
||||
private static HashMap<String, File> rawIcons = null;
|
||||
|
||||
private static void init() {
|
||||
/*try{
|
||||
reader = Jimi.createTypedJimiReader("image/targa");
|
||||
writer = Jimi.createTypedJimiWriter("image/png");
|
||||
}catch(JimiException e){
|
||||
err_pr.printException(e);
|
||||
icons = false;
|
||||
return;
|
||||
}*/
|
||||
init = true;
|
||||
existingIcons = new HashSet<String>();
|
||||
ImageIO.setUseCache(false);
|
||||
//executor = new ThreadPoolExecutor(50, 1000, 60, TimeUnit.SECONDS, bq);
|
||||
//timer = new Timer("Checker", true);
|
||||
executor = Executors.newCachedThreadPool();
|
||||
|
||||
rawIcons = new HashMap<String, File>();
|
||||
File[] tgas = new File("rawicons").listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().endsWith(".tga");
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure the icons directory exists
|
||||
if (tgas == null) {
|
||||
err_pr.println("Error: Icons directory is missing!");
|
||||
if (tolErr) return;
|
||||
else System.exit(1);
|
||||
}
|
||||
|
||||
for (File tga : tgas)
|
||||
rawIcons.put(tga.getName().toLowerCase(), tga);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds an <img>-tag pointing at a png-converted version of the
|
||||
* given icon.
|
||||
* If such an icon does not exist, returns a blank string.
|
||||
* The icon will be converted to PNG format if it has not yet been.
|
||||
*
|
||||
* @param iconName name of the icon to use
|
||||
* @return <img>-tag pointing at the image or a blank string
|
||||
*/
|
||||
public static String buildIcon(String iconName) {
|
||||
if (!icons) return "";
|
||||
else if (!init) init();
|
||||
|
||||
if (iconName.equals("****"))
|
||||
return "";
|
||||
|
||||
// Lowercase the name
|
||||
iconName = iconName.toLowerCase();
|
||||
|
||||
// Build the html
|
||||
String tag = iconTemplate.replace("~~~ImageURL~~~", "../../../images/" + iconName + ".png")
|
||||
.replace("~~~ImageName~~~", iconName);
|
||||
|
||||
// Case of already existing and indexed image
|
||||
if (existingIcons.contains(iconName))
|
||||
return tag;
|
||||
|
||||
File png = new File(imagePath + iconName + ".png");
|
||||
// See if the converted image exists already, but just hasn't been indexed yet
|
||||
if (png.exists()) {
|
||||
existingIcons.add(iconName);
|
||||
return tag;
|
||||
}
|
||||
|
||||
File tga = rawIcons.get(iconName + ".tga");
|
||||
// There is no icon to convert
|
||||
if (tga == null) {
|
||||
err_pr.println("Error: Missing icon file: " + iconName + ".tga");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Schedule the conversion for execution
|
||||
Convert task = new Convert();
|
||||
task.init(tga, png);
|
||||
Future fut = executor.submit(task);
|
||||
|
||||
|
||||
// Schedule timer task
|
||||
/*
|
||||
Check check = new Check();
|
||||
check.init(fut, iconName);
|
||||
timer.schedule(check, System.currentTimeMillis() + 30000);
|
||||
*/
|
||||
/*
|
||||
try{
|
||||
reader.setSource(new FileInputStream(new File("rawicons" + fileSeparator + iconName + ".tga")));
|
||||
writer.setSource(reader.getImage());
|
||||
writer.putImage(imagePath + iconName + ".png");
|
||||
}catch(Exception e){
|
||||
err_pr.printException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
*/
|
||||
// Assume eventual success and add the newly created image to the index
|
||||
existingIcons.add(iconName);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static class Convert implements Runnable {
|
||||
private File inFile, outFile;
|
||||
|
||||
/**
|
||||
* Initialization method
|
||||
*
|
||||
* @param inFile input file, Targa format
|
||||
* @param outFile output file, Portable Network Graphics format
|
||||
*/
|
||||
public void init(File inFile, File outFile) {
|
||||
this.inFile = inFile;
|
||||
this.outFile = outFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
if (!ImageIO.write(ImageIO.read(inFile), "png", outFile))
|
||||
err_pr.println("Error: Failed to convert image " + inFile);
|
||||
} catch (IOException e) {
|
||||
err_pr.printException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Check extends TimerTask {
|
||||
private Future toCheck;
|
||||
private String iconName;
|
||||
|
||||
/**
|
||||
* Initialization method
|
||||
*
|
||||
* @param toCheck future representing the image conversion to check on
|
||||
* @param iconName name of the icon being converted by the task to check on
|
||||
*/
|
||||
public void init(Future toCheck, String iconName) {
|
||||
this.toCheck = toCheck;
|
||||
this.iconName = iconName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.TimerTask#run()
|
||||
*/
|
||||
public void run() {
|
||||
if (!toCheck.isDone()) {
|
||||
toCheck.cancel(true);
|
||||
err_pr.println("Error: Failed icon conversion on file " + iconName + ".tga");
|
||||
}
|
||||
|
||||
//executor.purge();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
System.out.println("Yar!");
|
||||
icons = true;
|
||||
iconTemplate = readTemplate("templates" + fileSeparator + "english" + fileSeparator + "icon.html");
|
||||
System.out.println(buildImg("test"));
|
||||
|
||||
ImageIO.setUseCache(false);
|
||||
Iterator<ImageReader> it = ImageIO.getImageReadersByMIMEType("image/targa");
|
||||
while(it.hasNext())
|
||||
System.out.println(it.next().getFormatName());
|
||||
|
||||
java.awt.image.BufferedImage buf = ImageIO.read(new File("isk_x1app.tga"));
|
||||
System.out.println("Tar!");
|
||||
ImageIO.write(buf, "png", new File("test.png"));
|
||||
System.out.println("Far!");
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings$Modes.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings$Modes.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$Settings.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$SpellType.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$SpellType.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TLKStore.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TLKStore.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore$Loader.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore$Loader.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main$TwoDAStore.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.class
Normal file
Binary file not shown.
984
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.java
Normal file
984
nwn/nwnprc/DocGen/trunk/prc/autodoc/Main.java
Normal file
@@ -0,0 +1,984 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static prc.Main.*;
|
||||
import static prc.autodoc.EntryGeneration.*;
|
||||
import static prc.autodoc.MenuGeneration.*;
|
||||
import static prc.autodoc.PageGeneration.*;
|
||||
|
||||
/**
|
||||
* The main purpose of this autodocumenter is to create parts of the manual for
|
||||
* the PRC pack from 2da and TLK files. As a side effect of doing so, it finds
|
||||
* many errors present in the 2das.
|
||||
*/
|
||||
public class Main {
|
||||
/**
|
||||
* A small data structure class that gives access to both normal and custom
|
||||
* TLK with the same method
|
||||
*/
|
||||
public static class TLKStore {
|
||||
private final Data_TLK normal;
|
||||
private final Data_TLK custom;
|
||||
|
||||
/**
|
||||
* Creates a new TLKStore around the given two filenames. Equivalent to
|
||||
* TLKStore(normalName, customName, "tlk").
|
||||
*
|
||||
* @param normalName dialog.tlk or equivalent for the given language
|
||||
* @param customName prc_consortium.tlk or equivalent for the given languag
|
||||
* @throws TLKReadException if there are any problems reading either TLK
|
||||
*/
|
||||
public TLKStore(String normalName, String customName) {
|
||||
this.normal = new Data_TLK("tlk" + fileSeparator + normalName);
|
||||
this.custom = new Data_TLK("tlk" + fileSeparator + customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TLKStore around the given two filenames.
|
||||
*
|
||||
* @param normalName dialog.tlk or equivalent for the given language
|
||||
* @param customName prc_consortium.tlk or equivalent for the given languag
|
||||
* @param tlkDir Directory containing the two .tlk files
|
||||
* @throws TLKReadException if there are any problems reading either TLK
|
||||
*/
|
||||
public TLKStore(String normalName, String customName, String tlkDir) {
|
||||
this.normal = new Data_TLK(tlkDir + fileSeparator + normalName);
|
||||
this.custom = new Data_TLK(tlkDir + fileSeparator + customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TLK entry for the given StrRef. If there is nothing
|
||||
* at the location, returns Bad StrRef. Automatically picks between
|
||||
* normal and custom TLKs.
|
||||
*
|
||||
* @param num the line number in TLK
|
||||
* @return the contents of the given TLK slot, or Bad StrRef
|
||||
*/
|
||||
public String get(int num) {
|
||||
return num < 0x01000000 ? normal.getEntry(num) : custom.getEntry(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* See above, except that this one automatically parses the string for
|
||||
* the number.
|
||||
*
|
||||
* @param num the line number in TLK as string
|
||||
* @return as above, except it returns Bad StrRef in case parsing failed
|
||||
*/
|
||||
public String get(String num) {
|
||||
try {
|
||||
return get(Integer.parseInt(num));
|
||||
} catch (NumberFormatException e) {
|
||||
return Main.badStrRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Another data structure class. Stores 2das and handles loading them.
|
||||
*/
|
||||
public static class TwoDAStore {
|
||||
private static class Loader implements Runnable {
|
||||
private final String pathToLoad;
|
||||
private final List<Data_2da> list;
|
||||
private final CountDownLatch latch;
|
||||
|
||||
/**
|
||||
* Creates a new Loader to load the given 2da file
|
||||
*
|
||||
* @param pathToLoad path of the 2da to load
|
||||
* @param list list to store the loaded data into
|
||||
* @param latch latch to countdown on once loading is complete
|
||||
*/
|
||||
public Loader(String pathToLoad, List<Data_2da> list, CountDownLatch latch) {
|
||||
this.pathToLoad = pathToLoad;
|
||||
this.list = list;
|
||||
this.latch = latch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
Data_2da data = Data_2da.load2da(pathToLoad, true);
|
||||
list.add(data);
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failure while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final HashMap<String, Data_2da> data = new HashMap<String, Data_2da>();
|
||||
private final String twoDAPath;
|
||||
|
||||
/**
|
||||
* Creates a new TwoDAStore, without preloading anything.
|
||||
*
|
||||
* @param twoDAPath Path of the directory containing 2da files.
|
||||
*/
|
||||
public TwoDAStore(String twoDAPath) {
|
||||
this.twoDAPath = twoDAPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new TwoDAStore with all the main 2das preread in.
|
||||
* On a read failure, kills program execution, since there's nothing
|
||||
* that could be done anyway.
|
||||
*/
|
||||
public TwoDAStore() {
|
||||
this("2da");
|
||||
//long start = System.currentTimeMillis();
|
||||
if (verbose) System.out.print("Loading main 2da files ");
|
||||
boolean oldVerbose = verbose;
|
||||
verbose = false;
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(7);
|
||||
List<Data_2da> list = Collections.synchronizedList(new ArrayList<Data_2da>());
|
||||
// Read the main 2das
|
||||
new Thread(new Loader("2da" + fileSeparator + "classes.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "domains.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "feat.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "masterfeats.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "racialtypes.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "skills.2da", list, latch)).start();
|
||||
new Thread(new Loader("2da" + fileSeparator + "spells.2da", list, latch)).start();
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
err_pr.println("Error: Interrupted while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for (Data_2da entry : list)
|
||||
data.put(entry.getName(), entry);
|
||||
verbose = oldVerbose;
|
||||
if (verbose) System.out.println("- Done");
|
||||
/*
|
||||
try{
|
||||
data.put("classes", new Data_2da("2da" + fileSeparator + "classes.2da"));
|
||||
data.put("domains", new Data_2da("2da" + fileSeparator + "domains.2da"));
|
||||
data.put("feat", new Data_2da("2da" + fileSeparator + "feat.2da"));
|
||||
data.put("masterfeats", new Data_2da("2da" + fileSeparator + "masterfeats.2da"));
|
||||
data.put("racialtypes", new Data_2da("2da" + fileSeparator + "racialtypes.2da"));
|
||||
data.put("skills", new Data_2da("2da" + fileSeparator + "skills.2da"));
|
||||
data.put("spells", new Data_2da("2da" + fileSeparator + "spells.2da"));
|
||||
}catch(Exception e){
|
||||
err_pr.println("Error: Failure while reading main 2das. Exception data:\n");
|
||||
err_pr.printException(e);
|
||||
System.exit(1);
|
||||
}
|
||||
*/
|
||||
//System.out.println("Time taken: " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Data_2da structure wrapping the given 2da. If it hasn't been loaded
|
||||
* yet, the loading is done now.
|
||||
*
|
||||
* @param name name of the 2da to get. Without the file end ".2da".
|
||||
* @return a Data_2da structure
|
||||
* @throws TwoDAReadException if any errors are encountered while reading
|
||||
*/
|
||||
public Data_2da get(String name) {
|
||||
if (data.containsKey(name))
|
||||
return data.get(name);
|
||||
else {
|
||||
Data_2da temp = null;
|
||||
try {
|
||||
temp = Data_2da.load2da(twoDAPath + fileSeparator + name + ".2da", true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new TwoDAReadException("Problem with filename when trying to read from 2da:\n" + e);
|
||||
}
|
||||
data.put(name, temp);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for handling the settings file.
|
||||
*/
|
||||
public static class Settings {
|
||||
/* Some pattern matchers for use when parsing the settings file */
|
||||
private final Matcher mainMatch = Pattern.compile("\\S+:").matcher("");
|
||||
private final Matcher paraMatch = Pattern.compile("\"[^\"]+\"").matcher("");
|
||||
private final Matcher langMatch = Pattern.compile("\\w+=\"[^\"]+\"").matcher("");
|
||||
|
||||
/* An enumeration of the possible setting types */
|
||||
private enum Modes {
|
||||
/**
|
||||
* The parser is currently working on lines specifying languages used.
|
||||
*/
|
||||
LANGUAGE,
|
||||
/**
|
||||
* The parser is currently working on lines containing string patterns that are
|
||||
* used in differentiating between entries in spells.2da.
|
||||
*/
|
||||
SIGNATURE,
|
||||
/**
|
||||
* The parser is currently working on lines listing spells.2da entries that contain
|
||||
* a significantly modified BW spell.
|
||||
*/
|
||||
MODIFIED_SPELL
|
||||
}
|
||||
|
||||
/* Settings data read in */
|
||||
/**
|
||||
* The settings for languages. An ArrayList of String[] containing setting for a specific language
|
||||
*/
|
||||
public ArrayList<String[]> languages = new ArrayList<String[]>();
|
||||
/**
|
||||
* An ArrayList of Integers. Indices to spells.2da of standard spells modified by the PRC
|
||||
*/
|
||||
public ArrayList<Integer> modifiedSpells = new ArrayList<Integer>();
|
||||
/**
|
||||
* A set of script name prefixes used to find epic spell entries in spells.2da
|
||||
*/
|
||||
public String[] epicspellSignatures = null;
|
||||
/*/** A set of script name prefixes used to find psionic power entries in spells.2da *
|
||||
public String[] psionicpowerSignatures = null;*/
|
||||
|
||||
/**
|
||||
* Read the settings file in and store the data for later access.
|
||||
* Terminates execution on any errors.
|
||||
*/
|
||||
public Settings() {
|
||||
try {
|
||||
// The settings file should be present in the directory this is run from
|
||||
Scanner reader = new Scanner(new File("settings"));
|
||||
String check;
|
||||
Modes mode = null;
|
||||
while (reader.hasNextLine()) {
|
||||
check = reader.nextLine();
|
||||
|
||||
// Skip comments and blank lines
|
||||
if (check.startsWith("#") || check.trim().equals("")) continue;
|
||||
|
||||
// Check if a new rule is starting
|
||||
mainMatch.reset(check);
|
||||
if (mainMatch.find()) {
|
||||
if (mainMatch.group().equals("language:")) mode = Modes.LANGUAGE;
|
||||
else if (mainMatch.group().equals("signature:")) mode = Modes.SIGNATURE;
|
||||
else if (mainMatch.group().equals("modified_spell:")) mode = Modes.MODIFIED_SPELL;
|
||||
else {
|
||||
throw new Exception("Unrecognized setting detected");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take action based on current mode
|
||||
if (mode == Modes.LANGUAGE) {
|
||||
String[] temp = new String[LANGDATA_NUMENTRIES];
|
||||
String result;
|
||||
langMatch.reset(check);
|
||||
// parse the language entry
|
||||
for (int i = 0; i < LANGDATA_NUMENTRIES; i++) {
|
||||
if (!langMatch.find())
|
||||
throw new Exception("Missing language parameter");
|
||||
result = langMatch.group();
|
||||
|
||||
if (result.startsWith("name=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_LANGNAME] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("base=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_BASETLK] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("prc=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PRCTLK] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("feats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_FEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("allfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_ALLFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("epicfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_EPICFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("allepicfeats=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_ALLEPICFEATSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("baseclasses=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_BASECLASSESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("prestigeclasses=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PRESTIGECLASSESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("spells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("epicspells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_EPICSPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("psipowers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_PSIONICPOWERSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("modspells=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_MODIFIEDSPELLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("skills=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SKILLSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("domains=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_DOMAINSTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("races=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_RACESTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("spellbook=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_SPELLBOOKTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("powers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_POWERTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("truenameutterances=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_TRUENAMEUTTERANCETXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("invocations=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_INVOCATIONTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("maneuvers=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_MANEUVERTXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else if (result.startsWith("utterances=")) {
|
||||
paraMatch.reset(result);
|
||||
paraMatch.find();
|
||||
temp[LANGDATA_UTTERANCETXT] = paraMatch.group().substring(1, paraMatch.group().length() - 1);
|
||||
} else
|
||||
throw new Exception("Unknown language parameter encountered\n" + check);
|
||||
}
|
||||
languages.add(temp);
|
||||
}
|
||||
// Parse the spell script name signatures
|
||||
if (mode == Modes.SIGNATURE) {
|
||||
String[] temp = check.trim().split("=");
|
||||
if (temp[0].equals("epicspell")) {
|
||||
epicspellSignatures = temp[1].replace("\"", "").split("\\|");
|
||||
}/* Not needed anymore
|
||||
else if(temp[0].equals("psionicpower")){
|
||||
psionicpowerSignatures = temp[1].replace("\"", "").split("\\|");
|
||||
}*/ else
|
||||
throw new Exception("Unknown signature parameter encountered:\n" + check);
|
||||
}
|
||||
// Parse the spell modified spell indices
|
||||
if (mode == Modes.MODIFIED_SPELL) {
|
||||
modifiedSpells.add(Integer.parseInt(check.trim()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failed to read settings file:\n" + e + "\nAborting");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A small enumeration for use in spell printing methods
|
||||
*/
|
||||
public enum SpellType {
|
||||
/**
|
||||
* The spell is not a real spell or psionic power, instead specifies some feat's spellscript.
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* The spell is a normal spell.
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* The spell is an epic spell.
|
||||
*/
|
||||
EPIC,
|
||||
/**
|
||||
* The spell is a psionic power.
|
||||
*/
|
||||
PSIONIC,
|
||||
/**
|
||||
* The spell is a truename utterance.
|
||||
*/
|
||||
UTTERANCE,
|
||||
/**
|
||||
* The spell is an invocation.
|
||||
*/
|
||||
INVOCATION,
|
||||
/**
|
||||
* The spell is a maneuver.
|
||||
*/
|
||||
MANEUVER
|
||||
}
|
||||
|
||||
/**
|
||||
* A switche determinining how errors are handled
|
||||
*/
|
||||
public static boolean tolErr = true;
|
||||
|
||||
/**
|
||||
* A boolean determining whether to print icons for the pages or not
|
||||
*/
|
||||
public static boolean icons = false;
|
||||
|
||||
/**
|
||||
* A constant signifying Bad StrRef
|
||||
*/
|
||||
public static final String badStrRef = "Bad StrRef";
|
||||
|
||||
/**
|
||||
* The container object for general configuration data read from file
|
||||
*/
|
||||
public static Settings settings;// = new Settings();
|
||||
|
||||
/**
|
||||
* The file separator, given it's own constant for ease of use
|
||||
*/
|
||||
public static final String fileSeparator = System.getProperty("file.separator");
|
||||
|
||||
/**
|
||||
* Array of the settings for currently used language. Index with the LANGDATA_ constants
|
||||
*/
|
||||
public static String[] curLanguageData = null;
|
||||
|
||||
/**
|
||||
* Size of the curLanguageData array
|
||||
*/
|
||||
public static final int LANGDATA_NUMENTRIES = 22;
|
||||
/**
|
||||
* curLanguageData index of the language name
|
||||
*/
|
||||
public static final int LANGDATA_LANGNAME = 0;
|
||||
/**
|
||||
* curLanguageData index of the name of the dialog.tlk equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_BASETLK = 1;
|
||||
/**
|
||||
* curLanguageData index of the name of the prc_consortium.tlk equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PRCTLK = 2;
|
||||
/**
|
||||
* curLanguageData index of the name of the "All Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_ALLFEATSTXT = 3;
|
||||
/**
|
||||
* curLanguageData index of the name of the "All Epic Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_ALLEPICFEATSTXT = 4;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_FEATSTXT = 5;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Epic Feats" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_EPICFEATSTXT = 6;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Base Classes" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_BASECLASSESTXT = 7;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Prestige Classes" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PRESTIGECLASSESTXT = 8;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SPELLSTXT = 9;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Epic Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_EPICSPELLSTXT = 10;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Psionic Powers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_PSIONICPOWERSTXT = 11;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Modified Spells" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_MODIFIEDSPELLSTXT = 12;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Domains" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_DOMAINSTXT = 13;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Skills" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SKILLSTXT = 14;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Races" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_RACESTXT = 15;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Spellbook" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_SPELLBOOKTXT = 16;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Powers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_POWERTXT = 17;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Truename Utterances" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_TRUENAMEUTTERANCETXT = 18;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Invocations" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_INVOCATIONTXT = 19;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Maneuvers" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_MANEUVERTXT = 20;
|
||||
/**
|
||||
* curLanguageData index of the name of the "Utterances" string equivalent for this language
|
||||
*/
|
||||
public static final int LANGDATA_UTTERANCETXT = 21;
|
||||
|
||||
|
||||
/**
|
||||
* Current language name
|
||||
*/
|
||||
public static String curLanguage = null;
|
||||
|
||||
/**
|
||||
* The base path. <code>"manual" + fileSeparator + curLanguage + fileSeparator</code>
|
||||
*/
|
||||
public static String mainPath = null;
|
||||
/**
|
||||
* The path to content directory. <code>mainPath + "content" + fileSeparator</code>
|
||||
*/
|
||||
public static String contentPath = null;
|
||||
/**
|
||||
* The path to menu directory. <code>mainPath + "mainPath" + fileSeparator</code>
|
||||
*/
|
||||
public static String menuPath = null;
|
||||
/**
|
||||
* The path to the image directory. <code>"manual" + fileSeparator + "images" + fileSeparator</code>
|
||||
*/
|
||||
public static String imagePath = "manual" + fileSeparator + "images" + fileSeparator;
|
||||
|
||||
/**
|
||||
* Data structures for accessing TLKs
|
||||
*/
|
||||
public static TwoDAStore twoDA;
|
||||
/**
|
||||
* Data structures for accessing TLKs
|
||||
*/
|
||||
public static TLKStore tlk;
|
||||
|
||||
|
||||
/**
|
||||
* The template files
|
||||
*/
|
||||
public static String babAndSavthrTableHeaderTemplate = null,
|
||||
classTemplate = null,
|
||||
classTablesEntryTemplate = null,
|
||||
domainTemplate = null,
|
||||
featTemplate = null,
|
||||
mFeatTemplate = null,
|
||||
menuTemplate = null,
|
||||
menuItemTemplate = null,
|
||||
prereqANDFeatHeaderTemplate = null,
|
||||
prereqORFeatHeaderTemplate = null,
|
||||
raceTemplate = null,
|
||||
spellTemplate = null,
|
||||
skillTableHeaderTemplate = null,
|
||||
skillTemplate = null,
|
||||
successorFeatHeaderTemplate = null,
|
||||
iconTemplate = null,
|
||||
listEntrySetTemplate = null,
|
||||
listEntryTemplate = null,
|
||||
alphaSortedListTemplate = null,
|
||||
requiredForFeatHeaderTemplate = null,
|
||||
pageLinkTemplate = null,
|
||||
featMenuTemplate = null,
|
||||
spellSubradialListTemplate = null,
|
||||
spellSubradialListEntryTemplate = null,
|
||||
classFeatTableTemplate = null,
|
||||
classFeatTableEntryTemplate = null,
|
||||
classMagicTableTemplate = null,
|
||||
classMagicTableEntryTemplate = null,
|
||||
craftTemplate = null;
|
||||
|
||||
|
||||
/* Data structures to store generated entry data in */
|
||||
public static HashMap<Integer, SpellEntry> spells;
|
||||
public static HashMap<Integer, FeatEntry> masterFeats,
|
||||
feats;
|
||||
public static HashMap<Integer, ClassEntry> classes;
|
||||
public static HashMap<Integer, DomainEntry> domains;
|
||||
public static HashMap<Integer, RaceEntry> races;
|
||||
public static HashMap<Integer, GenericEntry> skills;
|
||||
|
||||
public static HashMap<Integer, GenericEntry> craft_armour;
|
||||
public static HashMap<Integer, GenericEntry> craft_weapon;
|
||||
public static HashMap<Integer, GenericEntry> craft_ring;
|
||||
public static HashMap<Integer, GenericEntry> craft_wondrous;
|
||||
|
||||
/**
|
||||
* Map of psionic power names to the indexes of the spells.2da entries chosen to represent the power in question
|
||||
*/
|
||||
public static HashMap<String, Integer> psiPowMap;
|
||||
|
||||
/**
|
||||
* Map of truenaming utterance names to the spells.2da indexes that contain utterance feat-linked entries
|
||||
*/
|
||||
public static HashMap<String, Integer> utterMap;
|
||||
|
||||
/**
|
||||
* Map of invocations to spells.2da
|
||||
*/
|
||||
public static HashMap<String, Integer> invMap;
|
||||
|
||||
/**
|
||||
* Map of maneuvers to spells.2da
|
||||
*/
|
||||
public static HashMap<String, Integer> maneuverMap;
|
||||
|
||||
|
||||
/**
|
||||
* Ye olde maine methode
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
/* Argument parsing */
|
||||
for (String opt : args) {
|
||||
if (opt.equals("--help"))
|
||||
readMe();
|
||||
|
||||
if (opt.startsWith("-")) {
|
||||
if (opt.contains("a"))
|
||||
tolErr = true;
|
||||
if (opt.contains("q")) {
|
||||
verbose = false;
|
||||
spinner.disable();
|
||||
}
|
||||
if (opt.contains("i"))
|
||||
icons = true;
|
||||
if (opt.contains("s"))
|
||||
spinner.disable();
|
||||
if (opt.contains("?"))
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
|
||||
// Load the settings
|
||||
settings = new Settings();
|
||||
|
||||
// Initialize the 2da container data structure
|
||||
twoDA = new TwoDAStore();
|
||||
|
||||
|
||||
// Print the manual files for each language specified
|
||||
for (int i = 0; i < settings.languages.size(); i++) {
|
||||
// Set language, path and load TLKs
|
||||
curLanguageData = settings.languages.get(i);
|
||||
curLanguage = curLanguageData[LANGDATA_LANGNAME];
|
||||
mainPath = "manual" + fileSeparator + curLanguage + fileSeparator;
|
||||
contentPath = mainPath + "content" + fileSeparator;
|
||||
menuPath = mainPath + "menus" + fileSeparator;
|
||||
|
||||
// If we fail on a language, skip to next one
|
||||
try {
|
||||
tlk = new TLKStore(curLanguageData[LANGDATA_BASETLK], curLanguageData[LANGDATA_PRCTLK]);
|
||||
} catch (TLKReadException e) {
|
||||
err_pr.println("Error: Failure while reading TLKs for language: " + curLanguage + ":\n" + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip to next if there is any problem with directories or templates
|
||||
if (!(readTemplates() && buildDirectories())) continue;
|
||||
|
||||
// Do the actual work
|
||||
createPages();
|
||||
createMenus();
|
||||
}
|
||||
|
||||
// Wait for the image conversion to finish before exiting main
|
||||
if (Icons.executor != null) {
|
||||
Icons.executor.shutdown();
|
||||
try {
|
||||
Icons.executor.awaitTermination(120, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
err_pr.println("Error: Interrupted while waiting for image conversion to finish");
|
||||
} finally {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the use instructions for this program and kills execution.
|
||||
*/
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" java prc/autodoc/Main [--help][-aiqs?]\n" +
|
||||
"\n" +
|
||||
"-a forces aborting printing on errors\n" +
|
||||
"-i adds icons to pages\n" +
|
||||
"-q quiet mode. Does not print any progress info, only failure messages\n" +
|
||||
"-s disable the spinner. Useful when logging to file\n" +
|
||||
"\n" +
|
||||
"--help prints this info you are reading\n" +
|
||||
"-? see --help\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all the template files for the current language.
|
||||
*
|
||||
* @return <code>true</code> if all the reads succeeded, <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean readTemplates() {
|
||||
String templatePath = "templates" + fileSeparator + curLanguage + fileSeparator;
|
||||
|
||||
try {
|
||||
babAndSavthrTableHeaderTemplate = readTemplate(templatePath + "babNsavthrtableheader.html");
|
||||
classTablesEntryTemplate = readTemplate(templatePath + "classtablesentry.html");
|
||||
classTemplate = readTemplate(templatePath + "class.html");
|
||||
domainTemplate = readTemplate(templatePath + "domain.html");
|
||||
featTemplate = readTemplate(templatePath + "feat.html");
|
||||
mFeatTemplate = readTemplate(templatePath + "masterfeat.html");
|
||||
menuTemplate = readTemplate(templatePath + "menu.html");
|
||||
menuItemTemplate = readTemplate(templatePath + "menuitem.html");
|
||||
prereqANDFeatHeaderTemplate = readTemplate(templatePath + "prerequisiteandfeatheader.html");
|
||||
prereqORFeatHeaderTemplate = readTemplate(templatePath + "prerequisiteorfeatheader.html");
|
||||
raceTemplate = readTemplate(templatePath + "race.html");
|
||||
spellTemplate = readTemplate(templatePath + "spell.html");
|
||||
skillTableHeaderTemplate = readTemplate(templatePath + "skilltableheader.html");
|
||||
skillTemplate = readTemplate(templatePath + "skill.html");
|
||||
successorFeatHeaderTemplate = readTemplate(templatePath + "successorfeatheader.html");
|
||||
iconTemplate = readTemplate(templatePath + "icon.html");
|
||||
listEntrySetTemplate = readTemplate(templatePath + "listpageentryset.html");
|
||||
listEntryTemplate = readTemplate(templatePath + "listpageentry.html");
|
||||
alphaSortedListTemplate = readTemplate(templatePath + "alphasorted_listpage.html");
|
||||
requiredForFeatHeaderTemplate = readTemplate(templatePath + "reqforfeatheader.html");
|
||||
pageLinkTemplate = readTemplate(templatePath + "pagelink.html");
|
||||
featMenuTemplate = readTemplate(templatePath + "featmenu.html");
|
||||
spellSubradialListTemplate = readTemplate(templatePath + "spellsubradials.html");
|
||||
spellSubradialListEntryTemplate = readTemplate(templatePath + "spellsubradialsentry.html");
|
||||
classFeatTableTemplate = readTemplate(templatePath + "classfeattable.html");
|
||||
classFeatTableEntryTemplate = readTemplate(templatePath + "classfeattableentry.html");
|
||||
classMagicTableTemplate = readTemplate(templatePath + "classmagictable.html");
|
||||
classMagicTableEntryTemplate = readTemplate(templatePath + "classmagictableentry.html");
|
||||
craftTemplate = readTemplate(templatePath + "craftprop.html");
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the template file given as parameter and returns a string with it's contents
|
||||
* Kills execution if any operations fail.
|
||||
*
|
||||
* @param filePath string representing the path of the template file
|
||||
* @return the contents of the template file as a string
|
||||
* @throws IOException if the reading fails
|
||||
*/
|
||||
private static String readTemplate(String filePath) throws IOException {
|
||||
try {
|
||||
Scanner reader = new Scanner(new File(filePath));
|
||||
StringBuffer temp = new StringBuffer();
|
||||
|
||||
while (reader.hasNextLine()) temp.append(reader.nextLine() + "\n");
|
||||
|
||||
return temp.toString();
|
||||
} catch (Exception e) {
|
||||
err_pr.println("Error: Failed to read template file:\n" + e);
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the directory structure for the current language
|
||||
* being processed.
|
||||
*
|
||||
* @return <code>true</code> if all directories are successfully created,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean buildDirectories() {
|
||||
String dirPath = mainPath + "content";
|
||||
|
||||
boolean toReturn = buildDir(dirPath);
|
||||
dirPath += fileSeparator;
|
||||
|
||||
toReturn = toReturn
|
||||
&& buildDir(dirPath + "base_classes")
|
||||
&& buildDir(dirPath + "class_epic_feats")
|
||||
&& buildDir(dirPath + "class_feats")
|
||||
&& buildDir(dirPath + "domains")
|
||||
&& buildDir(dirPath + "epic_feats")
|
||||
&& buildDir(dirPath + "epic_spells")
|
||||
&& buildDir(dirPath + "feats")
|
||||
&& buildDir(dirPath + "itemcrafting")
|
||||
&& buildDir(dirPath + "master_feats")
|
||||
&& buildDir(dirPath + "prestige_classes")
|
||||
&& buildDir(dirPath + "psionic_powers")
|
||||
&& buildDir(dirPath + "races")
|
||||
&& buildDir(dirPath + "skills")
|
||||
&& buildDir(dirPath + "spells")
|
||||
&& buildDir(dirPath + "utterances")
|
||||
&& buildDir(dirPath + "invocations")
|
||||
&& buildDir(dirPath + "maneuvers")
|
||||
|
||||
&& buildDir(mainPath + "menus");
|
||||
|
||||
System.gc();
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual work of building the directories
|
||||
*
|
||||
* @param path the target directory to create
|
||||
* @return <code>true</code> if the directory was already present or was successfully created,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
private static boolean buildDir(String path) {
|
||||
File builder = new File(path);
|
||||
if (!builder.exists()) {
|
||||
if (!builder.mkdirs()) {
|
||||
err_pr.println("Error: Failure creating directory:\n" + builder.getPath());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!builder.isDirectory()) {
|
||||
err_pr.println(builder.getPath() + " already exists as a file!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces each line break in the given TLK entry with
|
||||
* a line break followed by <code><br /></code>.
|
||||
*
|
||||
* @param toHTML tlk entry to convert
|
||||
* @return the modified string
|
||||
*/
|
||||
public static String htmlizeTLK(String toHTML) {
|
||||
return toHTML.replaceAll("\n", "\n<br />");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file at the given <code>path</code>, erasing previous file if present.
|
||||
* Prints the given <code>content</code> string into the file.
|
||||
*
|
||||
* @param path the path of the file to be created
|
||||
* @param content the string to be printed into the file
|
||||
* @throws PageGenerationException if one of the file operations fails
|
||||
*/
|
||||
public static void printPage(String path, String content) {
|
||||
try {
|
||||
File target = new File(path);
|
||||
// Clean up old version if necessary
|
||||
if (target.exists()) {
|
||||
if (verbose) System.out.println("Deleting previous version of " + path);
|
||||
target.delete();
|
||||
}
|
||||
target.createNewFile();
|
||||
|
||||
// Creater the writer and print
|
||||
FileWriter writer = new FileWriter(target, false);
|
||||
writer.write(content);
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
throw new PageGenerationException("IOException when printing " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Page creation. Calls all the specific functions for different page types
|
||||
*/
|
||||
private static void createPages() {
|
||||
/* First, do the pages that do not require linking to other pages */
|
||||
doSkills();
|
||||
doCrafting();
|
||||
listPsionicPowers();
|
||||
listTruenameUtterances();
|
||||
listInvocations();
|
||||
listManeuvers();
|
||||
doSpells();
|
||||
|
||||
/* Then, build the feats */
|
||||
preliMasterFeats();
|
||||
preliFeats();
|
||||
linkFeats();
|
||||
|
||||
/* Last, domains, races and classes, which all link to the previous */
|
||||
doDomains();
|
||||
doRaces();
|
||||
doClasses();
|
||||
|
||||
/* Then, print all of it */
|
||||
printSkills();
|
||||
printSpells();
|
||||
printFeats();
|
||||
printDomains();
|
||||
printRaces();
|
||||
printClasses();
|
||||
printCrafting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu creation. Calls the specific functions for different menu types
|
||||
*/
|
||||
private static void createMenus() {
|
||||
/* First, the types that do not need any extra data beyond name & path
|
||||
* and use GenericEntry
|
||||
*/
|
||||
doGenericMenu(skills, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_skills.html");
|
||||
doGenericMenu(domains, curLanguageData[LANGDATA_DOMAINSTXT], "manual_menus_domains.html");
|
||||
doGenericMenu(races, curLanguageData[LANGDATA_RACESTXT], "manual_menus_races.html");
|
||||
doGenericMenu(craft_armour, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_armour.html");
|
||||
doGenericMenu(craft_weapon, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_weapon.html");
|
||||
doGenericMenu(craft_ring, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_ring.html");
|
||||
doGenericMenu(craft_wondrous, curLanguageData[LANGDATA_SKILLSTXT], "manual_menus_craft_wondrous.html");
|
||||
/* Then the more specialised data where it needs to be split over several
|
||||
* menu pages
|
||||
*/
|
||||
doSpellMenus();
|
||||
doFeatMenus();
|
||||
doClassMenus();
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.class
Normal file
Binary file not shown.
263
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.java
Normal file
263
nwn/nwnprc/DocGen/trunk/prc/autodoc/MenuGeneration.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package prc.autodoc;
|
||||
|
||||
//import java.io.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.verbose;
|
||||
import static prc.autodoc.Main.*;
|
||||
import static prc.autodoc.Main.SpellType.*;
|
||||
|
||||
public final class MenuGeneration {
|
||||
private MenuGeneration() {/* No instances */}
|
||||
|
||||
/**
|
||||
* Sorts any of the pages for which GenericEntry is enough into alphabetic order
|
||||
* using a TreeMap, and prints a menu page out of the results.
|
||||
*/
|
||||
public static void doGenericMenu(HashMap<Integer, ? extends GenericEntry> entries, String menuName, String menuFileName) {
|
||||
TreeMap<String, String> links = new TreeMap<String, String>();
|
||||
StringBuffer toPrint = new StringBuffer();
|
||||
|
||||
if (verbose) System.out.println("Printing menu for " + menuName);
|
||||
|
||||
for (GenericEntry entry : entries.values()) {
|
||||
links.put(entry.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
entry.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", entry.name));
|
||||
}
|
||||
|
||||
while (links.size() > 0) {
|
||||
toPrint.append(links.remove(links.firstKey()));
|
||||
}
|
||||
|
||||
printPage(menuPath + menuFileName, menuTemplate.replaceAll("~~~menuName~~~", menuName)
|
||||
.replaceAll("~~~menuEntries~~~", toPrint.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the spells into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Normal, epic and psionics get their own menus
|
||||
*/
|
||||
public static void doSpellMenus() {
|
||||
TreeMap<String, String> normalSpellLinks = new TreeMap<String, String>(),
|
||||
epicSpellLinks = new TreeMap<String, String>(),
|
||||
psionicPowerLinks = new TreeMap<String, String>(),
|
||||
utteranceLinks = new TreeMap<String, String>(),
|
||||
invocationLinks = new TreeMap<String, String>(),
|
||||
maneuverLinks = new TreeMap<String, String>(),
|
||||
modSpellLinks = new TreeMap<String, String>();
|
||||
StringBuffer normalPrint = new StringBuffer(),
|
||||
epicPrint = new StringBuffer(),
|
||||
psionicPrint = new StringBuffer(),
|
||||
utterancePrint = new StringBuffer(),
|
||||
invocationPrint = new StringBuffer(),
|
||||
maneuverPrint = new StringBuffer(),
|
||||
modSpellPrint = new StringBuffer();
|
||||
String temp = null;
|
||||
|
||||
if (verbose) System.out.println("Printing spell menus");
|
||||
|
||||
for (SpellEntry spell : spells.values()) {
|
||||
switch (spell.type) {
|
||||
case NORMAL:
|
||||
normalSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case EPIC:
|
||||
temp = spell.name.startsWith("Epic Spell: ") ? spell.name.substring(12) : spell.name;
|
||||
epicSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", temp));
|
||||
break;
|
||||
case PSIONIC:
|
||||
psionicPowerLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case UTTERANCE:
|
||||
utteranceLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case INVOCATION:
|
||||
invocationLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
case MANEUVER:
|
||||
maneuverLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new AssertionError("Unhandled spelltype: " + spell.type);
|
||||
}
|
||||
|
||||
if (settings.modifiedSpells.contains(spell.entryNum))
|
||||
modSpellLinks.put(spell.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
spell.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", spell.name));
|
||||
}
|
||||
|
||||
while (normalSpellLinks.size() > 0)
|
||||
normalPrint.append(normalSpellLinks.remove(normalSpellLinks.firstKey()));
|
||||
while (epicSpellLinks.size() > 0)
|
||||
epicPrint.append(epicSpellLinks.remove(epicSpellLinks.firstKey()));
|
||||
while (psionicPowerLinks.size() > 0)
|
||||
psionicPrint.append(psionicPowerLinks.remove(psionicPowerLinks.firstKey()));
|
||||
while (utteranceLinks.size() > 0)
|
||||
utterancePrint.append(utteranceLinks.remove(utteranceLinks.firstKey()));
|
||||
while (invocationLinks.size() > 0)
|
||||
invocationPrint.append(invocationLinks.remove(invocationLinks.firstKey()));
|
||||
while (maneuverLinks.size() > 0)
|
||||
maneuverPrint.append(maneuverLinks.remove(maneuverLinks.firstKey()));
|
||||
while (modSpellLinks.size() > 0)
|
||||
modSpellPrint.append(modSpellLinks.remove(modSpellLinks.firstKey()));
|
||||
|
||||
printPage(menuPath + "manual_menus_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_SPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", normalPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_epic_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_EPICSPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", epicPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_psionic_powers.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_PSIONICPOWERSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", psionicPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_truename_utterances.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_TRUENAMEUTTERANCETXT])
|
||||
.replaceAll("~~~menuEntries~~~", utterancePrint.toString()));
|
||||
printPage(menuPath + "manual_menus_invocations.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_INVOCATIONTXT])
|
||||
.replaceAll("~~~menuEntries~~~", invocationPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_maneuvers.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_MANEUVERTXT])
|
||||
.replaceAll("~~~menuEntries~~~", maneuverPrint.toString()));
|
||||
printPage(menuPath + "manual_menus_modified_spells.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_MODIFIEDSPELLSTXT])
|
||||
.replaceAll("~~~menuEntries~~~", modSpellPrint.toString()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the feats into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Normal and epic feats get their own menus and class feats
|
||||
* are skipped.
|
||||
*/
|
||||
public static void doFeatMenus() {
|
||||
TreeMap<String, String> normalFeatLinks = new TreeMap<String, String>(),
|
||||
normalMasterfeatLinks = new TreeMap<String, String>(),
|
||||
epicFeatLinks = new TreeMap<String, String>(),
|
||||
epicMasterfeatLinks = new TreeMap<String, String>();
|
||||
StringBuffer normalList = new StringBuffer(),
|
||||
normalMasterList = new StringBuffer(),
|
||||
epicList = new StringBuffer(),
|
||||
epicMasterList = new StringBuffer();
|
||||
String temp = null;
|
||||
String normalMenu = featMenuTemplate,
|
||||
epicMenu = featMenuTemplate;
|
||||
|
||||
if (verbose) System.out.println("Printing feat menus");
|
||||
|
||||
// Print names
|
||||
normalMenu = normalMenu.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_FEATSTXT]);
|
||||
epicMenu = epicMenu.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_EPICFEATSTXT]);
|
||||
|
||||
// Parse through feats
|
||||
for (FeatEntry feat : feats.values()) {
|
||||
// Skip class feats and feats with masterfeat or a predecessor
|
||||
if (feat.isClassFeat || feat.isSuccessor || feat.master != null) continue;
|
||||
if (!feat.isEpic)
|
||||
normalFeatLinks.put(feat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
feat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", feat.name));
|
||||
else
|
||||
epicFeatLinks.put(feat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
feat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", feat.name));
|
||||
}
|
||||
|
||||
// Transfer the feat link lists into text form
|
||||
while (normalFeatLinks.size() > 0)
|
||||
normalList.append(normalFeatLinks.remove(normalFeatLinks.firstKey()));
|
||||
while (epicFeatLinks.size() > 0)
|
||||
epicList.append(epicFeatLinks.remove(epicFeatLinks.firstKey()));
|
||||
|
||||
// Parse through masterfeats
|
||||
for (FeatEntry masterfeat : masterFeats.values()) {
|
||||
if (masterfeat.isClassFeat && masterfeat.allChildrenClassFeat) continue;
|
||||
if (masterfeat.isEpic)
|
||||
epicMasterfeatLinks.put(masterfeat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
masterfeat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", masterfeat.name));
|
||||
if (!masterfeat.allChildrenEpic)
|
||||
normalMasterfeatLinks.put(masterfeat.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
masterfeat.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", masterfeat.name));
|
||||
}
|
||||
|
||||
// Transfer the masterfeat link lists into text form
|
||||
while (normalMasterfeatLinks.size() > 0)
|
||||
normalMasterList.append(normalMasterfeatLinks.remove(normalMasterfeatLinks.firstKey()));
|
||||
while (epicMasterfeatLinks.size() > 0)
|
||||
epicMasterList.append(epicMasterfeatLinks.remove(epicMasterfeatLinks.firstKey()));
|
||||
|
||||
// Add in a link to the page listing *all* feats
|
||||
normalMenu = normalMenu.replaceAll("~~~allFeatsLink~~~", menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
(contentPath + "feats" + fileSeparator + "alphasortedfeats.html")
|
||||
.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", curLanguageData[LANGDATA_ALLFEATSTXT]));
|
||||
|
||||
// Add in a link to the page listing all epic feats
|
||||
epicMenu = epicMenu.replaceAll("~~~allFeatsLink~~~", menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
(contentPath + "epic_feats" + fileSeparator + "alphasortedepicfeats.html")
|
||||
.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", curLanguageData[LANGDATA_ALLEPICFEATSTXT]));
|
||||
|
||||
// Add in the masterfeat links
|
||||
normalMenu = normalMenu.replaceAll("~~~masterFeats~~~", normalMasterList.toString());
|
||||
epicMenu = epicMenu.replaceAll("~~~masterFeats~~~", epicMasterList.toString());
|
||||
|
||||
// Add in the feat links
|
||||
normalMenu = normalMenu.replaceAll("~~~featLinks~~~", normalList.toString());
|
||||
epicMenu = epicMenu.replaceAll("~~~featLinks~~~", epicList.toString());
|
||||
|
||||
// Print the pages
|
||||
printPage(menuPath + "manual_menus_feat.html", normalMenu);
|
||||
printPage(menuPath + "manual_menus_epic_feat.html", epicMenu);
|
||||
}
|
||||
|
||||
//private static void doFeatMenusAux()
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the classes into alphabetic order using a TreeMap, and prints a menu
|
||||
* page out of the results. Base and prestige classes get their own menus
|
||||
*/
|
||||
public static void doClassMenus() {
|
||||
TreeMap<String, String> baseLinks = new TreeMap<String, String>(),
|
||||
prestigeLinks = new TreeMap<String, String>();
|
||||
StringBuffer basePrint = new StringBuffer(),
|
||||
prestigePrint = new StringBuffer();
|
||||
String temp = null;
|
||||
|
||||
if (verbose) System.out.println("Printing class menus");
|
||||
|
||||
for (ClassEntry clazz : classes.values()) {
|
||||
if (clazz.isBase)
|
||||
baseLinks.put(clazz.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
clazz.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", clazz.name));
|
||||
else
|
||||
prestigeLinks.put(clazz.name, menuItemTemplate.replaceAll("~~~TargetPath~~~",
|
||||
clazz.filePath.replace(mainPath, "../").replaceAll("\\\\", "/"))
|
||||
.replaceAll("~~~targetName~~~", clazz.name));
|
||||
}
|
||||
|
||||
while (baseLinks.size() > 0)
|
||||
basePrint.append(baseLinks.remove(baseLinks.firstKey()));
|
||||
while (prestigeLinks.size() > 0)
|
||||
prestigePrint.append(prestigeLinks.remove(prestigeLinks.firstKey()));
|
||||
|
||||
printPage(menuPath + "manual_menus_base_classes.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_BASECLASSESTXT])
|
||||
.replaceAll("~~~menuEntries~~~", basePrint.toString()));
|
||||
printPage(menuPath + "manual_menus_prestige_classes.html", menuTemplate.replaceAll("~~~menuName~~~", curLanguageData[LANGDATA_PRESTIGECLASSESTXT])
|
||||
.replaceAll("~~~menuEntries~~~", prestigePrint.toString()));
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.class
Normal file
Binary file not shown.
602
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.java
Normal file
602
nwn/nwnprc/DocGen/trunk/prc/autodoc/PageGeneration.java
Normal file
@@ -0,0 +1,602 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.Main.verbose;
|
||||
import static prc.autodoc.Main.*;
|
||||
|
||||
/**
|
||||
* This class contains the methods for manual page generation.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public final class PageGeneration {
|
||||
private PageGeneration() {/* No need for instantiation */}
|
||||
|
||||
/**
|
||||
* Handles printing of the skill pages.
|
||||
*/
|
||||
public static void printSkills() {
|
||||
String text = null;
|
||||
|
||||
for (GenericEntry skill : skills.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + skill.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = skillTemplate;
|
||||
text = text.replaceAll("~~~SkillName~~~", skill.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~SkillTLKDescription~~~",
|
||||
skill.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", skill.iconPath);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(skill.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + skill.entryNum + ": " + skill.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles printing of the crafting property pages.
|
||||
*/
|
||||
public static void printCrafting() {
|
||||
String text = null;
|
||||
|
||||
for (GenericEntry craft_armour_var : craft_armour.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_armour_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_armour_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_armour_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_armour_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_armour_var.entryNum + ": " + craft_armour_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_weapon_var : craft_weapon.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_weapon_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_weapon_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_weapon_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_weapon_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_weapon_var.entryNum + ": " + craft_weapon_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_ring_var : craft_ring.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_ring_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_ring_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_ring_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_ring_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_ring_var.entryNum + ": " + craft_ring_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
for (GenericEntry craft_wondrous_var : craft_wondrous.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + craft_wondrous_var.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = craftTemplate;
|
||||
text = text.replaceAll("~~~CraftPropName~~~", craft_wondrous_var.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~CraftPropTLKDescription~~~",
|
||||
craft_wondrous_var.text);
|
||||
// Print the page
|
||||
try {
|
||||
printPage(craft_wondrous_var.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for skill " + craft_wondrous_var.entryNum + ": " + craft_wondrous_var.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints all spells and spell-likes (psionics, truenaming).
|
||||
* As of now, all of these are similar enough to share the same
|
||||
* template, so they can be done here together.
|
||||
*/
|
||||
public static void printSpells() {
|
||||
String text = null;
|
||||
StringBuilder subradialText = null;
|
||||
|
||||
for (SpellEntry spell : spells.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + spell.name);
|
||||
// Start building the entry data. First, place in the name
|
||||
text = spellTemplate;
|
||||
text = text.replaceAll("~~~SpellName~~~", spell.name);
|
||||
// Then, put in the description
|
||||
text = text.replaceAll("~~~SpellTLKDescription~~~",
|
||||
spell.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", spell.iconPath);
|
||||
|
||||
// Handle subradials, if any
|
||||
subradialText = new StringBuilder();
|
||||
if (spell.subradials != null) {
|
||||
for (Tuple<String, String> subradial : spell.subradials) {
|
||||
subradialText.append(spellSubradialListEntryTemplate.replaceAll("~~~Icon~~~", subradial.e2)
|
||||
.replaceAll("~~~SubradialName~~~", subradial.e1));
|
||||
}
|
||||
subradialText = new StringBuilder(spellSubradialListTemplate.replaceAll("~~~EntryList~~~", subradialText.toString()));
|
||||
}
|
||||
text = text.replaceAll("~~~SubradialNames~~~", subradialText.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(spell.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for spell " + spell.entryNum + ": " + spell.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
// Force a clean-up of dead objects. This will keep discarded objects from slowing down the program as it
|
||||
// hits the memory limit
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple method for printing out all the feat pages.
|
||||
*/
|
||||
public static void printFeats() {
|
||||
// Print feats
|
||||
printFeatsAux();
|
||||
|
||||
// Print masterfeats
|
||||
printMasterFeatsAux();
|
||||
|
||||
// Print a page with alphabetically sorted list of all feats
|
||||
printPage(contentPath + "feats" + fileSeparator + "alphasortedfeats.html", buildAllFeatsList(false));
|
||||
|
||||
// Print a page with alphabetically sorted list of all epic feats
|
||||
printPage(contentPath + "epic_feats" + fileSeparator + "alphasortedepicfeats.html", buildAllFeatsList(true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the masterfeat pages.
|
||||
*/
|
||||
private static void printMasterFeatsAux() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
|
||||
for (FeatEntry masterfeat : masterFeats.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + masterfeat.name);
|
||||
// Build the entry data
|
||||
text = mFeatTemplate;
|
||||
text = text.replaceAll("~~~FeatName~~~",
|
||||
masterfeat.name);
|
||||
text = text.replaceAll("~~~FeatTLKDescription~~~",
|
||||
masterfeat.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", masterfeat.iconPath);
|
||||
|
||||
// Add in child feats
|
||||
temp = "";
|
||||
for (FeatEntry child : masterfeat.childFeats.values()) {
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", child.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", child.name);
|
||||
}
|
||||
text = text.replaceAll("~~~MasterFeatChildList~~~", temp);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(masterfeat.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for masterfeat " + masterfeat.entryNum + ": " + masterfeat.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the feat pages.
|
||||
*/
|
||||
private static void printFeatsAux() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
StringBuilder subradialText = null;
|
||||
|
||||
for (FeatEntry feat : feats.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + feat.name);
|
||||
// Build the entry data
|
||||
text = featTemplate;
|
||||
text = text.replaceAll("~~~FeatName~~~",
|
||||
feat.name);
|
||||
text = text.replaceAll("~~~FeatTLKDescription~~~",
|
||||
feat.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", feat.iconPath);
|
||||
|
||||
// Print prerequisites into the entry
|
||||
temp = "";
|
||||
if (feat.andRequirements.size() != 0) {
|
||||
temp += prereqANDFeatHeaderTemplate;
|
||||
for (FeatEntry andReq : feat.andRequirements.values())
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", andReq.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", andReq.name);
|
||||
}
|
||||
if (feat.orRequirements.size() != 0) {
|
||||
temp += prereqORFeatHeaderTemplate;
|
||||
for (FeatEntry orReq : feat.orRequirements.values())
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", orReq.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", orReq.name);
|
||||
}
|
||||
text = text.replaceAll("~~~PrerequisiteFeatList~~~", temp);
|
||||
|
||||
// Print the successor, if any, into the entry
|
||||
temp = "";
|
||||
if (feat.successor != null) {
|
||||
temp += successorFeatHeaderTemplate + pageLinkTemplate.replace("~~~Path~~~", feat.successor.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.successor.name);
|
||||
}
|
||||
text = text.replaceAll("~~~SuccessorFeat~~~", temp);
|
||||
|
||||
// Handle subradials, if any
|
||||
subradialText = new StringBuilder();
|
||||
if (feat.subradials != null) {
|
||||
for (Tuple<String, String> subradial : feat.subradials) {
|
||||
subradialText.append(spellSubradialListEntryTemplate.replaceAll("~~~Icon~~~", subradial.e2)
|
||||
.replaceAll("~~~SubradialName~~~", subradial.e1));
|
||||
}
|
||||
subradialText = new StringBuilder(spellSubradialListTemplate.replaceAll("~~~EntryList~~~", subradialText.toString()));
|
||||
}
|
||||
text = text.replaceAll("~~~SubradialNames~~~", subradialText.toString());
|
||||
|
||||
// Handle feats that have this as their prerequisite
|
||||
temp = "";
|
||||
if (feat.requiredForFeats.size() != 0) {
|
||||
temp += requiredForFeatHeaderTemplate;
|
||||
for (FeatEntry req : feat.requiredForFeats.values()) {
|
||||
temp += pageLinkTemplate.replace("~~~Path~~~", req.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", req.name);
|
||||
}
|
||||
}
|
||||
text = text.replaceAll("~~~RequiredForFeatList~~~", temp);
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(feat.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for feat " + feat.entryNum + ": " + feat.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an alphabetically sorted list of all (or only all epic) feats.
|
||||
*
|
||||
* @param epicOnly if <code>true</code>, only feats that are epic are placed in the list. Otherwise, all feats.
|
||||
* @return an html page containing the list
|
||||
*/
|
||||
private static String buildAllFeatsList(boolean epicOnly) {
|
||||
TreeMap<String, FeatEntry> sorted = new TreeMap<String, FeatEntry>(String.CASE_INSENSITIVE_ORDER);
|
||||
for (FeatEntry entry : feats.values())
|
||||
if (!epicOnly || (epicOnly && entry.isEpic))
|
||||
sorted.put(entry.name, entry);
|
||||
String toReturn = alphaSortedListTemplate,
|
||||
entrySet;
|
||||
FeatEntry entry;
|
||||
char cha = (char) 0;
|
||||
int counter = 0;
|
||||
boolean addedAny;
|
||||
while (sorted.size() > 0) {
|
||||
// Build the list for a single letter
|
||||
entrySet = listEntrySetTemplate.replace("~~~LinkId~~~", new String(new char[]{cha}))
|
||||
.replace("~~~EntrySetName~~~", new String(new char[]{cha}).toUpperCase());
|
||||
addedAny = false;
|
||||
while (sorted.size() > 0 &&
|
||||
sorted.firstKey().toLowerCase().startsWith(new String(new char[]{cha}))) {
|
||||
addedAny = true;
|
||||
entry = sorted.remove(sorted.firstKey());
|
||||
|
||||
entrySet = entrySet.replace("~~~FeatList~~~", listEntryTemplate.replace("~~~EvenOrOdd~~~", (counter++ % 2) == 0 ? "even" : "odd")
|
||||
.replace("~~~EntryPath~~~",
|
||||
entry.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~EntryName~~~", entry.name)
|
||||
+ "~~~FeatList~~~");
|
||||
}
|
||||
entrySet = entrySet.replace("~~~FeatList~~~", "");
|
||||
cha++;
|
||||
|
||||
// Add the sublist to the page
|
||||
if (addedAny)
|
||||
toReturn = toReturn.replace("~~~Content~~~", entrySet + "\n" + "~~~Content~~~");
|
||||
}
|
||||
// Clear off the last replacement marker
|
||||
toReturn = toReturn.replace("~~~Content~~~", "");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the domain pages.
|
||||
*/
|
||||
public static void printDomains() {
|
||||
String text = null;
|
||||
StringBuffer spellList = null;
|
||||
|
||||
for (DomainEntry domain : domains.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + domain.name);
|
||||
// Build the entry data
|
||||
text = domainTemplate;
|
||||
text = text.replaceAll("~~~DomainName~~~",
|
||||
domain.name);
|
||||
text = text.replaceAll("~~~DomainTLKDescription~~~",
|
||||
domain.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", domain.iconPath);
|
||||
|
||||
// Add a link to the granted feat
|
||||
text = text.replaceAll("~~~DomainFeat~~~",
|
||||
pageLinkTemplate.replace("~~~Path~~~", domain.grantedFeat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", domain.grantedFeat.name));
|
||||
|
||||
// Add links to the granted spells
|
||||
spellList = new StringBuffer();
|
||||
for (SpellEntry grantedSpell : domain.spells) {
|
||||
spellList.append(pageLinkTemplate.replace("~~~Path~~~", grantedSpell.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", grantedSpell.name));
|
||||
}
|
||||
text = text.replaceAll("~~~DomainSpellList~~~", spellList.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(domain.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for domain " + domain.entryNum + ": " + domain.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the race pages.
|
||||
*/
|
||||
public static void printRaces() {
|
||||
String text = null;
|
||||
StringBuffer featList = null;
|
||||
|
||||
for (RaceEntry race : races.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + race.name);
|
||||
// Build the entry data
|
||||
text = raceTemplate;
|
||||
text = text.replaceAll("~~~RaceName~~~",
|
||||
race.name);
|
||||
text = text.replaceAll("~~~RaceTLKDescription~~~",
|
||||
race.text);
|
||||
|
||||
// Add links to the racial feats
|
||||
featList = new StringBuffer();
|
||||
for (FeatEntry grantedFeat : race.raceFeats.values()) {
|
||||
featList.append(pageLinkTemplate.replace("~~~Path~~~", grantedFeat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", grantedFeat.name));
|
||||
}
|
||||
text = text.replaceAll("~~~RaceFeats~~~", featList.toString());
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(race.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for race " + race.entryNum + ": " + race.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles creation of the class pages.
|
||||
* Subsections handled by several following methods.
|
||||
*/
|
||||
public static void printClasses() {
|
||||
String text = null,
|
||||
temp = null;
|
||||
String[] tempArr = null;
|
||||
|
||||
for (ClassEntry class_ : classes.values()) {
|
||||
if (verbose) System.out.println("Printing page for " + class_.name);
|
||||
// Build the entry data
|
||||
text = classTemplate;
|
||||
text = text.replaceAll("~~~ClassName~~~",
|
||||
class_.name);
|
||||
text = text.replaceAll("~~~ClassTLKDescription~~~",
|
||||
class_.text);
|
||||
// Add in the icon
|
||||
text = text.replaceAll("~~~Icon~~~", class_.iconPath);
|
||||
|
||||
// Add in the BAB and saving throws table
|
||||
text = text.replaceAll("~~~ClassBABAndSavThrTable~~~", buildBabAndSaveTable(class_));
|
||||
|
||||
// Add in the skills table
|
||||
text = text.replaceAll("~~~ClassSkillTable~~~", buildSkillTable(class_));
|
||||
|
||||
// Add in the feat table
|
||||
text = text.replaceAll("~~~ClassFeatTable~~~", buildClassFeatTables(class_));
|
||||
|
||||
// Add in the spells / powers table
|
||||
text = text.replaceAll("~~~ClassSpellAndPowerTables~~~", buildClassSpellAndPowerTables(class_));
|
||||
|
||||
|
||||
// Print the page
|
||||
try {
|
||||
printPage(class_.filePath, text);
|
||||
} catch (PageGenerationException e) {
|
||||
err_pr.println("Error: Exception when writing page for class " + class_.entryNum + ": " + class_.name + ":\n" + e);
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the html table of levels and their bab + saving throw bonus values.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return string representation of the table
|
||||
*/
|
||||
private static String buildBabAndSaveTable(ClassEntry class_) {
|
||||
String toReturn = "";
|
||||
if (class_.babSav.size() != 0) {
|
||||
toReturn += babAndSavthrTableHeaderTemplate + "\n";
|
||||
// Start building the table
|
||||
for (int i = 0; i < class_.babSav.size(); i++) {
|
||||
toReturn += "<tr>\n";
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", (i + 1) + "");
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[0]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[1]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[2]);
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", class_.babSav.get(i)[3]);
|
||||
toReturn += "</tr>\n";
|
||||
}
|
||||
toReturn += "</table>\n";
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the html table of the class & cross-class skills of this class.
|
||||
* TreeMaps are used to arrange the printed skills in alphabetic order.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return string representation of the table
|
||||
*/
|
||||
private static String buildSkillTable(ClassEntry class_) {
|
||||
String toReturn = skillTableHeaderTemplate;
|
||||
GenericEntry tempSkill = null;
|
||||
// Clone the maps, since we'll be performing destructive operations on them
|
||||
TreeMap<String, GenericEntry> classSkills = new TreeMap<String, GenericEntry>(class_.skillList.e1),
|
||||
crossClassSkills = new TreeMap<String, GenericEntry>(class_.skillList.e2);
|
||||
|
||||
while (classSkills.size() > 0 || crossClassSkills.size() > 0) {
|
||||
toReturn += "<tr>\n";
|
||||
|
||||
if (classSkills.size() > 0) {
|
||||
tempSkill = classSkills.remove(classSkills.firstKey());
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", "<a href=\"" + tempSkill.filePath.replace(contentPath, "../").replaceAll("\\\\", "/") + "\" target=\"content\">" + tempSkill.name + "</a>");
|
||||
} else
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", " ");
|
||||
|
||||
if (crossClassSkills.size() > 0) {
|
||||
tempSkill = crossClassSkills.remove(crossClassSkills.firstKey());
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", "<a href=\"" + tempSkill.filePath.replace(contentPath, "../").replaceAll("\\\\", "/") + "\" target=\"content\">" + tempSkill.name + "</a>");
|
||||
} else
|
||||
toReturn += classTablesEntryTemplate.replaceAll("~~~Entry~~~", " ");
|
||||
|
||||
toReturn += "</tr>\n";
|
||||
}
|
||||
|
||||
toReturn += "</table>\n";
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the html table of the bonus and selectable class feats of the given class.
|
||||
* TreeMaps are used to arrange the printed feats in alphabetic order.
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return String that contains the table
|
||||
*/
|
||||
private static String buildClassFeatTables(ClassEntry class_) {
|
||||
List<TreeMap<String, FeatEntry>> grantedFeatList = class_.featList.e2.e1,
|
||||
selectableFeatList = class_.featList.e2.e2;
|
||||
List<Integer> bonusFeatCounts = class_.featList.e1;
|
||||
|
||||
// Start constructing the table
|
||||
StringBuffer tableText = new StringBuffer();
|
||||
StringBuffer linkList = null;
|
||||
String tableLine = null;
|
||||
for (int i = 0; i < grantedFeatList.size(); i++) {
|
||||
tableLine = classFeatTableEntryTemplate.replace("~~~Level~~~", String.valueOf(i + 1))
|
||||
.replace("~~~NumberOfBonusFeats~~~", bonusFeatCounts.get(i).toString());
|
||||
// Generate the granted feats list
|
||||
linkList = new StringBuffer();
|
||||
if (grantedFeatList.get(i) != null)
|
||||
for (FeatEntry feat : grantedFeatList.get(i).values()) {
|
||||
linkList.append(pageLinkTemplate.replace("~~~Path~~~", feat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.name));
|
||||
}
|
||||
else
|
||||
linkList.append(" ");
|
||||
tableLine = tableLine.replace("~~~FeatsGrantedList~~~", linkList.toString());
|
||||
|
||||
// Generate the granted feats list
|
||||
linkList = new StringBuffer();
|
||||
if (selectableFeatList.get(i) != null)
|
||||
for (FeatEntry feat : selectableFeatList.get(i).values()) {
|
||||
linkList.append(pageLinkTemplate.replace("~~~Path~~~", feat.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", feat.name));
|
||||
}
|
||||
else
|
||||
linkList.append(" ");
|
||||
tableLine = tableLine.replace("~~~SelectableFeatsList~~~", linkList.toString());
|
||||
|
||||
// Append the line to the table
|
||||
tableText.append(tableLine);
|
||||
}
|
||||
|
||||
return classFeatTableTemplate.replace("~~~TableContents~~~", tableText.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the html table of the new spellbook spells and psionic powers lists of
|
||||
* the given class. The entries are ordered by spell / power level
|
||||
*
|
||||
* @param class_ The class entry data structure of the class to generate the table for
|
||||
* @return String that contains the table
|
||||
*/
|
||||
private static String buildClassSpellAndPowerTables(ClassEntry class_) {
|
||||
StringBuffer toReturn = new StringBuffer();
|
||||
|
||||
for (Tuple<Tuple<String, String>, TreeMap<Integer, TreeMap<String, SpellEntry>>> magicData : class_.magics) {
|
||||
// Map of level numbers to maps of spell names to html links. Cloned due to destructive operations
|
||||
TreeMap<Integer, TreeMap<String, SpellEntry>> levelLists =
|
||||
new TreeMap<Integer, TreeMap<String, SpellEntry>>(magicData.e2);
|
||||
|
||||
StringBuffer tableLines = new StringBuffer(),
|
||||
spellLinks;
|
||||
String tableLine;
|
||||
while (levelLists.size() > 0) {
|
||||
tableLine = classMagicTableEntryTemplate.replace("~~~Level~~~", levelLists.firstKey().toString());
|
||||
spellLinks = new StringBuffer();
|
||||
for (SpellEntry spell : levelLists.remove(levelLists.firstKey()).values())
|
||||
spellLinks.append(pageLinkTemplate.replace("~~~Path~~~", spell.filePath.replace(contentPath, "../").replaceAll("\\\\", "/"))
|
||||
.replace("~~~Name~~~", spell.name));
|
||||
tableLines.append(tableLine.replace("~~~EntryList~~~", spellLinks.toString()));
|
||||
}
|
||||
|
||||
toReturn.append(classMagicTableTemplate.replace("~~~TableName~~~", magicData.e1.e1)
|
||||
.replace("~~~Type~~~", magicData.e1.e2)
|
||||
.replace("~~~TableContents~~~", tableLines.toString()));
|
||||
}
|
||||
|
||||
return toReturn.toString();
|
||||
}
|
||||
}
|
Binary file not shown.
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating failure while generating a page.
|
||||
*/
|
||||
public class PageGenerationException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x2L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public PageGenerationException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public PageGenerationException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.class
Normal file
Binary file not shown.
29
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.java
Normal file
29
nwn/nwnprc/DocGen/trunk/prc/autodoc/RaceEntry.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Data structure for a race entry.
|
||||
*/
|
||||
public class RaceEntry extends GenericEntry {
|
||||
|
||||
/**
|
||||
* A list of masterfeat's children
|
||||
*/
|
||||
public final TreeMap<String, FeatEntry> raceFeats;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the race
|
||||
* @param text Description of the race
|
||||
* @param filePath Path where the html page for this race will be written to
|
||||
* @param entryNum racialtypes.2da index
|
||||
* @param raceFeats Racial feat list
|
||||
*/
|
||||
public RaceEntry(String name, String text, String filePath,
|
||||
int entryNum, TreeMap<String, FeatEntry> raceFeats) {
|
||||
super(name, text, null, filePath, entryNum);
|
||||
this.raceFeats = raceFeats;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.class
Normal file
Binary file not shown.
38
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.java
Normal file
38
nwn/nwnprc/DocGen/trunk/prc/autodoc/SpellEntry.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import prc.autodoc.Main.SpellType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data structure for a spell entry.
|
||||
*/
|
||||
public class SpellEntry extends GenericEntry {
|
||||
/**
|
||||
* Type of this spell entry
|
||||
*/
|
||||
public final SpellType type;
|
||||
|
||||
/**
|
||||
* The spell's subradials, if any. List of spell name, icon path tuples.
|
||||
*/
|
||||
public final List<Tuple<String, String>> subradials;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param name Name of the spell
|
||||
* @param text Description of the spell
|
||||
* @param iconPath Path of the spell's icon
|
||||
* @param filePath Path of the html file describing the spell.
|
||||
* @param entryNum spells.2da index
|
||||
* @param type Type of the spell: Normal / Epic / Psionic / whatever
|
||||
* @param subradials
|
||||
*/
|
||||
public SpellEntry(String name, String text, String iconPath, String filePath,
|
||||
int entryNum, SpellType type, List<Tuple<String, String>> subradials) {
|
||||
super(name, text, iconPath, filePath, entryNum);
|
||||
this.type = type;
|
||||
this.subradials = subradials;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.class
Normal file
Binary file not shown.
34
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.java
Normal file
34
nwn/nwnprc/DocGen/trunk/prc/autodoc/Spinner.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package prc.autodoc;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An absolutely critical part of the Document Creator, not. Prints a spinning line
|
||||
* for the user to look at while the program is working.
|
||||
*/
|
||||
public final class Spinner {
|
||||
private final char[] states = new char[]{'|', '/', '-', '\\'};
|
||||
private int curState = 0;
|
||||
private boolean active = true;
|
||||
private Date lastSpinTime = new Date();
|
||||
|
||||
|
||||
/**
|
||||
* Spins the spinner.
|
||||
*/
|
||||
public void spin() {
|
||||
long minTimeBetweenSpinsInMS = 300;
|
||||
if (active && new Date().getTime() - lastSpinTime.getTime() > minTimeBetweenSpinsInMS) {
|
||||
System.out.print(states[curState = ++curState % states.length] + "\u0008");
|
||||
lastSpinTime = new Date();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns the spinner off.
|
||||
*/
|
||||
public void disable() {
|
||||
active = false;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.class
Normal file
Binary file not shown.
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.java
Normal file
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TLKReadException.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating TLK read failed.
|
||||
*/
|
||||
public class TLKReadException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x0L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public TLKReadException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public TLKReadException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.class
Normal file
Binary file not shown.
30
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.java
Normal file
30
nwn/nwnprc/DocGen/trunk/prc/autodoc/Tuple.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* A simple tuple class
|
||||
*
|
||||
* @param <T1> The type of the first element of the tuple
|
||||
* @param <T2> The type of the second element of the tuple
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Tuple<T1, T2> {
|
||||
/**
|
||||
* The first element
|
||||
*/
|
||||
public final T1 e1;
|
||||
/**
|
||||
* The second element
|
||||
*/
|
||||
public final T2 e2;
|
||||
|
||||
/**
|
||||
* Generates a new tuple out of the given two objects.
|
||||
*
|
||||
* @param e1 The object to become the first element of the new tuple
|
||||
* @param e2 The object to become the second element of the new tuple
|
||||
*/
|
||||
public Tuple(T1 e1, T2 e2) {
|
||||
this.e1 = e1;
|
||||
this.e2 = e2;
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.class
Normal file
Binary file not shown.
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.java
Normal file
23
nwn/nwnprc/DocGen/trunk/prc/autodoc/TwoDAReadException.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package prc.autodoc;
|
||||
|
||||
/**
|
||||
* An exception indicating 2da read failed.
|
||||
*/
|
||||
public class TwoDAReadException extends java.lang.RuntimeException{
|
||||
private static final long serialVersionUID = 0x1L;
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
*/
|
||||
public TwoDAReadException(String message) { super(message); }
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* @param message The message this exception is to carry
|
||||
* @param cause Another exception that caused this one to be thrown
|
||||
*/
|
||||
public TwoDAReadException(String message, Throwable cause){ super(message, cause); }
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/Main$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/Main$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/Main.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/Main.class
Normal file
Binary file not shown.
222
nwn/nwnprc/DocGen/trunk/prc/makedep/Main.java
Normal file
222
nwn/nwnprc/DocGen/trunk/prc/makedep/Main.java
Normal file
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* A system for calculating nwscript dependencies. Makes some assumptions specific
|
||||
* to the PRC setup.
|
||||
*/
|
||||
package prc.makedep;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import static prc.Main.*;
|
||||
|
||||
|
||||
/**
|
||||
* Calculates nwscript dependencies.
|
||||
*
|
||||
* Usage: makedep [-aio?] targetlist
|
||||
* Options:
|
||||
* -a Append to outputfile. This option must be defined before -o
|
||||
* -n Ignore include file if not found
|
||||
* -sPATH[,PATH...] List of source directories
|
||||
* -oFILE Use FILE as outputfile, stdout assumed
|
||||
* -?, --help This text
|
||||
*
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
static Map<String, NSSNode> scripts = new LinkedHashMap<String, NSSNode>();
|
||||
|
||||
protected static boolean append = false,
|
||||
ignoreMissing = false,
|
||||
error = false;
|
||||
static PrintStream oStrm = System.out;
|
||||
|
||||
/**
|
||||
* Main method. Entrypoint to the program
|
||||
*
|
||||
* @param args The arguments. See readMe() for accepted ones
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
HashMap<String, String> targetList = new LinkedHashMap<String, String>();
|
||||
List<String> targetListFileNames = new ArrayList<String>();
|
||||
boolean targetsFromStdin = false;
|
||||
|
||||
// Parse arguments
|
||||
for(int i = 0; i < args.length; i++) {//[-aio?] targetslist+
|
||||
// Parameter parseage
|
||||
String param = args[i];
|
||||
if(param.startsWith("-")) {
|
||||
if(param.startsWith("-s")) {
|
||||
getFiles(param.substring(2));
|
||||
}
|
||||
else if(param.startsWith("-o")) {
|
||||
setOutput(param.substring(2));
|
||||
}
|
||||
else {
|
||||
if(param.equals("--help")) readMe();
|
||||
else if(param.equals("-")) {
|
||||
targetsFromStdin = true;
|
||||
}
|
||||
else {
|
||||
for(char c : param.substring(1).toCharArray()){
|
||||
switch(c) {
|
||||
case 'a':
|
||||
append = true;
|
||||
break;
|
||||
case 'n':
|
||||
ignoreMissing = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
case '?':
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// It's a targets list file
|
||||
targetListFileNames.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
// Read targets from stdin if so specified
|
||||
Scanner scan;
|
||||
String targetName;
|
||||
if(targetsFromStdin) {
|
||||
scan = new Scanner(System.in);
|
||||
while(scan.hasNextLine()) {
|
||||
targetName = scan.nextLine().toLowerCase();
|
||||
// Strip everything after the .ncs from the line
|
||||
targetName = targetName.substring(0, targetName.indexOf(".ncs") + 4);
|
||||
targetList.put(NSSNode.getScriptName(targetName), targetName);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the target file list
|
||||
File targetListFile;
|
||||
for(String fileName : targetListFileNames) {
|
||||
targetListFile = new File(fileName);
|
||||
// Read the contents
|
||||
try {
|
||||
scan = new Scanner(targetListFile);
|
||||
} catch (FileNotFoundException e) {
|
||||
err_pr.println("Error: Could not find file: " + fileName);
|
||||
error = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
while(scan.hasNextLine()) {
|
||||
targetName = scan.nextLine().toLowerCase();
|
||||
// Strip everything after the .ncs from the line
|
||||
targetName = targetName.substring(0, targetName.indexOf(".ncs") + 4);
|
||||
targetList.put(NSSNode.getScriptName(targetName), targetName);
|
||||
}
|
||||
}
|
||||
|
||||
// Input sanity checks
|
||||
if(targetList.size() == 0) {
|
||||
err_pr.println("Error: No targets specified.");
|
||||
error = true;
|
||||
}
|
||||
for(String target : targetList.keySet()) {
|
||||
if(scripts.get(target.toLowerCase()) == null) {
|
||||
err_pr.println("Error: Script file for target " + target + " not found in given source directories.");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate if errored
|
||||
if(error) System.exit(1);
|
||||
|
||||
// TODO: Load the files concurrently. I suspect it will give a slight performance boost
|
||||
//NSSNode[] debugArr = debugMap.values().toArray(new NSSNode[0]);
|
||||
for(NSSNode script: scripts.values())
|
||||
script.linkDirect();
|
||||
|
||||
// Check for errors again
|
||||
if(error) System.exit(1);
|
||||
|
||||
|
||||
// Start a depth-first-search to find all the include trees
|
||||
for(NSSNode node : scripts.values()){
|
||||
node.linkFullyAndGetIncludes(null);
|
||||
//node.printSelf(oStrm, append);
|
||||
}
|
||||
|
||||
// Do the printing
|
||||
for(String target : targetList.keySet()) {
|
||||
scripts.get(target.toLowerCase()).printSelf(oStrm, append, targetList.get(target));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints usage and terminates.
|
||||
*/
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage: makedep [-aio?] targetslist+\n" +
|
||||
"Options:\n" +
|
||||
"-a Append to outputfile. This option must be defined before -o\n"+
|
||||
"-n Ignore include file if not found\n"+
|
||||
"-sPATH[,PATH...] List of source directories\n"+
|
||||
"-oFILE Use FILE as outputfile, stdout assumed\n" +
|
||||
"- Read targets from stdin. Same format as targets list files\n"+
|
||||
"-?, --help This text\n"+
|
||||
"\n"+
|
||||
"targetslist Name of a file containing a list of object (.ncs) files to\n"+
|
||||
" generate a make targets for.\n" +
|
||||
" File format is one path-to-target per line."
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks in the directories specified by the given list for .nss
|
||||
* files and adds them to the sources list.
|
||||
*
|
||||
* @param pathList comma-separated list of directories to look in
|
||||
*/
|
||||
private static void getFiles(String pathList){
|
||||
String[] paths = pathList.split(",");
|
||||
File[] files;
|
||||
String temp;
|
||||
for(String path : paths){
|
||||
files = new File(path).listFiles(new FileFilter(){
|
||||
public boolean accept(File file){
|
||||
return file.getName().endsWith(".nss");
|
||||
}
|
||||
});
|
||||
for(File file: files){
|
||||
temp = NSSNode.getScriptName(file.getName()).toLowerCase();
|
||||
if(!scripts.containsKey(temp))
|
||||
scripts.put(temp, new NSSNode(file.getPath()));
|
||||
else{
|
||||
err_pr.println("Error: Duplicate script file: " + temp);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output to write the results to to a file specified by the
|
||||
* given filename.
|
||||
* If the file is not found, the program terminates.
|
||||
*
|
||||
* @param outFileName Name of the file to print results to
|
||||
*/
|
||||
private static void setOutput(String outFileName){
|
||||
try{
|
||||
oStrm = new PrintStream(new FileOutputStream(outFileName, append), true);
|
||||
}catch(FileNotFoundException e){
|
||||
err_pr.println("Error: Missing output file " + outFileName + "\nTerminating!");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker$Node.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker$Node.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker.class
Normal file
Binary file not shown.
89
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker.java
Normal file
89
nwn/nwnprc/DocGen/trunk/prc/makedep/MakedepChecker.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package prc.makedep;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class MakedepChecker {
|
||||
private static class Node{
|
||||
private HashSet<String> deps = new HashSet<String>();
|
||||
private String full;
|
||||
|
||||
public Node(String full, String sdeps) {
|
||||
this.full = full;
|
||||
String[] sdepsar = sdeps.split(" ");
|
||||
for(String s : sdepsar)
|
||||
if(!s.equals(""))
|
||||
deps.add(s);
|
||||
}
|
||||
|
||||
public void compare(Node another){
|
||||
if(!(this.deps.containsAll(another.deps) && another.deps.containsAll(this.deps))){
|
||||
System.out.println("Differing lines:\n " + this.full + "\n " + another.full);
|
||||
if(!this.deps.containsAll(another.deps)){
|
||||
System.out.println(" Missing in olds:");
|
||||
HashSet<String> temp = another.deps;
|
||||
temp.removeAll(this.deps);
|
||||
for(String s : temp)
|
||||
System.out.println(" " + s);
|
||||
}
|
||||
if(!another.deps.containsAll(this.deps)){
|
||||
System.out.println(" Missing in news:");
|
||||
HashSet<String> temp = this.deps;
|
||||
temp.removeAll(another.deps);
|
||||
for(String s : temp)
|
||||
System.out.println(" " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Throwable{
|
||||
// Load old and new lists
|
||||
File odf = new File("oldmakedep.txt");
|
||||
File ndf = new File("newmakedep.txt");
|
||||
|
||||
HashMap<String, Node> olds = new HashMap<String, Node>();
|
||||
HashMap<String, Node> news = new HashMap<String, Node>();
|
||||
|
||||
Scanner scan = new Scanner(odf);
|
||||
while(scan.hasNextLine()){
|
||||
String s = scan.nextLine();
|
||||
if(s.equals(""))
|
||||
continue;
|
||||
String[] ss = s.split(":");
|
||||
olds.put(ss[0], new Node(s, ss[1]));
|
||||
}
|
||||
scan = new Scanner(ndf);
|
||||
while(scan.hasNextLine()){
|
||||
String s = scan.nextLine();
|
||||
if(s.equals(""))
|
||||
continue;
|
||||
String[] ss = s.split(":");
|
||||
news.put(ss[0], new Node(s, ss[1]));
|
||||
}
|
||||
|
||||
if(!(olds.keySet().containsAll(news.keySet()) &&
|
||||
news.keySet().containsAll(olds.keySet())
|
||||
)){
|
||||
System.out.println("Differing line counts!");
|
||||
|
||||
Set<String> foo = olds.keySet();
|
||||
foo.removeAll(news.keySet());
|
||||
System.out.println("Files not defined in news:");
|
||||
for(String s : foo)
|
||||
System.out.println(s);
|
||||
|
||||
|
||||
foo = news.keySet();
|
||||
foo.removeAll(olds.keySet());
|
||||
System.out.println("Files not defined in olds:");
|
||||
for(String s : foo)
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
for(String key : olds.keySet()){
|
||||
olds.get(key).compare(news.get(key));
|
||||
}
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode$STATES.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode$STATES.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode.class
Normal file
Binary file not shown.
259
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode.java
Normal file
259
nwn/nwnprc/DocGen/trunk/prc/makedep/NSSNode.java
Normal file
@@ -0,0 +1,259 @@
|
||||
package prc.makedep;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static prc.Main.*;
|
||||
|
||||
/**
|
||||
* A node in an NWScript include tree.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class NSSNode {
|
||||
private static enum STATES{
|
||||
/**
|
||||
* This node has not been visited yet in the full linking phase.
|
||||
*/
|
||||
UNSTARTED,
|
||||
/**
|
||||
* The depth-first-search has reached this node, but has not returned to it yet.
|
||||
*/
|
||||
WORKING,
|
||||
/**
|
||||
* All the includes for this node have been resolved.
|
||||
*/
|
||||
DONE};
|
||||
|
||||
private STATES state = STATES.UNSTARTED;
|
||||
|
||||
/**
|
||||
* While the node is in WORKING state, it's includes have not been resolved yet.
|
||||
* So, if a circular include is found, it is added here so that this node's includes
|
||||
* can be added to it's list once the DFS returns to this node.
|
||||
*/
|
||||
private HashSet<NSSNode> mergeLater = new HashSet<NSSNode>();
|
||||
|
||||
/**
|
||||
* A container for marking files that are already being handled during a merging cascade.
|
||||
*/
|
||||
private static HashSet<NSSNode> inMerge;
|
||||
|
||||
/**
|
||||
* The nodes included directly by this node via #include statements.
|
||||
*/
|
||||
private HashSet<NSSNode> adjenct = new LinkedHashSet<NSSNode>();
|
||||
|
||||
/**
|
||||
* The nodes included by this node either directly or via intermediary steps. Also,
|
||||
* each file is considered to include itself in order to make printing include lists
|
||||
* a bit less complex.
|
||||
*/
|
||||
private HashSet<NSSNode> includes = new LinkedHashSet<NSSNode>();
|
||||
|
||||
/**
|
||||
* The first node to call linkFullyAndGetIncludes() on this node.
|
||||
*/
|
||||
public NSSNode priCaller;
|
||||
|
||||
/**
|
||||
* The path used to reference this file.
|
||||
*/
|
||||
public String fileName;
|
||||
|
||||
/**
|
||||
* Creates a new, unlinked NSSNode
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
public NSSNode(String fileName) {
|
||||
fileName = fileName.toLowerCase();
|
||||
// Make sure the file exists
|
||||
if(!new File(fileName).exists()){
|
||||
Main.error = true;
|
||||
err_pr.println("Error: Missing script file: " + fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Each node is dependent on itself
|
||||
includes.add(this);
|
||||
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link this script file to those files it directly includes.
|
||||
*/
|
||||
public void linkDirect(){
|
||||
// Load the text for this file
|
||||
File file = new File(fileName);
|
||||
char[] cArray = new char[(int)file.length()];
|
||||
try{
|
||||
FileReader fr = new FileReader(fileName);
|
||||
fr.read(cArray);
|
||||
fr.close();
|
||||
}catch(Exception e){
|
||||
err_pr.println("Error: Error while reading file: " + fileName);
|
||||
Main.error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Debuggage
|
||||
if(fileName.indexOf("psi_inc_psifunc") != -1)
|
||||
System.currentTimeMillis();
|
||||
//*/
|
||||
|
||||
|
||||
String[] directIncludes = NWScript.findIncludes(new String(cArray));
|
||||
|
||||
for(String name : directIncludes){
|
||||
name = name.toLowerCase();
|
||||
NSSNode adj = Main.scripts.get(name);
|
||||
if(adj != null){
|
||||
if(adjenct.contains(adj))
|
||||
//System.out.println("Warning: " + getScriptName(fileName) + " includes " + getScriptName(adj.fileName) + " multiple times");
|
||||
System.out.printf("Warning: %-16s includes %-16s multiple times\n",
|
||||
getScriptName(fileName),
|
||||
getScriptName(adj.fileName)
|
||||
);
|
||||
adjenct.add(adj);
|
||||
}else if(!Main.ignoreMissing){
|
||||
System.out.println("Script file not found: " + name);
|
||||
Main.error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the full list of files included by this script.
|
||||
*
|
||||
* @param caller the node calling this function recursively passes a reference
|
||||
* to itself. Used in cases where the target node was already in
|
||||
* WORKING state.
|
||||
* @return HashSet containing the fully resolved list of files included by this one
|
||||
*/
|
||||
public HashSet<NSSNode> linkFullyAndGetIncludes(NSSNode caller) {
|
||||
if(state != STATES.UNSTARTED)
|
||||
if(state == STATES.DONE)
|
||||
return includes;
|
||||
else{
|
||||
// Add to a list to merge include lists later once this node is done
|
||||
NSSNode toMergeLater = caller;
|
||||
while(toMergeLater != this){
|
||||
mergeLater.add(toMergeLater);
|
||||
toMergeLater = toMergeLater.priCaller;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/* Debuggage stuff
|
||||
if(//fileName.indexOf("ss_ep_psionicsal") != -1 ||
|
||||
//fileName.indexOf("psi_inc_psifunc") != -1 ||
|
||||
//fileName.indexOf("prc_alterations") != -1 ||
|
||||
//fileName.indexOf("bonsum_shapelem") != -1 ||
|
||||
fileName.indexOf("pnp_shft_poly") != -1 ||
|
||||
false
|
||||
)
|
||||
System.currentTimeMillis();
|
||||
//*/
|
||||
// Mark the node as work-in-progress, so it won't be handled again
|
||||
state = STATES.WORKING;
|
||||
priCaller = caller;
|
||||
// Initialize the includes list for this script with the direct includes
|
||||
includes.addAll(adjenct);
|
||||
|
||||
HashSet<NSSNode> temp;
|
||||
for(NSSNode adj : adjenct){
|
||||
temp = adj.linkFullyAndGetIncludes(this);
|
||||
if(temp != null)
|
||||
includes.addAll(temp);
|
||||
}
|
||||
|
||||
// Do the delayed include list merges
|
||||
inMerge = new HashSet<NSSNode>();
|
||||
this.doMerge();
|
||||
/*for(NSSNode node : mergeLater)
|
||||
node.includes.addAll(this.includes);*/
|
||||
inMerge = null;
|
||||
|
||||
state = STATES.DONE;
|
||||
return includes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the include list of this file with all files that included this one while
|
||||
* it was still being worked on. Recurses to each of these files in order to update
|
||||
* files dependent on them.
|
||||
*/
|
||||
private void doMerge(){
|
||||
for(NSSNode node : mergeLater){
|
||||
if(!inMerge.contains(node)){
|
||||
inMerge.add(node);
|
||||
node.includes.addAll(this.includes);
|
||||
node.doMerge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name used in include statements for the given filename.
|
||||
*
|
||||
* @param path the path to parse
|
||||
* @return string, name used in include statements
|
||||
*/
|
||||
public static String getScriptName(String path) {
|
||||
// Cut out the .nss or .ncs
|
||||
try{
|
||||
path = path.substring(0, path.indexOf(".nss") != -1 ? path.indexOf(".nss") : path.indexOf(".ncs"));
|
||||
}catch(Exception e){
|
||||
err_pr.println(path);
|
||||
}
|
||||
|
||||
// Cut out the directories, if present
|
||||
if(path.indexOf(File.separator) != -1)
|
||||
path = path.substring(path.lastIndexOf(File.separator) + 1, path.length());
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints this node's list of includes to a stream.
|
||||
*
|
||||
* @param strm stream to print to
|
||||
* @param append if this is <code>true</code>, the PrintStream's <code>append</code> methods
|
||||
* are used instead of <code>print</code> methods.
|
||||
* @param target name of the object file to be built from this script
|
||||
*/
|
||||
public void printSelf(PrintStream strm, boolean append, String target) {
|
||||
String lineSeparator = System.getProperty("line.separator");
|
||||
if(append){
|
||||
//strm.append(fileName.replace(".nss", ".ncs") + ":"/* + fileName*/);
|
||||
strm.append(target + ":");
|
||||
for(NSSNode include : includes)
|
||||
strm.append(" " + include.fileName);
|
||||
strm.append(lineSeparator + lineSeparator);
|
||||
}else{
|
||||
strm.print(target + ":");
|
||||
for(NSSNode include : includes)
|
||||
strm.print(" " + include.fileName);
|
||||
strm.print(lineSeparator + lineSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A test main.
|
||||
*
|
||||
* @param args Ye olde parameters. Doesn't accept any
|
||||
*/
|
||||
public static void main(String[] args){
|
||||
System.out.println(getScriptName("C:\\foo\\bar\\meh.nss"));
|
||||
System.out.println(getScriptName("boo.nss"));
|
||||
System.out.println(getScriptName("lar\\floob.nss"));
|
||||
}
|
||||
|
||||
/**
|
||||
* An NSSNode's string representation is it's filename.
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString(){return fileName;}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript$STATES.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript$STATES.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript.class
Normal file
Binary file not shown.
144
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript.java
Normal file
144
nwn/nwnprc/DocGen/trunk/prc/makedep/NWScript.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package prc.makedep;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
|
||||
/**
|
||||
* A class for parsing NWScript files.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class NWScript {
|
||||
private static enum STATES{
|
||||
/**
|
||||
* Normal code, can switch to the other modes from here.
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* String mode. Exited by an unescaped " (technically should be ended
|
||||
* by a new line as well, but we assume the code is not that badly fubar'd).
|
||||
*/
|
||||
STRING,
|
||||
/**
|
||||
* Singe line comment, started by //. Exited by a newline.
|
||||
*/
|
||||
SCOMMENT,
|
||||
/**
|
||||
* Multi-line comment.
|
||||
*/
|
||||
MCOMMENT
|
||||
};
|
||||
|
||||
private static Matcher matcher = Pattern.compile("#include[ \t\u000B\f\r]*\"(.*)\"").matcher("");
|
||||
|
||||
|
||||
/**
|
||||
* Parses the given source text for #include directives and returns the names of
|
||||
* the files included.
|
||||
*
|
||||
* @param srcText contents of a nwscript source file
|
||||
* @return array of String containing the names of files included by this one
|
||||
*/
|
||||
public static String[] findIncludes(CharSequence srcText){
|
||||
StringBuffer wip = new StringBuffer(srcText);
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
|
||||
removeComments(wip);
|
||||
|
||||
// Parse for remaining #include statements
|
||||
//#include[ \t\x0B\f\r]*"(.*)"
|
||||
matcher.reset(wip);
|
||||
//String debug;
|
||||
while(matcher.find()){
|
||||
//debug = matcher.group(1);
|
||||
//list.add(debug);
|
||||
list.add(matcher.group(1));
|
||||
}
|
||||
|
||||
|
||||
return list.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the contents of comments with spaces.
|
||||
*
|
||||
* @param sbuf Stringbuffer containing nwscript to strip comments from
|
||||
*/
|
||||
private static void removeComments(StringBuffer sbuf){
|
||||
STATES state = STATES.NORMAL;
|
||||
char prev = '\u0000', cur;
|
||||
boolean evenBSlash = true;
|
||||
|
||||
for(int i = 0; i < sbuf.length(); i++){
|
||||
cur = sbuf.charAt(i);
|
||||
switch(state){
|
||||
case NORMAL:
|
||||
if(prev == '/'){
|
||||
if(cur == '/'){
|
||||
state = STATES.SCOMMENT;
|
||||
sbuf.setCharAt(i - 1, ' ');
|
||||
sbuf.setCharAt(i, ' ');
|
||||
}
|
||||
else if(cur == '*'){
|
||||
state = STATES.MCOMMENT;
|
||||
sbuf.setCharAt(i - 1, ' ');
|
||||
sbuf.setCharAt(i, ' ');
|
||||
|
||||
// Null current so that /*/ won't get mistakenly detected as having closed
|
||||
cur = ' ';
|
||||
}
|
||||
}
|
||||
else if(cur == '\"')
|
||||
state = STATES.STRING;
|
||||
break;
|
||||
case STRING:
|
||||
if(cur == '\"'){
|
||||
if(evenBSlash)
|
||||
state = STATES.NORMAL;
|
||||
}
|
||||
else if(cur == '\\')
|
||||
evenBSlash = !evenBSlash;
|
||||
else
|
||||
evenBSlash = true;
|
||||
break;
|
||||
case SCOMMENT:
|
||||
if(cur == '\n')
|
||||
state = STATES.NORMAL;
|
||||
else
|
||||
sbuf.setCharAt(i, ' ');
|
||||
break;
|
||||
case MCOMMENT:
|
||||
if(prev == '*' && cur == '/')
|
||||
state = STATES.NORMAL;
|
||||
|
||||
sbuf.setCharAt(i, ' ');
|
||||
break;
|
||||
}
|
||||
|
||||
prev = cur;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test main
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
findIncludes(
|
||||
"/**\n" +
|
||||
" * Mof! \" \"\n" +
|
||||
" */\n" +
|
||||
"#include \"test\"\n" +
|
||||
"#include \"tset\"\n" +
|
||||
"/*/ */\n"+
|
||||
"\n"+
|
||||
"void main()\n"+
|
||||
"{// Rar!\n"+
|
||||
" florb(); /* call florb */\n"+
|
||||
" /* another call */ florb();\n"+
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
}
|
3
nwn/nwnprc/DocGen/trunk/prc/prc.mf
Normal file
3
nwn/nwnprc/DocGen/trunk/prc/prc.mf
Normal file
@@ -0,0 +1,3 @@
|
||||
Main-Class: prc.Main
|
||||
|
||||
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AMSSpellbookMaker.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AMSSpellbookMaker.class
Normal file
Binary file not shown.
691
nwn/nwnprc/DocGen/trunk/prc/utils/AMSSpellbookMaker.java
Normal file
691
nwn/nwnprc/DocGen/trunk/prc/utils/AMSSpellbookMaker.java
Normal file
@@ -0,0 +1,691 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static prc.Main.spinner;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class AMSSpellbookMaker {
|
||||
private AMSSpellbookMaker() {/* Prevent instantiation */}
|
||||
|
||||
private static int spells2daRow = 0;
|
||||
private static int feat2daRow = 0;
|
||||
private static int iprp_feats2daRow = 0;
|
||||
private static int tlkRow = 0;
|
||||
private static int classSpellRow = 0;
|
||||
private static int classFeatRow = 0;
|
||||
private static int subradialID = 7000;
|
||||
private static Data_2da classes2da;
|
||||
private static Data_2da spells2da;
|
||||
private static Data_2da feat2da;
|
||||
private static Data_2da iprp_feats2da;
|
||||
private static Data_TLK customtlk;
|
||||
private static Data_TLK dialogtlk;
|
||||
private static Data_2da classSpell2da;
|
||||
private static Data_2da classFeat2da;
|
||||
private static String[] spellLabels;
|
||||
|
||||
private static final int MAGIC_TLK = 0x01000000;
|
||||
|
||||
private static String start_label = "####START_OF_AMS_SPELLBOOK_RESERVE";
|
||||
private static String end_label = "####END_OF_AMS_SPELLBOOK_RESERVE";
|
||||
|
||||
private static String spellbook_filename_start = "cls_spcr_";
|
||||
private static String class_filename_start = "cls_spell_";
|
||||
private static String AMSheader = "prc_";
|
||||
private static int classlength = 5;
|
||||
|
||||
/**
|
||||
* The main method, as usual.
|
||||
*
|
||||
* @param args do I really need to explain this?
|
||||
* @throws Exception this is a simple tool, just let all failures blow up
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Parse args
|
||||
for (String param : args) {//[--help]
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else if (param.equals("-tob")) {
|
||||
classlength = 3;
|
||||
spellbook_filename_start = "cls_mvcr_";
|
||||
AMSheader = "tob_";
|
||||
class_filename_start = "cls_move_";
|
||||
start_label = "####START_OF_TOB_SPELLBOOK_RESERVE";
|
||||
end_label = "####END_OF_TOB_SPELLBOOK_RESERVE";
|
||||
|
||||
System.out.println("Assembling Tome of Battle spellbooks...");
|
||||
} else if (param.equals("-inv")) {
|
||||
classlength = 3;
|
||||
spellbook_filename_start = "cls_ivcr_";
|
||||
AMSheader = "inv_";
|
||||
class_filename_start = "cls_inv_";
|
||||
start_label = "####START_OF_INV_SPELLBOOK_RESERVE";
|
||||
end_label = "####END_OF_INV_SPELLBOOK_RESERVE";
|
||||
|
||||
System.out.println("Assembling Invocation spellbooks...");
|
||||
} else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//load all the data files in advance
|
||||
//this is quite slow, but needed
|
||||
classes2da = Data_2da.load2da("2das" + File.separator + "classes.2da", true);
|
||||
spells2da = Data_2da.load2da("2das" + File.separator + "spells.2da", true);
|
||||
feat2da = Data_2da.load2da("2das" + File.separator + "feat.2da", true);
|
||||
iprp_feats2da = Data_2da.load2da("2das" + File.separator + "iprp_feats.2da", true);
|
||||
customtlk = new Data_TLK("tlk" + File.separator + "prc_consortium.tlk");
|
||||
dialogtlk = new Data_TLK("tlk" + File.separator + "dialog.tlk");
|
||||
spellLabels = spells2da.getLabels();
|
||||
|
||||
//get the start/end rows for each file for the reserved blocks
|
||||
getFirstSpells2daRow();
|
||||
getFirstFeat2daRow();
|
||||
getFirstIPRPFeats2daRow();
|
||||
getFirstTlkRow();
|
||||
System.out.println("First free spells.2da row is " + spells2daRow);
|
||||
System.out.println("First free feat.2da row is " + feat2daRow);
|
||||
System.out.println("First free iprp_feats.2da row is " + iprp_feats2daRow);
|
||||
System.out.println("First free tlk row is " + tlkRow);
|
||||
|
||||
//now process each class in turn
|
||||
for (int classRow = 0; classRow < classes2da.getEntryCount(); classRow++) {
|
||||
//the feat file is the root of the file naming layout
|
||||
String classfilename = classes2da.getEntry("FeatsTable", classRow);
|
||||
|
||||
//check its a real class not padding
|
||||
if (classfilename != null && classfilename.length() > 9) {
|
||||
classfilename = classfilename.substring(9);
|
||||
String classCoreFilename = spellbook_filename_start + classfilename;
|
||||
|
||||
//check the file exists
|
||||
File classCoreFile = new File("2das" + File.separator + classCoreFilename + ".2da");
|
||||
|
||||
if (classCoreFile.exists()) {
|
||||
//open the core spell file
|
||||
Data_2da classCoreSpell2da = Data_2da.load2da(classCoreFile.getPath(), true);
|
||||
|
||||
// If the cls_spell file for this class does not exist yet, create it
|
||||
File classSpell2daFile = new File("2das" + File.separator + class_filename_start + classfilename + ".2da");
|
||||
if (!classSpell2daFile.exists()) {
|
||||
System.out.println("File " + classSpell2daFile.getPath() + " did not exist, creating");
|
||||
classSpell2da = new Data_2da(class_filename_start + classfilename, "");
|
||||
classSpell2da.addColumn("Label");
|
||||
classSpell2da.addColumn("Level");
|
||||
classSpell2da.addColumn("FeatID");
|
||||
classSpell2da.addColumn("IPFeatID");
|
||||
classSpell2da.addColumn("SpellID");
|
||||
classSpell2da.addColumn("RealSpellID");
|
||||
classSpell2da.addColumn("ReqFeat");
|
||||
} else {
|
||||
classSpell2da = Data_2da.load2da(classSpell2daFile.getPath(), true);
|
||||
|
||||
// Clear all the existing rows
|
||||
for (String label : classSpell2da.getLabels())
|
||||
for (int i = 0; i < classSpell2da.getEntryCount(); i++)
|
||||
classSpell2da.setEntry(label, i, "****");
|
||||
}
|
||||
|
||||
// Make sure the file contains at least one line
|
||||
if (classSpell2da.getEntryCount() == 0) {
|
||||
classSpell2da.appendRow();
|
||||
}
|
||||
|
||||
// The first line should be left blank, so initialise index to 1
|
||||
classSpellRow = 1;
|
||||
|
||||
// Load the class feats 2da
|
||||
classFeat2da = Data_2da.load2da("2das" + File.separator + "cls_feat_" + classfilename + ".2da", true);
|
||||
getFirstClassFeat2daRow();
|
||||
|
||||
//get the class name
|
||||
String className = getCheckedTlkEntry(classes2da.getBiowareEntryAsInt("Name", classRow)) + " ";
|
||||
|
||||
// Construct the class portion of labels to be generated
|
||||
String classLabel = classes2da.getEntry("Label", classRow);
|
||||
// Nothing longer than Suel_Archanamach (16 chars) allowed in order to avoid extending the length of all spells.2da rows again
|
||||
if (classLabel.length() > 16)
|
||||
classLabel = classLabel.substring(0, 17);
|
||||
classLabel += "_";
|
||||
|
||||
//get the maximum spell level
|
||||
int maxLevel = 0;
|
||||
for (int row = 0; row < classCoreSpell2da.getEntryCount(); row++)
|
||||
maxLevel = Math.max(maxLevel, classCoreSpell2da.getBiowareEntryAsInt("Level", row));
|
||||
|
||||
//loop over all the spells
|
||||
for (int row = 0; row < classCoreSpell2da.getEntryCount(); row++) {
|
||||
//check its not a null row
|
||||
if (!classCoreSpell2da.getEntry("SpellID", row).equals("****")) {
|
||||
//get the real spellID
|
||||
int spellID = classCoreSpell2da.getBiowareEntryAsInt("SpellID", row);
|
||||
//get the level of the spell
|
||||
int spellLevel = classCoreSpell2da.getBiowareEntryAsInt("Level", row);
|
||||
//get the metamagic reference to know what types work
|
||||
int metamagic = spells2da.getBiowareEntryAsInt("Metamagic", spellID);
|
||||
/* not really necessary
|
||||
if(metamagic == 0)
|
||||
System.out.println("Check metamagic for spell " + spellID);
|
||||
*/
|
||||
|
||||
// Hack - Determine how radial masters there might be: 1 + metamagics
|
||||
int masterCount = 1;
|
||||
for (int metamagicFlag = 0x1; metamagicFlag <= 0x20; metamagicFlag <<= 1)
|
||||
if ((metamagic & metamagicFlag) != 0) {
|
||||
/*
|
||||
* 0x01 = 1 = Empower
|
||||
* 0x02 = 2 = Extend
|
||||
* 0x04 = 4 = Maximize
|
||||
* 0x08 = 8 = Quicken
|
||||
* 0x10 = 16 = Silent
|
||||
* 0x20 = 32 = Still
|
||||
*/
|
||||
int metaCost = 0;
|
||||
if (metamagicFlag == 0x01) metaCost = 2;
|
||||
else if (metamagicFlag == 0x02) metaCost = 1;
|
||||
else if (metamagicFlag == 0x04) metaCost = 3;
|
||||
else if (metamagicFlag == 0x08) metaCost = 4;
|
||||
else if (metamagicFlag == 0x10) metaCost = 1;
|
||||
else if (metamagicFlag == 0x20) metaCost = 1;
|
||||
|
||||
if (spellLevel + metaCost <= maxLevel)
|
||||
masterCount += 1;
|
||||
}
|
||||
List<Integer> preReservedClassSpell2daRows = new ArrayList<Integer>();
|
||||
// Reserve a number of cls_spell_ rows for the main entries.
|
||||
for (int i = 0; i < masterCount; i++) {
|
||||
// If needed, add rows to the file to prevent errors in addNewSpellbookData
|
||||
if (classSpellRow >= classSpell2da.getEntryCount()) {
|
||||
classSpell2da.appendRow();
|
||||
}
|
||||
preReservedClassSpell2daRows.add(classSpellRow++);
|
||||
}
|
||||
// Generate an iterator for it
|
||||
Iterator<Integer> preReservedClassSpell2daRowIterator = preReservedClassSpell2daRows.iterator();
|
||||
|
||||
//now loop over the metamagic varients
|
||||
//-1 represents no metamagic
|
||||
for (int metamagicNo = -1; metamagicNo < 6; metamagicNo++) {
|
||||
/*
|
||||
* 0x01 = 1 = Empower
|
||||
* 0x02 = 2 = Extend
|
||||
* 0x04 = 4 = Maximize
|
||||
* 0x08 = 8 = Quicken
|
||||
* 0x10 = 16 = Silent
|
||||
* 0x20 = 32 = Still
|
||||
*/
|
||||
// If creating the base entry, or the given metamagic applies
|
||||
if (metamagicNo == -1 || (metamagic & (1 << metamagicNo)) != 0) {
|
||||
String spellNameMetamagic = "";
|
||||
String spellLabelMetamagic = "";
|
||||
String metaScript = "";
|
||||
int metamagicLevel = 0;
|
||||
String metamagicFeat = "****";
|
||||
if (metamagicNo == -1) {
|
||||
spellNameMetamagic = "";
|
||||
spellLabelMetamagic = "";
|
||||
metaScript = "sp";
|
||||
metamagicLevel = 0;
|
||||
metamagicFeat = "****";
|
||||
} else if (metamagicNo == 0) {
|
||||
spellNameMetamagic = "Empowered ";
|
||||
spellLabelMetamagic = "Empowered_";
|
||||
metaScript = "em";
|
||||
metamagicLevel = 2;
|
||||
metamagicFeat = "11";
|
||||
} else if (metamagicNo == 1) {
|
||||
spellNameMetamagic = "Extended ";
|
||||
spellLabelMetamagic = "Exteneded_";
|
||||
metaScript = "ex";
|
||||
metamagicLevel = 1;
|
||||
metamagicFeat = "12";
|
||||
} else if (metamagicNo == 2) {
|
||||
spellNameMetamagic = "Maximized ";
|
||||
spellLabelMetamagic = "Maximized_";
|
||||
metaScript = "ma";
|
||||
metamagicLevel = 3;
|
||||
metamagicFeat = "25";
|
||||
} else if (metamagicNo == 3) {
|
||||
spellNameMetamagic = "Quickened ";
|
||||
spellLabelMetamagic = "Quickened_";
|
||||
metaScript = "qu";
|
||||
metamagicLevel = 4;
|
||||
metamagicFeat = "29";
|
||||
} else if (metamagicNo == 4) {
|
||||
spellNameMetamagic = "Silent ";
|
||||
spellLabelMetamagic = "Silent_";
|
||||
metaScript = "si";
|
||||
metamagicLevel = 1;
|
||||
metamagicFeat = "33";
|
||||
} else if (metamagicNo == 5) {
|
||||
spellNameMetamagic = "Still ";
|
||||
spellLabelMetamagic = "Still_";
|
||||
metaScript = "st";
|
||||
metamagicLevel = 1;
|
||||
metamagicFeat = "37";
|
||||
}
|
||||
//check if the metamagic adjusted level is less than the maximum level
|
||||
if ((metamagicLevel + spellLevel) <= maxLevel) {
|
||||
//debug printout
|
||||
//System.out.println(name+" : "+label);
|
||||
addNewSpellbookData(spellID,
|
||||
classfilename,
|
||||
metaScript,
|
||||
metamagicNo,
|
||||
metamagicLevel,
|
||||
metamagicFeat,
|
||||
spellLevel,
|
||||
className,
|
||||
spellNameMetamagic,
|
||||
classLabel,
|
||||
spellLabelMetamagic,
|
||||
preReservedClassSpell2daRowIterator,
|
||||
0);
|
||||
}//end of level check
|
||||
}//end of metamamgic check
|
||||
}//end of metamagic loop
|
||||
}// end if - The cls_spcr row contains an entry
|
||||
}//end of cls_spells_*_core.2da loop
|
||||
|
||||
//save the new cls_spell_*.2da file
|
||||
classSpell2da.save2da("2das", true, true);
|
||||
classFeat2da.save2da("2das", true, true);
|
||||
} else {
|
||||
//System.out.println(classfilename+" does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
//now resave the files we opened
|
||||
spells2da.save2da("2das", true, true);
|
||||
feat2da.save2da("2das", true, true);
|
||||
iprp_feats2da.save2da("2das", true, true);
|
||||
customtlk.saveAsXML("prc_consortium", "tlk", true);
|
||||
}
|
||||
|
||||
private static void addNewSpellbookData(int spellID,
|
||||
String classfilename,
|
||||
String metaScript,
|
||||
int metamagicNo,
|
||||
int metamagicLevel,
|
||||
String metamagicFeat,
|
||||
int spellLevel,
|
||||
String className,
|
||||
String spellNameMetamagic,
|
||||
String classLabel,
|
||||
String spellLabelMetamagic,
|
||||
Iterator<Integer> preReservedClassSpell2daRows,
|
||||
int subradialMaster) {
|
||||
// Hack - If not a subradial, use prereserved cls_spell row
|
||||
int localClassSpellRow;
|
||||
if (subradialMaster == 0) {
|
||||
localClassSpellRow = preReservedClassSpell2daRows.next();
|
||||
} else {
|
||||
// Grab the current value of classSpellRow for use and then increment it
|
||||
localClassSpellRow = classSpellRow++;
|
||||
}
|
||||
|
||||
//get the name of the spell
|
||||
String spellName = getCheckedTlkEntry(spells2da.getBiowareEntryAsInt("Name", spellID));
|
||||
//get the label of the spell
|
||||
String spellLabel = spells2da.getEntry("Label", spellID);
|
||||
//assemble the name
|
||||
String name = className + spellNameMetamagic + spellName;
|
||||
//assemble the label
|
||||
String label = classLabel + spellLabelMetamagic + spellLabel;
|
||||
//set the next tlk line to the name
|
||||
customtlk.setEntry(tlkRow, name);
|
||||
|
||||
//copy the original spells.2da line to the next free spells.2da line
|
||||
String[] originalSpellRow = spells2da.getRow(spellID);
|
||||
for (int i = 0; i < originalSpellRow.length; i++) {
|
||||
spells2da.setEntry(spellLabels[i], spells2daRow, spells2da.getEntry(spellLabels[i], spellID));
|
||||
}
|
||||
|
||||
//change the ImpactScript
|
||||
String script = AMSheader + (classfilename.length() <= 5 ? classfilename : classfilename.substring(0, classlength)) + "_generic";
|
||||
spells2da.setEntry("ImpactScript", spells2daRow, script);
|
||||
//change the Label
|
||||
spells2da.setEntry("Label", spells2daRow, label);
|
||||
//change the Name
|
||||
spells2da.setEntry("Name", spells2daRow, Integer.toString(tlkRow + MAGIC_TLK));
|
||||
|
||||
//if quickened, set conjuring/casting duration to zero
|
||||
if (metamagicNo == 3) {
|
||||
spells2da.setEntry("ConjTime", spells2daRow, "0");
|
||||
spells2da.setEntry("CastTime", spells2daRow, "0");
|
||||
}
|
||||
//if silenced, set it to no vocals
|
||||
if (metamagicNo == 4) {
|
||||
spells2da.setEntry("ConjSoundVFX", spells2daRow, "****");
|
||||
spells2da.setEntry("ConjSoundMale", spells2daRow, "****");
|
||||
spells2da.setEntry("ConjSoundFemale", spells2daRow, "****");
|
||||
spells2da.setEntry("CastSound", spells2daRow, "****");
|
||||
}
|
||||
//if stilled, set it to no casting animations
|
||||
if (metamagicNo == 5) {
|
||||
spells2da.setEntry("CastAnim", spells2daRow, "****");
|
||||
spells2da.setEntry("ConjAnim", spells2daRow, "****");
|
||||
}
|
||||
|
||||
//set the level to the correct value, including metamagic
|
||||
spells2da.setEntry("Innate", spells2daRow, Integer.toString(metamagicLevel + spellLevel));
|
||||
//clear class levels
|
||||
spells2da.setEntry("Bard", spells2daRow, "****");
|
||||
spells2da.setEntry("Cleric", spells2daRow, "****");
|
||||
spells2da.setEntry("Druid", spells2daRow, "****");
|
||||
spells2da.setEntry("Paladin", spells2daRow, "****");
|
||||
spells2da.setEntry("Ranger", spells2daRow, "****");
|
||||
spells2da.setEntry("Wiz_Sorc", spells2daRow, "****");
|
||||
|
||||
// set subradial master, if applicable
|
||||
if (subradialMaster != 0) {
|
||||
spells2da.setEntry("Master", spells2daRow, Integer.toString(subradialMaster));
|
||||
//calculate the new feat id
|
||||
int subradialFeatID = spells2da.getBiowareEntryAsInt("FeatID", subradialMaster);
|
||||
//Set the FEATID on each of the subspells as follows: (65536 * subfeat) + feat ID.
|
||||
//The top 16 bits is used for subfeat, the bottom for feat.
|
||||
subradialFeatID = (65536 * subradialID) + subradialFeatID;
|
||||
spells2da.setEntry("FeatID", spells2daRow, Integer.toString(subradialFeatID));
|
||||
} else {
|
||||
spells2da.setEntry("Master", spells2daRow, "****");
|
||||
//make it point to the new feat.2da line that will be added soon
|
||||
spells2da.setEntry("FeatID", spells2daRow, Integer.toString(feat2daRow));
|
||||
}
|
||||
|
||||
//remove projectiles from firing because the real spell will do this
|
||||
spells2da.setEntry("Proj", spells2daRow, "0");
|
||||
spells2da.setEntry("ProjModel", spells2daRow, "****");
|
||||
spells2da.setEntry("ProjType", spells2daRow, "****");
|
||||
spells2da.setEntry("ProjSpwnPoint", spells2daRow, "****");
|
||||
spells2da.setEntry("ProjSound", spells2daRow, "****");
|
||||
spells2da.setEntry("ProjOrientation", spells2daRow, "****");
|
||||
spells2da.setEntry("HasProjectile", spells2daRow, "0");
|
||||
|
||||
//add a feat.2da line
|
||||
if (subradialMaster == 0) {
|
||||
// Clear the line of old values
|
||||
for (String featLabel : feat2da.getLabels())
|
||||
feat2da.setEntry(featLabel, feat2daRow, "****");
|
||||
|
||||
// Reset the ReqAction column to 1
|
||||
feat2da.setEntry("ReqAction", feat2daRow, "1");
|
||||
|
||||
//make it point to the new spells.2da line
|
||||
feat2da.setEntry("SPELLID", feat2daRow, Integer.toString(spells2daRow));
|
||||
//change the Name
|
||||
feat2da.setEntry("FEAT", feat2daRow, Integer.toString(tlkRow + MAGIC_TLK));
|
||||
//change the Label
|
||||
feat2da.setEntry("LABEL", feat2daRow, label);
|
||||
//change the description
|
||||
feat2da.setEntry("DESCRIPTION", feat2daRow, spells2da.getEntry("SpellDesc", spells2daRow));
|
||||
//change the icon
|
||||
feat2da.setEntry("ICON", feat2daRow, spells2da.getEntry("IconResRef", spells2daRow));
|
||||
//personal range
|
||||
feat2da.setEntry("TARGETSELF", feat2daRow, spells2da.getEntry("Range", spellID).equals("P") ? "1" : "0");
|
||||
//if spell is hostile, make feat hostile
|
||||
if (spells2da.getEntry("HostileSetting", spellID).equals("1")) {
|
||||
feat2da.setEntry("HostileFeat", feat2daRow, "1");
|
||||
} else {
|
||||
feat2da.setEntry("HostileFeat", feat2daRow, "0");
|
||||
}
|
||||
//set the category to the same as the spell
|
||||
feat2da.setEntry("CATEGORY", feat2daRow, spells2da.getEntry("Category", spells2daRow));
|
||||
}
|
||||
|
||||
|
||||
//add an iprp_feats.2da line
|
||||
if (subradialMaster == 0) {
|
||||
// Clear the line of old values
|
||||
for (String iprpLabel : iprp_feats2da.getLabels())
|
||||
iprp_feats2da.setEntry(iprpLabel, iprp_feats2daRow, "****");
|
||||
|
||||
//set its label
|
||||
iprp_feats2da.setEntry("Label", iprp_feats2daRow, label);
|
||||
//set its name
|
||||
iprp_feats2da.setEntry("Name", iprp_feats2daRow, Integer.toString(tlkRow + MAGIC_TLK));
|
||||
//make it point to the new feat.2da line
|
||||
iprp_feats2da.setEntry("FeatIndex", iprp_feats2daRow, Integer.toString(feat2daRow));
|
||||
//set its cost to 0.0
|
||||
iprp_feats2da.setEntry("Cost", iprp_feats2daRow, "0.0");
|
||||
}
|
||||
|
||||
//add a cls_spell_*.2da line if needed
|
||||
if (localClassSpellRow >= classSpell2da.getEntryCount()) {
|
||||
classSpell2da.appendRow();
|
||||
}
|
||||
//set its label
|
||||
classSpell2da.setEntry("Label", localClassSpellRow, label);
|
||||
//make it point to the new spells.2da
|
||||
classSpell2da.setEntry("SpellID", localClassSpellRow, Integer.toString(spells2daRow));
|
||||
//make it point to the old spells.2da
|
||||
classSpell2da.setEntry("RealSpellID", localClassSpellRow, Integer.toString(spellID));
|
||||
|
||||
//if its a subradial, dont do this
|
||||
if (subradialMaster == 0) {
|
||||
//make it point to the new feat.2da
|
||||
classSpell2da.setEntry("FeatID", localClassSpellRow, Integer.toString(feat2daRow));
|
||||
//make it point to the new iprp_feats.2da
|
||||
classSpell2da.setEntry("IPFeatID", localClassSpellRow, Integer.toString(iprp_feats2daRow));
|
||||
//add the metamagic checks
|
||||
classSpell2da.setEntry("ReqFeat", localClassSpellRow, metamagicFeat);
|
||||
//set its level
|
||||
classSpell2da.setEntry("Level", localClassSpellRow, Integer.toString(metamagicLevel + spellLevel));
|
||||
} else {
|
||||
//make it point to the new feat.2da
|
||||
classSpell2da.setEntry("FeatID", localClassSpellRow, "****");
|
||||
//make it point to the new iprp_feats.2da
|
||||
classSpell2da.setEntry("IPFeatID", localClassSpellRow, "****");
|
||||
//add the metamagic checks
|
||||
classSpell2da.setEntry("ReqFeat", localClassSpellRow, "****");
|
||||
//set its level
|
||||
classSpell2da.setEntry("Level", localClassSpellRow, "****");
|
||||
}
|
||||
|
||||
//cls_feat_*.2da
|
||||
if (subradialMaster == 0) {
|
||||
classFeat2da.setEntry("FeatLabel", classFeatRow, label);
|
||||
classFeat2da.setEntry("FeatIndex", classFeatRow, Integer.toString(feat2daRow));
|
||||
classFeat2da.setEntry("List", classFeatRow, Integer.toString(0));
|
||||
classFeat2da.setEntry("GrantedOnLevel", classFeatRow, Integer.toString(99));
|
||||
classFeat2da.setEntry("OnMenu", classFeatRow, Integer.toString(1));
|
||||
}
|
||||
|
||||
|
||||
//move to next file lines
|
||||
getNextSpells2daRow();
|
||||
getNextTlkRow();
|
||||
//only need new ones of these if its not a subradial
|
||||
if (subradialMaster == 0) {
|
||||
getNextFeat2daRow();
|
||||
getNextIPRPFeats2daRow();
|
||||
getNextClassFeat2daRow();
|
||||
} else { //do this if it is a subradial
|
||||
// increase the subradial id ready for next one
|
||||
subradialID++;
|
||||
}
|
||||
|
||||
//add subradial spells
|
||||
if (subradialMaster == 0) {
|
||||
//store the spell row the master uses
|
||||
//will be incremented by subradials
|
||||
//the -1 is because you want the last used row, not the current blank row
|
||||
int masterSpellID = spells2daRow - 1;
|
||||
boolean doOnce = false;
|
||||
for (int subradial = 1; subradial <= 5; subradial++) {
|
||||
if (spells2da.getBiowareEntryAsInt("SubRadSpell" + subradial, spellID) != 0) {
|
||||
// It is, in fact, a radial master, so set it's ImpactScript to tell people
|
||||
// about the BioBug triggered by using subradial feats directly from class radial
|
||||
if (!doOnce) {
|
||||
doOnce = true;
|
||||
|
||||
spells2da.setEntry("ImpactScript", masterSpellID, "prc_radialbug");
|
||||
}
|
||||
addNewSpellbookData(spells2da.getBiowareEntryAsInt("SubRadSpell" + subradial, spellID),
|
||||
classfilename,
|
||||
metaScript,
|
||||
metamagicNo,
|
||||
metamagicLevel,
|
||||
metamagicFeat,
|
||||
spellLevel,
|
||||
className,
|
||||
spellNameMetamagic,
|
||||
classLabel,
|
||||
spellLabelMetamagic,
|
||||
preReservedClassSpell2daRows,
|
||||
masterSpellID);
|
||||
//update the master rows with the subradial spell rows
|
||||
//the -1 is because you want the last used row, not the current blank row
|
||||
spells2da.setEntry("SubRadSpell" + subradial, masterSpellID, Integer.toString(spells2daRow - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstSpells2daRow() {
|
||||
System.out.print("Finding start of spells.2da ");
|
||||
while (!spells2da.getEntry("Label", spells2daRow).equals(start_label)) {
|
||||
spells2daRow++;
|
||||
if (spells2daRow > spells2da.getEntryCount()) {
|
||||
System.out.println("Spells.2da reached the end of the file.");
|
||||
System.exit(1);
|
||||
}
|
||||
spinner.spin();
|
||||
}
|
||||
spells2daRow++;
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextSpells2daRow() {
|
||||
spells2daRow++;
|
||||
if (spells2da.getEntry("Label", spells2daRow).equals(end_label)) {
|
||||
getFirstSpells2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstFeat2daRow() {
|
||||
System.out.print("Finding start of feat.2da ");
|
||||
while (!feat2da.getEntry("Label", feat2daRow).equals(start_label)) {
|
||||
feat2daRow++;
|
||||
if (feat2daRow > feat2da.getEntryCount()) {
|
||||
System.out.println("Feat.2da reached the end of the file.");
|
||||
System.exit(1);
|
||||
}
|
||||
spinner.spin();
|
||||
}
|
||||
feat2daRow++;
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextFeat2daRow() {
|
||||
feat2daRow++;
|
||||
if (feat2da.getEntry("Label", feat2daRow).equals(end_label)) {
|
||||
getFirstFeat2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstIPRPFeats2daRow() {
|
||||
System.out.print("Finding start of iprp_spells.2da ");
|
||||
while (!iprp_feats2da.getEntry("Label", iprp_feats2daRow).equals(start_label)) {
|
||||
iprp_feats2daRow++;
|
||||
if (iprp_feats2daRow > iprp_feats2da.getEntryCount()) {
|
||||
System.out.println("iprp_feats.2da reached the end of the file.");
|
||||
System.exit(1);
|
||||
}
|
||||
spinner.spin();
|
||||
}
|
||||
iprp_feats2daRow++;
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextIPRPFeats2daRow() {
|
||||
iprp_feats2daRow++;
|
||||
if (iprp_feats2da.getEntry("Label", iprp_feats2daRow).equals(end_label)) {
|
||||
getFirstIPRPFeats2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstClassFeat2daRow() {
|
||||
classFeatRow = 0;
|
||||
System.out.print("Finding start of cls_feat_*.2da ");
|
||||
while (!classFeat2da.getEntry("FeatLabel", classFeatRow).equals(start_label)) {
|
||||
classFeatRow++;
|
||||
if (classFeatRow >= classFeat2da.getEntryCount()) {
|
||||
System.out.println("cls_feat_*.2da reached the end of the file.");
|
||||
System.exit(1);
|
||||
}
|
||||
spinner.spin();
|
||||
}
|
||||
getNextClassFeat2daRow();
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextClassFeat2daRow() {
|
||||
classFeatRow++;
|
||||
if (classFeat2da.getEntry("FeatLabel", classFeatRow).equals(end_label)) {
|
||||
classFeat2da.insertRow(classFeatRow);
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstTlkRow() {
|
||||
System.out.print("Finding start of prc_consortium.tlk ");
|
||||
while (!customtlk.getEntry(tlkRow).equals(start_label)) {
|
||||
tlkRow++;
|
||||
spinner.spin();
|
||||
}
|
||||
tlkRow++;
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextTlkRow() {
|
||||
tlkRow++;
|
||||
if (customtlk.getEntry(tlkRow).equals(end_label)) {
|
||||
getFirstTlkRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getCheckedTlkEntry(int entryNo) {
|
||||
if (entryNo > MAGIC_TLK) {
|
||||
return customtlk.getEntry(entryNo - MAGIC_TLK);
|
||||
}
|
||||
return dialogtlk.getEntry(entryNo);
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help]\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n" +
|
||||
"\n" +
|
||||
" -tob Tome of Battle" +
|
||||
" -inv Invocations" +
|
||||
"\n" +
|
||||
"Creates and/or updates the new AMS spellbooks data. Assumes it's being run from\n" +
|
||||
"the root of the nwnprc cvs module. Looks for dialog.tlk under tlk/.\n" +
|
||||
"Reads the cls_??cr_*.2da files and updates cls_feat_*.2da, cls_????*.2da,\n" +
|
||||
"feat.2da, iprp_feats.2da and spells.2da."
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater$1.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater.class
Normal file
Binary file not shown.
197
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater.java
Normal file
197
nwn/nwnprc/DocGen/trunk/prc/utils/AllClassFeatUpdater.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.Data_2da;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.Main.spinner;
|
||||
|
||||
|
||||
/**
|
||||
* This class is meant for updating the class feat lists with the entries common to all
|
||||
* base classes.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class AllClassFeatUpdater {
|
||||
|
||||
private static boolean cropduplicates = false;
|
||||
|
||||
/**
|
||||
* Ye olde main method.
|
||||
* Takes as parameters the path of the 2da to use as update template and
|
||||
*
|
||||
* @param args [--help] | [-c] pathtoupdate2da targetpath+
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String cfabcPath = null;
|
||||
List<String> paths = new ArrayList<String>();
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//[--help] | pathtoupdate2da targetpath+
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
cropduplicates = true;
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a pathname
|
||||
if (cfabcPath == null)
|
||||
cfabcPath = param;
|
||||
else
|
||||
paths.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfabcPath == null) {
|
||||
err_pr.println("Error: You did not specify the location of cls_feat_allBaseClasses.2da\n");
|
||||
readMe();
|
||||
}
|
||||
if (paths.size() == 0) {
|
||||
err_pr.println("Error: You did not specify targets!\n");
|
||||
readMe();
|
||||
}
|
||||
spinner.disable();
|
||||
|
||||
// Load and crop the template 2da
|
||||
Data_2da source = Data_2da.load2da(cfabcPath);
|
||||
int i = source.getEntryCount();
|
||||
boolean passedEnd = false, passedBegin = false;
|
||||
while (--i >= 0) {
|
||||
//###cls_feat_allBaseClasses_BEGIN###
|
||||
//###cls_feat_allBaseClasses_END###
|
||||
if (!passedEnd) {
|
||||
if (source.getEntry("FeatLabel", i).equals("###cls_feat_allBaseClasses_END###")) {
|
||||
passedEnd = true;
|
||||
continue;
|
||||
} else
|
||||
source.removeRow(i);
|
||||
} else if (!passedBegin) {
|
||||
if (source.getEntry("FeatLabel", i).equals("###cls_feat_allBaseClasses_BEGIN###"))
|
||||
passedBegin = true;
|
||||
} else {
|
||||
source.removeRow(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the targets and update all files found
|
||||
for (String path : paths) {
|
||||
File target = new File(path);
|
||||
File[] cls_feat2da;
|
||||
|
||||
if (target.isDirectory()) {
|
||||
cls_feat2da = target.listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().startsWith("cls_feat_") &&
|
||||
file.getName().toLowerCase().endsWith(".2da");
|
||||
}
|
||||
});
|
||||
} else if (target.getName().toLowerCase().startsWith("cls_feat_") &&
|
||||
target.getName().toLowerCase().endsWith(".2da"))
|
||||
cls_feat2da = new File[]{target};
|
||||
else {
|
||||
err_pr.println("Error: Parameter \"" + path + "\" is not a valid target!");
|
||||
continue;
|
||||
}
|
||||
|
||||
Arrays.sort(cls_feat2da);
|
||||
|
||||
for (File file : cls_feat2da) {
|
||||
try {
|
||||
update2da(source, Data_2da.load2da(file.getCanonicalPath()), file.getParentFile().getCanonicalPath());
|
||||
} catch (Exception e) {
|
||||
err_pr.printException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void update2da(Data_2da updateSource, Data_2da target, String path) throws IOException {
|
||||
// Find the beginning of replaceable area
|
||||
int beginRow = -1, i = 0;
|
||||
while (beginRow == -1 && i < target.getEntryCount()) {
|
||||
if (target.getEntry("FeatLabel", i).equals("###cls_feat_allBaseClasses_BEGIN###"))
|
||||
beginRow = i;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (beginRow != -1) {
|
||||
// Strip the lines to be replaced
|
||||
while (beginRow < target.getEntryCount()) {
|
||||
if (target.getEntry("FeatLabel", beginRow).equals("###cls_feat_allBaseClasses_END###")) {
|
||||
target.removeRow(beginRow);
|
||||
break;
|
||||
} else
|
||||
target.removeRow(beginRow);
|
||||
}
|
||||
|
||||
// Handle cropping, if it is enabled
|
||||
if (cropduplicates) {
|
||||
// Make a copy of the update source, which can then be cropped
|
||||
updateSource = (Data_2da) updateSource.clone();
|
||||
cropDuplicates(updateSource, target);
|
||||
}
|
||||
|
||||
for (i = 0; i < updateSource.getEntryCount(); i++) {
|
||||
target.insertRow(beginRow + i, updateSource.getRow(i));
|
||||
}
|
||||
|
||||
//System.out.println(target); System.exit(0);
|
||||
target.save2da(path, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void cropDuplicates(Data_2da toCrop, Data_2da source) {
|
||||
// Load the featIDs from source to a hashset
|
||||
HashSet<Integer> featIDs = new HashSet<Integer>();
|
||||
|
||||
for (int i = 0; i < source.getEntryCount(); i++) {
|
||||
try {
|
||||
featIDs.add(Integer.parseInt(source.getEntry("FeatIndex", i)));
|
||||
} catch (NumberFormatException nfe) {/* Ignore empty rows */}
|
||||
}
|
||||
|
||||
// Loop over the crop target, removing rows whose FeatIndex is present in the source
|
||||
for (int i = toCrop.getEntryCount() - 1; i >= 0; i--) {
|
||||
try {
|
||||
if (featIDs.contains(Integer.parseInt(toCrop.getEntry("FeatIndex", i))))
|
||||
toCrop.removeRow(i);
|
||||
} catch (NumberFormatException nfe) {/* Ignore empty rows */}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | [-c] pathtoupdate2da targetpath+\n" +
|
||||
"\n" +
|
||||
" pathtoupdate2da path of the cls_feat_allBaseClasses.2da\n" +
|
||||
" targetpath the path of a directory containing the cls_feat_*.2das to update\n" +
|
||||
" or directly the path of a cls_feat_*.2da\n" +
|
||||
"\n" +
|
||||
" -c crop rows from the update source that contain featIDs present elsewhere\n" +
|
||||
" in the target than in the updateable area\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Blank2daRows.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Blank2daRows.class
Normal file
Binary file not shown.
116
nwn/nwnprc/DocGen/trunk/prc/utils/Blank2daRows.java
Normal file
116
nwn/nwnprc/DocGen/trunk/prc/utils/Blank2daRows.java
Normal file
@@ -0,0 +1,116 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A tool for blanking ranges of 2da rows.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Blank2daRows {
|
||||
|
||||
/**
|
||||
* Ye olde maine methode.
|
||||
*
|
||||
* @param args The program arguments, as usual.
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0) readMe();
|
||||
String targetPath = null;
|
||||
List<int[]> ranges = new ArrayList<int[]>();
|
||||
|
||||
for (String param : args) {//target B-E ... | [--help]
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
default:
|
||||
System.err.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
// If the target file hasn't been specified, assume this is it
|
||||
if (targetPath == null)
|
||||
targetPath = param;
|
||||
else {
|
||||
try {
|
||||
if (!param.contains("-")) throw new Exception(); // Missing -
|
||||
String[] rawNums = param.split("-");
|
||||
if (rawNums.length != 2) throw new Exception(); // More than two numbers(?) in the string
|
||||
int[] range = new int[]{Integer.parseInt(rawNums[0]), Integer.parseInt(rawNums[1])};
|
||||
ranges.add(range);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Malformed number pair:" + param);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the 2da
|
||||
Data_2da target = Data_2da.load2da(targetPath);
|
||||
|
||||
// Bounds checks
|
||||
for (int[] range : ranges) {
|
||||
if (range[0] > range[1]) { // Lower bound > upper bound
|
||||
System.err.println("Lower bound > upper bound in pair: " + range[0] + "-" + range[1]);
|
||||
System.exit(1);
|
||||
}
|
||||
if (range[0] < 0 || range[1] < 0 ||
|
||||
range[0] >= target.getEntryCount() ||
|
||||
range[1] >= target.getEntryCount()) { // Bound out of range
|
||||
System.err.println("Bound out of range in pair: " + range[0] + "-" + range[1]);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Do blanking
|
||||
for (int[] range : ranges)
|
||||
blankRows(target, range[0], range[1]);
|
||||
|
||||
// Save 2da back out
|
||||
target.save2da(new File(targetPath).getParent(), true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the row blanking - replaces the contents of each column in the affected row range with whatever
|
||||
* is the default value in this 2da.
|
||||
*
|
||||
* @param target Data_2da to perform the operation on
|
||||
* @param begin Beginning of the range to blank, inclusive
|
||||
* @param end End of the range to blank, inclusive
|
||||
*/
|
||||
private static void blankRows(Data_2da target, int begin, int end) {
|
||||
for (int i = begin; i <= end; i++) {
|
||||
for (String label : target.getLabels())
|
||||
target.setEntry(label, i, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n" +
|
||||
" target B-E ... | [--help]\n" +
|
||||
"\n" +
|
||||
" This tool blanks rows in a 2da file, replacing the contents of given rows with\n" +
|
||||
" either **** or the 2da-specific default value if such is specified.\n" +
|
||||
"\n" +
|
||||
" target Path to the 2da file to apply the blanking operation to\n" +
|
||||
" B-E Row number pair, specifying which rows in the file to blank. Inclusive,\n" +
|
||||
" for example 1000-1002 would blank rows 1000, 1001 and 1002. Multiple\n" +
|
||||
" ranges may be specified.\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/BuildScrollHack.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/BuildScrollHack.class
Normal file
Binary file not shown.
87
nwn/nwnprc/DocGen/trunk/prc/utils/BuildScrollHack.java
Normal file
87
nwn/nwnprc/DocGen/trunk/prc/utils/BuildScrollHack.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.Main.TLKStore;
|
||||
import prc.autodoc.Main.TwoDAStore;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A class that combines Scrollgen, UpdateDes and ScrollMerchantGen. For use during
|
||||
* the build process to avoid loading the same 2da files several times.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class BuildScrollHack {
|
||||
|
||||
/**
|
||||
* Ye olde maine methode.
|
||||
*
|
||||
* @param args The arguments
|
||||
* @throws IOException Just toss any exceptions encountered
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 0) readMe();
|
||||
String twoDAPath = null;
|
||||
String tlkPath = null;
|
||||
String outPath = null;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//2dadir tlkdir outpath| [--help]
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a pathname
|
||||
if (twoDAPath == null)
|
||||
twoDAPath = param;
|
||||
else if (tlkPath == null)
|
||||
tlkPath = param;
|
||||
else if (outPath == null)
|
||||
outPath = param;
|
||||
else {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load data
|
||||
TwoDAStore twoDA = new TwoDAStore(twoDAPath);
|
||||
TLKStore tlks = new TLKStore("dialog.tlk", "prc_consortium.tlk", tlkPath);
|
||||
|
||||
ScrollGen.doScrollGen(twoDA, twoDAPath, outPath);
|
||||
UpdateDes.doUpdateDes(twoDA, twoDAPath);
|
||||
ScrollMerchantGen.doScrollMerchantGen(twoDA, tlks, outPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the use instructions for this program and kills execution.
|
||||
*/
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n" +
|
||||
" java -jar prc.jar buildscrhack 2dadir tlkdir outpath| [--help]\n" +
|
||||
"\n" +
|
||||
"2dadir Path to a directory containing 2da files\n" +
|
||||
"tlkdir Path to a directory containing dialog.tlk and prc_consortium.tlk\n" +
|
||||
"outdir Path to the directory to save the new scroll xml files in\n" +
|
||||
"\n" +
|
||||
"--help prints this info you are reading\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"A tool for automatically updating parts of des_crft_scrolls.2da and\n" +
|
||||
"des_crft_spells.2da based on spells.2da\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen$Script.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen$Script.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen.class
Normal file
Binary file not shown.
128
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen.java
Normal file
128
nwn/nwnprc/DocGen/trunk/prc/utils/CodeGen.java
Normal file
@@ -0,0 +1,128 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.Data_2da;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class CodeGen {
|
||||
private CodeGen() {
|
||||
}
|
||||
|
||||
private static class Script implements Cloneable {
|
||||
public String text,
|
||||
name;
|
||||
|
||||
public Script(String text, String name) {
|
||||
this.text = text;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new Script(text, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String prefix,
|
||||
suffix,
|
||||
template;
|
||||
private static Data_2da[] data;
|
||||
|
||||
/**
|
||||
* The main method, as usual.
|
||||
*
|
||||
* @param args do I really need to exapain this?
|
||||
* @throws Exception this is a simple tool, just let all failures blow up
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 0 || args[0].equals("--help") || args[0].equals("-?"))
|
||||
readMe();
|
||||
|
||||
prefix = args[0];
|
||||
suffix = args[1];
|
||||
template = readTemplate(args[2]);
|
||||
|
||||
data = new Data_2da[args.length - 3];
|
||||
for (int i = 0; i < data.length; i++)
|
||||
data[i] = Data_2da.load2da(args[i + 3]);
|
||||
|
||||
doCreation(new Script(template, prefix), 0);
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
"\tjava CodeGen namePrefix nameSuffix templatePath 2daPaths...\n" +
|
||||
"\n" +
|
||||
"namePrefix\tprefix that all the resulting filenames will share\n" +
|
||||
"nameSuffix\tsuffix that all the resulting filenames will share\n" +
|
||||
"templatePath\tlocation of the template to use. May be absolute or relative\n" +
|
||||
"2daPaths\tone or more 2da files to use fill the template with\n" +
|
||||
"\n\n" +
|
||||
"Places to replace in the template are marked with ~~~Identifier~~~. This will\n" +
|
||||
"be replaced by entries from a column in one of the 2das labeled Identifier.\n" +
|
||||
"This is case-insensitive.\n" +
|
||||
"\n" +
|
||||
"The 2da files must contain two columns labeled Suffix and Value.\n" +
|
||||
"\n" +
|
||||
"One script file will be generated for each possible combination of values from\n" +
|
||||
"the 2das. They will automatically have file type identifier of .nss"
|
||||
);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
|
||||
private static String readTemplate(String filePath) throws Exception {
|
||||
Scanner reader = new Scanner(new File(filePath));
|
||||
StringBuffer temp = new StringBuffer();
|
||||
|
||||
while (reader.hasNextLine()) temp.append(reader.nextLine() + "\n");
|
||||
|
||||
return temp.toString();
|
||||
}
|
||||
|
||||
|
||||
private static void doCreation(Script script, int depth) throws Exception {
|
||||
if (depth == data.length) {
|
||||
printScript(script);
|
||||
return;
|
||||
}
|
||||
Script copy;
|
||||
|
||||
for (int i = 0; i < data[depth].getEntryCount(); i++) {
|
||||
copy = (Script) script.clone();
|
||||
for (String label : data[depth].getLabels())
|
||||
copy.text = Pattern.compile("~~~" + label + "~~~", Pattern.CASE_INSENSITIVE)
|
||||
.matcher(copy.text)
|
||||
.replaceAll(data[depth].getEntry(label, i));
|
||||
/*copy.text = script.text.replaceAll("~~~" + data[depth].getName() + "~~~",
|
||||
data[depth].getEntry("Value", i));*/
|
||||
copy.name += data[depth].getEntry("Suffix", i) != null ?
|
||||
data[depth].getEntry("Suffix", i) :
|
||||
"";
|
||||
|
||||
doCreation(copy, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printScript(Script toPrint) throws Exception {
|
||||
File target = new File(toPrint.name + suffix);
|
||||
// Clean up old version if necessary
|
||||
if (target.exists()) {
|
||||
System.out.println("Deleting previous version of " + target.getName());
|
||||
target.delete();
|
||||
}
|
||||
target.createNewFile();
|
||||
|
||||
// Creater the writer and print
|
||||
FileWriter writer = new FileWriter(target, false);
|
||||
writer.write(toPrint.text);
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Data2daMerge.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Data2daMerge.class
Normal file
Binary file not shown.
127
nwn/nwnprc/DocGen/trunk/prc/utils/Data2daMerge.java
Normal file
127
nwn/nwnprc/DocGen/trunk/prc/utils/Data2daMerge.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public final class Data2daMerge {
|
||||
private Data2daMerge() {
|
||||
}
|
||||
|
||||
private static String source = "";
|
||||
private static String merge = "";
|
||||
private static String output = "";
|
||||
|
||||
/**
|
||||
* The main method, as usual.
|
||||
*
|
||||
* @param args do I really need to explain this?
|
||||
* @throws Exception this is a simple tool, just let all failures blow up
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 3 || args[0].equals("--help") || args[0].equals("-?"))
|
||||
readMe();
|
||||
|
||||
//check arguments for directories to use
|
||||
source = args[0];
|
||||
merge = args[1];
|
||||
output = args[2];
|
||||
|
||||
//assemble arrays of filenames
|
||||
File[] sourceFiles = new File(source).listFiles();
|
||||
File[] mergeFiles = new File(merge).listFiles();
|
||||
|
||||
//define some things for speed
|
||||
File sourceFile;
|
||||
File mergeFile;
|
||||
Data_2da sourceData;
|
||||
Data_2da mergeData;
|
||||
Data_2da outputData;
|
||||
|
||||
for (int i = 0; i < sourceFiles.length; i++) {
|
||||
sourceFile = sourceFiles[i];
|
||||
//ignore non-2da files
|
||||
if (sourceFile.getPath().endsWith(".2da")) {
|
||||
String sourceFilename = sourceFile.getName().substring(0, sourceFile.getName().length() - 4);
|
||||
//loop over the merge files to find one that matches the source
|
||||
boolean matchFound = false;
|
||||
for (int j = 0; j < mergeFiles.length; j++) {
|
||||
mergeFile = mergeFiles[j];
|
||||
//ignore non-2da files
|
||||
if (mergeFile.getPath().endsWith(".2da")) {
|
||||
String mergeFilename = mergeFile.getName().substring(0, mergeFile.getName().length() - 4);
|
||||
//its a match
|
||||
if (mergeFilename.equals(sourceFilename)) {
|
||||
matchFound = true;
|
||||
String sourcePath = sourceFile.getAbsolutePath();
|
||||
String mergePath = mergeFile.getAbsolutePath();
|
||||
sourceData = Data_2da.load2da(sourcePath, true);
|
||||
mergeData = Data_2da.load2da(mergePath, true);
|
||||
outputData = Data_2da.load2da(sourcePath, true);
|
||||
//Data_2da outputData = sourceData;
|
||||
//get the smallest number of rows
|
||||
int rowCount = sourceData.getEntryCount();
|
||||
if (rowCount > mergeData.getEntryCount())
|
||||
rowCount = mergeData.getEntryCount();
|
||||
|
||||
//check the columns match
|
||||
//or at least the number of them
|
||||
int colCount = sourceData.getLabels().length;
|
||||
if (mergeData.getLabels().length != colCount) {
|
||||
System.out.println("Number of columns does not match!");
|
||||
} else {
|
||||
//loop over the overlapping rows
|
||||
for (int row = 0; row < rowCount; row++) {
|
||||
for (int col = 0; col < colCount; col++) {
|
||||
String columnName = sourceData.getLabels()[col];
|
||||
String sourceEntry = sourceData.getEntry(columnName, row);
|
||||
String mergeEntry = mergeData.getEntry(columnName, row);
|
||||
if (!mergeEntry.equals("****")
|
||||
&& !mergeEntry.equals(sourceEntry)) {
|
||||
outputData.setEntry(columnName, row, mergeEntry);
|
||||
//made a change, log it
|
||||
System.out.println(sourceFilename + " : " + columnName + "," + row + " " + sourceEntry + " -> " + mergeEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
//check if merge has extra rows
|
||||
if (rowCount < mergeData.getEntryCount()) {
|
||||
for (int row = rowCount; row < mergeData.getEntryCount(); row++) {
|
||||
outputData.appendRow();
|
||||
//copy the extra rows to the output
|
||||
for (int col = 0; col < colCount; col++) {
|
||||
String columnName = sourceData.getLabels()[col];
|
||||
String mergeEntry = mergeData.getEntry(columnName, row);
|
||||
if (!mergeEntry.equals("****")) {
|
||||
outputData.setEntry(columnName, row, mergeEntry);
|
||||
//made a change, log it
|
||||
System.out.println(sourceFilename + " : " + columnName + "," + row + " null -> " + mergeEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//finished assembling the output file, write it
|
||||
//this overwrites the target file
|
||||
outputData.save2da(output, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
//end of file loop for
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
"\tjava 2damerge source merge output\n" +
|
||||
"\n" +
|
||||
"This application is designed to take all the 2DA\n" +
|
||||
"files in the source directory, merge them with the\n" +
|
||||
"2DA files in the merge directory, and output the\n" +
|
||||
"edited versions to the output directory"
|
||||
);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
Binary file not shown.
127
nwn/nwnprc/DocGen/trunk/prc/utils/Duplicate2daEntryDetector.java
Normal file
127
nwn/nwnprc/DocGen/trunk/prc/utils/Duplicate2daEntryDetector.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
|
||||
/**
|
||||
* Checks the given column in the given 2da for duplicate entries.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Duplicate2daEntryDetector {
|
||||
|
||||
private static boolean ignoreCase = false;
|
||||
private static boolean accountEmpty = false;
|
||||
|
||||
/**
|
||||
* Ye olde main.
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String filePath = null;
|
||||
ArrayList<String> labels = new ArrayList<String>();
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//[--help] | [-i] pathof2da columnlabel+
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
ignoreCase = true;
|
||||
break;
|
||||
case 'e':
|
||||
accountEmpty = true;
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a pathname
|
||||
if (filePath == null)
|
||||
filePath = param;
|
||||
else
|
||||
labels.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the 2da
|
||||
Data_2da file = Data_2da.load2da(filePath);
|
||||
|
||||
// Test the columns
|
||||
for (String label : labels) {
|
||||
TreeMap<String, ArrayList<Integer>> duplicates = new TreeMap<String, ArrayList<Integer>>();
|
||||
// Examine column
|
||||
HashMap<String, Integer> entries = new HashMap<String, Integer>();
|
||||
String value;
|
||||
for (int i = 0; i < file.getEntryCount(); i++) {
|
||||
value = accountForCase(file, label, i);
|
||||
// Do not account for empty entries unless requested
|
||||
if (value.equals("****") && !accountEmpty)
|
||||
continue;
|
||||
|
||||
if (!entries.containsKey(value))
|
||||
entries.put(value, i);
|
||||
else {
|
||||
// If no duplicates of this value have yet been found, init the arraylist for it
|
||||
if (!duplicates.containsKey(value)) {
|
||||
duplicates.put(value, new ArrayList<Integer>());
|
||||
duplicates.get(value).add(entries.get(value));
|
||||
}
|
||||
// Either way, add the current row to the list of duplicates
|
||||
duplicates.get(value).add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (ArrayList<Integer> duprows : duplicates.values()) {
|
||||
StringBuffer toPrint = new StringBuffer(file.getName() + ": duplicate " + label + " on rows");
|
||||
boolean first = true;
|
||||
for (int row : duprows) {
|
||||
if (!first)
|
||||
toPrint.append(',');
|
||||
else
|
||||
first = false;
|
||||
|
||||
toPrint.append(" " + row);
|
||||
}
|
||||
|
||||
err_pr.println(toPrint.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String accountForCase(Data_2da data, String label, int index) {
|
||||
return ignoreCase ?
|
||||
data.getEntry(label, index).toLowerCase() :
|
||||
data.getEntry(label, index);
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | [-ce] pathof2da columnlabel+\n" +
|
||||
"\n" +
|
||||
" pathof2da path of the 2da to check\n" +
|
||||
" columnlabel label of a column to test for duplicate entries\n" +
|
||||
"\n" +
|
||||
" -c ignores case of the entries testes for duplicacy\n" +
|
||||
" -e does not ignore empty entries. ie, ****\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n" +
|
||||
"\n" +
|
||||
"Unless -e is specified, empty entries (****) do not count as duplicates\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/DuplicateSubradials.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/DuplicateSubradials.class
Normal file
Binary file not shown.
200
nwn/nwnprc/DocGen/trunk/prc/utils/DuplicateSubradials.java
Normal file
200
nwn/nwnprc/DocGen/trunk/prc/utils/DuplicateSubradials.java
Normal file
@@ -0,0 +1,200 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.Data_2da;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A class that performs some validation on spell.2da by checking if it contains duplicated
|
||||
* subradial IDs.
|
||||
* Also has capability to attempt to replace the duplicate IDs with unique ones selected
|
||||
* automatically starting from a given index.
|
||||
*/
|
||||
public class DuplicateSubradials {
|
||||
private static class DuplicateData {
|
||||
int subnum;
|
||||
//Set<Integer> indices = new HashSet<Integer>();
|
||||
List<Integer> indices = new ArrayList<Integer>();
|
||||
|
||||
DuplicateData(int subnum) {
|
||||
this.subnum = subnum;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args The program arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String pathtospells2da = null;
|
||||
boolean fixduplicates = false;
|
||||
int replacementstart = -1;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//[--help] | [-f replacestart] pathtospells2da
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
fixduplicates = true;
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The option to attempt fixing the duplicates is on and the first replacement number hasn't been given yet
|
||||
if (fixduplicates == true && replacementstart == -1) {
|
||||
try {
|
||||
replacementstart = Integer.parseInt(param);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("replacestart value given is not numeric: " + param);
|
||||
readMe();
|
||||
}
|
||||
if (replacementstart < 0 || replacementstart >= 0x10000) {
|
||||
System.out.println("replacestart value given is not in valid range");
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
// It's a pathname
|
||||
else if (pathtospells2da == null)
|
||||
pathtospells2da = param;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the 2da to memory
|
||||
Data_2da spells = Data_2da.load2da(pathtospells2da);
|
||||
Map<Integer, Integer> subrads = new HashMap<Integer, Integer>(); // Map of subradial # to the first line it occurs on
|
||||
Map<Integer, DuplicateData> duplicates = new HashMap<Integer, DuplicateData>();
|
||||
String entry;
|
||||
int subnum = 0;
|
||||
// Parse through the 2da, looking for FeatID references that contain a subradial ID
|
||||
for (int i = 0; i < spells.getEntryCount(); i++) {
|
||||
entry = spells.getEntry("FeatID", i);
|
||||
// Skip blanks
|
||||
if (entry.equals("****")) continue;
|
||||
try {
|
||||
subnum = Integer.parseInt(entry);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Corrupt value in FeatID on row " + i + ": " + entry);
|
||||
continue;
|
||||
}
|
||||
// Skip non-subradial FeatIDs
|
||||
if (subnum < 0x10000) continue;
|
||||
subnum = subnum >>> 16;
|
||||
|
||||
if (subrads.containsKey(subnum)) {
|
||||
if (!duplicates.containsKey(subnum))
|
||||
duplicates.put(subnum, new DuplicateData(subnum));
|
||||
|
||||
duplicates.get(subnum).indices.add(i);
|
||||
} else subrads.put(subnum, i);
|
||||
}
|
||||
|
||||
// Print the results
|
||||
int requiredtofix = 0;
|
||||
for (DuplicateData dup : duplicates.values()) {
|
||||
System.out.println("Duplicate subradial ID: " + dup.subnum + " first occurrence on row " + subrads.get(dup.subnum));
|
||||
for (int i : dup.indices)
|
||||
System.out.println("Duplicate subradial ID: " + dup.subnum + " on row " + i);
|
||||
requiredtofix += dup.indices.size();
|
||||
}
|
||||
if (requiredtofix > 0)
|
||||
System.out.println("\nNumber of new subradial IDs required to make all unique: " + requiredtofix);
|
||||
|
||||
if (fixduplicates && requiredtofix > 0) {
|
||||
System.out.println("\n\nAttempting to fix.");
|
||||
|
||||
// Construct a list of the replacement subradial IDs
|
||||
List<Integer> replacementlist = new ArrayList<Integer>();
|
||||
int replacementid = replacementstart;
|
||||
while (replacementlist.size() < requiredtofix) {
|
||||
if (replacementid >= 0x10000) {// Make sure we don't exceed the bounds
|
||||
System.out.println("Not enough free subradial IDs in the range from " + replacementstart + " to " + 0x10000 + "!");
|
||||
System.exit(1);
|
||||
}
|
||||
// Pick ones not already in use
|
||||
if (!subrads.containsKey(replacementid))
|
||||
replacementlist.add(replacementid);
|
||||
|
||||
replacementid++;
|
||||
}
|
||||
|
||||
// Loop over the duplicates, fixing as we go
|
||||
Iterator<Integer> replacements = replacementlist.iterator();
|
||||
int featid;
|
||||
for (DuplicateData dup : duplicates.values()) {
|
||||
for (int i : dup.indices) {
|
||||
// Extract the base featID. Low 16 bits
|
||||
featid = Integer.parseInt(spells.getEntry("FeatID", i)) & 0x0000FFFF;
|
||||
// Insert new subradial number
|
||||
subnum = replacements.next();
|
||||
featid = featid | (subnum << 16);
|
||||
|
||||
// Store the new subradial'd featid in spells.2da
|
||||
spells.setEntry("FeatID", i, Integer.toString(featid));
|
||||
}
|
||||
}
|
||||
|
||||
// Save the 2da
|
||||
try {
|
||||
spells.save2da((new File(pathtospells2da)).getParent(), true, true);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error while saving spells.2da!\n" + e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// List the used subradial IDs
|
||||
System.out.println("Subradial IDs used:");
|
||||
Integer prev = null;
|
||||
for (Integer subrad : replacementlist) {
|
||||
// Detect if a new range is starting
|
||||
if (prev == null || // Special case - just starting
|
||||
subrad != (prev + 1) // There's a break in the series
|
||||
) {
|
||||
// Print the end of previous range
|
||||
if (prev != null)
|
||||
System.out.println(prev);
|
||||
|
||||
// Print the start of the new range
|
||||
System.out.print(subrad + " - ");
|
||||
}
|
||||
|
||||
// Update prev
|
||||
prev = subrad;
|
||||
}
|
||||
|
||||
// Print the end of the last range
|
||||
System.out.println(prev);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | [-f replacestart] pathtospells2da\n" +
|
||||
"\n" +
|
||||
" pathtospells2da path of the spells.2da to check\n" +
|
||||
" replacestart the first subradial ID to replace duplicates\n" +
|
||||
" with when fixing. optional, required if -f is set\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n" +
|
||||
" -f attempt to replace the duplicate subradial IDs with new\n" +
|
||||
" unused IDs starting with the value given as replacestart\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Looks for duplicate subradial IDs in the FeatID column of the given\n" +
|
||||
"spells.2da. May optionally attempt to replace the duplicates with unique\n" +
|
||||
"values.\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ItempropMaker.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ItempropMaker.class
Normal file
Binary file not shown.
278
nwn/nwnprc/DocGen/trunk/prc/utils/ItempropMaker.java
Normal file
278
nwn/nwnprc/DocGen/trunk/prc/utils/ItempropMaker.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import static prc.Main.verbose;
|
||||
|
||||
public final class ItempropMaker {
|
||||
private ItempropMaker() {
|
||||
}
|
||||
|
||||
|
||||
private static Data_2da itempropdef2da;
|
||||
private static Data_2da costtable2da;
|
||||
private static Data_2da paramtable2da;
|
||||
private static Data_2da[] cost2daarray;
|
||||
private static Data_2da[] param12daarray;
|
||||
private static StringBuilder xml;
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
//load the 2das
|
||||
itempropdef2da = Data_2da.load2da("2das" + File.separator + "itempropdef.2da", true);
|
||||
costtable2da = Data_2da.load2da("2das" + File.separator + "iprp_costtable.2da", true);
|
||||
paramtable2da = Data_2da.load2da("2das" + File.separator + "iprp_paramtable.2da", true);
|
||||
cost2daarray = new Data_2da[costtable2da.getEntryCount()];
|
||||
param12daarray = new Data_2da[paramtable2da.getEntryCount()];
|
||||
for (int i = 0; i < cost2daarray.length; i++) {
|
||||
cost2daarray[i] = Data_2da.load2da("2das" + File.separator + costtable2da.getBiowareEntry("Name", i) + ".2da", true);
|
||||
}
|
||||
for (int i = 0; i < param12daarray.length; i++) {
|
||||
param12daarray[i] = Data_2da.load2da("2das" + File.separator + paramtable2da.getBiowareEntry("TableResRef", i) + ".2da", true);
|
||||
}
|
||||
//loop over each row
|
||||
for (int itempropdef2darow = 85;
|
||||
itempropdef2darow < itempropdef2da.getEntryCount();
|
||||
itempropdef2darow++) {
|
||||
if (itempropdef2da.getBiowareEntryAsInt("Name", itempropdef2darow) != 0) {
|
||||
int type = itempropdef2darow;
|
||||
int subtype;
|
||||
int cost;
|
||||
int param1;
|
||||
if (itempropdef2da.getBiowareEntry("SubTypeResRef", type) == "")
|
||||
subtype = 0;
|
||||
else
|
||||
subtype = 1;
|
||||
if (itempropdef2da.getBiowareEntryAsInt("CostTableResRef", type) == 0)
|
||||
cost = 0;
|
||||
else
|
||||
cost = 1;
|
||||
if (itempropdef2da.getBiowareEntry("Param1ResRef", type) == "")
|
||||
param1 = 0;
|
||||
else
|
||||
param1 = 1;
|
||||
//loop over each subtype
|
||||
if (subtype != 0) {
|
||||
Data_2da subtype2da = Data_2da.load2da("2das" + File.separator + itempropdef2da.getBiowareEntry("SubTypeResRef", type) + ".2da", true);
|
||||
|
||||
for (int subtypeID = 0; subtypeID < subtype2da.getEntryCount(); subtypeID++) {
|
||||
//loop over the param1s, if applicable
|
||||
//look if there is a column for it
|
||||
boolean subtypeparam1columnexists = false;
|
||||
String[] columnlabels = subtype2da.getLabels();
|
||||
for (int i = 0; i < columnlabels.length; i++) {
|
||||
if (columnlabels[i] == "Param1ResRef")
|
||||
subtypeparam1columnexists = true;
|
||||
}
|
||||
if (subtypeparam1columnexists
|
||||
&& subtype2da.getBiowareEntry("Param1ResRef", subtypeID) == "") {
|
||||
param1 = 1;
|
||||
} else {
|
||||
if (itempropdef2da.getBiowareEntry("Param1ResRef", type) == "")
|
||||
param1 = 0;
|
||||
else
|
||||
param1 = 2;
|
||||
}
|
||||
if (param1 != 0) {
|
||||
int param1tableid = 0;
|
||||
if (param1 == 2)
|
||||
param1tableid = itempropdef2da.getBiowareEntryAsInt("Param1ResRef", type);
|
||||
else if (param1 == 1)
|
||||
param1tableid = subtype2da.getBiowareEntryAsInt("Param1ResRef", subtypeID);
|
||||
Data_2da param12da = param12daarray[param1tableid];
|
||||
for (int param1ID = 0; param1ID < param12da.getEntryCount(); param1ID++) {
|
||||
if (cost != 0) {
|
||||
int costtable = itempropdef2da.getBiowareEntryAsInt("CostTableResRef", type);
|
||||
Data_2da cost2da = cost2daarray[costtable];
|
||||
//has type, subtype, param1, and cost
|
||||
write(type, subtypeID, param1tableid, param1ID, costtable, cost2da.getEntryCount());
|
||||
} else {
|
||||
//no cost
|
||||
//has type, subtype, and param1
|
||||
write(type, subtypeID, param1tableid, param1ID, -1, -1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//no param1
|
||||
if (cost != 0) {
|
||||
int costtable = itempropdef2da.getBiowareEntryAsInt("CostTableResRef", type);
|
||||
Data_2da cost2da = cost2daarray[costtable];
|
||||
//has type, subtype, and cost
|
||||
write(type, subtypeID, -1, -1, costtable, cost2da.getEntryCount());
|
||||
} else {
|
||||
//no cost
|
||||
//has type, and subtype
|
||||
write(type, subtypeID, -1, -1, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//no subtype
|
||||
if (param1 != 0) {
|
||||
int param1tableid = itempropdef2da.getBiowareEntryAsInt("Param1ResRef", type);
|
||||
Data_2da param12da = param12daarray[param1tableid];
|
||||
for (int param1ID = 0; param1ID < param12da.getEntryCount(); param1ID++) {
|
||||
if (cost != 0) {
|
||||
int costtable = itempropdef2da.getBiowareEntryAsInt("CostTableResRef", type);
|
||||
Data_2da cost2da = cost2daarray[costtable];
|
||||
//has type, param1, and cost
|
||||
write(type, -1, param1tableid, param1ID, costtable, cost2da.getEntryCount());
|
||||
} else {
|
||||
//no cost
|
||||
//has type, and param1
|
||||
write(type, -1, param1tableid, param1ID, -1, -1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//no param1
|
||||
if (cost != 0) {
|
||||
int costtable = itempropdef2da.getBiowareEntryAsInt("CostTableResRef", type);
|
||||
Data_2da cost2da = cost2daarray[costtable];
|
||||
//has type, and cost
|
||||
write(type, -1, -1, -1, costtable, cost2da.getEntryCount());
|
||||
} else {
|
||||
//no cost
|
||||
//has type
|
||||
write(type, -1, -1, -1, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
<!-- This file was generated by the NWNTools GFF to XML writer.
|
||||
http://nwntools.sf.net/
|
||||
** Do not hand edit unless you know what you are doing. **
|
||||
|
||||
-->
|
||||
- <gff name="master111.uti" type="UTI" version="V3.2">
|
||||
- <struct id="-1">
|
||||
<element name="TemplateResRef" type="11" value="master111" />
|
||||
<element name="BaseItem" type="5" value="111" />
|
||||
<element name="LocalizedName" type="12" value="83617" />
|
||||
<element name="Description" type="12" value="-1" />
|
||||
<element name="DescIdentified" type="12" value="-1" />
|
||||
<element name="Tag" type="10" value="master111" />
|
||||
<element name="Charges" type="0" value="0" />
|
||||
<element name="Cost" type="4" value="2" />
|
||||
<element name="Stolen" type="0" value="0" />
|
||||
<element name="StackSize" type="2" value="1" />
|
||||
<element name="Plot" type="0" value="0" />
|
||||
<element name="AddCost" type="4" value="0" />
|
||||
<element name="Identified" type="0" value="1" />
|
||||
<element name="Cursed" type="0" value="0" />
|
||||
<element name="ModelPart1" type="0" value="11" />
|
||||
<element name="ModelPart2" type="0" value="11" />
|
||||
<element name="ModelPart3" type="0" value="11" />
|
||||
- <element name="PropertiesList" type="15">
|
||||
<struct id="0" >
|
||||
<element name="PropertyName" type="2" value="85" />
|
||||
<element name="Subtype" type="2" value="6" />
|
||||
<element name="CostTable" type="0" value="28" />
|
||||
<element name="CostValue" type="2" value="0" />
|
||||
<element name="Param1" type="0" value="0" />
|
||||
<element name="Param1Value" type="0" value="0" />
|
||||
<element name="ChanceAppear" type="0" value="100" />
|
||||
</struct>
|
||||
- <struct id="0">
|
||||
<element name="PropertyName" type="2" value="12" />
|
||||
<element name="Subtype" type="2" value="37" />
|
||||
<element name="CostTable" type="0" value="0" />
|
||||
<element name="CostValue" type="2" value="0" />
|
||||
<element name="Param1" type="0" value="255" />
|
||||
<element name="Param1Value" type="0" value="0" />
|
||||
<element name="ChanceAppear" type="0" value="100" />
|
||||
</struct>
|
||||
</element>
|
||||
<element name="PaletteID" type="0" value="47" />
|
||||
<element name="Comment" type="10" value="" />
|
||||
</struct>
|
||||
</gff>
|
||||
*/
|
||||
private static void write(int type, int subtype, int param1table, int param1value, int costtable,
|
||||
int costmax) throws Exception {
|
||||
|
||||
xml = new StringBuilder(0xFFFFF);
|
||||
//assemble the resref/tag
|
||||
String resref = "prc_ip" + type;
|
||||
if (subtype != -1)
|
||||
resref += "_" + subtype;
|
||||
if (param1value != -1)
|
||||
resref += "_" + param1value;
|
||||
//sanity checks
|
||||
if (param1value == -1)
|
||||
param1value = 0;
|
||||
if (param1table == -1)
|
||||
param1table = 255;
|
||||
if (subtype == -1)
|
||||
subtype = 0;
|
||||
if (costtable == -1)
|
||||
costtable = 0;
|
||||
if (costmax == -1)
|
||||
costmax = 0;
|
||||
//output stuff
|
||||
//header things first
|
||||
xml.append("<gff name=\"" + resref + ".uti\" type=\"UTI \" version=\"V3.2\">\n");
|
||||
xml.append(" <struct id=\"-1\">\n");
|
||||
xml.append(" <element name=\"TemplateResRef\" type=\"11\" value=\"" + resref + "\" />\n");
|
||||
xml.append(" <element name=\"BaseItem\" type=\"5\" value=\"78\" />\n");
|
||||
xml.append(" <element name=\"LocalizedName\" type=\"12\" value=\"-1\" >\n");
|
||||
xml.append(" <localString languageId=\"0\" value=\"0\" />\n");
|
||||
xml.append(" </element>\n");
|
||||
xml.append(" <element name=\"Description\" type=\"12\" value=\"-1\" />\n");
|
||||
xml.append(" <element name=\"DescIdentified\" type=\"12\" value=\"-1\" />\n");
|
||||
xml.append(" <element name=\"Tag\" type=\"10\" value=\"" + resref + "\" />\n");
|
||||
xml.append(" <element name=\"Charges\" type=\"0\" value=\"0\" />\n");
|
||||
xml.append(" <element name=\"Cost\" type=\"4\" value=\"2\" />\n");
|
||||
xml.append(" <element name=\"Stolen\" type=\"0\" value=\"0\" />\n");
|
||||
xml.append(" <element name=\"StackSize\" type=\"2\" value=\"1\" />\n");
|
||||
xml.append(" <element name=\"Plot\" type=\"0\" value=\"0\" />\n");
|
||||
xml.append(" <element name=\"AddCost\" type=\"4\" value=\"0\" />\n");
|
||||
xml.append(" <element name=\"Identified\" type=\"0\" value=\"1\" />\n");
|
||||
xml.append(" <element name=\"Cursed\" type=\"0\" value=\"0\" />\n");
|
||||
xml.append(" <element name=\"ModelPart1\" type=\"0\" value=\"1\" />\n");
|
||||
xml.append(" <element name=\"PropertiesList\" type=\"15\">\n");
|
||||
//loop over the itemproperties
|
||||
for (int i = 0; i < costmax; i++) {
|
||||
xml.append(" <struct id=\"0\" >\n");
|
||||
xml.append(" <element name=\"PropertyName\" type=\"2\" value=\"" + type + "\" />\n");
|
||||
xml.append(" <element name=\"Subtype\" type=\"2\" value=\"" + subtype + "\" />\n");
|
||||
xml.append(" <element name=\"CostTable\" type=\"0\" value=\"" + costtable + "\" />\n");
|
||||
xml.append(" <element name=\"CostValue\" type=\"2\" value=\"" + i + "\" />\n");
|
||||
xml.append(" <element name=\"Param1\" type=\"0\" value=\"" + param1table + "\" />\n");
|
||||
xml.append(" <element name=\"Param1Value\" type=\"0\" value=\"" + param1value + "\" />\n");
|
||||
xml.append(" <element name=\"ChanceAppear\" type=\"0\" value=\"100\" />\n");
|
||||
xml.append(" </struct>\n");
|
||||
}
|
||||
//footer stuff
|
||||
xml.append(" </element>\n");
|
||||
//this is set to 99 so it will not appear in the palette :)
|
||||
xml.append(" <element name=\"PaletteID\" type=\"0\" value=\"99\" />\n");
|
||||
xml.append(" <element name=\"Comment\" type=\"10\" value=\"\" />\n");
|
||||
xml.append(" </struct>\n");
|
||||
xml.append("</gff>");
|
||||
|
||||
File target = new File("xml_temp" + File.separator + resref + ".uti.xml");
|
||||
// Clean up old version if necessary
|
||||
if (target.exists()) {
|
||||
if (verbose) System.out.println("Deleting previous version of " + target.getName());
|
||||
target.delete();
|
||||
}
|
||||
if (verbose) System.out.println("Writing brand new version of " + target.getName());
|
||||
target.createNewFile();
|
||||
|
||||
// Creater the writer and print
|
||||
FileWriter writer = new FileWriter(target, true);
|
||||
writer.write(xml.toString());
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
// Force garbage collection
|
||||
System.gc();
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/LetoListsGenerator.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/LetoListsGenerator.class
Normal file
Binary file not shown.
137
nwn/nwnprc/DocGen/trunk/prc/utils/LetoListsGenerator.java
Normal file
137
nwn/nwnprc/DocGen/trunk/prc/utils/LetoListsGenerator.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
|
||||
/**
|
||||
* A class for generating Leto XML files from 2da and TLK.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public final class LetoListsGenerator {
|
||||
private final Data_TLK defaultTLK;
|
||||
private final Data_TLK userTLK;
|
||||
|
||||
private LetoListsGenerator(Data_TLK defaultTLK, Data_TLK userTLK) {
|
||||
this.defaultTLK = defaultTLK;
|
||||
this.userTLK = userTLK;
|
||||
}
|
||||
|
||||
private String getTLK(int num) {
|
||||
return num < 0x01000000 ? defaultTLK.getEntry(num) : userTLK.getEntry(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the given 2da into a Leto XML file.
|
||||
*
|
||||
* @param toPrint Data_2da containing the 2da to print
|
||||
* @param nameColumn The name of the column that defines the name of the entry in TLK
|
||||
* @param os The outputstream to write the xml to
|
||||
*/
|
||||
public void printData2daAsLetoXML(Data_2da toPrint, String nameColumn, OutputStream os) {
|
||||
PrintStream ps = new PrintStream(os, true);
|
||||
StringBuilder sb;
|
||||
// Print header
|
||||
ps.println("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
|
||||
ps.println("<LetoList comment=\"Created with a Java-based tool\">");
|
||||
|
||||
// Print contents
|
||||
for (int i = 0; i < toPrint.getEntryCount(); i++) {
|
||||
if (!toPrint.getBiowareEntry(nameColumn, i).equals("")) {
|
||||
sb = new StringBuilder(" <item index=\"" + i + "\" ");
|
||||
for (String column : toPrint.getLabels()) {
|
||||
sb.append(column.toLowerCase() + "=\"" + toPrint.getBiowareEntry(column, i) + "\" ");
|
||||
}
|
||||
|
||||
if (!getTLK(Integer.parseInt(toPrint.getBiowareEntry(nameColumn, i))).equals(""))
|
||||
sb.append(">" + getTLK(Integer.parseInt(toPrint.getBiowareEntry(nameColumn, i))) + "</item>");
|
||||
else
|
||||
sb.append("/>");
|
||||
|
||||
ps.println(sb);
|
||||
}
|
||||
}
|
||||
|
||||
// Print closing tag
|
||||
ps.println("</LetoList>");
|
||||
|
||||
ps.flush();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ye olde main methode.
|
||||
*
|
||||
* @param args The parameters
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
if (args.length == 0) readMe();
|
||||
String defaultTLKPath = null;
|
||||
String userTLKPath = null;
|
||||
ArrayList<String> twoDANames = new ArrayList<String>();
|
||||
ArrayList<String> columnNames = new ArrayList<String>();
|
||||
|
||||
for (String param : args) {//[-crmnqs] file... | -
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
|
||||
default:
|
||||
err_pr.println("Error: Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (defaultTLKPath == null)
|
||||
defaultTLKPath = param;
|
||||
else if (userTLKPath == null)
|
||||
userTLKPath = param;
|
||||
else {
|
||||
if (twoDANames.size() == columnNames.size())
|
||||
twoDANames.add(param);
|
||||
else
|
||||
columnNames.add(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultTLKPath == null || userTLKPath == null || twoDANames.size() != columnNames.size()) {
|
||||
System.err.println("Error! Missing parameters");
|
||||
readMe();
|
||||
}
|
||||
|
||||
LetoListsGenerator llg = new LetoListsGenerator(new Data_TLK(defaultTLKPath), new Data_TLK(userTLKPath));
|
||||
Data_2da twoDA;
|
||||
for (int i = 0; i < twoDANames.size(); i++) {
|
||||
twoDA = Data_2da.load2da(twoDANames.get(i));
|
||||
llg.printData2daAsLetoXML(twoDA, columnNames.get(i), new FileOutputStream("nwn-" + twoDA.getName().toLowerCase() + ".xml"));
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" pathToDefaultTLK pathToUserTLK [pathTo2da namecolumn]+\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Creates xml files for use with Leto editor based on the given files.\n" +
|
||||
"Requires default.tlk, an user tlk and any numbers of 2da and column\n" +
|
||||
"name pairs. The column name is used for fetching the name of the line\n" +
|
||||
"from TLK.\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/List2daEntries.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/List2daEntries.class
Normal file
Binary file not shown.
94
nwn/nwnprc/DocGen/trunk/prc/utils/List2daEntries.java
Normal file
94
nwn/nwnprc/DocGen/trunk/prc/utils/List2daEntries.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.Main;
|
||||
import prc.autodoc.Data_2da;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A class that lists the unique entries found in the given column of the given 2da file.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class List2daEntries {
|
||||
|
||||
/**
|
||||
* Ye olde main.
|
||||
*
|
||||
* @param args Program arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String filePath = null;
|
||||
ArrayList<String> labels = new ArrayList<String>();
|
||||
boolean quiet = false;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//[--help] | pathof2da columnlabel+
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a pathname
|
||||
if (filePath == null)
|
||||
filePath = param;
|
||||
else
|
||||
labels.add(param);
|
||||
}
|
||||
}
|
||||
|
||||
if (quiet) {
|
||||
Main.verbose = false;
|
||||
Main.spinner.disable();
|
||||
}
|
||||
|
||||
// Load the 2da
|
||||
Data_2da file = Data_2da.load2da(filePath);
|
||||
|
||||
// Loop over the columns
|
||||
for (String label : labels) {
|
||||
Set<String> entries = new HashSet<String>();
|
||||
String value;
|
||||
|
||||
for (int i = 0; i < file.getEntryCount(); i++) {
|
||||
value = file.getEntry(label, i);
|
||||
|
||||
entries.add(value);
|
||||
}
|
||||
|
||||
StringBuffer toPrint = new StringBuffer(quiet ? "" : (file.getName() + ": entries on column " + label + "\n"));
|
||||
for (String entry : entries) {
|
||||
toPrint.append(entry + "\n");
|
||||
}
|
||||
|
||||
System.out.println(toPrint.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | [-q] pathof2da columnlabel+\n" +
|
||||
"\n" +
|
||||
" pathof2da path of the 2da to check\n" +
|
||||
" columnlabel label of a column to list entries of\n" +
|
||||
"\n" +
|
||||
" -q silent mode. Only prints the results" +
|
||||
" --help prints this text\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ListSubradials.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ListSubradials.class
Normal file
Binary file not shown.
110
nwn/nwnprc/DocGen/trunk/prc/utils/ListSubradials.java
Normal file
110
nwn/nwnprc/DocGen/trunk/prc/utils/ListSubradials.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.Data_2da;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A class that parses spells.2da and lists used subradial feat ID ranges.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class ListSubradials {
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args The program arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String pathtospells2da = null;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//[--help] | pathtospells2da
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
default:
|
||||
System.out.println("Unknown parameter: " + c);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// It's a pathname
|
||||
if (pathtospells2da == null)
|
||||
pathtospells2da = param;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the 2da to memory
|
||||
Data_2da feats = Data_2da.load2da(pathtospells2da);
|
||||
TreeSet<Integer> subrads = new TreeSet<Integer>();
|
||||
String entry;
|
||||
int subnum;
|
||||
// Parse through the 2da, looking for FeatID references that contain a subradial ID
|
||||
for (int i = 0; i < feats.getEntryCount(); i++) {
|
||||
entry = feats.getEntry("FeatID", i);
|
||||
// Skip blanks
|
||||
if (entry.equals("****")) continue;
|
||||
try {
|
||||
subnum = Integer.parseInt(entry);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Corrupt value in FeatID on row " + i + ": " + entry);
|
||||
continue;
|
||||
}
|
||||
// Skip non-subradial FeatIDs
|
||||
if (subnum < 0x10000) continue;
|
||||
subnum = subnum >>> 16;
|
||||
|
||||
subrads.add(subnum);
|
||||
}
|
||||
|
||||
// Print the results
|
||||
System.out.println("Subradial IDs used:");
|
||||
if (subrads.isEmpty())
|
||||
System.out.println("None");
|
||||
else {
|
||||
Integer prev = null;
|
||||
for (Integer subrad : subrads) {
|
||||
// Detect if a new range is starting
|
||||
if (prev == null || // Special case - just starting
|
||||
subrad != (prev + 1) // There's a break in the series
|
||||
) {
|
||||
// Print the end of previous range
|
||||
if (prev != null)
|
||||
System.out.println(prev);
|
||||
|
||||
// Print the start of the new range
|
||||
System.out.print(subrad + " - ");
|
||||
}
|
||||
|
||||
// Update prev
|
||||
prev = subrad;
|
||||
}
|
||||
|
||||
// Print the end of the last range
|
||||
System.out.println(prev);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | pathtospells2da\n" +
|
||||
"\n" +
|
||||
" pathtospells2da path of the spells.2da to check\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Lists used subradial ID ranges in the FeatID column of the given spells.2da\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/NPCEvolve.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/NPCEvolve.class
Normal file
Binary file not shown.
188
nwn/nwnprc/DocGen/trunk/prc/utils/NPCEvolve.java
Normal file
188
nwn/nwnprc/DocGen/trunk/prc/utils/NPCEvolve.java
Normal file
@@ -0,0 +1,188 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.Random;
|
||||
|
||||
public final class NPCEvolve {
|
||||
private NPCEvolve() {
|
||||
}
|
||||
|
||||
private static final int countAreas = 5;
|
||||
private static final int countClasses = 11;
|
||||
private static final int countPackages = 10;
|
||||
public static Random rng = new Random();
|
||||
|
||||
/**
|
||||
* The main method, as usual.
|
||||
*
|
||||
* @param args do I really need to explain this?
|
||||
* @throws Exception this is a simple tool, just let all failures blow up
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 3 || args[0].equals("--help") || args[0].equals("-?"))
|
||||
readMe();
|
||||
|
||||
String logFilePath = args[0];
|
||||
String packageFilePath = args[1];
|
||||
String outputFilePath = args[2];
|
||||
|
||||
//this is the layout of the data string
|
||||
//## id class0pack1 class0pack2 ... class10pack9 class10pack10 ##
|
||||
//get the file
|
||||
File logFile = new File(logFilePath);
|
||||
BufferedReader reader = new BufferedReader(new FileReader(logFile));
|
||||
//parse it
|
||||
String line = reader.readLine();
|
||||
int[][][] dataset = new int[countAreas][countClasses][countPackages];
|
||||
int classID = 0;
|
||||
int packageID = 0;
|
||||
int areaID = 0;
|
||||
int score = 0;
|
||||
int countArea = 0;
|
||||
while (line != null) {
|
||||
if (line.matches("## ([0-9]*) [0-9 ]* ##")) {
|
||||
areaID = new Integer(line.substring(4, 6));
|
||||
//remove the +1 offset
|
||||
areaID--;
|
||||
//store highest area value
|
||||
if (areaID > countArea)
|
||||
countArea = areaID;
|
||||
classID = 0;
|
||||
packageID = 0;
|
||||
line = line.substring(7, line.length() - 3);
|
||||
String[] splitline = line.split(" ");
|
||||
for (int i = 0; i < splitline.length; i++) {
|
||||
score = new Integer(splitline[i]);
|
||||
dataset[areaID][classID][packageID] = new Integer(splitline[i]);
|
||||
//System.out.println("dataset["+areaID+"]["+classID+"]["+packageID+"] = "+dataset[areaID][classID][packageID]);
|
||||
//move to next slot
|
||||
packageID++;
|
||||
if (packageID >= countPackages) {
|
||||
packageID -= countPackages;
|
||||
classID++;
|
||||
if (classID >= countClasses)
|
||||
classID -= countClasses;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
line = reader.readLine();
|
||||
}
|
||||
//At this point, we have a big dataset with the most recent
|
||||
//scores for each area for each class/package combination
|
||||
//First step is to consolidate this to an average
|
||||
int[][] data = new int[countClasses][countPackages];
|
||||
for (classID = 0; classID < countClasses; classID++) {
|
||||
for (packageID = 0; packageID < countPackages; packageID++) {
|
||||
//reset score to zero
|
||||
score = 0;
|
||||
for (areaID = 0; areaID < countArea; areaID++) {
|
||||
score += dataset[areaID][classID][packageID];
|
||||
}
|
||||
data[classID][packageID] = score / countArea;
|
||||
System.out.println("data[" + classID + "][" + packageID + "] = " + data[classID][packageID]);
|
||||
}
|
||||
}
|
||||
|
||||
//now we know what each packageset scored, go through each class and cross the best 2 to
|
||||
//make the next generation
|
||||
for (classID = 0; classID < countClasses; classID++) {
|
||||
int packageMother = 0;
|
||||
int packageFather = 0;
|
||||
int scoreMother = 0;
|
||||
int scoreFather = 0;
|
||||
for (packageID = 0; packageID < countPackages; packageID++) {
|
||||
score = data[classID][packageID];
|
||||
if (score > scoreMother) {
|
||||
scoreFather = scoreMother;
|
||||
scoreMother = score;
|
||||
packageFather = packageMother;
|
||||
packageMother = packageID;
|
||||
} else if (score > scoreFather) {
|
||||
scoreFather = score;
|
||||
packageFather = packageID;
|
||||
}
|
||||
}
|
||||
//now we have a mother and a father packageset
|
||||
//remember, these are sets of packages, not the actual packages themselves
|
||||
//load the 2das
|
||||
String filename = "";
|
||||
filename = "evopset_" + classID + "_";
|
||||
//if(packageMother<10)
|
||||
// filename += "0";
|
||||
filename += "" + packageMother;
|
||||
Data_2da motherpackset2da = Data_2da.load2da(packageFilePath + File.separator + filename + ".2da");
|
||||
filename = "evopset_" + classID + "_";
|
||||
//if(packageFather<10)
|
||||
// filename += "0";
|
||||
filename += "" + packageFather;
|
||||
Data_2da fatherpackset2da = Data_2da.load2da(packageFilePath + File.separator + filename + ".2da");
|
||||
//create the output 2das
|
||||
for (int i = 0; i < countPackages; i++) {
|
||||
filename = "evopset_" + classID + "_";
|
||||
//if(i<10)
|
||||
// filename += "0";
|
||||
filename += i;
|
||||
Data_2da offspringpackset2da = new Data_2da(filename);
|
||||
offspringpackset2da.addColumn("PackOffset");
|
||||
int parentToUse = 1;
|
||||
for (int row = 0; row < 40; row++) {
|
||||
offspringpackset2da.appendRow();
|
||||
//1 in 10 chance to flip between parents
|
||||
if (rng.nextInt(10) == 0) {
|
||||
if (parentToUse == 1)
|
||||
parentToUse = 2;
|
||||
else if (parentToUse == 2)
|
||||
parentToUse = 1;
|
||||
}
|
||||
if (parentToUse == 1) {
|
||||
//copy from mother
|
||||
String value = motherpackset2da.getEntry("PackOffset", row);
|
||||
//mutation chance
|
||||
if (rng.nextInt(10) == 0) {
|
||||
value = "" + (rng.nextInt(10) + 1);
|
||||
}
|
||||
offspringpackset2da.setEntry("PackOffset", row, value);
|
||||
} else if (parentToUse == 2) {
|
||||
//copy from father
|
||||
String value = fatherpackset2da.getEntry("PackOffset", row);
|
||||
//mutation chance
|
||||
if (rng.nextInt(10) == 0) {
|
||||
value = "" + (rng.nextInt(10) + 1);
|
||||
}
|
||||
offspringpackset2da.setEntry("PackOffset", row, value);
|
||||
}
|
||||
}
|
||||
//now write it to the disk
|
||||
offspringpackset2da.save2da(outputFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
//pastebin for later ;)
|
||||
//first thing is load the overall packages.2da file
|
||||
//Data_2da packages2da = Data_2da.load2da(packageFilePath+File.separator+"packages.2da");
|
||||
/*
|
||||
//get the real package IDs
|
||||
packageMother += (countPackages*classID);
|
||||
packageFather += (countPackages*classID);
|
||||
//EvoPSP
|
||||
//EvoPFTBard01
|
||||
//EvoPSP*/
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
"\tjava npcevol logfile packages\n" +
|
||||
"\n" +
|
||||
"This application is designed to take a logfile \n" +
|
||||
"and parse it to extract relevant data.\n" +
|
||||
"Then it will take some package 2da files\n" +
|
||||
"and mutate them appropriately"
|
||||
);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$1.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$1.class
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user