// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2022
//                www.magicbane.com

package engine;

import engine.gameManager.ConfigManager;
import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector2f;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.objects.AbstractCharacter;
import engine.objects.ItemTemplate;
import engine.objects.Shrine;
import engine.objects.Zone;
import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.concurrent.ThreadLocalRandom;

/*
 * MagicBane engine enumeration class.
 *
 * All enumerations accessed by multiple
 * classes should be defined here to keep
 * the imports consolidated.
 */

public class mbEnums {

    public static <T extends Enum<T>> int toInt(EnumSet<T> enumSet) {

        int bitvector = 0;

        for (T value : enumSet)
            bitvector |= 1 << value.ordinal();

        return bitvector;
    }

    public static <T extends Enum<T>> long toLong(EnumSet<T> enumSet) {

        long bitvector = 0L;

        for (T value : enumSet)
            bitvector |= 1L << value.ordinal();

        return bitvector;
    }

    public static <E extends java.lang.Enum<E>> EnumSet<E> fromLong(long bitVector, Class<E> enumClass) {

        // Bitvector -> EnumSet without the EnumBitvector dependency

        EnumSet<E> enumSet = EnumSet.noneOf(enumClass);

        // Early exit if empty set

        if (bitVector == 0)
            return enumSet;

        for (E enumValue : enumClass.getEnumConstants()) {
            if ((bitVector & (1L << enumValue.ordinal())) != 0) {
                enumSet.add(enumValue);
            }
        }
        return enumSet;
    }

    public static <E extends java.lang.Enum<E>> EnumSet<E> fromString(String dbString, Class<E> enumClass) {

        // Build enumset from ; delimited string (from db)

        EnumSet<E> enumSet = EnumSet.noneOf(enumClass);

        // Early exit if empty set

        if (dbString.isEmpty())
            return enumSet;

        String[] enumArray = dbString.split(";");

        for (String enumeration : enumArray) {
            E parsedEnum = Enum.valueOf(enumClass, enumeration);
            enumSet.add(parsedEnum);
        }

        return enumSet;
    }

    public static <E extends Enum<E>> String asString(EnumSet<E> enumSet) {

        if (enumSet == null || enumSet.isEmpty())
            return "";

        StringBuilder result = new StringBuilder();

        for (E element : enumSet)
            result.append(element.name()).append(";");

        // Remove the trailing comma

        if (result.length() > 1)
            result.setLength(result.length() - 1);

        return result.toString();
    }

    public enum PetitionType {
        NONE,
        GENERAL,
        FEEDBACK,
        STUCK,
        HARASSMENT,
        EXPLOIT,
        BUG,
        GAME_STOPPER,
        TECH_SUPPORT

    }

    public enum PetitionSubType {
        NONE,
        DUPE,
        LEVELLING,
        SKILL_GAIN,
        KILLING,
        POLICY,
        OTHER,
        VIDEO,
        SOUND,
        NETWORKKl

    }

    public enum MobFlagType {
        AGGRESSIVE,
        CANROAM,
        CALLSFORHELP,
        RESPONDSTOCALLSFORHELP,
        HUMANOID,
        UNDEAD,
        BEAST,
        DRAGON,
        RAT,
        SENTINEL,
    }

    public enum MonsterType {
        Aelfborn,
        All,
        Animal,
        Aracoix,
        Celestial,
        Centaur,
        Construct,
        CSR,
        Dragon,
        Dwarf,
        Elf,
        Giant,
        Goblin,
        Grave,
        HalfGiant,
        Human,
        Infernal,
        Insect,
        Irekei,
        Minotaur,
        Monster,
        NecroPet,
        NPC,
        Pet,
        Plant,
        Rat,
        Reptile,
        Shade,
        Siege,
        Summoned,
        Troll,
        Undead,
        Nephilim,
        Vampire,
        SiegeEngineer

    }

    public enum CharacterSex {
        MALE,
        FEMALE,
        FUZZY,
        OTHER
    }

    public enum RaceType {

        // RaceRuneID / AggroType, isFemale

        AELFMALE(2000, MonsterType.Aelfborn, RunSpeed.STANDARD, CharacterSex.MALE, 1.05f),
        AELFFEMALE(2001, MonsterType.Aelfborn, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.05f),
        ARACOIXMALE(2002, MonsterType.Aracoix, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        ARACOIXFEMALE(2003, MonsterType.Aracoix, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
        CENTAURMALE(2004, MonsterType.Centaur, RunSpeed.CENTAUR, CharacterSex.MALE, 1.2f),
        CENTAURFEMALE(2005, MonsterType.Centaur, RunSpeed.CENTAUR, CharacterSex.FEMALE, 1.2f),
        DWARFMALE(2006, MonsterType.Dwarf, RunSpeed.STANDARD, CharacterSex.MALE, 0.80000001f),
        ELFMALE(2008, MonsterType.Elf, RunSpeed.STANDARD, CharacterSex.MALE, 1.4f),
        ELFFEMALE(2009, MonsterType.Elf, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.1f),
        HALFGIANTMALE(2010, MonsterType.HalfGiant, RunSpeed.STANDARD, CharacterSex.MALE, 1.15f),
        HUMANMALE(2011, MonsterType.Human, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        HUMANFEMALE(2012, MonsterType.Human, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
        IREKEIMALE(2013, MonsterType.Irekei, RunSpeed.STANDARD, CharacterSex.MALE, 1.1f),
        IREKEIFEMALE(2014, MonsterType.Irekei, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.1f),
        SHADEMALE(2015, MonsterType.Shade, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        SHADEFEMALE(2016, MonsterType.Shade, RunSpeed.STANDARD, CharacterSex.FEMALE, 1),
        MINOMALE(2017, MonsterType.Minotaur, RunSpeed.MINOTAUR, CharacterSex.MALE, 1.3f),
        ARCHONMALE(2018, MonsterType.Celestial, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        HALEGIANTOLDMALE(2019, MonsterType.HalfGiant, RunSpeed.STANDARD, CharacterSex.MALE, 1.15f),
        CSRFEMALE(2020, MonsterType.CSR, RunSpeed.STANDARD, CharacterSex.FEMALE, 0.66000003f),
        CSRMALE(2021, MonsterType.CSR, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        NEPHMALE(2025, MonsterType.Nephilim, RunSpeed.STANDARD, CharacterSex.MALE, 1.1f),
        NEPHFEMALE(2026, MonsterType.Nephilim, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.1f),
        HALFGIANTFEMALE(2027, MonsterType.HalfGiant, RunSpeed.STANDARD, CharacterSex.FEMALE, 1.15f),
        VAMPMALE(2028, MonsterType.Vampire, RunSpeed.STANDARD, CharacterSex.MALE, 1),
        VAMPFEMALE(2029, MonsterType.Vampire, RunSpeed.STANDARD, CharacterSex.FEMALE, 1);

        @SuppressWarnings("unchecked")
        private static final HashMap<Integer, RaceType> _raceTypeByID = new HashMap<>();
        private final MonsterType monsterType;
        private final CharacterSex characterSex;
        private final RunSpeed runSpeed;
        private final float scaleHeight;
        int runeID;

        RaceType(int runeID, MonsterType aggroType, RunSpeed runspeed, CharacterSex characterSex, float scaleHeight) {
            this.runeID = runeID;
            this.monsterType = aggroType;
            this.runSpeed = runspeed;
            this.characterSex = characterSex;
            this.scaleHeight = scaleHeight;
        }

        public static RaceType getRaceTypebyRuneID(int runeID) {
            return _raceTypeByID.get(runeID);
        }

        public static void initRaceTypeTables() {

            for (RaceType raceType : RaceType.values()) {
                _raceTypeByID.put(raceType.runeID, raceType);
            }
        }

        public int getRuneID() {
            return this.runeID;
        }

        public float getScaleHeight() {
            return this.scaleHeight;
        }

        public MonsterType getMonsterType() {
            return monsterType;
        }

        public RunSpeed getRunSpeed() {
            return runSpeed;
        }

        public CharacterSex getCharacterSex() {
            return characterSex;
        }
    }

    public enum RunSpeed {

        SENTINEL(0, 0, 0, 0, 0, 0, 0),
        STANDARD(6.1900001f, 13.97f, 4.2199998f, 13.97f, 6.3299999f, 18.379999f, 6.5f),
        CENTAUR(6.1900001f, 16.940001f, 5.5500002f, 16.940001f, 6.3299999f, 18.379999f, 6.5f),
        MINOTAUR(6.6300001f, 15.95f, 4.2199998f, 15.95f, 6.3299999f, 18.379999f, 6.5f);

        private final float walkStandard;
        private final float walkCombat;
        private final float runStandard;
        private final float runCombat;
        private final float swim;
        private final float flyRun;
        private final float flyWalk;

        RunSpeed(float walkStandard, float runStandard, float walkCombat, float runCombat, float flyWalk, float flyRun, float swim) {
            this.walkStandard = walkStandard;
            this.walkCombat = walkCombat;
            this.runStandard = runStandard;
            this.runCombat = runCombat;
            this.swim = swim;
            this.flyRun = flyRun;
            this.flyWalk = flyWalk;
        }


        public float getWalkStandard() {
            return walkStandard;
        }

        public float getWalkCombat() {
            return walkCombat;
        }

        public float getRunStandard() {
            return runStandard;
        }

        public float getRunCombat() {
            return runCombat;
        }

        public float getFlyRun() {
            return flyRun;
        }


        public float getFlyWalk() {
            return flyWalk;
        }

    }

    public enum FriendListType {

        VIEWHERALDRY(1),
        ADDHERALDRY(4),
        REMOVEHERALDRY(6),
        DEALTHS(7),
        KILLS(9),
        VIEWCONDEMN(11),
        ADDCONDEMN(14),
        REMOVECONDEMN(15),
        TOGGLEACTIVE(17),
        REVERSEKOS(19),
        VIEWFRIENDS(25),
        TOITEM(23),
        ADDFRIEND(28),
        REMOVEFRIEND(30);

        private final int listType;

        FriendListType(int listType) {
            this.listType = listType;
        }

        public static FriendListType getListTypeByID(int listType) {

            FriendListType outType = null;

            for (FriendListType friendListType : FriendListType.values()) {
                if (friendListType.listType == listType)
                    outType = friendListType;
            }
            return outType;
        }

    }

    public enum DispatchChannel {
        PRIMARY(0),
        SECONDARY(1);

        private final int channelID;

        DispatchChannel(int channelID) {
            this.channelID = channelID;
        }

        public int getChannelID() {
            return this.channelID;
        }

    }

    public enum PvpHistoryType {
        KILLS,
        DEATHS
    }

    public enum ChatMessageType {
        ERROR,
        INFO,
        MOTD
    }

    public enum DataRecordType {
        PVP,
        CHARACTER,
        BANE,
        GUILD,
        CITY,
        ZONE,
        REALM,
        MINE
    }

    public enum RecordEventType {
        CREATE,  // Shared with city/guild
        DISBAND,
        DESTROY, // City events
        CAPTURE,
        TRANSFER,
        PENDING,
        DEFEND,
        LOST // Realm event
    }

    public enum CharterType {
        FEUDAL(-600065291, 5060000),
        MERCANTILE(-15978914, 5060400),
        BELLIGERENT(762228431, 5060800);

        private final int charterID;
        private final int meshID;

        CharterType(int charterID, int meshID) {
            this.charterID = charterID;
            this.meshID = meshID;
        }

        public static CharterType getCharterTypeByID(int charterID) {
            CharterType outType = null;

            for (CharterType charterType : CharterType.values()) {
                if (charterType.charterID == charterID)
                    outType = charterType;
            }
            return outType;
        }

        public int getMeshID() {
            return meshID;
        }
    }


    public enum ChatChannelType {
        SYSTEM(1),
        FLASH(2),
        COMMANDER(3),
        NATION(5),
        LEADER(6),
        SHOUT(7),
        INFO(10),
        GUILD(12),
        INNERCOUNCIL(13),
        GROUP(14),
        CITY(15),
        SAY(16),
        EMOTE(17),
        TELL(19),
        COMBAT(20);

        private final int channelID;

        ChatChannelType(int channelID) {
            this.channelID = channelID;
        }

        public int getChannelID() {
            return this.channelID;
        }
    }

    public enum OwnerType {
        Npc,
        PlayerCharacter,
        Account,
        Mob
    }

    public enum SiegePhase {
        ERRANT,
        CHALLENGE,
        STANDOFF,
        WAR,
        CEASEFIRE
    }

    public enum SiegeResult {
        PENDING,
        DEFEND,
        DESTROY,
        CAPTURE
    }

    public enum TaxType {
        PROFIT,
        WEEKLY,
        NONE

    }

    public enum Ruins {

        ESTRAGOTH(569),
        KARFELL(570),
        MORELAN(571),
        REGARS(572),
        HALLOS(573),
        WESTERMORE(574),
        EYWAN(575),
        CAER(576);

        private final int zoneUUID;

        Ruins(int uuid) {
            this.zoneUUID = uuid;
        }

        public static Ruins getRandomRuin() {

            Ruins ruins;

            ruins = Ruins.values()[ThreadLocalRandom.current()
                    .nextInt(Ruins.values().length)];

            return ruins;
        }

        public Vector3fImmutable getLocation() {

            Zone ruinZone;
            Vector3fImmutable spawnLocation;

            // Send to SDR if so configured

            if (ConfigManager.MB_USE_RUINS.getValue().equalsIgnoreCase("true")) {
                ruinZone = ZoneManager.getZoneByUUID(this.zoneUUID);
                spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc(), 30);
            } else {
                ruinZone = ZoneManager.getZoneByName("sea dog's rest");

                // 14001 does not have a banestone to bind at

                if (ruinZone.templateID == 14001)
                    spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc(), 30);
                else
                    spawnLocation = Vector3fImmutable.getRandomPointOnCircle(ruinZone.getLoc()
                            .add(new Vector3fImmutable(-196.016f, 2.812f, 203.621f)), 30);
            }


            return spawnLocation;
        }

    }

    public enum Guards {

        HumanArcher(13.97f, 13.97f, 6.19f, 4.2199998f, 18.38f, 6.33f, 6.5f),
        HumanGuard(13.97f, 13.97f, 6.19f, 4.2199998f, 18.38f, 6.33f, 6.5f),
        HumanMage(13.97f, 13.97f, 6.19f, 4.2199998f, 18.38f, 6.33f, 6.5f),
        UndeadArcher(14.67f, 14.67f, 6.5f, 4.44f, 18.38f, 6.33f, 6.5f),
        UndeadGuard(14.67f, 14.67f, 6.5f, 4.44f, 18.38f, 6.33f, 6.5f),
        UndeadMage(14.67f, 14.67f, 6.5f, 4.44f, 18.38f, 6.33f, 6.5f);

        private final float runSpeed;
        private final float runCombatSpeed;
        private final float walkSpeed;
        private final float walkCombatSpeed;
        private final float fly;
        private final float flyWalk;
        private final float swim;

        Guards(float runSpeed, float runCombatSpeed, float walkSpeed, float walkCombatSpeed, float fly, float flyWalk, float swim) {
            this.runSpeed = runSpeed;
            this.runCombatSpeed = runCombatSpeed;
            this.walkSpeed = walkSpeed;
            this.walkCombatSpeed = walkCombatSpeed;
            this.fly = fly;
            this.flyWalk = flyWalk;
            this.swim = swim;
        }

        public float getRunSpeed() {
            return runSpeed;
        }

        public float getRunCombatSpeed() {
            return runCombatSpeed;
        }

        public float getWalkSpeed() {
            return walkSpeed;
        }

        public float getWalkCombatSpeed() {
            return walkCombatSpeed;
        }

        public float getFly() {
            return fly;
        }

        public float getSwim() {
            return swim;
        }

        public float getFlyWalk() {
            return flyWalk;
        }
    }

    public enum PortalType {

        EARTH(6f, 19.5f, 128),
        AIR(-6f, 19.5f, 256),
        FIRE(15f, 7.5f, 512),
        WATER(-15f, 8.5f, 1024),
        SPIRIT(0, 10.5f, 2048),
        CHAOS(22f, 3.5f, 8192),
        OBLIV(0f, 42f, 16384),
        MERCHANT(-22f, 4.5f, 4096),
        FORBID(0.0f, 0.0f, 0);

        public final Vector2f offset;
        public final int effectFlag;

        PortalType(float offsetX, float offsetY, int effectFlag) {

            this.offset = new Vector2f(offsetX, offsetY);
            this.effectFlag = effectFlag;

        }
    }

    // Enum for Item type flags

    public enum ItemType {
        DECORATION,
        WEAPON,
        ARMOR,
        BASE,
        GOLD,
        SCROLL,
        BOOK,
        WAND,
        POTION,
        KEY,
        CHARTER,
        GUILDTREE,
        SOUNDSOURCE,
        JEWELRY,
        CONTAINER,
        FOUNTAIN,
        FOOD,
        DRINKCONTAINER,
        MAPMARKER,
        DEED,
        EMPLOYMENTCONTRACT,
        PETTOTEM,
        SLAVECOLLAR,
        BLANKKEY,
        WARRANT,
        FURNITUREDEED,
        TENT,
        REAGENT,
        DEVICE,
        FORMULA,
        BUCKET,
        TREASURE,
        RUNE,
        OFFERING,
        RESOURCE,
        REALMCHARTER;
    }

    // Enum to derive effects for active spires from blueprintUUID

    public enum SpireType {

        WATCHFUL(1800100, (1 << 23), -1139520957),
        GROUNDING(1800400, (1 << 24), -1733819072),
        BINDING(1800700, (1 << 25), -1971545187),
        WARDING(1801000, (1 << 26), 2122002462),
        GUILEFUL(1801300, (1 << 27), -1378972677),
        BALEFUL(1801600, -1, 1323012132),
        ARCANE(1801900, (1 << 30), 1323888676),
        WOUNDING(1802200, (1 << 10), 1357392095),
        WEARYING(1802500, (1 << 10), 1350838495),
        CONFUSING(1802800, (1 << 10), 1358702815),
        CHILLING(1803100, (1 << 1), 1332155165),
        SEARING(1803400, (1 << 2), -1401744610),
        THUNDERING(1803700, (1 << 3), -443544829),
        UNHOLY(1804000, (1 << 4), 1330320167),
        BEFUDDLING(1804300, (1 << 5), 1489317547),
        WRATHFUL(1804600, (1 << 6), 165160210),
        SPITEFUL(1804900, (1 << 7), 1238906779),
        ENFEEBLING(1805200, (1 << 8), -908578401),
        CONFOUNDING(1805500, (1 << 9), 165165842),
        DISTRACTING(1805800, (1 << 10), 1238906697),
        WOLFPACK(1806100, (1 << 4), 416932375);

        private final int blueprintUUID;
        private final int effectFlag;
        private final int token;

        SpireType(int blueprint, int flag, int token) {
            this.blueprintUUID = blueprint;
            this.effectFlag = flag;
            this.token = token;
        }

        public static SpireType getByBlueprintUUID(int uuid) {

            SpireType outType = SpireType.GROUNDING;

            for (SpireType spireType : SpireType.values()) {

                if (spireType.blueprintUUID == uuid) {
                    outType = spireType;
                    return outType;
                }

            }

            return outType;
        }

        public int getBlueprintUUID() {
            return blueprintUUID;
        }

        public int getEffectFlag() {
            return effectFlag;
        }

        public int getToken() {
            return token;
        }

        public EffectsBase getEffectBase() {
            return PowersManager.getEffectByToken(token);
        }

    }

    public enum TransactionType {
        MAINTENANCE(43),
        WITHDRAWL(80),
        DEPOSIT(82),
        MINE(81),
        MIGRATION(83),
        PLAYERREWARD(84),
        TAXRESOURCE(85),
        TAXRESOURCEDEPOSIT(86);

        private final int ID;

        TransactionType(int ID) {
            this.ID = ID;
        }

        public int getID() {
            return ID;
        }
    }

    public enum TargetColor {

        White,
        Green,
        Cyan,
        Blue,
        Yellow,
        Orange,
        Red;

        public static TargetColor getCon(AbstractCharacter source,
                                         AbstractCharacter target) {
            return getCon(source.getLevel(), target.getLevel());
        }

        public static TargetColor getCon(short sourceLevel, short targetLevel) {
            if (targetLevel > (sourceLevel + 2))
                return Red;
            else if (targetLevel == (sourceLevel + 2))
                return Orange;
            else if (targetLevel == (sourceLevel + 1))
                return Yellow;

            short lowestBlue = (short) (sourceLevel - (((sourceLevel / 5)) + 2));

            if (lowestBlue <= targetLevel)
                return Blue;
            else if (lowestBlue - 1 <= targetLevel)
                return Cyan;
            else if (lowestBlue - 2 <= targetLevel)
                return Green;
            return White;
        }
    }

    public enum DamageType {
        NONE,
        CRUSHING,
        SLASHING,
        SIEGE,
        PIERCING,
        MAGIC,
        BLEEDING,
        POISON,
        MENTAL,
        HOLY,
        UNHOLY,
        LIGHTNING,
        FIRE,
        COLD,
        HEALING,
        ACID,
        DISEASE,
        UNKNOWN,
        // these added for immunities
        ATTACK,
        POWERS,
        COMBAT,
        SPIRES,
        SNARE,
        STUN,
        BLINDNESS,
        ROOT,
        FEAR,
        CHARM,
        POWERINHIBITOR,
        DEBUFF,
        STEAL,
        DRAIN;

        public static DamageType getDamageType(String modName) {

            if (modName.isEmpty())
                return DamageType.NONE;

            if(modName.toLowerCase().equals("blind"))
                modName = "BLINDNESS";

            if(modName.toLowerCase().equals("powerblock"))
                modName = "POWERINHIBITOR";

            //validity check for not looking up damage type that doesn't exist
            boolean valid = false;
            for(DamageType type : DamageType.values()){
                if(type.name().equals(modName))
                    valid = true;
            }

            if(!valid)
                return DamageType.NONE;

            DamageType damageType;

            try {
                damageType = DamageType.valueOf(modName.replace(",", "").toUpperCase());
            } catch (Exception e) {
                Logger.error(e);
                return DamageType.NONE;
            }
            return damageType;
        }
    }


    public enum SourceType {
        None,
        Abjuration,
        Acid,
        AntiSiege,
        Archery,
        Axe,
        Bardsong,
        Beastcraft,
        Benediction,
        BladeWeaving,
        Bleeding,
        Blind,
        Block,
        Bloodcraft,
        Bow,
        Buff,
        Channeling,
        Charm,
        Cold,
        COLD,
        Constitution,
        Corruption,
        Crossbow,
        Crushing,
        Dagger,
        DaggerMastery,
        DeBuff,
        Dexterity,
        Disease,
        Dodge,
        Dragon,
        Drain,
        Earth,
        Effect,
        Exorcism,
        Fear,
        Fire,
        FIRE,
        Fly,
        Giant,
        GreatAxeMastery,
        GreatSwordMastery,
        Hammer,
        Heal,
        Healing,
        Holy,
        HOLY,
        ImmuneToAttack,
        ImmuneToPowers,
        Intelligence,
        Invisible,
        Lightning,
        LIGHTNING,
        Liturgy,
        Magic,
        MAGIC,
        Mental,
        MENTAL,
        NatureLore,
        Necromancy,
        Parry,
        Piercing,
        Poison,
        POISON,
        PoleArm,
        Powerblock,
        Rat,
        ResistDeBuff,
        Restoration,
        Root,
        Shadowmastery,
        Siege,
        Slashing,
        Snare,
        Sorcery,
        Spear,
        SpearMastery,
        Spirit,
        Staff,
        Stormcalling,
        Strength,
        Stun,
        Summon,
        Sword,
        SwordMastery,
        Thaumaturgy,
        Theurgy,
        Transform,
        UnarmedCombat,
        UnarmedCombatMastery,
        Unholy,
        UNHOLY,
        Unknown,
        Warding,
        Warlockry,
        WayoftheGaana,
        WearArmorHeavy,
        WearArmorLight,
        WearArmorMedium,
        Wereform,
        Athletics,
        AxeMastery,
        Bargaining,
        BladeMastery,
        FlameCalling,
        GreatHammerMastery,
        HammerMastery,
        Leadership,
        PoleArmMastery,
        Running,
        StaffMastery,
        Throwing,
        Toughness,
        WayoftheWolf,
        WayoftheRat,
        WayoftheBear,
        Orthanatos,
        SunDancing,
        //Power categories.
        AE,
        AEDAMAGE,
        BEHAVIOR,
        BLESSING,
        BOONCLASS,
        BOONRACE,
        BREAKFLY,
        BUFF,
        CHANT,
        DAMAGE,
        DEBUFF,
        DISPEL,
        FLIGHT,
        GROUPBUFF,
        GROUPHEAL,
        HEAL,
        INVIS,
        MOVE,
        RECALL,
        SPECIAL,
        SPIREDISABLE,
        SPIREPROOFTELEPORT,
        STANCE,
        STUN,
        SUMMON,
        TELEPORT,
        THIEF,
        TRACK,
        TRANSFORM,
        VAMPDRAIN,
        WEAPON,
        Wizardry;

        public static SourceType GetSourceType(String modName) {
            SourceType returnMod;
            if (modName.isEmpty())
                return SourceType.None;

            try {
                returnMod = SourceType.valueOf(modName.replace(",", ""));
            } catch (Exception e) {
                Logger.error(modName);
                Logger.error(e);
                return SourceType.None;
            }
            return returnMod;
        }
    }

    public enum EffectSourceType {
        None,
        AttackSpeedBuff,
        Bleeding,
        Blind,
        Buff,
        Chant,
        Charm,
        Cold,
        Combat,
        ConstitutionBuff,
        Crushing,
        DamageShield,
        DeathShroud,
        DeBuff,
        Disease,
        Drain,
        Earth,
        Effect,
        Fear,
        Fire,
        Flight,
        Fortitude,
        Heal,
        Holy,
        Invisibility,
        Invulnerability,
        Lightning,
        Magic,
        Mental,
        Multielement,
        PetBuff,
        Piercing,
        Poison,
        Powerblock,
        RecoveryManaBuff,
        ResistDeBuff,
        Root,
        Siege,
        SiegeBuff,
        SiegeDamage,
        Silence,
        Slashing,
        Snare,
        Stance,
        Stun,
        Summon,
        Transform,
        Unholy,
        Wereform,
        WereformATRBuff,
        WereformConBuff,
        WereformDexBuff,
        WereformHPRecBuff,
        WereformMoveBuff,
        WereformPhysResBuff,
        WereformSPRecBuff,
        WereformStrBuff;

        public static EffectSourceType GetEffectSourceType(String modName) {
            EffectSourceType returnMod;
            if (modName.isEmpty())
                return EffectSourceType.None;

            try {
                returnMod = EffectSourceType.valueOf(modName.replace(",", ""));
            } catch (Exception e) {
                Logger.error(e);
                return EffectSourceType.None;
            }
            return returnMod;
        }
    }

    public enum StackType {
        None,
        AggRangeDeBuff,
        ArcheryPrecisionBuff,
        AttackDebuff,
        AttackSpeedBuff,
        AttackSpeedDeBuff,
        AttackValueBuff,
        AttackValueDebuff,
        AttrCONBuff,
        AttrCONDebuff,
        AttrDEXBuff,
        AttrINTBuff,
        AttrSPRBuff,
        AttrSTRBuff,
        Bleeding,
        Blindness,
        BluntResistanceDebuff,
        BMHealing,
        Charm,
        ClassBoon,
        Confusion,
        DamageAbsorber,
        DamageDebuff,
        DamageModifierBuff,
        DamageShield,
        DeathShroud,
        DefenseBuff,
        DefenseBuffGroup,
        DefenseDebuff,
        DetectInvis,
        DrainImmunity,
        ElementalDeBuff,
        EnchantWeapon,
        Fear,
        Flight,
        Frenzy,
        GroupHeal,
        HealingBuff,
        HealOverTime,
        HealResBuff,
        HealthPotion,
        IgnoreStack,
        Invisible,
        ManaPotion,
        MangonelFire,
        MeleeDamageDeBuff,
        MeleeDeBuff,
        MoveBuff,
        MoveDebuff,
        NoFear,
        NoPassiveDefense,
        NoPowerBlock,
        NoPowerInhibitor,
        NoRecall,
        NoSnare,
        NoStun,
        NoTrack,
        PassiveDefense,
        PersAttrSPRBuff,
        PetBuff,
        PierceResistanceDebuff,
        PoisonBuchinine,
        PoisonGalpa,
        PoisonGorgonsVenom,
        PoisonMagusbane,
        PoisonPellegorn,
        PowerBlock,
        PowerCostBuff,
        PowerDamageModifierBuff,
        PowerInhibitor,
        PrecisionBuff,
        Protection,
        RaceBoon,
        RecoveryHealthBuff,
        RecoveryHealthDeBuff,
        RecoveryManaBuff,
        RecoveryManaDeBuff,
        RecoveryStaminaBuff,
        RecoveryStaminaDeBuff,
        ResistanceBuff,
        ResistanceDeBuff,
        ResistanceDebuff,
        Root,
        SafeMode,
        SelfOneAttrBuff,
        SelfThreeAttrBuff,
        SelfTwoAttrBuff,
        SiegeDebuff,
        SiegeWeaponBuff,
        Silence,
        SkillDebuff,
        SlashResistanceDebuff,
        Snare,
        StackableAttrCONBuff,
        StackableAttrDEXBuff,
        StackableAttrSTRBuff,
        StackableDefenseBuff,
        StackableRecoveryHealthBuff,
        StackableRecoveryStaminaBuff,
        StaminaPotion,
        StanceA,
        StanceB,
        Stun,
        Track,
        Transform,
        WeaponMove;

        public static StackType GetStackType(String modName) {
            StackType stackType;
            if (modName.isEmpty())
                return StackType.None;

            try {
                stackType = StackType.valueOf(modName.replace(",", ""));
            } catch (Exception e) {
                Logger.error(modName);
                Logger.error(e);
                return StackType.None;
            }
            return stackType;
        }
    }

    public enum ModType {
        None,
        AdjustAboveDmgCap,
        Ambidexterity,
        AnimOverride,
        ArmorPiercing,
        AttackDelay,
        Attr,
        BlackMantle,
        BladeTrails,
        Block,
        BlockedPowerType,
        CannotAttack,
        CannotCast,
        CannotMove,
        CannotTrack,
        Charmed,
        ConstrainedAmbidexterity,
        DamageCap,
        DamageShield,
        DCV,
        Dodge,
        DR,
        Durability,
        ExclusiveDamageCap,
        Fade,
        Fly,
        Health,
        HealthFull,
        HealthRecoverRate,
        IgnoreDamageCap,
        IgnorePassiveDefense,
        ImmuneTo,
        ImmuneToAttack,
        ImmuneToPowers,
        Invisible,
        ItemName,
        Mana,
        ManaFull,
        ManaRecoverRate,
        MaxDamage,
        MeleeDamageModifier,
        MinDamage,
        NoMod,
        OCV,
        Parry,
        PassiveDefense,
        PowerCost,
        PowerCostHealth,
        PowerDamageModifier,
        ProtectionFrom,
        Resistance,
        ScaleHeight,
        ScaleWidth,
        ScanRange,
        SeeInvisible,
        Silenced,
        Skill,
        Slay,
        Speed,
        SpireBlock,
        Stamina,
        StaminaFull,
        StaminaRecoverRate,
        Stunned,
        Value,
        WeaponProc,
        WeaponRange,
        WeaponSpeed;

        public static ModType GetModType(String modName) {
            ModType modType;
            if (modName.isEmpty())
                return ModType.None;

            try {
                modType = ModType.valueOf(modName.replace(",", ""));
            } catch (Exception e) {
                Logger.error(e);
                return ModType.None;
            }
            return modType;
        }
    }

    public enum MovementState {

        IDLE,
        SITTING,
        RUNNING,
        FLYING,
        SWIMMING
    }

    public enum DoorState {

        OPEN,
        CLOSED,
        LOCKED,
        UNLOCKED
    }

    // Used with stored procedure GET_UID_ENUM() for
    // type tests against objects not yet loaded into the game.
    public enum DbObjectType {

        INVALID,
        ACCOUNT,
        BUILDING,
        CHARACTER,
        CITY,
        CONTAINER,
        GUILD,
        ITEM,
        MINE,
        MOB,
        NPC,
        SHRINE,
        WORLDSERVER,
        ZONE,
        WAREHOUSE
    }

    /**
     * Enumeration of Building Protection Status stored in the database as a
     * mysql enumfield. WARNING: This enumeration is fragile. Do not rename. Do
     * not reorder.
     */
    public enum ProtectionState {

        NONE,
        PROTECTED,
        UNDERSIEGE,
        CEASEFIRE,
        CONTRACT,
        DESTROYED,
        PENDING,
        NPC
    }

    public enum DisciplineType {

        Alchemist,
        Animator,
        Archer,
        Berserker,
        BlackMask,
        Blacksmith,
        BladeMaster,
        BladeWeaver,
        BloodProphet,
        BountyHunter,
        Clanwarden,
        Commander,
        DarkKnight,
        Duelist,
        ForgeMaster,
        GiantKiller,
        Gladiator,
        Huntsman,
        Knight,
        RatCatcher,
        RuneCaster,
        Enchanter,
        StormLord,
        Summoner,
        Sundancer,
        Trainer,
        Traveler,
        UndeadHunter,
        Werebear,
        Wererat,
        Werewolf,
        Wyrmslayer,
        Conjurer,
        Darksworn,
        Valkyr,
        BloodHorn,
        Shroudborne,
        Archmage,
        Thrall,
        Artillerist,
        Savant,
        SkyDancer,
        Prospector,
        Belgosch,
        Drannok,
        Gorgoi,
        Strigoi,
        Sapper,
        Saboteur,
        BattleMagus,
        Sanctifier,
    }

    public enum GuildHistoryType {
        JOIN(1),
        LEAVE(4),
        BANISHED(3),
        CREATE(7),
        DISBAND(5);
        private final int type;

        GuildHistoryType(int type) {
            this.type = type;
        }

        public int getType() {
            return type;
        }
    }

    public enum MovementType {
        WALK,
        RUN,
        COMBATWALK,
        COMBATRUN,
        FLYWALK,
        FLYRUN,
        SWIM;
    }

    public enum SexType {
        NONE,
        MALE,
        FEMALE
    }

    public enum ClassType {
        Fighter(SexType.NONE),
        Healer(SexType.NONE),
        Rogue(SexType.NONE),
        Mage(SexType.NONE),
        Assassin(SexType.NONE),
        Barbarian(SexType.NONE),
        Bard(SexType.NONE),
        Channeler(SexType.NONE),
        Confessor(SexType.NONE),
        Crusader(SexType.NONE),
        Doomsayer(SexType.NONE),
        Druid(SexType.NONE),
        Fury(SexType.FEMALE),
        Huntress(SexType.FEMALE),
        Prelate(SexType.NONE),
        Priest(SexType.NONE),
        Ranger(SexType.NONE),
        Scout(SexType.NONE),
        Sentinel(SexType.NONE),
        Templar(SexType.NONE),
        Thief(SexType.NONE),
        Warlock(SexType.MALE),
        Warrior(SexType.NONE),
        Wizard(SexType.NONE),
        Nightstalker(SexType.NONE),
        Necromancer(SexType.NONE),
        ;

        private final SexType sexRestriction;

        ClassType(SexType sexRestriction) {
            this.sexRestriction = sexRestriction;
        }

        public SexType getSexRestriction() {
            return sexRestriction;
        }
    }

    public enum ShrineType {

        Aelfborn(1701900, -75506007, true),
        Aracoix(1703100, -563708986, true),
        Centaur(1704000, 521645243, true),
        Dwarf(1708500, -2000467257, true),
        Elf(1703400, 1254603001, true),
        HalfGiant(1709100, 349844468, true),
        Human(1702200, 281172391, true),
        Irekei(1702800, -764988442, true),
        Minotaur(1704600, 549787579, true),
        Nephilim(1701000, -655183799, true),
        Shade(1700100, 1724071104, true),
        Assassin(1700400, 1989015892, false),
        Barbarian(1708800, 9157124, false),
        Bard(1704300, 80190554, false),
        Channeler(1702500, 5658278, false),
        Confessor(1707600, 1871658719, false),
        Crusader(1706700, -187454619, false),
        Doomsayer(1700700, -993659433, false),
        Druid(1701600, -926740122, false),
        Fury(1705500, 214401375, false),
        Huntress(1704900, 970312892, false),
        Prelate(1707000, -225200922, false),
        Priest(1705200, -535691898, false),
        Ranger(1701300, 604716986, false),
        Scout(1706100, -1497297486, false),
        Sentinel(1707300, -184898375, false),
        Templar(1707900, 826673315, false),
        Thief(1708200, 1757633920, false),
        Warlock(1706400, 1003385946, false),
        Warrior(1703700, 931048026, false),
        Wizard(1705800, 777115928, false),
        Nightstalker(1709400, 373174890, false),
        Necromancer(1709700, -319294505, false),
        Vampire(1710000, 1049274530, true);

        private final int blueprintUUID;
        private final int powerToken;
        private final ArrayList<Shrine> shrines = new ArrayList<>();
        private final boolean isRace;

        ShrineType(int blueprintUUID, int powerToken, boolean isRace) {
            this.blueprintUUID = blueprintUUID;
            this.powerToken = powerToken;
            this.isRace = isRace;

        }

        public int getBlueprintUUID() {
            return blueprintUUID;
        }

        public int getPowerToken() {
            return powerToken;
        }

        public ArrayList<Shrine> getShrinesCopy() {
            ArrayList<Shrine> copyShrines = new ArrayList<>();
            copyShrines.addAll(shrines);
            Collections.sort(copyShrines);
            return copyShrines;
        }

        public final void addShrineToServerList(Shrine shrine) {
            synchronized (shrines) {
                shrines.add(shrine);
            }
        }

        public final void RemoveShrineFromServerList(Shrine shrine) {
            synchronized (shrines) {
                shrines.remove(shrine);
            }
        }

        public boolean isRace() {
            return isRace;
        }
    }

    public enum GuildState {

        Errant(0),
        Sworn(4),
        Protectorate(6),
        Petitioner(2),
        Province(8),
        Nation(5),
        Sovereign(7);

        private final int stateID;

        GuildState(int stateID) {
            this.stateID = stateID;
        }

        public int getStateID() {
            return stateID;
        }

    }


    // Building group enumeration.
    // This is used to drive linear equations to calculate
    // structure hp, ranking times and such from within
    // the BuildingBlueprint class.
    //
    // It is also used as a bitvector flag in the npc
    // building slot mechanics.

    public enum BuildingGroup {
        NONE(0, 0),
        TOL(64f, 64f),
        BARRACK(32f, 64f),
        CHURCH(64f, 64f),
        FORGE(32f, 64f),
        SPIRE(16f, 16f),
        GENERICNOUPGRADE(16f, 16f),
        WALLSTRAIGHT(16f, 64),
        WALLCORNER(64f, 64f),
        SMALLGATE(64f, 64),
        ARTYTOWER(64f, 64),
        SIEGETENT(32f, 32f),
        BANESTONE(16f, 16f),
        MINE(16f, 16f),
        WAREHOUSE(32f, 32f),
        SHRINE(16f, 16f),
        RUNEGATE(64f, 64f),
        AMAZONHALL(64f, 64f),
        CATHEDRAL(64f, 64f),
        GREATHALL(64f, 64f),
        KEEP(64f, 64f),
        THIEFHALL(64f, 24f),
        TEMPLEHALL(64f, 64f),
        WIZARDHALL(64f, 64f),
        ELVENHALL(64f, 64f),
        ELVENSANCTUM(64f, 64f),
        IREKEIHALL(64f, 64f),
        FORESTHALL(64f, 64f),
        MAGICSHOP(32f, 32f),
        BULWARK(32f, 32f),
        SHACK(16f, 16f),
        INN(64f, 32f),
        TAILOR(32f, 32f),
        VILLA(64f, 32f),
        ESTATE(64f, 64f),
        FORTRESS(64f, 64f),
        CITADEL(64f, 64f),
        WALLSTRAIGHTTOWER(32F, 64),
        WALLSTAIRS(64, 64);

        private final Vector2f extents;

        BuildingGroup(float extentX, float extentY) {
            this.extents = new Vector2f(extentX, extentY);
        }

        public Vector2f getExtents() {
            return extents;
        }

    }

    public enum UpdateType {
        ALL,
        MOVEMENT,
        REGEN,
        FLIGHT,
        LOCATION,
        MOVEMENTSTATE
    }

    public enum ServerType {
        WORLDSERVER,
        LOGINSERVER,
        NONE
    }

    public enum AllianceType {
        RecommendedAlly,
        RecommendedEnemy,
        Ally,
        Enemy
    }

    public enum FriendStatus {
        Available,
        Away,
        Busy
    }

    public enum ProfitType {


        BuyNormal("buy_normal"),
        BuyGuild("buy_guild"),
        BuyNation("buy_nation"),
        SellNormal("sell_normal"),
        SellGuild("sell_guild"),
        SellNation("sell_nation");

        public String dbField;

        ProfitType(String dbField) {
            this.dbField = dbField;
        }
    }

    public enum GameObjectType {

        /*
         * These will be used as the 4 high bytes in the application protocol's
         * long CompositeID field and when tracking an AbstractGameObject's type
         * from within the code. The low 4 bytes will be used as the Object's
         * UUID
         */
        unknown,
        Account,
        AccountIP,
        ActiveEffect,
        ArmorBase,
        BaseClass,
        BeardStyle,
        BlockedIP,
        Building,
        BuildingLocation,
        BuildingModelBase,
        CharacterPower,
        CharacterPowers,
        CharacterRune,
        CharacterSkill,
        City,
        Contract,
        Corpse,
        CSSession,
        EffectsResourceCosts,
        EnchantmentBase,
        GenericItemBase,
        Group,
        Guild,
        GuildAllianceEnemy,
        GuildBanish,
        GuildCharacterKOS,
        GuildGuildKOS,
        GuildTableList,
        HairStyle,
        Item,
        ItemContainer,
        ItemEnchantment,
        JewelryBase,
        Kit,
        MenuOption,
        Mine,
        Mob,
        MobBase,
        MobLoot,
        MobType,
        NPC,
        NPCClassRune,
        NPCClassRuneThree,
        NPCClassRuneTwo,
        NPCExtraRune,
        NPCRaceRune,
        NPCRune,
        NPCShopkeeperRune,
        NPCTrainerRune,
        Nation,
        Petition,
        PlayerCharacter,
        PlayerInfo,
        PowerGrant,
        PowerReq,
        PowersBase,
        PowersBaseAttribute,
        PromotionClass,
        Race,
        RuneBase,
        RuneBaseAttribute,
        RuneBaseEffect,
        SkillReq,
        SkillsBase,
        SkillsBaseAttribute,
        MobileBooty,
        StrongBox,
        Trigger,
        ValidRaceBeardStyle,
        ValidRaceClassCombo,
        ValidRaceHairStyle,
        VendorDialog,
        Warehouse,
        WeaponBase,
        WorldServerInfo,
        WorldServerInfoSnapshot,
        Shrine,
        Zone,
        Transaction
    }

    public enum ContainerType {
        BANK,
        INVENTORY,
        VAULT
    }

    public enum CompoundCurveType {
        DefaultFlat(0),
        DefaultSlope(1),
        DefaultSlopeDown(-1),
        SL0001Up(0.01),
        SL0003Up(0.03),
        SL0005Up(0.05),
        SL0006Up(0.06),
        SL0007Up(0.07),
        SL0008Up(0.08),
        SL0010Up(0.10),
        SL0011Up(0.11),
        SL0012Up(0.12),
        SL0013Up(0.13),
        SL0014Up(0.14),
        SL00143U(0.143),
        SL0015Up(0.15),
        SL0016Up(0.16),
        SL0019Up(0.19),
        SL0020Up(0.20),
        SL0021Up(0.21),
        SL0022Up(0.22),
        SL0023Up(0.23),
        SL0024Up(0.24),
        SL0025Up(0.25),
        SL0026Up(0.26),
        SL0028Up(0.28),
        SL0030Up(0.30),
        SL0031Up(0.31),
        SL0032Up(0.32),
        SL0033Up(0.33),
        SL0034Up(0.34),
        SL0035Up(0.35),
        SL0037Up(0.37),
        SL0038Up(0.38),
        SL0039Up(0.39),
        SL0040Up(0.40),
        SL0041Up(0.41),
        SL0042Up(0.42),
        SL0043Up(0.43),
        SL0044Up(0.44),
        SL0045Up(0.45),
        SL0046Up(0.46),
        SL0047Up(0.47),
        SL0048Up(0.48),
        SL0050Up(0.50),
        SL0051Up(0.51),
        SL0053Up(0.53),
        SL0054Up(0.54),
        SL0055Up(0.55),
        SL0056Up(0.56),
        SL0057Up(0.57),
        SL0058Up(0.58),
        SL0060Up(0.60),
        SL0061Up(0.61),
        SL0063Up(0.63),
        SL0064Up(0.64),
        SL0065Up(0.65),
        SL0066Up(0.66),
        SL0067Up(0.67),
        SL0068Up(0.68),
        SL0069Up(0.69),
        SL0070Up(0.70),
        SL0071Up(0.71),
        SL0073Up(0.73),
        SL0074Up(0.74),
        SL0075Up(0.75),
        SL0076Up(0.76),
        SL0077Up(0.77),
        SL0079Up(0.79),
        SL0080Up(0.80),
        SL0081Up(0.81),
        SL0082Up(0.82),
        SL0083Up(0.83),
        SL0084Up(0.84),
        SL0085Up(0.85),
        SL0087Up(0.87),
        SL0088Up(0.88),
        SL0089Up(0.89),
        SL0090Up(0.90),
        SL0092Up(0.92),
        SL0098Up(0.98),
        SL0100Up(1.00),
        SL0106Up(1.06),
        SL0109Up(1.09),
        SL0112Up(1.12),
        SL0113Up(1.13),
        SL0115Up(1.15),
        SL0116Up(1.16),
        SL0122Up(1.22),
        SL0123Up(1.23),
        SL0125Up(1.25),
        SL0128Up(1.28),
        SL0130Up(1.30),
        SL0135Up(1.35),
        SL0140Up(1.40),
        SL0143Up(1.43),
        SL0145Up(1.45),
        SL0150Up(1.50),
        SL0154Up(1.54),
        SL0163Up(1.63),
        SL0166Up(1.66),
        SL0175Up(1.75),
        SL0188Up(1.88),
        SL0190Up(1.90),
        SL0200Up(2.00),
        SL0222Up(2.22),
        SL0225Up(2.25),
        SL0235Up(2.35),
        SL0238Up(2.38),
        SL0250Up(2.50),
        SL0260Up(2.60),
        SL0263Up(2.63),
        SL0275Up(2.75),
        SL0280Up(2.80),
        SL0300Up(3.00),
        SL0308Up(3.08),
        SL0312Up(3.12),
        SL0350Up(3.50),
        SL0357Up(3.57),
        SL0360Up(3.60),
        SL0375Up(3.75),
        SL0380Up(3.80),
        SL0385Up(3.85),
        SL0400Up(4.00),
        SL0410Up(4.10),
        SL0429Up(4.29),
        SL0450Up(4.50),
        SL0460Up(4.60),
        SL0480Up(4.80),
        SL0500Up(5.00),
        SL0510Up(5.10),
        SL0550Up(5.50),
        SL0600Up(6.00),
        SL0643Up(6.43),
        SL0714Up(7.14),
        SL0750Up(7.50),
        SL0790Up(7.90),
        SL0800Up(8.00),
        SL0900Up(9.00),
        SL1000Up(10.00),
        SL1050Up(10.50),
        SL1100Up(11.00),
        SL1125Up(11.25),
        SL1200Up(12.00),
        SL1282Up(12.82),
        SL1300Up(13.00),
        SL1350Up(13.50),
        SL1400Up(14.00),
        SL1500Up(15.00),
        SL1579Up(15.79),
        SL2000Up(20.00),
        SL2100Up(21.00),
        SL2500Up(25.00),
        SL2521Up(25.21),
        SL3000Up(30.00),
        SL4000Up(40.00),
        SL5000Up(50.00),
        SL6000Up(60.00),
        SL7500Up(75.00),
        SL8000Up(80.00),
        SL12000Up(120.00),
        SL14000Up(140.00),
        SL30000Up(300.00),
        SL66600Up(666.00),
        SL71500Up(715.00),
        SL00003Down(-0.003),
        SL0001Down(-0.01),
        SL0003Down(-0.03),
        SL0004Down(-0.04),
        SL0005Down(-0.05),
        SL0006Down(-0.06),
        SL0007Down(-0.07),
        SL00075Down(-0.075),
        SL0008Down(-0.08),
        SL0009Down(-0.09),
        SL0010Down(-0.10),
        SL0011Down(-0.11),
        SL0012Down(-0.12),
        SL0013Down(-0.13),
        SL00125Down(-0.125),
        SL0014Down(-0.14),
        SL0015Down(-0.15),
        SL0016Down(-0.16),
        SL0017Down(-0.17),
        SL00175Down(-0.175),
        SL0018Down(-0.18),
        SL0019Down(-0.19),
        SL0020Down(-0.20),
        SL0023Down(-0.23),
        SL0024Down(-0.24),
        SL0025Down(-0.25),
        SL0027Down(-0.27),
        SL0028Down(-0.28),
        SL0029Down(-0.29),
        SL0030Down(-0.30),
        SL0032Down(-0.32),
        SL0033Down(-0.33),
        SL0035Down(-0.35),
        SL0038Down(-0.38),
        SL0040Down(-0.40),
        SL0044Down(-0.44),
        SL0045Down(-0.45),
        SL0050Down(-0.50),
        SL0055Down(-0.55),
        SL0060Down(-0.60),
        SL0062Down(-0.62),
        SL0063Down(-0.63),
        SL0064Down(-0.64),
        SL0066Down(-0.66),
        SL0069Down(-0.69),
        SL0071Down(-0.71),
        SL0075Down(-0.75),
        SL0077Down(-0.77),
        SL0079Down(-0.79),
        SL0080Down(-0.80),
        SL0090Down(-0.90),
        SL0100Down(-1.00),
        SL0113Down(-1.13),
        SL0120Down(-1.20),
        SL0125Down(-1.25),
        SL0128Down(-1.28),
        SL0130Down(-1.30),
        SL0135Down(-1.35),
        SL0150Down(-1.50),
        SL0175Down(-1.75),
        SL0188Down(-1.88),
        SL0200Down(-2.00),
        SL0225Down(-2.25),
        SL0250Down(-2.50),
        SL0263Down(-2.63),
        SL0300Down(-3.00),
        SL0357Down(-3.57),
        SL0385Down(-3.85),
        SL0429Down(-4.29),
        SL0450Down(-4.50),
        SL0500Down(-5.00),
        SL0550Down(-5.50),
        SL0600Down(-6.00),
        SL0643Down(-6.43),
        SL0714Down(-7.14),
        SL0750Down(-7.50),
        SL0790Down(-7.90),
        SL0800Down(-8.00),
        SL1000Down(-10.00),
        SL1050Down(-10.50),
        SL1200Down(-12.00),
        SL1350Down(-13.50),
        SL1500Down(-15.00),
        SL1579Down(-15.79),
        SL2000Down(-20.00),
        SL2400Down(-24.00),
        SL2500Down(-25.00),
        SL3000Down(-30.00),
        SL4500Down(-45.00),
        SL7500Down(-75.00),
        SIVL0005(0.005),
        SIVL0008(0.008),
        SIVL0009(0.009),
        SIVL0010(0.010),
        SIVL0012(0.012),
        SIVL0013(0.013),
        SIVL0014(0.014),
        SIVL0015(0.015),
        SIVL0016(0.016),
        SIVL0017(0.017),
        SIVL0019(0.019),
        SIVL0020(0.020),
        SIVL0021(0.021),
        SIVL0022(0.022),
        SIVL0023(0.023),
        SIVL0024(0.024),
        SIVL0025(0.025),
        SIVL0026(0.026),
        SIVL0027(0.027),
        SIVL0029(0.029),
        SIVL0030(0.030),
        SIVL0031(0.031),
        SIVL0032(0.032),
        SIVL0033(0.033),
        SIVL0034(0.034),
        SIVL0035(0.035),
        SIVL0036(0.036),
        SIVL0038(0.038),
        SIVL0040(0.040),
        SIVL0044(0.044),
        SIVL0046(0.046),
        SIVL0048(0.048),
        SIVL0055(0.055),
        SIVL0056(0.056),
        SIVL0057(0.057),
        SIVL0058(0.058),
        SIVL0060(0.060),
        SIVL0061(0.061),
        SIVL0066(0.066),
        SIVL0067(0.067),
        SIVL0075(0.075),
        SIVL0078(0.078),
        SIVL0130(0.130),
        SIVL0150(0.150),
        SIVL0205(0.205),
        SIVL0220(0.220),
        SIVL0243(0.243),
        SIVL0360(0.360);

        private final double value;

        CompoundCurveType(double value) {

            this.value = value;
        }

        public double getValue() {
            return value;
        }
    }

    public enum PowerFailCondition {

        Attack,
        AttackSwing,
        Cast,
        CastSpell,
        EquipChange,
        Logout,
        Move,
        NewCharm,
        Sit,
        TakeDamage,
        TerritoryClaim,
        UnEquip
    }

    public enum PowerSubType {
        Amount,
        Ramp,
        UseAddFormula,
        DamageType1,
        DamageType2,
        DamageType3,
        Cancel
    }

    public enum PowerCategoryType {
        NONE,
        WEAPON,
        BUFF,
        DEBUFF,
        SPECIAL,
        DAMAGE,
        DISPEL,
        INVIS,
        STUN,
        TELEPORT,
        HEAL,
        VAMPDRAIN,
        BLESSING,
        BOONRACE,
        BOONCLASS,
        BEHAVIOR,
        CHANT,
        GROUPBUFF,
        MOVE,
        FLIGHT,
        GROUPHEAL,
        AEDAMAGE,
        BREAKFLY,
        AE,
        TRANSFORM,
        TRACK,
        SUMMON,
        STANCE,
        RECALL,
        SPIREPROOFTELEPORT,
        SPIREDISABLE,
        THIEF
    }

    public enum PowerTargetType {

        SELF,
        PCMOBILE,
        PET,
        MOBILE,
        PC,
        WEAPON,
        GUILDLEADER,
        BUILDING,
        GROUP,
        ARMORWEAPONJEWELRY,
        CORPSE,
        JEWELRY,
        WEAPONARMOR,
        ARMOR,
        ITEM
    }

    public enum ItemContainerType {
        NONE,
        INVENTORY,
        EQUIPPED,
        BANK,
        VAULT,
        FORGE,
        WAREHOUSE
    }

    public enum EquipSlotType {
        NONE,
        RHELD,
        LHELD,
        HELM,
        CHEST,
        SLEEVES,
        HANDS,
        RRING,
        LRING,
        AMULET,
        LEGS,
        FEET,
        CLOAK,
        SHIN,
        UPLEGS,
        UPARM,
        WINGS,
        BEARD,
        HAIR
    }

    public enum CityBoundsType {

        GRID(640),
        ZONE(875),
        PLACEMENT(876);

        public final float halfExtents;

        CityBoundsType(float halfExtents) {
            this.halfExtents = halfExtents;
        }
    }

    public enum GuildCharterType {
        NONE("None", new String[][]{{"None"}}, new String[]{"Thearchy", "Common Rule", "Theocracy", "Republic Rule"},
                EnumSet.noneOf(ClassType.class),
                EnumSet.noneOf(MonsterType.class),
                EnumSet.noneOf(SexType.class),
                0),

        CATHEDRAL("Church of the All-Father", new String[][]{
                {"Acolyte", "Acolyte"},
                {"Catechist"},
                {"Deacon", "Deaconess"},
                {"Priest", "Priestess"},
                {"High Priest", "High Priestess"},
                {"Bishop", "Bishop"},
                {"Lord Cardinal", "Lady Cardinal"},
                {"Patriarch", "Matriarch"}},
                new String[]{"Thearchy", "Common Rule", "Theocracy", "Republic Rule"},
                EnumSet.of(ClassType.Bard, ClassType.Channeler, ClassType.Crusader, ClassType.Nightstalker,
                        ClassType.Prelate, ClassType.Priest, ClassType.Sentinel, ClassType.Scout),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Centaur, MonsterType.Elf, MonsterType.HalfGiant,
                        MonsterType.Human),
                EnumSet.allOf(SexType.class),
                559),
        MILITARY("Military", new String[][]{
                {"Recruit"},
                {"Footman"},
                {"Corporal"},
                {"Sergeant"},
                {"Lieutenant"},
                {"Captain"},
                {"General"},
                {"Lord Marshall", "Lady Marshall"}},
                new String[]{"Autocracy", "Common Rule", "Council Rule", "Militocracy"},
                EnumSet.of(ClassType.Bard, ClassType.Priest, ClassType.Scout, ClassType.Warlock,
                        ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Centaur, MonsterType.HalfGiant, MonsterType.Human),
                EnumSet.allOf(SexType.class),
                560),
        TEMPLE("Temple of the Cleansing Flame", new String[][]{
                {"Aspirant"},
                {"Novice"},
                {"Initiate"},
                {"Inquisitor"},
                {"Jannisary"},
                {"Tribune"},
                {"Lictor"},
                {"Justiciar"},
                {"Pontifex", "Pontifectrix"}},
                new String[]{"Despot Rule", "Common Rule", "Protectorship", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Channeler, ClassType.Confessor,
                        ClassType.Nightstalker, ClassType.Priest, ClassType.Scout, ClassType.Templar),
                EnumSet.of(MonsterType.HalfGiant, MonsterType.Human),
                EnumSet.allOf(SexType.class),
                561),
        BARBARIAN("Barbarian Clan", new String[][]{
                {"Barbarian"},
                {"Skald"},
                {"Raider"},
                {"Karl"},
                {"Jarl"},
                {"Chieftain"},
                {"Thane"}},
                new String[]{"Chiefdom", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Barbarian, ClassType.Bard, ClassType.Doomsayer, ClassType.Fury,
                        ClassType.Priest, ClassType.Scout, ClassType.Thief, ClassType.Warrior),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.HalfGiant, MonsterType.Human, MonsterType.Minotaur),
                EnumSet.allOf(SexType.class),
                562),
        RANGER("Ranger's Brotherhood", new String[][]{
                {"Yeoman"},
                {"Pathfinder"},
                {"Tracker"},
                {"Seeker"},
                {"Protector"},
                {"Guardian"},
                {"Lord Protector", "Lady Protector"}},
                new String[]{"Despot Rule", "Collectivism", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Bard, ClassType.Channeler, ClassType.Druid, ClassType.Priest,
                        ClassType.Ranger, ClassType.Scout, ClassType.Warrior),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Elf, MonsterType.HalfGiant, MonsterType.Human, MonsterType.Shade),
                EnumSet.allOf(SexType.class),
                563),
        AMAZON("Amazon Temple", new String[][]{
                {"Amazon Thrall", "Amazon"},
                {"Amazon Slave", "Amazon Warrior"},
                {"Amazon Servant", "Amazon Chieftess"},
                {"Amazon Consort", "Amazon Princess"},
                {"Amazon Seneschal", "Majestrix"},
                {"Amazon Regent", "Imperatrix"}},
                new String[]{"Despot Rule", "Common Rule", "Gynarchy", "Gynocracy"},
                EnumSet.of(ClassType.Bard, ClassType.Druid, ClassType.Fury, ClassType.Huntress,
                        ClassType.Priest, ClassType.Scout, ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Elf, MonsterType.HalfGiant, MonsterType.Human),
                EnumSet.of(SexType.FEMALE),
                564),
        NOBLE("Noble House", new String[][]{
                {"Serf"},
                {"Vassal"},
                {"Exultant"},
                {"Lord", "Lady"},
                {"Baron", "Baroness"},
                {"Count", "Countess"},
                {"Duke", "Duchess"},
                {"King", "Queen"},
                {"Emperor", "Empress"}},
                new String[]{"Monarchy", "Common Rule", "Feodality", "Republic"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Channeler, ClassType.Priest,
                        ClassType.Scout, ClassType.Thief, ClassType.Warlock, ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.HalfGiant, MonsterType.Human),
                EnumSet.allOf(SexType.class),
                565),
        WIZARD("Wizard's Conclave", new String[][]{
                {"Apprentice"},
                {"Neophyte"},
                {"Adeptus Minor"},
                {"Adeptus Major"},
                {"Magus"},
                {"High Magus"},
                {"Archmagus"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Magocracy"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Channeler, ClassType.Doomsayer,
                        ClassType.Fury, ClassType.Necromancer, ClassType.Priest, ClassType.Warlock, ClassType.Wizard),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Elf, MonsterType.Human, MonsterType.Nephilim, MonsterType.Shade),
                EnumSet.allOf(SexType.class),
                566),
        MERCENARY("Mercenary Company", new String[][]{
                {"Soldier"},
                {"Man-at-Arms"},
                {"Veteran"},
                {"Myrmidon"},
                {"Captain"},
                {"Commander"},
                {"High Commander"},
                {"Warlord"}},
                new String[]{"Magistrature", "Mob Law", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Priest, ClassType.Scout,
                        ClassType.Thief, ClassType.Warlock, ClassType.Warrior),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Aracoix, MonsterType.HalfGiant, MonsterType.Human, MonsterType.Shade),
                EnumSet.allOf(SexType.class),
                567),
        THIEVES("Thieve's Den", new String[][]{
                {"Urchin"},
                {"Footpad"},
                {"Grifter"},
                {"Burglar"},
                {"Collector"},
                {"Naster Thief"},
                {"Treasurer"},
                {"Grandmaster Thief"},
                {"Grandfather"}},
                new String[]{"Despot Rule", "Common Rule", "Oligarchy", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Barbarian, ClassType.Bard, ClassType.Priest,
                        ClassType.Scout, ClassType.Thief, ClassType.Wizard),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Aracoix, MonsterType.Elf, MonsterType.Human, MonsterType.Irekei,
                        MonsterType.Nephilim, MonsterType.Shade, MonsterType.Vampire),
                EnumSet.allOf(SexType.class),
                568),
        DWARF("Dwarf Hold", new String[][]{
                {"Citizen"},
                {"Master"},
                {"Councilor"},
                {"Thane"},
                {"Great Thane"},
                {"High Thane"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Crusader, ClassType.Prelate, ClassType.Priest, ClassType.Sentinel,
                        ClassType.Warrior),
                EnumSet.of(MonsterType.Dwarf),
                EnumSet.allOf(SexType.class),
                569),
        HIGHCOURT("High Court", new String[][]{
                {"Eccekebe"},
                {"Saedulor"},
                {"Hodrimarth"},
                {"Mandrae"},
                {"Imaelin"},
                {"Thaelostor", "Thaelostril"},
                {"Dar Thaelostor", "Dar Thaelostril"},
                {"Aglaeron"},
                {"Ellestor", "Elestril"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Channeler, ClassType.Druid,
                        ClassType.Necromancer, ClassType.Priest, ClassType.Ranger, ClassType.Scout,
                        ClassType.Thief, ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Elf, MonsterType.Minotaur),
                EnumSet.allOf(SexType.class),
                570),
        VIRAKT("Virakt", new String[][]{
                {"Jov'uus"},
                {"Urikhan"},
                {"Irkhan"},
                {"Khal'usht"},
                {"Arkhalar"},
                {"Khal'uvho"},
                {"Khar'uus"},
                {"Kryqh'khalin"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Bard, ClassType.Channeler, ClassType.Fury,
                        ClassType.Huntress, ClassType.Nightstalker, ClassType.Priest, ClassType.Ranger,
                        ClassType.Scout, ClassType.Thief, ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Irekei),
                EnumSet.allOf(SexType.class),
                571),
        BRIALIA("Coven of Brialia", new String[][]{ // Unknown Rank names
                {"Devotee"},
                {"Initiated"},
                {"Witch of the First"},
                {"Witch of the Second"},
                {"Witch of the Third"},
                {"Elder"},
                {"Hierophant"},
                {"Witch King", "Witch Queen"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.allOf(ClassType.class),
                EnumSet.allOf(MonsterType.class),
                EnumSet.allOf(SexType.class),
                577),
        UNHOLY("Unholy Legion", new String[][]{ // Unknown Rank names
                {"Footman"},
                {"Fell Legionaire"},
                {"Fell Centurion"},
                {"Dark Captain"},
                {"Dark Commander"},
                {"Dark Master", "Dark Mistress"},
                {"Dread Master", "Dread Mistress"},
                {"Dread Lord", "Dread Lady"}},
                new String[]{"Despot Rule", "Despot Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Channeler, ClassType.Necromancer, ClassType.Priest,
                        ClassType.Scout, ClassType.Thief, ClassType.Warlock, ClassType.Warrior,
                        ClassType.Wizard),
                EnumSet.of(MonsterType.Human, MonsterType.Shade, MonsterType.Vampire),
                EnumSet.allOf(SexType.class),
                575),
        SCOURGE("Cult of the Scourge", new String[][]{
                {"Thrall"},
                {"Mudir"},
                {"Dark Brother", "Dark Sister"},
                {"Hand of the Dark"},
                {"Dark Father", "Dark Mother"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Bard, ClassType.Channeler, ClassType.Doomsayer, ClassType.Priest,
                        ClassType.Scout, ClassType.Warrior, ClassType.Wizard),
                EnumSet.of(MonsterType.Aelfborn, MonsterType.Human, MonsterType.Minotaur, MonsterType.Nephilim),
                EnumSet.allOf(SexType.class),
                572),
        PIRATE("Pirate Crew", new String[][]{
                {"Midshipman", "Midshipwoman"},
                {"Sailor"},
                {"Third Mat"},
                {"Second Mat"},
                {"First Mate"},
                {"Captain"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.allOf(ClassType.class),
                EnumSet.allOf(MonsterType.class),
                EnumSet.allOf(SexType.class),
                576),
        HERALD("Academy of Heralds", new String[][]{
                {"Pupil"},
                {"Scribe"},
                {"Recorder"},
                {"Scrivener"},
                {"Chronicler"},
                {"Scholar"},
                {"Archivist"},
                {"Loremaster"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.allOf(ClassType.class),
                EnumSet.allOf(MonsterType.class),
                EnumSet.allOf(SexType.class),
                582),
        CENTAUR("Centaur Cohort", new String[][]{
                {"Hoplite"},
                {"Peltast"},
                {"Myrmidon"},
                {"Myrmidon"},
                {"Cataphract"},
                {"Septenrion"},
                {"Praetorian"},
                {"Paragon"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Barbarian, ClassType.Crusader, ClassType.Druid, ClassType.Huntress,
                        ClassType.Prelate, ClassType.Priest, ClassType.Ranger, ClassType.Sentinel,
                        ClassType.Warrior),
                EnumSet.of(MonsterType.Centaur),
                EnumSet.allOf(SexType.class),
                574),
        KHREE("Aracoix Kh'ree", new String[][]{
                {"Duriacor"},
                {"Exarch"},
                {"Tetrarch"},
                {"Dimarch"},
                {"Elnarch"},
                {"Illiarch"},
                {"Tellotharch"},
                {"Erentar"},
                {"Araceos"},
                {"Hierarch"}},
                new String[]{"Despot Rule", "Common Rule", "Council Rule", "Republic Rule"},
                EnumSet.of(ClassType.Assassin, ClassType.Barbarian, ClassType.Bard, ClassType.Huntress,
                        ClassType.Priest, ClassType.Ranger, ClassType.Scout, ClassType.Thief,
                        ClassType.Warlock, ClassType.Warrior),
                EnumSet.of(MonsterType.Aracoix),
                EnumSet.allOf(SexType.class),
                573);

        public final EnumSet<ClassType> requiredClasses;
        public final EnumSet<MonsterType> requiredRaces;
        public final EnumSet<SexType> sexRequired;
        public final String name;
        private final String[][] ranks;    //Stored Rank#->Gender(M,F)
        private final String[] leadershipTypes;
        public final int templateID;
        public static HashMap<Integer, GuildCharterType> templateLookup = new HashMap<>();

        GuildCharterType(String name, String[][] ranks, String[] leadershipTypes, EnumSet<ClassType> requiredClasses,
                         EnumSet<MonsterType> requiredRaces, EnumSet<SexType> sexRequired, int templateID) {
            this.name = name;
            this.ranks = ranks;
            this.leadershipTypes = leadershipTypes;
            this.requiredClasses = requiredClasses;
            this.requiredRaces = requiredRaces;
            this.sexRequired = sexRequired;
            this.templateID = templateID;
        }

        public static void init() {
            for (GuildCharterType guildCharterType : GuildCharterType.values())
                GuildCharterType.templateLookup.put(guildCharterType.templateID, guildCharterType);
        }


        public static GuildCharterType getGuildTypeFromInt(int i) {
            return GuildCharterType.values()[i];
        }

        public int getNumberOfRanks() {
            return ranks.length;
        }

        public String getRankForGender(int rank, boolean male) {

            if (ranks.length < rank)
                return "";

            if (ranks[rank].length != 1 && !male)
                return ranks[rank][1];

            return ranks[rank][0];
        }

        public String getLeadershipType(int i) {
            return leadershipTypes[i];
        }

        public boolean canJoin(AbstractCharacter character) {
            if (this.requiredRaces.contains(character.absRace) == false)
                return false;
            if (this.requiredClasses.contains(character.absBaseClass) == false && this.requiredClasses.contains(character.absPromotionClass) == false)
                return false;
            if (this.sexRequired.contains(character.absGender) == false)
                return false;

            return true;
        }
    }

    public enum MinionClass {
        MELEE,
        ARCHER,
        MAGE
    }

    public enum MinionType {
        AELFBORNGUARD(951, 1637, MinionClass.MELEE, "Guard", "Aelfborn"),
        AELFBORNMAGE(952, 1635, MinionClass.MAGE, "Adept", "Aelfborn"),
        AMAZONGUARD(1500, 1670, MinionClass.MELEE, "Guard", "Amazon"),
        AMAZONMAGE(1502, 1638, MinionClass.MAGE, "Fury", "Amazon"),
        ARACOIXGUARD(1600, 1672, MinionClass.MELEE, "Guard", "Aracoix"), //used guard captain equipset.
        ARACOIXMAGE(1602, 885, MinionClass.MAGE, "Adept", "Aracoix"),
        CENTAURGUARD(1650, 1642, MinionClass.MELEE, "Guard", "Centaur"),
        CENTAURMAGE(1652, 1640, MinionClass.MAGE, "Druid", "Centaur"),
        DWARVENARCHER(845, 1644, MinionClass.ARCHER, "Marksman", "Dwarven"),
        DWARVENGUARD(1050, 1666, MinionClass.MELEE, "Guard", "Dwarven"),
        DWARVENMAGE(1052, 1643, MinionClass.MAGE, "War Priest", "Dwarven"),
        ELFGUARD(1180, 1671, MinionClass.MELEE, "Guard", "Elven"), //old 1645
        ELFMAGE(1182, 1667, MinionClass.MAGE, "Adept", "Elven"),
        FORESTGUARD(1550, 1668, MinionClass.MELEE, "Guard", "Forest"), //captain changed to guard equipset
        FORESTMAGE(1552, 436, MinionClass.MAGE, "Adept", "Forest"),
        HOLYGUARD(1525, 1658, MinionClass.MELEE, "Guard", "Holy Church"),
        HOLYMAGE(1527, 1646, MinionClass.MAGE, "Prelate", "Holy Church"),
        HUMANARCHER(846, 1654, MinionClass.ARCHER, "Archer", "Human"),
        HUMANGUARD(840, 1665, MinionClass.MELEE, "Guard", "Human"),
        HUMANMAGE(848, 1655, MinionClass.MAGE, "Adept", "Human"),
        IREKEIGUARD(1350, 1659, MinionClass.MELEE, "Guard", "Irekei"),
        IREKEIMAGE(1352, 1660, MinionClass.MAGE, "Adept", "Irekei"),
        MINOTAURARCHER(1701, 0, MinionClass.ARCHER, "Archer", "Minotaur"),
        MINOTAURGUARD(1700, 1673, MinionClass.MELEE, "Guard", "Minotaur"),
        NORTHMANGUARD(1250, 1669, MinionClass.MELEE, "Guard", "Northman"),
        NORTHMANMAGE(1252, 1650, MinionClass.MAGE, "Runecaster", "Northman"),
        SHADEGUARD(1450, 1662, MinionClass.MELEE, "Guard", "Shade"),
        SHADEMAGE(1452, 1664, MinionClass.MAGE, "Adept", "Shade"),
        TEMPLARGUARD(841, 1564, MinionClass.MELEE, "Marksman", "Templar"),
        TEMPLEGUARD(1575, 1652, MinionClass.MELEE, "Guard", "Temple"),
        TEMPLEMAGE(1577, 1656, MinionClass.MAGE, "Confessor", "Temple"),
        UNDEADGUARD(980100, 1674, MinionClass.MELEE, "Guard", "Undead"),
        UNDEADMAGE(980102, 1675, MinionClass.MAGE, "Adept", "Undead"),
        WEREWOLFGUARD(980104, 0, MinionClass.MELEE, "Guard", "Werewolf"),
        WEREBEARGUARD(980103, 0, MinionClass.MELEE, "Guard", "Werebear");
        public static HashMap<Integer, MinionType> ContractToMinionMap = new HashMap<>();
        private final int captainContractID;
        private final int equipSetID;
        private final MinionClass minionClass;
        private final String name;
        private final String race;

        MinionType(int captainContractID, int equipSetID, MinionClass minionClass, String name, String race) {

            this.captainContractID = captainContractID;
            this.equipSetID = equipSetID;
            this.minionClass = minionClass;
            this.name = name;
            this.race = race;

        }

        public static void InitializeMinions() {

            for (MinionType minionType : MinionType.values())
                ContractToMinionMap.put(minionType.captainContractID, minionType);
        }

        public String getName() {
            return name;
        }

        public String getRace() {
            return race;
        }

        public Boolean isMage() {
            return this.minionClass.ordinal() == MinionClass.MAGE.ordinal();
        }
    }

    public enum GridObjectType {
        STATIC,
        DYNAMIC
    }

    public enum SupportMsgType {
        NONE(0),
        PROTECT(1),
        UNPROTECT(3),
        VIEWUNPROTECTED(4),
        REMOVETAX(6),
        ACCEPTTAX(7),
        CONFIRMPROTECT(8);

        public static HashMap<Integer, SupportMsgType> typeLookup = new HashMap<>();
        private final int type;

        SupportMsgType(int messageType) {
            this.type = messageType;

        }

        public static void InitializeSupportMsgType() {

            for (SupportMsgType supportMsgType : SupportMsgType.values())
                typeLookup.put(supportMsgType.type, supportMsgType);
        }
    }

    public enum ResourceType {

        GOLD(7, -1670881623, 2308551, 100000000, 50000),
        ADAMANT(1580003, 1557001525, -1741189964, 1000, 10),
        AGATE(1580009, -1096157543, 75173057, 2000, 20),
        ANTIMONY(1580014, 1256147265, 452320058, 1000, 10),
        AZOTH(1580012, -1205326951, 78329697, 2000, 20),
        BLOODSTONE(1580020, -1912381716, -1569826353, 500, 5),
        BRONZEWOOD(1580006, -519681813, 1334770447, 1000, 30),
        COAL(1580008, -1672872311, 2559427, 3000, 30),
        DIAMOND(1580010, 1540225085, -1730704107, 2000, 20),
        GALVOR(1580017, -1683992404, -1596311545, 2000, 5),
        IRON(1580002, -1673518119, 2504297, 2000, 20),
        LUMBER(1580004, -1628412684, -1603256692, 10000, 100),
        MANDRAKE(1580007, -1519910613, 1191391799, 1000, 10),
        MITHRIL(1580021, 626743397, -1761257186, 500, 5),
        OAK(1580005, -1653034775, 74767, 3000, 30),
        OBSIDIAN(1580019, 778019055, -697973233, 500, 5),
        ONYX(1580011, -1675952151, 2977263, 1000, 10),
        ORICHALK(1580013, -1468730955, -2036290524, 3000, 30),
        QUICKSILVER(1580016, -2081208434, -472884509, 1000, 10),
        STONE(1580000, -1094703863, 74856115, 10000, 100),
        SULFUR(1580015, -1763687412, -1586349421, 1000, 10),
        TRUESTEEL(1580001, -169012482, -317484979, 2000, 20),
        WORMWOOD(1580018, 1204785075, 1532478436, 500, 5);

        public static HashMap<Integer, ResourceType> templateLookup = new HashMap<>();
        public static HashMap<Integer, ResourceType> templateHashLookup = new HashMap<>();
        public static HashMap<Integer, ResourceType> resourceHashLookup = new HashMap<>();
        public int templateID;
        public ItemTemplate template;
        public int resourceHash;
        public int templateHash;
        public int deposit_limit;
        public int mine_production;

        ResourceType(int templateID, int resourceHash, int templateHash, int deposit_limit, int mine_production) {
            this.templateID = templateID;
            this.template = ItemTemplate.templates.get(this.templateID);
            this.resourceHash = resourceHash;
            this.templateHash = templateHash;
            this.deposit_limit = deposit_limit;
            this.mine_production = mine_production;
        }

        public static void InitializeResourceTypes() {

            for (ResourceType resourceType : ResourceType.values()) {
                templateLookup.put(resourceType.templateID, resourceType);
                templateHashLookup.put(resourceType.templateHash, resourceType);
                resourceHashLookup.put(resourceType.resourceHash, resourceType);
            }

        }
    }

    public enum PowerActionType {
        ApplyEffect,
        ApplyEffects,
        Block,
        Charm,
        ClaimMine,
        ClearAggro,
        ClearNearbyAggro,
        Confusion,
        CreateMob,
        DamageOverTime,
        DeferredPower,
        DirectDamage,
        Invis,
        MobRecall,
        Peek,
        Recall,
        RemoveEffect,
        Resurrect,
        RunegateTeleport,
        SetItemFlag,
        SimpleDamage,
        SpireDisable,
        Steal,
        Summon,
        Teleport,
        Track,
        TransferStat,
        TransferStatOT,
        Transform,
        TreeChoke
    }

    public enum AccountStatus {
        BANNED,
        ACTIVE,
        ADMIN
    }

    public enum MobBehaviourType {
        None(null, false, false, false, false, false),
        Power(null, false, true, true, true, false),
        PowerHelpee(Power, false, true, true, false, true),
        PowerHelpeeWimpy(Power, true, false, true, false, false),
        PowerGrouperWimpy(Power, true, false, true, false, false),
        PowerAggro(Power, false, true, true, false, true),
        PowerAggroHelpee(Power, false, true, true, false, true),
        //Aggro
        Aggro(null, false, true, true, true, false),
        AggroHelpee(Aggro, false, true, true, false, true),
        AggroHelpeeWimpy(Aggro, true, false, true, false, false),
        AggroGrouperWimpy(Aggro, true, false, true, false, false),
        //Spell
        Spell(null, false, true, true, true, false),
        SpellHelpee(Spell, false, true, true, false, true),
        SpellHelpeeWimpy(Spell, true, false, true, false, false),
        SpellGrouperWimpy(Spell, true, false, true, false, false),
        SpellAggro(Spell, false, true, true, false, true),
        SpellAggroHelpee(Spell, false, true, true, false, true),
        SpellAggroHelpeeWimpy(Spell, true, false, true, false, false),
        SpellAggroHelpeeEpic(Spell, false, true, true, false, true),
        SpellAggroGrouperWimpy(Spell, true, false, true, false, false),
        //Independent Types
        SimpleStandingGuard(null, false, false, false, false, false),
        Pet1(null, false, false, true, false, false),
        SiegeEngine(null, false, false, false, false, false),
        Simple(null, false, false, true, false, false),
        Helpee(null, false, true, true, false, true),
        HelpeeWimpy(null, true, false, true, false, false),
        GuardCaptain(null, false, true, true, false, false),
        GuardMinion(GuardCaptain, false, true, true, false, false),
        GuardWallArcher(null, false, true, false, false, false),
        Wanderer(null, false, true, true, false, false),
        HamletGuard(null, false, true, false, false, false),
        AggroWanderer(null, false, false, true, false, false);

        public final MobBehaviourType BehaviourHelperType;
        public final boolean isWimpy;
        public final boolean isAgressive;
        public final boolean canRoam;
        public final boolean callsForHelp;
        public final boolean respondsToCallForHelp;

        MobBehaviourType(MobBehaviourType helpeebehaviourType, boolean wimpy, boolean agressive, boolean canroam, boolean callsforhelp, boolean respondstocallforhelp) {
            this.BehaviourHelperType = helpeebehaviourType;
            this.isWimpy = wimpy;
            this.isAgressive = agressive;
            this.canRoam = canroam;
            this.callsForHelp = callsforhelp;
            this.respondsToCallForHelp = respondstocallforhelp;
        }

    }

    public enum AIAgentType {
        MOBILE,
        GUARDCAPTAIN,
        GUARDMINION,
        GUARDWALLARCHER,
        PET,
        CHARMED,
        SIEGEENGINE
    }

    public enum ItemFlags {
        Indestructible,
        Identified,
        NoBond,
        NoQuit,
        Magic,
        NoDrop,
        Rare;
    }

    public enum ItemUseFlags {
        USE_SELF,
        USE_TARGET,
        EMPTY_DESTROY,
        EMPTY_NEWITEM;
    }

    public enum AttributeType {
        None,
        Strength,
        Dexterity,
        Constitution,
        Intelligence,
        Spirit,
    }

    public enum PassiveType {
        None(0),
        Dodge(20),
        Block(21),
        Parry(22);

        public int value;

        PassiveType(int value) {
            this.value = value;
        }
    }

    public enum FormationType {
        COLUMN(new Vector3f[]{new Vector3f(0, 0, 0), // Group
                // Lead
                new Vector3f(6, 0, 0), // Player 1 offset
                new Vector3f(0, 0, -6), // Player 2 offset
                new Vector3f(6, 0, -6), // Player 3 offset
                new Vector3f(0, 0, -12), // Player 4 offset
                new Vector3f(6, 0, -12), // Player 5 offset
                new Vector3f(0, 0, -18), // Player 6 offset
                new Vector3f(6, 0, -18), // Player 7 offset
                new Vector3f(0, 0, -24), // Player 8 offset
                new Vector3f(6, 0, -24)}),
        LINE(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(0, 0, -6), new Vector3f(0, 0, -12),
                new Vector3f(0, 0, -18), new Vector3f(0, 0, -24),
                new Vector3f(0, 0, -30), new Vector3f(0, 0, -36),
                new Vector3f(0, 0, -42), new Vector3f(0, 0, -48),
                new Vector3f(0, 0, -54)}),
        BOX(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(-6, 0, 0), new Vector3f(6, 0, 0),
                new Vector3f(-6, 0, -6), new Vector3f(0, 0, -6),
                new Vector3f(6, 0, -6), new Vector3f(-6, 0, -12),
                new Vector3f(0, 0, -12), new Vector3f(5, 0, -12),
                new Vector3f(0, 0, -18)}),
        TRIANGLE(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(-6, 0, -6), new Vector3f(6, 0, -6),
                new Vector3f(-12, 0, -12), new Vector3f(0, 0, -12),
                new Vector3f(12, 0, -12), new Vector3f(-18, 0, -18),
                new Vector3f(-6, 0, -18), new Vector3f(6, 0, -18),
                new Vector3f(18, 0, -18)}),
        CIRCLE(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(-12, 0, -3), new Vector3f(12, 0, -3),
                new Vector3f(-18, 0, -12), new Vector3f(18, 0, -12),
                new Vector3f(-18, 0, -21), new Vector3f(18, 0, -21),
                new Vector3f(-12, 0, -30), new Vector3f(12, 0, -30),
                new Vector3f(0, 0, -33)}),
        RANKS(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(0, 0, -6), new Vector3f(-6, 0, 0),
                new Vector3f(-6, 0, -6), new Vector3f(6, 0, 0),
                new Vector3f(6, 0, -6), new Vector3f(-12, 0, 0),
                new Vector3f(-12, 0, -6), new Vector3f(12, 0, 0),
                new Vector3f(12, 0, -6)}),
        WEDGE(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(6, 0, 0), new Vector3f(-6, 0, -6),
                new Vector3f(12, 0, -6), new Vector3f(-12, 0, -12),
                new Vector3f(18, 0, -12), new Vector3f(-18, 0, -18),
                new Vector3f(24, 0, -18), new Vector3f(-24, 0, -24),
                new Vector3f(30, 0, -24)}),
        INVERSEWEDGE(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(6, 0, 0), new Vector3f(-6, 0, 6),
                new Vector3f(12, 0, 6), new Vector3f(-12, 0, 12),
                new Vector3f(18, 0, 12), new Vector3f(-18, 0, 18),
                new Vector3f(24, 0, 18), new Vector3f(-24, 0, 24),
                new Vector3f(30, 0, 24)}),
        T(new Vector3f[]{new Vector3f(0, 0, 0),
                new Vector3f(-6, 0, 0), new Vector3f(6, 0, 0),
                new Vector3f(0, 0, -6), new Vector3f(-12, 0, 0),
                new Vector3f(12, 0, 0), new Vector3f(0, 0, -12),
                new Vector3f(-18, 0, 0), new Vector3f(18, 0, 0),
                new Vector3f(0, 0, -18)});

        public Vector3f[] offsets;

        FormationType(Vector3f[] offsets) {

            this.offsets = offsets;
        }

        public static Vector3f getOffset(int formation, int position) {

            FormationType formationType;

            if (position > 9 || position < 0)
                position = 0;

            formationType = FormationType.values()[formation];

            if (formationType == null)
                formationType = FormationType.BOX;

            return formationType.offsets[position];

        }
    }

    public enum ProductionActionType {
        NONE,
        PRODUCE,
        JUNK,
        RECYCLE,
        COMPLETE,
        SETPRICE,
        DEPOSIT,
        TAKE,
        CONFIRM_PRODUCE,
        CONFIRM_SETPRICE,
        CONFIRM_DEPOSIT,
        CONFIRM_TAKE;
    }

    public enum ItemModType {
        PREFIX,
        SUFFIX;
    }

    public enum PowerType {
        None,
        SPELL,
        SKILL
    }

    public enum CostType {
        NONE,
        HEALTH,
        MANA,
        STAMINA
    }

    public enum AreaType {
        NONE,
        SPHERE,
        POINTBLANK,
        LINE,
        CONE,
        WALL
    }

    public enum ExcludeType {
        NONE,
        CASTER,
        GROUP,
        GUILD,
        NATION,
        PLAYERS,
        ALLBUTGROUP,
        ALLBUTPETS
    }

    public enum CastingModeType {
        NONE,
        COMBAT,
        NONCOMBAT,
        BOTH
    }

    public enum TargetSelectType {
        NONE,
        CLICK,
        GROUP,
        GUILD,
        NEARBYMOBS,
        NAME
    }

    public enum CategoryToPowerType {
        None,
        GreaterThanOrEqualTo,
        GreaterThan,
        Always
    }

    public enum ModificationType {
        ADD,
        MULTIPLY
    }

    public enum ServerConfig {
        MBDB_108("AERYNTH", "ARAC", "MOURNING", 300000),
        MBDB_192("DALGOTH", "ARAC", "GOOK", 300001),
        MBDB_162("VORGINA", "LORE", "SAEDRON", 300002),
        MBDB_164("VORGINA", "ARAC", "THURIN", 300002);

        public final String mapType;
        public final String ruleType;
        public final String serverName;
        public final int realmMap;

        ServerConfig(String mapType, String ruleType, String serverName, int realmMap) {

            this.mapType = mapType;
            this.ruleType = ruleType;
            this.serverName = serverName;
            this.realmMap = realmMap;
        }
    }
}

