From 76681b6b0e36be58f8433ad6655215b1714e3e27 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Wed, 30 May 2018 06:49:25 -0400 Subject: [PATCH] Update to latest iteration. --- .../mod/sin/actions/SorceryCombineAction.java | 6 +- .../sin/actions/items/EnchantOrbAction.java | 79 ++++++++--- .../sin/actions/items/EternalOrbAction.java | 130 +++++++++++++++++ src/main/java/mod/sin/creatures/Avenger.java | 1 + .../java/mod/sin/creatures/HornedPony.java | 1 + .../java/mod/sin/creatures/titans/Ifrit.java | 1 + .../java/mod/sin/creatures/titans/Lilith.java | 1 + .../sin/creatures/titans/LilithZombie.java | 1 + src/main/java/mod/sin/items/EnchantOrb.java | 3 +- src/main/java/mod/sin/items/EternalOrb.java | 43 ++++++ src/main/java/mod/sin/wyvern/Arena.java | 4 +- src/main/java/mod/sin/wyvern/Bounty.java | 4 +- .../java/mod/sin/wyvern/CombatChanges.java | 132 ++++++++++++++++-- src/main/java/mod/sin/wyvern/ItemMod.java | 3 + src/main/java/mod/sin/wyvern/MiscChanges.java | 16 +-- .../java/mod/sin/wyvern/PlayerTitles.java | 12 ++ .../java/mod/sin/wyvern/QualityOfLife.java | 14 ++ src/main/java/mod/sin/wyvern/Titans.java | 72 +++++----- src/main/java/mod/sin/wyvern/WyvernMods.java | 2 + .../sin/wyvern/bestiary/MethodsBestiary.java | 82 ++--------- .../mod/sin/wyvern/bounty/LootBounty.java | 70 ++++++++-- .../sin/wyvern/mastercraft/Mastercraft.java | 7 + 22 files changed, 514 insertions(+), 170 deletions(-) create mode 100644 src/main/java/mod/sin/actions/items/EternalOrbAction.java create mode 100644 src/main/java/mod/sin/items/EternalOrb.java diff --git a/src/main/java/mod/sin/actions/SorceryCombineAction.java b/src/main/java/mod/sin/actions/SorceryCombineAction.java index 0aa6994..c218cfa 100644 --- a/src/main/java/mod/sin/actions/SorceryCombineAction.java +++ b/src/main/java/mod/sin/actions/SorceryCombineAction.java @@ -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]"); diff --git a/src/main/java/mod/sin/actions/items/EnchantOrbAction.java b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java index f6df48f..cd75ccc 100644 --- a/src/main/java/mod/sin/actions/items/EnchantOrbAction.java +++ b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java @@ -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 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..."); } diff --git a/src/main/java/mod/sin/actions/items/EternalOrbAction.java b/src/main/java/mod/sin/actions/items/EternalOrbAction.java new file mode 100644 index 0000000..88ec014 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/EternalOrbAction.java @@ -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 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 + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/creatures/Avenger.java b/src/main/java/mod/sin/creatures/Avenger.java index 690791f..64c808c 100644 --- a/src/main/java/mod/sin/creatures/Avenger.java +++ b/src/main/java/mod/sin/creatures/Avenger.java @@ -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; diff --git a/src/main/java/mod/sin/creatures/HornedPony.java b/src/main/java/mod/sin/creatures/HornedPony.java index e999832..34b59d6 100644 --- a/src/main/java/mod/sin/creatures/HornedPony.java +++ b/src/main/java/mod/sin/creatures/HornedPony.java @@ -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; diff --git a/src/main/java/mod/sin/creatures/titans/Ifrit.java b/src/main/java/mod/sin/creatures/titans/Ifrit.java index b2d76e3..be335bd 100644 --- a/src/main/java/mod/sin/creatures/titans/Ifrit.java +++ b/src/main/java/mod/sin/creatures/titans/Ifrit.java @@ -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 diff --git a/src/main/java/mod/sin/creatures/titans/Lilith.java b/src/main/java/mod/sin/creatures/titans/Lilith.java index 06bb852..ccca045 100644 --- a/src/main/java/mod/sin/creatures/titans/Lilith.java +++ b/src/main/java/mod/sin/creatures/titans/Lilith.java @@ -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 diff --git a/src/main/java/mod/sin/creatures/titans/LilithZombie.java b/src/main/java/mod/sin/creatures/titans/LilithZombie.java index 0c9f008..8a5b58d 100644 --- a/src/main/java/mod/sin/creatures/titans/LilithZombie.java +++ b/src/main/java/mod/sin/creatures/titans/LilithZombie.java @@ -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; diff --git a/src/main/java/mod/sin/items/EnchantOrb.java b/src/main/java/mod/sin/items/EnchantOrb.java index 80b2d47..1630b31 100644 --- a/src/main/java/mod/sin/items/EnchantOrb.java +++ b/src/main/java/mod/sin/items/EnchantOrb.java @@ -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); diff --git a/src/main/java/mod/sin/items/EternalOrb.java b/src/main/java/mod/sin/items/EternalOrb.java new file mode 100644 index 0000000..6bbda77 --- /dev/null +++ b/src/main/java/mod/sin/items/EternalOrb.java @@ -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); + } +} diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index be78a66..056669c 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -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); diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java index 1108856..e7727b1 100644 --- a/src/main/java/mod/sin/wyvern/Bounty.java +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -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);" + "}"); diff --git a/src/main/java/mod/sin/wyvern/CombatChanges.java b/src/main/java/mod/sin/wyvern/CombatChanges.java index ca7d0e9..93afa41 100644 --- a/src/main/java/mod/sin/wyvern/CombatChanges.java +++ b/src/main/java/mod/sin/wyvern/CombatChanges.java @@ -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(); - }*/ + } } } diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index 034f2f7..b40dd11 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -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()); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 3f6b244..915e4a9 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -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;" diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index af41855..10a41c6 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -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); } } diff --git a/src/main/java/mod/sin/wyvern/QualityOfLife.java b/src/main/java/mod/sin/wyvern/QualityOfLife.java index d0e1c3d..b88ccfb 100644 --- a/src/main/java/mod/sin/wyvern/QualityOfLife.java +++ b/src/main/java/mod/sin/wyvern/QualityOfLife.java @@ -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(); } } } diff --git a/src/main/java/mod/sin/wyvern/Titans.java b/src/main/java/mod/sin/wyvern/Titans.java index f5b87cc..694b2e8 100644 --- a/src/main/java/mod/sin/wyvern/Titans.java +++ b/src/main/java/mod/sin/wyvern/Titans.java @@ -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) { diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 23a9c80..ab5084b 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -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; diff --git a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java index 84f1aad..6dcdf14 100644 --- a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java +++ b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java @@ -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; } diff --git a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java index 20b8ec7..6d2dc79 100644 --- a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java @@ -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 diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java index f456d1f..2ac65a8 100644 --- a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java +++ b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java @@ -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");