From 2a406a017050219cb7375e271928d4103533618f Mon Sep 17 00:00:00 2001 From: honeyhoney <> Date: Mon, 13 Nov 2017 18:27:00 -0500 Subject: [PATCH] runelite-client: add basic attack indicator plugin --- .../main/java/net/runelite/api/Varbits.java | 15 ++ .../net/runelite/api/widgets/WidgetID.java | 7 + .../net/runelite/api/widgets/WidgetInfo.java | 6 +- .../AttackIndicatorConfig.java | 48 +++++++ .../AttackIndicatorOverlay.java | 119 ++++++++++++++++ .../AttackIndicatorPlugin.java | 131 ++++++++++++++++++ .../plugins/attackindicator/AttackStyle.java | 50 +++++++ .../plugins/attackindicator/WeaponType.java | 88 ++++++++++++ 8 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java index bd3516893a..034946bd2f 100644 --- a/runelite-api/src/main/java/net/runelite/api/Varbits.java +++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java @@ -91,6 +91,21 @@ public enum Varbits POISON(102, 0, 5), VENOM(102, 6, 9), + /** + * Attack Style + */ + ATTACK_STYLE(43, 0, 7), + + /** + * Equipped weapon type + */ + EQUIPPED_WEAPON_TYPE(357, 843, 0, 5), + + /** + * Defensive casting mode + */ + DEFENSIVE_CASTING_MODE(2668, 439, 8, 8), + /** * Options */ diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index eb28cf242e..0fdaeb2a6b 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -46,6 +46,7 @@ class WidgetID static final int DIALOG_NPC_GROUP_ID = 231; static final int SLAYER_REWARDS_GROUP_ID = 426; static final int PRIVATE_CHAT = 163; + static final int CHATBOX_GROUP_ID = 162; static class SlayerRewards { @@ -137,6 +138,12 @@ class WidgetID static final int RESIZABLE_VIEWPORT_BOTTOM_LINE = 12; } + static class Chatbox + { + static final int CHATBOX_MESSAGES = 29; + static final int CHATBOX_BUTTONS = 1; + } + static class Prayer { static final int THICK_SKIN = 4; diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index ee173eeb75..5533ae61b1 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -90,7 +90,11 @@ public enum WidgetInfo PRIVATE_CHAT_MESSAGE(WidgetID.PRIVATE_CHAT, 0), - SLAYER_REWARDS_TOPBAR(WidgetID.SLAYER_REWARDS_GROUP_ID, WidgetID.SlayerRewards.TOP_BAR); + SLAYER_REWARDS_TOPBAR(WidgetID.SLAYER_REWARDS_GROUP_ID, WidgetID.SlayerRewards.TOP_BAR), + + CHATBOX(WidgetID.CHATBOX_GROUP_ID, 0), + CHATBOX_MESSAGES(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_MESSAGES), + CHATBOX_BUTTONS(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_BUTTONS); private final int groupId; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java new file mode 100644 index 0000000000..740674fe5c --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017, honeyhoney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 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 OWNER 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. + */ +package net.runelite.client.plugins.attackindicator; + +import net.runelite.client.config.Config; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = "attackindicator", + name = "Attack Indicators", + description = "Configuration for the attack indicator plugin" +) +public interface AttackIndicatorConfig extends Config +{ + @ConfigItem( + keyName = "enabled", + name = "Enabled", + description = "Configures whether or not the attack indicator overlay is displayed" + ) + default boolean enabled() + { + return true; + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java new file mode 100644 index 0000000000..34234965cd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017, honeyhoney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 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 OWNER 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. + */ +package net.runelite.client.plugins.attackindicator; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import javax.annotation.Nullable; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.GameState; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.overlay.Overlay; +import net.runelite.client.ui.overlay.OverlayPosition; + +public class AttackIndicatorOverlay extends Overlay +{ + private static final int ANCHOR_X = -4; + private static final int ANCHOR_Y = -1; + private static final int BORDER_SIZE = 2; + private static final Color BACKGROUND_COLOR = new Color(56, 48, 35, 100); + private static final Color OUTSIDE_STROKE_COLOR = new Color(56, 48, 35, 255); + private static final Color INSIDE_STROKE_COLOR = new Color(90, 82, 69, 255); + + @Inject + @Nullable + Client client; + + private final AttackIndicatorConfig config; + private final AttackIndicatorPlugin plugin; + + @Inject + public AttackIndicatorOverlay(AttackIndicatorPlugin plugin, AttackIndicatorConfig config) + { + super(OverlayPosition.DYNAMIC); + this.plugin = plugin; + this.config = config; + } + + @Override + public Dimension render(Graphics2D graphics) + { + if (!config.enabled() || client.getGameState() != GameState.LOGGED_IN) + { + return null; + } + + Rectangle chatbox = getChatboxBounds(); + if (chatbox == null) + { + return null; + } + + // Setup string + graphics.setFont(FontManager.getRunescapeFont()); + FontMetrics fm = graphics.getFontMetrics(); + String attackStyleString = plugin.getAttackStyle().getName(); + + // Create anchor point + Point anchor = new Point(chatbox.x + chatbox.width + ANCHOR_X, chatbox.y + ANCHOR_Y); + + // Calculate size of background + Rectangle background = fm.getStringBounds(attackStyleString, graphics).getBounds(); + background.setBounds(background.x, background.y, background.width + BORDER_SIZE, background.height + BORDER_SIZE); + + // Render background + graphics.setColor(BACKGROUND_COLOR); + graphics.fillRect(anchor.x - background.width, anchor.y - background.height, background.width, background.height); + + // Render outside stroke + graphics.setColor(OUTSIDE_STROKE_COLOR); + graphics.drawRect(anchor.x - background.width, anchor.y - background.height, background.width + BORDER_SIZE / 2, background.height + BORDER_SIZE / 2); + + // Render inside stroke + graphics.setColor(INSIDE_STROKE_COLOR); + graphics.drawRect(anchor.x - background.width + BORDER_SIZE / 2, anchor.y - background.height + BORDER_SIZE / 2, background.width - BORDER_SIZE / 2, background.height - BORDER_SIZE / 2); + + // Render text with shadow + graphics.setColor(Color.BLACK); + graphics.drawString(attackStyleString, anchor.x - background.width + 3, anchor.y); + graphics.setColor(Color.WHITE); + graphics.drawString(attackStyleString, anchor.x - background.width + 2, anchor.y - 1); + + return null; + } + + private Rectangle getChatboxBounds() + { + Widget chatbox = client.getWidget(WidgetInfo.CHATBOX); + return chatbox != null ? chatbox.getBounds() : null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java new file mode 100644 index 0000000000..efb6b2ae0e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, honeyhoney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 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 OWNER 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. + */ +package net.runelite.client.plugins.attackindicator; + +import com.google.common.eventbus.Subscribe; +import com.google.inject.Binder; +import com.google.inject.Provides; +import javax.annotation.Nullable; +import javax.inject.Inject; +import net.runelite.api.Client; +import net.runelite.api.Varbits; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.events.VarbitChanged; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import static net.runelite.client.plugins.attackindicator.AttackStyle.CASTING; +import static net.runelite.client.plugins.attackindicator.AttackStyle.DEFENSIVE_CASTING; + +@PluginDescriptor( + name = "Attack indicator plugin" +) +public class AttackIndicatorPlugin extends Plugin +{ + @Inject + @Nullable + Client client; + + private int attackStyleVarbit = -1; + private int equippedWeaponTypeVarbit = -1; + private int castingModeVarbit = -1; + private AttackStyle attackStyle; + + @Inject + AttackIndicatorOverlay overlay; + + @Override + public void configure(Binder binder) + { + binder.bind(AttackIndicatorOverlay.class); + } + + @Provides + AttackIndicatorConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(AttackIndicatorConfig.class); + } + + @Override + public AttackIndicatorOverlay getOverlay() + { + return overlay; + } + + public AttackStyle getAttackStyle() + { + return attackStyle; + } + + @Subscribe + public void onAttackStyleChange(VarbitChanged event) + { + if (attackStyleVarbit == -1 || attackStyleVarbit != client.getSetting(Varbits.ATTACK_STYLE)) + { + attackStyleVarbit = client.getSetting(Varbits.ATTACK_STYLE); + updateAttackStyle(client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE), attackStyleVarbit, + client.getSetting(Varbits.DEFENSIVE_CASTING_MODE)); + } + } + + @Subscribe + public void onEquippedWeaponTypeChange(VarbitChanged event) + { + if (equippedWeaponTypeVarbit == -1 || equippedWeaponTypeVarbit != client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE)) + { + equippedWeaponTypeVarbit = client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE); + updateAttackStyle(equippedWeaponTypeVarbit, client.getSetting(Varbits.ATTACK_STYLE), + client.getSetting(Varbits.DEFENSIVE_CASTING_MODE)); + } + } + + @Subscribe + public void onCastingModeChange(VarbitChanged event) + { + if (castingModeVarbit == -1 || castingModeVarbit != client.getSetting(Varbits.DEFENSIVE_CASTING_MODE)) + { + castingModeVarbit = client.getSetting(Varbits.DEFENSIVE_CASTING_MODE); + updateAttackStyle(client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE), client.getSetting(Varbits.ATTACK_STYLE), + castingModeVarbit); + } + } + + private void updateAttackStyle(int equippedWeaponType, int attackStyleIndex, int castingMode) + { + AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponType).getAttackStyles(); + if (attackStyleIndex < attackStyles.length) + { + attackStyle = attackStyles[attackStyleIndex]; + if (attackStyle == null) + { + return; + } + if ((attackStyle == CASTING) && (castingMode == 1)) + { + attackStyle = DEFENSIVE_CASTING; + } + } + } + +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java new file mode 100644 index 0000000000..a3eaea9afa --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017, honeyhoney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 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 OWNER 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. + */ +package net.runelite.client.plugins.attackindicator; + +public enum AttackStyle +{ + ACCURATE("Accurate"), + AGGRESSIVE("Aggressive"), + DEFENSIVE("Defensive"), + CONTROLLED("Controlled"), + RANGING("Ranging"), + LONGRANGE("Longrange"), + CASTING("Casting"), + DEFENSIVE_CASTING("Defensive Casting"), + OTHER("Other"); + + private final String name; + + AttackStyle(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java new file mode 100644 index 0000000000..5283fc06cd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017, honeyhoney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 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 OWNER 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. + */ +package net.runelite.client.plugins.attackindicator; + +import java.util.HashMap; +import java.util.Map; +import static net.runelite.client.plugins.attackindicator.AttackStyle.*; + +public enum WeaponType +{ + TYPE_0(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_1(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_2(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_3(RANGING, RANGING, null, LONGRANGE), + TYPE_4(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_5(RANGING, RANGING, null, LONGRANGE), + TYPE_6(AGGRESSIVE, RANGING, DEFENSIVE_CASTING, null), + TYPE_7(RANGING, RANGING, null, DEFENSIVE_CASTING), + TYPE_8(OTHER, AGGRESSIVE, null, null), + TYPE_9(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_10(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_11(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_12(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), + TYPE_13(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_14(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_15(CONTROLLED, CONTROLLED, CONTROLLED, DEFENSIVE), + TYPE_16(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_17(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_18(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING), + TYPE_19(RANGING, RANGING, null, LONGRANGE), + TYPE_20(ACCURATE, CONTROLLED, null, LONGRANGE), + TYPE_21(ACCURATE, AGGRESSIVE, null, DEFENSIVE), + TYPE_22(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE), + TYPE_23(CASTING, CASTING, null, DEFENSIVE_CASTING), + TYPE_24(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), + TYPE_25(CONTROLLED, AGGRESSIVE, null, DEFENSIVE), + TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE), + TYPE_27(ACCURATE, null, null, OTHER); + + private static final Map weaponTypes = new HashMap<>(); + + private final AttackStyle[] attackStyles; + + static + { + for (WeaponType weaponType : values()) + { + weaponTypes.put(weaponType.ordinal(), weaponType); + } + } + + WeaponType(AttackStyle... attackStyles) + { + this.attackStyles = attackStyles; + } + + public AttackStyle[] getAttackStyles() + { + return attackStyles; + } + + public static WeaponType getWeaponType(int id) + { + return weaponTypes.get(id); + } +}