Update to latest version.
This commit is contained in:
@@ -1,25 +1,43 @@
|
||||
package mod.sin.wyvern;
|
||||
|
||||
import com.wurmonline.server.Server;
|
||||
import com.wurmonline.server.bodys.Wound;
|
||||
import com.wurmonline.server.bodys.Wounds;
|
||||
import com.wurmonline.server.creatures.Creature;
|
||||
import com.wurmonline.server.creatures.Creatures;
|
||||
import com.wurmonline.server.items.Item;
|
||||
import com.wurmonline.server.players.Player;
|
||||
import javassist.CannotCompileException;
|
||||
import com.wurmonline.shared.constants.Enchants;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.Descriptor;
|
||||
import javassist.bytecode.*;
|
||||
import mod.sin.lib.Util;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class CombatChanges {
|
||||
public static Logger logger = Logger.getLogger(CombatChanges.class.getName());
|
||||
|
||||
public static int getWeaponType(Item weapon){
|
||||
if(weapon.enchantment == Enchants.ACID_DAM){
|
||||
return Wound.TYPE_ACID;
|
||||
}else if(weapon.enchantment == Enchants.FROST_DAM){
|
||||
return Wound.TYPE_COLD;
|
||||
}else if(weapon.enchantment == Enchants.FIRE_DAM){
|
||||
return Wound.TYPE_BURN;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static float combatRatingAdditive(float combatRating, Creature cret, Creature opponent){
|
||||
//logger.info("Checking additive ("+cret.getName()+" vs "+opponent.getName()+"), combatRating = "+combatRating);
|
||||
float add = 0.0f;
|
||||
if((cret != null && !cret.isPlayer()) || (opponent != null && !opponent.isPlayer())){
|
||||
if(cret != null && cret.isPlayer() && (opponent != null && !opponent.isPlayer())){
|
||||
if(cret.isRoyalExecutioner()){
|
||||
add += 2.0f;
|
||||
}
|
||||
@@ -29,9 +47,9 @@ public class CombatChanges {
|
||||
public static float combatRatingMultiplicative(float combatRating, Creature cret, Creature opponent){
|
||||
//logger.info("Checking mult ("+cret.getName()+" vs "+opponent.getName()+"), combatRating = "+combatRating);
|
||||
float mult = 1.0f;
|
||||
if(cret != null && cret.isDominated()){
|
||||
if(cret != null){
|
||||
//logger.info("Cret is a pet.");
|
||||
if(cret.getDominator() != null) {
|
||||
if(cret.isDominated() && cret.getDominator() != null) {
|
||||
if (cret.getDominator() instanceof Player) {
|
||||
Player owner = (Player) cret.getDominator();
|
||||
double depth = owner.getSoulDepth().getKnowledge();
|
||||
@@ -41,10 +59,107 @@ public class CombatChanges {
|
||||
logger.info("Somehow a pet is dominated by a non-player? (" + cret.getDominator().getName() + ")");
|
||||
}
|
||||
}
|
||||
if(QualityOfLife.getVehicleSafe(cret) != null){
|
||||
mult *= 0.75f;
|
||||
}
|
||||
}
|
||||
return mult;
|
||||
}
|
||||
|
||||
public static float getAdjustedOakshell(Creature defender, Item armour, float armourMod){
|
||||
if(defender != null && armour == null){
|
||||
float oakshellPower = defender.getBonusForSpellEffect(Enchants.CRET_OAKSHELL);
|
||||
if(oakshellPower > 0f){
|
||||
return (float) (1-(0.8f*Math.pow((oakshellPower/(oakshellPower+80)), 0.5d)));
|
||||
}
|
||||
}
|
||||
return armourMod; // Returns previous armourMod if the target has armour.
|
||||
}
|
||||
|
||||
protected static ArrayList<Creature> uniques = new ArrayList<>();
|
||||
public static void pollUniqueCollection(){
|
||||
for(Creature cret : Creatures.getInstance().getCreatures()){
|
||||
if(cret.isUnique() && !uniques.contains(cret)){
|
||||
logger.info("Found unique not in unique list, adding now: "+cret.getName());
|
||||
uniques.add(cret);
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
while(i < uniques.size()){
|
||||
if(uniques.get(i).isDead()){
|
||||
logger.info("Unique was found dead ("+uniques.get(i).getName()+"). Removing from uniques list.");
|
||||
uniques.remove(uniques.get(i));
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void pollUniqueRegeneration(){
|
||||
if(!uniques.isEmpty()) {
|
||||
for (Creature cret : uniques) {
|
||||
if (cret.getBody().isWounded()) {
|
||||
Wounds tWounds = cret.getBody().getWounds();
|
||||
int toHeal = 75;
|
||||
Wound w = tWounds.getWounds()[Server.rand.nextInt(tWounds.getWounds().length)];
|
||||
if (w.getSeverity() > toHeal) {
|
||||
w.modifySeverity(-toHeal);
|
||||
break;
|
||||
} else {
|
||||
w.heal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean canDoDamage(double damage, Creature attacker, Creature defender, Item weapon) {
|
||||
logger.info(String.format("canDoDamage from %s to %s with %s - %.1f", attacker.getName(), defender.getName(), weapon.getName(), damage));
|
||||
return damage > 1D;
|
||||
}
|
||||
|
||||
static void patchCombatDamageCheck(ClassPool classPool) throws NotFoundException, BadBytecode {
|
||||
CtClass cls = classPool.getCtClass("com.wurmonline.server.creatures.CombatHandler");
|
||||
CtMethod method = cls.getMethod("setDamage", "(Lcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/items/Item;DBB)Z");
|
||||
MethodInfo methodInfo = method.getMethodInfo();
|
||||
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
|
||||
ConstPool constPool = codeAttribute.getConstPool();
|
||||
CodeIterator codeIterator = codeAttribute.iterator();
|
||||
|
||||
// Scan through all the bytecode - look for a multiplication followed by comparing
|
||||
while (codeIterator.hasNext()) {
|
||||
int pos = codeIterator.next();
|
||||
int op = codeIterator.byteAt(pos);
|
||||
if (op != CodeIterator.DMUL) continue; // not multiplication - continue
|
||||
op = codeIterator.byteAt(++pos);
|
||||
if (op == CodeIterator.LDC2_W && codeIterator.byteAt(pos + 3) == CodeIterator.DCMPL) {
|
||||
// found the pattern, check the value it's comparing to
|
||||
int ref = codeIterator.u16bitAt(pos + 1);
|
||||
double val = constPool.getDoubleInfo(ref);
|
||||
if (val == 500.0) {
|
||||
// here it is, generate new code to insert
|
||||
// We'll be calling canDoDamage, the first parameter (damage) is already on the stack, prepare the rest
|
||||
Bytecode newCode = new Bytecode(constPool);
|
||||
newCode.add(Bytecode.ALOAD_0); // this
|
||||
newCode.addGetfield(cls, "creature", "Lcom/wurmonline/server/creatures/Creature;"); // this.creature
|
||||
newCode.add(Bytecode.ALOAD_1); // defender - first parameter of setDamage
|
||||
newCode.add(Bytecode.ALOAD_2); // weapon - second parameter of setDamage
|
||||
|
||||
// call our methor, result is left on the stack
|
||||
newCode.addInvokestatic(
|
||||
CombatChanges.class.getName(), "canDoDamage",
|
||||
"(DLcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/items/Item;)Z");
|
||||
|
||||
// The code we're replacing is 4 bytes - LDC2_W, 2byte reference and DCMPL
|
||||
// Insert a gap for to match the size of the new code
|
||||
codeIterator.insertGap(pos, newCode.getSize() - 4);
|
||||
|
||||
// And put the new code
|
||||
codeIterator.write(newCode.get(), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void preInit(){
|
||||
try{
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
@@ -83,11 +198,86 @@ public class CombatChanges {
|
||||
replace = "if($2.isDominated() && $1 != null && $1.isUnique()){" +
|
||||
//" logger.info(\"Detected unique hit on a pet. Adding damage.\");" +
|
||||
" $5 = $5 * 2d;" +
|
||||
"}" +
|
||||
"if($2.isUnique() && $1 != null && $1.isDominated()){" +
|
||||
" logger.info(\"Detected pet hit on a unique. Reducing damage.\");" +
|
||||
" $5 = $5 * 0.5d;" +
|
||||
"}";
|
||||
Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);
|
||||
|
||||
Util.setReason("Adjust weapon damage type based on the potion/salve applied.");
|
||||
replace = "int wt = "+CombatChanges.class.getName()+".getWeaponType($1);"
|
||||
+ "if(wt != -1){"
|
||||
+ " type = wt;"
|
||||
+ " return wt;"
|
||||
+ "}";
|
||||
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace);
|
||||
|
||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
||||
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
|
||||
CtClass[] params2 = {
|
||||
ctCreature,
|
||||
ctItem,
|
||||
ctCreature
|
||||
};
|
||||
String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2);
|
||||
replace = "$_ = true;";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace);
|
||||
|
||||
Util.setReason("Fix magranon damage bonus stacking.");
|
||||
replace = "if(mildStack){" +
|
||||
" $_ = $proceed($$) * 8 / 5;" +
|
||||
"}else{" +
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace);
|
||||
|
||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
||||
CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction");
|
||||
CtClass[] params3 = {
|
||||
ctCreature,
|
||||
ctAttackAction,
|
||||
ctCreature
|
||||
};
|
||||
String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3);
|
||||
replace = "$_ = true;";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace);
|
||||
|
||||
Util.setReason("Fix magranon damage bonus stacking.");
|
||||
replace = "if(mildStack){" +
|
||||
" $_ = $proceed($$) * 8 / 5;" +
|
||||
"}else{" +
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace);
|
||||
|
||||
Util.setReason("Nerf truehit/excel.");
|
||||
replace = "$_ = $proceed($$) * 0.5f;";
|
||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace);
|
||||
|
||||
Util.setReason("Nerf oakshell.");
|
||||
replace = "if(defender.isPlayer() && defender.getBonusForSpellEffect((byte)22) > 0f){" +
|
||||
" armourMod = "+CombatChanges.class.getName()+".getAdjustedOakshell(defender, armour, armourMod);" +
|
||||
"}" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getDamReductionBonusFor", replace);
|
||||
|
||||
Util.setReason("Disable natural regeneration on uniques.");
|
||||
CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound");
|
||||
replace = "if(!this.creature.isUnique()){"
|
||||
+ " $_ = $proceed($$);"
|
||||
+ "}";
|
||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace);
|
||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace);
|
||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace);
|
||||
|
||||
//patchCombatDamageCheck(classPool);
|
||||
//patchCombatDamageCheckAddWound(classPool);
|
||||
|
||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||
throw new HookException(e);
|
||||
}
|
||||
}/* catch (BadBytecode badBytecode) {
|
||||
badBytecode.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user