Notice something wrong, missing, or inadequate? Feel free to edit pages yourself and make use of discussion pages.
Wiki content is created, maintained, and administrated by players. Learn how you can help!

Spells/Parsing/code:Main.java

From SoDWiki
< Spells‎ | Parsing
Revision as of 21:15, 24 August 2010 by Tyrsell (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search
package com.zak.sod.extractor;

/******************************************************************************
*    Based on the OpenSpell code, originally written in Pascal. This program
*    takes an everquest spell file and parses out into organized, plain text.
*    What you want to do with it afterwards is your own business. The original
*    wasn't released under a license, so this will be released under the MIT OS
*    Licesnse.
*
*
*    The MIT License
*   
*    Copyright (c) 2008 Zak-Corps.
*   
*    Permission is hereby granted, free of charge, to any person obtaining a copy
*    of this software and associated documentation files (the "Software"), to deal
*    in the Software without restriction, including without limitation the rights
*    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*    copies of the Software, and to permit persons to whom the Software is
*    furnished to do so, subject to the following conditions:
*
*    1) Credit given in derivative works
*    2) Notification prior to distribution of derivative works
*   
*    The above copyright notice and this permission notice shall be included in
*    all copies or substantial portions of the Software.
*   
*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*    THE SOFTWARE.
*
*    Now that the legal stuff is out of the way, enjoy.
*
*    @author Tyrsell
*    @author [email protected]
*
*    Based on the work by:
*    @author Windcatcher from EQEmulator Forums
*             (http://www.eqemulator.net/forums/index.php )
*
*    @version 1.5 release 1/09/2008
******************************************************************************/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File ;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Main {

    static File sodSpellFile;    // The File to read
   
    static BufferedReader inputReader;    // Wrapped around the FileReader
    static FileReader fileReader;    // Convenience stream to read the file
   
    static BufferedWriter outputWriter; // Same as above but for output stream
    static FileWriter fileWriter;
   
   
    // All the information we will be storing and formating.
    static String name, range, aeRange, castTime, recastTime, duration, spellType, reagents2, reagentAmt2,
                    aeDuration, icon1, icon2, manaCost, reagents, reagentAmt, resistType, effects, targets,
                    skill, resistAdjust, pcClass, notes, classToken, zoneType, id, push;
   
    static String warMinLevel, clrMinLevel, palMinLevel, rngMinLevel, shdMinLevel,
                    druMinLevel, mnkMinLevel, brdMinLevel, rogMinLevel, shmMinLevel,
                    necMinLevel, wizMinLevel, magMinLevel, encMinLevel, bstMinLevel;
   

    
    /**
     * Many of the strings from the parsed spell are meaningless numbers. This
     * method takes those meaningless numbers, and assigns a real value to them.
     * For example prior to this method, resistType is a number between 0 and 5,
     * lets say 1 for this example. We know that that 1 means Magic Resist, so
     * we change the "1" string into "Magic Resist" string. Other minor changes
     * are made to certain fields as well.
     *
     * @return It doesn't return anything, it does change many static variable
     */
    public static void processStrings(){
       
        // name, range, manaCost and aeRange are fine as is!
       
        // Conversion of a string to int, converted to seconds from milliseconds...
        int decodedInteger = (Integer.decode( castTime )).intValue();
        //and back to a string again. I hate java.
        if( decodedInteger > 0 )
            castTime = (decodedInteger/1000)+" seconds";
        else
            castTime = "Instant";
       
        // and we get to do it again!
        decodedInteger = (Integer.decode( recastTime )).intValue();
        if( decodedInteger > 0 )
            recastTime = (decodedInteger/1000)+" seconds";
        else
            recastTime = "Instant";
       
        // duration is in ticks
        decodedInteger = (Integer.decode( duration )).intValue();
        if( decodedInteger > 0 )
            duration = duration;
        else
            duration = "0";
       
        // and again for ae Duration
        decodedInteger = (Integer.decode( aeDuration )).intValue();
        if( decodedInteger > 0 )
            aeDuration = (decodedInteger/1000)+" seconds";
        else
            aeDuration = "0";

        // reagents prints a useless number. Needs manual entry
        decodedInteger = (Integer.decode( reagents )).intValue();
       
        if( decodedInteger == 10028)
        	reagents = "Peridot";
        else if( decodedInteger == 31291)
        	reagents = "Summoned: Peridot";
        else if( decodedInteger == 10024)
        	reagents = "Pearl";
        else if( decodedInteger >= 0 )
            reagents = "[[Fill In Missing Reagents]]";
        else
            reagents = "";
        
        // reagents2 prints a useless number. Needs manual entry
        decodedInteger = (Integer.decode( reagents2 )).intValue();
       
        if( decodedInteger == 10028)
        	reagents2 = "Peridot";
        else if( decodedInteger == 31291)
        	reagents2 = "Summoned: Peridot";
        else if( decodedInteger == 10024)
        	reagents2 = "Pearl";
        else if( decodedInteger >= 0 )
            reagents2 = "[[Fill In Missing Reagents]]";
        else
            reagents2 = "";
       
        // deal with indoor V outdoor spells
        zoneType = Tables.getZoneType ( zoneType );
       
        // resistType has a look up table
        resistType = Tables.getResistances( resistType );
       
        // Effect processing is done during the inital parse around line 200
       
        // targets has a look up table
        targets = Tables.getTargets( targets );
       
        // skill has a look up table
        skill = Tables.getSkill( skill );
       
        // classes are confusing, and likely need to be done custom for your app
        classToken = Tables.getClass( classToken );
        
        spellType = Tables.getSpellType( spellType );
    }//proceessTokens
   
    /**
     * The work horse method. This is where the parsing and formatting is done. 
     * So if you need to change the output, this is where you edit.
     * 
     * @param inputFile - The spells_us.txt file that contains all unparsed spell data
     * @param outputFile - The location where we will save this formatted data
     * @throws FileNotFoundException - If the file does not exist at the given location
     * @throws IOException - For any number of issues, mainly as a protection
     */
    public static void mainProcess( String inputFile, String outputFile ) throws FileNotFoundException, IOException {
        // We have the filepath hardcoded. A GUI will fix this for release
        String filepath = inputFile;
        sodSpellFile = new File( filepath );
       
        System.out.println( "Loading File: " + sodSpellFile.getName());
      
        // Attempt to read the file
        
        // These statements are so java reads a file without efficently
        fileReader = new FileReader( sodSpellFile );
        inputReader = new BufferedReader( fileReader );
      
        // Ditto but for writing files
        fileWriter = new FileWriter( outputFile );
        outputWriter = new BufferedWriter( fileWriter );
       
        //Get the first line
        String curLine = inputReader.readLine();
      
 
        // While there is something left to read...
        while( curLine != null ){
           
            // Splits data by the '^' char, and stores in an array of 175
            String[] result = curLine.split("\\^");
           
           
            // Now we pick and choose what we want to save. The index it is
            // saved to is based on the OpenSpell.xml document attached to
            // this project. Credits can be found in the Tables Class
            id = result[0];
            name = result[1];
            notes = result[6];
            range = result[9];
            aeRange = result[10];
            castTime = result[13];
            recastTime = result[15];
            duration = result[17];
            aeDuration = result[18];
            manaCost = result[19];
            icon1 = result[56];
            icon2 = result[144];
            spellType = result[83];
            reagents = result[58];
            reagents2 = result[59];
            reagentAmt = result[62];
            reagentAmt2 = result[63];
            resistType = result[85];
            push = result[11];
           
            // Effects are a bit confusing...
            // Indexes 86-97 are the individual effects
            // Indexes 70-81 are the effects formulas
            // Indexes 20-31 are the minimum values mapped to those effects
            // Indexes 32-55 are supposed to be the max values, but 32-43 don't seem to be
            // so 86 has the value at 20, 90 the value of 25.. etc...
           
            System.out.println("******************");
            String[] slots = {"","","","","","","","","","","",""};
            int counter = 0;
             for( int x = 86; x < 98; x++){
            	
                int effectVal = (Integer.decode( result[x] )).intValue();
                effects = "";    // Clears the string from last iteration
                
                if( effectVal < 200 ){
                	int effectFormula = (Integer.decode( result[x-16] )).intValue();
                	int minVal = (Integer.decode( result[x-66] )).intValue();
                	int maxVal = (Integer.decode( result[x-42] )).intValue();
                	System.out.println(effectVal+" min: "+minVal+" max: "+maxVal);
                	effects = Tables.getEffects(effectVal,minVal,maxVal);
                	if(effectVal != 11 && effectVal != 123){
                		if( minVal < 0 && maxVal < 0 && Math.abs(minVal) != Math.abs(maxVal))
	                   		effects = effects+" to "+result[x-42];
                		else if( minVal < 0 && maxVal != 0 && Math.abs(minVal) != Math.abs(maxVal)) 
	                   		effects = effects+" to -"+result[x-42];
	                    else if( maxVal > 0 && Math.abs(minVal) != Math.abs(maxVal))
	                   		effects = effects+" to "+result[x-42];
                	}
                	slots[counter] = effects;
                	counter++;
                }
            }
          
            targets = result[98];
            skill = result[100];
            zoneType = result[101];
           
            // Classes work a bit different from everything else,
            // Each class has a slot. If the slot reads 255 then the class
            // Can't use it. If it is < 65, then they can, and thats the min
            // level.
            warMinLevel = result[104];
            clrMinLevel = result[105];
            palMinLevel = result[106];
            rngMinLevel = result[107];
            shdMinLevel = result[108];
            druMinLevel = result[109];
            mnkMinLevel = result[110];
            brdMinLevel = result[111];
            rogMinLevel = result[112];
            shmMinLevel = result[113];
            necMinLevel = result[114];
            wizMinLevel = result[115];
            magMinLevel = result[116];
            encMinLevel = result[117];
            bstMinLevel = result[118];
           
            // We put all the data into one big string to send over to parse
            // during processStrings
            classToken = warMinLevel+ "^" + clrMinLevel+ "^" + palMinLevel+ "^" + rngMinLevel+ "^" +
                                shdMinLevel+ "^" +druMinLevel+ "^" + mnkMinLevel+ "^" + brdMinLevel+ "^" +
                                rogMinLevel+ "^" + shmMinLevel+ "^" +necMinLevel+ "^" + wizMinLevel+ "^" +
                                magMinLevel+ "^" + encMinLevel+ "^" + bstMinLevel;
           
            resistAdjust = result[147];
      
            // Subroutine here for readability! See the method for why
            processStrings();
           
            /** ~~~~This is the section you probably want to change~~~~ **/
           
            
            name = name.replace(' ', '_');
            if(Integer.valueOf(reagentAmt) == -1){
            	reagentAmt = "0";
            }
            String nameURL = "http://wiki.shardsofdalaya.com/index.php?title=Spell:_"+name;
           
            int set = (Integer.valueOf(icon2) / 36) + 1;
            int slot = (Integer.valueOf(icon2) % 36) + 1;
            
            String setString = set+"";
            String slotString = "";
            if(slot < 10){
            	slotString = "0"+slot;
            }
            else {
            	slotString = slot+"";
            }
            
            String finalSpellOutput =
            "{{spelltable| pcclass = "+ classToken + "\n"+
            "   | IDnum = " +  id + "\n"+
            "   | name = " +  name + "\n"+
            "   | mana = " + manaCost + "\n"+
            "   | range = " + range + "\n"+
            "   | skill = " + skill + "\n"+
            "   | cast = " + castTime + "\n"+
            "   | aerad = " + aeRange + "\n"+
            "   | restype = " + resistType + "\n"+
            "   | recharge = " + recastTime + "\n"+
            "   | aedur = " + aeDuration + "\n"+
            "   | resadj = " + resistAdjust + "\n"+
            "   | duration = " + duration + "\n"+
            "   | ttype = "+ targets + "\n"+
            "   | restr = " + zoneType + "\n"+
            "   | reagenttype1 = " + reagents+ "\n"+
            "   | reagentamount1 = " + reagentAmt+ "\n"+
            "   | reagenttype2 = " + reagents2+ "\n"+
            "   | reagentamount2 = " + reagentAmt2+ "\n"+
            "   | spelltype = "+ spellType +"\n"+
            "   | effects = \n"+
            "   | push = "+ push +"\n"+ 
            "   | slot1 = "+ slots[0] +"\n"+
            "   | slot2 = "+ slots[1] +"\n"+
            "   | slot3 = "+ slots[2] +"\n"+
            "   | slot4 = "+ slots[3] +"\n"+
            "   | slot5 = "+ slots[4] +"\n"+
            "   | slot6 = "+ slots[5] +"\n"+
            "   | slot7 = "+ slots[6] +"\n"+
            "   | slot8 = "+ slots[7] +"\n"+
            "   | slot9 = "+ slots[8] +"\n"+
            "   | slot10 = "+ slots[9] +"\n"+
            "   | slot11 = "+ slots[10] +"\n"+
            "   | slot12 = "+ slots[11] +"\n"+
            "   | image =  "+ setString+"_"+slotString +"\n"+
            "   | notes = "+ "\n"+
            "   | spellline = \n"+
            "   | nextspell = \n"+
            "   | prevspell = \n"+
            "}}";
            
            
            // Writes the finalized String to a file
            outputWriter.write( nameURL + "~\n");
            outputWriter.write( finalSpellOutput );
            outputWriter.write( "\n[[Category: Spells]]~\n" );
            outputWriter.flush();
       
           
            /** ~~~~ End of Output Section ~~~~ **/
           
            // Move on to the next spell and reset the counter
            curLine = inputReader.readLine();
        }
    
  
        // Closes the streams up since we're done, but pray they don't IOE
        try {
            fileReader.close();
            inputReader.close();
            outputWriter.close();
            fileWriter.close();
        } catch (IOException iow) {
            System.err.println( "Critical Error: Steam Closing Failed. Oops!");
        }
        
        System.out.println( "Parse Complete" );
    }//mainProcess
  
}//Main