Initial Commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/bin/
|
||||
132
src/mod/sin/armoury/ArmourTweaks.java
Normal file
132
src/mod/sin/armoury/ArmourTweaks.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
342
src/mod/sin/armoury/ArmouryMod.java
Normal file
342
src/mod/sin/armoury/ArmouryMod.java
Normal 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);
|
||||
}
|
||||
}
|
||||
302
src/mod/sin/armoury/CombatTweaks.java
Normal file
302
src/mod/sin/armoury/CombatTweaks.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
94
src/mod/sin/armoury/ShieldTweaks.java
Normal file
94
src/mod/sin/armoury/ShieldTweaks.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
247
src/mod/sin/armoury/WeaponTweaks.java
Normal file
247
src/mod/sin/armoury/WeaponTweaks.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user