package com.hero.objects.characteristics;

import java.math.BigDecimal;

import org.jdom.Element;

import com.hero.HeroDesigner;
import com.hero.objects.CharAffectingObject;
import com.hero.objects.GenericObject;
import com.hero.objects.powers.CompoundPower;
import com.hero.objects.powers.Power;
import com.hero.util.Constants;
import com.hero.util.Rounder;

/**
 * Copyright (c) 2000 - 2005, CompNet Design, Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, is prohibited unless the following conditions are met: 1.
 * Express written consent of CompNet Design, Inc. is obtained by the developer.
 * 2. Redistributions must retain this copyright notice. THIS SOFTWARE IS
 * PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * @author CompNet Design, Inc.
 * @version $Revision$
 */

public class Leaping extends Characteristic {

    private static String xmlID = "LEAPING";

    protected double primaryForward;

    protected long primaryForwardCalcTime;

    protected double primaryUpward;

    protected long primaryUpwardCalcTime;

    protected double secondaryForward;

    protected long secondaryForwardCalcTime;

    protected double secondaryUpward;

    protected long secondaryUpwardCalcTime;

    public Leaping(Element root) {
        super(root, Leaping.xmlID);
    }

    @Override
    protected void calcBaseValue() {
        double bonus = 0;
        doubleBase = 0;
        if (HeroDesigner.getActiveHero() != null) {
            for (int i = 0; i < HeroDesigner.getActiveHero()
                    .getCharacteristics().size(); i++) {
                Characteristic ch = (Characteristic) HeroDesigner
                        .getActiveHero().getCharacteristics().get(i);
                if (!ch.getXMLID().equals(getXMLID())
                        && ch.getIncreaseLevels(getType()) > 0
                        && ch.getIncrease(getType()) != 0) {
                    double mult = ch.getCharacteristicValue()
                            * ch.getIncrease(getType()) / ch
                                    .getIncreaseLevels(getType());
                    doubleBase += mult;
                    bonus += Rounder.roundDown(mult * 2) / 2d;
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
                if (HeroDesigner.getActiveHero().getPowers().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue; // only interested in figured
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())) {
                            continue; // only interested in figured
                        } else if (cp.getPowers().get(j) instanceof Characteristic) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += Rounder.roundDown(mult * 2) / 2d;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Characteristic) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += Rounder.roundDown(mult * 2) / 2d;
                        }
                    }
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment()
                    .size(); i++) {
                if (HeroDesigner.getActiveHero().getEquipment().get(i)
                        .getXMLID().equals(getXMLID())) {
                    continue; // only interested in figured
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())) {
                            continue; // only interested in figured
                        } else if (cp.getPowers().get(j) instanceof Characteristic) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += Rounder.roundDown(mult * 2) / 2d;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Characteristic) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += Rounder.roundDown(mult * 2) / 2d;
                        }
                    }
                }
            }
        }

        // the following is because Leaping should be based off of total STR,
        // not incremental purchases/rounding:
        bonus = Rounder.roundDown(doubleBase * 2) / 2d;

        if (baseLevel + bonus < minimumLevel) {
            baseValue = minimumLevel;
        } else if (baseLevel + bonus < maxVal) {
            baseValue = baseLevel + bonus;
        } else {
            baseValue = maxVal - bonus;
        }
        baseValueCalcTime = System.currentTimeMillis();
    }

    protected void calcPrimaryForward() {
        double bonus = 0;
        if (HeroDesigner.getActiveHero() != null) {
            doubleBase = super.getCharacteristicValue();
            for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
                if (HeroDesigner.getActiveHero().getPowers().get(i)
                        .getXMLID().equals(getXMLID())
                        && GenericObject.findObjectByID(HeroDesigner
                                .getActiveHero().getPowers().get(i)
                                .getAssignedModifiers(), "UPWARDMOVEMENTONLY") == null) {
                    Characteristic power = (Characteristic) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getAffectPrimary() && power.getAffectTotal()) {
                        bonus += power.getLevels();
                        doubleBase += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())
                                && GenericObject.findObjectByID(cp.getPowers()
                                        .get(j).getAssignedModifiers(),
                                        "UPWARDMOVEMENTONLY") == null) {
                            Characteristic power = (Characteristic) cp
                                    .getPowers().get(j);
                            if (power.getAffectPrimary()
                                    && power.getAffectTotal()) {
                                bonus += power.getLevels();
                                doubleBase += power.getLevels();
                            }
                        } else if (cp.getPowers().get(j) instanceof Power) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += mult;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += mult;
                        }
                    }
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment()
                    .size(); i++) {
                if (HeroDesigner.getActiveHero().getEquipment().get(i)
                        .getXMLID().equals(getXMLID())
                        && GenericObject.findObjectByID(HeroDesigner
                                .getActiveHero().getEquipment().get(i)
                                .getAssignedModifiers(), "UPWARDMOVEMENTONLY") == null) {
                    Characteristic power = (Characteristic) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getAffectPrimary() && power.getAffectTotal()) {
                        bonus += power.getLevels();
                        doubleBase += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())
                                && GenericObject.findObjectByID(cp.getPowers()
                                        .get(j).getAssignedModifiers(),
                                        "UPWARDMOVEMENTONLY") == null) {
                            Characteristic power = (Characteristic) cp
                                    .getPowers().get(j);
                            if (power.getAffectPrimary()
                                    && power.getAffectTotal()) {
                                bonus += power.getLevels();
                                doubleBase += power.getLevels();
                            }
                        } else if (cp.getPowers().get(j) instanceof Power) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += mult;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += mult;
                        }
                    }
                }
            }
        }
        if (doubleBase < maxVal) {
            primaryForward = doubleBase;
        } else {
            primaryForward = maxVal;
        }

        primaryForwardCalcTime = System.currentTimeMillis();
    }

    protected void calcPrimaryUpward() {
        double bonus = 0;
        if (HeroDesigner.getActiveHero() != null) {
            doubleBase = super.getCharacteristicValue();
            for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
                if (HeroDesigner.getActiveHero().getPowers().get(i)
                        .getXMLID().equals(getXMLID())
                        && GenericObject.findObjectByID(HeroDesigner
                                .getActiveHero().getPowers().get(i)
                                .getAssignedModifiers(), "FORWARDMOVEMENTONLY") == null) {
                    Characteristic power = (Characteristic) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getAffectPrimary() && power.getAffectTotal()) {
                        bonus += power.getLevels();
                        doubleBase += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())
                                && GenericObject.findObjectByID(cp.getPowers()
                                        .get(j).getAssignedModifiers(),
                                        "FORWARDMOVEMENTONLY") == null) {
                            Characteristic power = (Characteristic) cp
                                    .getPowers().get(j);
                            if (power.getAffectPrimary()
                                    && power.getAffectTotal()) {
                                bonus += power.getLevels();
                                doubleBase += power.getLevels();
                            }
                        } else if (cp.getPowers().get(j) instanceof Power) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += mult;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getPowers().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += mult;
                        }
                    }
                }
            }
            for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment()
                    .size(); i++) {
                if (HeroDesigner.getActiveHero().getEquipment().get(i)
                        .getXMLID().equals(getXMLID())
                        && GenericObject.findObjectByID(HeroDesigner
                                .getActiveHero().getEquipment().get(i)
                                .getAssignedModifiers(), "FORWARDMOVEMENTONLY") == null) {
                    Characteristic power = (Characteristic) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getAffectPrimary() && power.getAffectTotal()) {
                        bonus += power.getLevels();
                        doubleBase += power.getLevels();
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                    CompoundPower cp = (CompoundPower) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    for (int j = 0; j < cp.getPowers().size(); j++) {
                        if (cp.getPowers().get(j).getXMLID().equals(
                                getXMLID())
                                && GenericObject.findObjectByID(cp.getPowers()
                                        .get(j).getAssignedModifiers(),
                                        "FORWARDMOVEMENTONLY") == null) {
                            Characteristic power = (Characteristic) cp
                                    .getPowers().get(j);
                            if (power.getAffectPrimary()
                                    && power.getAffectTotal()) {
                                bonus += power.getLevels();
                                doubleBase += power.getLevels();
                            }
                        } else if (cp.getPowers().get(j) instanceof Power) {
                            CharAffectingObject power = (CharAffectingObject) cp
                                    .getPowers().get(j);
                            if (power.getIncreaseLevels(getType()) > 0
                                    && power.getIncrease(getType()) != 0) {
                                if (power.getAffectPrimary()
                                        && CharAffectingObject.checkFigured(power, getType())
                                        && power.getAffectTotal()) {
                                    double mult = power.getIncreaseValue(
                                            getType(), true);
                                    doubleBase += mult;
                                    bonus += mult;
                                }
                            }
                        }
                    }
                } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof Power) {
                    CharAffectingObject power = (CharAffectingObject) HeroDesigner
                            .getActiveHero().getEquipment().get(i);
                    if (power.getIncreaseLevels(getType()) > 0
                            && power.getIncrease(getType()) != 0) {
                        if (power.getAffectPrimary()
                                && CharAffectingObject.checkFigured(power, getType())
                                && power.getAffectTotal()) {
                            double mult = power.getIncreaseValue(getType(),
                                    true);
                            doubleBase += mult;
                            bonus += mult;
                        }
                    }
                }
            }
        }
        if (doubleBase / 2d < maxVal) {
            primaryUpward = doubleBase / 2d;
        } else {
            primaryUpward = maxVal;
        }

        primaryUpwardCalcTime = System.currentTimeMillis();
    }

    protected void calcSecondaryForward() {
        double bonus = 0;
        for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
            if (HeroDesigner.getActiveHero().getPowers().get(i).getXMLID()
                    .equals(getXMLID())
                    && GenericObject.findObjectByID(HeroDesigner
                            .getActiveHero().getPowers().get(i)
                            .getAssignedModifiers(), "UPWARDMOVEMENTONLY") == null) {
                Characteristic power = (Characteristic) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (!power.getAffectPrimary() && power.getAffectTotal()) {
                    bonus += power.getLevels();
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                CompoundPower cp = (CompoundPower) HeroDesigner.getActiveHero()
                        .getPowers().get(i);
                for (int j = 0; j < cp.getPowers().size(); j++) {
                    if (cp.getPowers().get(j).getXMLID().equals(getXMLID())
                            && GenericObject.findObjectByID(cp.getPowers()
                                    .get(j).getAssignedModifiers(),
                                    "UPWARDMOVEMENTONLY") == null) {
                        Characteristic power = (Characteristic) cp.getPowers()
                                .get(j);
                        if (!power.getAffectPrimary() && power.getAffectTotal()) {
                            bonus += power.getLevels();
                        }
                    } else if (cp.getPowers().get(j) instanceof CharAffectingObject) {
                        CharAffectingObject power = (CharAffectingObject) cp
                                .getPowers().get(j);
                        if (power.getIncreaseLevels(getType()) > 0
                                && power.getIncrease(getType()) != 0) {
                            if (!power.getAffectPrimary()
                                    && CharAffectingObject.checkFigured(power, getType())
                                    && power.getAffectTotal()) {
                                double mult = power.getIncreaseValue(getType(),
                                        false);
                                bonus += mult;
                            }
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())) {
                    double add = power.getIncreaseValue(getType(), false);
                    bonus += add;
                }
            }
        }
        for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment().size(); i++) {
            if (HeroDesigner.getActiveHero().getEquipment().get(i).getXMLID()
                    .equals(getXMLID())
                    && GenericObject.findObjectByID(HeroDesigner
                            .getActiveHero().getEquipment().get(i)
                            .getAssignedModifiers(), "UPWARDMOVEMENTONLY") == null) {
                Characteristic power = (Characteristic) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (!power.getAffectPrimary() && power.getAffectTotal()) {
                    bonus += power.getLevels();
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                CompoundPower cp = (CompoundPower) HeroDesigner.getActiveHero()
                        .getEquipment().get(i);
                for (int j = 0; j < cp.getPowers().size(); j++) {
                    if (cp.getPowers().get(j).getXMLID().equals(getXMLID())
                            && GenericObject.findObjectByID(cp.getPowers()
                                    .get(j).getAssignedModifiers(),
                                    "UPWARDMOVEMENTONLY") == null) {
                        Characteristic power = (Characteristic) cp.getPowers()
                                .get(j);
                        if (!power.getAffectPrimary() && power.getAffectTotal()) {
                            bonus += power.getLevels();
                        }
                    } else if (cp.getPowers().get(j) instanceof CharAffectingObject) {
                        CharAffectingObject power = (CharAffectingObject) cp
                                .getPowers().get(j);
                        if (power.getIncreaseLevels(getType()) > 0
                                && power.getIncrease(getType()) != 0) {
                            if (!power.getAffectPrimary()
                                    && CharAffectingObject.checkFigured(power, getType())
                                    && power.getAffectTotal()) {
                                double mult = power.getIncreaseValue(getType(),
                                        false);
                                bonus += mult;
                            }
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())) {
                    double add = power.getIncreaseValue(getType(), false);
                    bonus += add;
                }
            }
        }
        bonus += getPrimaryForward();
        if (bonus < maxVal) {
            secondaryForward = bonus;
        } else {
            secondaryForward = maxVal;
        }

        secondaryForwardCalcTime = System.currentTimeMillis();
    }

    protected void calcSecondaryUpward() {
        double bonus = 0;
        for (int i = 0; i < HeroDesigner.getActiveHero().getPowers().size(); i++) {
            if (HeroDesigner.getActiveHero().getPowers().get(i).getXMLID()
                    .equals(getXMLID())
                    && GenericObject.findObjectByID(HeroDesigner
                            .getActiveHero().getPowers().get(i)
                            .getAssignedModifiers(), "FORWARDMOVEMENTONLY") == null) {
                Characteristic power = (Characteristic) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (!power.getAffectPrimary() && power.getAffectTotal()) {
                    bonus += power.getLevels();
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CompoundPower) {
                CompoundPower cp = (CompoundPower) HeroDesigner.getActiveHero()
                        .getPowers().get(i);
                for (int j = 0; j < cp.getPowers().size(); j++) {
                    if (cp.getPowers().get(j).getXMLID().equals(getXMLID())
                            && GenericObject.findObjectByID(cp.getPowers()
                                    .get(j).getAssignedModifiers(),
                                    "FORWARDMOVEMENTONLY") == null) {
                        Characteristic power = (Characteristic) cp.getPowers()
                                .get(j);
                        if (!power.getAffectPrimary() && power.getAffectTotal()) {
                            bonus += power.getLevels();
                            doubleBase += power.getLevels();
                        }
                    } else if (cp.getPowers().get(j) instanceof CharAffectingObject) {
                        CharAffectingObject power = (CharAffectingObject) cp
                                .getPowers().get(j);
                        if (power.getIncreaseLevels(getType()) > 0
                                && power.getIncrease(getType()) != 0) {
                            if (!power.getAffectPrimary()
                                    && CharAffectingObject.checkFigured(power, getType())
                                    && power.getAffectTotal()) {
                                double mult = power.getIncreaseValue(getType(),
                                        false);
                                doubleBase += mult;
                                bonus += mult;
                            }
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getPowers().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getPowers().get(i);
                if (power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())) {
                    double add = power.getIncreaseValue(getType(), false);

                    bonus += add;
                }
            }
        }
        for (int i = 0; i < HeroDesigner.getActiveHero().getEquipment().size(); i++) {
            if (HeroDesigner.getActiveHero().getEquipment().get(i).getXMLID()
                    .equals(getXMLID())
                    && GenericObject.findObjectByID(HeroDesigner
                            .getActiveHero().getEquipment().get(i)
                            .getAssignedModifiers(), "FORWARDMOVEMENTONLY") == null) {
                Characteristic power = (Characteristic) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (!power.getAffectPrimary() && power.getAffectTotal()) {
                    bonus += power.getLevels();
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CompoundPower) {
                CompoundPower cp = (CompoundPower) HeroDesigner.getActiveHero()
                        .getEquipment().get(i);
                for (int j = 0; j < cp.getPowers().size(); j++) {
                    if (cp.getPowers().get(j).getXMLID().equals(getXMLID())
                            && GenericObject.findObjectByID(cp.getPowers()
                                    .get(j).getAssignedModifiers(),
                                    "FORWARDMOVEMENTONLY") == null) {
                        Characteristic power = (Characteristic) cp.getPowers()
                                .get(j);
                        if (!power.getAffectPrimary() && power.getAffectTotal()) {
                            bonus += power.getLevels();
                            doubleBase += power.getLevels();
                        }
                    } else if (cp.getPowers().get(j) instanceof CharAffectingObject) {
                        CharAffectingObject power = (CharAffectingObject) cp
                                .getPowers().get(j);
                        if (power.getIncreaseLevels(getType()) > 0
                                && power.getIncrease(getType()) != 0) {
                            if (!power.getAffectPrimary()
                                    && CharAffectingObject.checkFigured(power, getType())
                                    && power.getAffectTotal()) {
                                double mult = power.getIncreaseValue(getType(),
                                        false);
                                doubleBase += mult;
                                bonus += mult;
                            }
                        }
                    }
                }
            } else if (HeroDesigner.getActiveHero().getEquipment().get(i) instanceof CharAffectingObject) {
                CharAffectingObject power = (CharAffectingObject) HeroDesigner
                        .getActiveHero().getEquipment().get(i);
                if (power.getIncreaseLevels(getType()) > 0
                        && CharAffectingObject.checkFigured(power, getType())) {
                    double add = power.getIncreaseValue(getType(), false);

                    bonus += add;
                }
            }
        }
        double value = bonus / 2 + getPrimaryUpward();
        if (value < maxVal) {
            secondaryUpward = value;
        } else {
            secondaryUpward = maxVal;
        }

        secondaryUpwardCalcTime = System.currentTimeMillis();
    }

    @Override
    public String getCharacteristicBase() {
        BigDecimal bd = new BigDecimal(
                Rounder.roundDown(getBaseValue() * 2) / 2d);
        bd = bd.setScale(1, BigDecimal.ROUND_HALF_UP);
        return bd.toString();
    }

    @Override
    public String getColumn2Output() {
    	boolean is6E = HeroDesigner.getActiveTemplate().is6E();
        if (getLevels() == 0 && addModifiersToBase()
                && getModifierString().trim().length() > 0) {
            String mods = getModifierString();
            if (mods.trim().startsWith(",")) {
                mods = mods.trim().substring(1, mods.length()).trim();
            }
            mods += " applied to " + getAlias();

            if (getName() != null && getName().trim().length() > 0) {
                mods = "<i>" + getName() + ":</i>  " + mods;
            }

            return mods;
        }
        String ret = getAlias();
        if (getName().trim().length() > 0) {
            ret = "<i>" + getName() + ":</i>  " + ret;
        }
        if (getAffectTotal() && getLevels() > 0) {
            ret += " +";
        } else {
            ret += " ";
        }
        ret += getLevels() + (is6E?"m":"\"");
        if (getAffectTotal()) {
            ret += " (" + getDisplayNotes() + ")";
        }
        if (getInput() != null && getInput().trim().length() > 0) {
            ret += ":  " + getInput();
        }
        if (getSelectedOption() != null) {
            ret += " (";
            ret += getSelectedOption().getAlias();

            String adderString = getAdderString();
            if (adderString.trim().length() > 0) {
                ret += "; " + adderString;
            }
            ret += ")";
        } else {
            String adderString = getAdderString();
            if (adderString.trim().length() > 0) {
                ret += " (" + adderString + ")";
            }
        }
        ret += getModifierString();
        if (getEndUsage() > 0
                && GenericObject.findObjectByID(HeroDesigner.getActiveHero().getPowers(),
                        "ENDURANCERESERVE") != null
                && GenericObject.findObjectByID(getAllAssignedModifiers(), "ENDRESERVEOREND") == null
                && !HeroDesigner.getInstance().getPrefs().useWG()) {
            if (getUseENDReserve()) {
                ret += " (uses END Reserve)";
            } else {
                ret += " (uses Personal END)";
            }
        }

        return ret;
    }

    @Override
    public String getDisplayNotes() {
    	boolean is6E = HeroDesigner.getActiveTemplate().is6E();
        String ret = "";
        double primaryForward = getPrimaryForward();
        double primaryUpward = getPrimaryUpward();
        double secondaryForward = getSecondaryForward();
        double secondaryUpward = getSecondaryUpward();
        String pFor = "";
        if (primaryForward - Rounder.roundDown(primaryForward) >= .5
                && (primaryForward > 1 || getLevels() >= 0)) {
            pFor = Rounder.roundDown(primaryForward) + " 1/2"+(is6E?"m":"\"");
        } else {
            pFor = Rounder.roundDown(primaryForward) + (is6E?"m":"\"");
        }
        String pUp = "";
        if (primaryUpward - Rounder.roundDown(primaryUpward) >= .5
                && (primaryUpward > 1 || getLevels() >= 0)) {
            pUp = Rounder.roundDown(primaryUpward) + " 1/2"+(is6E?"m":"\"");
        } else if (primaryUpward - Rounder.roundDown(primaryUpward) >= .5
                && (primaryUpward > 0 || getLevels() >= 0)) {
            pUp = "1/2"+(is6E?"m":"\"");
        } else {
            pUp = Rounder.roundDown(primaryUpward) + (is6E?"m":"\"");
        }
        String secFor = "";
        if (secondaryForward - Rounder.roundDown(secondaryForward) >= .5
                && (secondaryForward > 1 || getLevels() >= 0)) {
            secFor = Rounder.roundDown(secondaryForward) + " 1/2"+(is6E?"m":"\"");
        } else {
            secFor = Rounder.roundDown(secondaryForward) + (is6E?"m":"\"");
        }
        String secUp = "";
        if (secondaryUpward - Rounder.roundDown(secondaryUpward) >= .5
                && (secondaryUpward > 1 || getLevels() >= 0)) {
            secUp = Rounder.roundDown(secondaryUpward) + " 1/2"+(is6E?"m":"\"");
        } else if (secondaryUpward - Rounder.roundDown(secondaryUpward) >= .5
                && (secondaryUpward > 0 || getLevels() >= 0)) {
            secUp = "1/2"+(is6E?"m":"\"");
        } else {
            secUp = Rounder.roundDown(secondaryUpward) + (is6E?"m":"\"");
        }

        if (primaryForward != secondaryForward
                || primaryUpward != secondaryUpward) {
            ret = pFor + "/" + secFor + " forward, " + pUp + "/" + secUp
                    + " upward";
        } else {
            ret = pFor + " forward, " + pUp + " upward";
        }
        return ret;
    }

    public double getPrimaryForward() {
        if (primaryForwardCalcTime <= 0
                || primaryForwardCalcTime < HeroDesigner.lastEdit) {
            calcPrimaryForward();
        }
        return primaryForward;
    }

    public double getPrimaryUpward() {
        if (primaryUpwardCalcTime <= 0
                || primaryUpwardCalcTime < HeroDesigner.lastEdit) {
            calcPrimaryUpward();
        }
        return primaryUpward;
    }

    @Override
    public String getRoll() {
        return "";
    }

    public double getSecondaryForward() {
        if (secondaryForwardCalcTime <= 0
                || secondaryForwardCalcTime < HeroDesigner.lastEdit) {
            calcSecondaryForward();
        }
        return secondaryForward;
    }

    public double getSecondaryUpward() {
        if (secondaryUpwardCalcTime <= 0
                || secondaryUpwardCalcTime < HeroDesigner.lastEdit) {
            calcSecondaryUpward();
        }
        return secondaryUpward;
    }

    @Override
    public int getType() {
        return Constants.LEAPING;
    }

    @Override
    public String getValueDisplay() {
    	boolean is6E = HeroDesigner.getActiveTemplate().is6E();
        String ret = "";
        double primaryForward = getPrimaryForward();
        double secondaryForward = getSecondaryForward();
        String pFor = "";
        if (primaryForward - Rounder.roundDown(primaryForward) >= .5
                && (primaryForward > 1 || getLevels() >= 0)) {
            pFor = Rounder.roundDown(primaryForward) + " 1/2"+(is6E?"m":"\"");
        } else {
            pFor = Rounder.roundDown(primaryForward) + (is6E?"m":"\"");
        }
        String secFor = "";
        if (secondaryForward - Rounder.roundDown(secondaryForward) >= .5
                && (secondaryForward > 1 || getLevels() >= 0)) {
            secFor = Rounder.roundDown(secondaryForward) + " 1/2"+(is6E?"m":"\"");
        } else {
            secFor = Rounder.roundDown(secondaryForward) + (is6E?"m":"\"");
        }
        if (primaryForward != secondaryForward) {
            ret = pFor + "/" + secFor;
        } else {
            ret = pFor;
        }
        return ret;
    }

    @Override
    public void init(Element element) {
        display = "Leaping";
        levelCost = 1;
        levelValue = 1;
        minimumCost = 1;
        baseCost = 0;
        super.init(element);
    }

    @Override
    public boolean isFigured() {
        return false;
    }

    public boolean verified() {
        return true;
    }

    @Override
    public double getCharacteristicValue() {
        double ret = super.getCharacteristicValue();
        return Math.floor(ret);
    }

    @Override
    public void setValue(double val) {
        double check = getCharacteristicValue();
        double base = Math.floor(getBaseValue());
        if (val == check) {
            return; // no action needed...
        } else {
            if (val < minimumLevel) {
                setLevels((int) Rounder.roundHalfDown(minimumLevel - val));
            }
            if (val < maxVal) {
                setLevels((int) Rounder.roundHalfDown(val - base));
            } else {
                setLevels((int) Rounder.roundHalfDown(maxVal - val));
            }
        }
    }
}