Initial Commit

This commit is contained in:
Sindusk
2018-03-30 17:23:56 -04:00
commit 155d28401e
6 changed files with 1118 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/bin/

View File

@@ -0,0 +1,132 @@
package mod.sin.armoury;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.server.Server;
import com.wurmonline.server.combat.Armour;
import com.wurmonline.server.combat.ArmourTypes;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.Materials;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import mod.sin.lib.Util;
public class ArmourTweaks {
public static Logger logger = Logger.getLogger(ArmourTweaks.class.getName());
public static ArmouryMod mod;
public static float newGetArmourModFor(Item armour){
int armourType;
float toReturn = 0.0f;
if (armour != null && (armourType = armour.getArmourType()) > -1) {
if(mod.armourTypeReduction.containsKey(armourType)){
toReturn = mod.armourTypeReduction.get(armourType)-mod.unarmouredReduction;
}else{
logger.severe("[ERROR]: Could not find armour reduction reference for armour type "+armourType);
toReturn = 0f;
}
if (mod.armourReductionOverride.containsKey(armour.getTemplateId())){
toReturn = mod.armourReductionOverride.get(armour.getTemplateId())-mod.unarmouredReduction;
}
if ((armourType == ArmourTypes.ARMOUR_RING || armourType == ArmourTypes.ARMOUR_CHAIN) && armour.getMaterial() == Materials.MATERIAL_STEEL){
toReturn += 0.02f;
}
if (armour.getMaterial() == Materials.MATERIAL_GLIMMERSTEEL){
toReturn += mod.glimmersteelMaterialMod;
} else if(armour.getMaterial() == Materials.MATERIAL_SERYLL) {
toReturn += mod.seryllMaterialMod;
} else if (armour.getMaterial() == Materials.MATERIAL_ADAMANTINE) {
toReturn += mod.adamantineMaterialMod;
}
toReturn *= 1.0f + Armour.getRarityArmourBonus(armour.getRarity());
toReturn = mod.unarmouredReduction + (float)((double)toReturn * Server.getBuffedQualityEffect(armour.getCurrentQualityLevel() / 100.0f));
}
return 1.0f - toReturn;
}
public static void setArmourLimitFactors(ArmouryMod mod){
try{
logger.info("Setting armour limit factors");
for(Armour armour : mod.clothArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.clothArmourLimitFactor);
}
for(Armour armour : mod.leatherArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.leatherArmourLimitFactor);
}
for(Armour armour : mod.studdedArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.studdedArmourLimitFactor);
}
for(Armour armour : mod.chainArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.chainArmourLimitFactor);
}
for(Armour armour : mod.plateArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.plateArmourLimitFactor);
}
for(Armour armour : mod.drakeArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.drakeArmourLimitFactor);
}
for(Armour armour : mod.dragonscaleArmour){
ReflectionUtil.setPrivateField(armour, ReflectionUtil.getField(armour.getClass(), "limitingFactor"), mod.dragonscaleArmourLimitFactor);
}
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void preInit(ArmouryMod mod){
ArmourTweaks.mod = mod;
try {
ClassPool classPool = HookManager.getInstance().getClassPool();
final Class<ArmourTweaks> thisClass = ArmourTweaks.class;
if(mod.enableArmourReductionModifications){
CtClass ctArmour = classPool.get("com.wurmonline.server.combat.Armour");
String body = ""
+ "{"
+ " return "+ArmourTweaks.class.getName()+".newGetArmourModFor($1);"
+ "}";
Util.setBodyDeclared(thisClass, ctArmour, "getArmourModFor", body);
/*ctArmour.getDeclaredMethod("getArmourModFor").setBody("{ "
+ "return "+ArmourTweaks.class.getName()+".newGetArmourModFor($1); }");*/
}
} catch (NotFoundException e) {
e.printStackTrace();
}
}
public static void onItemTemplatesCreated(ArmouryMod mod){
try {
if(mod.enableArmourMovementModifications){
logger.info("Starting armour movement modifications...");
for(String armourName : mod.armourMovement.keySet()){
int armourTemplate = 0;
if(mod.armourNameToItemTemplate.containsKey(armourName)){
armourTemplate = mod.armourNameToItemTemplate.get(armourName);
}else{
logger.severe("[ERROR]: Could not edit armour movement for item name \""+armourName+"\". It may be invalid.");
continue;
}
Armour armourToEdit = Armour.getArmour(armourTemplate);
if(armourToEdit != null){
float oldValue = ReflectionUtil.getPrivateField(armourToEdit, ReflectionUtil.getField(armourToEdit.getClass(), "movemodifier"));
ReflectionUtil.setPrivateField(armourToEdit, ReflectionUtil.getField(armourToEdit.getClass(), "movemodifier"), mod.armourMovement.get(armourName));
logger.info("Editing movement modifier for armour \""+armourName+"\": From "+oldValue+" to "+mod.armourMovement.get(armourName));
}else{
logger.severe("[ERROR]: Could not edit armour movement for item name \""+armourName+"\". It may be invalid.");
}
}
}
if(mod.enableCustomArmourLimitFactors){
setArmourLimitFactors(mod);
}
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,342 @@
package mod.sin.armoury;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.interfaces.Configurable;
import org.gotti.wurmunlimited.modloader.interfaces.ItemTemplatesCreatedListener;
import org.gotti.wurmunlimited.modloader.interfaces.PreInitable;
import org.gotti.wurmunlimited.modloader.interfaces.ServerStartedListener;
import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod;
import com.wurmonline.server.combat.Armour;
import com.wurmonline.server.combat.ArmourTypes;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.items.ItemTemplate;
import com.wurmonline.server.items.ItemTemplateFactory;
public class ArmouryMod
implements WurmServerMod, Configurable, PreInitable, ItemTemplatesCreatedListener, ServerStartedListener {
private Logger logger;
// Configuration options
public boolean bDebug = false;
public boolean enableNonPlayerCrits = true;
public boolean fixArmourLimitBuffBug = true;
public boolean fixArmourLimitSpellEffect = true;
// -- Armour configuration -- //
public boolean enableArmourReductionModifications = true;
public float unarmouredReduction = 0.05f;
// Armour Mapping
public String[] armourTypes = {"cloth", "leather", "studded", "chain", "plate", "drake", "dragonscale", // Worn armour pieces
"scale", "ring", "splint"}; // Used by the system but not worn by players
public HashMap<Integer, Float> armourTypeReduction = new HashMap<Integer, Float>();
public HashMap<String, Integer> armourTypeReference = new HashMap<String, Integer>();
// Armour modifiers
public float adamantineMaterialMod = 0.05f;
public float glimmersteelMaterialMod = 0.1f;
public float seryllMaterialMod = 0.1f;
// Armour limit factors
public boolean enableCustomArmourLimitFactors = true;
public float clothArmourLimitFactor = 0.3f;
public float leatherArmourLimitFactor = 0.3f;
public float studdedArmourLimitFactor = 0.0f;
public float chainArmourLimitFactor = -0.15f;
public float plateArmourLimitFactor = -0.3f;
public float drakeArmourLimitFactor = -0.3f;
public float dragonscaleArmourLimitFactor = -0.3f;
public HashMap<Integer, Float> armourReductionOverride = new HashMap<Integer, Float>();
// Armour movement
public boolean enableArmourMovementModifications = true;
public HashMap<String, Float> armourMovement = new HashMap<String, Float>();
// - Shield configuration -- //
public boolean enableShieldDamageEnchants = true;
public boolean enableShieldSpeedEnchants = true;
// -- Weapon configuration -- //
public float minimumSwingTime = 3.0f;
public boolean raresReduceSwingTime = true;
public float rareSwingSpeedReduction = 0.2f;
public boolean fixSavedSwingTimer = true;
public boolean betterDualWield = true; // HIGHLY EXPERIMENTAL
// Weapon variable changes
public HashMap<Integer, Float> weaponDamage = new HashMap<Integer, Float>();
public HashMap<Integer, Float> weaponSpeed = new HashMap<Integer, Float>();
public HashMap<Integer, Float> weaponCritChance = new HashMap<Integer, Float>();
public HashMap<Integer, Integer> weaponReach = new HashMap<Integer, Integer>();
public HashMap<Integer, Integer> weaponWeightGroup = new HashMap<Integer, Integer>();
public HashMap<Integer, Float> weaponParryPercent = new HashMap<Integer, Float>();
public HashMap<Integer, Double> weaponSkillPenalty = new HashMap<Integer, Double>();
public ArmouryMod(){
this.logger = Logger.getLogger(this.getClass().getName());
}
@Override
public void configure(Properties properties) {
this.logger.info("Beginning configuration... [Testing]");
// Base configuration options
this.bDebug = Boolean.parseBoolean(properties.getProperty("debug", Boolean.toString(this.bDebug)));
this.enableNonPlayerCrits = Boolean.parseBoolean(properties.getProperty("enableNonPlayerCrits", Boolean.toString(this.enableNonPlayerCrits)));
this.fixArmourLimitBuffBug = Boolean.parseBoolean(properties.getProperty("fixArmourLimitBuffBug", Boolean.toString(this.fixArmourLimitBuffBug)));
this.fixArmourLimitSpellEffect = Boolean.parseBoolean(properties.getProperty("fixArmourLimitSpellEffect", Boolean.toString(this.fixArmourLimitSpellEffect)));
// Armour configuration
this.initArmourDefaults(); // Create references for use soon.
this.enableArmourReductionModifications = Boolean.parseBoolean(properties.getProperty("enableArmourReductionModifications", Boolean.toString(this.enableArmourReductionModifications)));
if(enableArmourReductionModifications){
this.unarmouredReduction = Float.parseFloat(properties.getProperty("unarmouredReduction", Float.toString(this.unarmouredReduction)));
for(String armourType : armourTypes){
int armourNum = armourTypeReference.get(armourType);
float defaultVal = armourTypeReduction.get(armourNum);
armourTypeReduction.put(armourNum, Float.parseFloat(properties.getProperty(armourType+"Reduction", Float.toString(defaultVal))));
if(armourTypeReduction.get(armourNum) <= 0f){
this.logger.warning("[ERROR]: Armour type \""+armourType+"\" not set properly the Armour Reduction configuration in armoury.properties! It will not reduce damage at all until resolved!");
}
}
}
this.adamantineMaterialMod = Float.parseFloat(properties.getProperty("adamantineMaterialMod", Float.toString(this.adamantineMaterialMod)));
this.glimmersteelMaterialMod = Float.parseFloat(properties.getProperty("glimmersteelMaterialMod", Float.toString(this.glimmersteelMaterialMod)));
this.seryllMaterialMod = Float.parseFloat(properties.getProperty("seryllMaterialMod", Float.toString(this.seryllMaterialMod)));
// Armour limit factors
this.enableCustomArmourLimitFactors = Boolean.parseBoolean(properties.getProperty("enableCustomArmourLimitFactors", Boolean.toString(this.enableCustomArmourLimitFactors)));
this.clothArmourLimitFactor = Float.parseFloat(properties.getProperty("clothArmourLimitFactor", Float.toString(this.clothArmourLimitFactor)));
this.leatherArmourLimitFactor = Float.parseFloat(properties.getProperty("leatherArmourLimitFactor", Float.toString(this.leatherArmourLimitFactor)));
this.studdedArmourLimitFactor = Float.parseFloat(properties.getProperty("studdedArmourLimitFactor", Float.toString(this.studdedArmourLimitFactor)));
this.chainArmourLimitFactor = Float.parseFloat(properties.getProperty("chainArmourLimitFactor", Float.toString(this.chainArmourLimitFactor)));
this.plateArmourLimitFactor = Float.parseFloat(properties.getProperty("plateArmourLimitFactor", Float.toString(this.plateArmourLimitFactor)));
this.drakeArmourLimitFactor = Float.parseFloat(properties.getProperty("drakeArmourLimitFactor", Float.toString(this.drakeArmourLimitFactor)));
this.dragonscaleArmourLimitFactor = Float.parseFloat(properties.getProperty("dragonscaleArmourLimitFactor", Float.toString(this.dragonscaleArmourLimitFactor)));
// Armour movement modifiers
this.enableArmourMovementModifications = Boolean.parseBoolean(properties.getProperty("enableArmourMovementModifications", Boolean.toString(this.enableArmourMovementModifications)));
// Shield configuration
this.enableShieldDamageEnchants = Boolean.parseBoolean(properties.getProperty("enableShieldDamageEnchants", Boolean.toString(this.enableShieldDamageEnchants)));
// Weapon configuration
this.minimumSwingTime = Float.parseFloat(properties.getProperty("minimumSwingTime", Float.toString(this.minimumSwingTime)));
this.raresReduceSwingTime = Boolean.parseBoolean(properties.getProperty("raresReduceSwingTime", Boolean.toString(this.raresReduceSwingTime)));
this.rareSwingSpeedReduction = Float.parseFloat(properties.getProperty("rareSwingSpeedReduction", Float.toString(this.rareSwingSpeedReduction)));
this.fixSavedSwingTimer = Boolean.parseBoolean(properties.getProperty("fixSavedSwingTimer", Boolean.toString(this.fixSavedSwingTimer)));
this.betterDualWield = Boolean.parseBoolean(properties.getProperty("betterDualWield", Boolean.toString(this.betterDualWield)));
for (String name : properties.stringPropertyNames()) {
try {
String value = properties.getProperty(name);
switch (name) {
case "debug":
case "classname":
case "classpath":
case "sharedClassLoader":
break; //ignore
default:
if (name.startsWith("armourMovement")) {
String[] split = value.split(",");
String armourName = split[0];
float newVal = Float.parseFloat(split[1]);
armourMovement.put(armourName, newVal);
} else if (name.startsWith("armourReductionOverride")) {
String[] split = value.split(",");
int armourId = Integer.parseInt(split[0]);
float reductionValue = Float.parseFloat(split[1]);
armourReductionOverride.put(armourId, reductionValue);
} else if (name.startsWith("weaponDamage")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
float newVal = Float.parseFloat(split[1]);
weaponDamage.put(weaponId, newVal);
} else if (name.startsWith("weaponSpeed")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
float newVal = Float.parseFloat(split[1]);
weaponSpeed.put(weaponId, newVal);
} else if (name.startsWith("weaponCritChance")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
float newVal = Float.parseFloat(split[1]);
weaponCritChance.put(weaponId, newVal);
} else if (name.startsWith("weaponReach")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
int newVal = Integer.parseInt(split[1]);
weaponReach.put(weaponId, newVal);
} else if (name.startsWith("weaponWeightGroup")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
int newVal = Integer.parseInt(split[1]);
weaponWeightGroup.put(weaponId, newVal);
} else if (name.startsWith("weaponParryPercent")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
float newVal = Float.parseFloat(split[1]);
weaponParryPercent.put(weaponId, newVal);
} else if (name.startsWith("weaponSkillPenalty")) {
String[] split = value.split(",");
int weaponId = Integer.parseInt(split[0]);
double newVal = Double.parseDouble(split[1]);
weaponSkillPenalty.put(weaponId, newVal);
} else {
//Debug("Unknown config property: " + name);
}
}
} catch (Exception e) {
Debug("Error processing property " + name);
e.printStackTrace();
}
}
// Print values of mod configuration
this.logger.info(" -- Mod Configuration -- ");
this.logger.log(Level.INFO, "enableNonPlayerCrits: " + this.enableNonPlayerCrits);
this.logger.log(Level.INFO, "fixArmourLimitBuffBug: " + this.fixArmourLimitBuffBug);
this.logger.log(Level.INFO, "fixArmourLimitSpellEffect: " + this.fixArmourLimitSpellEffect);
this.logger.info(" -- Armour Configuration -- ");
this.logger.log(Level.INFO, "enableArmourReductionModifications: " + this.enableArmourReductionModifications);
if(enableArmourReductionModifications){
this.logger.log(Level.INFO, "unarmouredReduction: " + this.unarmouredReduction);
this.logger.info("> Armour Reduction Settings <");
for(String armourType : armourTypeReference.keySet()){
this.logger.info(armourType+" - "+((int)(armourTypeReduction.get(armourTypeReference.get(armourType))*100))+"%");
}
}
this.logger.log(Level.INFO, "adamantineMaterialMod: " + this.adamantineMaterialMod);
this.logger.log(Level.INFO, "glimmersteelMaterialMod: " + this.glimmersteelMaterialMod);
this.logger.log(Level.INFO, "seryllMaterialMod: " + this.seryllMaterialMod);
this.logger.log(Level.INFO, "enableCustomArmourLimitFactors: " + this.enableCustomArmourLimitFactors);
if(enableCustomArmourLimitFactors){
this.logger.log(Level.INFO, "clothArmourLimitFactor: " + this.clothArmourLimitFactor);
this.logger.log(Level.INFO, "leatherArmourLimitFactor: " + this.leatherArmourLimitFactor);
this.logger.log(Level.INFO, "studdedArmourLimitFactor: " + this.studdedArmourLimitFactor);
this.logger.log(Level.INFO, "chainArmourLimitFactor: " + this.chainArmourLimitFactor);
this.logger.log(Level.INFO, "plateArmourLimitFactor: " + this.plateArmourLimitFactor);
this.logger.log(Level.INFO, "drakeArmourLimitFactor: " + this.drakeArmourLimitFactor);
this.logger.log(Level.INFO, "dragonscaleArmourLimitFactor: " + this.dragonscaleArmourLimitFactor);
}
this.logger.info(" -- Shield Configuration -- ");
this.logger.log(Level.INFO, "enableShieldDamageEnchants: " + this.enableShieldDamageEnchants);
this.logger.info(" -- Weapon Configuration -- ");
this.logger.log(Level.INFO, "minimumSwingTime: " + this.minimumSwingTime);
this.logger.log(Level.INFO, "raresReduceSwingTime: " + this.raresReduceSwingTime);
this.logger.log(Level.INFO, "rareSwingSpeedReduction: " + this.rareSwingSpeedReduction);
this.logger.log(Level.INFO, "fixSavedSwingTimer: " + this.fixSavedSwingTimer);
this.logger.log(Level.INFO, "betterDualWield: " + this.betterDualWield);
this.Debug("Debugging messages are enabled.");
this.logger.info(" -- Configuration complete -- ");
}
protected void Debug(String x) {
if (this.bDebug) {
System.out.println(String.valueOf(this.getClass().getSimpleName()) + ": " + x);
System.out.flush();
this.logger.log(Level.INFO, x);
}
}
@Override
public void preInit(){
CombatTweaks.preInit(this);
ArmourTweaks.preInit(this);
ShieldTweaks.preInit(this);
}
@Override
public void onItemTemplatesCreated(){
logger.info("Creating armour template lists...");
createArmourTemplateLists();
ArmourTweaks.onItemTemplatesCreated(this);
}
@Override
public void onServerStarted(){
WeaponTweaks.onServerStarted(this);
}
public HashMap<String, Integer> armourNameToItemTemplate = new HashMap<String, Integer>();
public ArrayList<Armour> clothArmour = new ArrayList<Armour>();
public ArrayList<Armour> leatherArmour = new ArrayList<Armour>();
public ArrayList<Armour> studdedArmour = new ArrayList<Armour>();
public ArrayList<Armour> chainArmour = new ArrayList<Armour>();
public ArrayList<Armour> plateArmour = new ArrayList<Armour>();
public ArrayList<Armour> drakeArmour = new ArrayList<Armour>();
public ArrayList<Armour> dragonscaleArmour = new ArrayList<Armour>();
private void addArmour(ArrayList<Armour> typeList, int itemTemplate){
ItemTemplate it = ItemTemplateFactory.getInstance().getTemplateOrNull(itemTemplate);
if(it != null){
armourNameToItemTemplate.put(it.getName(), itemTemplate);
}
typeList.add(Armour.getArmour(itemTemplate));
}
public void createArmourTemplateLists(){
addArmour(clothArmour, ItemList.clothHood);
addArmour(clothArmour, ItemList.clothSleeve);
addArmour(clothArmour, ItemList.clothJacket);
addArmour(clothArmour, ItemList.clothShirt);
addArmour(clothArmour, ItemList.clothGlove);
addArmour(clothArmour, ItemList.clothHose);
addArmour(clothArmour, ItemList.clothShoes);
addArmour(leatherArmour, ItemList.leatherHat0);
addArmour(leatherArmour, ItemList.leatherCap);
addArmour(leatherArmour, ItemList.leatherSleeve);
addArmour(leatherArmour, ItemList.leatherJacket);
addArmour(leatherArmour, ItemList.leatherGlove);
addArmour(leatherArmour, ItemList.leatherHose);
addArmour(leatherArmour, ItemList.leatherBoot);
addArmour(studdedArmour, ItemList.studdedLeatherCap);
addArmour(studdedArmour, ItemList.studdedLeatherSleeve);
addArmour(studdedArmour, ItemList.studdedLeatherJacket);
addArmour(studdedArmour, ItemList.studdedLeatherGlove);
addArmour(studdedArmour, ItemList.studdedLeatherHose);
addArmour(studdedArmour, ItemList.studdedLeatherBoot);
addArmour(chainArmour, ItemList.chainCoif);
addArmour(chainArmour, ItemList.chainSleeve);
addArmour(chainArmour, ItemList.chainJacket);
addArmour(chainArmour, ItemList.chainGlove);
addArmour(chainArmour, ItemList.chainHose);
addArmour(chainArmour, ItemList.chainBoot);
addArmour(plateArmour, ItemList.helmetGreat);
addArmour(plateArmour, ItemList.helmetBasinet);
addArmour(plateArmour, ItemList.helmetOpen);
addArmour(plateArmour, ItemList.plateSleeve);
addArmour(plateArmour, ItemList.plateJacket);
addArmour(plateArmour, ItemList.plateGauntlet);
addArmour(plateArmour, ItemList.plateHose);
addArmour(plateArmour, ItemList.plateBoot);
addArmour(drakeArmour, ItemList.dragonLeatherCap);
addArmour(drakeArmour, ItemList.dragonLeatherSleeve);
addArmour(drakeArmour, ItemList.dragonLeatherJacket);
addArmour(drakeArmour, ItemList.dragonLeatherGlove);
addArmour(drakeArmour, ItemList.dragonLeatherHose);
addArmour(drakeArmour, ItemList.dragonLeatherBoot);
addArmour(dragonscaleArmour, ItemList.dragonScaleSleeve);
addArmour(dragonscaleArmour, ItemList.dragonScaleJacket);
addArmour(dragonscaleArmour, ItemList.dragonScaleGauntlet);
addArmour(dragonscaleArmour, ItemList.dragonScaleHose);
addArmour(dragonscaleArmour, ItemList.dragonScaleBoot);
}
private void initArmourDefaults(){
armourTypeReference.put("cloth", ArmourTypes.ARMOUR_CLOTH);
armourTypeReduction.put(ArmourTypes.ARMOUR_CLOTH, 0.4f);
armourTypeReference.put("leather", ArmourTypes.ARMOUR_LEATHER);
armourTypeReduction.put(ArmourTypes.ARMOUR_LEATHER, 0.5f);
armourTypeReference.put("studded", ArmourTypes.ARMOUR_STUDDED);
armourTypeReduction.put(ArmourTypes.ARMOUR_STUDDED, 0.55f);
armourTypeReference.put("chain", ArmourTypes.ARMOUR_CHAIN);
armourTypeReduction.put(ArmourTypes.ARMOUR_CHAIN, 0.6f);
armourTypeReference.put("plate", ArmourTypes.ARMOUR_PLATE);
armourTypeReduction.put(ArmourTypes.ARMOUR_PLATE, 0.7f);
armourTypeReference.put("drake", ArmourTypes.ARMOUR_LEATHER_DRAGON);
armourTypeReduction.put(ArmourTypes.ARMOUR_LEATHER_DRAGON, 0.7f);
armourTypeReference.put("dragonscale", ArmourTypes.ARMOUR_SCALE_DRAGON);
armourTypeReduction.put(ArmourTypes.ARMOUR_SCALE_DRAGON, 0.75f);
armourTypeReference.put("scale", ArmourTypes.ARMOUR_SCALE);
armourTypeReduction.put(ArmourTypes.ARMOUR_SCALE, 0.5f);
armourTypeReference.put("ring", ArmourTypes.ARMOUR_RING);
armourTypeReduction.put(ArmourTypes.ARMOUR_RING, 0.55f);
armourTypeReference.put("splint", ArmourTypes.ARMOUR_SPLINT);
armourTypeReduction.put(ArmourTypes.ARMOUR_SPLINT, 0.6f);
}
}

View File

@@ -0,0 +1,302 @@
package mod.sin.armoury;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.CombatHandler;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.SpellEffectsEnum;
import com.wurmonline.server.items.Item;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtPrimitiveType;
import javassist.NotFoundException;
import javassist.bytecode.Descriptor;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import mod.sin.lib.Util;
public class CombatTweaks {
public static Item handleDualWieldAttack(CombatHandler handler, Creature opponent, float delta){
try {
Creature performer = ReflectionUtil.getPrivateField(handler, ReflectionUtil.getField(handler.getClass(), "creature"));
for(Item weapon : performer.getSecondaryWeapons()){
if(Server.rand.nextBoolean()) continue;
float time = handler.getSpeed(weapon);
float timer = performer.addToWeaponUsed(weapon, delta);
if(timer > time){
performer.deductFromWeaponUsed(weapon, time);
return weapon;
}
}
return null;
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
return null;
}
}
public static void preInit(ArmouryMod mod){
try {
ClassPool classPool = HookManager.getInstance().getClassPool();
Class<CombatTweaks> thisClass = CombatTweaks.class;
// - Allow critical hits on creatures as well as players -
mod.enableNonPlayerCrits = false; // Disabled for now as it's not working.
if(mod.enableNonPlayerCrits){
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
CtClass[] attackParams1 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
classPool.get("com.wurmonline.server.items.Item"),
CtPrimitiveType.booleanType
};
String desc = Descriptor.ofMethod(CtPrimitiveType.booleanType, attackParams1);
Util.setReason("Enable player critical strikes on creatures.");
Util.instrumentDescribed(thisClass, ctCombatHandler, "attack", desc, "isPlayer", "$_ = true");
/*ctCombatHandler.getMethod("attack", Descriptor.ofMethod(CtPrimitiveType.booleanType, attackParams1)).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isPlayer")) {
m.replace("$_ = true;");
return;
}
}
});*/
CtClass[] attackParams2 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
classPool.get("com.wurmonline.server.creatures.AttackAction")
};
desc = Descriptor.ofMethod(CtPrimitiveType.booleanType, attackParams2);
Util.setReason("Enable player critical strikes on creatures.");
Util.instrumentDescribed(thisClass, ctCombatHandler, "attack", desc, "isPlayer", "$_ = true");
/*ctCombatHandler.getMethod("attack", Descriptor.ofMethod(CtPrimitiveType.booleanType, attackParams2)).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isPlayer")) {
m.replace("$_ = true;");
return;
}
}
});*/
}
// - Fix the Armour Limit being shown in the buff bar at all times -
if(mod.fixArmourLimitBuffBug){
CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo");
String replace = ""
+ "communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_NONE);"
+ "communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_MEDIUM);"
+ "communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_HEAVY);"
+ "$_ = $proceed($$);";
Util.setReason("Fix armour limit buff bug.");
Util.instrumentDeclared(thisClass, ctPlayerInfo, "setArmourLimitingFactor", "sendRemoveSpellEffect", replace);
/*ctPlayerInfo.getDeclaredMethod("setArmourLimitingFactor").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("sendRemoveSpellEffect")) {
m.replace("communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_NONE);"
+ "communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_MEDIUM);"
+ "communicator.sendRemoveSpellEffect(com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_HEAVY);"
+ "$_ = $proceed($$);");
return;
}
}
});*/
replace = "if($1 == null){"
+ " $1 = com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_NONE;"
+ "}"
+ "$_ = $proceed($$);"
+ "communicator.sendAddSpellEffect($1, 100000, this.limitingArmourFactor*100.0f);";
Util.setReason("Fix armour limit buff bug.");
Util.instrumentDeclared(thisClass, ctPlayerInfo, "setArmourLimitingFactor", "sendAddStatusEffect", replace);
ctPlayerInfo.getDeclaredMethod("setArmourLimitingFactor").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("sendAddStatusEffect")) {
m.replace("if($1 == null){"
+ " $1 = com.wurmonline.server.creatures.SpellEffectsEnum.ARMOUR_LIMIT_NONE;"
+ "}"
+ "$_ = $proceed($$);"
+ "communicator.sendAddSpellEffect($1, 100000, this.limitingArmourFactor*100.0f);");
return;
}
}
});
}
// - Make spell effects hud show your armour limit properly - //
if(mod.fixArmourLimitSpellEffect){
ReflectionUtil.setPrivateField(SpellEffectsEnum.ARMOUR_LIMIT_HEAVY, ReflectionUtil.getField(SpellEffectsEnum.ARMOUR_LIMIT_HEAVY.getClass(), "name"), "Armour Penalty");
ReflectionUtil.setPrivateField(SpellEffectsEnum.ARMOUR_LIMIT_MEDIUM, ReflectionUtil.getField(SpellEffectsEnum.ARMOUR_LIMIT_MEDIUM.getClass(), "name"), "Armour Penalty");
ReflectionUtil.setPrivateField(SpellEffectsEnum.ARMOUR_LIMIT_LIGHT, ReflectionUtil.getField(SpellEffectsEnum.ARMOUR_LIMIT_LIGHT.getClass(), "name"), "Armour Bonus");
ReflectionUtil.setPrivateField(SpellEffectsEnum.ARMOUR_LIMIT_NONE, ReflectionUtil.getField(SpellEffectsEnum.ARMOUR_LIMIT_NONE.getClass(), "name"), "Armour Bonus");
}
// - Change the minimum swing timer - //
if(mod.minimumSwingTime != 3.0f){
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
String strBuilder = "";
if(mod.raresReduceSwingTime){
strBuilder += ""
+ "if(weapon.getRarity() > 0){"
+ " calcspeed -= weapon.getRarity()*"+String.valueOf(mod.rareSwingSpeedReduction)+"f;"
+ "}";
}
strBuilder += "$_ = $proceed("+String.valueOf(mod.minimumSwingTime)+"f, $2);";
final String stringReplace = strBuilder;
CtClass[] params1 = {
classPool.get("com.wurmonline.server.creatures.AttackAction"),
classPool.get("com.wurmonline.server.items.Item")
};
String desc = Descriptor.ofMethod(CtClass.floatType, params1);
Util.setReason("Adjust swing timer.");
Util.instrumentDescribed(thisClass, ctCombatHandler, "getSpeed", desc, "max", stringReplace);
/*ctCombatHandler.getMethod("getSpeed", desc).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("max")) {
m.replace(stringReplace);
return;
}
}
});*/
CtClass[] params2 = { classPool.get("com.wurmonline.server.items.Item") };
desc = Descriptor.ofMethod(CtClass.floatType, params2);
Util.setReason("Adjust swing timer.");
Util.instrumentDescribed(thisClass, ctCombatHandler, "getSpeed", desc, "max", stringReplace);
/*ctCombatHandler.getMethod("getSpeed", desc).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("max")) {
m.replace(stringReplace);
return;
}
}
});*/
}
// - Saved swing timer fix -
if(mod.fixSavedSwingTimer){
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
String replace = "$_ = $proceed($1, new Float(0f));";
Util.setReason("Fix saved swing timer.");
Util.instrumentDeclared(thisClass, ctCreature, "deductFromWeaponUsed", "put", replace);
/*ctCreature.getDeclaredMethod("deductFromWeaponUsed").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("put")) {
m.replace("$_ = $proceed($1, new Float(0f));");
return;
}
}
});*/
}
// - Attempt for a better dual wield system -
// This really doesn't work. I don't get dual wield and why it's so bad.
if(mod.betterDualWield){
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
CtClass[] params1 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
CtClass.intType,
CtClass.booleanType,
CtClass.floatType,
classPool.get("com.wurmonline.server.behaviours.Action")
};
String desc = Descriptor.ofMethod(CtClass.booleanType, params1);
String replace = "if(this.creature.isPlayer()){"
+ " com.wurmonline.server.items.Item weapon = mod.sin.armoury.CombatTweaks.handleDualWieldAttack(this, opponent, delta);"
+ " if(weapon != null){"
+ " lDead = attack(opponent, weapon, true);"
+ " }"
+ "}"
+ "$_ = $proceed($$);";
Util.setReason("Better Dual Wield");
Util.instrumentDescribed(thisClass, ctCombatHandler, "attack", desc, "getSecondaryWeapons", replace);
/*ctCombatHandler.getMethod("attack", desc).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("getSecondaryWeapons")) {
m.replace("if(this.creature.isPlayer()){"
+ " com.wurmonline.server.items.Item weapon = mod.sin.armoury.CombatTweaks.handleDualWieldAttack(this, opponent, delta);"
+ " if(weapon != null){"
+ " lDead = attack(opponent, weapon, true);"
+ " }"
+ "}"
+ "$_ = $proceed($$);");
return;
}
}
});*/
/*ctCombatHandler.getMethod("attack", desc).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("nextBoolean")) {
m.replace("$_ = true;");
return;
}
}
});*/
replace = "if(this.creature.isPlayer()){"
+ " $_ = 1;"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}";
Util.setReason("Better Dual Wield");
Util.instrumentDescribed(thisClass, ctCombatHandler, "attack", desc, "getHugeMoveCounter", replace);
/*ctCombatHandler.getMethod("attack", desc).instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("getHugeMoveCounter")) {
m.replace("if(this.creature.isPlayer()){"
+ " $_ = 1;"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}");
return;
}
}
});*/
}
/*CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
ctCreature.getDeclaredMethod("addToWeaponUsed").insertBefore("logger.info(\"Timer for \"+$1.getName()+\" = \"+this.weaponsUsed.get($1));");
// Conclusion: This is the "main loop" for combat. It is called very frequently.
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
CtClass[] params1 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
CtClass.intType,
CtClass.booleanType,
CtClass.floatType,
classPool.get("com.wurmonline.server.behaviours.Action")
};
String desc = Descriptor.ofMethod(CtClass.booleanType, params1);
CtMethod ctAttack = ctCombatHandler.getMethod("attack", desc);
//ctAttack.insertBefore("logger.info(\"Calling attack(Creature, int, boolean, float, Action)\");");
ctAttack.instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("deductFromWeaponUsed")) {
m.replace("logger.info(\"Deducting from weapon: \"+$2);"
+ "$_ = $proceed($$);");
return;
}
}
});*/
// Conclusion: This apparently is not used in standard combat.
/*CtClass[] params2 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
classPool.get("com.wurmonline.server.creatures.AttackAction")
};
desc = Descriptor.ofMethod(CtClass.booleanType, params2);
ctCombatHandler.getMethod("attack", desc).insertBefore("logger.info(\"Calling attack(Creature, AttackAction)\");");*/
// Conclusion: This is called only when a swing is done.
/*CtClass[] params3 = {
classPool.get("com.wurmonline.server.creatures.Creature"),
classPool.get("com.wurmonline.server.items.Item"),
CtClass.booleanType
};
desc = Descriptor.ofMethod(CtClass.booleanType, params3);
ctCombatHandler.getMethod("attack", desc).insertBefore("logger.info(\"Calling attack(Creature, Item, boolean)\");");*/
} catch (CannotCompileException | NotFoundException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,94 @@
package mod.sin.armoury;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.server.Server;
import com.wurmonline.server.bodys.Wound;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.sounds.SoundPlayer;
import com.wurmonline.shared.constants.Enchants;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import mod.sin.lib.Util;
public class ShieldTweaks {
public static Logger logger = Logger.getLogger(ShieldTweaks.class.getName());
public static boolean checkShieldSpeed(Item shield){
if(shield != null && shield.getSpellSpeedBonus() > Server.rand.nextInt(500)){
return true;
}
return false;
}
public static void doSharedPain(Creature attacker, Creature defender, Item shield){
if(shield.getSpellPainShare() > 0f){
float powerReq = Server.rand.nextInt(300);
if(!(powerReq < shield.getSpellPainShare())){
return;
}
boolean playSound = false;
if(shield.getBonusForSpellEffect(Enchants.BUFF_ROTTING_TOUCH) > 0f){
double damage = shield.getBonusForSpellEffect(Enchants.BUFF_ROTTING_TOUCH)*31d;
attacker.addWoundOfType(defender, Wound.TYPE_INFECTION, 0, true, 1.0f, true, damage);
playSound = true;
}else if(shield.getBonusForSpellEffect(Enchants.BUFF_FLAMING_AURA) > 0f){
double damage = shield.getBonusForSpellEffect(Enchants.BUFF_FLAMING_AURA)*27d;
attacker.addWoundOfType(defender, Wound.TYPE_BURN, 0, true, 1.0f, true, damage);
playSound = true;
}else if(shield.getBonusForSpellEffect(Enchants.BUFF_FROSTBRAND) > 0f){
double damage = shield.getBonusForSpellEffect(Enchants.BUFF_FROSTBRAND)*28d;
attacker.addWoundOfType(defender, Wound.TYPE_COLD, 0, true, 1.0f, true, damage);
playSound = true;
}else if(shield.getBonusForSpellEffect(Enchants.BUFF_VENOM) > 0f){
double damage = shield.getBonusForSpellEffect(Enchants.BUFF_VENOM)*30d;
attacker.addWoundOfType(defender, Wound.TYPE_POISON, 0, true, 1.0f, true, damage);
playSound = true;
}
if(playSound){
SoundPlayer.playSound(attacker.getTemplate().getHitSound(attacker.getSex()), attacker.getTileX(), attacker.getTileY(), true, 0.3f);
}
}
}
public static void preInit(ArmouryMod mod){
try {
ClassPool classPool = HookManager.getInstance().getClassPool();
Class<ShieldTweaks> thisClass = ShieldTweaks.class;
if(mod.enableShieldDamageEnchants){
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
String replace = ShieldTweaks.class.getName()+".doSharedPain(this.creature, defender, defShield);"
+ "$_ = $proceed($$);";
Util.setReason("Enable shield damage enchants.");
Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "setDamage", replace);
/*ctCombatHandler.getDeclaredMethod("checkShield").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("setDamage")) {
m.replace(ShieldTweaks.class.getName()+".doSharedPain(this.creature, defender, defShield);"
+ "$_ = $proceed($$);");
return;
}
}
});*/
}
if(mod.enableShieldSpeedEnchants){
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
String insert = "if("+ShieldTweaks.class.getName()+".checkShieldSpeed(defender.getShield())){"
+ " defender.getCombatHandler().usedShieldThisRound--;"
+ "}";
Util.setReason("Enable shield speed enchants.");
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "checkShield", insert);
/*ctCombatHandler.getDeclaredMethod("checkShield").insertBefore(""
+ "if("+ShieldTweaks.class.getName()+".checkShieldSpeed(defender.getShield())){"
+ " defender.getCombatHandler().usedShieldThisRound--;"
+ "}");*/
}
}catch (NotFoundException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,247 @@
package mod.sin.armoury;
import java.util.Map;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import com.wurmonline.server.combat.Weapon;
import com.wurmonline.server.items.ItemTemplate;
import com.wurmonline.server.items.ItemTemplateFactory;
public class WeaponTweaks {
public static Logger logger = Logger.getLogger(WeaponTweaks.class.getName());
public static Map<Integer, Weapon> weapons;
public static void printWeapons(){
try{
for(int i : weapons.keySet()){
Weapon cw = weapons.get(i);
ItemTemplate wt = ItemTemplateFactory.getInstance().getTemplateOrNull(i);
if(wt == null){
logger.warning("Null weapon template for id "+i);
}else{
logger.info("Weapon \""+wt.sizeString+wt.getName()+"\" (ID "+i+") stats: ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "damage"))+" damage], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "speed"))+" speed], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "critchance"))+" critchance], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "reach"))+" reach], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "weightGroup"))+" weightGroup], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "parryPercent"))+" parryPercent], ["+
ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "skillPenalty"))+" skillPenalty]"
);
}
}
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void editWeaponStats(ArmouryMod mod){
try {
Weapon cw;
ItemTemplate it;
String tweakType = "";
if(mod.weaponDamage.keySet() != null){
tweakType = "damage";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponDamage.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
float oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "damage"));
float newValue = mod.weaponDamage.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting damage on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "damage"), newValue);
}
}
if(mod.weaponSpeed.keySet() != null){
tweakType = "speed";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponSpeed.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
float oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "speed"));
float newValue = mod.weaponSpeed.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting speed on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "speed"), newValue);
}
}
if(mod.weaponCritChance.keySet() != null){
tweakType = "crit chance";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponCritChance.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
float oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "critchance"));
float newValue = mod.weaponCritChance.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting crit chance on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "critchance"), newValue);
}
}
if(mod.weaponReach.keySet() != null){
tweakType = "reach";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponReach.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
int oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "reach"));
int newValue = mod.weaponReach.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting reach on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "reach"), newValue);
}
}
if(mod.weaponWeightGroup.keySet() != null){
tweakType = "weight group";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponWeightGroup.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
int oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "weightGroup"));
int newValue = mod.weaponWeightGroup.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting weight group on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "weightGroup"), newValue);
}
}
if(mod.weaponParryPercent.keySet() != null){
tweakType = "parry percent";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponParryPercent.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
float oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "parryPercent"));
float newValue = mod.weaponParryPercent.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting parry percent on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "parryPercent"), newValue);
}
}
if(mod.weaponSkillPenalty.keySet() != null){
tweakType = "skill penalty";
logger.info("Beginning weapon "+tweakType+" tweaks...");
for(int id : mod.weaponSkillPenalty.keySet()){
it = ItemTemplateFactory.getInstance().getTemplateOrNull(id);
if(it == null){
logger.severe("[ERROR]: Item template for id "+id+" in weapon "+tweakType+" configuration is invalid. Please double check your configuration.");
continue;
}
cw = weapons.get(id);
if(cw == null){
logger.severe("[ERROR]: Weapon for id "+id+" in the weapon "+tweakType+" configuration is invalid.");
continue;
}
double oldValue = ReflectionUtil.getPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "skillPenalty"));
double newValue = mod.weaponSkillPenalty.get(id);
String diff = "";
if(newValue > oldValue){
diff = "+"+(newValue-oldValue);
}else{
diff = String.valueOf(newValue-oldValue);
}
logger.info("Setting skill penalty on "+it.sizeString+it.getName()+" to "+newValue+" from "+oldValue+" ("+diff+")");
ReflectionUtil.setPrivateField(cw, ReflectionUtil.getField(cw.getClass(), "skillPenalty"), newValue);
}
}
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void onServerStarted(ArmouryMod mod){
try {
logger.info("Beginning WeaponTweaks initialization...");
weapons = ReflectionUtil.getPrivateField(Weapon.class, ReflectionUtil.getField(Weapon.class, "weapons"));
//printWeapons(); // For debugging/information purposes
editWeaponStats(mod);
//printWeapons(); // For debugging/information purposes
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}