Update to latest iteration.

This commit is contained in:
Sindusk
2018-05-30 06:49:25 -04:00
parent 4ec6d1cbdd
commit 76681b6b0e
22 changed files with 514 additions and 170 deletions

View File

@@ -126,8 +126,10 @@ public class SorceryCombineAction implements ModAction {
performer.getCommunicator().sendSafeServerMessage("A new sorcery has been created!");
MiscChanges.sendServerTabMessage("arena", performer.getName()+" has created a new sorcery!", 52, 152, 219);
Item sorcery = ItemUtil.createRandomSorcery((byte) (2+Server.rand.nextInt(1)));
logger.info("Player "+performer.getName()+" created a "+sorcery.getName()+" with "+(3-sorcery.getAuxData())+" charges.");
performer.getInventory().insertItem(sorcery, true);
if(sorcery != null) {
logger.info("Player " + performer.getName() + " created a " + sorcery.getName() + " with " + (3 - sorcery.getAuxData()) + " charges.");
performer.getInventory().insertItem(sorcery, true);
}
if(newAux >= 0) {
first.setAuxData(newAux);
first.setName("sorcery fragment [" + (first.getAuxData() + 1) + "/10]");

View File

@@ -3,6 +3,7 @@ package mod.sin.actions.items;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -57,7 +58,7 @@ public class EnchantOrbAction implements ModAction {
public List<ActionEntry> getBehavioursFor(Creature performer, Item source, Item object)
{
if(performer instanceof Player && source != null && object != null && source.getTemplateId() == EnchantOrb.templateId && source != object){
return Arrays.asList(actionEntry);
return Collections.singletonList(actionEntry);
}
return null;
}
@@ -84,8 +85,8 @@ public class EnchantOrbAction implements ModAction {
player.getCommunicator().sendNormalServerMessage("You must use an Enchant Orb to transfer enchants.");
return true;
}
if(source.getWurmId() == target.getWurmId()){
player.getCommunicator().sendNormalServerMessage("You cannot enchant the orb with itself!");
if(target.getTemplate().getTemplateId() == EnchantOrb.templateId){
player.getCommunicator().sendNormalServerMessage("You cannot enchant an Enchant Orb with another.");
return true;
}
ItemSpellEffects effs = source.getSpellEffects();
@@ -93,36 +94,78 @@ public class EnchantOrbAction implements ModAction {
player.getCommunicator().sendNormalServerMessage("The "+source.getTemplate().getName()+" has no enchants.");
return true;
}
if(!Spell.mayBeEnchanted(target)){
/*if(!Spell.mayBeEnchanted(target)){
player.getCommunicator().sendNormalServerMessage("The "+target.getTemplate().getName()+" may not be enchanted.");
}
}*/
ItemSpellEffects teffs = target.getSpellEffects();
if(teffs == null){
teffs = new ItemSpellEffects(target.getWurmId());
}
for(SpellEffect eff : effs.getEffects()){
Spell spell = Spells.getEnchantment(eff.type);
boolean canEnchant = Spell.mayBeEnchanted(target);
boolean canEnchant = false;// = Spell.mayBeEnchanted(target);
byte type = eff.type;
if(spell == null){
logger.info("Error: Enchant for "+eff.type+" doesn't exist.");
continue;
}
if(canEnchant){
try {
Method m = spell.getClass().getDeclaredMethod("precondition", Skill.class, Creature.class, Item.class);
canEnchant = ReflectionUtil.callPrivateMethod(spell, m, player.getChannelingSkill(), performer, target);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
if(eff.type < -60){ // It's a rune
if(teffs.getNumberOfRuneEffects() > 0){
teffs.getRandomRuneEffect();
player.getCommunicator().sendAlertServerMessage("The "+target.getTemplate().getName()+" already has a rune attached and resists the application of the "+eff.getName()+".");
continue;
}else{
canEnchant = true;
}
}else{
if(teffs.getSpellEffect(type) != null){
float power = teffs.getSpellEffect(type).getPower();
if(power >= 100f){
player.getCommunicator().sendAlertServerMessage("The "+target.getTemplate().getName()+" already has the maximum power for "+eff.getName()+", and refuses to accept more.");
continue;
}else if(power + eff.getPower() > 100){
float difference = 100-power;
eff.setPower(eff.getPower()-difference);
teffs.getSpellEffect(type).setPower(100);
player.getCommunicator().sendSafeServerMessage("The "+eff.getName()+" transfers some of its power to the "+target.getTemplate().getName()+".");
continue;
}else{
teffs.getSpellEffect(type).setPower(effs.getSpellEffect(type).getPower()+power);
effs.removeSpellEffect(type);
player.getCommunicator().sendSafeServerMessage("The "+eff.getName()+" fully transfers to the "+target.getTemplate().getName()+".");
continue;
}
}else{
canEnchant = true;
}
}
}else {
try {
Method m = spell.getClass().getDeclaredMethod("precondition", Skill.class, Creature.class, Item.class);
canEnchant = ReflectionUtil.callPrivateMethod(spell, m, player.getChannelingSkill(), performer, target);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
if(canEnchant){
if(teffs.getSpellEffect(type) != null){
if(teffs.getSpellEffect(type).getPower() >= eff.getPower()) {
player.getCommunicator().sendAlertServerMessage("The " + target.getTemplate().getName() + " already has a more powerful " + eff.getName() + " and resists the transfer.");
continue;
}else{
teffs.getSpellEffect(type).setPower(eff.getPower());
effs.removeSpellEffect(type);
player.getCommunicator().sendSafeServerMessage("The "+eff.getName()+" replaces the existing enchant.");
continue;
}
}
SpellEffect newEff = new SpellEffect(target.getWurmId(), type, eff.getPower(), 20000000);
teffs.addSpellEffect(newEff);
Items.destroyItem(source.getWurmId());
effs.removeSpellEffect(type);
player.getCommunicator().sendSafeServerMessage("The "+eff.getName()+" transfers to the "+target.getTemplate().getName()+".");
}
}
if(effs.getEffects().length == 0){
player.getCommunicator().sendSafeServerMessage("The "+source.getTemplate().getName()+" exhausts the last of its magic and vanishes.");
Items.destroyItem(source.getWurmId());
}
}else{
logger.info("Somehow a non-player activated an Enchant Orb...");
}

View File

@@ -0,0 +1,130 @@
package mod.sin.actions.items;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Items;
import com.wurmonline.server.behaviours.Action;
import com.wurmonline.server.behaviours.ActionEntry;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemFactory;
import com.wurmonline.server.items.ItemSpellEffects;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.players.Player;
import com.wurmonline.server.skills.Skill;
import com.wurmonline.server.spells.Spell;
import com.wurmonline.server.spells.SpellEffect;
import com.wurmonline.server.spells.Spells;
import mod.sin.items.EnchantOrb;
import mod.sin.items.EternalOrb;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer;
import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider;
import org.gotti.wurmunlimited.modsupport.actions.ModAction;
import org.gotti.wurmunlimited.modsupport.actions.ModActions;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class EternalOrbAction implements ModAction {
private static Logger logger = Logger.getLogger(EternalOrbAction.class.getName());
private final short actionId;
private final ActionEntry actionEntry;
public EternalOrbAction() {
logger.log(Level.WARNING, "EternalOrbAction()");
actionId = (short) ModActions.getNextActionId();
actionEntry = ActionEntry.createEntry(
actionId,
"Absorb enchants",
"absorbing",
new int[0]
//new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */
);
ModActions.registerAction(actionEntry);
}
@Override
public BehaviourProvider getBehaviourProvider()
{
return new BehaviourProvider() {
// Menu with activated object
@Override
public List<ActionEntry> getBehavioursFor(Creature performer, Item source, Item object)
{
if(performer instanceof Player && source != null && object != null && source.getTemplateId() == EternalOrb.templateId && source != object){
return Collections.singletonList(actionEntry);
}
return null;
}
};
}
@Override
public ActionPerformer getActionPerformer()
{
return new ActionPerformer() {
@Override
public short getActionId() {
return actionId;
}
// With activated object
@Override
public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter)
{
if(performer instanceof Player){
Player player = (Player) performer;
if(source.getTemplate().getTemplateId() != EternalOrb.templateId){
player.getCommunicator().sendNormalServerMessage("You must use an Eternal Orb to absorb enchants.");
return true;
}
if(source.getWurmId() == target.getWurmId()){
player.getCommunicator().sendNormalServerMessage("You cannot absorb the orb with itself!");
return true;
}
ItemSpellEffects teffs = target.getSpellEffects();
if(teffs == null || teffs.getEffects().length == 0){
player.getCommunicator().sendNormalServerMessage("The "+target.getTemplate().getName()+" has no enchants.");
return true;
}
try {
Item enchantOrb = ItemFactory.createItem(EnchantOrb.templateId, source.getCurrentQualityLevel(), "");
ItemSpellEffects effs = enchantOrb.getSpellEffects();
if(effs == null){
effs = new ItemSpellEffects(enchantOrb.getWurmId());
}
for(SpellEffect teff : teffs.getEffects()){
byte type = teff.type;
SpellEffect newEff = new SpellEffect(enchantOrb.getWurmId(), type, teff.getPower(), 20000000);
effs.addSpellEffect(newEff);
teffs.removeSpellEffect(type);
player.getCommunicator().sendSafeServerMessage("The "+teff.getName()+" transfers to the "+enchantOrb.getTemplate().getName()+".");
if(enchantOrb.getDescription().equals("")){
enchantOrb.setDescription(newEff.getName().substring(0,1)+String.format("%d", (int) newEff.getPower()));
}else{
enchantOrb.setDescription(enchantOrb.getDescription()+" "+newEff.getName().substring(0,1)+String.format("%d", (int) newEff.getPower()));
}
}
performer.getInventory().insertItem(enchantOrb, true);
Items.destroyItem(source.getWurmId());
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
}else{
logger.info("Somehow a non-player activated an Enchant Orb...");
}
return true;
}
}; // ActionPerformer
}
}

View File

@@ -73,6 +73,7 @@ public class Avenger implements ModCreature, CreatureTypes {
builder.combatDamageType(Wound.TYPE_COLD);
builder.maxPercentOfCreatures(0.005f);
builder.maxGroupAttackSize(100);
builder.color(70, 70, 255);
templateId = builder.getTemplateId();
return builder;

View File

@@ -69,6 +69,7 @@ public class HornedPony implements ModCreature, CreatureTypes {
builder.combatDamageType(Wound.TYPE_INTERNAL);
builder.maxPercentOfCreatures(0.001f);
builder.maxGroupAttackSize(100);
builder.color(128, 10, 70);
templateId = builder.getTemplateId();
return builder;

View File

@@ -53,6 +53,7 @@ public class Ifrit implements ModCreature, CreatureTypes {
builder.baseCombatRating(99.0f);
builder.combatDamageType(Wound.TYPE_BURN);
builder.maxGroupAttackSize(150);
builder.color(255, 128, 128);
//builder.usesNewAttacks(true);
// float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack

View File

@@ -53,6 +53,7 @@ public class Lilith implements ModCreature, CreatureTypes {
builder.baseCombatRating(99.0f);
builder.combatDamageType(Wound.TYPE_INFECTION);
builder.maxGroupAttackSize(150);
builder.color(128, 0, 0);
//builder.usesNewAttacks(true);
// float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack

View File

@@ -54,6 +54,7 @@ public class LilithZombie implements ModCreature, CreatureTypes {
builder.combatDamageType(Wound.TYPE_INFECTION);
builder.maxPercentOfCreatures(0.005f);
builder.maxGroupAttackSize(100);
builder.color(128, 10, 10);
templateId = builder.getTemplateId();
return builder;

View File

@@ -3,6 +3,7 @@ package mod.sin.items;
import java.io.IOException;
import java.util.logging.Logger;
import com.wurmonline.server.items.Materials;
import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder;
import com.wurmonline.server.MiscConstants;
@@ -32,7 +33,7 @@ public class EnchantOrb implements ItemTypes, MiscConstants {
itemBuilder.modelName("model.artifact.orbdoom");
itemBuilder.difficulty(5.0f);
itemBuilder.weightGrams(500);
itemBuilder.material((byte)52);
itemBuilder.material(Materials.MATERIAL_CRYSTAL);
itemBuilder.value(50000);
itemBuilder.isTraded(true);

View File

@@ -0,0 +1,43 @@
package mod.sin.items;
import com.wurmonline.server.MiscConstants;
import com.wurmonline.server.items.ItemTemplate;
import com.wurmonline.server.items.ItemTypes;
import com.wurmonline.server.items.Materials;
import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder;
import java.io.IOException;
import java.util.logging.Logger;
public class EternalOrb implements ItemTypes, MiscConstants {
public static Logger logger = Logger.getLogger(EternalOrb.class.getName());
public static int templateId;
public void createTemplate() throws IOException{
String name = "eternal orb";
ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.eternal.orb");
itemBuilder.name(name, "eternal orbs", "Legends say it consumes magic from an object, and moves it to another.");
itemBuilder.itemTypes(new short[]{
ItemTypes.ITEM_TYPE_FULLPRICE,
ItemTypes.ITEM_TYPE_NOSELLBACK,
ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE
});
itemBuilder.imageNumber((short) 819);
itemBuilder.behaviourType((short) 1);
itemBuilder.combatDamage(0);
itemBuilder.decayTime(Long.MAX_VALUE);
itemBuilder.dimensions(1, 1, 1);
itemBuilder.primarySkill((int) NOID);
itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY);
itemBuilder.modelName("model.artifact.orbdoom");
itemBuilder.difficulty(5.0f);
itemBuilder.weightGrams(500);
itemBuilder.material(Materials.MATERIAL_CRYSTAL);
itemBuilder.value(200000);
itemBuilder.isTraded(true);
ItemTemplate template = itemBuilder.build();
templateId = template.getTemplateId();
logger.info(name+" TemplateID: "+templateId);
}
}

View File

@@ -761,8 +761,8 @@ public class Arena {
Util.setReason("Reduce player vs player damage by half.");
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isDominated() || $1.isPlayer()) && $0.creature.isPlayer()){" +
" logger.info(\"Detected player hit against player/pet opponent. Halving damage.\");" +
" $3 = $3 * 0.5d;" +
//" logger.info(\"Detected player hit against player/pet opponent. Halving damage.\");" +
" $3 = $3 * 0.7d;" +
"}";
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "setDamage", replace);

View File

@@ -195,7 +195,7 @@ public class Bounty {
//ctCreatureStatus.getDeclaredMethod("getSizeMod").setBody("{return mod.sin.wyvern.bestiary.MethodsBestiary.getAdjustedSizeMod(this);}");
// -- Enable adjusting color for creatures -- //
CtClass ctCreatureTemplate = classPool.get("com.wurmonline.server.creatures.CreatureTemplate");
/*CtClass ctCreatureTemplate = classPool.get("com.wurmonline.server.creatures.CreatureTemplate");
replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){"
+ " return "+MethodsBestiary.class.getName()+".getCreatureColorRed(this);"
+ "}";
@@ -207,7 +207,7 @@ public class Bounty {
replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){"
+ " return "+MethodsBestiary.class.getName()+".getCreatureColorBlue(this);"
+ "}";
Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorBlue", replace);
Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorBlue", replace);*/
/*ctCreatureTemplate.getDeclaredMethod("getColorRed").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){"
+ " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorRed(this);"
+ "}");

View File

@@ -1,6 +1,7 @@
package mod.sin.wyvern;
import com.wurmonline.server.Server;
import com.wurmonline.server.Servers;
import com.wurmonline.server.bodys.Wound;
import com.wurmonline.server.bodys.Wounds;
import com.wurmonline.server.creatures.Creature;
@@ -66,6 +67,33 @@ public class CombatChanges {
return mult;
}
public static int getLifeTransferAmountModifier(Wound wound, int initial){
byte type = wound.getType();
if(type == Wound.TYPE_ACID || type == Wound.TYPE_BURN || type == Wound.TYPE_COLD){
initial *= 0.5;
}else if(type == Wound.TYPE_INTERNAL || type == Wound.TYPE_INFECTION || type == Wound.TYPE_POISON){
initial *= 0.3;
}
return initial;
}
public static float getLifeTransferModifier(Creature creature, Creature defender){
if(Servers.localServer.PVPSERVER && (defender.isDominated() || defender.isPlayer()) && creature.isPlayer()){
return 0.5f;
}
return 1.0f;
}
public static void doLifeTransfer(Creature creature, Creature defender, Item attWeapon, double defdamage, float armourMod){
float lifeTransfer = attWeapon.getSpellLifeTransferModifier()*getLifeTransferModifier(creature, defender);
Wound[] w;
if (lifeTransfer > 0.0f && defdamage * (double)armourMod * (double)lifeTransfer / (double)(creature.isChampion() ? 1000.0f : 500.0f) > 500.0 && creature.getBody() != null && creature.getBody().getWounds() != null && (w = creature.getBody().getWounds().getWounds()).length > 0) {
int amount = - (int)(defdamage * (double)lifeTransfer / (double)(creature.isChampion() ? 1000.0f : (creature.getCultist() != null && creature.getCultist().healsFaster() ? 250.0f : 500.0f)));
amount = getLifeTransferAmountModifier(w[0], amount);
w[0].modifySeverity(amount);
}
}
public static float getAdjustedOakshell(Creature defender, Item armour, float armourMod){
if(defender != null && armour == null){
float oakshellPower = defender.getBonusForSpellEffect(Enchants.CRET_OAKSHELL);
@@ -111,13 +139,76 @@ public class CombatChanges {
}
}
}
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));
public static boolean canDoDamage(double damage, Creature attacker, Creature defender) {
//logger.info(String.format("canDoDamage from %s to %s - %.1f", attacker.getName(), defender.getName(), damage));
return damage > 1D;
}
static void patchCombatDamageCheck(ClassPool classPool) throws NotFoundException, BadBytecode {
static void patchCombatDamageCheckCombatEngine(ClassPool classPool) throws NotFoundException, BadBytecode {
CtClass cls = classPool.getCtClass("com.wurmonline.server.combat.CombatEngine");
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
CtClass ctString = classPool.get("java.lang.String");
CtClass ctBattle = classPool.get("com.wurmonline.server.combat.Battle");
CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine");
// @Nullable Creature performer, Creature defender, byte type, int pos, double damage, float armourMod,
// String attString, @Nullable Battle battle, float infection, float poison, boolean archery, boolean alreadyCalculatedResist
CtClass[] params1 = {
ctCreature,
ctCreature,
CtClass.byteType,
CtClass.intType,
CtClass.doubleType,
CtClass.floatType,
ctString,
ctBattle,
CtClass.floatType,
CtClass.floatType,
CtClass.booleanType,
CtClass.booleanType
};
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
CtMethod method = cls.getMethod("addWound", desc1);
//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); // performer - first parameter of addWound
newCode.add(Bytecode.ALOAD_1); // defender - first parameter of addWound
// 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;)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);
}
}
}
}
static void patchCombatDamageCheckCombatHandler(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();
@@ -142,12 +233,11 @@ public class CombatChanges {
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");
"(DLcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/creatures/Creature;)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
@@ -160,6 +250,7 @@ public class CombatChanges {
}
}
public static void preInit(){
try{
ClassPool classPool = HookManager.getInstance().getClassPool();
@@ -271,13 +362,34 @@ public class CombatChanges {
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace);
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace);
//patchCombatDamageCheck(classPool);
//patchCombatDamageCheckAddWound(classPool);
Util.setReason("Allow Life Transfer to stack with Rotting Touch (Mechanics-Wise).");
replace = CombatChanges.class.getName()+".doLifeTransfer(this.creature, defender, attWeapon, defdamage, armourMod);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isWeaponCrush", replace);
Util.setReason("Reduce Life Transfer power on PvP.");
replace = "$_ = $proceed($$)*"+CombatChanges.class.getName()+".getLifeTransferModifier(this.creature, defender);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getSpellLifeTransferModifier", replace);
Util.setReason("Reduce Life Transfer healing amount for certain wounds.");
replace = "$_ = $proceed("+CombatChanges.class.getName()+".getLifeTransferAmountModifier($0, $1));";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "modifySeverity", replace);
Util.setReason("Make AOSP not disgustingly broken.");
replace = "if(!this.creature.isPlayer()){" +
" $_ = $proceed($$)*this.creature.addSpellResistance((short) 278);" +
"}else{" +
" $_ = $proceed($$);" +
"}";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getSpellPainShare", replace);
patchCombatDamageCheckCombatEngine(classPool);
patchCombatDamageCheckCombatHandler(classPool);
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
throw new HookException(e);
}/* catch (BadBytecode badBytecode) {
} catch (BadBytecode badBytecode) {
badBytecode.printStackTrace();
}*/
}
}
}

View File

@@ -49,6 +49,7 @@ public class ItemMod {
public static DepthDrill DEPTH_DRILL = new DepthDrill();
public static DisintegrationRod DISINTEGRATION_ROD = new DisintegrationRod();
public static EnchantOrb ENCHANT_ORB = new EnchantOrb();
public static EternalOrb ETERNAL_ORB = new EternalOrb();
public static Eviscerator EVISCERATOR = new Eviscerator();
public static FriyanTablet FRIYAN_TABLET = new FriyanTablet();
public static HugeCrate HUGE_CRATE = new HugeCrate();
@@ -112,6 +113,7 @@ public class ItemMod {
DEPTH_DRILL.createTemplate();
DISINTEGRATION_ROD.createTemplate();
ENCHANT_ORB.createTemplate();
ETERNAL_ORB.createTemplate();
EVISCERATOR.createTemplate();
FRIYAN_TABLET.createTemplate();
HUGE_CRATE.createTemplate();
@@ -174,6 +176,7 @@ public class ItemMod {
ModActions.registerAction(new DisintegrationRodAction());
ModActions.registerAction(new EnchantersCrystalInfuseAction());
ModActions.registerAction(new EnchantOrbAction());
ModActions.registerAction(new EternalOrbAction());
ModActions.registerAction(new FriyanTabletAction());
ModActions.registerAction(new SealedMapAction());
ModActions.registerAction(new SupplyDepotAction());

View File

@@ -38,13 +38,6 @@ import java.util.logging.Logger;
public class MiscChanges {
public static Logger logger = Logger.getLogger(MiscChanges.class.getName());
public static void doLifeTransfer(Creature creature, Item attWeapon, double defdamage, float armourMod){
Wound[] w;
if (attWeapon.getSpellLifeTransferModifier() > 0.0f && defdamage * (double)armourMod * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : 500.0f) > 500.0 && creature.getBody() != null && creature.getBody().getWounds() != null && (w = creature.getBody().getWounds().getWounds()).length > 0) {
w[0].modifySeverity(- (int)(defdamage * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : (creature.getCultist() != null && creature.getCultist().healsFaster() ? 250.0f : 500.0f))));
}
}
public static void sendServerTabMessage(String channel, final String message, final int red, final int green, final int blue){
DiscordRelay.sendToDiscord(channel, message, true);
// WARNING: Never change this from a new Runnable. Lambdas are a lie and will break everything.
@@ -314,8 +307,8 @@ public class MiscChanges {
// - Enable creature custom colors - (Used for creating custom color creatures eg. Lilith) - //
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
replace = "{ return true; }";
Util.setBodyDeclared(thisClass, ctCreature, "hasCustomColor", replace);
/*replace = "{ return true; }";
Util.setBodyDeclared(thisClass, ctCreature, "hasCustomColor", replace);*/
// - Increase the amount of checks for new unique spawns by 5x - //
CtClass ctServer = classPool.get("com.wurmonline.server.Server");
@@ -393,11 +386,6 @@ public class MiscChanges {
+ "}";
Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace);
Util.setReason("Allow Life Transfer to stack with Rotting Touch (Mechanics-Wise).");
replace = MiscChanges.class.getName()+".doLifeTransfer(this.creature, attWeapon, defdamage, armourMod);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isWeaponCrush", replace);
// - Allow GM's to bypass the 5 second emote sound limit. - //
replace = "if(this.getPower() > 0){"
+ " return true;"

View File

@@ -41,6 +41,7 @@ public class PlayerTitles {
}
}
public static void preInit(){
// Donations
playerTitles.put("Sindusk", "Phenomenal Feline");
customTitles.put("Sindawn", 501); // Developer
@@ -70,5 +71,16 @@ public class PlayerTitles {
customTitles.put("Reevi", 807); // Science Guy
customTitles.put("Genocide", 808); // Grand Designer
donatorTitles.add("Seleas");
customTitles.put("Seleas", 809); // The Crazy Cat Lord
playerTitles.put("Seleas", "No, Really");
donatorTitles.add("Piratemax");
customTitles.put("Piratemax", 810); // Slave
playerTitles.put("Piratemax", "Boy Next Door");
// Other rewards
customTitles.put("Critias", 602);
}
}

View File

@@ -8,10 +8,13 @@ import com.wurmonline.server.creatures.NoSuchCreatureException;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.zones.NoSuchZoneException;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.bytecode.Descriptor;
import javassist.expr.ExprEditor;
import javassist.expr.FieldAccess;
import mod.sin.lib.Util;
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
@@ -164,8 +167,19 @@ public class QualityOfLife {
QualityOfLife.class.getName()+".vehicleHook(performer, $0);";
Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "createGem", desc2, "putItemInfrontof", replace);
CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player");
ctPlayer.getMethod("poll", "()Z").instrument(new ExprEditor() {
@Override
public void edit(FieldAccess f) throws CannotCompileException {
if (f.getFieldName().equals("vehicle") && f.isReader())
f.replace("$_ = -10L;");
}
});
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
throw new HookException(e);
} catch (CannotCompileException e) {
e.printStackTrace();
}
}
}

View File

@@ -535,42 +535,44 @@ public class Titans {
int prevDamage = titanDamage.get(titan);
int currentDamage = titan.getStatus().damage;
long wurmid = titan.getWurmId();
if(titan.isOnSurface() && currentDamage > 0){
// Advanced Ability
int chance;
int range;
int radius;
if(currentDamage > 52428) { // 20%
chance = 40;
range = 8;
radius = 2;
}else if(currentDamage > 32767){ // 50%
chance = 45;
range = 5;
radius = 1;
}else if(currentDamage > 16383){ // 75%
chance = 55;
range = 4;
radius = 1;
}else{
chance = 60;
range = 3;
radius = 0;
}
if(titanAdvancedTimed.containsKey(wurmid)){
int currentChance = titanAdvancedTimed.get(wurmid);
boolean success = Server.rand.nextInt(currentChance) == 0;
if(success){
performAdvancedAbility(titan, range, radius);
titanAdvancedTimed.put(wurmid, currentChance+chance-1);
}else{
titanAdvancedTimed.put(wurmid, currentChance-1);
if(currentDamage > 0) {
if (titan.isOnSurface()) {
// Advanced Ability
int chance;
int range;
int radius;
if (currentDamage > 52428) { // 20%
chance = 40;
range = 7;
radius = 2;
} else if (currentDamage > 32767) { // 50%
chance = 45;
range = 5;
radius = 1;
} else if (currentDamage > 16383) { // 75%
chance = 55;
range = 4;
radius = 1;
} else {
chance = 60;
range = 3;
radius = 0;
}
}else{
titanAdvancedTimed.put(wurmid, chance);
if (titanAdvancedTimed.containsKey(wurmid)) {
int currentChance = titanAdvancedTimed.get(wurmid);
boolean success = Server.rand.nextInt(currentChance) == 0;
if (success) {
performAdvancedAbility(titan, range, radius);
titanAdvancedTimed.put(wurmid, currentChance + chance - 1);
} else {
titanAdvancedTimed.put(wurmid, currentChance - 1);
}
} else {
titanAdvancedTimed.put(wurmid, chance);
}
} else if (!titan.isOnSurface() && Server.rand.nextInt(20) == 0) {
performAdvancedAbility(titan, 3, 3);
}
}else if(!titan.isOnSurface() && Server.rand.nextInt(20) == 0){
performAdvancedAbility(titan, 5, 2);
}
}
protected static void pollDamageMechanics(Creature titan){
@@ -762,7 +764,7 @@ public class Titans {
int tiley = (int) (minY+(minY*2*Server.rand.nextFloat()))*4;*/
int[] titanTemplates = {Lilith.templateId, Ifrit.templateId};
try {
Creature.doNew(titanTemplates[Server.rand.nextInt(titanTemplates.length)], spawnX, spawnY, 360f*Server.rand.nextFloat(), 0, "", (byte)0);
Creature.doNew(titanTemplates[Server.rand.nextInt(titanTemplates.length)], spawnX, spawnY, 360f*Server.rand.nextFloat(), 1, "", (byte)0);
lastSpawnedTitan = System.currentTimeMillis();
updateLastSpawnedTitan();
} catch (Exception e) {

View File

@@ -18,6 +18,8 @@ import java.util.logging.SimpleFormatter;
import com.wurmonline.server.Items;
import com.wurmonline.server.creatures.Communicator;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
import com.wurmonline.server.items.*;
import mod.sin.lib.Util;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;

View File

@@ -42,76 +42,6 @@ import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
public class MethodsBestiary {
protected static Logger logger = Logger.getLogger(MethodsBestiary.class.getName());
public static boolean checkColorTemplate(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return true;
}/*else if(templateId == ForestSpider.templateId){
return true;
}*/else if(templateId == Avenger.templateId){
return true;
}else if(templateId == HornedPony.templateId){
return true;
}else if(templateId == LilithZombie.templateId){
return true;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return false;
}
public static byte getCreatureColorRed(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
/*if(templateId == ForestSpider.templateId){
return (byte)0;
}else */if(templateId == Avenger.templateId){
return (byte)70;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
public static byte getCreatureColorGreen(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return (byte)0;
}else if(templateId == Avenger.templateId){
return (byte)70;
}else if(templateId == HornedPony.templateId){
return (byte)10;
}else if(templateId == LilithZombie.templateId){
return (byte)0;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
public static byte getCreatureColorBlue(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return (byte)0;
}/*else if(templateId == ForestSpider.templateId){
return (byte)0;
}*/else if(templateId == HornedPony.templateId){
return (byte)70;
}else if(templateId == LilithZombie.templateId){
return (byte)0;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
protected static boolean isUsuallyHitched(int templateId){
if(templateId == Charger.templateId){
@@ -297,8 +227,10 @@ public class MethodsBestiary {
}else if(creature.getTemplate().getTemplateId() == WyvernRed.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == WyvernWhite.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == Charger.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == WyvernBlue.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == Charger.templateId){
return true;
}
return creature.isHorse();
@@ -339,8 +271,10 @@ public class MethodsBestiary {
}else if(templateId == WyvernWhite.templateId){
return 0.5f;
}else if(templateId == WyvernRed.templateId){
return 0.25f;
}
return 0.25f;
}else if(templateId == WyvernBlue.templateId){
return 0.20f;
}
return -1f;
}

View File

@@ -1,16 +1,10 @@
package mod.sin.wyvern.bounty;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Logger;
import com.wurmonline.mesh.Tiles;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.HistoryManager;
import com.wurmonline.server.Players;
import com.wurmonline.server.Server;
import com.wurmonline.server.Servers;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
@@ -18,18 +12,21 @@ import com.wurmonline.server.creatures.Creatures;
import com.wurmonline.server.items.*;
import com.wurmonline.server.villages.Village;
import com.wurmonline.server.villages.Villages;
import mod.sin.armour.SpectralHide;
import mod.sin.creatures.Reaper;
import mod.sin.creatures.SpectralDrake;
import mod.sin.items.ChaosCrystal;
import mod.sin.items.EnchantersCrystal;
import mod.sin.items.AffinityOrb;
import mod.sin.items.FriyanTablet;
import mod.sin.items.caches.*;
import mod.sin.wyvern.Bounty;
import mod.sin.wyvern.MiscChanges;
import mod.sin.wyvern.Arena;
import mod.sin.wyvern.Titans;
import mod.sin.wyvern.util.ItemUtil;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Logger;
public class LootBounty {
public static final Logger logger = Logger.getLogger(LootBounty.class.getName());
protected static final Random random = new Random();
@@ -102,14 +99,61 @@ public class LootBounty {
}
return 0;
}
public static void insertUniqueLoot(Creature mob, Item corpse){
try {
Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 90+(10*random.nextFloat()), "");
corpse.insertItem(affinityOrb);
int[] cacheIds = {
ArtifactCache.templateId,
CrystalCache.templateId, CrystalCache.templateId,
DragonCache.templateId, DragonCache.templateId,
MoonCache.templateId, MoonCache.templateId,
RiftCache.templateId,
TreasureMapCache.templateId
};
int i = 1+Server.rand.nextInt(3);
while(i > 0){
Item cache = ItemFactory.createItem(cacheIds[Server.rand.nextInt(cacheIds.length)], 50+(30*random.nextFloat()), "");
if(Server.rand.nextInt(5) == 0){
cache.setRarity((byte) 1);
}
corpse.insertItem(cache);
i--;
}
if(mob.isDragon()) {
int mTemplate = mob.getTemplate().getTemplateId();
int lootTemplate = ItemList.drakeHide;
if(mTemplate == CreatureTemplateFactory.DRAGON_BLACK_CID || mTemplate == CreatureTemplateFactory.DRAGON_BLUE_CID || mTemplate == CreatureTemplateFactory.DRAGON_GREEN_CID
|| mTemplate == CreatureTemplateFactory.DRAGON_RED_CID || mTemplate == CreatureTemplateFactory.DRAGON_WHITE_CID){
lootTemplate = ItemList.dragonScale;
}
logger.info("Generating extra hide & scale to insert on the corpse of " + mob.getName() + ".");
ItemTemplate itemTemplate = ItemTemplateFactory.getInstance().getTemplate(lootTemplate);
for (i = 0; i < 2; i++) {
Item loot = ItemFactory.createItem(lootTemplate, 80 + (15 * random.nextFloat()), "");
String creatureName = mob.getTemplate().getName().toLowerCase();
if (!loot.getName().contains(creatureName)) {
loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName());
}
loot.setData2(mTemplate);
int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == ItemList.drakeHide ? 3 : 1);
loot.setWeight((int) ((weightGrams * 0.02f) + (weightGrams * 0.02f * random.nextFloat())), true);
corpse.insertItem(loot);
}
}
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
}
public static void blessWorldWithMoonVeins(Creature mob){
int i = 20;
int i = 10+Server.rand.nextInt(6);
while(i > 0){
int x = random.nextInt(Server.surfaceMesh.getSize());
int y = random.nextInt(Server.surfaceMesh.getSize());
short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y));
int type = Tiles.decodeType((int)Server.caveMesh.getTile(x, y));
int type = Tiles.decodeType(Server.caveMesh.getTile(x, y));
if(height >= 100 && (type == Tiles.Tile.TILE_CAVE_WALL.id || type == Tiles.Tile.TILE_CAVE.id)){
Tiles.Tile tileType = random.nextBoolean() ? Tiles.Tile.TILE_CAVE_WALL_ORE_ADAMANTINE : Tiles.Tile.TILE_CAVE_WALL_ORE_GLIMMERSTEEL;
Server.caveMesh.setTile(x, y, Tiles.encode(Tiles.decodeHeight(Server.caveMesh.getTile(x, y)), tileType.id, Tiles.decodeData(Server.caveMesh.getTile(x, y))));
@@ -310,6 +354,8 @@ public class LootBounty {
blessWorldWithMoonVeins(mob);
// Spawn 5-10 friyan tablets throughout the world.
spawnFriyanTablets();
// Add unique loot
insertUniqueLoot(mob, corpse);
// Spawn Spectral Drake
/*if (mob.isDragon()) { // Spawn the spectral drake and add extra hide/scale

View File

@@ -83,10 +83,15 @@ public class Mastercraft {
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Special_Title", 553, "Special Guy", "Special Girl", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Prophet_Ear", 554, "Prophet Ear", "Prophet Ear", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Koza", 555, "Koza", "Koza", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Wyvern_Hunter", 556, "Wyvern Hunter", "Wyvern Hunter", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Overlord", 557, "Overlord", "Overlord", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Troll", 558, "Troll", "Troll", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Beggar", 559, "Beggar", "Beggar", -1, "NORMAL");
// Contest Titles
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Home_Decorator", 600, "Home Decorator", "Home Decorator", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Arena_Champion", 601, "Champion of the Arena", "Champion of the Arena", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pastamancer", 602, "Pastamancer", "Pastamancer", -1, "NORMAL");
// Special Event Titles
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Titan_Slayer", 700, "Titanslayer", "Titanslayer", -1, "NORMAL");
@@ -104,6 +109,8 @@ public class Mastercraft {
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Alexia_TheTreasuring", 806, "The Treasuring", "The Treasuring", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Reevi_ScienceGuy", 807, "Science Guy", "Science Guy", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Genocide_GrandDesigner", 808, "Grand Designer", "Grand Designer", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Seleas_CrazyCatLord", 809, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Piratemax_Slave", 810, "Slave", "Slave", -1, "NORMAL");
// Characteristic Titles
ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Normal", 1000, "Logical", "Logical", 100, "NORMAL");