/**
*------------------------------------------------------------------------------
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lostkingdomsfrontier.pfrpg.encounter.combat;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.lostkingdomsfrontier.pfrpg.AdjustableValue;
import org.lostkingdomsfrontier.pfrpg.Adjustment;
import org.lostkingdomsfrontier.pfrpg.dice.Dice;
import org.lostkingdomsfrontier.pfrpg.entity.Ability;
import org.lostkingdomsfrontier.pfrpg.entity.AbilityListenerValue;
import org.lostkingdomsfrontier.pfrpg.entity.AbilityValue;
import org.lostkingdomsfrontier.pfrpg.entity.Size;
/**
* @author bebopjmm
*
*/
public class Defense
{
static final Log LOG = LogFactory.getLog(Defense.class);
public enum AC_Type {
AC_Reg, AC_Touch;
}
EnumMap<AC_Type, AbilityListenerValue> armorClass;
ArrayList<Adjustment> naturalArmor = new ArrayList<Adjustment>();
Adjustment bestNaturalArmor;
Adjustment sizeAdj;
boolean rollDefense = true;
boolean isFlatFooted = true;
Dice dice = Dice.getInstance();
public Defense(Size size, AbilityValue dexterityAbility)
{
// sizeAdj = Size.generateCombatAdjustment(size);
armorClass = new EnumMap<AC_Type, AbilityListenerValue>(AC_Type.class);
AbilityListenerValue acEntry = null;
for (AC_Type ac : EnumSet.range(AC_Type.AC_Reg, AC_Type.AC_Touch)) {
acEntry = new AbilityListenerValue(ac.toString(), 0, dexterityAbility);
acEntry.addAdjustment(sizeAdj);
armorClass.put(ac, acEntry);
}
}
public void setBaseDefenseBonus(int baseDefenseBonus)
{
LOG.info("Setting baseDefenseBonus to: " + baseDefenseBonus);
AbilityListenerValue acEntry = null;
for (AC_Type ac : armorClass.keySet()) {
acEntry = armorClass.get(ac);
acEntry.setBase(baseDefenseBonus);
}
}
/**
* @param newSize
*/
public void setSize(Size newSize)
{
sizeAdj.setValue(newSize.getCombatModifier());
}
public boolean isFlatFooted()
{
return this.isFlatFooted;
}
public void setFlatFooted(boolean isFlatFooted)
{
this.isFlatFooted = isFlatFooted;
AbilityListenerValue acEntry = null;
if (isFlatFooted) {
LOG.info("Limiting DEX bonus for AC to 0");
for (AC_Type ac : EnumSet.range(AC_Type.AC_Reg, AC_Type.AC_Touch)) {
acEntry = armorClass.get(ac);
acEntry.setLimiter(Ability.DEX, (short)0);
}
}
else {
LOG.info("Removing DEX bonus limits for AC");
for (AC_Type ac : EnumSet.range(AC_Type.AC_Reg, AC_Type.AC_Touch)) {
acEntry = armorClass.get(ac);
acEntry.removeLimiter(Ability.DEX);
}
}
}
public int defend(boolean touchAttack)
{
// NO Dex bonus if flatFooted
// NO AC bonus if touch
int defense = 0;
if (rollDefense) {
int baseRoll = dice.roll(1, 20, 0);
defense = baseRoll;
}
defense += armorClass.get(AC_Type.AC_Reg).getCurrent();
return defense;
}
public int defend(int playerRoll, boolean touchAttack)
{
return playerRoll + armorClass.get(AC_Type.AC_Reg).getCurrent();
}
public AdjustableValue getArmorClass(AC_Type selection)
{
return armorClass.get(selection);
}
public synchronized void addNaturalArmor(Adjustment adjustment)
{
LOG.info("Old regular AC = " + getArmorClass(AC_Type.AC_Reg).getCurrent());
naturalArmor.add(adjustment);
// find and apply the largest natural armor adjustment to AC.
if (bestNaturalArmor == null) {
bestNaturalArmor = adjustment;
AbilityListenerValue acEntry = armorClass.get(AC_Type.AC_Reg);
acEntry.addAdjustment(bestNaturalArmor);
LOG.debug("New natural armor is best, value = " + adjustment.getValue());
}
else if (adjustment.getValue() > bestNaturalArmor.getValue()) {
AbilityListenerValue acEntry = armorClass.get(AC_Type.AC_Reg);
acEntry.removeAdjustment(bestNaturalArmor);
bestNaturalArmor = adjustment;
acEntry.addAdjustment(bestNaturalArmor);
LOG.debug("New natural armor is best, value = " + adjustment.getValue());
}
LOG.info("New regular AC = " + getArmorClass(AC_Type.AC_Reg).getCurrent());
}
public synchronized void removeNaturalArmor(Adjustment adjustment)
{
if (!naturalArmor.contains(adjustment)) {
return;
}
naturalArmor.remove(adjustment);
if (bestNaturalArmor == adjustment) {
AbilityListenerValue acEntry = armorClass.get(AC_Type.AC_Reg);
acEntry.removeAdjustment(bestNaturalArmor);
bestNaturalArmor = null;
int bestVal = -1;
for (Adjustment armorOption : naturalArmor) {
if (armorOption.getValue() > bestVal) {
bestNaturalArmor = armorOption;
bestVal = armorOption.getValue();
}
}
if (bestNaturalArmor != null) {
acEntry.addAdjustment(bestNaturalArmor);
}
}
}
}