package net.scapeemulator.game.model.player;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import net.scapeemulator.game.model.mob.Animation;
import net.scapeemulator.game.model.mob.combat.AttackStyle;
import net.scapeemulator.game.model.mob.combat.AttackType;
import net.scapeemulator.game.model.mob.combat.CombatBonuses;
import net.scapeemulator.game.model.player.requirement.Requirements;
import net.scapeemulator.game.model.player.requirement.SkillRequirement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class EquipmentDefinition {
public enum WeaponClass {
AXE(75, "ACCURATE_SLASH", "AGGRESSIVE_SLASH", "AGGRESSIVE_CRUSH", "DEFENSIVE_SLASH"),
HAMMER(76, "ACCURATE_CRUSH", "AGGRESSIVE_CRUSH", "DEFENSIVE_CRUSH"),
BOW(77, "ACCURATE_RANGE", "RAPID_RANGE", "DEFENSIVE_RANGE"),
CLAWS(78, "ACCURATE_SLASH", "AGGRESSIVE_SLASH", "SHARED_STAB", "DEFENSIVE_SLASH"),
LONGBOW(79, "ACCURATE_RANGE", "RAPID_RANGE", "DEFENSIVE_RANGE"),
FIXED_DEVICE(80),
SWORD(81, "ACCURATE_SLASH", "AGGRESSIVE_SLASH", "SHARED_STAB", "DEFENSIVE_SLASH"),
TWO_H_SWORD(82, "ACCURATE_SLASH", "AGGRESSIVE_SLASH", "AGGRESSIVE_CRUSH", "DEFENSIVE_SLASH"),
PICKAXE(83, "ACCURATE_STAB", "AGGRESSIVE_STAB", "AGGRESSIVE_CRUSH", "DEFENSIVE_STAB"),
HALBERD(84, "SHARED_STAB", "AGGRESSIVE_SLASH", "DEFENSIVE_STAB"),
STAFF(85, "ACCURATE_CRUSH", "AGGRESSIVE_CRUSH", "DEFENSIVE_CRUSH"),
SCYTHE(86, "ACCURATE_SLASH", "AGGRESSIVE_STAB", "AGGRESSIVE_CRUSH", "DEFENSIVE_SLASH"),
SPEAR(87, "SHARED_STAB", "SHARED_SLASH", "SHARED_CRUSH", "DEFENSIVE_STAB"),
MACE(88, "ACCURATE_CRUSH", "AGGRESSIVE_CRUSH", "SHARED_STAB", "DEFENSIVE_CRUSH"),
DAGGER(89, "ACCURATE_STAB", "AGGRESSIVE_STAB", "AGGRESSIVE_SLASH", "DEFENSIVE_STAB"),
MAGIC_STAFF(90, "ACCURATE_CRUSH", "AGGRESSIVE_CRUSH", "DEFENSIVE_CRUSH"),
THROWN(91, "ACCURATE_RANGE", "RAPID_RANGE", "DEFENSIVE_RANGE"),
UNARMED(92, "ACCURATE_CRUSH", "AGGRESSIVE_CRUSH", "DEFENSIVE_CRUSH"),
WHIP(93, "ACCURATE_SLASH", "SHARED_SLASH", "DEFENSIVE_SLASH");
//473, 474 chin/lizard
private int tabId;
private AttackStyle[] styles;
private AttackType[] types;
private WeaponClass(int tabId, String ... attackInfo) {
this.tabId = tabId;
styles = new AttackStyle[attackInfo.length];
types = new AttackType[attackInfo.length];
for(int i = 0; i < attackInfo.length; i++) {
String[] info = attackInfo[i].split("_");
styles[i] = AttackStyle.valueOf(info[0]);
types[i] = AttackType.valueOf(info[1]);
}
}
public int getTabId() {
return tabId;
}
public AttackStyle getAttackStyle(int index) {
if(index < 0 || index >= styles.length) {
return null;
}
return styles[index];
}
public AttackType getAttackType(int index) {
if(index < 0 || index >= types.length) {
return null;
}
return types[index];
}
}
public static final int FLAG_TWO_HANDED = 0x1;
public static final int FLAG_FULL_HELM = 0x2;
public static final int FLAG_FULL_MASK = 0x4;
public static final int FLAG_FULL_BODY = 0x8;
private static final Logger logger = LoggerFactory.getLogger(EquipmentDefinition.class);
private static final Map<Integer, EquipmentDefinition> definitions = new HashMap<>();
public static void init() throws IOException {
try (DataInputStream reader = new DataInputStream(new FileInputStream("data/game/equipment.dat"))) {
int id;
while ((id = reader.readShort()) != -1) {
int flags = reader.read() & 0xFF;
int slot = reader.read() & 0xFF;
int equipId = reader.readShort() & 0xFFFF;
int[] bonusValues = new int[13];
for(int i = 0; i < 13; i++) {
bonusValues[i] = reader.readShort();
}
int stance = 0, weaponClass = 0, speed = 0, range = 0;
int[] animations = new int[5];
if (slot == Equipment.WEAPON) {
stance = reader.readShort() & 0xFFFF;
weaponClass = reader.read() & 0xFF;
speed = reader.read() & 0xFF;
range = reader.read() & 0xFF;
for(int i = 0; i < animations.length; i++) {
animations[i] = reader.readShort() & 0xFFFF;
}
}
EquipmentDefinition equipment = new EquipmentDefinition();
equipment.equipmentId = equipId;
equipment.slot = slot;
equipment.twoHanded = (flags & FLAG_TWO_HANDED) != 0;
equipment.fullHelm = (flags & FLAG_FULL_HELM) != 0;
equipment.fullMask = (flags & FLAG_FULL_MASK) != 0;
equipment.fullBody = (flags & FLAG_FULL_BODY) != 0;
CombatBonuses bonuses = new CombatBonuses();
bonuses.setAttackBonus(AttackType.STAB, bonusValues[0]);
bonuses.setAttackBonus(AttackType.SLASH, bonusValues[1]);
bonuses.setAttackBonus(AttackType.CRUSH, bonusValues[2]);
bonuses.setAttackBonus(AttackType.MAGIC, bonusValues[3]);
bonuses.setAttackBonus(AttackType.RANGE, bonusValues[4]);
bonuses.setDefenceBonus(AttackType.STAB, bonusValues[5]);
bonuses.setDefenceBonus(AttackType.SLASH, bonusValues[6]);
bonuses.setDefenceBonus(AttackType.CRUSH, bonusValues[7]);
bonuses.setDefenceBonus(AttackType.MAGIC, bonusValues[8]);
bonuses.setDefenceBonus(AttackType.RANGE, bonusValues[9]);
bonuses.setStrengthBonus(bonusValues[10]);
bonuses.setPrayerBonus(bonusValues[11]);
bonuses.setRangeStrengthBonus(bonusValues[12]);
equipment.bonuses = bonuses;
if (slot == Equipment.WEAPON) {
equipment.stance = stance;
equipment.weaponClass = WeaponClass.values()[weaponClass];
equipment.speed = speed;
equipment.range = range;
equipment.animations = animations;
}
int skill = 0;
while ((skill = reader.read()) != 255) {
equipment.requirements.addRequirement(new SkillRequirement(skill, reader.read() & 0xFF, false, slot == Equipment.WEAPON ? "wield that" : "wear that"));
}
definitions.put(id, equipment);
}
logger.info("Loaded " + definitions.size() + " equipment definitions.");
}
}
public static EquipmentDefinition forId(int id) {
return definitions.get(id);
}
public static EquipmentDefinition UNARMED = new EquipmentDefinition();
static {
UNARMED.slot = Equipment.WEAPON;
UNARMED.weaponClass = WeaponClass.UNARMED;
UNARMED.speed = 4;
UNARMED.range = 1;
UNARMED.animations = new int[]{422, 423, 422, -1, 424};
}
private int id, equipmentId, slot, stance, speed, range;
private int[] animations;
private boolean fullBody, fullMask, fullHelm, twoHanded;
private CombatBonuses bonuses;
private WeaponClass weaponClass;
private Requirements requirements = new Requirements();
public int getId() {
return id;
}
public int getEquipmentId() {
return equipmentId;
}
public int getSlot() {
return slot;
}
public Requirements getRequirements() {
return requirements;
}
public boolean isFullBody() {
if (slot != Equipment.BODY)
throw new IllegalStateException("Invalid body item: " + id);
return fullBody;
}
public boolean isFullMask() {
if (slot != Equipment.HEAD)
throw new IllegalStateException("Invalid head item: " + id);
return fullMask;
}
public boolean isFullHelm() {
if (slot != Equipment.HEAD)
throw new IllegalStateException("Invalid head item: " + id);
return fullHelm;
}
public boolean isTwoHanded() {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
return twoHanded;
}
public int getStance() {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
return stance;
}
public int getSpeed() {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
return speed;
}
public int getRange() {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
return range;
}
public CombatBonuses getBonuses() {
return bonuses;
}
public WeaponClass getWeaponClass() {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
return weaponClass;
}
public Animation getAnimation(AttackStyle style, AttackType type) {
if (slot != Equipment.WEAPON)
throw new IllegalStateException("Invalid weapon: " + id);
for(int i = 0; i < weaponClass.styles.length; i++) {
if(weaponClass.styles[i] == style && weaponClass.types[i] == type) {
return new Animation(animations[i]);
}
}
return null;
}
}