/*
* WieldCategory.java
* Copyright (c) 2010 Tom Parker <thpr@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @author Jayme Cox <jaymecox@users.sourceforge.net>
* Created on November 21, 2003, 11:26 PM
*
* Current Ver: $Revision$
*
*/
package pcgen.core.character;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pcgen.cdom.base.Loadable;
import pcgen.cdom.enumeration.IntegerKey;
import pcgen.cdom.enumeration.ObjectKey;
import pcgen.cdom.reference.CDOMDirectSingleRef;
import pcgen.cdom.reference.CDOMSingleRef;
import pcgen.core.Equipment;
import pcgen.core.Globals;
import pcgen.core.PlayerCharacter;
import pcgen.core.QualifiedObject;
import pcgen.core.SizeAdjustment;
import pcgen.core.prereq.PrereqHandler;
import pcgen.rules.context.AbstractReferenceContext;
public final class WieldCategory implements Loadable
{
private URI sourceURI;
private String categoryName;
private int handsRequired;
private boolean isFinessable;
private int sizeDifference;
private Map<Integer, Float> damageMultiplier = new HashMap<>();
private Map<Integer, CDOMSingleRef<WieldCategory>> wcSteps = new HashMap<>();
private List<QualifiedObject<CDOMSingleRef<WieldCategory>>> categorySwitches = new ArrayList<>();
@Override
public URI getSourceURI()
{
return sourceURI;
}
@Override
public void setSourceURI(URI source)
{
sourceURI = source;
}
public void setKeyName(String key)
{
setName(key);
}
@Override
public String getKeyName()
{
return getDisplayName();
}
@Override
public String getDisplayName()
{
return categoryName;
}
@Override
public void setName(String name)
{
categoryName = name;
}
@Override
public String getLSTformat()
{
return getDisplayName();
}
@Override
public boolean isInternal()
{
return false;
}
@Override
public boolean isType(String type)
{
return false;
}
public int getHandsRequired()
{
return handsRequired;
}
public void setHandsRequired(int hands)
{
handsRequired = hands;
}
public void setFinessable(boolean finessable)
{
isFinessable = finessable;
}
public boolean isFinessable()
{
return isFinessable;
}
public void setSizeDifference(int difference)
{
sizeDifference = difference;
}
public void setWieldCategoryStep(int location,
CDOMSingleRef<WieldCategory> stepCat)
{
CDOMSingleRef<WieldCategory> previous = wcSteps.put(location, stepCat);
if (previous != null)
{
// overwrite warning?
}
}
public void addDamageMult(int numHands, float mult)
{
Float previous = damageMultiplier.put(numHands, mult);
if (previous != null)
{
// overwrite warning?
}
}
public WieldCategory getWieldCategoryStep(int steps)
{
CDOMSingleRef<WieldCategory> wcRef = wcSteps.get(steps);
return wcRef == null ? null : wcRef.get();
}
public void addCategorySwitch(
QualifiedObject<CDOMSingleRef<WieldCategory>> qo)
{
categorySwitches.add(qo);
}
public int getObjectSizeInt(Equipment eq)
{
return eq.sizeInt() + sizeDifference;
}
/**
* Get the WieldCategory adjusted for the size difference between the weapon
* and the PC. This uses the 3.5 equipment sizes.
*
* @param pc
* Player character to get the weild category for.
* @param eq
* Equipment to get the weild category for.
* @return The ajusted WieldCategory
*/
public WieldCategory adjustForSize(final PlayerCharacter pc,
final Equipment eq)
{
if (pc == null || eq == null || eq.get(ObjectKey.WIELD) == null)
{
return this;
}
// Check if we have a bonus that changes the weapons effective size
// for wield purposes.
SizeAdjustment oldEqSa = eq.getSizeAdjustment();
if (pc.sizeInt() != eq.sizeInt())
{
int aBump = 0;
aBump += (int) pc.getTotalBonusTo("WIELDCATEGORY", eq
.getWieldName());
aBump += (int) pc.getTotalBonusTo("WIELDCATEGORY", "ALL");
// loops for each equipment type
int modWield = 0;
for ( String eqType : eq.typeList() )
{
final StringBuilder sB = new StringBuilder("WEAPONPROF=TYPE.");
sB.append(eqType);
// get the type bonus (ex TYPE.MARTIAL)
final int i = (int) pc.getTotalBonusTo(sB.toString(), "WIELDCATEGORY");
// get the highest bonus
if (i < modWield)
{
modWield = i;
}
}
aBump += modWield;
if (aBump != 0)
{
final int newSizeInt = eq.sizeInt() + aBump;
AbstractReferenceContext ref =
Globals.getContext().getReferenceContext();
SizeAdjustment sadj =
ref.getSortedList(SizeAdjustment.class,
IntegerKey.SIZEORDER).get(newSizeInt);
eq.put(ObjectKey.SIZE, CDOMDirectSingleRef.getRef(sadj));
}
}
WieldCategory pcWCat = getSwitch(pc, eq);
eq.put(ObjectKey.SIZE, CDOMDirectSingleRef.getRef(oldEqSa));
return pcWCat;
}
private WieldCategory getSwitch(PlayerCharacter pc, Equipment eq)
{
WieldCategory pcWCat = this;
// TODO what if more than one matches??
for (QualifiedObject<CDOMSingleRef<WieldCategory>> qo : categorySwitches)
{
if (PrereqHandler.passesAll(qo.getPrerequisiteList(), eq, pc))
{
pcWCat = qo.getRawObject().get();
}
}
return pcWCat;
}
@Override
public int hashCode()
{
return categoryName.hashCode();
}
@Override
public boolean equals(Object o)
{
if (o instanceof WieldCategory)
{
/*
* Light weight check due to ReferenceManufacturer enforcement
*/
WieldCategory other = (WieldCategory) o;
return categoryName.equals(other.categoryName);
}
return false;
}
}