mirror of
http://prc.nwn.ee:3000/Jaysyn/PRC8.git
synced 2025-12-26 19:47:15 -05:00
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/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.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$2.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$2.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$3.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$3.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$4.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen$4.class
Normal file
Binary file not shown.
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen.class
Normal file
Binary file not shown.
376
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen.java
Normal file
376
nwn/nwnprc/DocGen/trunk/prc/utils/Precache2daGen.java
Normal file
@@ -0,0 +1,376 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
|
||||
/**
|
||||
* A class that parses 2das and determines which rows need to be
|
||||
* cached for the spells / powers to work fast.
|
||||
*
|
||||
* @author Heikki 'Ornedan' Aitakangas
|
||||
*/
|
||||
public class Precache2daGen {
|
||||
private static String path2daDir = null;
|
||||
private static final Data_2da output = new Data_2da("precacherows");
|
||||
|
||||
static {
|
||||
output.addColumn("RowNum");
|
||||
output.addColumn("Type");
|
||||
}
|
||||
|
||||
private static Data_2da spells = null/*,
|
||||
feat = null*/;
|
||||
|
||||
private static int normalSpellMaxRow = 4200;
|
||||
|
||||
/**
|
||||
* Ye olde maine methode.
|
||||
*
|
||||
* @param args The program arguments
|
||||
* @throws Throwable Any problems just crash the program
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
// parse args
|
||||
for (int i = 0; i < args.length; i++) {//[--help] | [--normalspellsmax #] pathto2dadir
|
||||
// Parameter parseage
|
||||
String param = args[i];
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else if (param.equals("--normalspellsmax")) {
|
||||
try {
|
||||
normalSpellMaxRow = Integer.parseInt(args[++i]);
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Invalid number given with parameter --normalspellsmax");
|
||||
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 (path2daDir == null)
|
||||
path2daDir = param;
|
||||
}
|
||||
}
|
||||
|
||||
if (path2daDir == null)
|
||||
readMe();
|
||||
|
||||
// Load a directory listing
|
||||
File dir = new File(path2daDir);
|
||||
if (!dir.isDirectory()) {
|
||||
err_pr.println("Error: Not a directory: " + path2daDir);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Load the main 2das
|
||||
spells = Data_2da.load2da(dir.getPath() + File.separator + "spells.2da");
|
||||
//feat = Data_2da.load2da(dir.getPath() + File.separator + "feat.2da");
|
||||
|
||||
handleNormalSpells();
|
||||
//should generalise all of the AMS ones later - Flaming_Sword
|
||||
handlePsionics(dir);
|
||||
handleTruenaming(dir);
|
||||
handleTob(dir);
|
||||
handleInvocations(dir);
|
||||
handleNewSpells();
|
||||
|
||||
output.appendRow();
|
||||
|
||||
output.save2da(".", false, true);
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
System.out.println("Usage:\n" +
|
||||
" [--help] | [--normalspellsmax #] pathto2dadir\n" +
|
||||
"\n" +
|
||||
" pathto2dadir path of the directory containing the 2das that will be parsed\n" +
|
||||
"\n" +
|
||||
" normalspellsmax The greatest index to which the normal spells seek will\n" +
|
||||
" reach to. Defaults to 5000\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
" --help prints this text\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void handleNormalSpells() {
|
||||
int temp;
|
||||
for (int i = 0; i < normalSpellMaxRow; i++) {
|
||||
if (// Check the row i itself
|
||||
!spells.getEntry("Bard", i).equals("****") ||
|
||||
!spells.getEntry("Cleric", i).equals("****") ||
|
||||
!spells.getEntry("Druid", i).equals("****") ||
|
||||
!spells.getEntry("Paladin", i).equals("****") ||
|
||||
!spells.getEntry("Ranger", i).equals("****") ||
|
||||
!spells.getEntry("Wiz_Sorc", i).equals("****") ||
|
||||
// Check the master
|
||||
(// Make sure a master entry exists
|
||||
!spells.getEntry("Master", i).equals("****") &&
|
||||
(// See if it's a normal spell
|
||||
!spells.getEntry("Bard", temp = Integer.parseInt(spells.getEntry("Master", i))).equals("****") ||
|
||||
!spells.getEntry("Cleric", temp).equals("****") ||
|
||||
!spells.getEntry("Druid", temp).equals("****") ||
|
||||
!spells.getEntry("Paladin", temp).equals("****") ||
|
||||
!spells.getEntry("Ranger", temp).equals("****") ||
|
||||
!spells.getEntry("Wiz_Sorc", temp).equals("****")
|
||||
)
|
||||
)
|
||||
) {
|
||||
// It's a normal spell or a subradial of one
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, Integer.toString(i));
|
||||
output.setEntry("Type", temp, "N");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void handlePsionics(File dir) {
|
||||
File[] files = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().startsWith("cls_psipw_") &&
|
||||
file.getName().toLowerCase().endsWith(".2da");
|
||||
}
|
||||
});
|
||||
|
||||
Data_2da[] cls_psipw_2das = new Data_2da[files.length];
|
||||
for (int i = 0; i < files.length; i++)
|
||||
cls_psipw_2das[i] = Data_2da.load2da(files[i].getPath());
|
||||
|
||||
int temp;
|
||||
Set<Integer> realEntriesHandled = new HashSet<Integer>();
|
||||
// First, spells.2da referencing entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// Add the feat-linked power's data
|
||||
if (!cls_psipw.getEntry("SpellID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("SpellID", i));
|
||||
output.setEntry("Type", temp, "P");
|
||||
}
|
||||
// Add the real entry's data
|
||||
if (!cls_psipw.getEntry("RealSpellID", i).equals("****")) {
|
||||
temp = Integer.parseInt(cls_psipw.getEntry("RealSpellID", i));
|
||||
if (!realEntriesHandled.contains(temp)) {
|
||||
realEntriesHandled.add(temp);
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("RealSpellID", i));
|
||||
output.setEntry("Type", temp, "PS");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Feat.2da entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// The feat's data
|
||||
if (!cls_psipw.getEntry("FeatID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("FeatID", i));
|
||||
output.setEntry("Type", temp, "PF");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleTob(File dir) {
|
||||
File[] files = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().startsWith("cls_move_") &&
|
||||
file.getName().toLowerCase().endsWith(".2da");
|
||||
}
|
||||
});
|
||||
|
||||
Data_2da[] cls_psipw_2das = new Data_2da[files.length];
|
||||
for (int i = 0; i < files.length; i++)
|
||||
cls_psipw_2das[i] = Data_2da.load2da(files[i].getPath());
|
||||
|
||||
int temp;
|
||||
Set<Integer> realEntriesHandled = new HashSet<Integer>();
|
||||
// First, spells.2da referencing entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// Add the feat-linked power's data
|
||||
if (!cls_psipw.getEntry("SpellID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("SpellID", i));
|
||||
output.setEntry("Type", temp, "P");
|
||||
}
|
||||
// Add the real entry's data
|
||||
if (!cls_psipw.getEntry("RealSpellID", i).equals("****")) {
|
||||
temp = Integer.parseInt(cls_psipw.getEntry("RealSpellID", i));
|
||||
if (!realEntriesHandled.contains(temp)) {
|
||||
realEntriesHandled.add(temp);
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("RealSpellID", i));
|
||||
output.setEntry("Type", temp, "PS");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Feat.2da entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// The feat's data
|
||||
if (!cls_psipw.getEntry("FeatID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("FeatID", i));
|
||||
output.setEntry("Type", temp, "PF");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleInvocations(File dir) {
|
||||
File[] files = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().startsWith("cls_inv_") &&
|
||||
file.getName().toLowerCase().endsWith(".2da");
|
||||
}
|
||||
});
|
||||
|
||||
Data_2da[] cls_psipw_2das = new Data_2da[files.length];
|
||||
for (int i = 0; i < files.length; i++)
|
||||
cls_psipw_2das[i] = Data_2da.load2da(files[i].getPath());
|
||||
|
||||
int temp;
|
||||
Set<Integer> realEntriesHandled = new HashSet<Integer>();
|
||||
// First, spells.2da referencing entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// Add the feat-linked power's data
|
||||
if (!cls_psipw.getEntry("SpellID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("SpellID", i));
|
||||
output.setEntry("Type", temp, "P");
|
||||
}
|
||||
// Add the real entry's data
|
||||
if (!cls_psipw.getEntry("RealSpellID", i).equals("****")) {
|
||||
temp = Integer.parseInt(cls_psipw.getEntry("RealSpellID", i));
|
||||
if (!realEntriesHandled.contains(temp)) {
|
||||
realEntriesHandled.add(temp);
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("RealSpellID", i));
|
||||
output.setEntry("Type", temp, "PS");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Feat.2da entries
|
||||
for (Data_2da cls_psipw : cls_psipw_2das) {
|
||||
for (int i = 0; i < cls_psipw.getEntryCount(); i++) {
|
||||
// The feat's data
|
||||
if (!cls_psipw.getEntry("FeatID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_psipw.getEntry("FeatID", i));
|
||||
output.setEntry("Type", temp, "PF");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pretty much a copy of psionics, at least for now
|
||||
private static void handleTruenaming(File dir) {
|
||||
File[] files = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File file) {
|
||||
return file.getName().toLowerCase().startsWith("cls_true_") &&
|
||||
file.getName().toLowerCase().endsWith(".2da") &&
|
||||
!file.getName().equalsIgnoreCase("cls_true_known.2da") && // Skip special cases
|
||||
!file.getName().equalsIgnoreCase("cls_true_maxlvl.2da");
|
||||
}
|
||||
});
|
||||
|
||||
Data_2da[] cls_true_2das = new Data_2da[files.length];
|
||||
for (int i = 0; i < files.length; i++)
|
||||
cls_true_2das[i] = Data_2da.load2da(files[i].getPath());
|
||||
|
||||
int temp;
|
||||
Set<Integer> realEntriesHandled = new HashSet<Integer>();
|
||||
// First, spells.2da referencing entries
|
||||
for (Data_2da cls_true : cls_true_2das) {
|
||||
for (int i = 0; i < cls_true.getEntryCount(); i++) {
|
||||
// Add the feat-linked spells.2da data
|
||||
if (!cls_true.getEntry("SpellID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_true.getEntry("SpellID", i));
|
||||
output.setEntry("Type", temp, "P");
|
||||
}
|
||||
// Add the real entry's data
|
||||
if (!cls_true.getEntry("RealSpellID", i).equals("****")) {
|
||||
temp = Integer.parseInt(cls_true.getEntry("RealSpellID", i));
|
||||
if (!realEntriesHandled.contains(temp)) {
|
||||
realEntriesHandled.add(temp);
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_true.getEntry("RealSpellID", i));
|
||||
output.setEntry("Type", temp, "PS");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Feat.2da entries
|
||||
for (Data_2da cls_true : cls_true_2das) {
|
||||
for (int i = 0; i < cls_true.getEntryCount(); i++) {
|
||||
// The feat's data
|
||||
if (!cls_true.getEntry("FeatID", i).equals("****")) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, cls_true.getEntry("FeatID", i));
|
||||
output.setEntry("Type", temp, "PF");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleNewSpells() {
|
||||
int begin = -1, end = -1;
|
||||
int temp, i = normalSpellMaxRow;
|
||||
while (i < spells.getEntryCount()) {
|
||||
if (spells.getEntry("Label", i).equals("####START_OF_NEW_SPELLBOOK_RESERVE"))
|
||||
begin = i + 1;
|
||||
if (spells.getEntry("Label", i).equals("####END_OF_NEW_SPELLBOOK_RESERVE"))
|
||||
end = i - 1;
|
||||
if (begin != -1 && end != -1)
|
||||
break;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (begin == -1 || end == -1) {
|
||||
err_pr.println("Error: Missing a new spellbook reserve marker");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
for (i = begin; i <= end; i++) {
|
||||
output.appendRow();
|
||||
temp = output.getEntryCount() - 1;
|
||||
output.setEntry("RowNum", temp, String.valueOf(i));
|
||||
output.setEntry("Type", temp, "NS");
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Radials.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Radials.class
Normal file
Binary file not shown.
33
nwn/nwnprc/DocGen/trunk/prc/utils/Radials.java
Normal file
33
nwn/nwnprc/DocGen/trunk/prc/utils/Radials.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package prc.utils;
|
||||
|
||||
/**
|
||||
* A class for generating subradial FeatID values when given a feat.2da index and
|
||||
* the first subradial value.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Radials {
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args The program arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0)
|
||||
readMe();
|
||||
|
||||
int feat = Integer.parseInt(args[0]),
|
||||
radialrangestart = Integer.parseInt(args[1]);
|
||||
|
||||
System.out.println("Five consecutive radialfeat FeatIDs for feat " + feat + " starting from " + radialrangestart + ":");
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
System.out.println((radialrangestart + i) + " & " + feat + ": " + ((radialrangestart + i) * 0x10000 + feat));
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage: java Radials featid subradnum");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/SQLMaker.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/SQLMaker.class
Normal file
Binary file not shown.
266
nwn/nwnprc/DocGen/trunk/prc/utils/SQLMaker.java
Normal file
266
nwn/nwnprc/DocGen/trunk/prc/utils/SQLMaker.java
Normal file
@@ -0,0 +1,266 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import static prc.Main.spinner;
|
||||
import static prc.Main.verbose;
|
||||
|
||||
public final class SQLMaker {
|
||||
private SQLMaker() {
|
||||
}
|
||||
|
||||
private static BufferedWriter sql;
|
||||
private static String q = "";
|
||||
private static boolean mysql = false;
|
||||
private static boolean sqlite = true;
|
||||
|
||||
/**
|
||||
* 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 == 0 || args[0].equals("--help") || args[0].equals("-?"))
|
||||
readMe();
|
||||
|
||||
String dir = args[0];
|
||||
if (args.length >= 1 && args[1].equalsIgnoreCase("MySQL")) {
|
||||
q = "`";
|
||||
mysql = true;
|
||||
sqlite = false;
|
||||
}
|
||||
|
||||
// Create the output stream
|
||||
File target = new File("out.sql");
|
||||
// Clean up old version if necessary
|
||||
if (target.exists()) {
|
||||
if (verbose) System.out.println("Deleting previous version of " + target.getName());
|
||||
target.delete();
|
||||
}
|
||||
target.createNewFile();
|
||||
|
||||
// Allocate output buffer of 1Mb
|
||||
sql = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target)), 0xFFFFF);
|
||||
|
||||
|
||||
//setup the transaction
|
||||
if (sqlite)
|
||||
sql.append("BEGIN IMMEDIATE;\n");
|
||||
//optimize for windows
|
||||
if (sqlite)
|
||||
sql.append("PRAGMA page_size=4096;\n");
|
||||
//delete any preexsiting tables
|
||||
sql.append("DROP TABLE IF EXISTS " + q + "prc_cached2da" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_appearance" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_classes" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_cls_feat" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_feat" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_ireq" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_item_to_ireq" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_portraits" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_racialtypes" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_soundset" + q + ";\n" +
|
||||
"DROP TABLE IF EXISTS " + q + "prc_cached2da_spells" + q + ";\n"
|
||||
);
|
||||
//create a few tables
|
||||
sql.append(
|
||||
/*
|
||||
"CREATE TABLE "+q+"prc_cached2da_ireq"+q+" (" +
|
||||
""+q+"rowid"+q+" integer DEFAULT -1, " +
|
||||
""+q+"file"+q+" varchar(20) DEFAULT '_', " +
|
||||
""+q+"LABEL"+q+" varchar(255) DEFAULT '_', " +
|
||||
""+q+"ReqType"+q+" varchar(255) DEFAULT '_', " +
|
||||
""+q+"ReqParam1"+q+" varchar(255) DEFAULT '_', " +
|
||||
""+q+"ReqParam2"+q+" varchar(255) DEFAULT '_');\n" +
|
||||
*/
|
||||
"CREATE TABLE " + q + "prc_cached2da_cls_feat" + q + " (" +
|
||||
"" + q + "rowid" + q + " integer DEFAULT -1, " +
|
||||
"" + q + "file" + q + " varchar(20) DEFAULT '_', " +
|
||||
"" + q + "FeatLabel" + q + " varchar(255) DEFAULT '_', " +
|
||||
"" + q + "FeatIndex" + q + " varchar(255) DEFAULT '_', " +
|
||||
"" + q + "List" + q + " varchar(255) DEFAULT '_', " +
|
||||
"" + q + "GrantedOnLevel" + q + " varchar(255) DEFAULT '_', " +
|
||||
"" + q + "OnMenu" + q + " varchar(255) DEFAULT '_');\n" +
|
||||
|
||||
"CREATE TABLE " + q + "prc_cached2da" + q + " (" +
|
||||
"" + q + "file" + q + " varchar(20) DEFAULT '_', " +
|
||||
"" + q + "columnid" + q + " varchar(255) DEFAULT '_', " +
|
||||
"" + q + "rowid" + q + " integer DEFAULT -1, " +
|
||||
"" + q + "data" + q + " varchar(255) DEFAULT '_');\n"
|
||||
);
|
||||
|
||||
File[] files = new File(dir).listFiles();
|
||||
for (int i = 0; i < files.length; i++)
|
||||
addFileToSQL(files[i]);
|
||||
|
||||
//create some indexs
|
||||
sql.append("CREATE UNIQUE INDEX " + q + "spellsrowindex" + q + " ON " + q + "prc_cached2da_spells" + q + " (" + q + "rowid" + q + ");\n" +
|
||||
"CREATE UNIQUE INDEX " + q + "featrowindex" + q + " ON " + q + "prc_cached2da_feat" + q + " (" + q + "rowid" + q + ");\n" +
|
||||
"CREATE INDEX " + q + "clsfeatindex" + q + " ON " + q + "prc_cached2da_cls_feat" + q + " (" + q + "file" + q + ", " + q + "FeatIndex" + q + ");\n" +
|
||||
"CREATE UNIQUE INDEX " + q + "appearrowindex" + q + " ON " + q + "prc_cached2da_appearance" + q + " (" + q + "rowid" + q + ");\n" +
|
||||
"CREATE UNIQUE INDEX " + q + "portrrowindex" + q + " ON " + q + "prc_cached2da_portraits" + q + " (" + q + "rowid" + q + ");\n" +
|
||||
"CREATE UNIQUE INDEX " + q + "soundsrowindex" + q + " ON " + q + "prc_cached2da_soundset" + q + " (" + q + "rowid" + q + ");\n" +
|
||||
//"CREATE UNIQUE INDEX "+q+"datanameindex"+q+" ON "+q+"prc_data"+q+" ("+q+"name"+q+");\n" +
|
||||
"CREATE UNIQUE INDEX " + q + "cachedindex" + q + " ON " + q + "prc_cached2da" + q + " (" + q + "file" + q + ", " + q + "columnid" + q + ", " + q + "rowid" + q + ");\n"
|
||||
//"CREATE INDEX "+q+"ireqfileindex"+q+" ON "+q+"prc_cached2da_ireq"+q+" ("+q+"file"+q+");\n" +
|
||||
//"CREATE UNIQUE INDEX "+q+"refrindex"+q+" ON "+q+"prc_cached2da_item_to_ireq"+q+" ("+q+"L_RESREF"+q+", "+q+"rowid"+q+");\n"
|
||||
);
|
||||
//complete the transaction
|
||||
if (sqlite)
|
||||
sql.append("COMMIT;\n");
|
||||
|
||||
sql.flush();
|
||||
sql.close();
|
||||
}
|
||||
|
||||
private static void readMe() {
|
||||
System.out.println("Usage:\n" +
|
||||
"\tjava 2datosql precacher2das\n" +
|
||||
"\n" +
|
||||
"This application is designed to take all the 2DA\n" +
|
||||
"files in the directory and output a SQL\n" +
|
||||
"file for them"
|
||||
);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void addFileToSQL(File file) throws Exception {
|
||||
String filename = file.getAbsolutePath();
|
||||
Data_2da data = Data_2da.load2da(filename, true);
|
||||
//remove path and extension from filename
|
||||
filename = file.getName();
|
||||
filename = filename.substring(0, filename.length() - 4);
|
||||
//tell the user what were doing
|
||||
if (verbose) System.out.print("Making SQL from " + filename + " ");
|
||||
//specific files get their own tables
|
||||
if (filename.matches("feat")
|
||||
|| filename.matches("spells")
|
||||
|| filename.matches("portraits")
|
||||
|| filename.matches("soundset")
|
||||
|| filename.matches("appearance")
|
||||
|| filename.matches("portraits")
|
||||
|| filename.matches("classes")
|
||||
|| filename.matches("racialtypes"))
|
||||
//|| filename.matches("item_to_ireq"))
|
||||
{
|
||||
|
||||
//output the table creation
|
||||
addSQLForSingleTable(data, filename);
|
||||
}
|
||||
//some groups get specific matches
|
||||
else if (filename.matches("cls_feat_[^ ]*")) {
|
||||
addSQLForGroupedTable(data, filename, "cls_feat");
|
||||
}
|
||||
/*
|
||||
else if(filename.matches("ireq_[^ ]*")){
|
||||
addSQLForGroupedTable(data, filename, "ireq");
|
||||
}
|
||||
*/
|
||||
//everything else goes in the same table
|
||||
else {
|
||||
addSQLForGeneralTable(data, filename);
|
||||
}
|
||||
//tell user finished that table
|
||||
if (verbose) System.out.println("- Done");
|
||||
|
||||
// Force garbage collection
|
||||
System.gc();
|
||||
}
|
||||
|
||||
/*
|
||||
* Below are the three functions that produce SQL for adding
|
||||
* to each of the 3 table types.
|
||||
*/
|
||||
|
||||
|
||||
private static void addSQLForSingleTable(Data_2da data, String filename) throws Exception {
|
||||
|
||||
StringBuilder entry;
|
||||
entry = new StringBuilder("CREATE TABLE " + q + "prc_cached2da_" + filename + q + " (" + q + "rowid" + q + " integer");
|
||||
String[] labels = data.getLabels();
|
||||
for (int i = 0; i < labels.length; i++) {
|
||||
entry.append(", " + q + labels[i] + q + " varchar(255) DEFAULT '_'");
|
||||
}
|
||||
entry.append(");");
|
||||
|
||||
sql.append(entry + "\n");
|
||||
//put the data in
|
||||
for (int row = 0; row < data.getEntryCount(); row++) {
|
||||
entry = new StringBuilder("INSERT INTO " + q + "prc_cached2da_" + filename + q);
|
||||
//entry +=" (rowid";
|
||||
//for(int i = 0 ; i < labels.length ; i++){
|
||||
// entry += ", "+labels[i];
|
||||
//}
|
||||
//entry += ")"
|
||||
entry.append(" VALUES (" + row);
|
||||
for (int column = 0; column < labels.length; column++) {
|
||||
entry.append(", ");
|
||||
|
||||
String value = data.getEntry(labels[column], row);
|
||||
|
||||
if (value == "****")
|
||||
value = "";
|
||||
entry.append("'" + value + "'");
|
||||
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
entry.append(");");
|
||||
sql.append(entry + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSQLForGroupedTable(Data_2da data, String filename, String tablename) throws Exception {
|
||||
String[] labels = data.getLabels();
|
||||
StringBuilder entry;
|
||||
for (int row = 0; row < data.getEntryCount(); row++) {
|
||||
entry = new StringBuilder("INSERT INTO " + q + "prc_cached2da_" + tablename + q);
|
||||
//entry +="(rowid";
|
||||
//for(int i = 0 ; i < labels.length ; i++){
|
||||
// entry += ", "+labels[i];
|
||||
//}
|
||||
//entry += ", file)";
|
||||
entry.append(" VALUES (" + row);
|
||||
entry.append(", '" + filename + "'");
|
||||
for (int column = 0; column < labels.length; column++) {
|
||||
entry.append(", ");
|
||||
|
||||
String value = data.getEntry(labels[column], row);
|
||||
|
||||
if (value == "****")
|
||||
value = "";
|
||||
entry.append("'" + value + "'");
|
||||
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
entry.append(");");
|
||||
sql.append(entry + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSQLForGeneralTable(Data_2da data, String filename) throws Exception {
|
||||
String[] labels = data.getLabels();
|
||||
StringBuilder entry;
|
||||
for (int row = 0; row < data.getEntryCount(); row++) {
|
||||
for (int column = 0; column < labels.length; column++) {
|
||||
entry = new StringBuilder("INSERT INTO " + q + "prc_cached2da" + q + " VALUES ('" + filename + "', '" + labels[column] + "', " + row + ", ");
|
||||
|
||||
String value = data.getEntry(labels[column], row);
|
||||
|
||||
if (value == "****")
|
||||
value = "";
|
||||
entry.append("'" + value + "'");
|
||||
entry.append(");");
|
||||
sql.append(entry + "\n");
|
||||
|
||||
if (verbose) spinner.spin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollGen.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollGen.class
Normal file
Binary file not shown.
339
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollGen.java
Normal file
339
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollGen.java
Normal file
@@ -0,0 +1,339 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
import prc.autodoc.Main.TwoDAStore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.Main.verbose;
|
||||
|
||||
/**
|
||||
* Creates scrolls based on iprp_spells.2da and spells.2da.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class ScrollGen {
|
||||
|
||||
/**
|
||||
* 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 outPath = null;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//2dadir outdir | [--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 (outPath == null)
|
||||
outPath = param;
|
||||
else {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load data
|
||||
TwoDAStore twoDA = new TwoDAStore(twoDAPath);
|
||||
|
||||
doScrollGen(twoDA, twoDAPath, outPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual scroll generation. Made public for the purposes of BuildScrollHack.
|
||||
*
|
||||
* @param twoDA A TwoDAStore for loading 2da data from
|
||||
* @param twoDAPath Path where the 2da files are located. For resaving
|
||||
* @param outPath Path to directory to store the xml files in
|
||||
* @throws IOException Just tossed back up
|
||||
*/
|
||||
public static void doScrollGen(TwoDAStore twoDA, String twoDAPath, String outPath) throws IOException {
|
||||
Data_2da spells = twoDA.get("spells"),
|
||||
des_crft_scroll = twoDA.get("des_crft_scroll"),
|
||||
des_crft_spells = twoDA.get("des_crft_spells"),
|
||||
iprp_spells = twoDA.get("iprp_spells");
|
||||
|
||||
|
||||
// For each spells.2da entry, find the iprp_spells.2da entry with lowest CasterLvl value
|
||||
Map<Integer, Tuple<Integer, Integer>> lowestIndex = new HashMap<Integer, Tuple<Integer, Integer>>(); // Map of spells.2da index -> (iprp_spells.2da index, CasterLvl value)
|
||||
int spellID, casterLvl;
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) { // Only lines that are connected to spells.2da are scanned
|
||||
spellID = Integer.parseInt(iprp_spells.getEntry("SpellIndex", i));
|
||||
casterLvl = Integer.parseInt(iprp_spells.getEntry("CasterLvl", i));
|
||||
|
||||
if (lowestIndex.get(spellID) == null || lowestIndex.get(spellID).e2 > casterLvl)
|
||||
lowestIndex.put(spellID, new Tuple<Integer, Integer>(i, casterLvl));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// For each scroll to make, find which spellcasting classes should be able to use that scroll
|
||||
// Map of spells.2da index -> (iprp_spells.2da index, list of classes.2da index)
|
||||
Map<Integer, Tuple<Integer, Set<Integer>>> scrolls = new HashMap<Integer, Tuple<Integer, Set<Integer>>>();
|
||||
|
||||
for (int spellsIndex : lowestIndex.keySet()) {
|
||||
int iprpIndex = lowestIndex.get(spellsIndex).e1;
|
||||
Set<Integer> classList = getClassesForSpell(twoDA, spellsIndex).keySet();
|
||||
|
||||
if (classList.size() > 0)
|
||||
scrolls.put(spellsIndex, new Tuple<Integer, Set<Integer>>(iprpIndex, classList));
|
||||
}
|
||||
|
||||
// Do the scrolls
|
||||
for (int spellsIndex : scrolls.keySet()) {
|
||||
String scrollName = "prc_scr_" + scrolls.get(spellsIndex).e1.toString();
|
||||
String scrollXml = doScroll(spells, scrollName, spellsIndex, scrolls.get(spellsIndex).e1, scrolls.get(spellsIndex).e2);
|
||||
|
||||
// Print the scroll
|
||||
printScroll(outPath, scrollName, scrollXml);
|
||||
|
||||
// Update des_crft_scrolls accordingly
|
||||
Set<Integer> classList = scrolls.get(spellsIndex).e2;
|
||||
if (classList.contains(1))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Bard", scrollName);
|
||||
if (classList.contains(9) || classList.contains(10))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Wiz_Sorc", scrollName);
|
||||
if (classList.contains(2))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Cleric", scrollName);
|
||||
if (classList.contains(3))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Druid", scrollName);
|
||||
if (classList.contains(6))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Paladin", scrollName);
|
||||
if (classList.contains(7))
|
||||
setScroll(des_crft_scroll, spells, spellsIndex, "Ranger", scrollName);
|
||||
}
|
||||
|
||||
// Save updated des_crft_scrolls.2da
|
||||
des_crft_scroll.save2da(twoDAPath, true, true);
|
||||
}
|
||||
|
||||
public static Map<Integer, Integer> getClassesForSpell(TwoDAStore twoDA, int spellsIndex)
|
||||
{
|
||||
Data_2da spells = twoDA.get("spells");
|
||||
Map<Integer, Integer> classList = new TreeMap<Integer, Integer>();
|
||||
|
||||
// BAD
|
||||
// Hardcoded classes.2da indexes
|
||||
String bardSpell = spells.getEntry("Bard", spellsIndex);
|
||||
String clericSpell = spells.getEntry("Cleric", spellsIndex);
|
||||
String druidSpell = spells.getEntry("Druid", spellsIndex);
|
||||
String paladinSpell = spells.getEntry("Paladin", spellsIndex);
|
||||
String rangerSpell = spells.getEntry("Ranger", spellsIndex);
|
||||
String wizSpell = spells.getEntry("Wiz_Sorc", spellsIndex);
|
||||
if (!bardSpell.equals("****"))
|
||||
classList.put(1, Integer.parseInt(bardSpell));
|
||||
if (!clericSpell.equals("****"))
|
||||
classList.put(2, Integer.parseInt(clericSpell));
|
||||
if (!druidSpell.equals("****"))
|
||||
classList.put(3, Integer.parseInt(druidSpell));
|
||||
if (!paladinSpell.equals("****"))
|
||||
classList.put(6, Integer.parseInt(paladinSpell));
|
||||
if (!rangerSpell.equals("****"))
|
||||
classList.put(7, Integer.parseInt(rangerSpell));
|
||||
if (!wizSpell.equals("****")) {
|
||||
classList.put(9, Integer.parseInt(wizSpell));
|
||||
classList.put(10, Integer.parseInt(wizSpell));
|
||||
}
|
||||
/// For each spell, find which new spellbooks have that spell
|
||||
// Map of spells.2da index -> (map of classes.2da index -> spell level)
|
||||
Map<Integer, Map<Integer, Integer>> newSpellBooks = getNewSpellbooksClasses(twoDA, spells);
|
||||
|
||||
// New spellbooks
|
||||
Map<Integer, Integer> newSpellBookEntries = newSpellBooks.get(spellsIndex);
|
||||
if (newSpellBookEntries != null)
|
||||
for(Integer classId : newSpellBookEntries.keySet()) {
|
||||
classList.put(classId, newSpellBookEntries.get(classId));
|
||||
}
|
||||
|
||||
return classList;
|
||||
|
||||
}
|
||||
|
||||
private static Map<Integer, Map<Integer, Integer>> newSpellbookCache = null;
|
||||
|
||||
private static Map<Integer, Map<Integer, Integer>> getNewSpellbooksClasses(TwoDAStore twoDA, Data_2da spells) {
|
||||
if (newSpellbookCache != null) return newSpellbookCache;
|
||||
// Map of spells.2da index -> list of classes.2da index
|
||||
HashMap<Integer, Map<Integer, Integer>> toReturn = new HashMap<Integer, Map<Integer, Integer>>();
|
||||
String classAbrev = null;
|
||||
Data_2da classes = twoDA.get("classes"),
|
||||
spellList = null;
|
||||
Integer spellId;
|
||||
|
||||
for (int classId = 0; classId < classes.getEntryCount(); classId++) {
|
||||
if (!classes.getEntry("PlayerClass", classId).equals("1")) continue;
|
||||
|
||||
// Extract the class abbreviation
|
||||
classAbrev = classes.getEntry("FeatsTable", classId).toLowerCase().substring(9);
|
||||
|
||||
// Attempt to load the spellbook 2da
|
||||
try {
|
||||
spellList = twoDA.get("cls_spcr_" + classAbrev);
|
||||
} catch (TwoDAReadException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < spellList.getEntryCount(); i++) {
|
||||
String spellEntry = spellList.getEntry("SpellID", i);
|
||||
String spellLevelEntry = spellList.getEntry("Level", i);
|
||||
if (!spellEntry.equals("****")) {
|
||||
spellId = Integer.parseInt(spellEntry);
|
||||
int spellLevel = Integer.parseInt(spellLevelEntry);
|
||||
if (toReturn.get(spellId) == null) {
|
||||
toReturn.put(spellId, new TreeMap<Integer, Integer>());
|
||||
}
|
||||
toReturn.get(spellId).put(classId, spellLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
newSpellbookCache = toReturn;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
private static void setScroll(Data_2da des_crft_scroll, Data_2da spells, int spellsIndex, String column, String scrollName) {
|
||||
// Set the main entry
|
||||
des_crft_scroll.setEntry(column, spellsIndex, scrollName);
|
||||
|
||||
// Set each subradial's entry
|
||||
for (int i = 1; i <= 5; i++)
|
||||
if (!spells.getEntry("SubRadSpell" + i, spellsIndex).equals("****")) {
|
||||
des_crft_scroll.setEntry(column, Integer.parseInt(spells.getEntry("SubRadSpell" + i, spellsIndex)), scrollName);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String xmlPrefix =
|
||||
"<gff name=\"~~~Name~~~.uti\" type=\"UTI \" version=\"V3.2\" >" + "\n" +
|
||||
" <struct id=\"-1\" >" + "\n" +
|
||||
" <element name=\"TemplateResRef\" type=\"11\" value=\"~~~Name~~~\" />" + "\n" +
|
||||
" <element name=\"BaseItem\" type=\"5\" value=\"75\" />" + "\n" +
|
||||
" <element name=\"LocalizedName\" type=\"12\" value=\"~~~TLKName~~~\" />" + "\n" +
|
||||
" <element name=\"Description\" type=\"12\" value=\"-1\" />" + "\n" +
|
||||
" <element name=\"DescIdentified\" type=\"12\" value=\"~~~TLKDesc~~~\" />" + "\n" +
|
||||
" <element name=\"Tag\" type=\"10\" value=\"~~~Tag~~~\" />" + "\n" +
|
||||
" <element name=\"Charges\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"Cost\" type=\"4\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"Stolen\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"StackSize\" type=\"2\" value=\"1\" />" + "\n" +
|
||||
" <element name=\"Plot\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"AddCost\" type=\"4\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"Identified\" type=\"0\" value=\"1\" />" + "\n" +
|
||||
" <element name=\"Cursed\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"ModelPart1\" type=\"0\" value=\"1\" />" + "\n" +
|
||||
" <element name=\"PropertiesList\" type=\"15\" >" + "\n" +
|
||||
" <struct id=\"0\" >" + "\n" +
|
||||
" <element name=\"PropertyName\" type=\"2\" value=\"15\" />" + "\n" +
|
||||
" <element name=\"Subtype\" type=\"2\" value=\"~~~IPIndex~~~\" />" + "\n" +
|
||||
" <element name=\"CostTable\" type=\"0\" value=\"3\" />" + "\n" +
|
||||
" <element name=\"CostValue\" type=\"2\" value=\"1\" />" + "\n" +
|
||||
" <element name=\"Param1\" type=\"0\" value=\"255\" />" + "\n" +
|
||||
" <element name=\"Param1Value\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"ChanceAppear\" type=\"0\" value=\"100\" />" + "\n" +
|
||||
" </struct>" + "\n";
|
||||
private static final String xmlClass =
|
||||
" <struct id=\"0\" >" + "\n" +
|
||||
" <element name=\"PropertyName\" type=\"2\" value=\"63\" />" + "\n" +
|
||||
" <element name=\"Subtype\" type=\"2\" value=\"~~~Class~~~\" />" + "\n" +
|
||||
" <element name=\"CostTable\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"CostValue\" type=\"2\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"Param1\" type=\"0\" value=\"255\" />" + "\n" +
|
||||
" <element name=\"Param1Value\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"ChanceAppear\" type=\"0\" value=\"100\" />" + "\n" +
|
||||
" </struct>" + "\n";
|
||||
private static final String xmlSuffix =
|
||||
" </element>" + "\n" +
|
||||
" <element name=\"PaletteID\" type=\"0\" value=\"26\" />" + "\n" +
|
||||
" <element name=\"Comment\" type=\"10\" value=\"1\" />" + "\n" +
|
||||
" </struct>" + "\n" +
|
||||
"</gff>";
|
||||
|
||||
private static String doScroll(Data_2da spells, String name, int spellsIndex, int iprpIndex, Set<Integer> classes) {
|
||||
// Determine TLK references
|
||||
int tlkName = Integer.parseInt(spells.getEntry("Name", spellsIndex));
|
||||
int tlkDesc = Integer.parseInt(spells.getEntry("SpellDesc", spellsIndex));
|
||||
|
||||
// Build the string
|
||||
String toReturn = xmlPrefix.replaceAll("~~~Name~~~", name)
|
||||
.replaceAll("~~~Tag~~~", name.toUpperCase())
|
||||
.replaceAll("~~~IPIndex~~~", "" + iprpIndex)
|
||||
.replaceAll("~~~TLKName~~~", "" + tlkName)
|
||||
.replaceAll("~~~TLKDesc~~~", "" + tlkDesc);
|
||||
|
||||
for (Integer classIndex : classes)
|
||||
toReturn += xmlClass.replaceAll("~~~Class~~~", classIndex.toString());
|
||||
|
||||
toReturn += xmlSuffix;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
private static void printScroll(String outDir, String scrollName, String scrollXml) {
|
||||
String path = outDir + File.separator + scrollName + ".uti.xml";
|
||||
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(scrollXml);
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
err_pr.println("Error: IOException when printing " + path + ":\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 scrollgen 2dadir outdir | [--help]\n" +
|
||||
"\n" +
|
||||
"2dadir Path to a directory containing 2da files\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 creating spell scrolls based on iprp_spells.2da\n" +
|
||||
"and spells.2da. Generates pspeed's modpacker -compatible XML\n" +
|
||||
"Also updates des_crft_scrolls with the new scroll resrefs.\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollMerchantGen.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollMerchantGen.class
Normal file
Binary file not shown.
386
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollMerchantGen.java
Normal file
386
nwn/nwnprc/DocGen/trunk/prc/utils/ScrollMerchantGen.java
Normal file
@@ -0,0 +1,386 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
import prc.autodoc.Main.TLKStore;
|
||||
import prc.autodoc.Main.TwoDAStore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static prc.Main.verbose;
|
||||
|
||||
|
||||
/**
|
||||
* A little tool that parses des_crft_scroll, extracts unique item resrefs from it and
|
||||
* makes a merchant selling those resrefs.
|
||||
*
|
||||
* @author Heikki 'Ornedan' Aitakangas
|
||||
*/
|
||||
public class ScrollMerchantGen {
|
||||
|
||||
/**
|
||||
* Ye olde maine methode.
|
||||
*
|
||||
* @param args The arguments
|
||||
* @throws IOException If the writing fails, just die on the exception
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 0) readMe();
|
||||
String twoDAPath = null;
|
||||
String tlkPath = null;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//2dadir tlkdir | [--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 {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load data
|
||||
TwoDAStore twoDA = new TwoDAStore(twoDAPath);
|
||||
TLKStore tlks = new TLKStore("dialog.tlk", "prc_consortium.tlk", tlkPath);
|
||||
|
||||
doScrollMerchantGen(twoDA, tlks, "scrolltemp");
|
||||
}
|
||||
public static Set<Integer> getAllSpellCastingClasses(TwoDAStore twoDA)
|
||||
{
|
||||
Set<Integer> vanillaSpellcasterClasses = Set.of(1,2,3,6,7,9,10);
|
||||
HashSet<Integer> result = new HashSet<Integer>();
|
||||
Data_2da classes = twoDA.get("classes");
|
||||
for(int i = 0; i < classes.getEntryCount(); i++) {
|
||||
// handle the vanilla spellcasters
|
||||
if (vanillaSpellcasterClasses.contains(i)) {
|
||||
result.add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean isSpellCaster = classes.getEntry("SpellCaster", i).equals("1");
|
||||
boolean isPlayerClass = classes.getEntry("PlayerClass", i).equals("1");
|
||||
if (!isSpellCaster || !isPlayerClass) continue;
|
||||
|
||||
// Attempt to load the spellbook 2da for the class. If it fails, not a spellcaster,
|
||||
// or a spellcaster that reuses another book (so we don't need a shop for them).
|
||||
try {
|
||||
String classAbrev = classes.getEntry("FeatsTable", i).toLowerCase().substring(9);
|
||||
twoDA.get("cls_spcr_" + classAbrev);
|
||||
} catch (TwoDAReadException e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String label = classes.getEntry("Label", i);
|
||||
if (!label.equals("****")) result.add(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Performs the scroll merchant generation for all scroll shops.
|
||||
* @param twoDA A TwoDAStore for loading 2da data from
|
||||
* @param tlks A TLKStore for reading tlk data from
|
||||
* @throws IOException Just tossed back up
|
||||
*/
|
||||
public static void doScrollMerchantGen(TwoDAStore twoDA, TLKStore tlks, String outPath) throws IOException {
|
||||
String shopPrefix = "prcSS_";
|
||||
List<ScrollInfo> allScrolls = getAllScrolls(twoDA, tlks);
|
||||
doScrollMerchantGenShop(twoDA, tlks, outPath, false, allScrolls, "prc_scrolls", scroll -> true);
|
||||
for(int classId : getAllSpellCastingClasses(twoDA)) {
|
||||
String allClassSpellsShop = shopPrefix + "C" + classId;
|
||||
|
||||
|
||||
doScrollMerchantGenShop(twoDA, tlks, outPath, false, allScrolls, allClassSpellsShop,
|
||||
scroll -> scroll.classesForSpellWithLevel.containsKey(classId));
|
||||
|
||||
for(int level = 0; level <= 9; level++) {
|
||||
final int spellLevel = level;
|
||||
String shopName = shopPrefix + "C" + classId + "L" + level;
|
||||
doScrollMerchantGenShop(twoDA, tlks, outPath, false, allScrolls, shopName,
|
||||
scroll -> {
|
||||
Map<Integer, Integer> classSpellInfo = scroll.classesForSpellWithLevel;
|
||||
return classSpellInfo.containsKey(classId) && classSpellInfo.get(classId).equals(spellLevel);
|
||||
});
|
||||
}
|
||||
}
|
||||
char[] letters = "abcdefghijklmnopqrstuvwxyz".toCharArray();
|
||||
for(char letter : letters) {
|
||||
String shopName = "prcSS_alpha_" + letter;
|
||||
doScrollMerchantGenShop(twoDA, tlks, outPath, true, allScrolls, shopName,
|
||||
scroll -> scroll.Name.toLowerCase().startsWith("" + letter));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<ScrollInfo> getAllScrolls(TwoDAStore twoDA, TLKStore tlks)
|
||||
{
|
||||
Data_2da spells2da = twoDA.get("spells");
|
||||
Data_2da scrolls2da = twoDA.get("des_crft_scroll");
|
||||
// Loop over the scroll entries and get a list of unique resrefs
|
||||
TreeMap<Integer, TreeMap<String, ScrollInfo>> arcaneScrollResRefs = new TreeMap<Integer, TreeMap<String, ScrollInfo>>();
|
||||
TreeMap<Integer, TreeMap<String, ScrollInfo>> divineScrollResRefs = new TreeMap<Integer, TreeMap<String, ScrollInfo>>();
|
||||
String entry;
|
||||
for (int i = 0; i < scrolls2da.getEntryCount(); i++) {
|
||||
// Skip subradials
|
||||
if (spells2da.getEntry("Master", i).equals("****")) {
|
||||
if (!(entry = scrolls2da.getEntry("Wiz_Sorc", i)).equals("****"))
|
||||
addScroll(arcaneScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
if (!(entry = scrolls2da.getEntry("Cleric", i)).equals("****"))
|
||||
addScroll(divineScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
if (!(entry = scrolls2da.getEntry("Paladin", i)).equals("****"))
|
||||
addScroll(divineScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
if (!(entry = scrolls2da.getEntry("Druid", i)).equals("****"))
|
||||
addScroll(divineScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
if (!(entry = scrolls2da.getEntry("Ranger", i)).equals("****"))
|
||||
addScroll(divineScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
if (!(entry = scrolls2da.getEntry("Bard", i)).equals("****"))
|
||||
addScroll(arcaneScrollResRefs, twoDA, tlks, i, entry.toLowerCase());
|
||||
}
|
||||
}
|
||||
//int posCounter = 0;
|
||||
Stream<ScrollInfo> arcaneLevelScrollRefRefs = arcaneScrollResRefs.values()
|
||||
.stream().flatMap(scrollMap -> scrollMap.values().stream());
|
||||
Stream<ScrollInfo> divineLevelScrollRefRefs = divineScrollResRefs.values()
|
||||
.stream().flatMap(scrollMap -> scrollMap.values().stream());
|
||||
Stream<ScrollInfo> allScrollInfos = Stream.concat(arcaneLevelScrollRefRefs, divineLevelScrollRefRefs)
|
||||
.distinct()
|
||||
.sorted((scroll1, scroll2) -> -scroll1.Name.compareTo(scroll2.Name));
|
||||
|
||||
return allScrollInfos.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the scroll merchant generation. Made public for the purposes of BuildScrollHack.
|
||||
*
|
||||
* @param twoDA A TwoDAStore for loading 2da data from
|
||||
* @param tlks A TLKStore for reading tlk data from
|
||||
* @param allScrolls A list containing ScrollInfo for all scrolls
|
||||
* @param shopName The name of the shop (will generate a <shopName>.utm.xml file)
|
||||
* @param scrollFilter A predicate used to filter the scrolls for the given shop
|
||||
* @throws IOException Just tossed back up
|
||||
*/
|
||||
private static void doScrollMerchantGenShop(TwoDAStore twoDA, TLKStore tlks, String outPath,
|
||||
boolean generateEmptyShops,
|
||||
List<ScrollInfo> allScrolls, String shopName, Predicate<ScrollInfo> scrollFilter) throws IOException {
|
||||
// Load the 2da file
|
||||
Data_2da scrolls2da = twoDA.get("des_crft_scroll");
|
||||
Data_2da spells2da = twoDA.get("spells");
|
||||
|
||||
|
||||
|
||||
String xmlPrefix =
|
||||
"<gff name=\"" + shopName + ".utm\" type=\"UTM \" version=\"V3.2\" >" + "\n" +
|
||||
" <struct id=\"-1\" >" + "\n" +
|
||||
" <element name=\"ResRef\" type=\"11\" value=\"" + shopName + "\" />" + "\n" +
|
||||
" <element name=\"LocName\" type=\"12\" value=\"64113\" >" + "\n" +
|
||||
" <localString languageId=\"0\" value=\"" + shopName + "\" />" + "\n" +
|
||||
" </element>" + "\n" +
|
||||
" <element name=\"Tag\" type=\"10\" value=\"" + shopName + "\" />" + "\n" +
|
||||
" <element name=\"MarkUp\" type=\"5\" value=\"100\" />" + "\n" +
|
||||
" <element name=\"MarkDown\" type=\"5\" value=\"100\" />" + "\n" +
|
||||
" <element name=\"BlackMarket\" type=\"0\" value=\"0\" />" + "\n" +
|
||||
" <element name=\"BM_MarkDown\" type=\"5\" value=\"15\" />" + "\n" +
|
||||
" <element name=\"IdentifyPrice\" type=\"5\" value=\"-1\" />" + "\n" +
|
||||
" <element name=\"MaxBuyPrice\" type=\"5\" value=\"-1\" />" + "\n" +
|
||||
" <element name=\"StoreGold\" type=\"5\" value=\"-1\" />" + "\n" +
|
||||
" <element name=\"OnOpenStore\" type=\"11\" value=\"\" />" + "\n" +
|
||||
" <element name=\"OnStoreClosed\" type=\"11\" value=\"\" />" + "\n" +
|
||||
" <element name=\"WillNotBuy\" type=\"15\" />" + "\n" +
|
||||
" <element name=\"WillOnlyBuy\" type=\"15\" >" + "\n" +
|
||||
" <struct id=\"97869\" >" + "\n" +
|
||||
" <element name=\"BaseItem\" type=\"5\" value=\"29\" />" + "\n" +
|
||||
" </struct>" + "\n" +
|
||||
" </element>" + "\n" +
|
||||
" <element name=\"StoreList\" type=\"15\" >" + "\n" +
|
||||
" <struct id=\"0\" />" + "\n" +
|
||||
" <struct id=\"4\" />" + "\n" +
|
||||
" <struct id=\"2\" >" + "\n" +
|
||||
" <element name=\"ItemList\" type=\"15\" >" + "\n";
|
||||
String xmlSuffix =
|
||||
" </element>" + "\n" +
|
||||
" </struct>" + "\n" +
|
||||
" <struct id=\"3\" />" + "\n" +
|
||||
" <struct id=\"1\" />" + "\n" +
|
||||
" </element>" + "\n" +
|
||||
" <element name=\"ID\" type=\"0\" value=\"5\" />" + "\n" +
|
||||
" <element name=\"Comment\" type=\"10\" value=\"\" />" + "\n" +
|
||||
" </struct>" + "\n" +
|
||||
"</gff>" + "\n";
|
||||
|
||||
StringBuffer xmlString = new StringBuffer();
|
||||
|
||||
Stream<ScrollInfo> allScrollRefRefs = allScrolls.stream().filter(scrollFilter);
|
||||
int[] posCounterRef = new int[] { 0 };
|
||||
allScrollRefRefs.forEach(scroll -> {
|
||||
int posCounter = posCounterRef[0];
|
||||
String resref = scroll.ScrollResRef;
|
||||
String name = scroll.Name;
|
||||
xmlString.append(
|
||||
" <struct id=\"" + posCounter + "\" >" + "\n" +
|
||||
" <element name=\"InventoryRes\" type=\"11\" value=\"" + resref + "\" />" + "<!-- " + name + " -->" + "\n" +
|
||||
" <element name=\"Repos_PosX\" type=\"2\" value=\"" + (posCounter % 10) + "\" />" + "\n" +
|
||||
" <element name=\"Repos_Posy\" type=\"2\" value=\"" + (posCounter / 10) + "\" />" + "\n" +
|
||||
" <element name=\"Infinite\" type=\"0\" value=\"1\" />" + "\n" +
|
||||
" </struct>" + "\n"
|
||||
);
|
||||
posCounterRef[0]+= 1;
|
||||
|
||||
});
|
||||
if (posCounterRef[0] == 0) {
|
||||
System.out.println("No scrolls found for shop " + shopName);
|
||||
if (!generateEmptyShops) return;
|
||||
}
|
||||
|
||||
// // Then divine scrolls
|
||||
// for (Map<String, String> levelScrollResRefs : divineScrollResRefs.values())
|
||||
// for (String name : levelScrollResRefs.keySet()) {
|
||||
// String resref = levelScrollResRefs.get(name);
|
||||
// xmlString.append(
|
||||
// " <struct id=\"" + posCounter + "\" >" + "\n" +
|
||||
// " <element name=\"InventoryRes\" type=\"11\" value=\"" + resref + "\" />" + "<!-- " + name + " -->" + "\n" +
|
||||
// " <element name=\"Repos_PosX\" type=\"2\" value=\"" + (posCounter % 10) + "\" />" + "\n" +
|
||||
// " <element name=\"Repos_Posy\" type=\"2\" value=\"" + (posCounter / 10) + "\" />" + "\n" +
|
||||
// " <element name=\"Infinite\" type=\"0\" value=\"1\" />" + "\n" +
|
||||
// " </struct>" + "\n"
|
||||
// );
|
||||
// posCounter++;
|
||||
// }
|
||||
|
||||
String shopFilePath = outPath + File.separator + shopName + ".utm.xml";
|
||||
File target = new File(shopFilePath);
|
||||
// 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(xmlPrefix + xmlString.toString() + xmlSuffix);
|
||||
// Clean up
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
private static class ScrollInfo {
|
||||
private TwoDAStore twoDAStore;
|
||||
|
||||
public ScrollInfo(TwoDAStore twoDA, int rowNum, String scrollResRef, String name) {
|
||||
this.twoDAStore = twoDA;
|
||||
this.ScrollResRef = scrollResRef;
|
||||
this.Name = name;
|
||||
|
||||
Data_2da spells2da = twoDA.get("spells");
|
||||
|
||||
|
||||
try {
|
||||
this.SpellLevel = Integer.parseInt(spells2da.getEntry("Innate", rowNum));
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Non-number value in spells.2da Innate column on line " + rowNum + ": " + spells2da.getEntry("Innate", rowNum));
|
||||
return;
|
||||
}
|
||||
|
||||
Data_2da classes = twoDA.get("classes");
|
||||
this.classesForSpellWithLevel = ScrollGen.getClassesForSpell(twoDA, rowNum);
|
||||
|
||||
}
|
||||
public int SpellLevel = -1;
|
||||
public String ScrollResRef;
|
||||
public String Name;
|
||||
public Map<Integer, Integer> classesForSpellWithLevel;
|
||||
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (this == other) return true;
|
||||
if (other == null) return false;
|
||||
if (getClass() != other.getClass()) return false;
|
||||
ScrollInfo otherScroll = (ScrollInfo)other;
|
||||
return ScrollResRef.equals(otherScroll.ScrollResRef);
|
||||
}
|
||||
public int hashCode() {
|
||||
return Objects.hash(ScrollResRef);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addScroll(TreeMap<Integer, TreeMap<String, ScrollInfo>> scrollResRefs,
|
||||
TwoDAStore twoDAStore, TLKStore tlks, int rowNum, String scrollResRef) {
|
||||
int innateLevel = -1,
|
||||
tlkRef = -1;
|
||||
|
||||
Data_2da spells2da = twoDAStore.get("spells");
|
||||
// HACK - Skip non-PRC scrolls
|
||||
if (!scrollResRef.startsWith("prc_scr_"))
|
||||
return;
|
||||
|
||||
|
||||
try {
|
||||
tlkRef = Integer.parseInt(spells2da.getEntry("Name", rowNum));
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Non-number value in spells.2da Name column on line " + rowNum + ": " + spells2da.getEntry("Name", rowNum));
|
||||
return;
|
||||
}
|
||||
ScrollInfo scroll = new ScrollInfo(twoDAStore, rowNum, scrollResRef, tlks.get(tlkRef));
|
||||
scroll.SpellLevel = innateLevel;
|
||||
|
||||
innateLevel = scroll.SpellLevel;
|
||||
|
||||
if (scrollResRefs.get(innateLevel) == null)
|
||||
scrollResRefs.put(innateLevel, new TreeMap<String, ScrollInfo>());
|
||||
|
||||
scrollResRefs.get(innateLevel).put(tlks.get(tlkRef), scroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 scrmrchgen 2dadir tlkdir | [--help]\n" +
|
||||
"\n" +
|
||||
"2dadir Path to a directory containing des_crft_scroll.2da and spells.2da.\n" +
|
||||
"tlkdir Path to a directory containing dialog.tlk and prc_consortium.tlk\n" +
|
||||
"\n" +
|
||||
"--help prints this info you are reading\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Generates a merchant file - prc_scrolls.utm - based on the given scroll list\n" +
|
||||
"2da file. The merchant file will be written to current directory in Pspeed's\n" +
|
||||
"XML <-> Gff -xml format\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/SpellbookMaker.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/SpellbookMaker.class
Normal file
Binary file not shown.
661
nwn/nwnprc/DocGen/trunk/prc/utils/SpellbookMaker.java
Normal file
661
nwn/nwnprc/DocGen/trunk/prc/utils/SpellbookMaker.java
Normal file
@@ -0,0 +1,661 @@
|
||||
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 SpellbookMaker {
|
||||
private SpellbookMaker() {/* 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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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 = "cls_spcr_" + 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 + "cls_spell_" + classfilename + ".2da");
|
||||
if (!classSpell2daFile.exists()) {
|
||||
System.out.println("File " + classSpell2daFile.getPath() + " did not exist, creating");
|
||||
classSpell2da = new Data_2da("cls_spell_" + 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);
|
||||
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 = "prc_" + (classfilename.length() <= 5 ? classfilename : classfilename.substring(0, 5)) + "_" + metaScript + "_gen";
|
||||
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_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
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_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
getFirstSpells2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstFeat2daRow() {
|
||||
System.out.print("Finding start of feat.2da ");
|
||||
while (!feat2da.getEntry("Label", feat2daRow).equals("####START_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
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_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
getFirstFeat2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstIPRPFeats2daRow() {
|
||||
System.out.print("Finding start of iprp_spells.2da ");
|
||||
while (!iprp_feats2da.getEntry("Label", iprp_feats2daRow).equals("####START_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
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_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
getFirstIPRPFeats2daRow();
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstClassFeat2daRow() {
|
||||
classFeatRow = 0;
|
||||
System.out.print("Finding start of cls_feat_*.2da ");
|
||||
while (!classFeat2da.getEntry("FeatLabel", classFeatRow).equals("####START_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
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_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
classFeat2da.insertRow(classFeatRow);
|
||||
}
|
||||
}
|
||||
|
||||
private static void getFirstTlkRow() {
|
||||
System.out.print("Finding start of prc_consortium.tlk ");
|
||||
while (!customtlk.getEntry(tlkRow).equals("####START_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
tlkRow++;
|
||||
spinner.spin();
|
||||
}
|
||||
tlkRow++;
|
||||
System.out.println("- Done");
|
||||
}
|
||||
|
||||
private static void getNextTlkRow() {
|
||||
tlkRow++;
|
||||
if (customtlk.getEntry(tlkRow).equals("####END_OF_NEW_SPELLBOOK_RESERVE")) {
|
||||
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" +
|
||||
"\n" +
|
||||
"Creates and/or updates the new 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_spcr_*.2da files and updates cls_feat_*.2da, cls_spell*.2da,\n" +
|
||||
"feat.2da, iprp_feats.2da and spells.2da."
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/UpdateDes.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/UpdateDes.class
Normal file
Binary file not shown.
189
nwn/nwnprc/DocGen/trunk/prc/utils/UpdateDes.java
Normal file
189
nwn/nwnprc/DocGen/trunk/prc/utils/UpdateDes.java
Normal file
@@ -0,0 +1,189 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
import prc.autodoc.Main.TwoDAStore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A tool for automatically updating parts of des_crft_scrolls.2da
|
||||
* and des_crft_spells.2da based on spells.2da.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class UpdateDes {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//2dadir | [--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 {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TwoDAStore twoDA = new TwoDAStore(twoDAPath);
|
||||
|
||||
doUpdateDes(twoDA, twoDAPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual 2da updating. Made public for the purposes of BuildScrollHack.
|
||||
*
|
||||
* @param twoDA A TwoDAStore for loading 2da data from
|
||||
* @param twoDAPath Path where the 2da files are located. For resaving
|
||||
* @throws IOException Just tossed back up
|
||||
*/
|
||||
public static void doUpdateDes(TwoDAStore twoDA, String twoDAPath) throws IOException {
|
||||
Data_2da spells = twoDA.get("spells"),
|
||||
des_crft_scroll = twoDA.get("des_crft_scroll"),
|
||||
des_crft_spells = twoDA.get("des_crft_spells"),
|
||||
iprp_spells = twoDA.get("iprp_spells");
|
||||
|
||||
// First, find the highest entry in spells that should have a corresponding entry in des_crft_scroll
|
||||
// In other words, one that is cast by arcane or divine casters
|
||||
int highestScroll = -1;
|
||||
for (int i = 0; i < spells.getEntryCount(); i++) {
|
||||
if (!(spells.getEntry("Bard", i).equals("****") &&
|
||||
spells.getEntry("Cleric", i).equals("****") &&
|
||||
spells.getEntry("Druid", i).equals("****") &&
|
||||
spells.getEntry("Paladin", i).equals("****") &&
|
||||
spells.getEntry("Ranger", i).equals("****") &&
|
||||
spells.getEntry("Wiz_Sorc", i).equals("****")))
|
||||
highestScroll = i;
|
||||
}
|
||||
//System.out.println("Highest entry that should have des_crft_scroll entry: " + highestScroll);
|
||||
|
||||
// If des_crft_scroll size is under the number determined above, add entries
|
||||
while (des_crft_scroll.getEntryCount() <= highestScroll)
|
||||
des_crft_scroll.appendRow();
|
||||
|
||||
// Next, do the same for des_crft_spells size. Except it should just be equal to spells size
|
||||
while (des_crft_spells.getEntryCount() < spells.getEntryCount())
|
||||
des_crft_spells.appendRow();
|
||||
|
||||
// Next, update any case where Label of des_crft_scroll or des_crft_spells is **** and spells not ****
|
||||
for (int i = 0; i < des_crft_scroll.getEntryCount(); i++) {
|
||||
if (!spells.getEntry("Label", i).equals("****") &&
|
||||
!spells.getEntry("Label", i).equals(des_crft_scroll.getEntry("Label", i))) {
|
||||
des_crft_scroll.setEntry("Label", i, spells.getEntry("Label", i));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < des_crft_spells.getEntryCount(); i++) {
|
||||
if (!spells.getEntry("Label", i).equals("****") &&
|
||||
!spells.getEntry("Label", i).equals(des_crft_spells.getEntry("Label", i))) {
|
||||
des_crft_spells.setEntry("Label", i, spells.getEntry("Label", i));
|
||||
}
|
||||
}
|
||||
|
||||
// Next, update all des_crft_spells Level column values to equal spells Innate values
|
||||
for (int i = 0; i < des_crft_spells.getEntryCount(); i++) {
|
||||
des_crft_spells.setEntry("Level", i, spells.getEntry("Innate", i));
|
||||
}
|
||||
|
||||
|
||||
// Update des_crft_spell IPRP_SpellIndex to be the one with lowest CasterLvl for that spell
|
||||
Map<Integer, Tuple<Integer, Integer>> lowestIndex = new HashMap<Integer, Tuple<Integer, Integer>>(); // Map of spells.2da index -> (iprp_spells.2da index, CasterLvl value)
|
||||
int spellID, casterLvl;
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) { // Only lines that are connected to spells.2da are scanned
|
||||
spellID = Integer.parseInt(iprp_spells.getEntry("SpellIndex", i));
|
||||
casterLvl = Integer.parseInt(iprp_spells.getEntry("CasterLvl", i));
|
||||
|
||||
if (lowestIndex.get(spellID) == null || lowestIndex.get(spellID).e2 > casterLvl)
|
||||
lowestIndex.put(spellID, new Tuple<Integer, Integer>(i, casterLvl));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < des_crft_spells.getEntryCount(); i++) {
|
||||
if (lowestIndex.get(i) != null) {
|
||||
des_crft_spells.setEntry("IPRP_SpellIndex", i, lowestIndex.get(i).e1.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update all des_crft_spells entries that define IPRP_SpellIndex based on that iprp_spells.2da data
|
||||
int iprp_index;
|
||||
for (int i = 0; i < des_crft_spells.getEntryCount(); i++) {
|
||||
// If there is an IP Cast Spell for this spell, see what uses it specifies and match them
|
||||
if (!des_crft_spells.getEntry("IPRP_SpellIndex", i).equals("****")) {
|
||||
iprp_index = Integer.parseInt(des_crft_spells.getEntry("IPRP_SpellIndex", i));
|
||||
|
||||
if (iprp_spells.getEntry("GeneralUse", iprp_index).equals("1"))
|
||||
des_crft_spells.setEntry("NoScroll", i, "0");
|
||||
else
|
||||
des_crft_spells.setEntry("NoScroll", i, "1");
|
||||
|
||||
if (iprp_spells.getEntry("PotionUse", iprp_index).equals("1"))
|
||||
des_crft_spells.setEntry("NoPotion", i, "0");
|
||||
else
|
||||
des_crft_spells.setEntry("NoPotion", i, "1");
|
||||
|
||||
if (iprp_spells.getEntry("WandUse", iprp_index).equals("1"))
|
||||
des_crft_spells.setEntry("NoWand", i, "0");
|
||||
else
|
||||
des_crft_spells.setEntry("NoWand", i, "1");
|
||||
}
|
||||
// No IP, no item creation
|
||||
else {
|
||||
des_crft_spells.setEntry("NoScroll", i, "1");
|
||||
des_crft_spells.setEntry("NoPotion", i, "1");
|
||||
des_crft_spells.setEntry("NoWand", i, "1");
|
||||
}
|
||||
}
|
||||
|
||||
des_crft_scroll.save2da(twoDAPath, true, true);
|
||||
des_crft_spells.save2da(twoDAPath, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 updatedescrft 2dadir | [--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" +
|
||||
"\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/Validator.class
Normal file
BIN
nwn/nwnprc/DocGen/trunk/prc/utils/Validator.class
Normal file
Binary file not shown.
314
nwn/nwnprc/DocGen/trunk/prc/utils/Validator.java
Normal file
314
nwn/nwnprc/DocGen/trunk/prc/utils/Validator.java
Normal file
@@ -0,0 +1,314 @@
|
||||
package prc.utils;
|
||||
|
||||
import prc.autodoc.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static prc.Main.err_pr;
|
||||
import static prc.autodoc.Main.TwoDAStore;
|
||||
|
||||
/**
|
||||
* Performs a bunch of cross-reference tests on 2das.
|
||||
*
|
||||
* @author Ornedan
|
||||
*/
|
||||
public class Validator {
|
||||
private static TwoDAStore twoDA;
|
||||
private static boolean pedantic = false;
|
||||
|
||||
/**
|
||||
* Ye olde maine methode.
|
||||
*
|
||||
* @param args The arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) readMe();
|
||||
String twoDAPath = null;
|
||||
String tlkPath = null;
|
||||
|
||||
// parse args
|
||||
for (String param : args) {//2dadir tlkdir | [--help]
|
||||
// Parameter parseage
|
||||
if (param.startsWith("-")) {
|
||||
if (param.equals("--help")) readMe();
|
||||
else {
|
||||
for (char c : param.substring(1).toCharArray()) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
pedantic = true;
|
||||
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 {
|
||||
System.out.println("Unknown parameter: " + param);
|
||||
readMe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
twoDA = new TwoDAStore(twoDAPath);
|
||||
|
||||
doSpellsAndDes2dasTest(twoDAPath);
|
||||
|
||||
doSpellsAndIprpSpellsTest(twoDAPath);
|
||||
|
||||
doDesAndIprpTest(twoDAPath);
|
||||
}
|
||||
|
||||
private static void doDesAndIprpTest(String twoDAPath) {
|
||||
Data_2da iprp_spells = twoDA.get("iprp_spells"),
|
||||
des_crft_spells = twoDA.get("des_crft_spells");
|
||||
|
||||
// For each des_crft_spells entry, see if it points at the lowest CasterLvl entry
|
||||
Map<Integer, Tuple<Integer, Integer>> lowestIndex = new HashMap<Integer, Tuple<Integer, Integer>>(); // Map of spells.2da index -> (iprp_spells.2da index, CasterLvl value)
|
||||
int spellID, casterLvl;
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) { // Only lines that are connected to spells.2da are scanned
|
||||
try {
|
||||
spellID = Integer.parseInt(iprp_spells.getEntry("SpellIndex", i));
|
||||
} catch (NumberFormatException e) {
|
||||
// Logged already, just skip
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
casterLvl = Integer.parseInt(iprp_spells.getEntry("CasterLvl", i));
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Error: Non-number value in iprp_spells.2da CasterLvl column on line " + i + ": " + iprp_spells.getEntry("CasterLvl", i));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lowestIndex.get(spellID) == null || lowestIndex.get(spellID).e2 > casterLvl)
|
||||
lowestIndex.put(spellID, new Tuple<Integer, Integer>(i, casterLvl));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < des_crft_spells.getEntryCount(); i++) {
|
||||
if (!des_crft_spells.getEntry("IPRP_SpellIndex", i).equals("****")) {
|
||||
if (lowestIndex.get(i) == null)
|
||||
err_pr.println("Error: Error: des_crft_spells.2da IPRP_SpellIndex defined for spell " + i + ", but no matching iprp_spells.2da entries exist");
|
||||
try {
|
||||
if (lowestIndex.get(i).e1 != Integer.parseInt(des_crft_spells.getEntry("IPRP_SpellIndex", i)))
|
||||
err_pr.println("Error: Warning: des_crft_spells.2da IPRP_SpellIndex entry on line " + i + " points at iprp_spells.2da entry with non-lowest CasterLvl value: " + des_crft_spells.getEntry("IPRP_SpellIndex", i) + " (lowest is on line: " + lowestIndex.get(i).e1 + ")");
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Error: Non-number value in des_crft_spells.2da IPRP_SpellIndex column on line " + i + ": " + iprp_spells.getEntry("SpellIndex", i));
|
||||
}
|
||||
} else if (lowestIndex.get(i) != null)
|
||||
err_pr.println("Error: Error: iprp_spells.2da entry defined for spell " + i + ", but des_crft_spells.2da IPRP_SpellIndex is not");
|
||||
}
|
||||
}
|
||||
|
||||
private static void doSpellsAndIprpSpellsTest(String twoDAPath) {
|
||||
Data_2da spells = twoDA.get("spells"),
|
||||
iprp_spells = twoDA.get("iprp_spells");
|
||||
|
||||
// For each iprp_spells entry, make sure InnateLevel matches spells Innate
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) { // Only lines that are connected to spells.2da are scanned
|
||||
try {
|
||||
if (!iprp_spells.getEntry("InnateLvl", i).equals(spells.getEntry("Innate", Integer.parseInt(iprp_spells.getEntry("SpellIndex", i))))
|
||||
&&
|
||||
!(spells.getEntry("Innate", Integer.parseInt(iprp_spells.getEntry("SpellIndex", i))).equals("0") &&
|
||||
iprp_spells.getEntry("InnateLvl", i).equals("0.5")
|
||||
)
|
||||
)
|
||||
err_pr.println("Error: Warning: Differing Innate and InnateLvl among spells.2da and iprp_spells.2da on iprp_spells.2da line " + i + ": " + "(" + spells.getEntry("Innate", Integer.parseInt(iprp_spells.getEntry("SpellIndex", i))) + "," + iprp_spells.getEntry("InnateLvl", i) + ")");
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Error: Non-number value in iprp_spells.2da SpellIndex column on line " + i + ": " + iprp_spells.getEntry("SpellIndex", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each iprp_spells entry, if GeneralUse is 1, check whether PotionUse and WandUse obey the standard level constraints
|
||||
if (pedantic) {
|
||||
int level;
|
||||
boolean targetSelf;
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) { // Only lines that are connected to spells.2da are scanned
|
||||
if (!iprp_spells.getEntry("GeneralUse", i).equals("****") &&
|
||||
!iprp_spells.getEntry("GeneralUse", i).equals("0")) {
|
||||
try {
|
||||
level = Integer.parseInt(iprp_spells.getEntry("InnateLvl", i));
|
||||
} catch (NumberFormatException e) {
|
||||
if (iprp_spells.getEntry("InnateLvl", i).equals("0.5"))
|
||||
level = 0;
|
||||
else {
|
||||
err_pr.println("Error: Error: Non-number value in iprp_spells.2da InnateLvl column on line " + i + ": " + iprp_spells.getEntry("InnateLvl", i));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
targetSelf =
|
||||
(Integer.parseInt(spells.getEntry("TargetType",
|
||||
Integer.parseInt(iprp_spells.getEntry("SpellIndex", i)))
|
||||
.substring(2),
|
||||
16)
|
||||
& 0x1) == 1;
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Error: Non-number value among iprp_spells.2da SpellIndex and spells.2da TargetType on iprp_spells.2da line " + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iprp_spells.getEntry("PotionUse", i).equals("0") && targetSelf && level <= 3)
|
||||
err_pr.println("Error: Warning: PotionUse 0 in iprp_spells.2da when spell of 3rd level or less and self-targetable on line " + i);
|
||||
if (iprp_spells.getEntry("PotionUse", i).equals("1") && (!targetSelf || level > 3))
|
||||
err_pr.println("Error: Warning: PotionUse 1 in iprp_spells.2da when spell of level higher than 3rd or not self-targetable on line " + i);
|
||||
|
||||
if (iprp_spells.getEntry("WandUse", i).equals("0") && level <= 4)
|
||||
err_pr.println("Error: Warning: WandUse 0 in iprp_spells.2da when spell of 4th level or less on line " + i);
|
||||
if (iprp_spells.getEntry("WandUse", i).equals("1") && level > 4)
|
||||
err_pr.println("Error: Warning: WandUse 1 in iprp_spells.2da when spell of level higher than 4th on line " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each actual spell in spells.2da, make sure there is at least one iprp_spells.2da entry
|
||||
Set<Integer> spellIDs = new TreeSet<Integer>();
|
||||
for (int i = 0; i < spells.getEntryCount(); i++) {
|
||||
if (!spells.getEntry("Bard", i).equals("****") ||
|
||||
!spells.getEntry("Cleric", i).equals("****") ||
|
||||
!spells.getEntry("Druid", i).equals("****") ||
|
||||
!spells.getEntry("Paladin", i).equals("****") ||
|
||||
!spells.getEntry("Ranger", i).equals("****") ||
|
||||
!spells.getEntry("Wiz_Sorc", i).equals("****"))
|
||||
spellIDs.add(i);
|
||||
}
|
||||
for (int i = 0; i < iprp_spells.getEntryCount(); i++) {
|
||||
if (!iprp_spells.getEntry("SpellIndex", i).equals("****")) {
|
||||
try {
|
||||
spellIDs.remove(Integer.parseInt(iprp_spells.getEntry("SpellIndex", i)));
|
||||
} catch (NumberFormatException e) {
|
||||
err_pr.println("Error: Error: Non-number value in iprp_spells.2da SpellIndex column on line " + i + ": " + iprp_spells.getEntry("SpellIndex", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int spellID : spellIDs)
|
||||
err_pr.println("Error: Error: Spell " + spellID + " does not have any iprp_spells.2da entries");
|
||||
}
|
||||
|
||||
private static void doSpellsAndDes2dasTest(String twoDAPath) {
|
||||
Data_2da spells = twoDA.get("spells"),
|
||||
des_crft_scroll = twoDA.get("des_crft_scroll"),
|
||||
des_crft_spells = twoDA.get("des_crft_spells");
|
||||
|
||||
// First, whine about differing lengths on spells and des_crft_spells
|
||||
if (spells.getEntryCount() != des_crft_spells.getEntryCount())
|
||||
err_pr.println("Error: Warning: spells.2da and des_crft_spells.2da have different number of entries");
|
||||
|
||||
int maxCommon = Math.min(Math.min(spells.getEntryCount(), des_crft_spells.getEntryCount()), des_crft_scroll.getEntryCount());
|
||||
|
||||
// First, check labels up to the common max
|
||||
for (int i = 0; i < maxCommon; i++) {
|
||||
if (!(spells.getEntry("Label", i).equals(des_crft_spells.getEntry("Label", i)) &&
|
||||
spells.getEntry("Label", i).equals(des_crft_scroll.getEntry("Label", i)) &&
|
||||
des_crft_spells.getEntry("Label", i).equals(des_crft_scroll.getEntry("Label", i))))
|
||||
err_pr.println("Error: Warning: Differing Label among spells.2da, des_crft_scroll.2da and des_crft_spells.2da on line: " + i + "('" + spells.getEntry("Label", i) + "','" + des_crft_scroll.getEntry("Label", i) + "','" + des_crft_spells.getEntry("Label", i) + "')");
|
||||
}
|
||||
|
||||
// Then, check spells.2da and des_crft_spells.2da
|
||||
int a = 0, b = 0;
|
||||
boolean spellsNum, desNum;
|
||||
for (int i = 0; i < Math.min(spells.getEntryCount(), des_crft_spells.getEntryCount()); i++) {
|
||||
spellsNum = desNum = true;
|
||||
// Here, we are only interested in lines that contain something
|
||||
if (!(spells.getEntry("Label", i).startsWith("**") ||
|
||||
spells.getEntry("Label", i).equals("ReservedForISCAndESS"))
|
||||
) {
|
||||
if (!spells.getEntry("Label", i).equals(des_crft_spells.getEntry("Label", i)))
|
||||
err_pr.println("Error: Warning: Differing Label among spells.2da and des_crft_spells.2da on line: " + i + "('" + spells.getEntry("Label", i) + "','" + des_crft_spells.getEntry("Label", i) + "')");
|
||||
try {
|
||||
a = Integer.parseInt(spells.getEntry("Innate", i));
|
||||
} catch (NumberFormatException e) {
|
||||
spellsNum = false;
|
||||
}
|
||||
try {
|
||||
b = Integer.parseInt(des_crft_spells.getEntry("Level", i));
|
||||
} catch (NumberFormatException e) {
|
||||
desNum = false;
|
||||
}
|
||||
|
||||
// If both are numeric, compare
|
||||
if (spellsNum && desNum) {
|
||||
if (a != b)
|
||||
err_pr.println("Error: Error: Differing Innate and Level values among spells.2da and des_crft_spells.2da on line " + i + ": " + "(" + a + "," + b + ")");
|
||||
} // Otherwise, erroneous cases are those where only one value is non-numeric
|
||||
else if (!spellsNum && desNum)
|
||||
err_pr.println("Error: Error: Non-number value in spells.2da Innate column on line " + i + ": " + spells.getEntry("Innate", i));
|
||||
else if (spellsNum && !desNum)
|
||||
err_pr.println("Error: Error: Non-number value in des_crft_spells.2da Level column on line " + i + ": " + des_crft_spells.getEntry("Level", i));
|
||||
// Or where the non-numericity is not just ****
|
||||
else {
|
||||
if (!spells.getEntry("Innate", i).equals("****"))
|
||||
err_pr.println("Error: Error: Non-number value in spells.2da Innate column on line " + i + ": " + spells.getEntry("Innate", i));
|
||||
if (!des_crft_spells.getEntry("Level", i).equals("****"))
|
||||
err_pr.println("Error: Error: Non-number value in des_crft_spells.2da Level column on line " + i + ": " + des_crft_spells.getEntry("Level", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then check that all spells that have a scroll is are NoScroll 0
|
||||
for (int i = 0; i < des_crft_scroll.getEntryCount(); i++) {
|
||||
if ((!des_crft_scroll.getEntry("Wiz_Sorc", i).equals("****") ||
|
||||
!des_crft_scroll.getEntry("Cleric", i).equals("****") ||
|
||||
!des_crft_scroll.getEntry("Paladin", i).equals("****") ||
|
||||
!des_crft_scroll.getEntry("Druid", i).equals("****") ||
|
||||
!des_crft_scroll.getEntry("Ranger", i).equals("****") ||
|
||||
!des_crft_scroll.getEntry("Bard", i).equals("****")
|
||||
) &&
|
||||
des_crft_spells.getEntry("NoScroll", i).equals("1")
|
||||
)
|
||||
err_pr.println("Error: Error: NoScroll 1 in des_crft_spells.2da when a scroll entry has been defined in des_crft_scroll.2da on line: " + i);
|
||||
}
|
||||
|
||||
// Then check that all spells that should have a scroll do have a scroll
|
||||
for (int i = 0; i < spells.getEntryCount(); i++) {
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Bard", i);
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Cleric", i);
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Druid", i);
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Paladin", i);
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Ranger", i);
|
||||
checkScrollsPresence(spells, des_crft_scroll, "Wiz_Sorc", i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkScrollsPresence(Data_2da spells, Data_2da des_crft_scroll, String column, int i) {
|
||||
if (!spells.getEntry(column, i).equals("****")) {
|
||||
if (i >= des_crft_scroll.getEntryCount() || des_crft_scroll.getEntry(column, i).equals("****")) {
|
||||
err_pr.println("Error: Error: No " + column + " scroll defined in des_crft_scroll when " + column + " level is defined in spells on line: " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 validate 2dadir tlkdir | [--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" +
|
||||
"\n" +
|
||||
"-p pedantic mode. Makes extra checks\n" +
|
||||
"\n" +
|
||||
"--help prints this info you are reading\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"Performs a set of validation operations on 2da files.\n"
|
||||
);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user