From 23fac18308a62a1b9332a138d9dd8ffdfd9f21c9 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Sat, 2 Feb 2019 05:20:11 -0500 Subject: [PATCH 1/8] Update to latest version 1.2 for Wurm Unlimited 1.8 --- build.gradle | 4 +- src/main/java/mod/sin/creatures/Reaper.java | 13 ++-- src/main/java/mod/sin/items/AffinityOrb.java | 5 +- src/main/java/mod/sin/items/EternalOrb.java | 2 +- .../java/mod/sin/items/EternalReservoir.java | 1 + src/main/java/mod/sin/weapons/BattleYoyo.java | 2 +- src/main/java/mod/sin/wyvern/Arena.java | 34 +++------ src/main/java/mod/sin/wyvern/Crystals.java | 14 +++- .../java/mod/sin/wyvern/EconomicChanges.java | 15 +++- src/main/java/mod/sin/wyvern/ItemMod.java | 56 +++++---------- src/main/java/mod/sin/wyvern/MiscChanges.java | 41 ++++++++--- .../java/mod/sin/wyvern/PlayerTitles.java | 3 +- .../java/mod/sin/wyvern/SupplyDepots.java | 8 +-- src/main/java/mod/sin/wyvern/WyvernMods.java | 2 +- .../sin/wyvern/bestiary/MethodsBestiary.java | 36 +++++++--- .../mod/sin/wyvern/bounty/PlayerBounty.java | 26 +++---- .../sin/wyvern/mastercraft/Mastercraft.java | 70 +------------------ 17 files changed, 151 insertions(+), 181 deletions(-) diff --git a/build.gradle b/build.gradle index fe37c50..d55467e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group "mod.sin" -version "1.1" +version "1.2" repositories { mavenCentral() @@ -11,7 +11,7 @@ repositories { } dependencies { - compile 'org.gotti.wurmunlimited:server-modlauncher:0.37' + compile 'org.gotti.wurmunlimited:server-modlauncher:0.39-beta1' compile 'com.github.Sindusk:sindusklibrary:v1.7' compile 'com.github.Sindusk:DiscordRelay:v1.2' compile 'com.github.Sindusk:DUSKombat:v1.0' diff --git a/src/main/java/mod/sin/creatures/Reaper.java b/src/main/java/mod/sin/creatures/Reaper.java index a8e6b14..89d4ec1 100644 --- a/src/main/java/mod/sin/creatures/Reaper.java +++ b/src/main/java/mod/sin/creatures/Reaper.java @@ -2,6 +2,7 @@ package mod.sin.creatures; import com.wurmonline.server.bodys.BodyTemplate; import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTemplate; import com.wurmonline.server.combat.ArmourTypes; import com.wurmonline.server.items.Materials; import com.wurmonline.server.skills.SkillList; @@ -30,25 +31,25 @@ public class Reaper implements ModCreature, CreatureTypes { "The reaper, here to claim the souls of the living.", "model.creature.gmdark", types, BodyTemplate.TYPE_HUMAN, (short) 20, (byte) 0, (short) 350, (short) 100, (short) 60, "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", - 0.10f, 35.0f, 45.0f, 22.0f, 40.0f, 0.0f, 1.0f, 500, + 0.09f, 37.0f, 48.0f, 25.0f, 45.0f, 0.0f, 1.0f, 500, new int[]{}, 20, 70, Materials.MATERIAL_MEAT_HUMANOID); - builder.skill(SkillList.BODY_STRENGTH, 60.0f); + builder.skill(SkillList.BODY_STRENGTH, 70.0f); builder.skill(SkillList.BODY_STAMINA, 70.0f); builder.skill(SkillList.BODY_CONTROL, 60.0f); builder.skill(SkillList.MIND_LOGICAL, 35.0f); builder.skill(SkillList.MIND_SPEED, 45.0f); builder.skill(SkillList.SOUL_STRENGTH, 80.0f); builder.skill(SkillList.SOUL_DEPTH, 80.0f); - builder.skill(SkillList.WEAPONLESS_FIGHTING, 80.0f); - builder.skill(SkillList.GROUP_FIGHTING, 80.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 85.0f); + builder.skill(SkillList.GROUP_FIGHTING, 85.0f); builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); builder.handDamString("slice"); builder.kickDamString("reap"); builder.maxAge(200); - builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); - builder.baseCombatRating(55.0f); + builder.armourType(ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON); + builder.baseCombatRating(58.0f); builder.combatDamageType(Wound.TYPE_PIERCE); builder.maxGroupAttackSize(100); diff --git a/src/main/java/mod/sin/items/AffinityOrb.java b/src/main/java/mod/sin/items/AffinityOrb.java index 956fd5d..b9ed7d0 100644 --- a/src/main/java/mod/sin/items/AffinityOrb.java +++ b/src/main/java/mod/sin/items/AffinityOrb.java @@ -20,10 +20,9 @@ public class AffinityOrb implements ItemTypes, MiscConstants { itemBuilder.name(name, "affinity orbs", "A valuable orb that infuses the user with hidden knowledge."); itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); itemBuilder.itemTypes(new short[]{ - ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_NODROP, ItemTypes.ITEM_TYPE_FULLPRICE, - ItemTypes.ITEM_TYPE_NOSELLBACK, - ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + ItemTypes.ITEM_TYPE_NOSELLBACK }); itemBuilder.imageNumber((short) 919); itemBuilder.behaviourType((short) 1); diff --git a/src/main/java/mod/sin/items/EternalOrb.java b/src/main/java/mod/sin/items/EternalOrb.java index 6bbda77..261971e 100644 --- a/src/main/java/mod/sin/items/EternalOrb.java +++ b/src/main/java/mod/sin/items/EternalOrb.java @@ -33,7 +33,7 @@ public class EternalOrb implements ItemTypes, MiscConstants { itemBuilder.difficulty(5.0f); itemBuilder.weightGrams(500); itemBuilder.material(Materials.MATERIAL_CRYSTAL); - itemBuilder.value(200000); + itemBuilder.value(100000); itemBuilder.isTraded(true); ItemTemplate template = itemBuilder.build(); diff --git a/src/main/java/mod/sin/items/EternalReservoir.java b/src/main/java/mod/sin/items/EternalReservoir.java index c5936a9..4ae5108 100644 --- a/src/main/java/mod/sin/items/EternalReservoir.java +++ b/src/main/java/mod/sin/items/EternalReservoir.java @@ -29,6 +29,7 @@ public class EternalReservoir implements ItemTypes, MiscConstants { ItemTypes.ITEM_TYPE_NOTAKE, ItemTypes.ITEM_TYPE_DECORATION, ItemTypes.ITEM_TYPE_USE_GROUND_ONLY, + ItemTypes.ITEM_TYPE_HASDATA, ItemTypes.ITEM_TYPE_NEVER_SHOW_CREATION_WINDOW_OPTION, ItemTypes.ITEM_TYPE_NOT_MISSION }); diff --git a/src/main/java/mod/sin/weapons/BattleYoyo.java b/src/main/java/mod/sin/weapons/BattleYoyo.java index 4b9fab9..68e3d20 100644 --- a/src/main/java/mod/sin/weapons/BattleYoyo.java +++ b/src/main/java/mod/sin/weapons/BattleYoyo.java @@ -39,7 +39,7 @@ public class BattleYoyo implements ItemTypes, MiscConstants { itemBuilder.behaviourType((short) 35); itemBuilder.combatDamage(35); itemBuilder.decayTime(Long.MAX_VALUE); - itemBuilder.dimensions(5, 10, 80); + itemBuilder.dimensions(5, 10, 20); itemBuilder.primarySkill(SkillList.YOYO); itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); itemBuilder.modelName("model.toy.yoyo."); diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index d04f88c..b5cfdb8 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -84,6 +84,9 @@ public class Arena { } public static void sendHotaMessage(String message){ + if (SupplyDepots.host != null) { + MiscChanges.sendGlobalFreedomChat(SupplyDepots.host, message, 200, 200, 200); + } DiscordRelay.sendToDiscord("arena", message, true); } @@ -114,18 +117,9 @@ public class Arena { } statue.setAuxData((byte)winStreak); } - int r = winStreak * 50 & 255; - int g = 0; - int b = 0; - if (winStreak > 5 && winStreak < 16) { - r = 0; - } - if (winStreak > 5 && winStreak < 20) { - g = winStreak * 50 & 255; - } - if (winStreak > 5 && winStreak < 30) { - b = winStreak * 50 & 255; - } + int r = (winStreak + Server.rand.nextInt(5)) * 50 & 255; + int g = (winStreak + Server.rand.nextInt(5)) * 80 & 255; + int b = (winStreak + Server.rand.nextInt(5)) * 120 & 255; statue.setColor(WurmColor.createColor(r, g, b)); statue.getColor(); Zone z = Zones.getZone(statue.getTileX(), statue.getTileY(), true); @@ -180,16 +174,16 @@ public class Arena { statue.insertItem(token, true); i--; } - // Add 3-5 seryll lumps of medium ql - i = 3+Server.rand.nextInt(3); // 3-5 lumps + // Add 4-6 seryll lumps of medium ql + i = 4+Server.rand.nextInt(3); // 4-6 lumps while(i > 0){ Item seryll = ItemFactory.createItem(ItemList.seryllBar, 40f+(60f*Server.rand.nextFloat()), null); statue.insertItem(seryll, true); i--; } - // Add 2-4 silver - long iron = 20000; // 2 silver - iron += Server.rand.nextInt(20000); // add up to 2 more silver + // Add 3-6 silver + long iron = 30000; // 3 silver + iron += Server.rand.nextInt(30000); // add up to 3 more silver Item[] coins = Economy.getEconomy().getCoinsFor(iron); for(Item coin : coins){ statue.insertItem(coin, true); @@ -481,12 +475,6 @@ public class Arena { String desc3 = Descriptor.ofMethod(CtClass.voidType, params3); replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER && !lVehicle.isLocked();"; Util.instrumentDescribed(thisClass, ctCreature, "setVehicle", desc3, "isThisAChaosServer", replace); - - // - Allow managing animals on Arena - // - CtClass ctManageMenu = classPool.get("com.wurmonline.server.behaviours.ManageMenu"); - replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctManageMenu, "getBehavioursFor", "isThisAPvpServer", replace); - Util.instrumentDeclared(thisClass, ctManageMenu, "action", "isThisAPvpServer", replace); // - Multiply mine door bash damage by 3 on Arena - // CtClass ctTerraforming = classPool.get("com.wurmonline.server.behaviours.Terraforming"); diff --git a/src/main/java/mod/sin/wyvern/Crystals.java b/src/main/java/mod/sin/wyvern/Crystals.java index 3dba1c3..4539895 100644 --- a/src/main/java/mod/sin/wyvern/Crystals.java +++ b/src/main/java/mod/sin/wyvern/Crystals.java @@ -7,6 +7,7 @@ import com.wurmonline.server.items.ItemSpellEffects; import com.wurmonline.server.items.NotOwnedException; import com.wurmonline.server.skills.NoSuchSkillException; import com.wurmonline.server.skills.SkillList; +import com.wurmonline.server.spells.SpellEffect; import com.wurmonline.shared.constants.Enchants; import mod.sin.items.ChaosCrystal; import mod.sin.items.EnchantersCrystal; @@ -63,7 +64,18 @@ public class Crystals { e.printStackTrace(); } if(target.getSpellEffects() != null){ - diff += target.getSpellEffects().getEffects().length*10; + for (SpellEffect eff : target.getSpellEffects().getEffects()){ + // Double power-based penalty for BotD + if (eff.type == Enchants.BUFF_BLESSINGDARK){ + diff += eff.getPower() * 0.1f; + } + if (eff.type != Enchants.BUFF_BLOODTHIRST) { + diff += eff.getPower() * 0.1f; + }else{ + // Bloodthirst penalty (1 per 1000 power) + diff += eff.getPower() * 0.001f; + } + } } return diff; } diff --git a/src/main/java/mod/sin/wyvern/EconomicChanges.java b/src/main/java/mod/sin/wyvern/EconomicChanges.java index 832df19..eae1670 100644 --- a/src/main/java/mod/sin/wyvern/EconomicChanges.java +++ b/src/main/java/mod/sin/wyvern/EconomicChanges.java @@ -92,6 +92,15 @@ public class EconomicChanges { replace = "$_ = "+EconomicChanges.class.getName()+".getNewVillageTiles(vill.getNumTiles());"; Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "getNumTiles", replace); + Util.setReason("Disable upkeep on arena for now until a fix can be found."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + //replace = "$_ = false;"; + Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "isUpkeep", replace); + /*Util.setReason("Allow players to get a full deed refund."); replace = "{ return "+EconomicChanges.class.getName()+".getNewDisbandMoney(this, this.getVillage()); }"; Util.setBodyDeclared(thisClass, ctGuardPlan, "getDisbandMoneyLeft", replace);*/ @@ -114,8 +123,8 @@ public class EconomicChanges { replace = "$1 = "+EconomicChanges.class.getName()+".getNewShopDiff($0, $1, $0.shopDiff);"; Util.insertBeforeDeclared(thisClass, ctTrade, "addShopDiff", replace); - } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { - throw new HookException(e); - } + } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { + throw new HookException(e); + } } } diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index ce40779..5a5a245 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -6,10 +6,10 @@ import java.lang.reflect.Method; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.logging.Logger; import com.wurmonline.server.Servers; +import com.wurmonline.server.combat.ArmourTemplate; import mod.sin.items.caches.*; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -17,7 +17,6 @@ import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; import org.gotti.wurmunlimited.modsupport.actions.ModActions; import com.wurmonline.server.behaviours.ActionEntry; -import com.wurmonline.server.combat.Armour; import com.wurmonline.server.combat.Weapon; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.items.Item; @@ -116,7 +115,6 @@ public class ItemMod { CORPSE_DECORATION.createTemplate(); DEPTH_DRILL.createTemplate(); DISINTEGRATION_ROD.createTemplate(); - //ELECTRUM_LUMP.createTemplate(); ENCHANT_ORB.createTemplate(); ETERNAL_ORB.createTemplate(); EVISCERATOR.createTemplate(); @@ -200,7 +198,6 @@ public class ItemMod { //COIN_DECORATION.initCreationEntry(); //CORPSE_DECORATION.initCreationEntry(); DEPTH_DRILL.initCreationEntry(); - //ELECTRUM_LUMP.initCreationEntry(); EVISCERATOR.initCreationEntry(); KNUCKLES.initCreationEntry(); MASS_STORAGE_UNIT.initCreationEntry(); @@ -227,47 +224,28 @@ public class ItemMod { GLIMMERSCALE_HOSE.initCreationEntry(); GLIMMERSCALE_SLEEVE.initCreationEntry(); GLIMMERSCALE_VEST.initCreationEntry();*/ - - // Allow sickle heads from steel & moon metals: - // [3/28/18] Disabled: Implemented in WU 1.6. - /*CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.steelBar, - ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar, - ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar, - ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar, - ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); - // Allow steel staff to be created from moon metals: - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar, - ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES); - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar, - ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES); - CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar, - ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES);*/ } public static void createCustomArmours(){ try { logger.info("Beginning custom armour creation."); - Map armours = ReflectionUtil.getPrivateField(null, ReflectionUtil.getField(Armour.class, "armours")); - armours.put(SpectralBoot.templateId, new Armour(SpectralBoot.templateId, 0.002f, 0.3f)); - armours.put(SpectralCap.templateId, new Armour(SpectralCap.templateId, 0.003f, 0.3f)); - armours.put(SpectralGlove.templateId, new Armour(SpectralGlove.templateId, 0.002f, 0.3f)); - armours.put(SpectralHose.templateId, new Armour(SpectralHose.templateId, 0.0075f, 0.3f)); - armours.put(SpectralJacket.templateId, new Armour(SpectralJacket.templateId, 0.01f, 0.3f)); - armours.put(SpectralSleeve.templateId, new Armour(SpectralSleeve.templateId, 0.004f, 0.3f)); + new ArmourTemplate(SpectralBoot.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.002f); + new ArmourTemplate(SpectralCap.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.003f); + new ArmourTemplate(SpectralGlove.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.002f); + new ArmourTemplate(SpectralHose.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.0075f); + new ArmourTemplate(SpectralJacket.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.01f); + new ArmourTemplate(SpectralSleeve.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON, 0.004f); - armours.put(GlimmerscaleBoot.templateId, new Armour(GlimmerscaleBoot.templateId, 0.002f, 0.15f)); - armours.put(GlimmerscaleGlove.templateId, new Armour(GlimmerscaleGlove.templateId, 0.001f, 0.15f)); - armours.put(GlimmerscaleHelmet.templateId, new Armour(GlimmerscaleHelmet.templateId, 0.008f, 0.15f)); - armours.put(GlimmerscaleHose.templateId, new Armour(GlimmerscaleHose.templateId, 0.05f, 0.15f)); - armours.put(GlimmerscaleSleeve.templateId, new Armour(GlimmerscaleSleeve.templateId, 0.008f, 0.15f)); - armours.put(GlimmerscaleVest.templateId, new Armour(GlimmerscaleVest.templateId, 0.05f, 0.15f)); + new ArmourTemplate(GlimmerscaleBoot.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.002f); + new ArmourTemplate(GlimmerscaleGlove.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.001f); + new ArmourTemplate(GlimmerscaleHelmet.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.008f); + new ArmourTemplate(GlimmerscaleHose.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.05f); + new ArmourTemplate(GlimmerscaleSleeve.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.008f); + new ArmourTemplate(GlimmerscaleVest.templateId, ArmourTemplate.ARMOUR_TYPE_SCALE_DRAGON, 0.05f); //ReflectionUtil.setPrivateField(null, ReflectionUtil.getField(Armour.class, "armours"), armours); - } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + } catch (IllegalArgumentException | ClassCastException e) { e.printStackTrace(); } } @@ -277,7 +255,7 @@ public class ItemMod { logger.info("Beginning custom weapon creation."); new Weapon(BattleYoyo.templateId, 6.85f, 3.85f, 0.008f, 2, 2, 0.0f, 0d); new Weapon(Club.templateId, 8.1f, 4.5f, 0.002f, 3, 3, 0.4f, 0.5d); - new Weapon(Knuckles.templateId, 3.6f, 2.2f, 0.002f, 1, 1, 0.2f, 0.5d); + new Weapon(Knuckles.templateId, 3.7f, 2.2f, 0.002f, 1, 1, 0.2f, 0.5d); new Weapon(Warhammer.templateId, 9.40f, 5.6f, 0.008f, 4, 3, 1f, 0d); //new Weapon(ItemList.stoneChisel, 50f, 1f, 0.5f, 8, 1, 3f, -5f); // Titan weaponry @@ -360,6 +338,10 @@ public class ItemMod { ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "value"), 100000); ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "fullprice"), true); + // Resurrection Stones to 2 silver instead of 5 silver. + ItemTemplate resurrectionStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.resurrectionStone); + ReflectionUtil.setPrivateField(resurrectionStone, ReflectionUtil.getField(resurrectionStone.getClass(), "value"), 20000); + // Set transmutation rod to 2 gold instead of 50 silver. //ItemTemplate transmutationRod = ItemTemplateFactory.getInstance().getTemplate(668); //ReflectionUtil.setPrivateField(transmutationRod, ReflectionUtil.getField(transmutationRod.getClass(), "value"), 2000000); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 798b0c1..51e830d 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -11,6 +11,7 @@ import com.wurmonline.server.items.SimpleCreationEntry; import com.wurmonline.server.players.Player; import com.wurmonline.server.players.PlayerInfo; import com.wurmonline.server.players.PlayerInfoFactory; +import com.wurmonline.server.players.Titles; import com.wurmonline.server.skills.Skill; import com.wurmonline.server.skills.SkillList; import com.wurmonline.server.villages.Village; @@ -33,10 +34,7 @@ import org.nyxcode.wurm.discordrelay.DiscordRelay; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import java.util.logging.Logger; public class MiscChanges { @@ -99,7 +97,9 @@ public class MiscChanges { } catch (NoSuchCreatureException ignored) {} } - Players.getInstance().broadCastDeathInfo(player, attackerString.toString()); + if(!attackerString.toString().isEmpty()) { + Players.getInstance().broadCastDeathInfo(player, attackerString.toString()); + } } public static void broadCastDeaths(Creature player, String slayers){ @@ -295,6 +295,20 @@ public class MiscChanges { } return 0; } + + public static Titles.Title[] cleanTitles(Titles.Title[] titles){ + ArrayList arrTitles = new ArrayList<>(); + for(Titles.Title title : titles){ + logger.info("Checking title "+title); + if(title != null){ + logger.info("Title "+title.getName()+" is valid."); + arrTitles.add(title); + }else{ + logger.info("Title invalid. Discarding."); + } + } + return arrTitles.toArray(new Titles.Title[0]); + } public static void preInit(){ try{ @@ -311,7 +325,7 @@ public class MiscChanges { "Website/Maps: https://www.sarcasuals.com/", "Server Discord: https://discord.gg/r8QNXAC", "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", - "Server Wiki/Documentation: https://docs.google.com/document/d/1GeaygilS-Z-d1TuGB7awOe9sJNV4o5BTZw_a2ATJy98"}; + "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing"}; StringBuilder str = new StringBuilder("{" + " com.wurmonline.server.Message mess;"); for (String anInfoTabLine : infoTabLine) { @@ -659,13 +673,13 @@ public class MiscChanges { "$_ = $proceed($$);"; Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace); - Util.setReason("Fix intrateleport block bug."); + /*Util.setReason("Fix intrateleport block bug."); replace = "if($6.contains(\"blocked\")){" + " logger.info(\"Detected a blocked movement, resetting position back to old.\");" + " $1 = $0.getMovementScheme().xOld;" + " $2 = $0.getMovementScheme().yOld;" + "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "intraTeleport", replace); + Util.insertBeforeDeclared(thisClass, ctCreature, "intraTeleport", replace);*/ Util.setReason("Allow royal smith to improve smithing items faster."); replace = "if("+MiscChanges.class.getName()+".royalSmithImprove($1, improve)){" + @@ -855,6 +869,17 @@ public class MiscChanges { "}"; Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); + /*Util.setReason("Fix title NPE from sorting."); + CtClass ctTitleCompoundQuestion = classPool.get("com.wurmonline.server.questions.TitleCompoundQuestion"); + replace = "titles = "+MiscChanges.class.getName()+".cleanTitles(titles);" + + "int i = 0;" + + "while(i < titles.length){" + + " logger.info(\"Title: \"+titles[i]);" + + " i++;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctTitleCompoundQuestion, "sendQuestion", "sort", replace);*/ + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index 8c4d056..8e2167f 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -30,6 +30,7 @@ public class PlayerTitles { return ""; } public static void awardCustomTitles(Player p){ + /* Disabled until a fix for title implementations is done. String name = p.getName(); if(donatorTitles.contains(name)){ Titles.Title donator = Titles.Title.getTitle(800); @@ -38,7 +39,7 @@ public class PlayerTitles { if(customTitles.containsKey(name)){ Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name)); p.addTitle(customTitle); - } + }*/ } public static void preInit(){ // Donations diff --git a/src/main/java/mod/sin/wyvern/SupplyDepots.java b/src/main/java/mod/sin/wyvern/SupplyDepots.java index 5bff79a..48b113f 100644 --- a/src/main/java/mod/sin/wyvern/SupplyDepots.java +++ b/src/main/java/mod/sin/wyvern/SupplyDepots.java @@ -223,7 +223,7 @@ public class SupplyDepots { } public static void giveCacheReward(Creature performer){ Item inv = performer.getInventory(); - Item enchantOrb = ItemUtil.createEnchantOrb(40f+(Math.min(Server.rand.nextFloat()*40f, Server.rand.nextFloat()*40f))); + Item enchantOrb = ItemUtil.createEnchantOrb(60f+(Math.min(Server.rand.nextFloat()*60f, Server.rand.nextFloat()*60f))); if(enchantOrb != null) { inv.insertItem(enchantOrb); } @@ -232,16 +232,16 @@ public class SupplyDepots { int[] cacheIds = { ArmourCache.templateId, ArtifactCache.templateId, - CrystalCache.templateId, CrystalCache.templateId, + CrystalCache.templateId, CrystalCache.templateId, CrystalCache.templateId, DragonCache.templateId, DragonCache.templateId, GemCache.templateId, MoonCache.templateId, MoonCache.templateId, RiftCache.templateId, TreasureMapCache.templateId }; - int i = 2+Server.rand.nextInt(2); // 2-3 caches. + int i = 3+Server.rand.nextInt(2); // 2-3 caches. while(i > 0){ - Item cache = ItemFactory.createItem(cacheIds[Server.rand.nextInt(cacheIds.length)], 20f+(60f*Server.rand.nextFloat()), ""); + Item cache = ItemFactory.createItem(cacheIds[Server.rand.nextInt(cacheIds.length)], 40f+(50f*Server.rand.nextFloat()), ""); inv.insertItem(cache, true); i--; } diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 2517b7f..318020b 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -144,7 +144,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Bloodlust.preInit(); AntiCheat.preInit(); Mastercraft.preInit(); - Mastercraft.addNewTitles(); + //Mastercraft.addNewTitles(); SupplyDepots.preInit(); KeyEvent.preInit(); //GemAugmentation.preInit(); diff --git a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java index a9c7896..854f88d 100644 --- a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java +++ b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java @@ -524,6 +524,19 @@ public class MethodsBestiary { e.printStackTrace(); } } + + private static void setSkill(int templateId, int skillId, float value){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + Skills skills = ReflectionUtil.getPrivateField(template, ReflectionUtil.getField(template.getClass(), "skills")); + skills.learnTemp(skillId, value); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "skills"), skills); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } private static void setWorgFields(int templateId) { try { @@ -594,18 +607,18 @@ public class MethodsBestiary { setUniqueTypes(CreatureTemplate.CYCLOPS_CID); // Dragon natural armour increases: - setNaturalArmour(CreatureTemplate.DRAGON_BLUE_CID, 0.035f); - setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.035f); - setNaturalArmour(CreatureTemplate.DRAGON_BLACK_CID, 0.045f); - setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.035f); + setNaturalArmour(CreatureTemplate.DRAGON_BLUE_CID, 0.025f); + setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.025f); + setNaturalArmour(CreatureTemplate.DRAGON_BLACK_CID, 0.035f); + setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.025f); // Drake natural armour increases: - setNaturalArmour(CreatureTemplate.DRAKE_RED_CID, 0.065f); - setNaturalArmour(CreatureTemplate.DRAKE_BLUE_CID, 0.065f); - setNaturalArmour(CreatureTemplate.DRAKE_WHITE_CID, 0.075f); - setNaturalArmour(CreatureTemplate.DRAKE_GREEN_CID, 0.065f); - setNaturalArmour(CreatureTemplate.DRAKE_BLACK_CID, 0.055f); + setNaturalArmour(CreatureTemplate.DRAKE_RED_CID, 0.055f); + setNaturalArmour(CreatureTemplate.DRAKE_BLUE_CID, 0.055f); + setNaturalArmour(CreatureTemplate.DRAKE_WHITE_CID, 0.065f); + setNaturalArmour(CreatureTemplate.DRAKE_GREEN_CID, 0.055f); + setNaturalArmour(CreatureTemplate.DRAKE_BLACK_CID, 0.045f); // Goblin leader natural armour increase: - setNaturalArmour(CreatureTemplate.GOBLIN_LEADER_CID, 0.055f); + setNaturalArmour(CreatureTemplate.GOBLIN_LEADER_CID, 0.045f); // Worg armour reduction on Arena if(Servers.localServer.PVPSERVER) { @@ -630,6 +643,9 @@ public class MethodsBestiary { // Set worg fields setWorgFields(CreatureTemplate.WORG_CID); + + // Set skills for certain creatures + setSkill(CreatureTemplate.CYCLOPS_CID, SkillList.GROUP_FIGHTING, 80.0f); } protected static void sendParticleEffect(Communicator comm, long creatureId, Creature creature, String particle, float duration){ diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java index 5a97db2..ba3fd0d 100644 --- a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -1,12 +1,5 @@ package mod.sin.wyvern.bounty; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.logging.Logger; - import com.wurmonline.server.FailedException; import com.wurmonline.server.Server; import com.wurmonline.server.Servers; @@ -17,9 +10,6 @@ import com.wurmonline.server.items.ItemFactory; import com.wurmonline.server.items.ItemTemplate; import com.wurmonline.server.items.NoSuchTemplateException; import com.wurmonline.server.players.Player; -import com.wurmonline.server.players.Titles.Title; -import com.wurmonline.server.skills.NoSuchSkillException; -import com.wurmonline.server.skills.SkillList; import mod.piddagoras.duskombat.DamageEngine; import mod.sin.armour.SpectralHide; import mod.sin.creatures.Reaper; @@ -27,9 +17,19 @@ import mod.sin.creatures.SpectralDrake; import mod.sin.items.AffinityOrb; import mod.sin.items.caches.RiftCache; import mod.sin.items.caches.TitanCache; -import mod.sin.wyvern.*; +import mod.sin.wyvern.Bounty; +import mod.sin.wyvern.MiscChanges; +import mod.sin.wyvern.RareSpawns; +import mod.sin.wyvern.Titans; import mod.sin.wyvern.util.ItemUtil; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.logging.Logger; + public class PlayerBounty { public static final Logger logger = Logger.getLogger(PlayerBounty.class.getName()); protected static final Random random = new Random(); @@ -109,7 +109,7 @@ public class PlayerBounty { fightStrength = "legendary"; } player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly."); - player.addTitle(Title.getTitle(701)); + //player.addTitle(Title.getTitle(701)); }catch (NoSuchTemplateException | FailedException e) { e.printStackTrace(); } @@ -148,7 +148,7 @@ public class PlayerBounty { player.getInventory().insertItem(riftCache, true); } if(Titans.isTitan(mob)){ - player.addTitle(Title.getTitle(700)); + //player.addTitle(Title.getTitle(700)); Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f, mob.getName()); player.getInventory().insertItem(affinityOrb, true); Item titanCache = ItemFactory.createItem(TitanCache.templateId, 99f, mob.getName()); diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java index af11de8..74bce1c 100644 --- a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java +++ b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java @@ -72,9 +72,9 @@ public class Mastercraft { try { ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title"); // GM/Developer Titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 500, "Game Master", "Game Master", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Developer", 501, "Developer", "Developer", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pet_Me", 502, "Pet Me", "Pet Me", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 2500, "Game Master", "Game Master", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Developer", 2501, "Developer", "Developer", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pet_Me", 2502, "Pet Me", "Pet Me", -1, "NORMAL"); // Troll Titles ExtendTitleEnum.getSingletonInstance().addExtendEntry("Macro_King", 550, "Macro King", "Macro King", -1, "NORMAL"); @@ -114,70 +114,6 @@ public class Mastercraft { ExtendTitleEnum.getSingletonInstance().addExtendEntry("Piratemax_Slave", 810, "Slave", "Slave", -1, "NORMAL"); ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eltacolad_TrueTaco", 811, "The One True Taco", "The One True Taco", -1, "NORMAL"); - // Characteristic Titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Normal", 1000, "Logical", "Logical", 100, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Minor", 1001, "Intelligent", "Intelligent", 100, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Master", 1002, "Brilliant", "Brilliant", 100, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Legendary", 1003, "Mentalist", "Mentalist", 100, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Normal", 1004, "Keen", "Keen", 101, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Minor", 1005, "Thinker", "Thinker", 101, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Master", 1006, "Clever", "Clever", 101, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Legendary", 1007, "Mind Over Matter", "Mind Over Matter", 101, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Normal", 1008, "Strong", "Strong", 102, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Minor", 1009, "Fortified", "Fortified", 102, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Master", 1010, "Unyielding", "Unyielding", 102, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Legendary", 1011, "Force of Nature", "Force of Nature", 102, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Normal", 1012, "Enduring", "Enduring", 103, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Minor", 1013, "Resilient", "Resilient", 103, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Master", 1014, "Vigorous", "Vigorous", 103, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Legendary", 1015, "Unstoppable", "Unstoppable", 103, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Normal", 1016, "Nimble", "Nimble", 104, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Minor", 1017, "Deft", "Deft", 104, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Master", 1018, "Skillful", "Skillful", 104, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Legendary", 1019, "Manipulator", "Manipulator", 104, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Normal", 1020, "Spirited", "Spirited", 105, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Minor", 1021, "Diviner", "Diviner", 105, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Master", 1022, "Anima", "Anima", 105, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Legendary", 1023, "Prophet", "Prophet", 105, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Normal", 1024, "Sensible", "Sensible", 106, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Minor", 1025, "Medium", "Medium", 106, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Master", 1026, "Spiritual", "Spiritual", 106, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Legendary", 1027, "Planewalker", "Planewalker", 106, "LEGENDARY"); - - // Skill Titles (Full) - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Normal", 1100, "Acolyte", "Acolyte", 10090, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Minor", 1101, "Disciple", "Disciple", 10090, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Master", 1102, "Monk", "Monk", 10090, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Legendary", 1103, "Sensei", "Sensei", 10090, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Normal", 1104, "Mower", "Mower", 10047, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Minor", 1105, "Harvester", "Harvester", 10047, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Master", 1106, "Scythian", "Scythian", 10047, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Legendary", 1107, "Reaper", "Reaper", 10047, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Normal", 1108, "Resistant", "Resistant", 10054, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Minor", 1109, "Guardian", "Guardian", 10054, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Master", 1110, "Bulwark", "Bulwark", 10054, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Legendary", 1111, "Unbreakable", "Unbreakable", 10054, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Normal", 1112, "Angry", "Angry", 10053, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Minor", 1113, "Violent", "Violent", 10053, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Master", 1114, "Battleborn", "Battleborn", 10053, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Legendary", 1115, "Warmonger", "Warmonger", 10053, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Normal", 1116, "Infantry", "Infantry", 10055, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Minor", 1117, "Marauder", "Marauder", 10055, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Master", 1118, "Gladiator", "Gladiator", 10055, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Legendary", 1119, "Templar", "Templar", 10055, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Normal", 1120, "Scrapper", "Scrapper", 10052, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Minor", 1121, "Brawler", "Brawler", 10052, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Master", 1122, "Boxer", "Boxer", 10052, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Legendary", 1123, "Martial Artist", "Martial Artist", 10052, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BladesSmithing_Normal", 1124, "Bladesmith", "Bladesmith", SkillList.SMITHING_WEAPON_BLADES, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BladesSmithing_Minor", 1125, "Renowned Bladesmith", "Renowned Bladesmith", SkillList.SMITHING_WEAPON_BLADES, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BladesSmithing_Master", 1126, "Master Bladesmith", "Master Bladesmith", SkillList.SMITHING_WEAPON_BLADES, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("BladesSmithing_Legendary", 1127, "Legendary Bladesmith", "Legendary Bladesmith", SkillList.SMITHING_WEAPON_BLADES, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("HeadSmithing_Normal", 1128, "Headsmither", "Headsmither", SkillList.SMITHING_WEAPON_HEADS, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("HeadSmithing_Minor", 1129, "Renowned Headsmither", "Renowned Headsmither", SkillList.SMITHING_WEAPON_HEADS, "MINOR"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("HeadSmithing_Master", 1130, "Master Headsmither", "Master Headsmither", SkillList.SMITHING_WEAPON_HEADS, "MASTER"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("HeadSmithing_Legendary", 1131, "Legendary Headsmither", "Legendary Headsmither", SkillList.SMITHING_WEAPON_HEADS, "LEGENDARY"); - // Skill Titles (100) ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archery_Legendary", 1500, "Legendary Marksman", "Legendary Marksman", 1030, "LEGENDARY"); ExtendTitleEnum.getSingletonInstance().addExtendEntry("Body_Legendary", 1501, "Hercules", "Hercules", 1, "LEGENDARY"); From 550ef20925530689a5f59a58e1be3f0e8cc4e053 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Fri, 22 Mar 2019 11:56:31 -0400 Subject: [PATCH 2/8] Update to Wurm Unlimited 1.9 and latest code --- build.gradle | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../server/questions/AffinityOrbQuestion.java | 1 - .../questions/BookConversionQuestion.java | 2 +- .../mod/sin/actions/ArenaEscapeAction.java | 2 +- .../mod/sin/actions/ArenaTeleportAction.java | 9 +- .../sin/actions/items/EternalOrbAction.java | 9 +- src/main/java/mod/sin/creatures/Charger.java | 2 +- src/main/java/mod/sin/items/AffinityOrb.java | 1 - src/main/java/mod/sin/wyvern/Arena.java | 25 +- src/main/java/mod/sin/wyvern/Bloodlust.java | 6 +- src/main/java/mod/sin/wyvern/Bounty.java | 20 +- .../java/mod/sin/wyvern/CombatChanges.java | 43 ++-- .../java/mod/sin/wyvern/DeityChanges.java | 21 +- .../java/mod/sin/wyvern/EconomicChanges.java | 8 +- src/main/java/mod/sin/wyvern/ItemMod.java | 16 +- src/main/java/mod/sin/wyvern/MiscChanges.java | 46 +++- .../java/mod/sin/wyvern/MountedChanges.java | 10 +- .../java/mod/sin/wyvern/PlayerTitles.java | 215 ++++++++++++++++-- .../java/mod/sin/wyvern/QualityOfLife.java | 4 +- src/main/java/mod/sin/wyvern/RareSpawns.java | 4 +- src/main/java/mod/sin/wyvern/Titans.java | 14 +- src/main/java/mod/sin/wyvern/WyvernMods.java | 4 +- .../sin/wyvern/bestiary/MethodsBestiary.java | 29 ++- .../mod/sin/wyvern/bounty/LootBounty.java | 3 + .../mod/sin/wyvern/bounty/PlayerBounty.java | 9 +- .../sin/wyvern/mastercraft/Mastercraft.java | 5 +- 27 files changed, 397 insertions(+), 119 deletions(-) diff --git a/build.gradle b/build.gradle index d55467e..772e4e9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group "mod.sin" -version "1.2" +version "1.3" repositories { mavenCentral() @@ -11,8 +11,8 @@ repositories { } dependencies { - compile 'org.gotti.wurmunlimited:server-modlauncher:0.39-beta1' - compile 'com.github.Sindusk:sindusklibrary:v1.7' + compile 'org.gotti.wurmunlimited:server-modlauncher:0.43-beta1' + compile 'com.github.Sindusk:sindusklibrary:v2.2' compile 'com.github.Sindusk:DiscordRelay:v1.2' compile 'com.github.Sindusk:DUSKombat:v1.0' compile 'com.github.Sindusk:TreasureHunting:1.1.4' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff2a712..6860bb2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip diff --git a/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java b/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java index 9af6961..f3dff36 100644 --- a/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/AffinityOrbQuestion.java @@ -39,7 +39,6 @@ public class AffinityOrbQuestion extends Question { //logger.info("Converting "+player.getName()+" to " + Deities.getDeityName(deity)); String skillName = SkillSystem.getNameFor(skillNum); logger.info("Adding affinity for skill "+skillName+" to "+player.getName()); - Items.destroyItem(affinityOrb.getWurmId()); Affinity[] affs = Affinities.getAffinities(player.getWurmId()); boolean found = false; diff --git a/src/main/java/com/wurmonline/server/questions/BookConversionQuestion.java b/src/main/java/com/wurmonline/server/questions/BookConversionQuestion.java index b97e21e..3a05409 100644 --- a/src/main/java/com/wurmonline/server/questions/BookConversionQuestion.java +++ b/src/main/java/com/wurmonline/server/questions/BookConversionQuestion.java @@ -40,7 +40,7 @@ public class BookConversionQuestion extends Question { Deity d = Deities.getDeity(deity); p.setDeity(d); p.setPriest(true); - if(d.hateGod){ + if(d.isHateGod()){ p.setAlignment(-Math.abs(p.getAlignment())); }else{ p.setAlignment(Math.abs(p.getAlignment())); diff --git a/src/main/java/mod/sin/actions/ArenaEscapeAction.java b/src/main/java/mod/sin/actions/ArenaEscapeAction.java index 289ff19..3d16d09 100644 --- a/src/main/java/mod/sin/actions/ArenaEscapeAction.java +++ b/src/main/java/mod/sin/actions/ArenaEscapeAction.java @@ -38,7 +38,6 @@ public class ArenaEscapeAction implements ModAction { ModActions.registerAction(actionEntry); } - @Override public BehaviourProvider getBehaviourProvider() { @@ -93,6 +92,7 @@ public class ArenaEscapeAction implements ModAction { } if(counter == 1.0f){ performer.getCommunicator().sendNormalServerMessage("You prepare your body and mind to transfer to another realm."); + performer.playAnimation("meditate", false); act.setTimeLeft(1800); performer.sendActionControl("Preparing", true, act.getTimeLeft()); }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ diff --git a/src/main/java/mod/sin/actions/ArenaTeleportAction.java b/src/main/java/mod/sin/actions/ArenaTeleportAction.java index 3c19264..1f427cf 100644 --- a/src/main/java/mod/sin/actions/ArenaTeleportAction.java +++ b/src/main/java/mod/sin/actions/ArenaTeleportAction.java @@ -86,18 +86,19 @@ public class ArenaTeleportAction implements ModAction { } if(counter == 1.0f){ performer.getCommunicator().sendNormalServerMessage("You sit and begin to transfer your mind."); + performer.playAnimation("meditate", false); act.setTimeLeft(600); performer.sendActionControl("Transferring", true, act.getTimeLeft()); }else if(act.currentSecond() == 10){ - performer.getCommunicator().sendAlertServerMessage("You are about to enter a PvP environment.", (byte) 3); + performer.getCommunicator().sendAlertServerMessage("You are about to enter a full PvP environment.", (byte) 3); }else if(act.currentSecond() == 20){ - performer.getCommunicator().sendNormalServerMessage("Death will leave your corpse and return you here. Anyone may loot your corpse in the arena.", (byte) 3); + performer.getCommunicator().sendNormalServerMessage("Death will not drop your items. Instead they will be damaged heavily and returned to you upon respawn.", (byte) 3); }else if(act.currentSecond() == 30){ - performer.getCommunicator().sendNormalServerMessage("Upon transfer, you will be placed in a random location. This could be safely outside of danger, or directly on a group of enemies.", (byte) 3); + performer.getCommunicator().sendNormalServerMessage("If you are part of a deed, you will arrive at the token. Otherwise, you will be placed in a random location.", (byte) 3); }else if(act.currentSecond() == 40){ performer.getCommunicator().sendNormalServerMessage("You can equip creatures such as horses by simply leading them. Taming is not required in the Arena.", (byte) 3); }else if(act.currentSecond() == 55){ - performer.getCommunicator().sendNormalServerMessage("It appears you have accepted these conditions. Transferring to the arena. Good luck.", (byte) 3); + performer.getCommunicator().sendNormalServerMessage("It appears you have accepted these conditions. Transferring to the Revenant Arena. Good luck.", (byte) 3); }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ ServerEntry targetserver = Servers.localServer.serverNorth; if(targetserver == null){ diff --git a/src/main/java/mod/sin/actions/items/EternalOrbAction.java b/src/main/java/mod/sin/actions/items/EternalOrbAction.java index 34b3bc3..f51f7a6 100644 --- a/src/main/java/mod/sin/actions/items/EternalOrbAction.java +++ b/src/main/java/mod/sin/actions/items/EternalOrbAction.java @@ -5,10 +5,7 @@ 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.items.*; import com.wurmonline.server.players.Player; import com.wurmonline.server.skills.Skill; import com.wurmonline.server.spells.Spell; @@ -90,6 +87,10 @@ public class EternalOrbAction implements ModAction { player.getCommunicator().sendNormalServerMessage("You cannot absorb the orb with itself!"); return true; } + if(target.getTemplateId() == ItemList.arrowHunting || target.getTemplateId() == ItemList.arrowWar){ + player.getCommunicator().sendNormalServerMessage("You cannot use Eternal Orbs on arrows."); + return true; + } ItemSpellEffects teffs = target.getSpellEffects(); if(teffs == null || teffs.getEffects().length == 0){ player.getCommunicator().sendNormalServerMessage("The "+target.getTemplate().getName()+" has no enchants."); diff --git a/src/main/java/mod/sin/creatures/Charger.java b/src/main/java/mod/sin/creatures/Charger.java index de65a56..bbaa9c1 100644 --- a/src/main/java/mod/sin/creatures/Charger.java +++ b/src/main/java/mod/sin/creatures/Charger.java @@ -91,7 +91,7 @@ public class Charger implements ModCreature, CreatureTypes { vehicle.createPassengerSeats(0); vehicle.setSeatFightMod(0, 0.8f, 1.1f); - vehicle.setSeatOffset(0, 0.0f, 0.0f, 0.5f); + vehicle.setSeatOffset(0, 0.0f, 0.0f, 0.0f); vehicle.setCreature(true); vehicle.setSkillNeeded(Servers.localServer.PVPSERVER ? 25.0f : 37.0f); vehicle.setName(creature.getName()); diff --git a/src/main/java/mod/sin/items/AffinityOrb.java b/src/main/java/mod/sin/items/AffinityOrb.java index b9ed7d0..807f69d 100644 --- a/src/main/java/mod/sin/items/AffinityOrb.java +++ b/src/main/java/mod/sin/items/AffinityOrb.java @@ -20,7 +20,6 @@ public class AffinityOrb implements ItemTypes, MiscConstants { itemBuilder.name(name, "affinity orbs", "A valuable orb that infuses the user with hidden knowledge."); itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); itemBuilder.itemTypes(new short[]{ - ItemTypes.ITEM_TYPE_NODROP, ItemTypes.ITEM_TYPE_FULLPRICE, ItemTypes.ITEM_TYPE_NOSELLBACK }); diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index b5cfdb8..9ca0b76 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -427,6 +427,15 @@ public class Arena { } });*/ + // Die method description + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params8 = new CtClass[]{ + CtClass.booleanType, + ctString, + CtClass.booleanType + }; + String desc8 = Descriptor.ofMethod(CtClass.voidType, params8); + // - Ensure corpses are not loot protected on PvP - // Util.setReason("Ensure corpses are not loot protected."); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" @@ -434,13 +443,13 @@ public class Arena { + "}else{" + " $_ = $proceed($$);" + "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "setProtected", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "setProtected", replace); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + " $_ = true;" + "}else{" + " $_ = $proceed($$);" + "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "isInPvPZone", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "isInPvPZone", replace); // - Allow players to do actions in PvP houses - // CtClass ctMethods = classPool.get("com.wurmonline.server.behaviours.Methods"); @@ -680,15 +689,7 @@ public class Arena { "}else{" + " $_ = $proceed($$);" + "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "getFavor", replace); - - /*Util.setReason("Nerf resurrection stones."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = com.wurmonline.server.Server.rand.nextInt(40) > 35;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "isDeathProtected", replace);*/ + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "getFavor", replace); Util.setReason("Adjust spawn question mechanics."); CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); @@ -770,7 +771,7 @@ public class Arena { " keepItems = true;" + "}" + "$_ = $proceed($$);"; - Util.instrumentDeclaredCount(thisClass, ctCreature, "die", "isOnCurrentServer", 1, replace); + Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, replace); Util.setReason("Disable player skill loss on Arena."); replace = "if(this.isPlayer() && this.isDeathProtected()){" + diff --git a/src/main/java/mod/sin/wyvern/Bloodlust.java b/src/main/java/mod/sin/wyvern/Bloodlust.java index 2463ea3..38299d7 100644 --- a/src/main/java/mod/sin/wyvern/Bloodlust.java +++ b/src/main/java/mod/sin/wyvern/Bloodlust.java @@ -67,6 +67,8 @@ public class Bloodlust { final Class thisClass = Bloodlust.class; String replace; + /* Disabled in Wurm Unlimited 1.9 - May need to be revisited in the future. + Util.setReason("Hook for bloodlust system."); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); CtClass ctString = classPool.get("java.lang.String"); @@ -97,8 +99,8 @@ public class Bloodlust { " float lustMult = "+Bloodlust.class.getName()+".getLustMult($1);" + " $5 = $5 * lustMult;" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace); - } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ + } catch ( IllegalArgumentException | ClassCastException e) { throw new HookException(e); } } diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java index bd7b25f..23b0e68 100644 --- a/src/main/java/mod/sin/wyvern/Bounty.java +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -119,10 +119,20 @@ public class Bounty { } } });*/ + + // Die method description + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params1 = new CtClass[]{ + CtClass.booleanType, + ctString, + CtClass.booleanType + }; + String desc1 = Descriptor.ofMethod(CtClass.voidType, params1); + replace = "$_ = $proceed($$);" //+ "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);"; + LootBounty.class.getName()+".checkLootTable(this, corpse);"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "setRotation", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc1, "setRotation", replace); /*ctCreature.getDeclaredMethod("die").instrument(new ExprEditor(){ public void edit(MethodCall m) throws CannotCompileException { if (m.getMethodName().equals("setRotation")) { @@ -135,7 +145,7 @@ public class Bounty { });*/ // doNew(int templateid, boolean createPossessions, float aPosX, float aPosY, float aRot, int layer, String name, byte gender, byte kingdom, byte ctype, boolean reborn, byte age) - CtClass[] params = { + CtClass[] params2 = { CtClass.intType, CtClass.booleanType, CtClass.floatType, @@ -150,8 +160,8 @@ public class Bounty { CtClass.byteType, CtClass.intType }; - String desc = Descriptor.ofMethod(ctCreature, params); - Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc, "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); + String desc2 = Descriptor.ofMethod(ctCreature, params2); + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); // Debugging to show all new creatures created. //CtMethod ctDoNew = ctCreature.getMethod("doNew", "(IZFFFILjava/lang/String;BBBZB)Lcom/wurmonline/server/creatures/Creature;"); //ctDoNew.insertBefore("logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); @@ -159,7 +169,7 @@ public class Bounty { replace = "$_ = $proceed($$);" //+ "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"; + MethodsBestiary.class.getName()+".modifyNewCreature($1);"; - Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc, "sendToWorld", replace); + Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc2, "sendToWorld", replace); /*ctDoNew.instrument(new ExprEditor(){ public void edit(MethodCall m) throws CannotCompileException { if (m.getMethodName().equals("sendToWorld")) { diff --git a/src/main/java/mod/sin/wyvern/CombatChanges.java b/src/main/java/mod/sin/wyvern/CombatChanges.java index 23fca28..ad2478b 100644 --- a/src/main/java/mod/sin/wyvern/CombatChanges.java +++ b/src/main/java/mod/sin/wyvern/CombatChanges.java @@ -9,16 +9,16 @@ import com.wurmonline.server.creatures.Creatures; import com.wurmonline.server.items.Item; import com.wurmonline.server.players.Player; import com.wurmonline.shared.constants.Enchants; -import javassist.*; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; import javassist.bytecode.*; -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; import java.util.ArrayList; -import java.util.Objects; import java.util.logging.Logger; public class CombatChanges { @@ -151,6 +151,8 @@ public class CombatChanges { return damage > 1D; } + /* Disabled as of WU 1.9 - No longer necessary and no longer functions. + 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"); @@ -213,9 +215,9 @@ public class CombatChanges { } } } - } + }*/ - static void patchCombatDamageCheckCombatHandler(ClassPool classPool) throws NotFoundException, BadBytecode { + /*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(); @@ -255,7 +257,7 @@ public class CombatChanges { } } } - } + }*/ // Added to CombatHandled public static void pollCreatureActionStacks(){ @@ -283,8 +285,11 @@ public class CombatChanges { "$_ = $proceed($$);"; Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getFlankingModifier", replace); - Util.setReason("Increase unique damage to pets."); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + + /* Disabled in Wurm Unlimited 1.9 - No longer necessary while using DUSKombat. + + Util.setReason("Increase unique damage to pets."); 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"); @@ -313,7 +318,7 @@ public class CombatChanges { " logger.info(\"Detected pet hit on a unique. Reducing damage.\");" + " $5 = $5 * 0.5d;" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace); + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ Util.setReason("Adjust weapon damage type based on the potion/salve applied."); replace = "int wt = "+CombatChanges.class.getName()+".getWeaponType($1);" @@ -323,7 +328,6 @@ public class CombatChanges { + "}"; Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace); - Util.setReason("Adjust bloodthirst to epic settings."); CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); CtClass[] params2 = { ctCreature, @@ -331,8 +335,12 @@ public class CombatChanges { ctCreature }; String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2); + + /* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way. + + Util.setReason("Adjust bloodthirst to epic settings."); replace = "$_ = true;"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace); + Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace);*/ Util.setReason("Fix magranon damage bonus stacking."); replace = "if(mildStack){" + @@ -342,7 +350,6 @@ public class CombatChanges { "}"; Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace); - Util.setReason("Adjust bloodthirst to epic settings."); CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction"); CtClass[] params3 = { ctCreature, @@ -350,8 +357,12 @@ public class CombatChanges { ctCreature }; String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3); + + /* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way. + + Util.setReason("Adjust bloodthirst to epic settings."); replace = "$_ = true;"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace); + Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace);*/ Util.setReason("Fix magranon damage bonus stacking."); replace = "if(mildStack){" + @@ -451,13 +462,11 @@ public class CombatChanges { CombatChanges.class.getName()+".goodLog(\"Zones.pollNextZones(\"+sleepTime+\") call to Creatures.getInstance().pollAllCreatures(\"+$1+\") [time \"+java.lang.System.currentTimeMillis()+\"]\");"; Util.instrumentDeclared(thisClass, ctZones, "pollNextZones", "pollAllCreatures", replace);*/ - patchCombatDamageCheckCombatEngine(classPool); - patchCombatDamageCheckCombatHandler(classPool); + //patchCombatDamageCheckCombatEngine(classPool); + //patchCombatDamageCheckCombatHandler(classPool); } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); - } catch (BadBytecode badBytecode) { - badBytecode.printStackTrace(); } } } diff --git a/src/main/java/mod/sin/wyvern/DeityChanges.java b/src/main/java/mod/sin/wyvern/DeityChanges.java index 620872a..e03430b 100644 --- a/src/main/java/mod/sin/wyvern/DeityChanges.java +++ b/src/main/java/mod/sin/wyvern/DeityChanges.java @@ -11,18 +11,19 @@ public class DeityChanges { public static void onServerStarted(){ if(Deities.getDeity(101) != null){ // Edit Thelastdab Player God Deity thelastdab = Deities.getDeity(101); + // Set template deity + thelastdab.setMountainGod(true); // Add some defining affinities - thelastdab.metalAffinity = true; - thelastdab.deathProtector = true; - thelastdab.mountainGod = true; - thelastdab.warrior = true; + thelastdab.setMetalAffinity(true); + thelastdab.setDeathProtector(true); + thelastdab.setWarrior(true); // Remove some affinities - thelastdab.learner = false; - thelastdab.repairer = false; - thelastdab.befriendCreature = false; - thelastdab.healer = false; - thelastdab.clayAffinity = false; - thelastdab.waterGod = false; + thelastdab.setLearner(false); + thelastdab.setRepairer(false); + thelastdab.setBefriendCreature(false); + thelastdab.setHealer(false); + thelastdab.setClayAffinity(false); + thelastdab.setWaterGod(false); } /*if(Deities.getDeity(102) != null){ // Edit Cyberhusky player god Deity cyberhusky = Deities.getDeity(102); diff --git a/src/main/java/mod/sin/wyvern/EconomicChanges.java b/src/main/java/mod/sin/wyvern/EconomicChanges.java index eae1670..c62fe88 100644 --- a/src/main/java/mod/sin/wyvern/EconomicChanges.java +++ b/src/main/java/mod/sin/wyvern/EconomicChanges.java @@ -43,7 +43,7 @@ public class EconomicChanges { float dam = item.getDamage(); // =($A$25*A2*A2 / 10000) float initialValue = ((float)item.getTemplate().getValue())*qual*qual/10000f; - float baseCost = 100000f; + float baseCost = 50000f; float power = 6.0f; // =((10+B2/4.5)*(1-POW(A2/100, $A$27)) + B2*POW(A2/100, $A$27)) * ((100 - $A$29) / 100) return (int) (((baseCost+(initialValue/4.5f)) * (1f-Math.pow(qual/100f, power)) + initialValue*Math.pow(qual/100f, power)) * ((100f-dam)/100f) * PRICE_MARKUP); @@ -87,11 +87,13 @@ public class EconomicChanges { final Class thisClass = EconomicChanges.class; String replace; + /* [2/4/19] Disabled - Likely causing issues with upkeep fluctuation. Util.setReason("Increase deed upkeep by modifying the amount of tiles it thinks it has."); CtClass ctGuardPlan = classPool.get("com.wurmonline.server.villages.GuardPlan"); replace = "$_ = "+EconomicChanges.class.getName()+".getNewVillageTiles(vill.getNumTiles());"; - Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "getNumTiles", replace); + Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "getNumTiles", replace);*/ + /* [2/4/19] Disabled - Probably not necessary anymore. Util.setReason("Disable upkeep on arena for now until a fix can be found."); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + " $_ = false;" @@ -99,7 +101,7 @@ public class EconomicChanges { " $_ = $proceed($$);" + "}"; //replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "isUpkeep", replace); + Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "isUpkeep", replace);*/ /*Util.setReason("Allow players to get a full deed refund."); replace = "{ return "+EconomicChanges.class.getName()+".getNewDisbandMoney(this, this.getVillage()); }"; diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index 5a5a245..806135f 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -253,10 +253,10 @@ public class ItemMod { public static void createCustomWeapons(){ try { logger.info("Beginning custom weapon creation."); - new Weapon(BattleYoyo.templateId, 6.85f, 3.85f, 0.008f, 2, 2, 0.0f, 0d); - new Weapon(Club.templateId, 8.1f, 4.5f, 0.002f, 3, 3, 0.4f, 0.5d); - new Weapon(Knuckles.templateId, 3.7f, 2.2f, 0.002f, 1, 1, 0.2f, 0.5d); - new Weapon(Warhammer.templateId, 9.40f, 5.6f, 0.008f, 4, 3, 1f, 0d); + new Weapon(BattleYoyo.templateId, 6.85f, 3.75f, 0.012f, 2, 2, 0.0f, 0d); + new Weapon(Club.templateId, 8.3f, 4.5f, 0.002f, 3, 3, 0.4f, 0.5d); + new Weapon(Knuckles.templateId, 3.8f, 2.2f, 0.002f, 1, 1, 0.2f, 0.5d); + new Weapon(Warhammer.templateId, 9.50f, 5.6f, 0.015f, 4, 3, 1f, 0d); //new Weapon(ItemList.stoneChisel, 50f, 1f, 0.5f, 8, 1, 3f, -5f); // Titan weaponry new Weapon(MaartensMight.templateId, 11, 5, 0.02f, 4, 4, 1.0f, 0d); @@ -327,6 +327,10 @@ public class ItemMod { int newKindlingVolume = kindling.getSizeX()*kindling.getSizeY()*kindling.getSizeZ(); ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "volume"), newKindlingVolume); + // Allow sleep powder to be dropped. + ItemTemplate sleepPowder = ItemTemplateFactory.getInstance().getTemplate(ItemList.sleepPowder); + ReflectionUtil.setPrivateField(sleepPowder, ReflectionUtil.getField(sleepPowder.getClass(), "nodrop"), false); + // Set silver mirror price to 10 silver instead of 1 iron. ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror); ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 200000); @@ -342,6 +346,10 @@ public class ItemMod { ItemTemplate resurrectionStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.resurrectionStone); ReflectionUtil.setPrivateField(resurrectionStone, ReflectionUtil.getField(resurrectionStone.getClass(), "value"), 20000); + // Shaker Orbs to 2 silver instead of 5 silver. + ItemTemplate shakerOrb = ItemTemplateFactory.getInstance().getTemplate(ItemList.shakerOrb); + ReflectionUtil.setPrivateField(shakerOrb, ReflectionUtil.getField(shakerOrb.getClass(), "value"), 20000); + // Set transmutation rod to 2 gold instead of 50 silver. //ItemTemplate transmutationRod = ItemTemplateFactory.getInstance().getTemplate(668); //ReflectionUtil.setPrivateField(transmutationRod, ReflectionUtil.getField(transmutationRod.getClass(), "value"), 2000000); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 51e830d..113b4b8 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -5,6 +5,7 @@ import com.wurmonline.server.bodys.Wound; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.creatures.Creatures; import com.wurmonline.server.creatures.NoSuchCreatureException; +import com.wurmonline.server.creatures.SpellEffectsEnum; import com.wurmonline.server.items.Item; import com.wurmonline.server.items.ItemTemplate; import com.wurmonline.server.items.SimpleCreationEntry; @@ -14,6 +15,7 @@ import com.wurmonline.server.players.PlayerInfoFactory; import com.wurmonline.server.players.Titles; import com.wurmonline.server.skills.Skill; import com.wurmonline.server.skills.SkillList; +import com.wurmonline.server.spells.SpellEffect; import com.wurmonline.server.villages.Village; import com.wurmonline.server.webinterface.WcKingdomChat; import com.wurmonline.server.zones.VolaTile; @@ -309,6 +311,20 @@ public class MiscChanges { } return arrTitles.toArray(new Titles.Title[0]); } + + public static boolean shouldSendBuff(SpellEffectsEnum effect){ + // Continue not showing any that don't have a buff in the first place + if (!effect.isSendToBuffBar()){ + return false; + } + // Resistances and vulnerabilities are 20 - 43 + if (effect.getTypeId() <= 43 && effect.getTypeId() >= 20){ + return false; + } + + // Is send to buff bar and not something we're stopping, so allow it. + return true; + } public static void preInit(){ try{ @@ -325,7 +341,8 @@ public class MiscChanges { "Website/Maps: https://www.sarcasuals.com/", "Server Discord: https://discord.gg/r8QNXAC", "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", - "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing"}; + "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing", + "Patreon: https://www.patreon.com/sindusk"}; StringBuilder str = new StringBuilder("{" + " com.wurmonline.server.Message mess;"); for (String anInfoTabLine : infoTabLine) { @@ -844,13 +861,13 @@ public class MiscChanges { "}"; Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); - Util.setReason("Fix bug causing high cast spells to reduce power."); + /*Util.setReason("Fix bug causing high cast spells to reduce power."); CtClass ctSpellEffect = classPool.get("com.wurmonline.server.spells.SpellEffect"); replace = "{" + " final float mod = 5.0f * (1.0f - java.lang.Math.min($0.getPower(), 100f) / 100.0f);" + " $0.setPower(mod + $1);" + "}"; - Util.setBodyDeclared(thisClass, ctSpellEffect, "improvePower", replace); + Util.setBodyDeclared(thisClass, ctSpellEffect, "improvePower", replace);*/ Util.setReason("Disable smelting pots from being used."); CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); @@ -880,6 +897,29 @@ public class MiscChanges { "$_ = $proceed($$);"; Util.instrumentDeclared(thisClass, ctTitleCompoundQuestion, "sendQuestion", "sort", replace);*/ + /*Util.setReason("Remove buff bar spam from sorceries."); + replace = "$_ = false;"; + Util.instrumentDeclared(thisClass, ctAbilities, "sendEffectsToCreature", "hasAnyAbility", replace);*/ + + Util.setReason("Hide buff bar icons for sorceries."); + CtClass ctSpellEffectsEnum = classPool.get("com.wurmonline.server.creatures.SpellEffectsEnum"); + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params15 = { + ctSpellEffectsEnum, + CtClass.intType, + ctString + }; + String desc15 = Descriptor.ofMethod(CtClass.voidType, params15); + CtClass[] params16 = { + ctSpellEffectsEnum, + CtClass.intType + }; + String desc16 = Descriptor.ofMethod(CtClass.voidType, params16); + replace = "$_ = "+MiscChanges.class.getName()+".shouldSendBuff($0);"; + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc15, "isSendToBuffBar", replace); + Util.setReason("Hide buff bar icons for sorceries."); + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/MountedChanges.java b/src/main/java/mod/sin/wyvern/MountedChanges.java index 7ba15ac..d5ba127 100644 --- a/src/main/java/mod/sin/wyvern/MountedChanges.java +++ b/src/main/java/mod/sin/wyvern/MountedChanges.java @@ -27,25 +27,25 @@ public class MountedChanges { Item leftFoot = creature.getEquippedItem(BodyPartConstants.LEFT_FOOT); leftFoot.setDamage(leftFoot.getDamage()+(leftFoot.getDamageModifier()*0.002f)); gear.add(leftFoot); - } catch (NoSuchItemException | NoSpaceException ignored) { + } catch (NoSpaceException ignored) { } try { Item rightFoot = creature.getEquippedItem(BodyPartConstants.RIGHT_FOOT); rightFoot.setDamage(rightFoot.getDamage()+(rightFoot.getDamageModifier()*0.002f)); gear.add(rightFoot); - } catch (NoSuchItemException | NoSpaceException ignored) { + } catch (NoSpaceException ignored) { } try { Item leftHand = creature.getEquippedItem(BodyPartConstants.LEFT_HAND); leftHand.setDamage(leftHand.getDamage()+(leftHand.getDamageModifier()*0.002f)); gear.add(leftHand); - } catch (NoSuchItemException | NoSpaceException ignored) { + } catch (NoSpaceException ignored) { } try { Item rightHand = creature.getEquippedItem(BodyPartConstants.RIGHT_HAND); rightHand.setDamage(rightHand.getDamage()+(rightHand.getDamageModifier()*0.002f)); gear.add(rightHand); - } catch (NoSuchItemException | NoSpaceException ignored) { + } catch (NoSpaceException ignored) { } for(Item shoe : gear){ factor += Math.max(10f, shoe.getCurrentQualityLevel()) / 2000f; @@ -96,7 +96,7 @@ public class MountedChanges { saddleFactor += saddle.getRarity() * 0.03f; factor *= saddleFactor; } - } catch (NoSuchItemException | NoSpaceException ignored) { + } catch (NoSpaceException ignored) { } factor *= creature.getMovementScheme().getSpeedModifier(); } diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index 8e2167f..ff6ec7b 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -1,20 +1,192 @@ package mod.sin.wyvern; +import com.wurmonline.server.DbConnector; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.players.Player; +import com.wurmonline.server.players.PlayerInfo; import com.wurmonline.server.players.Titles; +import com.wurmonline.server.utils.DbUtilities; +import javassist.CtClass; +import javassist.CtPrimitiveType; +import javassist.bytecode.Descriptor; +import mod.enumbuster.EnumBuster; +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; +import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.sql.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; public class PlayerTitles { public static Logger logger = Logger.getLogger(PlayerTitles.class.getName()); + private static Titles.Title[] titleArray; + // Player Title Maps protected static ArrayList donatorTitles = new ArrayList<>(); + protected static ArrayList patronTitles = new ArrayList<>(); protected static HashMap customTitles = new HashMap<>(); protected static HashMap playerTitles = new HashMap<>(); + // Event Title ID's + public static int TITAN_SLAYER = 10000; + public static int SPECTRAL = 10001; + public static int PASTAMANCER = 10002; + + // Player Donation Title ID's + public static int PATRON = 19999; + public static int DONATOR = 20000; + public static int PAZZA_FAVORITE_GM = 20001; + public static int WARRIORGEN_THAT_GUY = 20002; + public static int ETERNALLOVE_WARRIORGENS_WIFE = 20003; + public static int BAMBAM_THORN_ONE = 20004; + public static int SVENJA_CARE_DEPENDANT = 20005; + public static int ALEXIA_THE_TREASURING = 20006; + public static int REEVI_SCIENCE_GUY = 20007; + public static int GENOCIDE_GRAND_DESIGNER = 20008; + public static int SELEAS_CRAZY_CAT_LORD = 20009; + public static int PIRATEMAX_SLAVE = 20010; + public static int ELTACOLAD_TRUE_TACO = 20011; + public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012; + + public static void onItemTemplatesCreated(){ + interceptLoadTitles(); + EnumBuster buster = new EnumBuster<>(Titles.Title.class, Titles.Title.class); + // Random titles for fun + //PlayerTitles.createTitle(buster, "Game_Master", 2500, "Game Master", "Game Master", -1, Titles.TitleType.NORMAL); + //PlayerTitles.createTitle(buster, "Developer", 2501, "Developer", "Developer", -1, Titles.TitleType.NORMAL); + //PlayerTitles.createTitle(buster, "Pet_Me", 2502, "Pet Me", "Pet Me", -1, Titles.TitleType.NORMAL); + + // Event Titles + createTitle(buster, "Titan_Slayer", TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Spectral", SPECTRAL, "Spectral", "Spectral", -1, Titles.TitleType.NORMAL); + //PlayerTitles.createTitle(buster, "Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, Titles.TitleType.NORMAL); + //PlayerTitles.createTitle(buster, "Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Pastamancer", PASTAMANCER, "Pastamancer", "Pastamancer", -1, Titles.TitleType.NORMAL); + + // Donation Titles + createTitle(buster, "Patron", PATRON, "Patron", "Patron", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Donator", DONATOR, "Donator", "Donator", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Pazza_FavoriteGM", PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Warriorgen_ThatGuy", WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Eternallove_WarriorgensWife", ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Bambam_ThornOne", BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Svenja_CareDependant", SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Alexia_TheTreasuring", ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Reevi_ScienceGuy", REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Genocide_GrandDesigner", GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Seleas_CrazyCatLord", SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Piratemax_Slave", PIRATEMAX_SLAVE, "Slave", "Slave", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Eltacolad_TrueTaco", ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, Titles.TitleType.NORMAL); + createTitle(buster, "Atticus_The_Great_Illuminaty", ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, Titles.TitleType.NORMAL); + + // Supporter titles + logger.info(Arrays.toString(Titles.Title.values())); + titleArray = Titles.Title.values(); + } + + private static void createTitle(EnumBuster buster, String enumName, int id, String titleMale, String titleFemale, int skillId, Titles.TitleType type) { + Titles.Title testTitle = buster.make(enumName, 0, new Class[]{Integer.TYPE, String.class, String.class, Integer.TYPE, Titles.TitleType.class}, new Object[]{id, titleMale, titleFemale, skillId, type}); + buster.addByValue(testTitle); + logger.log(Level.INFO, String.format("Created new title with ID #%d: %s [\"%s\", \"%s\"]", id, enumName, titleMale, titleFemale)); + } + + public static boolean hasTitle(Creature c, int titleId) { + if (c.isPlayer()) { + Titles.Title[] titles; + Titles.Title[] arrtitle = titles = ((Player)c).getTitles(); + int n = arrtitle.length; + int n2 = 0; + while (n2 < n) { + Titles.Title title = arrtitle[n2]; + if (title == null) { + throw new RuntimeException("We have NULL in titles collection, that is not nice at all!"); + } + if (title.getTitleId() == titleId) { + return true; + } + ++n2; + } + } else { + return true; + } + return false; + } + + private static void interceptLoadTitles() { + String descriptor = Descriptor.ofMethod((CtClass)CtPrimitiveType.voidType, (CtClass[])new CtClass[]{CtClass.longType}); + HookManager.getInstance().registerHook("com.wurmonline.server.players.DbPlayerInfo", "loadTitles", descriptor, new InvocationHandlerFactory(){ + + public InvocationHandler createInvocationHandler() { + return new InvocationHandler(){ + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + Object result; + block8 : { + ResultSet rs; + Connection dbcon; + PreparedStatement ps; + result = method.invoke(proxy, args); + PlayerInfo pi = (PlayerInfo)proxy; + Set titles = ReflectionUtil.getPrivateField(pi, ReflectionUtil.getField(pi.getClass(), "titles")); + titles.remove(null); + dbcon = null; + ps = null; + rs = null; + try { + try { + dbcon = DbConnector.getPlayerDbCon(); + ps = dbcon.prepareStatement("select TITLEID from TITLES where WURMID=?"); + ps.setLong(1, pi.getPlayerId()); + rs = ps.executeQuery(); + while (rs.next()) { + if (Titles.Title.getTitle(rs.getInt("TITLEID")) != null){ + continue; + } + titles.add(PlayerTitles.getTitle(rs.getInt("TITLEID"))); + } + } + catch (SQLException ex) { + logger.log(Level.INFO, "Failed to load titles for " + pi.getPlayerId(), ex); + DbUtilities.closeDatabaseObjects(ps, rs); + DbConnector.returnConnection(dbcon); + break block8; + } + } + catch (Throwable throwable) { + DbUtilities.closeDatabaseObjects(ps, rs); + DbConnector.returnConnection(dbcon); + throw throwable; + } + DbUtilities.closeDatabaseObjects(ps, rs); + DbConnector.returnConnection(dbcon); + } + return result; + } + }; + } + + }); + } + + public static Titles.Title getTitle(int titleAsInt) { + int i = 0; + while (i < titleArray.length) { + if (titleAsInt == titleArray[i].getTitleId()) { + return titleArray[i]; + } + ++i; + } + throw new RuntimeException("Could not find title: " + titleAsInt); + } + public static boolean hasCustomTitle(Creature creature){ if(creature instanceof Player){ Player p = (Player) creature; @@ -30,61 +202,62 @@ public class PlayerTitles { return ""; } public static void awardCustomTitles(Player p){ - /* Disabled until a fix for title implementations is done. String name = p.getName(); if(donatorTitles.contains(name)){ - Titles.Title donator = Titles.Title.getTitle(800); + Titles.Title donator = getTitle(DONATOR); p.addTitle(donator); } + if(patronTitles.contains(name)){ + Titles.Title patron = getTitle(PATRON); + p.addTitle(patron); + } if(customTitles.containsKey(name)){ - Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name)); + Titles.Title customTitle = getTitle(customTitles.get(name)); p.addTitle(customTitle); - }*/ + } } public static void preInit(){ // Donations - playerTitles.put("Sindusk", "Phenomenal Feline"); - - customTitles.put("Sindawn", 501); // Developer - playerTitles.put("Sindawn", "Pet Me"); - donatorTitles.add("Pazza"); - customTitles.put("Pazza", 801); // Sindusks Favorite GM + customTitles.put("Pazza", PAZZA_FAVORITE_GM); // Sindusks Favorite GM donatorTitles.add("Warriorgen"); - customTitles.put("Warriorgen", 802); // That Guy + customTitles.put("Warriorgen", WARRIORGEN_THAT_GUY); // That Guy donatorTitles.add("Eternallove"); - customTitles.put("Eternallove", 803); // Warriorgens Wife + customTitles.put("Eternallove", ETERNALLOVE_WARRIORGENS_WIFE); // Warriorgens Wife donatorTitles.add("Bambam"); - customTitles.put("Bambam", 804); // Thorn One + customTitles.put("Bambam", BAMBAM_THORN_ONE); // Thorn One donatorTitles.add("Svenja"); - customTitles.put("Svenja", 805); // The care-dependent + customTitles.put("Svenja", SVENJA_CARE_DEPENDANT); // The care-dependent playerTitles.put("Svenja", "Akuma"); donatorTitles.add("Alexiaselena"); - customTitles.put("Alexiaselena", 806); // The Treasuring + customTitles.put("Alexiaselena", ALEXIA_THE_TREASURING); // The Treasuring playerTitles.put("Alexiaselena", "Kami"); donatorTitles.add("Reevi"); - customTitles.put("Reevi", 807); // Science Guy + customTitles.put("Reevi", REEVI_SCIENCE_GUY); // Science Guy - customTitles.put("Genocide", 808); // Grand Designer + customTitles.put("Genocide", GENOCIDE_GRAND_DESIGNER); // Grand Designer donatorTitles.add("Seleas"); - customTitles.put("Seleas", 809); // The Crazy Cat Lord + customTitles.put("Seleas", SELEAS_CRAZY_CAT_LORD); // The Crazy Cat Lord playerTitles.put("Seleas", "No, Really"); donatorTitles.add("Piratemax"); - customTitles.put("Piratemax", 810); // Slave + customTitles.put("Piratemax", PIRATEMAX_SLAVE); // Slave playerTitles.put("Piratemax", "Boy Next Door"); donatorTitles.add("Eltacolad"); - customTitles.put("Eltacolad", 811); // The One True Taco + customTitles.put("Eltacolad", ELTACOLAD_TRUE_TACO); // The One True Taco + + patronTitles.add("Atticus"); + customTitles.put("Atticus", ATTICUS_THE_GREAT_ILLUMINATY); // The Great Illuminaty // Other rewards - customTitles.put("Critias", 602); + customTitles.put("Critias", PASTAMANCER); } } diff --git a/src/main/java/mod/sin/wyvern/QualityOfLife.java b/src/main/java/mod/sin/wyvern/QualityOfLife.java index b88ccfb..59bf52a 100644 --- a/src/main/java/mod/sin/wyvern/QualityOfLife.java +++ b/src/main/java/mod/sin/wyvern/QualityOfLife.java @@ -146,10 +146,12 @@ public class QualityOfLife { replace = "{ return this.template.holyItem; }"; Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc100, replace); + /* Disabled in Wurm Unlimited 1.9 - Priest Rework changes removed this restriction. + Util.setReason("Remove requirement for Libila priests to bless creatures before taming."); CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", replace); + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", replace);*/ Util.setReason("Send gems, source crystals, flint, etc. into vehicle."); CtClass[] params2 = { diff --git a/src/main/java/mod/sin/wyvern/RareSpawns.java b/src/main/java/mod/sin/wyvern/RareSpawns.java index 44411bb..8baa2c5 100644 --- a/src/main/java/mod/sin/wyvern/RareSpawns.java +++ b/src/main/java/mod/sin/wyvern/RareSpawns.java @@ -122,6 +122,8 @@ public class RareSpawns { + "}"; Util.insertBeforeDeclared(thisClass, ctWormBrains, "precondition", replace); + /* Disabled in Wurm Unlimited 1.9 - No longer necessary while using DUSKombat. + Util.setReason("Increase titan extra damage to pets."); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); CtClass ctString = classPool.get("java.lang.String"); @@ -148,7 +150,7 @@ public class RareSpawns { //" logger.info(\"Detected rare spawn hit on a pet. Adding damage.\");" + " $5 = $5 * 2d;" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace); + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ }catch (NotFoundException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/Titans.java b/src/main/java/mod/sin/wyvern/Titans.java index 94d80b9..1cf104f 100644 --- a/src/main/java/mod/sin/wyvern/Titans.java +++ b/src/main/java/mod/sin/wyvern/Titans.java @@ -153,7 +153,7 @@ public class Titans { if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ return; } - lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f); + lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f, 0f, 0f, true, true); /*if (!lCret.addWoundOfType(lCret, Wound.TYPE_INFECTION, 1, true, 1.0f, true, 50000f)) { Creatures.getInstance().setCreatureDead(lCret); Players.getInstance().setCreatureDead(lCret); @@ -291,7 +291,7 @@ public class Titans { } t.sendAttachCreatureEffect(lCret, (byte) 8, (byte) 0, (byte) 0, (byte) 0, (byte) 0); try { - if (lCret.addWoundOfType(titan, Wound.TYPE_INFECTION, lCret.getBody().getRandomWoundPos(), false, 1.0f, false, 25000.0 * (double)lCret.addSpellResistance((short) 448))){ + if (lCret.addWoundOfType(titan, Wound.TYPE_INFECTION, lCret.getBody().getRandomWoundPos(), false, 1.0f, false, 25000.0 * (double)lCret.addSpellResistance((short) 448), 0f, 0f, true, true)){ return; } } catch (Exception e) { @@ -389,7 +389,7 @@ public class Titans { Server.getInstance().broadCastAction(titan.getName() + " picks a target at random and Smites "+target.getName()+"!", titan, 50); target.getCommunicator().sendAlertServerMessage(titan.getName() + " smites you.", (byte) 4); try { - target.addWoundOfType(titan, Wound.TYPE_BURN, target.getBody().getRandomWoundPos(), false, 1.0f, false, maxdam); + target.addWoundOfType(titan, Wound.TYPE_BURN, target.getBody().getRandomWoundPos(), false, 1.0f, false, maxdam, 0f, 0f, true, true); } catch (Exception e) { e.printStackTrace(); } @@ -830,13 +830,15 @@ public class Titans { + "}"; Util.insertBeforeDeclared(thisClass, ctSmite, "precondition", replace);*/ + /* Disabled in Wurm Unlimited 1.9 - No longer necessary as spells are balanced. + Util.setReason("Disable casting Worm Brains on titans."); CtClass ctWormBrains = classPool.get("com.wurmonline.server.spells.WormBrains"); replace = "if("+Titans.class.getName()+".isTitan($3)){" + " $2.getCommunicator().sendNormalServerMessage(\"Titans are immune to that spell.\");" + " return false;" + "}"; - Util.insertBeforeDeclared(thisClass, ctWormBrains, "precondition", replace); + Util.insertBeforeDeclared(thisClass, ctWormBrains, "precondition", replace);*/ CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); Util.setReason("Add spell resistance to titans."); @@ -845,6 +847,8 @@ public class Titans { "}"; Util.insertBeforeDeclared(thisClass, ctCreature, "addSpellResistance", replace); + /* Disabled in Wurm Unlimited 1.9 - No longer needed while using DUSKombat. + Util.setReason("Increase titan extra damage to pets."); CtClass ctString = classPool.get("java.lang.String"); CtClass ctBattle = classPool.get("com.wurmonline.server.combat.Battle"); @@ -870,7 +874,7 @@ public class Titans { " logger.info(\"Detected titan hit on a pet. Adding damage.\");" + " $5 = $5 * 2d;" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace); + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ }catch (NotFoundException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 318020b..feba667 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -12,10 +12,8 @@ import java.util.logging.Logger; import java.util.logging.SimpleFormatter; import com.wurmonline.server.Message; -import com.wurmonline.server.creatures.Communicator; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.items.*; -import com.wurmonline.server.kingdom.Kingdoms; import mod.sin.actions.items.SorcerySplitAction; import mod.sin.lib.Util; import org.gotti.wurmunlimited.modloader.ReflectionUtil; @@ -248,6 +246,8 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea ItemMod.createItems(); logger.info("Creating Cache items."); Caches.createItems(); + logger.info("Initiating Title changes."); + PlayerTitles.onItemTemplatesCreated(); try { logger.info("Editing existing item templates."); ItemMod.modifyItems(); diff --git a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java index 854f88d..b055928 100644 --- a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java +++ b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java @@ -457,6 +457,17 @@ public class MethodsBestiary { e.printStackTrace(); } } + + private static void setCombatRating(int templateId, float value){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "baseCombatRating"), value); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } private static void setNaturalArmour(int templateId, float value){ try{ @@ -646,6 +657,9 @@ public class MethodsBestiary { // Set skills for certain creatures setSkill(CreatureTemplate.CYCLOPS_CID, SkillList.GROUP_FIGHTING, 80.0f); + + // Set combat rating for valrei creatures to improve their bounty + setCombatRating(CreatureTemplate.SON_OF_NOGUMP_CID, 30.0f); } protected static void sendParticleEffect(Communicator comm, long creatureId, Creature creature, String particle, float duration){ @@ -737,6 +751,15 @@ public class MethodsBestiary { }); } + // Die method description + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params5 = new CtClass[]{ + CtClass.booleanType, + ctString, + CtClass.booleanType + }; + String desc5 = Descriptor.ofMethod(CtClass.voidType, params5); + Util.setReason("Deny chargers walking through walls."); CtClass ctPathFinder = classPool.get("com.wurmonline.server.creatures.ai.PathFinder"); replace = "if("+MethodsBestiary.class.getName()+".denyPathingOverride($0)){" + @@ -749,7 +772,7 @@ public class MethodsBestiary { Util.instrumentDeclared(thisClass, ctCreature, "startPathingToTile", "isGhost", replace); Util.instrumentDeclared(thisClass, ctCreature, "moveAlongPath", "isGhost", replace); Util.instrumentDeclared(thisClass, ctCreature, "takeSimpleStep", "isGhost", replace); - Util.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); Util.setReason("Apply random types to creatures in the wilderness."); CtClass[] params2 = { @@ -809,7 +832,7 @@ public class MethodsBestiary { + "if("+MethodsBestiary.class.getName()+".hasCustomCorpseSize(this)){" + " "+MethodsBestiary.class.getName()+".setCorpseSizes(this, corpse);" + "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "addItem", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "addItem", replace); Util.setReason("Add spell resistance to custom creatures."); replace = "float cResist = "+MethodsBestiary.class.getName()+".getCustomSpellResistance(this);" + @@ -833,7 +856,7 @@ public class MethodsBestiary { + "}else{" + " $_ = $proceed($$);" + "}"; - Util.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); Util.setReason("Attach special effects to creatures."); CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); diff --git a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java index 6afd463..860ec1a 100644 --- a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java @@ -307,9 +307,12 @@ public class LootBounty { if(crystalStr > 10000){ // 1 silver numCrystals += doRollingCrystalReward(mob, corpse, crystalStr, EnchantersCrystal.templateId, 5, 20000); }*/ + boolean sendLootHelp = false; // Begin loot table drops int templateId = mob.getTemplate().getTemplateId(); + + // Arena damages player equipment on death if(Servers.localServer.PVPSERVER && mob.isPlayer()){ if(mob.isDeathProtected()) { logger.info("Death protection was active for " + mob.getName() + ". Inserting silver coin reward."); diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java index ba3fd0d..27cba1b 100644 --- a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -17,10 +17,7 @@ import mod.sin.creatures.SpectralDrake; import mod.sin.items.AffinityOrb; import mod.sin.items.caches.RiftCache; import mod.sin.items.caches.TitanCache; -import mod.sin.wyvern.Bounty; -import mod.sin.wyvern.MiscChanges; -import mod.sin.wyvern.RareSpawns; -import mod.sin.wyvern.Titans; +import mod.sin.wyvern.*; import mod.sin.wyvern.util.ItemUtil; import java.io.IOException; @@ -109,7 +106,7 @@ public class PlayerBounty { fightStrength = "legendary"; } player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly."); - //player.addTitle(Title.getTitle(701)); + player.addTitle(PlayerTitles.getTitle(PlayerTitles.SPECTRAL)); }catch (NoSuchTemplateException | FailedException e) { e.printStackTrace(); } @@ -148,7 +145,7 @@ public class PlayerBounty { player.getInventory().insertItem(riftCache, true); } if(Titans.isTitan(mob)){ - //player.addTitle(Title.getTitle(700)); + player.addTitle(PlayerTitles.getTitle(PlayerTitles.TITAN_SLAYER)); Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f, mob.getName()); player.getInventory().insertItem(affinityOrb, true); Item titanCache = ItemFactory.createItem(TitanCache.templateId, 99f, mob.getName()); diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java index 74bce1c..512152c 100644 --- a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java +++ b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java @@ -68,7 +68,7 @@ public class Mastercraft { } return mult; } - public static void addNewTitles(){ + /*public static void addNewTitles(){ try { ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title"); // GM/Developer Titles @@ -146,7 +146,8 @@ public class Mastercraft { } catch (BadBytecode | ClassNotFoundException | NotFoundException | CannotCompileException e) { logger.warning(e.getMessage()); } - } + }*/ + public static void changeExistingTitles(){ for (Titles.Title title : Titles.Title.values()) { if (Objects.equals("Pumpkin King", title.getFemaleName())){ From a5f9c0c48bdf7ccc87005e736ae1f2b5da6f6323 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Sun, 14 Apr 2019 00:24:25 -0400 Subject: [PATCH 3/8] Fixes for 1.9 --- build.gradle | 2 +- .../sin/actions/items/EnchantOrbAction.java | 8 +++++- .../java/mod/sin/wyvern/DeityChanges.java | 9 +++++++ src/main/java/mod/sin/wyvern/MiscChanges.java | 11 ++++++++ .../java/mod/sin/wyvern/MountedChanges.java | 27 +++++++++++-------- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 772e4e9..ab276ea 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group "mod.sin" -version "1.3" +version "1.4" repositories { mavenCentral() diff --git a/src/main/java/mod/sin/actions/items/EnchantOrbAction.java b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java index cd75ccc..4152045 100644 --- a/src/main/java/mod/sin/actions/items/EnchantOrbAction.java +++ b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import com.wurmonline.server.spells.ItemEnchantment; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; @@ -138,7 +139,12 @@ public class EnchantOrbAction implements ModAction { } }else { try { - Method m = spell.getClass().getDeclaredMethod("precondition", Skill.class, Creature.class, Item.class); + Method m; + if (spell instanceof ItemEnchantment){ + m = ItemEnchantment.class.getDeclaredMethod("precondition", Skill.class, Creature.class, Item.class); + }else { + 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(); diff --git a/src/main/java/mod/sin/wyvern/DeityChanges.java b/src/main/java/mod/sin/wyvern/DeityChanges.java index e03430b..6dd4b28 100644 --- a/src/main/java/mod/sin/wyvern/DeityChanges.java +++ b/src/main/java/mod/sin/wyvern/DeityChanges.java @@ -12,7 +12,9 @@ public class DeityChanges { if(Deities.getDeity(101) != null){ // Edit Thelastdab Player God Deity thelastdab = Deities.getDeity(101); // Set template deity + thelastdab.setTemplateDeity(Deities.DEITY_MAGRANON); thelastdab.setMountainGod(true); + thelastdab.setHateGod(false); // Rolled Libila // Add some defining affinities thelastdab.setMetalAffinity(true); thelastdab.setDeathProtector(true); @@ -25,6 +27,13 @@ public class DeityChanges { thelastdab.setClayAffinity(false); thelastdab.setWaterGod(false); } + if(Deities.getDeity(102) != null){ + Deity reevi = Deities.getDeity(102); + // Set template deity + reevi.setTemplateDeity(Deities.DEITY_MAGRANON); + reevi.setMountainGod(true); + reevi.setWaterGod(false); // Rolled Vynora + } /*if(Deities.getDeity(102) != null){ // Edit Cyberhusky player god Deity cyberhusky = Deities.getDeity(102); // Add some defining affinities diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 113b4b8..4a9c9b0 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -920,6 +920,17 @@ public class MiscChanges { Util.setReason("Hide buff bar icons for sorceries."); Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + // 1.9 Achievement fix [Bdew] + classPool.getCtClass("com.wurmonline.server.players.Achievements").getMethod("loadAllAchievements", "()V") + .instrument(new ExprEditor(){ + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getTimestamp")) + m.replace("$_=com.wurmonline.server.utils.DbUtilities.getTimestampOrNull(rs.getString($1)); " + + "if ($_==null) $_=new java.sql.Timestamp(java.lang.System.currentTimeMillis());"); + } + }); + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/MountedChanges.java b/src/main/java/mod/sin/wyvern/MountedChanges.java index d5ba127..d3eeecb 100644 --- a/src/main/java/mod/sin/wyvern/MountedChanges.java +++ b/src/main/java/mod/sin/wyvern/MountedChanges.java @@ -1,10 +1,7 @@ package mod.sin.wyvern; -import com.wurmonline.server.NoSuchItemException; import com.wurmonline.server.creatures.Creature; -import com.wurmonline.server.creatures.NoArmourException; import com.wurmonline.server.items.Item; -import com.wurmonline.server.items.ItemList; import com.wurmonline.server.items.NoSpaceException; import com.wurmonline.shared.constants.BodyPartConstants; import com.wurmonline.shared.constants.Enchants; @@ -25,26 +22,34 @@ public class MountedChanges { ArrayList gear = new ArrayList<>(); try { Item leftFoot = creature.getEquippedItem(BodyPartConstants.LEFT_FOOT); - leftFoot.setDamage(leftFoot.getDamage()+(leftFoot.getDamageModifier()*0.002f)); - gear.add(leftFoot); + if (leftFoot != null) { + leftFoot.setDamage(leftFoot.getDamage() + (leftFoot.getDamageModifier() * 0.002f)); + gear.add(leftFoot); + } } catch (NoSpaceException ignored) { } try { Item rightFoot = creature.getEquippedItem(BodyPartConstants.RIGHT_FOOT); - rightFoot.setDamage(rightFoot.getDamage()+(rightFoot.getDamageModifier()*0.002f)); - gear.add(rightFoot); + if (rightFoot != null) { + rightFoot.setDamage(rightFoot.getDamage() + (rightFoot.getDamageModifier() * 0.002f)); + gear.add(rightFoot); + } } catch (NoSpaceException ignored) { } try { Item leftHand = creature.getEquippedItem(BodyPartConstants.LEFT_HAND); - leftHand.setDamage(leftHand.getDamage()+(leftHand.getDamageModifier()*0.002f)); - gear.add(leftHand); + if (leftHand != null) { + leftHand.setDamage(leftHand.getDamage() + (leftHand.getDamageModifier() * 0.002f)); + gear.add(leftHand); + } } catch (NoSpaceException ignored) { } try { Item rightHand = creature.getEquippedItem(BodyPartConstants.RIGHT_HAND); - rightHand.setDamage(rightHand.getDamage()+(rightHand.getDamageModifier()*0.002f)); - gear.add(rightHand); + if (rightHand != null) { + rightHand.setDamage(rightHand.getDamage() + (rightHand.getDamageModifier() * 0.002f)); + gear.add(rightHand); + } } catch (NoSpaceException ignored) { } for(Item shoe : gear){ From 9eb8d1a2b55221191a2a1c29f4fad5fa0c0e1b5a Mon Sep 17 00:00:00 2001 From: Sindusk Date: Mon, 29 Apr 2019 07:40:33 -0400 Subject: [PATCH 4/8] WyvernMods Configurable Phase 1 --- build.gradle | 3 +- mods/WyvernMods.properties | 524 ++++++++- .../java/mod/sin/items/ArrowPackHunting.java | 3 +- src/main/java/mod/sin/items/ArrowPackWar.java | 3 +- .../mod/sin/items/StatuetteCyberhusky.java | 4 +- src/main/java/mod/sin/wyvern/AntiCheat.java | 29 +- src/main/java/mod/sin/wyvern/Arena.java | 852 +++++++------- .../java/mod/sin/wyvern/GemAugmentation.java | 5 + src/main/java/mod/sin/wyvern/ItemMod.java | 2 +- src/main/java/mod/sin/wyvern/MiscChanges.java | 1007 +++++++++-------- .../java/mod/sin/wyvern/PlayerTitles.java | 192 +--- .../java/mod/sin/wyvern/QualityOfLife.java | 109 +- src/main/java/mod/sin/wyvern/WyvernMods.java | 608 ++++++++-- .../mod/sin/wyvern/bounty/PlayerBounty.java | 5 +- 14 files changed, 2163 insertions(+), 1183 deletions(-) diff --git a/build.gradle b/build.gradle index ab276ea..c5e79dc 100644 --- a/build.gradle +++ b/build.gradle @@ -11,8 +11,9 @@ repositories { } dependencies { - compile 'org.gotti.wurmunlimited:server-modlauncher:0.43-beta1' + compile 'org.gotti.wurmunlimited:server-modlauncher:0.43' compile 'com.github.Sindusk:sindusklibrary:v2.2' + compile 'com.github.bdew-wurm:bdew_server_mod_tools:v1.0.0' compile 'com.github.Sindusk:DiscordRelay:v1.2' compile 'com.github.Sindusk:DUSKombat:v1.0' compile 'com.github.Sindusk:TreasureHunting:1.1.4' diff --git a/mods/WyvernMods.properties b/mods/WyvernMods.properties index 3b8b85c..5aa6675 100644 --- a/mods/WyvernMods.properties +++ b/mods/WyvernMods.properties @@ -1,6 +1,524 @@ classname=mod.sin.wyvern.WyvernMods classpath=WyvernMods.jar sharedClassLoader=true -depend.import=SinduskLibrary,TreasureHunting,DiscordRelay -#If true, will print debug messages and log heavily. -debug=true \ No newline at end of file + +# Bdew's Server Mod Tools mod is required for operation of WyvernMods. +depend.requires=bdew_server_mod_tools + +# These other mods are required to be installed. Each one is able to be configured to avoid operation. +depend.import=SinduskLibrary,TreasureHunting,DiscordRelay,DUSKombat + +# If automata is installed, it should be loaded first to avoid conflict. It is not required. +depend.suggests=automata + +# -- Introduction -- # +# WyvernMods contains many different modules. Each configuration section is separated based on the module it controls. +# Each module has a "master" configuration which completely enables or disables the module. +# If a master configuration is disabled, all the further configurations do not need to be adjusted. +# There may also be sub-modules that can be enabled and disabled. +# Module configurations are separated by formatted comments in this configuration file: + +## >> MAJOR MODULE << ## +# > MINOR MODULE < # +# > END MINOR MODULE < # +## >> END MAJOR MODULE << ## + +# Finally, there will also be configurations which are open-ended and allow an unlimited amount of configurations. +# These configurations will be annotated with "-#" appended to the configuration. +# These will always be identified with a dash in the configuration. For example, "itemCreation-1:" +# Every individual configuration made in this way needs it's own unique number after it (called an index). +# Multiple configurations with the same index will not apply properly. Make sure each configuration has it's own unique index. +# Finally, all multiple configurations will be separated using a colon (:) instead of an equals sign (=). + +## >> MISCELLANEOUS CHANGES MODULE << ## +## The Miscellaneous Changes module includes various bugfixes and QoL improvements that affect gameplay. +enableMiscChangesModule=true + +# > INFO TAB < # +# The information tab is a tab which appears for all players on login. +enableInfoTab=true +#infoTabName: The name of the tab to display when the players log in. +infoTabName=Server +#infoTabLine-#: Line to be added to the info tab on login. +# This is a multiple configuration option. +infoTabLine-1:Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/ +infoTabLine-2:Website/Maps: https://www.sarcasuals.com/ +infoTabLine-3:Server Discord: https://discord.gg/r8QNXAC +infoTabLine-4:Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4 +infoTabLine-5:Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing +infoTabLine-6:Patreon: https://www.patreon.com/sindusk +# > END INFO TAB < # + +#ignoreBridgeChecks: Disable most bridge validity checks, allowing them to be built in/over/through houses. +ignoreBridgeChecks=true +#disableMailboxUsageWhileLoaded: Disables the usage of mailboxes while they're loaded in a vehicle. +# This option is used in tandem with the ability to allow mailboxes to be loaded. +# If they cannot be loaded, this option will do nothing. +disableMailboxUsageWhileLoaded=true +#increasedLegendaryCreatures: Changes the chances for a legendary creature (AKA "Uniques") to spawn when checked. +# This can be used for multiple purposes, including disabling natural unique spawns altogether. +# Use the next setting while this option is enabled to tweak how you want them to spawn. +increasedLegendaryCreatures=true +#increasedLegendaryFrequency: The amount of times to check for a legendary to spawn when they are checked (6 hours). +# 0 = Disable legendary creatures from spawning altogether. +# 1 = Vanilla settings for spawning legendary creatures. +# 2 = Double the default chance for legendary to spawn when checked. +# 5 = Five times the default chance for legendary to spawn when checked. +increasedLegendaryFrequency=5 +#allowFacebreykerNaturalSpawn: Adds Facebreyker (custom creature from WyvernMods) to the natural spawn list for legendary creatures. +allowFacebreykerNaturalSpawn=true +#announcePlayerTitles: When players obtain a title, there will be a server message stating they've just earned it. +# The announcement ignores any title obtained on a PvP server, as well as any titles gained by GM's (power 1 or higher). +# This will also create a message in Discord via DiscordRelay to the "event" channel. +announcePlayerTitles=true +# TODO: Allow editing the tab that it announces the title and the discord channel it sends to. +#improveCombinedLeather: If leather is able to be combined (via other configuration), it will by default prevent improving items with higher QL than the material. +# This option overrides that interaction, and allows leather of any QL be used to improve despite it being able to be combined. +improveCombinedLeather=true +#allowModdedImproveTemplates: Enables the usage of modded improve templates while improving certain items (Spectral Hide & Glimmerscale). +allowModdedImproveTemplates=true +#fatigueActionOverride: Allows players to take fatiguing actions (improve, farming, mining, etc.) while not grounded. +# This means players can mine from a wagon, farm from a cart, improve on their horse, etc. +# An exception to this is destroy actions on PvP servers. They have special handling to disable their usage while mounted. +fatigueActionOverride=true +#fixPortalIssues: Fixes some kind of portal issues. Don't remember what caused this change to be made or what it does. +fixPortalIssues=true +#disableMinimumShieldDamage: By default, shields take a minimum of 0.01 damage each time they're hit. +# This option disables that threshhold and allows shields to take less than 0.01 damage when hit. +# Specifically, if a shield is made of adamantine or similar, it would always take less damage than one made from iron. +disableMinimumShieldDamage=true +#disableGMEmoteLimit: By default, players must wait 5 seconds before the sound from another emote will play. +# This option allows GM's (power 1 or higher) to bypass this limit. +# This change was made so I could rapidly slap my GM's or players when they upset me by binding a key with Bdew's custom actions mod. +# Instead of only seeing the event tab messages from the slap assault, they would also hear each and every excruciating slap. +disableGMEmoteLimit=true +#creatureArcheryWander: When a creature is struck by an arrow from a long distance, they will fail to acquire the player as a target. +# This prevents them from moving in to attack someone who is archering them. +# In some cases, players were able to abuse this to gain archery skill at zero risk. +# This option makes creatures wander slightly in a random direction after being hit by archery. +# Usually, this results in them moving close enough to the player to acquire them as a target +# and engage them in melee combat or far enough the player cannot archer anymore. +creatureArcheryWander=true +#globalDeathTabs: Broadcast death tabs to GL-Freedom on all servers. +# This does not override the Deaths tab on the server the player died on. +# It just humiliates them globally instead of just on that server. +globalDeathTabs=true +#disablePvPOnlyDeathTabs: Allows PvP deaths on a PvE server to be broadcast in the Deaths tab. +disablePvPOnlyDeathTabs=true +#fixLibilaCrossingIssues: There were issues where Libila priest faith would reset when crossing servers. +# This was a fix attempted to prevent it. It may no longer be necessary as of the 1.9 Priest Update but does no harm being enabled. +fixLibilaCrossingIssues=true +#higherFoodAffinities: Increases the potency of food affinity skill gains from 10% to 30%. +higherFoodAffinities=true +#TODO: Allow adjustment of the percentage increase (and potentially reduction) of food affinities. +#fasterCharcoalBurn: Increases the rate at which charcoal burns by double. +# It does this by triggering the "production" each time it ticks twice, applying double damage afterwards. +# It will produce the same amount of resources, but do so twice as quickly. +fasterCharcoalBurn=true +#TODO: Allow further adjustment of the rate at which charcoal burns. +#uncapTraderItemCount: By default, traders can only show 9 of each item they have in stock. +# This option removes that cap, and allows them to show their full stock of each item. +uncapTraderItemCount=true +#logExcessiveActions: Log any player performing more than 10 commands in a single second. +# This is useful to catch potential macro's, but also has false positives! +# It will log players who hold down a key for a command for example. +logExcessiveActions=true + +# > DYNAMIC SKILL RATE < # +# Dynamic Skill Rate is a new skill rate system that adjusts the skill gain rate as skill increase. +# For reference, please see the Revenant Skill Gain graph: https://i.imgur.com/XQeMJjV.png +useDynamicSkillRate=true +#TODO: Add options to adjust the dynamic skill gain rates. +#> END DYNAMIC SKILL RATE < # + +#reduceLockpickBreaking: Adds 40QL to the calculations when a lockpick is checking whether it should break. +# This results in a much lower rate of lockpicks breaking. They still take damage when lockpicking. +reduceLockpickBreaking=true +#allowFreedomMyceliumAbsorb: Allows players on Freedom servers that follow Libila to absorb mycelium. +allowFreedomMyceliumAbsorb=true +#largerHouses: Doubles the size that players can construct buildings. +# It does this by multiplying their effective carpentry during planning checks. +largerHouses=true +#TODO: Add option to adjust the carpentry multiplier. +#reduceImbuePower: Reduces the amount of power applied by smearing imbues. +# This does not affect their functionality, simply reduces the amount of power applied per imbue to 1/5th. +reduceImbuePower=true +#TODO: Add option to adjust multiplier on imbue power. +#fixVehicleSpeeds: When updating the speed of a vehicle, the vanilla code uses a random check to determine whether to update. +# This creates scenarios where the speed of a vehicle does not update properly for a long duration. +# For example, when archering a horse, it could take anywhere from 1 to 20 seconds for the speed to properly reduce. +# This option removes that random check and forces it to update immediately whenever the vehicle speed would change. +fixVehicleSpeeds=true +#reduceMailingCosts: Reduces mailing costs from 1 copper to 10 iron. +reduceMailingCosts=true +#TODO: Add option to adjust mailing cost to a percentage of default. +#guardTargetChanges: Prevent guards from assisting in combat with some of the stronger modded creatures. +# Includes: Legendary Creatures, Titans, and Rare Spawns. +guardTargetChanges=true +#enableLibilaStrongwallPvE: Enables Strongwall for Libila on Freedom/PvE servers. +enableLibilaStrongwallPvE=true +#royalCookNoFoodDecay: Royal Cooks (kingdom title) will create "royal" food which is immune to decay. +royalCookNoFoodDecay=true +#mayorsCommandAbandonedVehicles: Allows mayors to take temporary command of vehicles abandoned on their deed. +# This does not allow them to access the contents/hold of the vehicle. +# They can only command the vehicle if it is within their village. +# The vehicle must belong to a player who has not logged in for 7 days. +# If they move the vehicle off their deed and disembark, they will no longer be able to command it. +mayorsCommandAbandonedVehicles=true +#opulenceFoodAffinityTimerIncrease: Adds 0.25% increased timer per power of opulence on a food. +# Example: Food grants 1 minute per bite. With 100 Opulence, it would gain 25% increased timer, giving 1.25 minutes per bite. +opulenceFoodAffinityTimerIncrease=true +#TODO: Add option to configure the amount of increase per opulence power. [Side-note: Maybe add to Spellcraft instead] +#disableFoodFirstBiteBonus: By default, when eating food the affinity timer will give 10x longer duration on the first bite. +# This creates a meta where taking a single bite out of a good affinity meal then waiting for the buff to expire is optimal to conserve food. +# This option disables that first bite bonus, making each bite grant the same duration regardless of whether it's the first +# bite or if they're adding onto an already existing food affinity timer. +disableFoodFirstBiteBonus=true +#bedQualitySleepBonus: The quality of the bed a player sleeps in will increase the amount of sleep bonus obtained after waking up. +# The increase in sleep bonus is equivalent to 0.5% more per QL of the bed. At 100QL, the bed will grant 50% more sleep bonus. +bedQualitySleepBonus=true +#TODO: Add option to configure the amount of bonus the bed QL grants. +#royalSmithImproveFaster: Royal Smiths (kingdom title) will improve smithing items 10% faster. +# This bonus is comparable to having 10 additional Wind of Ages power on the tools using to improve with. +royalSmithImproveFaster=true +#TODO: Add option to configure improve speed bonus. +#fixMountedBodyStrength: When body strength is modded to allow higher carry weights, mounts do not register the increase. +# Issues such as being unable to move on a horse because it thinks you're over encumbered begin to crop up. +# This option fixes that interaction by making the code which handles mounted encumberance to adjust for the increase in strength. +fixMountedBodyStrength=true +#adjustedFoodBiteFill: Adjusts the amount of fill from foods from being linear along the QL axis. +# Instead, it grants more fill than usual at lower QL, but drops off to less fill per QL at higher QL. +# See this graph for the difference: https://i.imgur.com/RsBo86z.png +adjustedFoodBiteFill=true +#TODO: Add additional options to configure the amount of food fill. +#rareMaterialImprove: Allows rare materials to potentially transfer rarity when improving normally, instead of only when consumed. +# This prevents players from being punished by combining rare materials, and offers a more intuitive approach to using rare materials. +rareMaterialImprove=true +#rarityWindowBadLuckProtection: This provides a new system that creates "bad luck protection" in rarity windows. +# Instead of being entirely random, the chance for a rarity window will increase each time the roll fails. +# Every time the roll succeeds, the chance will decrease to adjust. This creates a more even spread of RNG. +# Mathematically, this also helps prevent outliers such as having multiple rarity windows in a row or the opposite of not having any for a long duration. +rarityWindowBadLuckProtection=true +#rareCreationAdjustments: Rarity from creation materials will apply when creating new items. +# The following system only applies to items which are created in their entirety from two consumable resources. +# For example, using a rare handle and a rare sword blade to create a sword would use this system. +# Using a rare anvil and a rare lump will not use this system, since the anvil is not consumed in the process. +# Metallurgy does work. Using rare charcoal with rare iron will produce rare steel, for example. +# When the item is created, it will roll randomly between the two rarities of the resources used to create it, distributed equally. +# For example, using a rare handle with a supreme blade will give a 50% chance at a rare, and 50% chance at a supreme. +# Using a normal handle on that same supreme blade would yield a 33% chance at normal, 33% chance at rare, and 33% chance at supreme. +# Using a fantastic handle on the supreme blade would offer a 50% chance at supreme, 50% chance on fantastic. +# If both items are the same rarity, it completely guarantees that the resulting item will be the same rarity. +# A fantastic handle and a fantstic blade will always create a fantastic sword. +rareCreationAdjustments=true +#alwaysArmourTitleBenefits: Armour titles grant a bonus to improvement when equipped. +# This option grants these bonuses at all times even if the title is not equipped. +alwaysArmourTitleBenefits=true +#tomeUsageAnyAltar: Allows sorcery tomes to be used at any 3x3 flat altar. +# This removes height restrictions, being near water, in a cave, etc. Any flat 3x3 area with an altar will work to use the tome. +tomeUsageAnyAltar=true +#keyOfHeavensLoginOnly: Forces Key of the Heavens to only be able to be used on the login server. +# This is done to prevent issues with deity generation. +keyOfHeavensLoginOnly=true +#lessFillingDrinks: Makes drinks (not water) fill less of the water bar (roughly 1/5 as much as default). +# This allows players to get more use out of affinity drinks. +lessFillingDrinks=true +#TODO: Add additional options to adjust how much less filling drinks are. +#disableHelpGMCommands: Disables GM commands from appearing for non-GM's when using /help. This is a bug with the vanilla game. +disableHelpGMCommands=true +#reduceActionInterruptOnDamage: Reduces the chances of actions being interrupted when taking damage. +# The reduction should be something around 1/2 as likely to be interrupted, though it's hard to tell for sure. +reduceActionInterruptOnDamage=true +#TODO: Add multiplier option for chance to be interrupted. +#fixMissionNullPointerException: In rare instances, the Epic Mission system can fail to properly intialize it's item template list. +# When this happens, there's a chance that another function will call for a random item template. +# Upon execution, it fails to find a random template and crashes the server with a Null Pointer Exception. +# This option fixes this issue and will initialize the list if one does not exist when the server calls for a random template. +fixMissionNullPointerException=true +#disableSmeltingPots: Simply disables the functionality of smelting pots. +# Smelting pots will still exist, but it will display an error "Smelting is disabled." when attempting to smelt. +disableSmeltingPots=true +#hideSorceryBuffBar: Hides the buff icons for sorceries. They can still be found in the Spell Effects window. +hideSorceryBuffBar=true +#sqlAchievementFix: Fixes the errors that occur with achievements in SQL in WU 1.9. +sqlAchievementFix=true + +## >> END MISCELLANEOUS CHANGES MODULE << ## + +## >> ARENA MODULE << ## +## The Arena Module handles many miscellaneous tweaks and additions specific to PvP servers. +## Some of the options here can also have positive impact on PvE servers and were configured here because there was +## overlap in the code where the functionality for Arena-specific features had to be made. +enableArenaModule=true + +#equipHorseGearByLeading: Allow players to equip horse gear by simply leading. +# If enabled, this also allows GM's (power 1 and higher) to bypass all restrictions for equipping items on creatures for both PvE and PvP servers. +equipHorseGearByLeading=true +#lockpickingImprovements: Reduces the restrictions for allowing lockpicking. +# On PvP servers, this will make it so basically any container is able to be lockpicked by anyone without permissions getting in the way. +# On PvE servers, this allows players to lockpick chests which are not owned by a player (such as treasure chests from TreasureHunting mod). +lockpickingImprovements=true +#placeDeedsOutsideKingdomInfluence: Allows placing deeds outside of kingdom influence for all kingdoms. +# Keep in mind this also removes the requirement of creating a tower before planting a deed. +placeDeedsOutsideKingdomInfluence=true +#disablePMKs: Disables the ability to create a Player Made Kingdom. +disablePMKs=true +#disablePlayerChampions: Disables the ability for players to become a Champion. +disablePlayerChampions=true +#arenaAggression: Adjusts the aggression for creatures and players towards other players to fit a same-kingdom PvP environment. +arenaAggression=true +#enemyTitleHook: Allows (ENEMY) to be appended to players who are hostile towards eachother in a same-kingdom PvP environment. +# On PvE servers, this also the hook for the extra custom title module. +enemyTitleHook=true +#enemyPresenceOnAggression: Adjusts the enemy presence mechanic to work based on the aggression of a player instead of kingdom. +# By default, in same-kingdom PvP enviornments, a player of the same kingdom will not apply enemy presence in local. +# This option makes it so even if the player is in the same kingdom, if they are considered hostile to the player they will apply enemy presence. +enemyPresenceOnAggression=true +#disableFarwalkerItems: Disables farwalker twigs and farwalker stones on PvP servers. +disableFarwalkerItems=true +#alwaysAllowAffinitySteal: Always allow players to steal affinities from players they slay in PvP combat. +alwaysAllowAffinitySteal=true +#adjustFightSkillGain: Increases fight skill gained on PvP servers by 50%. +# It does this by adding an additional tick of fight skill gain equivalent to 50% of the first tick. +adjustFightSkillGain=true +#TODO: Add additional option to adjust fight skill gain multiplier. +#useAggressionForNearbyEnemies: Changes the check for nearby enemies to use aggression instead of kingdom checks. +# This option is meant to help enable same-kingdom PvP environments. +useAggressionForNearbyEnemies=true +#disablePvPCorpseProtection: Disables the loot protection systems on corpses on PvP servers. +# This allows anyone, regardless of permission status, to loot a corpse when it drops. +disablePvPCorpseProtection=true +#bypassHousePermissions: This bypasses most of the permissions and restriction checks in houses for players on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +bypassHousePermissions=true +#allowStealingAgainstDeityWishes: Allows players to steal items against their deity wishes without being punished on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +allowStealingAgainstDeityWishes=true +#sameKingdomVehicleTheft: When a vehicle is unlocked, enemy kingdom players can "take ownership" by commanding the vehicle. +# This option is meant to help enable same-kingdom PvP environments by allowing players to take ownership +# of an unlocked vehicle even if it belongs to a player in the same kingdom as them. +sameKingdomVehicleTheft=true +#adjustMineDoorDamage: Increases the amount of damage done by bashing mine doors by 3x on PvP servers. +adjustMineDoorDamage=true +#TODO: Add option to adjust how much to multiply bash damage by. +#sameKingdomPermissionsAdjustments: Various adjustments to same-kingdom permissions. +# This option is meant to help enable same-kingdom PvP environments. +sameKingdomPermissionsAdjustments=true +#disableCAHelpOnPvP: Disables players from seeing the CA HELP window on PvP servers. +# This can be abused to allow players to see enemy CA's who are online. +disableCAHelpOnPvP=true +#sameKingdomVillageWarfare: Makes players in a village enemies with all other villages that are not in their alliance. +# This option is meant to help enable same-kingdom PvP environments. +sameKingdomVillageWarfare=true +#adjustHotARewards: Adjusts the rewards from winning Hunt of the Ancients. +# Keep in mind one of the rewards that gets added with this option is a key fragment (1/50th of a key of the heavens). +adjustHotARewards=true +#TODO: Add options to further customize the rewards from HotA. +#capMaximumGuards: Caps the maximum amount of guards in a village to 5. +capMaximumGuards=true +#TODO: Add option to configure maximum amount of guards. +#disableTowerConstruction: Disables the ability to construct towers on PvP servers. +# This does not remove existing towers or disable them from being spawned in by GM's. +disableTowerConstruction=true +#adjustLocalRange: Changes the local range on PvP servers from 80 tiles to 50 tiles. +adjustLocalRange=true +#TODO: Add option to configure new local range. +#disableKarmaTeleport: Disables the ability to use Karma Teleport on PvP servers. +disableKarmaTeleport=true +#limitLeadCreatures: Limits the amount of creatures players can lead on PvP servers to 1. +limitLeadCreatures=true +#TODO: Add option to configure how many creatures players can lead at a time. +#adjustBashTimer: Doubles the bash timer for destroying walls/structures. +# This option can be useful for high action speed servers, as the destroy timers are affected by action time multipliers. +adjustBashTimer=true +#TODO: Add option to adjust the base bash timer. +#discordRelayHotAMessages: Adds HotA messages to Discord Relay. +discordRelayHotAMessages=true +#TODO: Add this option to DiscordRelay instead with configuration of channel and similar. +#allowAttackingSameKingdomGuards: Allows players to attack guards of the same kingdom. +# This option is meant to help enable same-kingdom PvP environments. +allowAttackingSameKingdomGuards=true +#fixGuardsAttackingThemselves: If the server is configured for same-kingdom PvP, you can sometimes run into an issue. +# Guards will attempt to target themselves and see themselves as enemies, and try to attack themselves. +# Luckily the game does not allow them to fight themselves. However, they will spam the local log with messages. +# If you encounter this issue, enable this option to stop them from being stupid. +fixGuardsAttackingThemselves=true +#reducedMineDoorOpenTime: Reduces the amount of time a mine door stays open when an enemy passes through from 120 seconds to 30 seconds. +reducedMineDoorOpenTime=true +#allowSameKingdomFightSkillGains: Allow players to gain fight skill from killing members of the same kingdom. +# This option is meant to help enable same-kingdom PvP environments. +allowSameKingdomFightSkillGains=true +#allowArcheringOnSameKingdomDeeds: Allows archery against other players while they are on a same-kingdom deed. +# This option is meant to help enable same-kingdom PvP environments. +allowArcheringOnSameKingdomDeeds=true +#sendNewSpawnQuestionOnPvP: A new spawn question created when a player dies. +# The new spawn question allows them to respawn on another server instead of the one they died on. +# WARNING: I highly recommend disabling this option as it will not work on most servers. +sendNewSpawnQuestionOnPvP=true +#TODO: Improve this option into a minor module and make the new spawn question function well for servers that are not Revenant. +#sendArtifactDigsToDiscord: When a player digs up an artifact, this option will announce the artifact message in Discord. +# The message will be identical to the one found in the Area History for the server. +sendArtifactDigsToDiscord=true +#TODO: Add this option to DiscordRelay instead with configuration of channel and similar. +#makeFreedomFavoredKingdom: Makes Freedom always the favored kingdom on the server. Affects both PvE and PvP servers. +# This option is specifically meant to prevent PvP servers from creating epic missions which favor inactive kingdoms. +# In that way, it is sort of meant to enable same-kingdom PvP environments, but can be useful in other senses as well. +makeFreedomFavoredKingdom=true +#crownInfluenceOnAggression: Converts the Crown of Might influence effect (that grants CR) to affect allies instead of kingdom. +# This option is meant to help enable same-kingdom PvP environments. +crownInfluenceOnAggression=true +#disableOWFL: Disables players from dropping items on their corpse on PvP servers. This option will have no effect on PvE servers. +# OWFL = Open World Full Loot. This option is designed to make a PvP environment where players do not lose their inventory on death. +# This option essentially operates by making an always-functioning resurrection stone apply to every player that dies. +disableOWFL=true +#resurrectionStonesProtectSkill: Players with a resurrection stone will not lose skill upon death. Affects both PvE and PvP servers. +resurrectionStonesProtectSkill=true +#resurrectionStonesProtectFightSkill: Players with a resurrection stone will not lose fighting skill upon death. Affects both PvE and PvP servers. +resurrectionStonesProtectFightSkill=true +#resurrectionStonesProtectAffinities: Players with a resurrection stone will not lose affinities on death on PvP servers. +resurrectionStonesProtectAffinities=true +#bypassPlantedPermissionChecks: Removes all permission checks for if a player can move a planted item on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +bypassPlantedPermissionChecks=true + +## >> END ARENA MODULE << ## + +## >> CUSTOM TITLES MODULE << ## +## The Custom Titles Module allows configuration and addition of new titles. +enableCustomTitlesModule=true + +#addCustomTitle-#: Adds a custom title. Format: addTitle-#:titleId,maleTitle,femaleTitle,skillId,titleType +# titleId = Some value, preferably greater than 1000, used to index the title that you're adding. These need to be unique to each title. +# maleTitle = The title name when a male character is using the title. +# femaleTitle = The title name when a female character is using the title. +# skillId = The ID of the skill to award this title for. If you don't want to attach this to a skill or don't know what this means, use -1 to disable. +# titleType = The skill level to award at. NORMAL (50), MINOR (70), MASTER (90), LEGENDARY (100). If you aren't using a skillId, then use NORMAL. +addCustomTitle-1:19999,Patron,Patron,-1,NORMAL +addCustomTitle-2:20000,Donator,Donator,-1,NORMAL +addCustomTitle-3:20001,Sindusks Favourite GM,Sindusk Favourite GM,-1,NORMAL +addCustomTitle-4:20002,That Guy,That Guy,-1,NORMAL +addCustomTitle-5:20003,Warriorgens Wife,Warriorgens Wife,-1,NORMAL +addCustomTitle-6:20004,Thorn One,Thorn One,-1,NORMAL +addCustomTitle-7:20005,The care-dependent,The care-dependent,-1,NORMAL +addCustomTitle-8:20006,The Treasuring,The Treasuring,-1,NORMAL +addCustomTitle-9:20007,Science Guy,Science Guy,-1,NORMAL +addCustomTitle-10:20008,Grand Designer,Grand Designer,-1,NORMAL +addCustomTitle-11:20009,The Crazy Cat Lord,The Crazy Cat Lord,-1,NORMAL +addCustomTitle-12:20010,Slave,Slave,-1,NORMAL +addCustomTitle-13:20011,The One True Taco,The One True Taco,-1,NORMAL +addCustomTitle-14:20012,The Great Illuminaty,The Great Illuminaty,-1,NORMAL + +# Event Titles +addCustomTitle-100:10002,Pastamancer,Pastamancer,-1,NORMAL + +#awardTitle-#: Awards a title to a player on their next login. Format: awardTitle-#:titleId,playerName,playerName,playerName... +# titleId = The id of the title to award the player. This can be the ID of a default title or custom title. Both will work. +# playerName = The name of the player to award the title to. +# - The playerName option can be repeated for as many players you want to award the title to. +# Example: awardTitle-1:10000,Sindusk,Sindawn,Sinsalt +# If a player already has the title, the system will identify they've already received the title. +# It's safe to leave configurations here for players who have already claimed their title. +awardTitle-1:19999,Atticus +awardTitle-2:20000,Pazza,Warriorgen,Eternallove,Bambam,Svenja,Alexiaselena,Reevi,Seleas,Piratemax,Eltacolad +awardTitle-3:20001,Pazza +awardTitle-4:20002,Warriorgen +awardTitle-5:20003,Eternallove +awardTitle-6:20004,Bambam +awardTitle-7:20005,Svenja +awardTitle-8:20006,Alexiaselena +awardTitle-9:20007,Reevi +awardTitle-10:20008,Genocide +awardTitle-11:20009,Seleas +awardTitle-12:20010,Piratemax +awardTitle-13:20011,Eltacolad +awardTitle-14:20012,Atticus + +# Event Titles +awardTitle-100:10002,Critias + +## >> END CUSTOM TITLES MODULE << ## + +## >> ANTI-CHEAT MODULE << ## +## The Anti-Cheat Module helps mitigate client mods that allow players to utilize data that should never be sent. +## Wyvern Anti-Cheat does NOT prevent ESP mods. +## It does, however, do a fairly effective job at limiting the use of X-Ray and livemap for detecting ores they should not see. +enableAntiCheatModule=true + +# > SPOOF HIDDEN ORE < # +# Spoofing hidden ore is the process of falsifying information sent to the client to hide ore they should not be able to see. +# This process works by the server identifying whether or not a player should be able to see a vein of ore through various checks. +# For example, if a vein is surrounded by 4 cave walls, the player should not be able to see that ore since it's completely surrounded. +# This system will "spoof" the data sent from the server to clients in the strip (area) around the vein as normal rock. +# This prevents anyone from using a client mod to see the vein (X-Ray or Livemap for example) which would normally be obscured from view. +# The system will have no effect on veins which players should normally be able to see. Exposed veins are not spoofed. +# Finally, this is also unable to be countered through any client modding efforts. Since there is no difference between the data +# that is sent instead of a normal rock vein, no amount of client modding would be able to surpass this anti-cheat method. +enableSpoofHiddenOre=true +#prospectingVision: This system allows players with high prospecting skill to bypass the spoof system to a certain extent. +# In it's current implementation, after 20 prospecting, players will be allowed to see 1 tile out per 18 prospecting levels. +# For example, a player with 50 prospecting skill would receive proper information to their client up to 3 tiles into a wall. +# This system is meant to give information to players about what exists in a cave system without requiring them to prospect every wall. +prospectingVision=true +#TODO: Add additional options to the spoof hidden ore minor module to configure further operation. + +# > END SPOOF HIDDEN ORE < # + +#mapSteamIds: This option will map player SteamID's to their name in the modsupport database under SteamIdMap. +# Since this option's creation, there has been a STEAM_IDS table added to the wurmplayers database by default which logs Steam ID's on each login. +# The default system works by logging the access times for each Steam ID and when it was connected, alongside the duration of the login. +# Overall, the default system is more accurate, but it's also quite difficult to read at a glance. +# Viewing a single player's Steam ID will require cross referencing their player WurmID with the PLAYERS table. +# What this option does is make a table that is simply NAME and STEAMID, with one unique entry each. +# This makes it very easy to find a player's Steam ID and ban it, if necessary. +# Additionally, it makes it simple to know all the SteamID's which have been used to access a single account. +# ! This table & option is also required for other certain functions in WyvernMods ! +mapSteamIds=true + +## >> END ANTI-CHEAT MODULE << ## + +## >> QUALITY OF LIFE MODULE << ## +## The Quality Of Life Module includes some additions that improve the general quality of life of gameplay. +## Many of these options are built with a mindset of enhancing the play of normal players, +## but can be abused to significant gain by those who see them as an opportunity to make cheating easier. +## It's important to think of the abuse cases and whether or not you're okay with those abuse cases being +## available before enabling this module or its features. +enableQualityOfLifeModule=true + +#mineCaveToVehicle: Allows mining from cave wall directly into a vehicle while commander. +# Requires the fatigue action override under Misc Changes Module to function (otherwise you cannot mine while commanding a vehicle). +# When enabled, this will also deposit the ore directly into a BSB until full if one exists. +# If no BSB exists, it will deposit to crates until full. +# If no crates exist in the vehicle, it will simply mine into the cargo hold of the vehicle until it's full. +# If there is no space in the vehicle for the ore, it will mine to ground as normal until a full pile exists. +mineCaveToVehicle=true +#mineSurfaceToVehicle: Allows surface mining directly into a vehicle while commanding. +# This option is identical to mineCaveToVehicle, but applies to surface mining instead. +# Also requires fatigue action override in Misc Changes Module to function. +mineSurfaceToVehicle=true +#chopLogsToVehicle: Allows chopping up logs directly into a vehicle while commander. +# This option is identical to mineCaveToVehicle, but applies to chopping up logs instead. +# Also requires fatigue action override in Misc Changes Module to function. +chopLogsToVehicle=true +#statuetteAnyMaterial: Allows casting using a statuette of any material. +# By default, a statuette that is not made of gold or silver will not work for spell casting. +# This option changes that functionality by disregarding the material and only checking the item itself. +# Will not allow players to use incorrect statuettes for casting (such as statuette of Fo to cast as a Vynora priest). +statuetteAnyMaterial=true +#mineGemsToVehicle: Allows mining gems and other materials (like salt) directly to vehicle. +# This option is identical to mineCaveToVehicle, but handles tertiary materials like gems and salt instead. +# Also requires fatigue action override in Misc Changes Module to function. +mineGemsToVehicle=true +#regenerateStaminaOnVehicleAnySlope: Allows players to regenerate stamina while on a vehicle regardless of the slope underneath the vehicle. +# By default, if you are on a slope greater than 20 while on a vehicle, you do not regenerate stamina. +# This option removes the 20 slope limitation and allows players to regenerate stamina while on a vehicle so long as they are stationary. +regenerateStaminaOnVehicleAnySlope=true + +## >> END QUALITY OF LIFE MODULE << ## + +## >> TREASURE CHEST LOOT MODULE << ## +## The Treasure Chest Loot Module affects the vanilla treasure chests. +## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them. +enableTreasureChestLootModule=true + +# TODO: Add additional options to configure the loot granted from treasure chests. +## >> END TREASURE CHEST LOOT MODULE << ## diff --git a/src/main/java/mod/sin/items/ArrowPackHunting.java b/src/main/java/mod/sin/items/ArrowPackHunting.java index 8d26c97..bd5d867 100644 --- a/src/main/java/mod/sin/items/ArrowPackHunting.java +++ b/src/main/java/mod/sin/items/ArrowPackHunting.java @@ -28,7 +28,8 @@ public class ArrowPackHunting { itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_REPAIRABLE, - ItemTypes.ITEM_TYPE_WOOD + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON }); itemBuilder.imageNumber((short) 760); itemBuilder.behaviourType((short) 1); diff --git a/src/main/java/mod/sin/items/ArrowPackWar.java b/src/main/java/mod/sin/items/ArrowPackWar.java index 30bd72a..b9421a7 100644 --- a/src/main/java/mod/sin/items/ArrowPackWar.java +++ b/src/main/java/mod/sin/items/ArrowPackWar.java @@ -28,7 +28,8 @@ public class ArrowPackWar { itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_REPAIRABLE, - ItemTypes.ITEM_TYPE_WOOD + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON }); itemBuilder.imageNumber((short) 760); itemBuilder.behaviourType((short) 1); diff --git a/src/main/java/mod/sin/items/StatuetteCyberhusky.java b/src/main/java/mod/sin/items/StatuetteCyberhusky.java index 1923f25..9200543 100644 --- a/src/main/java/mod/sin/items/StatuetteCyberhusky.java +++ b/src/main/java/mod/sin/items/StatuetteCyberhusky.java @@ -17,10 +17,10 @@ import com.wurmonline.server.skills.SkillList; public class StatuetteCyberhusky implements ItemTypes, MiscConstants { public static Logger logger = Logger.getLogger(StatuetteCyberhusky.class.getName()); public static int templateId; - private String name = "statuette of Cyberhusky"; + private String name = "statuette of Reevi"; public void createTemplate() throws IOException{ ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.statuette.cyberhusky"); - itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Cyberhusky."); + itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Reevi."); itemBuilder.itemTypes(new short[]{ // {108, 52, 22, 44, 87, 92, 147} - Statuette ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_DECORATION, diff --git a/src/main/java/mod/sin/wyvern/AntiCheat.java b/src/main/java/mod/sin/wyvern/AntiCheat.java index a1fbd3d..bc29506 100644 --- a/src/main/java/mod/sin/wyvern/AntiCheat.java +++ b/src/main/java/mod/sin/wyvern/AntiCheat.java @@ -121,7 +121,7 @@ public class AntiCheat { return false; } private static int getDummyWallAntiCheat(int tilex, int tiley){ - return Tiles.encode(Tiles.decodeHeight(Server.caveMesh.data[tilex | tiley << Constants.meshSize]), Tiles.Tile.TILE_CAVE_WALL.id, Tiles.decodeData((int)Server.caveMesh.data[tilex | tiley << Constants.meshSize])); + return Tiles.encode(Tiles.decodeHeight(Server.caveMesh.data[tilex | tiley << Constants.meshSize]), Tiles.Tile.TILE_CAVE_WALL.id, Tiles.decodeData(Server.caveMesh.data[tilex | tiley << Constants.meshSize])); } public static void sendCaveStripAntiCheat(Communicator comm, short xStart, short yStart, int width, int height){ if (comm.player != null && comm.player.hasLink()) { @@ -149,7 +149,7 @@ public class AntiCheat { if(!(Tiles.decodeType(Server.caveMesh.getTile(xx, yy)) == Tiles.Tile.TILE_CAVE_EXIT.id)){ if(prospecting < 20 && isSurroundedByCaveWalls(xx, yy)){ bb.putInt(getDummyWallAntiCheat(xx, yy)); - }else if(prospecting > 20 && playerCanSeeVein(xx, yy, distance)){ + }else if(WyvernMods.prospectingVision && prospecting > 20 && playerCanSeeVein(xx, yy, distance)){ bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); }else if(!isSurroundedByCaveWalls(xx, yy)){ bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); @@ -178,6 +178,8 @@ public class AntiCheat { } } } + + @Deprecated public static boolean isVisibleThroughTerrain(Creature performer, Creature defender){ int trees = 0; //int treetilex = -1; @@ -230,6 +232,8 @@ public class AntiCheat { } return true; } + + @Deprecated public static boolean isVisibleToAntiCheat(Creature cret, Creature watcher) { if (!cret.isVisible()) { return cret.getPower() > 0 && cret.getPower() <= watcher.getPower(); @@ -276,17 +280,18 @@ public class AntiCheat { String replace; // - Change the caveStrip method to the custom one, so we can edit what the clients see! - // - CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "{ mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$); }"; - Util.setBodyDeclared(thisClass, ctCommunicator, "sendCaveStrip", replace); - /*ctCommunicator.getDeclaredMethod("sendCaveStrip").setBody("{" - + " mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$);" - + "}");*/ + if (WyvernMods.enableSpoofHiddenOre) { + CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); + replace = "{ mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$); }"; + Util.setBodyDeclared(thisClass, ctCommunicator, "sendCaveStrip", replace); + } - Util.setReason("Map Steam ID's to Modsupport table."); - CtClass ctLoginHandler = classPool.get("com.wurmonline.server.LoginHandler"); - replace = AntiCheat.class.getName()+".mapPlayerSteamId($1, $2);"; - Util.insertBeforeDeclared(thisClass, ctLoginHandler, "preValidateLogin", replace); + if (WyvernMods.mapSteamIds) { + Util.setReason("Map Steam ID's to Modsupport table."); + CtClass ctLoginHandler = classPool.get("com.wurmonline.server.LoginHandler"); + replace = AntiCheat.class.getName() + ".mapPlayerSteamId($1, $2);"; + Util.insertBeforeDeclared(thisClass, ctLoginHandler, "preValidateLogin", replace); + } // - Change the creature isVisibleTo method to the custom one, so we can edit what the clients see! - // /*CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index 9ca0b76..b770a58 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -216,31 +216,19 @@ public class Arena { // - Allow horse gear to be added/removed from horses without branding or taming (PvP Only) - // CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "if(this.player.getPower() > 0){" + - " $_ = this.player;" + - "}else if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" - + " $_ = owner.getLeader();" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "getDominator", replace); - Util.instrumentDeclared(thisClass, ctCommunicator, "equipCreatureCheck", "getDominator", replace); - /*ctCommunicator.getDeclaredMethod("reallyHandle_CMD_MOVE_INVENTORY").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getDominator")) { - m.replace("if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" - + " $_ = owner.getLeader();" - + "}else{" - + " if(this.player.getPower() > 0){" - + " $_ = this.player;" - + " }else{" - + " $_ = $proceed($$);" - + " }" - + "}"); - return; - } - } - });*/ + if (WyvernMods.equipHorseGearByLeading) { + Util.setReason("Allow equipping horse gear without taming."); + replace = "if(this.player.getPower() > 0){" + + " $_ = this.player;" + + "}else if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" + + " $_ = owner.getLeader();" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "getDominator", replace); + Util.setReason("Allow equipping horse gear without taming."); + Util.instrumentDeclared(thisClass, ctCommunicator, "equipCreatureCheck", "getDominator", replace); + } // - Allow lockpicking on PvP server, as well as treasure chests on PvE - // CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); @@ -256,69 +244,72 @@ public class Arena { CtClass.floatType }; String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); - Util.setReason("Allow lockpicking on the PvP server and improve PvE treasure chest lockpicking."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = target.getLastOwnerId() == -10 || target.getLastOwnerId() == 0 || target.getTemplateId() == 995;" - + "}"; - Util.instrumentDescribed(thisClass, ctItemBehaviour, "action", desc1, "isInPvPZone", replace); - CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "$_ = $proceed($$);" - + "if($_ == -10 || $_ == 0){ ok = true; }"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "picklock", "getLastOwnerId", replace); - /*ctMethodsItems.getDeclaredMethod("picklock").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getLastOwnerId")) { - m.replace("$_ = $proceed($$);" - + "if($_ == -10 || $_ == 0){ ok = true; }"); - return; - } - } - });*/ + if (WyvernMods.lockpickingImprovements) { + Util.setReason("Allow lockpicking on the PvP server and improve PvE treasure chest lockpicking."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = target.getLastOwnerId() == -10 || target.getLastOwnerId() == 0 || target.getTemplateId() == 995;" + + "}"; + Util.instrumentDescribed(thisClass, ctItemBehaviour, "action", desc1, "isInPvPZone", replace); + + Util.setReason("Allow lockpicking if a container is not owned by a player."); + replace = "$_ = $proceed($$);" + + "if($_ == -10 || $_ == 0){ ok = true; }"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "picklock", "getLastOwnerId", replace); + } // - Disable villages and PMK's on the PvP server - // CtClass ctVillageFoundationQuestion = classPool.get("com.wurmonline.server.questions.VillageFoundationQuestion"); - Util.setReason("Allow placing deed outside of kingdom border."); - replace = "$_ = (byte) 4;"; - Util.instrumentDeclared(thisClass, ctVillageFoundationQuestion, "checkSize", "getKingdom", replace); + if (WyvernMods.placeDeedsOutsideKingdomInfluence) { + Util.setReason("Allow placing deed outside of kingdom border."); + replace = "$_ = (byte) 4;"; + Util.instrumentDeclared(thisClass, ctVillageFoundationQuestion, "checkSize", "getKingdom", replace); + } CtClass ctKingdomFoundationQuestion = classPool.get("com.wurmonline.server.questions.KingdomFoundationQuestion"); - Util.setReason("Disable PMK's on the Arena server."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Player-Made Kingdoms are disabled on this server.\");" - + " return;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctKingdomFoundationQuestion, "sendQuestion", replace); + if (WyvernMods.disablePMKs) { + Util.setReason("Disable PMK's on the Arena server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Player-Made Kingdoms are disabled on this server.\");" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctKingdomFoundationQuestion, "sendQuestion", replace); + } // - Disable champion players altogether - // CtClass ctRealDeathQuestion = classPool.get("com.wurmonline.server.questions.RealDeathQuestion"); - Util.setReason("Disable player champions."); - replace = "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" - + "return;"; - Util.insertBeforeDeclared(thisClass, ctRealDeathQuestion, "sendQuestion", replace); + if (WyvernMods.disablePlayerChampions) { + Util.setReason("Disable player champions."); + replace = "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" + + "return;"; + Util.insertBeforeDeclared(thisClass, ctRealDeathQuestion, "sendQuestion", replace); + } // - Re-sort player aggression on the PvP server - // CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return "+Arena.class.getName()+".getArenaAttitude(this, $1);" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "getAttitude", replace); + if (WyvernMods.arenaAggression) { + Util.setReason("Adjust creature-player aggression on the PvP server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return " + Arena.class.getName() + ".getArenaAttitude(this, $1);" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "getAttitude", replace); - Util.setReason("Re-sort creature-player aggression on the PvP server."); - replace = "" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isPlayer() || this.isPlayer())){" + - " if($1.citizenVillage != null && this.citizenVillage != null){" + - " if($1.citizenVillage == this.citizenVillage){" + - " return 1;" + - " }" + - " if($1.citizenVillage.isAlly(this.citizenVillage)){" + - " return 1;" + - " }" + - " }" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "getAttitude", replace); + Util.setReason("Re-sort creature-player aggression on the PvP server."); + replace = "" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isPlayer() || this.isPlayer())){" + + " if($1.citizenVillage != null && this.citizenVillage != null){" + + " if($1.citizenVillage == this.citizenVillage){" + + " return 1;" + + " }" + + " if($1.citizenVillage.isAlly(this.citizenVillage)){" + + " return 1;" + + " }" + + " }" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "getAttitude", replace); + } // - Hook for (ENEMY) declaration to allow for enemy presence blocking - // CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); @@ -331,101 +322,71 @@ public class Arena { CtClass.floatType }; String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); - replace = "if(this.watcher.isPlayer()){" + - " if("+PlayerTitles.class.getName()+".hasCustomTitle(creature)){" + - " suff = suff + "+PlayerTitles.class.getName()+".getCustomTitle(creature);" + - " }" + - " if(com.wurmonline.server.Servers.localServer.PVPSERVER && creature.isPlayer() && "+Arena.class.getName()+".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " suff = suff + \" (ENEMY)\";" - + " enemy = true;" + - " }" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "isChampion", replace); + if (WyvernMods.enemyTitleHook) { + Util.setReason("Add hook for custom titles on all servers and arena aggression ENEMY suffix on PvP servers."); + replace = "if(this.watcher.isPlayer()){" + + " if(" + PlayerTitles.class.getName() + ".hasCustomTitle(creature)){" + + " suff = suff + " + PlayerTitles.class.getName() + ".getCustomTitle(creature);" + + " }" + + " if(com.wurmonline.server.Servers.localServer.PVPSERVER && creature.isPlayer() && " + Arena.class.getName() + ".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " suff = suff + \" (ENEMY)\";" + + " enemy = true;" + + " }" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "isChampion", replace); + } // - Modify when an enemy is present or not to use attitude instead of kingdom - // - replace = "if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && "+Arena.class.getName()+".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " $_ = 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "checkIfEnemyIsPresent", "getKingdomId", replace); - /*ctVirtualZone.getDeclaredMethod("checkIfEnemyIsPresent").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getKingdomId")) { - m.replace("if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && mod.sin.wyvern.Arena.getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " $_ = 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"); - return; - } - } - });*/ + if (WyvernMods.enemyPresenceOnAggression) { + Util.setReason("Apply enemy presence based on aggression instead of kingdom."); + replace = "if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && " + Arena.class.getName() + ".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " $_ = 1;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "checkIfEnemyIsPresent", "getKingdomId", replace); + } // - Block twigs and stones on the PvP server - // CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); - Util.setReason("Block farwalker twigs and stones on PvP."); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctMethodsCreatures, "teleportCreature", "isInPvPZone", replace); - /*ctMethodsCreatures.getDeclaredMethod("teleportCreature").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isInPvPZone")) { - m.replace("$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"); - return; - } - } - });*/ - - // - After respawn on PvP, send directly to PvE server - // - /*CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " "+Arena.class.getName()+".respawnPlayer(this.getResponder(), com.wurmonline.server.Servers.localServer);" - + " return;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace);*/ - /*ctSpawnQuestion.getDeclaredMethod("sendQuestion").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " mod.sin.wyvern.Arena.respawnPlayer(this.getResponder(), com.wurmonline.server.Servers.localServer);" - + " return;" - + "}");*/ + if (WyvernMods.disableFarwalkerItems) { + Util.setReason("Block farwalker twigs and stones on PvP."); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "teleportCreature", "isInPvPZone", replace); + } // - Allow affinity stealing and battle rank changes - // - Util.setReason("Allow affinity stealing and battle rank changes."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "isEnemyOnChaos", replace); + if (WyvernMods.alwaysAllowAffinitySteal) { + Util.setReason("Allow affinity stealing and battle rank changes."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "isEnemyOnChaos", replace); + } //CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - Util.setReason("Increase fight skill gain on PvP server."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " p.getFightingSkill().setKnowledge(pskill + (skillGained*1.5d), false);" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkInitialTitle", replace); + if (WyvernMods.adjustFightSkillGain) { + Util.setReason("Adjust fight skill gain on PvP server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " p.getFightingSkill().setKnowledge(pskill + (skillGained*1.5d), false);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkInitialTitle", replace); + } // - Fix nearby enemy check to find aggression instead of kingdom - // - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = c.getAttitude(performer) != 2 && c.getAttitude(performer) != 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "isEnemiesNearby", "isFriendlyKingdom", replace); - /*ctMethodsItems.getDeclaredMethod("isEnemiesNearby").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isFriendlyKingdom")) { - m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = c.getAttitude(performer) != 2;" - + "}else{" - + " $_ = $proceed($$);" - + "}"); - return; - } - } - });*/ + if (WyvernMods.useAggressionForNearbyEnemies) { + Util.setReason("Fix nearby enemy check to use aggression instead of kingdom."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = c.getAttitude(performer) != 2 && c.getAttitude(performer) != 1;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "isEnemiesNearby", "isFriendlyKingdom", replace); + } // Die method description CtClass ctString = classPool.get("java.lang.String"); @@ -437,144 +398,137 @@ public class Arena { String desc8 = Descriptor.ofMethod(CtClass.voidType, params8); // - Ensure corpses are not loot protected on PvP - // - Util.setReason("Ensure corpses are not loot protected."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = $proceed(false);" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "setProtected", replace); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "isInPvPZone", replace); + if (WyvernMods.disablePvPCorpseProtection) { + Util.setReason("Ensure corpses are not loot protected."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed(false);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "setProtected", replace); + Util.setReason("Ensure corpses are not loot protected."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "isInPvPZone", replace); + } // - Allow players to do actions in PvP houses - // CtClass ctMethods = classPool.get("com.wurmonline.server.behaviours.Methods"); - Util.setReason("Enable players to do actions in PvP houses."); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctMethods, "isNotAllowedMessage", "isEnemy", replace); + if (WyvernMods.bypassHousePermissions) { + Util.setReason("Enable players to do actions in PvP houses."); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctMethods, "isNotAllowedMessage", "isEnemy", replace); + } // - Allow stealing against deity wishes without being punished on Arena - // - //CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); - Util.setReason("Allow stealing against deity wishes without being punished."); - replace = "$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctAction, "checkLegalMode", "isLibila", replace); - /*ctAction.getDeclaredMethod("checkLegalMode").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isLibila")) { - m.replace("$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"); - return; - } - } - });*/ + if (WyvernMods.allowStealingAgainstDeityWishes) { + Util.setReason("Allow stealing against deity wishes without being punished."); + replace = "$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctAction, "checkLegalMode", "isLibila", replace); + } // - Allow taking ownership of vehicles on Arena - // - // TODO: Fix. - Util.setReason("Allow taking ownership of vehicles on Arena."); - CtClass[] params3 = new CtClass[]{ - CtClass.longType, - CtClass.booleanType, - CtClass.byteType, - CtClass.intType, - CtClass.intType - }; - String desc3 = Descriptor.ofMethod(CtClass.voidType, params3); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER && !lVehicle.isLocked();"; - Util.instrumentDescribed(thisClass, ctCreature, "setVehicle", desc3, "isThisAChaosServer", replace); + if (WyvernMods.sameKingdomVehicleTheft) { + Util.setReason("Allow taking ownership of vehicles on Arena."); + CtClass[] params3 = new CtClass[]{ + CtClass.longType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType, + CtClass.intType + }; + String desc3 = Descriptor.ofMethod(CtClass.voidType, params3); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER && !lVehicle.isLocked();"; + Util.instrumentDescribed(thisClass, ctCreature, "setVehicle", desc3, "isThisAChaosServer", replace); + } // - Multiply mine door bash damage by 3 on Arena - // CtClass ctTerraforming = classPool.get("com.wurmonline.server.behaviours.Terraforming"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " damage *= 3d;" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctTerraforming, "destroyMineDoor", "getOrCreateTile", replace); - /*ctTerraforming.getDeclaredMethod("destroyMineDoor").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getOrCreateTile")) { - m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " damage *= 3d;" - + "}" - + "$_ = $proceed($$);"); - return; - } - } - });*/ + if (WyvernMods.adjustMineDoorDamage) { + Util.setReason("Adjust mine door bash damage."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " damage *= 3d;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctTerraforming, "destroyMineDoor", "getOrCreateTile", replace); + } // - Prevent tons of errors for legality on Arena. - // - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "isOkToKillBy", replace); - /*ctCreature.getDeclaredMethod("isOkToKillBy").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}");*/ - Util.insertBeforeDeclared(thisClass, ctCreature, "hasBeenAttackedBy", replace); - /*ctCreature.getDeclaredMethod("hasBeenAttackedBy").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}");*/ + if (WyvernMods.sameKingdomPermissionsAdjustments) { + Util.setReason("Adjust same-kingdom permissions on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "isOkToKillBy", replace); + Util.setReason("Adjust same-kingdom permissions on Arena."); + Util.insertBeforeDeclared(thisClass, ctCreature, "hasBeenAttackedBy", replace); + } // - Disable CA Help on Arena - // - Util.setReason("Disable CA HELP on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "seesPlayerAssistantWindow", replace); + if (WyvernMods.disableCAHelpOnPvP) { + Util.setReason("Disable CA HELP on PvP servers."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "seesPlayerAssistantWindow", replace); + } - Util.setReason("Make players who are non-allied enemies of villages."); - CtClass ctVillage = classPool.get("com.wurmonline.server.villages.Village"); - CtClass[] params4 = new CtClass[]{ - ctCreature, - CtClass.booleanType - }; - String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); - replace = "" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER && $1.isPlayer()){" + - " if($1.getPower() > 0){" + - " return false;" + - " }" + - " if(this.isCitizen($1) || this.isAlly($1)){" + - " return false;" + - " }" + - " return true;" + - "}" + - // Additional code added to ensure village guards do not attack titans or rare creatures. - "if("+Titans.class.getName()+".isTitan($1) || "+RareSpawns.class.getName()+".isRareCreature($1)){" + - " return false;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctVillage, "isEnemy", desc4, replace); + CtClass ctVillage = classPool.get("com.wurmonline.server.villages.Village"); + if (WyvernMods.sameKingdomVillageWarfare) { + Util.setReason("Make players who are non-allied enemies of villages."); + CtClass[] params4 = new CtClass[]{ + ctCreature, + CtClass.booleanType + }; + String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); + replace = "" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER && $1.isPlayer()){" + + " if($1.getPower() > 0){" + + " return false;" + + " }" + + " if(this.isCitizen($1) || this.isAlly($1)){" + + " return false;" + + " }" + + " return true;" + + "}" + + // Additional code added to ensure village guards do not attack titans or rare creatures. + "if(" + Titans.class.getName() + ".isTitan($1) || " + RareSpawns.class.getName() + ".isRareCreature($1)){" + + " return false;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctVillage, "isEnemy", desc4, replace); - Util.setReason("Make all deeds enemies of eachother unless allied."); - CtClass[] params5 = new CtClass[]{ - ctVillage - }; - String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); - replace = "{ if($1 == null){" + - " return false;" + - " }" + - " if($1.kingdom != this.kingdom){" + - " return true;" + - " }" + - " if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if(this.isAlly($1)){" + - " return false;" + - " }" + - " if($0 == $1){" + - " return false;" + - " }" + - " return true;" + - "}" + - "return false; }"; - Util.setBodyDescribed(thisClass, ctVillage, "isEnemy", desc5, replace); + Util.setReason("Make all deeds enemies of eachother unless allied."); + CtClass[] params5 = new CtClass[]{ + ctVillage + }; + String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); + replace = "{ if($1 == null){" + + " return false;" + + " }" + + " if($1.kingdom != this.kingdom){" + + " return true;" + + " }" + + " if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if(this.isAlly($1)){" + + " return false;" + + " }" + + " if($0 == $1){" + + " return false;" + + " }" + + " return true;" + + "}" + + "return false; }"; + Util.setBodyDescribed(thisClass, ctVillage, "isEnemy", desc5, replace); + } - Util.setReason("Change HotA reward"); - replace = Arena.class.getName()+".createNewHotaPrize(this, $1);"; - Util.setBodyDeclared(thisClass, ctVillage, "createHotaPrize", replace); + if (WyvernMods.adjustHotARewards) { + Util.setReason("Adjust HotA rewards."); + replace = Arena.class.getName() + ".createNewHotaPrize(this, $1);"; + Util.setBodyDeclared(thisClass, ctVillage, "createHotaPrize", replace); + } CtClass ctGuardPlan = classPool.get("com.wurmonline.server.villages.GuardPlan"); CtClass[] params6 = new CtClass[]{ @@ -582,122 +536,140 @@ public class Arena { CtClass.intType }; String desc6 = Descriptor.ofMethod(CtClass.intType, params6); - Util.setReason("Cap maximum guards to 5."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " return Math.min(5, Math.max(3, $1 * $2 / 49));" + - "}"; - Util.insertBeforeDescribed(thisClass, ctGuardPlan, "getMaxGuards", desc6, replace); + if (WyvernMods.capMaximumGuards) { + Util.setReason("Cap maximum guards to 5."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return Math.min(5, Math.max(3, $1 * $2 / 49));" + + "}"; + Util.insertBeforeDescribed(thisClass, ctGuardPlan, "getMaxGuards", desc6, replace); + } - Util.setReason("Disable towers"); - CtClass ctAdvancedCreationEntry = classPool.get("com.wurmonline.server.items.AdvancedCreationEntry"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " performer.getCommunicator().sendAlertServerMessage(\"Towers are disabled for now. A new system is in progress.\");" + - " throw new com.wurmonline.server.NoSuchItemException(\"Towers are disabled.\");" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "cont", "isTowerTooNear", replace); - Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "run", "isTowerTooNear", replace); + if (WyvernMods.disableTowerConstruction) { + Util.setReason("Disable towers from being constructed."); + CtClass ctAdvancedCreationEntry = classPool.get("com.wurmonline.server.items.AdvancedCreationEntry"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " performer.getCommunicator().sendAlertServerMessage(\"Towers are disabled.\");" + + " throw new com.wurmonline.server.NoSuchItemException(\"Towers are disabled.\");" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "cont", "isTowerTooNear", replace); + Util.setReason("Disable towers from being constructed."); + Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "run", "isTowerTooNear", replace); + } - Util.setReason("Reduce local range (player)."); - replace = "if($3 > 5){" + - " $_ = $proceed($1, $2, 50);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isWithinDistanceTo", replace); - Util.setReason("Reduce local range (creature)."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isPlayer", replace); + if (WyvernMods.adjustLocalRange) { + Util.setReason("Reduce local range (player)."); + replace = "if($3 > 5){" + + " $_ = $proceed($1, $2, 50);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isWithinDistanceTo", replace); + Util.setReason("Reduce local range (creature)."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isPlayer", replace); + } - CtClass ctKarmaQuestion = classPool.get("com.wurmonline.server.questions.KarmaQuestion"); - Util.setReason("Disable Karma teleport."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = true;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctKarmaQuestion, "answer", "isInPvPZone", replace); + if (WyvernMods.disableKarmaTeleport) { + CtClass ctKarmaQuestion = classPool.get("com.wurmonline.server.questions.KarmaQuestion"); + Util.setReason("Disable Karma teleport."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctKarmaQuestion, "answer", "isInPvPZone", replace); + } - Util.setReason("Make players only able to lead one creature."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " return this.followers == null || this.followers.size() < 1;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "mayLeadMoreCreatures", replace); + if (WyvernMods.limitLeadCreatures) { + Util.setReason("Make players only able to lead one creature."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return this.followers == null || this.followers.size() < 1;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "mayLeadMoreCreatures", replace); + } - CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); - Util.setReason("Increase bash timer to 15 seconds."); - replace = "time = 600;" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsStructure, "destroyWall", "getStructure", replace); + if (WyvernMods.adjustBashTimer) { + CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); + Util.setReason("Increase bash timer."); + replace = "time = 600;" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsStructure, "destroyWall", "getStructure", replace); + } - CtClass ctHota = classPool.get("com.wurmonline.server.epic.Hota"); - Util.setReason("Display discord message for HotA announcements."); - replace = Arena.class.getName()+".sendHotaMessage($1);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctHota, "poll", "broadCastSafe", replace); - Util.setReason("Display discord message for HotA wins."); - Util.instrumentDeclared(thisClass, ctHota, "win", "broadCastSafe", replace); - Util.setReason("Display discord message for HotA conquers & neutralizes."); - replace = "if($2.getData1() == 0){" + - " "+Arena.class.getName()+".sendHotaMessage($1.getName() + \" neutralizes the \" + $2.getName() + \".\");" + - "}else{" + - " "+Arena.class.getName()+".sendHotaMessage($1.getName() + \" conquers the \" + $2.getName() + \".\");" + - "}"; - Util.insertBeforeDeclared(thisClass, ctHota, "addPillarConquered", replace); + if (WyvernMods.discordRelayHotAMessages) { + CtClass ctHota = classPool.get("com.wurmonline.server.epic.Hota"); + Util.setReason("Display discord message for HotA announcements."); + replace = Arena.class.getName() + ".sendHotaMessage($1);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctHota, "poll", "broadCastSafe", replace); + Util.setReason("Display discord message for HotA wins."); + Util.instrumentDeclared(thisClass, ctHota, "win", "broadCastSafe", replace); + Util.setReason("Display discord message for HotA conquers & neutralizes."); + replace = "if($2.getData1() == 0){" + + " " + Arena.class.getName() + ".sendHotaMessage($1.getName() + \" neutralizes the \" + $2.getName() + \".\");" + + "}else{" + + " " + Arena.class.getName() + ".sendHotaMessage($1.getName() + \" conquers the \" + $2.getName() + \".\");" + + "}"; + Util.insertBeforeDeclared(thisClass, ctHota, "addPillarConquered", replace); + } - // handle_TARGET_and_TARGET_HOSTILE - CtClass ctCreatureBehaviour = classPool.get("com.wurmonline.server.behaviours.CreatureBehaviour"); - Util.setReason("Allow players to attack enemy guards."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCreatureBehaviour, "handle_TARGET_and_TARGET_HOSTILE", "isFriendlyKingdom", replace); + if (WyvernMods.allowAttackingSameKingdomGuards) { + CtClass ctCreatureBehaviour = classPool.get("com.wurmonline.server.behaviours.CreatureBehaviour"); + Util.setReason("Allow players to attack enemy guards."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreatureBehaviour, "handle_TARGET_and_TARGET_HOSTILE", "isFriendlyKingdom", replace); + } - Util.setReason("Fix templars attacking themselves."); - replace = "if($1.isSpiritGuard()){" + - " return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctVillage, "addTarget", replace); + if (WyvernMods.fixGuardsAttackingThemselves) { + Util.setReason("Fix templars attacking themselves."); + replace = "if($1.isSpiritGuard()){" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctVillage, "addTarget", replace); + } - Util.setReason("Keep mine doors open for shorter durations."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctCreature, "checkOpenMineDoor", "isThisAChaosServer", replace); + if (WyvernMods.reducedMineDoorOpenTime) { + Util.setReason("Keep mine doors open for 30 seconds instead of 120 seconds."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctCreature, "checkOpenMineDoor", "isThisAChaosServer", replace); + } - Util.setReason("Fix fight skill gains against enemy players."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if($0 == this){" + - " $_ = -1;" + - " }else{" + - " $_ = $proceed($$);" + - " }" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "getKingdomId", replace); + if (WyvernMods.allowSameKingdomFightSkillGains) { + Util.setReason("Fix fight skill gains against enemy players."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if($0 == this){" + + " $_ = -1;" + + " }else{" + + " $_ = $proceed($$);" + + " }" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "getKingdomId", replace); + } - Util.setReason("Enable archering enemies on deeds."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctVillage, "mayAttack", "isEnemyOnChaos", replace); + if (WyvernMods.allowArcheringOnSameKingdomDeeds) { + Util.setReason("Enable archering enemies on deeds."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctVillage, "mayAttack", "isEnemyOnChaos", replace); + } - // Server.rand.nextFloat()*(35/(1-2*desiredPercent)) - Util.setReason("Nerf magranon faith protection."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = com.wurmonline.server.Server.rand.nextInt(40);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "getFavor", replace); + if (WyvernMods.sendNewSpawnQuestionOnPvP) { + Util.setReason("Adjust spawn question mechanics."); + CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + Arena.class.getName() + ".sendNewSpawnQuestion(this);" + + "return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace); + } - Util.setReason("Adjust spawn question mechanics."); - CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - Arena.class.getName()+".sendNewSpawnQuestion(this);" + - "return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace); CtClass ctMeshIO = classPool.get("com.wurmonline.mesh.MeshIO"); CtClass[] params7 = new CtClass[]{ ctCreature, @@ -711,20 +683,25 @@ public class Arena { CtClass.booleanType }; String desc7 = Descriptor.ofMethod(CtClass.booleanType, params7); - replace = Arena.class.getName()+".sendHotaMessage($1+\" \"+$2);" + - "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctTerraforming, "dig", desc7, "addHistory", replace); + if (WyvernMods.sendArtifactDigsToDiscord) { + Util.setReason("Announce digging up artifacts on Discord."); + replace = Arena.class.getName() + ".sendHotaMessage($1+\" \"+$2);" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctTerraforming, "dig", desc7, "addHistory", replace); + } // Creature performer, Item source, int tilex, int tiley, int tile, float counter, boolean corner, MeshIO mesh, boolean toPile - Util.setReason("Set favored kingdom for PvP"); - CtClass ctDeities = classPool.get("com.wurmonline.server.deities.Deities"); - replace = "{ return (byte) 4; }"; - Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + if (WyvernMods.makeFreedomFavoredKingdom) { + CtClass ctDeities = classPool.get("com.wurmonline.server.deities.Deities"); + Util.setReason("Set favored kingdom for PvP"); + replace = "{ return (byte) 4; }"; + Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); - Util.setReason("Set favored kingdom for PvP"); - CtClass ctDeity = classPool.get("com.wurmonline.server.deities.Deity"); - replace = "{ return (byte) 4; }"; - Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + CtClass ctDeity = classPool.get("com.wurmonline.server.deities.Deity"); + Util.setReason("Set favored kingdom for PvP"); + replace = "{ return (byte) 4; }"; + Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + } /*Util.setReason("Decrease PvP combat damage."); CtClass ctString = classPool.get("java.lang.String"); @@ -753,51 +730,62 @@ public class Arena { "}"; Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc8, replace);*/ + /* Removed in favor of DUSKombat. 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.7d;" + "}"; - Util.insertBeforeDeclared(thisClass, ctCombatHandler, "setDamage", replace); + Util.insertBeforeDeclared(thisClass, ctCombatHandler, "setDamage", replace);*/ - Util.setReason("Disable crown influence from spreading to enemies."); - replace = "$_ = $0.getAttitude(this) == 1;"; - Util.instrumentDeclared(thisClass, ctPlayer, "spreadCrownInfluence", "isFriendlyKingdom", replace); + if (WyvernMods.crownInfluenceOnAggression) { + Util.setReason("Disable crown influence from spreading to enemies."); + replace = "$_ = $0.getAttitude(this) == 1;"; + Util.instrumentDeclared(thisClass, ctPlayer, "spreadCrownInfluence", "isFriendlyKingdom", replace); + } - Util.setReason("Disable item drops from players on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer()){" + - " this.getCommunicator().sendSafeServerMessage(\"You have died on the Arena server and your items are kept safe.\");" + - " keepItems = true;" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, replace); + if (WyvernMods.disableOWFL) { + Util.setReason("Disable item drops from players on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer()){" + + " this.getCommunicator().sendSafeServerMessage(\"You have died on the Arena server and your items are kept safe.\");" + + " keepItems = true;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, replace); + } - Util.setReason("Disable player skill loss on Arena."); - replace = "if(this.isPlayer() && this.isDeathProtected()){" + - " this.getCommunicator().sendSafeServerMessage(\"You have died with a Resurrection Stone and your knowledge is kept safe.\");" + - " return;" + - "}else{" + - " this.getCommunicator().sendAlertServerMessage(\"You have died without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "punishSkills", replace); + if (WyvernMods.resurrectionStonesProtectSkill) { + Util.setReason("Disable player skill loss on Arena."); + replace = "if(this.isPlayer() && this.isDeathProtected()){" + + " this.getCommunicator().sendSafeServerMessage(\"You have died with a Resurrection Stone and your knowledge is kept safe.\");" + + " return;" + + "}else{" + + " this.getCommunicator().sendAlertServerMessage(\"You have died without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "punishSkills", replace); + } - Util.setReason("Disable player fight skill loss on Arena."); - replace = "if(this.isPlayer() && this.isDeathProtected()){" + - " $_ = null;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclaredCount(thisClass, ctCreature, "modifyFightSkill", "setKnowledge", 1, replace); + if (WyvernMods.resurrectionStonesProtectFightSkill) { + Util.setReason("Disable player fight skill loss if they have a resurrection stone."); + replace = "if(this.isPlayer() && this.isDeathProtected()){" + + " $_ = null;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclaredCount(thisClass, ctCreature, "modifyFightSkill", "setKnowledge", 1, replace); + } - Util.setReason("Disable player affinity loss on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + - " this.getCommunicator().sendSafeServerMessage(\"Your resurrection stone keeps your affinities safe from your slayers.\");" + - " $_ = "+Arena.class.getName()+".getNullAffinities();" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace); + if (WyvernMods.resurrectionStonesProtectAffinities) { + Util.setReason("Disable player affinity loss on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + + " this.getCommunicator().sendSafeServerMessage(\"Your resurrection stone keeps your affinities safe from your slayers.\");" + + " $_ = " + Arena.class.getName() + ".getNullAffinities();" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace); + } /*Util.setReason("Enable stealing from deeds."); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + @@ -807,6 +795,14 @@ public class Arena { "}"; Util.instrumentDeclared(thisClass, ctMethodsItems, "checkIfStealing", "mayPass", replace);*/ + if (WyvernMods.bypassPlantedPermissionChecks) { + Util.setReason("Allow movement of planted items on Arena regardless of permission status."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "checkPlantedPermissions", replace); + } + }catch (NotFoundException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/GemAugmentation.java b/src/main/java/mod/sin/wyvern/GemAugmentation.java index f6ba55b..467b18c 100644 --- a/src/main/java/mod/sin/wyvern/GemAugmentation.java +++ b/src/main/java/mod/sin/wyvern/GemAugmentation.java @@ -25,6 +25,11 @@ public class GemAugmentation { Class thisClass = GemAugmentation.class; String replace; + Util.setReason("Disable Gem Augmentation skill from converting."); + CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); + replace = "$_ = $proceed($1, $2, true, $4);"; + Util.instrumentDeclared(thisClass, ctMethodsReligion, "listen", "skillCheck", replace); + Util.setReason("Primary Gem Augmentation Hook."); CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); replace = "$_ = "+GemAugmentation.class.getName()+".setGemmedQuality($0, power, maxGain, modifier);"; diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index 806135f..77ab7d7 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -204,7 +204,7 @@ public class ItemMod { //SKELETON_DECORATION.initCreationEntry(); SOUL_FORGE.initCreationEntry(); STATUETTE_BREYK.initCreationEntry(); - //STATUETTE_CYBERHUSKY.initCreationEntry(); + STATUETTE_CYBERHUSKY.initCreationEntry(); WARHAMMER.initCreationEntry(); WARHAMMER_HEAD.initCreationEntry(); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 4a9c9b0..65f9a76 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -325,7 +325,7 @@ public class MiscChanges { // Is send to buff bar and not something we're stopping, so allow it. return true; } - + public static void preInit(){ try{ ClassPool classPool = HookManager.getInstance().getClassPool(); @@ -334,214 +334,263 @@ public class MiscChanges { // - Create Server tab with initial messages - // CtClass ctPlayers = classPool.get("com.wurmonline.server.Players"); - CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat"); - String infoTabTitle = "Server"; - // Initial messages: - String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/", - "Website/Maps: https://www.sarcasuals.com/", - "Server Discord: https://discord.gg/r8QNXAC", - "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", - "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing", - "Patreon: https://www.patreon.com/sindusk"}; - StringBuilder str = new StringBuilder("{" - + " com.wurmonline.server.Message mess;"); - for (String anInfoTabLine : infoTabLine) { - str.append(" mess = new com.wurmonline.server.Message(player, (byte)16, \"").append(infoTabTitle).append("\",\"").append(anInfoTabLine).append("\", 0, 255, 0);").append(" player.getCommunicator().sendMessage(mess);"); + if (WyvernMods.enableInfoTab) { + CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat"); + String infoTabTitle = WyvernMods.infoTabName; + // Initial messages: + //String[] infoTabLine = (String[]) WyvernMods.infoTabLines.toArray(); + /*String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/", + "Website/Maps: https://www.sarcasuals.com/", + "Server Discord: https://discord.gg/r8QNXAC", + "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", + "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing", + "Patreon: https://www.patreon.com/sindusk"};*/ + StringBuilder str = new StringBuilder("{ com.wurmonline.server.Message mess;"); + for (String anInfoTabLine : WyvernMods.infoTabLines) { + str.append(" mess = new com.wurmonline.server.Message(player, (byte)16, \"").append(infoTabTitle).append("\",\"").append(anInfoTabLine).append("\", 0, 255, 0);").append(" player.getCommunicator().sendMessage(mess);"); + } + str.append("}"); + m.insertAfter(str.toString()); } - str.append("}"); - m.insertAfter(str.toString()); // - Enable bridges to be built inside/over/through houses - // CtClass ctPlanBridgeChecks = classPool.get("com.wurmonline.server.structures.PlanBridgeChecks"); - replace = "{ return new com.wurmonline.server.structures.PlanBridgeCheckResult(false); }"; - Util.setBodyDeclared(thisClass, ctPlanBridgeChecks, "checkForBuildings", replace); + if (WyvernMods.ignoreBridgeChecks) { + Util.setReason("Disable bridge construction checks."); + replace = "{ return new com.wurmonline.server.structures.PlanBridgeCheckResult(false); }"; + Util.setBodyDeclared(thisClass, ctPlanBridgeChecks, "checkForBuildings", replace); + } // - Disable mailboxes from being used while loaded - // CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); - replace = "$_ = $proceed($$);" - + "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);" - + "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){" - + " if(theTarget.getTopParent() != theTarget.getWurmId()){" - + " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");" - + " return false;" - + " }" - + "}"; - Util.instrumentDeclared(thisClass, ctItem, "moveToItem", "getOwnerId", replace); + if (WyvernMods.disableMailboxUsageWhileLoaded) { + Util.setReason("Disable mailbox usage while loaded."); + replace = "$_ = $proceed($$);" + + "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);" + + "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){" + + " if(theTarget.getTopParent() != theTarget.getWurmId()){" + + " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");" + + " return false;" + + " }" + + "}"; + Util.instrumentDeclared(thisClass, ctItem, "moveToItem", "getOwnerId", replace); + } - // - 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);*/ - // - Increase the amount of checks for new unique spawns by 5x - // + // - Increase the amount of checks for new legendary creature to spawn - // CtClass ctServer = classPool.get("com.wurmonline.server.Server"); - replace = "for(int i = 0; i < 5; i++){" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace); + if (WyvernMods.increasedLegendaryCreatures) { + Util.setReason("Increase chances of a Legendary Creature spawning."); + replace = "for(int i = 0; i < "+String.valueOf(WyvernMods.increasedLegendaryFrequency)+"; i++){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace); + } - // - Add Facebreyker to the list of spawnable uniques - // + // - Add Facebreyker to the list of spawnable legendary creatures - // CtClass ctDens = classPool.get("com.wurmonline.server.zones.Dens"); - replace = "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"; - Util.insertBeforeDeclared(thisClass, ctDens, "checkDens", replace); - //ctDens.getDeclaredMethod("checkDens").insertAt(0, "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"); + if (WyvernMods.allowFacebreykerNaturalSpawn) { + Util.setReason("Add Facebreyker to the natural legendary spawn list."); + replace = "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"; + Util.insertBeforeDeclared(thisClass, ctDens, "checkDens", replace); + } // - Announce player titles in the Server tab - // CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); - replace = "$_ = $proceed($$);" - + "if(!com.wurmonline.server.Servers.localServer.PVPSERVER && this.getPower() < 1){" - + " "+MiscChanges.class.getName()+".sendServerTabMessage(\"event\", this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" - + "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace); + if (WyvernMods.announcePlayerTitles) { + Util.setReason("Announce player titles in the server tab."); + replace = "$_ = $proceed($$);" + + "if(!com.wurmonline.server.Servers.localServer.PVPSERVER && this.getPower() < 1){" + + " " + MiscChanges.class.getName() + ".sendServerTabMessage(\"event\", this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace); + } // - Make leather not suck even after it's able to be combined. - // CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){" - + " $_ = $proceed($$);" - + "}else{" - + " $_ = false;" - + "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace); + if (WyvernMods.improveCombinedLeather) { + Util.setReason("Allow leather to improve beyond QL after being combinable."); + replace = "if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){" + + " $_ = $proceed($$);" + + "}else{" + + " $_ = false;" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace); + } // - Check new improve materials - // - replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);" - + "if(temp != -10){" - + " return temp;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); + if (WyvernMods.allowModdedImproveTemplates) { + Util.setReason("Enable modded improve templates."); + replace = "int temp = " + ItemMod.class.getName() + ".getModdedImproveTemplateId($1);" + + "if(temp != -10){" + + " return temp;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); + } // - Remove fatiguing actions requiring you to be on the ground - // CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); - CtConstructor[] ctActionConstructors = ctAction.getConstructors(); - for(CtConstructor constructor : ctActionConstructors) { - constructor.instrument(new ExprEditor() { - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isFatigue")) { - m.replace("" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if(!com.wurmonline.server.behaviours.Actions.isActionDestroy(this.getNumber())){" + - " $_ = false;" + - " }else{" + - " $_ = $proceed($$);" + - " }" + - "}else{" + - " $_ = false;" + - "}"); - logger.info("Set isFatigue to false in action constructor."); + if (WyvernMods.fatigueActionOverride) { + CtConstructor[] ctActionConstructors = ctAction.getConstructors(); + for (CtConstructor constructor : ctActionConstructors) { + constructor.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isFatigue")) { + m.replace("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if(!com.wurmonline.server.behaviours.Actions.isActionDestroy(this.getNumber())){" + + " $_ = false;" + + " }else{" + + " $_ = $proceed($$);" + + " }" + + "}else{" + + " $_ = false;" + + "}"); + logger.info("Set isFatigue to false in action constructor."); + } + } + }); + } + } + + if (WyvernMods.fixPortalIssues) { + Util.setReason("Fix Portal Issues."); + CtClass ctPortal = classPool.get("com.wurmonline.server.questions.PortalQuestion"); + Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "willLeaveServer", "$_ = true;"); + Util.setReason("Fix Portal Issues."); + Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "getKnowledge", "$_ = true;"); + } + + if (WyvernMods.disableMinimumShieldDamage) { + Util.setReason("Disable the minimum 0.01 damage on shield damage, allowing damage modifiers to rule."); + CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); + replace = "if($1 < 0.5f){" + + " $_ = $proceed((float) 0, (float) $2);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace); + } + + if (WyvernMods.disableGMEmoteLimit) { + // - Allow GM's to bypass the 5 second emote sound limit. - // + Util.setReason("Allow GM's to bypass the 5 second emote sound limit."); + replace = "if(this.getPower() > 0){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace); + } + + // - Make creatures wander slightly if they are shot from afar by an arrow - // + CtClass ctArrows = classPool.get("com.wurmonline.server.combat.Arrows"); + if (WyvernMods.creatureArcheryWander) { + Util.setReason("Make creatures wander slightly when archered."); + replace = "if(!defender.isPathing()){" + + " defender.startPathing(com.wurmonline.server.Server.rand.nextInt(100));" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctArrows, "addToHitCreature", "addAttacker", replace); + } + + if (WyvernMods.globalDeathTabs) { + Util.setReason("Broadcast death tabs to GL-Freedom."); + replace = MiscChanges.class.getName() + ".broadCastDeaths($1, $2);"; + Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", replace); + } + + /* Disabled 1.9 - PvE Death Tabs are now part of vanilla. + Util.setReason("Broadcast player death tabs always."); + replace = MiscChanges.class.getName()+".broadCastDeathsPvE($0, $0.attackers);"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "modifyRanking", replace);*/ + + if (WyvernMods.disablePvPOnlyDeathTabs) { + Util.setReason("Disable PvP only death tabs."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctPlayers, "broadCastDeathInfo", "isThisAPvpServer", replace); + } + + if (WyvernMods.fixLibilaCrossingIssues) { + Util.setReason("Attempt to prevent libila from losing faith when crossing servers."); + CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection"); + ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) { + fieldAccess.replace("$_ = false;"); + logger.info("Instrumented PVPSERVER = false for Libila faith transfers."); + } + } + }); + ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("HOMESERVER", fieldAccess.getFieldName())) { + fieldAccess.replace("$_ = false;"); + logger.info("Instrumented HOMESERVER = false for Libila faith transfers."); } } }); } - - Util.setReason("Fix Portal Issues."); - CtClass ctPortal = classPool.get("com.wurmonline.server.questions.PortalQuestion"); - Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "willLeaveServer", "$_ = true;"); - Util.setReason("Fix Portal Issues."); - Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "getKnowledge", "$_ = true;"); - Util.setReason("Disable the minimum 0.01 damage on shield damage, allowing damage modifiers to rule."); - CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); - replace = "if($1 < 0.5f){" - + " $_ = $proceed((float) 0, (float) $2);" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace); + CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + CtClass[] params4 = { + CtClass.doubleType, + CtClass.booleanType, + CtClass.floatType, + CtClass.booleanType, + CtClass.doubleType + }; + String desc4 = Descriptor.ofMethod(CtClass.voidType, params4); - // - Allow GM's to bypass the 5 second emote sound limit. - // - replace = "if(this.getPower() > 0){" - + " return true;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace); + if (WyvernMods.higherFoodAffinities) { + Util.setReason("Increase food affinity to give 30% increased skillgain instead of 10%."); + replace = "int timedAffinity = (com.wurmonline.server.skills.AffinitiesTimed.isTimedAffinity(pid, this.getNumber()) ? 2 : 0);" + + "advanceMultiplicator *= (double)(1.0f + (float)timedAffinity * 0.1f);" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc4, "hasSleepBonus", replace); + } - // - Make creatures wander slightly if they are shot from afar by an arrow - // - CtClass ctArrows = classPool.get("com.wurmonline.server.combat.Arrows"); - replace = "if(!defender.isPathing()){" - + " defender.startPathing(com.wurmonline.server.Server.rand.nextInt(100));" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctArrows, "addToHitCreature", "addAttacker", replace); - - Util.setReason("Broadcast death tabs to GL-Freedom."); - replace = MiscChanges.class.getName()+".broadCastDeaths($1, $2);"; - Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", replace); - - Util.setReason("Broadcast player death tabs always."); - replace = MiscChanges.class.getName()+".broadCastDeathsPvE($0, $0.attackers);"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "modifyRanking", replace); - - Util.setReason("Disable PvP only death tabs."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctPlayers, "broadCastDeathInfo", "isThisAPvpServer", replace); - - Util.setReason("Attempt to prevent libila from losing faith when crossing servers."); - CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection"); - ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())){ - fieldAccess.replace("$_ = false;"); - logger.info("Instrumented PVPSERVER = false for Libila faith transfers."); - } - } - }); - ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("HOMESERVER", fieldAccess.getFieldName())){ - fieldAccess.replace("$_ = false;"); - logger.info("Instrumented HOMESERVER = false for Libila faith transfers."); - } - } - }); - - Util.setReason("Increase food affinity to give 30% increased skillgain instead of 10%."); - CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); - CtClass[] params4 = { - CtClass.doubleType, - CtClass.booleanType, - CtClass.floatType, - CtClass.booleanType, - CtClass.doubleType - }; - String desc4 = Descriptor.ofMethod(CtClass.voidType, params4); - replace = "int timedAffinity = (com.wurmonline.server.skills.AffinitiesTimed.isTimedAffinity(pid, this.getNumber()) ? 2 : 0);" - + "advanceMultiplicator *= (double)(1.0f + (float)timedAffinity * 0.1f);" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc4, "hasSleepBonus", replace); - - Util.setReason("Double the rate at which charcoal piles produce items."); CtClass[] params5 = { CtClass.booleanType, CtClass.booleanType, CtClass.longType }; String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); - replace = "this.createDaleItems();" - + "decayed = this.setDamage(this.damage + 1.0f * this.getDamageModifier());" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctItem, "poll", desc5, "createDaleItems", replace); + if (WyvernMods.fasterCharcoalBurn) { + Util.setReason("Double the rate at which charcoal piles produce items."); + replace = "this.createDaleItems();" + + "decayed = this.setDamage(this.damage + 1.0f * this.getDamageModifier());" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctItem, "poll", desc5, "createDaleItems", replace); + } Util.setReason("Allow traders to display more than 9 items of a single type."); CtClass ctTradeHandler = classPool.get("com.wurmonline.server.creatures.TradeHandler"); - ctTradeHandler.getDeclaredMethod("addItemsToTrade").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if(m.getMethodName().equals("size") && m.getLineNumber() > 200){ // I don't think the line number check matters, but I'm leaving it here anyway. - m.replace("$_ = 1;"); - logger.info("Instrumented size for trades to allow traders to show more than 9 items at a time."); + if (WyvernMods.uncapTraderItemCount) { + ctTradeHandler.getDeclaredMethod("addItemsToTrade").instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("size") && m.getLineNumber() > 200) { // I don't think the line number check matters, but I'm leaving it here anyway. + m.replace("$_ = 1;"); + logger.info("Instrumented size for trades to allow traders to show more than 9 items at a time."); + } } - } - }); + }); + } // -- Identify players making over 10 commands per second and causing the server log message -- // CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "$_ = $proceed($$);" - + "if(this.player != null){" - + " logger.info(\"Potential player macro: \"+this.player.getName()+\" [\"+this.commandsThisSecond+\" commands]\");" - + "}"; - Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_ITEM_CREATION_LIST", "log", replace); + if (WyvernMods.logExcessiveActions) { + Util.setReason("Log excessive actions per second."); + replace = "$_ = $proceed($$);" + + "if(this.player != null){" + + " logger.info(\"Potential player macro: \"+this.player.getName()+\" [\"+this.commandsThisSecond+\" commands]\");" + + "}"; + Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_ITEM_CREATION_LIST", "log", replace); + } //1f+0.5f*(1f-Math.pow(2, -Math.pow((eff-1f), pow1)/pow2)) + /* Disabled in 1.9 - Fixed with Priest Update. Util.setReason("Fix 100+ quality or power making certain interaction broken."); replace = "{" + "double pow1 = 1.0;" @@ -549,7 +598,7 @@ public class MiscChanges { + "double newEff = $1 >= 1.0 ? 1.0+0.5*(1.0-Math.pow(2.0, -Math.pow(($1-1.0), pow1)/pow2)) : Math.max(0.05, 1.0 - (1.0 - $1) * (1.0 - $1));" + "return newEff;" + "}"; - Util.setBodyDeclared(thisClass, ctServer, "getBuffedQualityEffect", replace); + Util.setBodyDeclared(thisClass, ctServer, "getBuffedQualityEffect", replace);*/ // double advanceMultiplicator, boolean decay, float times, boolean useNewSystem, double skillDivider) CtClass[] params = { @@ -560,189 +609,220 @@ public class MiscChanges { CtClass.doubleType }; String desc = Descriptor.ofMethod(CtClass.voidType, params); - double minRate = 1.0D; - double maxRate = 8.0D; - double newPower = 2.5; - Util.setReason("Adjust skill rate to a new, dynamic rate system."); - replace = "double minRate = " + String.valueOf(minRate) + ";" + - "double maxRate = " + String.valueOf(maxRate) + ";" + - "double newPower = " + String.valueOf(newPower) + ";" + - "$1 = $1*(minRate+(maxRate-minRate)*Math.pow((100-this.knowledge)*0.01, newPower));"; - Util.insertBeforeDescribed(thisClass, ctSkill,"alterSkill", desc, replace); + if (WyvernMods.useDynamicSkillRate) { + double minRate = 1.0D; + double maxRate = 8.0D; + double newPower = 2.5; - Util.setReason("Reduce chance of lockpicks breaking."); - replace = "$_ = 40f + $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "checkLockpickBreakage", "getCurrentQualityLevel", replace); + Util.setReason("Adjust skill rate to a new, dynamic rate system."); + replace = "double minRate = " + String.valueOf(minRate) + ";" + + "double maxRate = " + String.valueOf(maxRate) + ";" + + "double newPower = " + String.valueOf(newPower) + ";" + + "$1 = $1*(minRate+(maxRate-minRate)*Math.pow((100-this.knowledge)*0.01, newPower));"; + Util.insertBeforeDescribed(thisClass, ctSkill, "alterSkill", desc, replace); + } + if (WyvernMods.reduceLockpickBreaking) { + Util.setReason("Reduce chance of lockpicks breaking."); + replace = "$_ = 40f + $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "checkLockpickBreakage", "getCurrentQualityLevel", replace); + } + + // Allow Freedom players to absorb mycelium CtClass ctTileBehaviour = classPool.get("com.wurmonline.server.behaviours.TileBehaviour"); CtMethod[] ctGetBehavioursFors = ctTileBehaviour.getDeclaredMethods("getBehavioursFor"); - for(CtMethod method : ctGetBehavioursFors){ - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getKingdomTemplateId")) { - m.replace("$_ = 3;"); - } - } - }); - } + if (WyvernMods.allowFreedomMyceliumAbsorb) { + for (CtMethod method : ctGetBehavioursFors) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getKingdomTemplateId")) { + m.replace("$_ = 3;"); + } + } + }); + } + } CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); - Util.setReason("Allow players to construct larger houses."); - float carpentryMultiplier = 2f; - replace = "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = $proceed($$)*"+String.valueOf(carpentryMultiplier)+";" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToExpandStructure", "getKnowledge", replace); - Util.setReason("Allow players to construct larger houses."); - Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToContractStructure", "getKnowledge", replace); + if (WyvernMods.largerHouses) { + Util.setReason("Allow players to construct larger houses."); + float carpentryMultiplier = 2f; + replace = "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed($$)*" + String.valueOf(carpentryMultiplier) + ";" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToExpandStructure", "getKnowledge", replace); + Util.setReason("Allow players to construct larger houses."); + Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToContractStructure", "getKnowledge", replace); + } - Util.setReason("Reduce power of imbues."); - replace = "$_ = Math.max(-80d, -80d+$2);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "smear", "max", replace); + if (WyvernMods.reduceImbuePower) { + Util.setReason("Reduce power of imbues."); + replace = "$_ = Math.max(-80d, -80d+$2);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "smear", "max", replace); + } - Util.setReason("Update vehicle speeds reliably."); - replace = "if($1 == 8){" + - " $_ = 0;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "checkVehicleSpeeds", "nextInt", replace); + if (WyvernMods.fixVehicleSpeeds) { + Util.setReason("Update vehicle speeds reliably."); + replace = "if($1 == 8){" + + " $_ = 0;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "checkVehicleSpeeds", "nextInt", replace); + } - Util.setReason("Reduce mailing costs by 90%."); - CtClass ctMailSendConfirmQuestion = classPool.get("com.wurmonline.server.questions.MailSendConfirmQuestion"); - replace = "$_ = $_ / 10;"; - Util.insertAfterDeclared(thisClass, ctMailSendConfirmQuestion, "getCostForItem", replace); + if (WyvernMods.reduceMailingCosts) { + Util.setReason("Reduce mailing costs by 90%."); + CtClass ctMailSendConfirmQuestion = classPool.get("com.wurmonline.server.questions.MailSendConfirmQuestion"); + replace = "$_ = $_ / 10;"; + Util.insertAfterDeclared(thisClass, ctMailSendConfirmQuestion, "getCostForItem", replace); + } - Util.setReason("Remove guard tower guards helping against certain types of enemies."); - CtClass ctGuardTower = classPool.get("com.wurmonline.server.kingdom.GuardTower"); - replace = "if($0.isUnique() || "+Titans.class.getName()+".isTitan($0) || "+RareSpawns.class.getName()+".isRareCreature($0)){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctGuardTower, "alertGuards", "isWithinTileDistanceTo", replace); + if (WyvernMods.guardTargetChanges) { + Util.setReason("Remove guard tower guards helping against certain types of enemies."); + CtClass ctGuardTower = classPool.get("com.wurmonline.server.kingdom.GuardTower"); + replace = "if($0.isUnique() || " + Titans.class.getName() + ".isTitan($0) || " + RareSpawns.class.getName() + ".isRareCreature($0)){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctGuardTower, "alertGuards", "isWithinTileDistanceTo", replace); + } // Enable Strongwall for Libila and other spells on PvE CtClass ctSpellGenerator = classPool.get("com.wurmonline.server.spells.SpellGenerator"); - ctSpellGenerator.getDeclaredMethod("createSpells").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) - fieldAccess.replace("$_ = true;"); - logger.info("Instrumented SpellGenerator PVPSERVER field to enable all spells."); - } - }); + if (WyvernMods.enableLibilaStrongwallPvE) { + ctSpellGenerator.getDeclaredMethod("createSpells").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) + fieldAccess.replace("$_ = true;"); + logger.info("Instrumented SpellGenerator PVPSERVER field to enable all spells."); + } + }); + } - Util.setReason("Make heated food never decay if cooked by a royal cook."); CtClass ctTempStates = classPool.get("com.wurmonline.server.items.TempStates"); - replace = "$_ = $proceed($$);" + - "if(chefMade){" + - " $0.setName(\"royal \"+$0.getName());" + - " $0.setHasNoDecay(true);" + - "}"; - Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "setName", replace); - Util.setReason("Stop royal food decay."); - // Item parent, int parentTemp, boolean insideStructure, boolean deeded, boolean saveLastMaintained, boolean inMagicContainer, boolean inTrashbin - CtClass[] params11 = { - ctItem, - CtClass.intType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType - }; - String desc11 = Descriptor.ofMethod(CtClass.booleanType, params11); - replace = "if($0.isFood() && $0.hasNoDecay()){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctItem, "poll", desc11, "setDamage", replace); + if (WyvernMods.royalCookNoFoodDecay) { + Util.setReason("Make heated food never decay if cooked by a royal cook."); + replace = "$_ = $proceed($$);" + + "if(chefMade){" + + " $0.setName(\"royal \"+$0.getName());" + + " $0.setHasNoDecay(true);" + + "}"; + Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "setName", replace); - Util.setReason("Allow mayors to command abandoned vehicles off their deed."); - replace = "if("+MiscChanges.class.getName()+".checkMayorCommand($0, $1)){" + - " return true;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctItem, "mayCommand", replace); + Util.setReason("Stop royal food decay."); + // Item parent, int parentTemp, boolean insideStructure, boolean deeded, boolean saveLastMaintained, boolean inMagicContainer, boolean inTrashbin + CtClass[] params11 = { + ctItem, + CtClass.intType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType + }; + String desc11 = Descriptor.ofMethod(CtClass.booleanType, params11); + replace = "if($0.isFood() && $0.hasNoDecay()){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctItem, "poll", desc11, "setDamage", replace); + } + + if (WyvernMods.mayorsCommandAbandonedVehicles) { + Util.setReason("Allow mayors to command abandoned vehicles off their deed."); + replace = "if(" + MiscChanges.class.getName() + ".checkMayorCommand($0, $1)){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "mayCommand", replace); + } - Util.setReason("Modify timed affinity timer."); CtClass ctAffinitiesTimed = classPool.get("com.wurmonline.server.skills.AffinitiesTimed"); - replace = "$_ = "+MiscChanges.class.getName()+".getFoodOpulenceBonus($0);"; - Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "addTimedAffinityFromBonus", "getFoodComplexity", replace); - Util.setReason("Food affinity timer normalization."); - replace = "long time = "+WurmCalendar.class.getName()+".getCurrentTime();" + - "if($0.getExpires($1) == null){" + - " $_ = Long.valueOf(time);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "add", "getExpires", replace); + if (WyvernMods.opulenceFoodAffinityTimerIncrease) { + Util.setReason("Add opulence bonus to food affinity timers."); + replace = "$_ = " + MiscChanges.class.getName() + ".getFoodOpulenceBonus($0);"; + Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "addTimedAffinityFromBonus", "getFoodComplexity", replace); + } - Util.setReason("Make bed QL affect sleep bonus timer."); - CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo"); - replace = "secs = "+MiscChanges.class.getName()+".getBedBonus(secs, this.bed);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace); + if (WyvernMods.disableFoodFirstBiteBonus) { + Util.setReason("Food affinity timer normalization."); + replace = "long time = " + WurmCalendar.class.getName() + ".getCurrentTime();" + + "if($0.getExpires($1) == null){" + + " $_ = Long.valueOf(time);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "add", "getExpires", replace); + } - /*Util.setReason("Fix intrateleport block bug."); - replace = "if($6.contains(\"blocked\")){" + - " logger.info(\"Detected a blocked movement, resetting position back to old.\");" + - " $1 = $0.getMovementScheme().xOld;" + - " $2 = $0.getMovementScheme().yOld;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "intraTeleport", replace);*/ + if (WyvernMods.bedQualitySleepBonus) { + Util.setReason("Make bed QL affect sleep bonus timer."); + CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo"); + replace = "secs = " + MiscChanges.class.getName() + ".getBedBonus(secs, this.bed);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace); + } - Util.setReason("Allow royal smith to improve smithing items faster."); - replace = "if("+MiscChanges.class.getName()+".royalSmithImprove($1, improve)){" + - " $_ = $proceed($$) * 0.9f;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getImproveActionTime", replace); - Util.setReason("Allow royal smith to improve smithing items faster."); - Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getImproveActionTime", replace); - Util.setReason("Allow royal smith to improve smithing items faster. Also make tempering use water enchants."); - replace = "if("+MiscChanges.class.getName()+".royalSmithImprove($1, improve)){" + - " $_ = $proceed($1, target) * 0.9f;" + - "}else{" + - " $_ = $proceed($1, target);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "getImproveActionTime", replace); + if (WyvernMods.royalSmithImproveFaster) { + Util.setReason("Allow royal smith to improve smithing items faster."); + replace = "if(" + MiscChanges.class.getName() + ".royalSmithImprove($1, improve)){" + + " $_ = $proceed($$) * 0.9f;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getImproveActionTime", replace); + Util.setReason("Allow royal smith to improve smithing items faster."); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getImproveActionTime", replace); + Util.setReason("Allow royal smith to improve smithing items faster. Also make tempering use water enchants."); + replace = "if(" + MiscChanges.class.getName() + ".royalSmithImprove($1, improve)){" + + " $_ = $proceed($1, target) * 0.9f;" + + "}else{" + + " $_ = $proceed($1, target);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "getImproveActionTime", replace); + } // Fix for body strength not working properly when mounted. (Bdew) - ctCreature.getMethod("getTraitMovePercent", "(Z)F").instrument(new ExprEditor() { - private boolean first = true; + if (WyvernMods.fixMountedBodyStrength) { + ctCreature.getMethod("getTraitMovePercent", "(Z)F").instrument(new ExprEditor() { + private boolean first = true; - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getStrengthSkill")) { - if (first) - m.replace("wmod = wmod * 3D; $_ = $proceed() * (this.isUnicorn()?3D:2D);"); - else - m.replace("$_ = $proceed() * (this.isUnicorn()?3D:2D);"); - first = false; + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getStrengthSkill")) { + if (first) + m.replace("wmod = wmod * 3D; $_ = $proceed() * (this.isUnicorn()?3D:2D);"); + else + m.replace("$_ = $proceed() * (this.isUnicorn()?3D:2D);"); + first = false; + } } - } - }); + }); + } - Util.setReason("Modify food fill percent."); - CtClass[] params12 = { - ctAction, - ctCreature, - ctItem, - CtClass.floatType - }; - String desc12 = Descriptor.ofMethod(CtClass.booleanType, params12); - replace = "$_ = $proceed($1, $2, $3, $4, "+MiscChanges.class.getName()+".getNewFoodFill(qlevel));"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "eat", desc12, "modifyHunger", replace); + if (WyvernMods.adjustedFoodBiteFill) { + Util.setReason("Modify food fill percent."); + CtClass[] params12 = { + ctAction, + ctCreature, + ctItem, + CtClass.floatType + }; + String desc12 = Descriptor.ofMethod(CtClass.booleanType, params12); + replace = "$_ = $proceed($1, $2, $3, $4, " + MiscChanges.class.getName() + ".getNewFoodFill(qlevel));"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "eat", desc12, "modifyHunger", replace); + } // Fix for butchering not giving skill gain when butchering too many items + /* Disabled in 1.9 - No longer necessary due to fishing changes. ctMethodsItems.getDeclaredMethod("filet").instrument(new ExprEditor() { private boolean first = true; @@ -757,7 +837,7 @@ public class MiscChanges { } } } - }); + });*/ // How to add a skill! /*CtClass ctSkillSystem = classPool.get("com.wurmonline.server.skills.SkillSystem"); @@ -765,171 +845,172 @@ public class MiscChanges { ctSkillSystemConstructor.insertAfter("com.wurmonline.server.skills.SkillSystem.addSkillTemplate(new "+SkillTemplate.class.getName()+"(10096, \"Battle Yoyos\", 4000.0f, new int[]{1022}, 1209600000l, (short) 4, true, true));");*/ - Util.setReason("Hook for rare material usage in improvement."); - replace = "if("+MiscChanges.class.getName()+".rollRarityImprove($0, usedWeight)){" + - " rarity = source.getRarity();" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setWeight", replace); + if (WyvernMods.rareMaterialImprove) { + Util.setReason("Hook for rare material usage in improvement."); + replace = "if(" + MiscChanges.class.getName() + ".rollRarityImprove($0, usedWeight)){" + + " rarity = source.getRarity();" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setWeight", replace); + } - Util.setReason("Bad luck protection on rarity windows."); - replace = "if($1 == 3600){" + - " $_ = "+MiscChanges.class.getName()+".getRarityWindowChance(this.getWurmId());" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "poll", "nextInt", replace); + if (WyvernMods.rarityWindowBadLuckProtection) { + Util.setReason("Bad luck protection on rarity windows."); + replace = "if($1 == 3600){" + + " $_ = " + MiscChanges.class.getName() + ".getRarityWindowChance(this.getWurmId());" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "poll", "nextInt", replace); + } CtClass ctSimpleCreationEntry = classPool.get("com.wurmonline.server.items.SimpleCreationEntry"); - ctSimpleCreationEntry.getDeclaredMethod("run").instrument(new ExprEditor() { - private boolean first = true; - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getRarity")) { - if (first) { - m.replace("byte newRarity = "+MiscChanges.class.getName()+".getNewCreationRarity(this, source, target, template);" + - "if(newRarity > 0){" + - " act.setRarity(newRarity);" + - "}" + - "$_ = $proceed($$);"); - logger.info("Replaced getRarity in SimpleCreationEntry to allow functional rare creations."); - first = false; + if (WyvernMods.rareCreationAdjustments) { + ctSimpleCreationEntry.getDeclaredMethod("run").instrument(new ExprEditor() { + private boolean first = true; + + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getRarity")) { + if (first) { + m.replace("byte newRarity = " + MiscChanges.class.getName() + ".getNewCreationRarity(this, source, target, template);" + + "if(newRarity > 0){" + + " act.setRarity(newRarity);" + + "}" + + "$_ = $proceed($$);"); + logger.info("Replaced getRarity in SimpleCreationEntry to allow functional rare creations."); + first = false; + } } } - } - }); + }); + } - Util.setReason("Make armour title benefits always occur."); - replace = "$_ = improve.getNumber();"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getSkillId", replace); - Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getSkillId", replace); + if (WyvernMods.alwaysArmourTitleBenefits) { + Util.setReason("Make armour title benefits always occur."); + replace = "$_ = improve.getNumber();"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getSkillId", replace); + Util.setReason("Make armour title benefits always occur."); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getSkillId", replace); + } - Util.setReason("Make it so sorceries can be used anywhere with a flat 3x3 altar."); CtClass ctAbilities = classPool.get("com.wurmonline.server.players.Abilities"); - replace = "$_ = 1;"; - Util.instrumentDeclared(thisClass, ctAbilities, "isInProperLocation", "getTemplateId", replace); - Util.setReason("Make the key of the heavens only usable on PvE"); - replace = "if($1.getTemplateId() == 794 && com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" may not be used on Arena.\");" + - " return false;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace); + if (WyvernMods.tomeUsageAnyAltar) { + Util.setReason("Make it so sorceries can be used anywhere with a flat 3x3 altar."); + replace = "$_ = 1;"; + Util.instrumentDeclared(thisClass, ctAbilities, "isInProperLocation", "getTemplateId", replace); + } - Util.setReason("Make drinks less filling."); - CtClass[] params13 = { - ctAction, - ctCreature, - ctItem, - CtClass.floatType - }; - String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13); - replace = "if(template != 128){" + - " $_ = $proceed($1, $2, $3*5);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "sendActionControl", replace); - replace = "if(template != 128){" + - " $_ = $proceed($1/5, $2, $3, $4, $5);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", replace); + if (WyvernMods.keyOfHeavensLoginOnly) { + Util.setReason("Make the key of the heavens only usable on PvE"); + replace = "if($1.getTemplateId() == 794 && com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" must be used on the login server.\");" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace); + } - Util.setReason("Disable Gem Augmentation skill from converting."); - CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); - replace = "$_ = $proceed($1, $2, true, $4);"; - Util.instrumentDeclared(thisClass, ctMethodsReligion, "listen", "skillCheck", replace); + if (WyvernMods.lessFillingDrinks) { + Util.setReason("Make drinks less filling."); + CtClass[] params13 = { + ctAction, + ctCreature, + ctItem, + CtClass.floatType + }; + String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13); + replace = "if(template != 128){" + + " $_ = $proceed($1, $2, $3*5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "sendActionControl", replace); + replace = "if(template != 128){" + + " $_ = $proceed($1/5, $2, $3, $4, $5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", replace); + } - Util.setReason("Disable GM commands from displaying in /help unless the player is a GM."); - CtClass ctServerTweaksHandler = classPool.get("com.wurmonline.server.ServerTweaksHandler"); - replace = "if($1.getPower() < 1){" + - " return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctServerTweaksHandler, "sendHelp", replace); + if (WyvernMods.disableHelpGMCommands) { + Util.setReason("Disable GM commands from displaying in /help unless the player is a GM."); + CtClass ctServerTweaksHandler = classPool.get("com.wurmonline.server.ServerTweaksHandler"); + replace = "if($1.getPower() < 1){" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctServerTweaksHandler, "sendHelp", replace); + } - Util.setReason("Make damage less likely to interrupt actions during combat."); - replace = "$1 = $1/2;"; - Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", replace); + if (WyvernMods.reduceActionInterruptOnDamage) { + Util.setReason("Make damage less likely to interrupt actions during combat."); + replace = "$1 = $1/2;"; + Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", replace); + } - Util.setReason("Fix mission null pointer exception."); - CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); - replace = "if(itemplates.size() < 1){" + - " com.wurmonline.server.epic.EpicServerStatus.setupMissionItemTemplates();" + - "}"; - Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); + if (WyvernMods.fixMissionNullPointerException) { + Util.setReason("Fix mission null pointer exception."); + CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); + replace = "if(itemplates.size() < 1){" + + " com.wurmonline.server.epic.EpicServerStatus.setupMissionItemTemplates();" + + "}"; + Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); + } - /*Util.setReason("Fix bug causing high cast spells to reduce power."); - CtClass ctSpellEffect = classPool.get("com.wurmonline.server.spells.SpellEffect"); - replace = "{" + - " final float mod = 5.0f * (1.0f - java.lang.Math.min($0.getPower(), 100f) / 100.0f);" + - " $0.setPower(mod + $1);" + - "}"; - Util.setBodyDeclared(thisClass, ctSpellEffect, "improvePower", replace);*/ + if (WyvernMods.disableSmeltingPots) { + Util.setReason("Disable smelting pots from being used."); + CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); + CtClass[] params14 = { + ctAction, + ctCreature, + ctItem, + ctItem, + CtClass.shortType, + CtClass.floatType + }; + String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14); + replace = "if($5 == 519){" + + " $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); + } - Util.setReason("Disable smelting pots from being used."); - CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); - CtClass[] params14 = { - ctAction, - ctCreature, - ctItem, - ctItem, - CtClass.shortType, - CtClass.floatType - }; - String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14); - replace = "if($5 == 519){" + - " $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" + - " return true;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); - - /*Util.setReason("Fix title NPE from sorting."); - CtClass ctTitleCompoundQuestion = classPool.get("com.wurmonline.server.questions.TitleCompoundQuestion"); - replace = "titles = "+MiscChanges.class.getName()+".cleanTitles(titles);" + - "int i = 0;" + - "while(i < titles.length){" + - " logger.info(\"Title: \"+titles[i]);" + - " i++;" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctTitleCompoundQuestion, "sendQuestion", "sort", replace);*/ - - /*Util.setReason("Remove buff bar spam from sorceries."); - replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctAbilities, "sendEffectsToCreature", "hasAnyAbility", replace);*/ - - Util.setReason("Hide buff bar icons for sorceries."); - CtClass ctSpellEffectsEnum = classPool.get("com.wurmonline.server.creatures.SpellEffectsEnum"); - CtClass ctString = classPool.get("java.lang.String"); - CtClass[] params15 = { - ctSpellEffectsEnum, - CtClass.intType, - ctString - }; - String desc15 = Descriptor.ofMethod(CtClass.voidType, params15); - CtClass[] params16 = { - ctSpellEffectsEnum, - CtClass.intType - }; - String desc16 = Descriptor.ofMethod(CtClass.voidType, params16); - replace = "$_ = "+MiscChanges.class.getName()+".shouldSendBuff($0);"; - Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc15, "isSendToBuffBar", replace); - Util.setReason("Hide buff bar icons for sorceries."); - Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + if (WyvernMods.hideSorceryBuffBar) { + Util.setReason("Hide buff bar icons for sorceries."); + CtClass ctSpellEffectsEnum = classPool.get("com.wurmonline.server.creatures.SpellEffectsEnum"); + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params15 = { + ctSpellEffectsEnum, + CtClass.intType, + ctString + }; + String desc15 = Descriptor.ofMethod(CtClass.voidType, params15); + CtClass[] params16 = { + ctSpellEffectsEnum, + CtClass.intType + }; + String desc16 = Descriptor.ofMethod(CtClass.voidType, params16); + replace = "$_ = " + MiscChanges.class.getName() + ".shouldSendBuff($0);"; + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc15, "isSendToBuffBar", replace); + Util.setReason("Hide buff bar icons for sorceries."); + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + } // 1.9 Achievement fix [Bdew] - classPool.getCtClass("com.wurmonline.server.players.Achievements").getMethod("loadAllAchievements", "()V") - .instrument(new ExprEditor(){ - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getTimestamp")) - m.replace("$_=com.wurmonline.server.utils.DbUtilities.getTimestampOrNull(rs.getString($1)); " + - "if ($_==null) $_=new java.sql.Timestamp(java.lang.System.currentTimeMillis());"); - } - }); + if (WyvernMods.sqlAchievementFix) { + classPool.getCtClass("com.wurmonline.server.players.Achievements").getMethod("loadAllAchievements", "()V") + .instrument(new ExprEditor() { + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getTimestamp")) + m.replace("$_=com.wurmonline.server.utils.DbUtilities.getTimestampOrNull(rs.getString($1)); " + + "if ($_==null) $_=new java.sql.Timestamp(java.lang.System.currentTimeMillis());"); + } + }); + } } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index ff6ec7b..7bff2bb 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -1,32 +1,18 @@ package mod.sin.wyvern; -import com.wurmonline.server.DbConnector; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.players.Player; -import com.wurmonline.server.players.PlayerInfo; import com.wurmonline.server.players.Titles; -import com.wurmonline.server.utils.DbUtilities; -import javassist.CtClass; -import javassist.CtPrimitiveType; -import javassist.bytecode.Descriptor; -import mod.enumbuster.EnumBuster; -import org.gotti.wurmunlimited.modloader.ReflectionUtil; -import org.gotti.wurmunlimited.modloader.classhooks.HookManager; -import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; +import net.bdew.wurm.tools.server.ModTitles; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.sql.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; public class PlayerTitles { public static Logger logger = Logger.getLogger(PlayerTitles.class.getName()); - private static Titles.Title[] titleArray; // Player Title Maps protected static ArrayList donatorTitles = new ArrayList<>(); @@ -37,10 +23,10 @@ public class PlayerTitles { // Event Title ID's public static int TITAN_SLAYER = 10000; public static int SPECTRAL = 10001; - public static int PASTAMANCER = 10002; + //public static int PASTAMANCER = 10002; // Player Donation Title ID's - public static int PATRON = 19999; + /*public static int PATRON = 19999; public static int DONATOR = 20000; public static int PAZZA_FAVORITE_GM = 20001; public static int WARRIORGEN_THAT_GUY = 20002; @@ -53,138 +39,43 @@ public class PlayerTitles { public static int SELEAS_CRAZY_CAT_LORD = 20009; public static int PIRATEMAX_SLAVE = 20010; public static int ELTACOLAD_TRUE_TACO = 20011; - public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012; - - public static void onItemTemplatesCreated(){ - interceptLoadTitles(); - EnumBuster buster = new EnumBuster<>(Titles.Title.class, Titles.Title.class); - // Random titles for fun - //PlayerTitles.createTitle(buster, "Game_Master", 2500, "Game Master", "Game Master", -1, Titles.TitleType.NORMAL); - //PlayerTitles.createTitle(buster, "Developer", 2501, "Developer", "Developer", -1, Titles.TitleType.NORMAL); - //PlayerTitles.createTitle(buster, "Pet_Me", 2502, "Pet Me", "Pet Me", -1, Titles.TitleType.NORMAL); + public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012;*/ + public static void init(){ + for (WyvernMods.CustomTitle title : WyvernMods.customTitles){ + createTitle(title.getTitleId(), title.getMaleTitle(), title.getFemaleTitle(), title.getSkillId(), title.getType()); + } // Event Titles - createTitle(buster, "Titan_Slayer", TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Spectral", SPECTRAL, "Spectral", "Spectral", -1, Titles.TitleType.NORMAL); + createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, "NORMAL"); + createTitle(SPECTRAL, "Spectral", "Spectral", -1, "NORMAL"); //PlayerTitles.createTitle(buster, "Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, Titles.TitleType.NORMAL); //PlayerTitles.createTitle(buster, "Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Pastamancer", PASTAMANCER, "Pastamancer", "Pastamancer", -1, Titles.TitleType.NORMAL); + //createTitle(PASTAMANCER, "Pastamancer", "Pastamancer", -1, "NORMAL"); // Donation Titles - createTitle(buster, "Patron", PATRON, "Patron", "Patron", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Donator", DONATOR, "Donator", "Donator", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Pazza_FavoriteGM", PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Warriorgen_ThatGuy", WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Eternallove_WarriorgensWife", ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Bambam_ThornOne", BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Svenja_CareDependant", SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Alexia_TheTreasuring", ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Reevi_ScienceGuy", REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Genocide_GrandDesigner", GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Seleas_CrazyCatLord", SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Piratemax_Slave", PIRATEMAX_SLAVE, "Slave", "Slave", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Eltacolad_TrueTaco", ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Atticus_The_Great_Illuminaty", ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, Titles.TitleType.NORMAL); + /* Moved to configuration + createTitle(PATRON, "Patron", "Patron", -1, "NORMAL"); + createTitle(DONATOR, "Donator", "Donator", -1, "NORMAL"); + createTitle(PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, "NORMAL"); + createTitle(WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, "NORMAL"); + createTitle(ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, "NORMAL"); + createTitle(BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, "NORMAL"); + createTitle(SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, "NORMAL"); + createTitle(ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, "NORMAL"); + createTitle(REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, "NORMAL"); + createTitle(GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, "NORMAL"); + createTitle(SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL"); + createTitle(PIRATEMAX_SLAVE, "Slave", "Slave", -1, "NORMAL"); + createTitle(ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, "NORMAL"); + createTitle(ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, "NORMAL");*/ // Supporter titles logger.info(Arrays.toString(Titles.Title.values())); - titleArray = Titles.Title.values(); } - private static void createTitle(EnumBuster buster, String enumName, int id, String titleMale, String titleFemale, int skillId, Titles.TitleType type) { - Titles.Title testTitle = buster.make(enumName, 0, new Class[]{Integer.TYPE, String.class, String.class, Integer.TYPE, Titles.TitleType.class}, new Object[]{id, titleMale, titleFemale, skillId, type}); - buster.addByValue(testTitle); - logger.log(Level.INFO, String.format("Created new title with ID #%d: %s [\"%s\", \"%s\"]", id, enumName, titleMale, titleFemale)); - } - - public static boolean hasTitle(Creature c, int titleId) { - if (c.isPlayer()) { - Titles.Title[] titles; - Titles.Title[] arrtitle = titles = ((Player)c).getTitles(); - int n = arrtitle.length; - int n2 = 0; - while (n2 < n) { - Titles.Title title = arrtitle[n2]; - if (title == null) { - throw new RuntimeException("We have NULL in titles collection, that is not nice at all!"); - } - if (title.getTitleId() == titleId) { - return true; - } - ++n2; - } - } else { - return true; - } - return false; - } - - private static void interceptLoadTitles() { - String descriptor = Descriptor.ofMethod((CtClass)CtPrimitiveType.voidType, (CtClass[])new CtClass[]{CtClass.longType}); - HookManager.getInstance().registerHook("com.wurmonline.server.players.DbPlayerInfo", "loadTitles", descriptor, new InvocationHandlerFactory(){ - - public InvocationHandler createInvocationHandler() { - return new InvocationHandler(){ - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object result; - block8 : { - ResultSet rs; - Connection dbcon; - PreparedStatement ps; - result = method.invoke(proxy, args); - PlayerInfo pi = (PlayerInfo)proxy; - Set titles = ReflectionUtil.getPrivateField(pi, ReflectionUtil.getField(pi.getClass(), "titles")); - titles.remove(null); - dbcon = null; - ps = null; - rs = null; - try { - try { - dbcon = DbConnector.getPlayerDbCon(); - ps = dbcon.prepareStatement("select TITLEID from TITLES where WURMID=?"); - ps.setLong(1, pi.getPlayerId()); - rs = ps.executeQuery(); - while (rs.next()) { - if (Titles.Title.getTitle(rs.getInt("TITLEID")) != null){ - continue; - } - titles.add(PlayerTitles.getTitle(rs.getInt("TITLEID"))); - } - } - catch (SQLException ex) { - logger.log(Level.INFO, "Failed to load titles for " + pi.getPlayerId(), ex); - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - break block8; - } - } - catch (Throwable throwable) { - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - throw throwable; - } - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - } - return result; - } - }; - } - - }); - } - - public static Titles.Title getTitle(int titleAsInt) { - int i = 0; - while (i < titleArray.length) { - if (titleAsInt == titleArray[i].getTitleId()) { - return titleArray[i]; - } - ++i; - } - throw new RuntimeException("Could not find title: " + titleAsInt); + private static void createTitle(int id, String titleMale, String titleFemale, int skillId, String type) { + ModTitles.addTitle(id, titleMale, titleFemale, skillId, type); + logger.log(Level.INFO, String.format("Created new title with ID #%d: [\"%s\", \"%s\"]", id, titleMale, titleFemale)); } public static boolean hasCustomTitle(Creature creature){ @@ -203,22 +94,33 @@ public class PlayerTitles { } public static void awardCustomTitles(Player p){ String name = p.getName(); - if(donatorTitles.contains(name)){ - Titles.Title donator = getTitle(DONATOR); + for (int titleId : WyvernMods.awardTitles.keySet()){ + try { + Titles.Title theTitle = Titles.Title.getTitle(titleId); + ArrayList playerList = WyvernMods.awardTitles.get(titleId); + if (playerList.contains(name)){ + p.addTitle(theTitle); + } + }catch(Exception e){ + logger.warning("Failed to get title with ID "+titleId); + } + } + /*if(donatorTitles.contains(name)){ + Titles.Title donator = Titles.Title.getTitle(DONATOR); p.addTitle(donator); } if(patronTitles.contains(name)){ - Titles.Title patron = getTitle(PATRON); + Titles.Title patron = Titles.Title.getTitle(PATRON); p.addTitle(patron); } if(customTitles.containsKey(name)){ - Titles.Title customTitle = getTitle(customTitles.get(name)); + Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name)); p.addTitle(customTitle); - } + }*/ } public static void preInit(){ // Donations - donatorTitles.add("Pazza"); + /*donatorTitles.add("Pazza"); customTitles.put("Pazza", PAZZA_FAVORITE_GM); // Sindusks Favorite GM donatorTitles.add("Warriorgen"); @@ -258,6 +160,6 @@ public class PlayerTitles { customTitles.put("Atticus", ATTICUS_THE_GREAT_ILLUMINATY); // The Great Illuminaty // Other rewards - customTitles.put("Critias", PASTAMANCER); + customTitles.put("Critias", PASTAMANCER);*/ } } diff --git a/src/main/java/mod/sin/wyvern/QualityOfLife.java b/src/main/java/mod/sin/wyvern/QualityOfLife.java index 59bf52a..1201d80 100644 --- a/src/main/java/mod/sin/wyvern/QualityOfLife.java +++ b/src/main/java/mod/sin/wyvern/QualityOfLife.java @@ -87,7 +87,6 @@ public class QualityOfLife { final Class thisClass = QualityOfLife.class; String replace; - Util.setReason("Allow players to mine directly into vehicles."); CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); @@ -106,45 +105,35 @@ public class QualityOfLife { CtClass.floatType }; String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); - replace = "$_ = null;" - + QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc1, "putItemInfrontof", replace); + if (WyvernMods.mineCaveToVehicle) { + Util.setReason("Allow players to mine directly into vehicles."); + replace = "$_ = null;" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc1, "putItemInfrontof", replace); + } - /*Util.setReason("Allow players to surface mine directly into vehicles."); CtClass ctTileRockBehaviour = classPool.get("com.wurmonline.server.behaviours.TileRockBehaviour"); - CtClass[] params2 = { - ctAction, - ctCreature, - ctItem, - CtClass.intType, - CtClass.intType, - CtClass.booleanType, - CtClass.intType, - CtClass.intType, - CtClass.shortType, - CtClass.floatType - }; - String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); - replace = "$_ = $proceed($$);" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "action", desc2, "setDataXY", replace);*/ + if (WyvernMods.mineSurfaceToVehicle) { + Util.setReason("Allow players to surface mine directly into vehicles."); + replace = "$_ = $proceed($$);" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDeclared(thisClass, ctTileRockBehaviour, "mine", "setDataXY", replace); + } - Util.setReason("Allow players to surface mine directly into vehicles."); - CtClass ctTileRockBehaviour = classPool.get("com.wurmonline.server.behaviours.TileRockBehaviour"); - replace = "$_ = $proceed($$);" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDeclared(thisClass, ctTileRockBehaviour, "mine", "setDataXY", replace); - - Util.setReason("Allow players to chop logs directly into vehicles."); CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "$_ = null;" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "chop", "putItemInfrontof", replace); + if (WyvernMods.chopLogsToVehicle) { + Util.setReason("Allow players to chop logs directly into vehicles."); + replace = "$_ = null;" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "chop", "putItemInfrontof", replace); + } - Util.setReason("Allow statuettes to be used when not gold/silver."); - String desc100 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{}); - replace = "{ return this.template.holyItem; }"; - Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc100, replace); + if (WyvernMods.statuetteAnyMaterial) { + Util.setReason("Allow statuettes to be used when not gold/silver."); + String desc100 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{}); + replace = "{ return this.template.holyItem; }"; + Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc100, replace); + } /* Disabled in Wurm Unlimited 1.9 - Priest Rework changes removed this restriction. @@ -153,30 +142,34 @@ public class QualityOfLife { replace = "$_ = false;"; Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", replace);*/ - Util.setReason("Send gems, source crystals, flint, etc. into vehicle."); - CtClass[] params2 = { - CtClass.intType, - CtClass.intType, - CtClass.intType, - CtClass.intType, - ctCreature, - CtClass.doubleType, - CtClass.booleanType, - ctAction - }; - String desc2 = Descriptor.ofMethod(ctItem, params2); - replace = "$_ = null;" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "createGem", desc2, "putItemInfrontof", replace); + if (WyvernMods.mineGemsToVehicle) { + Util.setReason("Send gems, source crystals, flint, etc. into vehicle."); + CtClass[] params2 = { + CtClass.intType, + CtClass.intType, + CtClass.intType, + CtClass.intType, + ctCreature, + CtClass.doubleType, + CtClass.booleanType, + ctAction + }; + String desc2 = Descriptor.ofMethod(ctItem, params2); + replace = "$_ = null;" + + 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;"); - } - }); + if (WyvernMods.regenerateStaminaOnVehicleAnySlope) { + 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); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index feba667..8910dad 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -1,21 +1,24 @@ package mod.sin.wyvern; -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.file.Paths; -import java.util.Properties; -import java.util.logging.FileHandler; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; - import com.wurmonline.server.Message; +import com.wurmonline.server.TimeConstants; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.items.*; +import com.wurmonline.server.players.Player; +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; +import mod.sin.actions.*; import mod.sin.actions.items.SorcerySplitAction; +import mod.sin.creatures.*; +import mod.sin.creatures.titans.*; +import mod.sin.lib.Prop; import mod.sin.lib.Util; +import mod.sin.wyvern.bestiary.MethodsBestiary; +import mod.sin.wyvern.mastercraft.Mastercraft; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -24,28 +27,177 @@ import org.gotti.wurmunlimited.modsupport.actions.ModActions; import org.gotti.wurmunlimited.modsupport.creatures.ModCreatures; import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviours; -import com.wurmonline.server.TimeConstants; -import com.wurmonline.server.players.Player; - -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.NotFoundException; -import javassist.expr.ExprEditor; -import javassist.expr.MethodCall; -import mod.sin.actions.*; -import mod.sin.creatures.*; -import mod.sin.creatures.titans.*; -import mod.sin.wyvern.bestiary.MethodsBestiary; -import mod.sin.wyvern.mastercraft.Mastercraft; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Properties; +import java.util.logging.Logger; public class WyvernMods implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener, PlayerLoginListener, ChannelMessageListener { private static Logger logger = Logger.getLogger(WyvernMods.class.getName()); public static boolean espCounter = false; public static boolean enableDepots = false; - - boolean bDebug = false; + + // Miscellaneous Changes Module Configuration + public static boolean enableMiscChangesModule = true; + public static boolean enableInfoTab = true; + public static String infoTabName = "Server"; + public static ArrayList infoTabLines = new ArrayList<>(); + public static boolean ignoreBridgeChecks = true; + public static boolean disableMailboxUsageWhileLoaded = true; + public static boolean increasedLegendaryCreatures = true; + public static int increasedLegendaryFrequency = 5; + public static boolean allowFacebreykerNaturalSpawn = true; + public static boolean announcePlayerTitles = true; + public static boolean improveCombinedLeather = true; + public static boolean allowModdedImproveTemplates = true; + public static boolean fatigueActionOverride = true; + public static boolean fixPortalIssues = true; + public static boolean disableMinimumShieldDamage = true; + public static boolean disableGMEmoteLimit = true; + public static boolean creatureArcheryWander = true; + public static boolean globalDeathTabs = true; + public static boolean disablePvPOnlyDeathTabs = true; + public static boolean fixLibilaCrossingIssues = true; + public static boolean higherFoodAffinities = true; + public static boolean fasterCharcoalBurn = true; + public static boolean uncapTraderItemCount = true; + public static boolean logExcessiveActions = true; + public static boolean useDynamicSkillRate = true; + public static boolean reduceLockpickBreaking = true; + public static boolean allowFreedomMyceliumAbsorb = true; + public static boolean largerHouses = true; + public static boolean reduceImbuePower = true; + public static boolean fixVehicleSpeeds = true; + public static boolean reduceMailingCosts = true; + public static boolean guardTargetChanges = true; + public static boolean enableLibilaStrongwallPvE = true; + public static boolean royalCookNoFoodDecay = true; + public static boolean mayorsCommandAbandonedVehicles = true; + public static boolean opulenceFoodAffinityTimerIncrease = true; + public static boolean disableFoodFirstBiteBonus = true; + public static boolean bedQualitySleepBonus = true; + public static boolean royalSmithImproveFaster = true; + public static boolean fixMountedBodyStrength = true; + public static boolean adjustedFoodBiteFill = true; + public static boolean rareMaterialImprove = true; + public static boolean rarityWindowBadLuckProtection = true; + public static boolean rareCreationAdjustments = true; + public static boolean alwaysArmourTitleBenefits = true; + public static boolean tomeUsageAnyAltar = true; + public static boolean keyOfHeavensLoginOnly = true; + public static boolean lessFillingDrinks = true; + public static boolean disableHelpGMCommands = true; + public static boolean reduceActionInterruptOnDamage = true; + public static boolean fixMissionNullPointerException = true; + public static boolean disableSmeltingPots = true; + public static boolean hideSorceryBuffBar = true; + public static boolean sqlAchievementFix = true; + + // Arena Module Configuration + public static boolean enableArenaModule = true; + public static boolean equipHorseGearByLeading = true; + public static boolean lockpickingImprovements = true; + public static boolean placeDeedsOutsideKingdomInfluence = true; + public static boolean disablePMKs = true; + public static boolean disablePlayerChampions = true; + public static boolean arenaAggression = true; + public static boolean enemyTitleHook = true; + public static boolean enemyPresenceOnAggression = true; + public static boolean disableFarwalkerItems = true; + public static boolean alwaysAllowAffinitySteal = true; + public static boolean adjustFightSkillGain = true; + public static boolean useAggressionForNearbyEnemies = true; + public static boolean disablePvPCorpseProtection = true; + public static boolean bypassHousePermissions = true; + public static boolean allowStealingAgainstDeityWishes = true; + public static boolean sameKingdomVehicleTheft = true; + public static boolean adjustMineDoorDamage = true; + public static boolean sameKingdomPermissionsAdjustments = true; + public static boolean disableCAHelpOnPvP = true; + public static boolean sameKingdomVillageWarfare = true; + public static boolean adjustHotARewards = true; + public static boolean capMaximumGuards = true; + public static boolean disableTowerConstruction = true; + public static boolean adjustLocalRange = true; + public static boolean disableKarmaTeleport = true; + public static boolean limitLeadCreatures = true; + public static boolean adjustBashTimer = true; + public static boolean discordRelayHotAMessages = true; + public static boolean allowAttackingSameKingdomGuards = true; + public static boolean fixGuardsAttackingThemselves = true; + public static boolean reducedMineDoorOpenTime = true; + public static boolean allowSameKingdomFightSkillGains = true; + public static boolean allowArcheringOnSameKingdomDeeds = true; + public static boolean sendNewSpawnQuestionOnPvP = true; + public static boolean sendArtifactDigsToDiscord = true; + public static boolean makeFreedomFavoredKingdom = true; + public static boolean crownInfluenceOnAggression = true; + public static boolean disableOWFL = true; + public static boolean resurrectionStonesProtectSkill = true; + public static boolean resurrectionStonesProtectFightSkill = true; + public static boolean resurrectionStonesProtectAffinities = true; + public static boolean bypassPlantedPermissionChecks = true; + + // Custom Titles Module Configuration + public static boolean enableCustomTitlesModule = true; + public static ArrayList customTitles = new ArrayList<>(); + public static HashMap> awardTitles = new HashMap<>(); + + // Anti-Cheat Module Configuration + public static boolean enableAntiCheatModule = true; + public static boolean enableSpoofHiddenOre = true; + public static boolean prospectingVision = true; + public static boolean mapSteamIds = true; + + // Quality Of Life Module Configuration + public static boolean enableQualityOfLifeModule = true; + public static boolean mineCaveToVehicle = true; + public static boolean mineSurfaceToVehicle = true; + public static boolean chopLogsToVehicle = true; + public static boolean statuetteAnyMaterial = true; + public static boolean mineGemsToVehicle = true; + public static boolean regenerateStaminaOnVehicleAnySlope = true; + + // Treasure Chest Loot Module Configuration + public static boolean enableTreasureChestLootModule = true; + + public static class CustomTitle{ + protected int titleId; + protected String maleTitle; + protected String femaleTitle; + protected int skillId; + protected String type; + public CustomTitle(int titleId, String maleTitle, String femaleTitle, int skillId, String type){ + this.titleId = titleId; + this.maleTitle = maleTitle; + this.femaleTitle = femaleTitle; + this.skillId = skillId; + if (type.equals("NORMAL") || type.equals("MINOR") || type.equals("MASTER") || type.equals("LEGENDARY")){ + this.type = type; + }else{ + logger.info("Failed to register proper custom title type \""+type+"\" for title ID "+titleId+". Defaulting to \"NORMAL\""); + this.type = "NORMAL"; + } + } + public int getTitleId(){ + return titleId; + } + public String getMaleTitle(){ + return maleTitle; + } + public String getFemaleTitle(){ + return femaleTitle; + } + public int getSkillId(){ + return skillId; + } + public String getType(){ + return type; + } + } public static boolean customCommandHandler(ByteBuffer byteBuffer, Player player) throws UnsupportedEncodingException{ byte[] tempStringArr = new byte[byteBuffer.get() & 255]; @@ -71,35 +223,331 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea } public void configure(Properties properties) { - this.bDebug = Boolean.parseBoolean(properties.getProperty("debug", Boolean.toString(this.bDebug))); - try { - String logsPath = Paths.get("mods", new String[0]) + "/logs/"; - File newDirectory = new File(logsPath); - if (!newDirectory.exists()) { - newDirectory.mkdirs(); - } - FileHandler fh = new FileHandler(String.valueOf(String.valueOf(logsPath)) + this.getClass().getSimpleName() + ".log", 10240000, 200, true); - if (this.bDebug) { - fh.setLevel(Level.INFO); - } else { - fh.setLevel(Level.WARNING); - } - fh.setFormatter(new SimpleFormatter()); - logger.addHandler(fh); - } - catch (IOException ie) { - System.err.println(String.valueOf(this.getClass().getName()) + ": Unable to add file handler to logger"); - } - //this.logger.log(Level.INFO, "Property: " + this.somevalue); - this.Debug("Debugging messages are enabled."); - } + Prop.properties = properties; - private void Debug(String x) { - if (this.bDebug) { - System.out.println(String.valueOf(this.getClass().getSimpleName()) + ": " + x); - System.out.flush(); - logger.log(Level.INFO, x); - } + // -- Configuration Setting -- // + + // Miscellaneous Changes Module + enableMiscChangesModule = Prop.getBooleanProperty("enableMiscChangesModule", enableMiscChangesModule); + enableInfoTab = Prop.getBooleanProperty("enableInfoTab", enableInfoTab); + infoTabName = Prop.getStringProperty("infoTabName", infoTabName); + ignoreBridgeChecks = Prop.getBooleanProperty("ignoreBridgeChecks", ignoreBridgeChecks); + disableMailboxUsageWhileLoaded = Prop.getBooleanProperty("disableMailboxUsageWhileLoaded", disableMailboxUsageWhileLoaded); + increasedLegendaryCreatures = Prop.getBooleanProperty("increasedLegendaryCreatures", increasedLegendaryCreatures); + increasedLegendaryFrequency = Prop.getIntegerProperty("increasedLegendaryFrequency", increasedLegendaryFrequency); + allowFacebreykerNaturalSpawn = Prop.getBooleanProperty("allowFacebreykerNaturalSpawn", allowFacebreykerNaturalSpawn); + announcePlayerTitles = Prop.getBooleanProperty("announcePlayerTitles", announcePlayerTitles); + improveCombinedLeather = Prop.getBooleanProperty("improveCombinedLeather", improveCombinedLeather); + allowModdedImproveTemplates = Prop.getBooleanProperty("allowModdedImproveTemplates", allowModdedImproveTemplates); + fatigueActionOverride = Prop.getBooleanProperty("fatigueActionOverride", fatigueActionOverride); + fixPortalIssues = Prop.getBooleanProperty("fixPortalIssues", fixPortalIssues); + disableMinimumShieldDamage = Prop.getBooleanProperty("disableMinimumShieldDamage", disableMinimumShieldDamage); + disableGMEmoteLimit = Prop.getBooleanProperty("disableGMEmoteLimit", disableGMEmoteLimit); + creatureArcheryWander = Prop.getBooleanProperty("creatureArcheryWander", creatureArcheryWander); + globalDeathTabs = Prop.getBooleanProperty("globalDeathTabs", globalDeathTabs); + disablePvPOnlyDeathTabs = Prop.getBooleanProperty("disablePvPOnlyDeathTabs", disablePvPOnlyDeathTabs); + fixLibilaCrossingIssues = Prop.getBooleanProperty("fixLibilaCrossingIssues", fixLibilaCrossingIssues); + higherFoodAffinities = Prop.getBooleanProperty("higherFoodAffinities", higherFoodAffinities); + fasterCharcoalBurn = Prop.getBooleanProperty("fasterCharcoalBurn", fasterCharcoalBurn); + uncapTraderItemCount = Prop.getBooleanProperty("uncapTraderItemCount", uncapTraderItemCount); + logExcessiveActions = Prop.getBooleanProperty("logExcessiveActions", logExcessiveActions); + useDynamicSkillRate = Prop.getBooleanProperty("useDynamicSkillRate", useDynamicSkillRate); + reduceLockpickBreaking = Prop.getBooleanProperty("reduceLockpickBreaking", reduceLockpickBreaking); + allowFreedomMyceliumAbsorb = Prop.getBooleanProperty("allowFreedomMyceliumAbsorb", allowFreedomMyceliumAbsorb); + largerHouses = Prop.getBooleanProperty("largerHouses", largerHouses); + reduceImbuePower = Prop.getBooleanProperty("reduceImbuePower", reduceImbuePower); + fixVehicleSpeeds = Prop.getBooleanProperty("fixVehicleSpeeds", fixVehicleSpeeds); + reduceMailingCosts = Prop.getBooleanProperty("reduceMailingCosts", reduceMailingCosts); + guardTargetChanges = Prop.getBooleanProperty("guardTargetChanges", guardTargetChanges); + enableLibilaStrongwallPvE = Prop.getBooleanProperty("enableLibilaStrongwallPvE", enableLibilaStrongwallPvE); + royalCookNoFoodDecay = Prop.getBooleanProperty("royalCookNoFoodDecay", royalCookNoFoodDecay); + mayorsCommandAbandonedVehicles = Prop.getBooleanProperty("mayorsCommandAbandonedVehicles", mayorsCommandAbandonedVehicles); + opulenceFoodAffinityTimerIncrease = Prop.getBooleanProperty("opulenceFoodAffinityTimerIncrease", opulenceFoodAffinityTimerIncrease); + disableFoodFirstBiteBonus = Prop.getBooleanProperty("disableFoodFirstBiteBonus", disableFoodFirstBiteBonus); + bedQualitySleepBonus = Prop.getBooleanProperty("bedQualitySleepBonus", bedQualitySleepBonus); + royalSmithImproveFaster = Prop.getBooleanProperty("royalSmithImproveFaster", royalSmithImproveFaster); + fixMountedBodyStrength = Prop.getBooleanProperty("fixMountedBodyStrength", fixMountedBodyStrength); + adjustedFoodBiteFill = Prop.getBooleanProperty("adjustedFoodBiteFill", adjustedFoodBiteFill); + rareMaterialImprove = Prop.getBooleanProperty("rareMaterialImprove", rareMaterialImprove); + rarityWindowBadLuckProtection = Prop.getBooleanProperty("rarityWindowBadLuckProtection", rarityWindowBadLuckProtection); + rareCreationAdjustments = Prop.getBooleanProperty("rareCreationAdjustments", rareCreationAdjustments); + alwaysArmourTitleBenefits = Prop.getBooleanProperty("alwaysArmourTitleBenefits", alwaysArmourTitleBenefits); + tomeUsageAnyAltar = Prop.getBooleanProperty("tomeUsageAnyAltar", tomeUsageAnyAltar); + keyOfHeavensLoginOnly = Prop.getBooleanProperty("keyOfHeavensLoginOnly", keyOfHeavensLoginOnly); + lessFillingDrinks = Prop.getBooleanProperty("lessFillingDrinks", lessFillingDrinks); + disableHelpGMCommands = Prop.getBooleanProperty("disableHelpGMCommands", disableHelpGMCommands); + reduceActionInterruptOnDamage = Prop.getBooleanProperty("reduceActionInterruptOnDamage", reduceActionInterruptOnDamage); + fixMissionNullPointerException = Prop.getBooleanProperty("fixMissionNullPointerException", fixMissionNullPointerException); + disableSmeltingPots = Prop.getBooleanProperty("disableSmeltingPots", disableSmeltingPots); + hideSorceryBuffBar = Prop.getBooleanProperty("hideSorceryBuffBar", hideSorceryBuffBar); + sqlAchievementFix = Prop.getBooleanProperty("sqlAchievementFix", sqlAchievementFix); + + // Arena Module + enableArenaModule = Prop.getBooleanProperty("enableArenaModule", enableArenaModule); + equipHorseGearByLeading = Prop.getBooleanProperty("equipHorseGearByLeading", equipHorseGearByLeading); + lockpickingImprovements = Prop.getBooleanProperty("lockpickingImprovements", lockpickingImprovements); + placeDeedsOutsideKingdomInfluence = Prop.getBooleanProperty("placeDeedsOutsideKingdomInfluence", placeDeedsOutsideKingdomInfluence); + disablePMKs = Prop.getBooleanProperty("disablePMKs", disablePMKs); + disablePlayerChampions = Prop.getBooleanProperty("disablePlayerChampions", disablePlayerChampions); + arenaAggression = Prop.getBooleanProperty("arenaAggression", arenaAggression); + enemyTitleHook = Prop.getBooleanProperty("enemyTitleHook", enemyTitleHook); + enemyPresenceOnAggression = Prop.getBooleanProperty("enemyPresenceOnAggression", enemyPresenceOnAggression); + disableFarwalkerItems = Prop.getBooleanProperty("disableFarwalkerItems", disableFarwalkerItems); + alwaysAllowAffinitySteal = Prop.getBooleanProperty("alwaysAllowAffinitySteal", alwaysAllowAffinitySteal); + adjustFightSkillGain = Prop.getBooleanProperty("adjustFightSkillGain", adjustFightSkillGain); + useAggressionForNearbyEnemies = Prop.getBooleanProperty("useAggressionForNearbyEnemies", useAggressionForNearbyEnemies); + disablePvPCorpseProtection = Prop.getBooleanProperty("disablePvPCorpseProtection", disablePvPCorpseProtection); + bypassHousePermissions = Prop.getBooleanProperty("bypassHousePermissions", bypassHousePermissions); + allowStealingAgainstDeityWishes = Prop.getBooleanProperty("allowStealingAgainstDeityWishes", allowStealingAgainstDeityWishes); + sameKingdomVehicleTheft = Prop.getBooleanProperty("sameKingdomVehicleTheft", sameKingdomVehicleTheft); + adjustMineDoorDamage = Prop.getBooleanProperty("adjustMineDoorDamage", adjustMineDoorDamage); + sameKingdomPermissionsAdjustments = Prop.getBooleanProperty("sameKingdomPermissionsAdjustments", sameKingdomPermissionsAdjustments); + disableCAHelpOnPvP = Prop.getBooleanProperty("disableCAHelpOnPvP", disableCAHelpOnPvP); + sameKingdomVillageWarfare = Prop.getBooleanProperty("sameKingdomVillageWarfare", sameKingdomVillageWarfare); + adjustHotARewards = Prop.getBooleanProperty("adjustHotARewards", adjustHotARewards); + capMaximumGuards = Prop.getBooleanProperty("capMaximumGuards", capMaximumGuards); + disableTowerConstruction = Prop.getBooleanProperty("disableTowerConstruction", disableTowerConstruction); + adjustLocalRange = Prop.getBooleanProperty("adjustLocalRange", adjustLocalRange); + disableKarmaTeleport = Prop.getBooleanProperty("disableKarmaTeleport", disableKarmaTeleport); + limitLeadCreatures = Prop.getBooleanProperty("limitLeadCreatures", limitLeadCreatures); + adjustBashTimer = Prop.getBooleanProperty("adjustBashTimer", adjustBashTimer); + discordRelayHotAMessages = Prop.getBooleanProperty("discordRelayHotAMessages", discordRelayHotAMessages); + allowAttackingSameKingdomGuards = Prop.getBooleanProperty("allowAttackingSameKingdomGuards", allowAttackingSameKingdomGuards); + fixGuardsAttackingThemselves = Prop.getBooleanProperty("fixGuardsAttackingThemselves", fixGuardsAttackingThemselves); + reducedMineDoorOpenTime = Prop.getBooleanProperty("reducedMineDoorOpenTime", reducedMineDoorOpenTime); + allowSameKingdomFightSkillGains = Prop.getBooleanProperty("allowSameKingdomFightSkillGains", allowSameKingdomFightSkillGains); + allowArcheringOnSameKingdomDeeds = Prop.getBooleanProperty("allowArcheringOnSameKingdomDeeds", allowArcheringOnSameKingdomDeeds); + sendNewSpawnQuestionOnPvP = Prop.getBooleanProperty("sendNewSpawnQuestionOnPvP", sendNewSpawnQuestionOnPvP); + sendArtifactDigsToDiscord = Prop.getBooleanProperty("sendArtifactDigsToDiscord", sendArtifactDigsToDiscord); + makeFreedomFavoredKingdom = Prop.getBooleanProperty("makeFreedomFavoredKingdom", makeFreedomFavoredKingdom); + crownInfluenceOnAggression = Prop.getBooleanProperty("crownInfluenceOnAggression", crownInfluenceOnAggression); + disableOWFL = Prop.getBooleanProperty("disableOWFL", disableOWFL); + resurrectionStonesProtectSkill = Prop.getBooleanProperty("resurrectionStonesProtectSkill", resurrectionStonesProtectSkill); + resurrectionStonesProtectFightSkill = Prop.getBooleanProperty("resurrectionStonesProtectFightSkill", resurrectionStonesProtectFightSkill); + resurrectionStonesProtectAffinities = Prop.getBooleanProperty("resurrectionStonesProtectAffinities", resurrectionStonesProtectAffinities); + bypassPlantedPermissionChecks = Prop.getBooleanProperty("bypassPlantedPermissionChecks", bypassPlantedPermissionChecks); + + // Custom Titles Module + enableCustomTitlesModule = Prop.getBooleanProperty("enableCustomTitlesModule", enableCustomTitlesModule); + + // Anti-Cheat Module + enableAntiCheatModule = Prop.getBooleanProperty("enableAntiCheatModule", enableAntiCheatModule); + enableSpoofHiddenOre = Prop.getBooleanProperty("enableSpoofHiddenOre", enableSpoofHiddenOre); + prospectingVision = Prop.getBooleanProperty("prospectingVision", prospectingVision); + mapSteamIds = Prop.getBooleanProperty("mapSteamIds", mapSteamIds); + + // Quality Of Life Module + enableQualityOfLifeModule = Prop.getBooleanProperty("enableQualityOfLifeModule", enableQualityOfLifeModule); + mineCaveToVehicle = Prop.getBooleanProperty("mineCaveToVehicle", mineCaveToVehicle); + mineSurfaceToVehicle = Prop.getBooleanProperty("mineSurfaceToVehicle", mineSurfaceToVehicle); + chopLogsToVehicle = Prop.getBooleanProperty("chopLogsToVehicle", chopLogsToVehicle); + statuetteAnyMaterial = Prop.getBooleanProperty("statuetteAnyMaterial", statuetteAnyMaterial); + mineGemsToVehicle = Prop.getBooleanProperty("mineGemsToVehicle", mineGemsToVehicle); + regenerateStaminaOnVehicleAnySlope = Prop.getBooleanProperty("regenerateStaminaOnVehicleAnySlope", regenerateStaminaOnVehicleAnySlope); + + // Treasure Chest Loot Module + enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule); + + // Multiple-option Configuration Parsing + // This handles all the configurations that allow multiple different configurations to be applied. + for (String name : properties.stringPropertyNames()) { + try { + String value = properties.getProperty(name); + switch (name) { + case "debug": + case "classname": + case "classpath": + case "sharedClassLoader": + case "depend.requires": + case "depend.import": + case "depend.suggests": + break; //ignore + default: + if (name.startsWith("infoTabLine")) { + infoTabLines.add(value); + }else if (name.startsWith("addCustomTitle")) { + String[] values = value.split(","); + if(values.length > 5 || values.length < 5){ + logger.warning("Error parsing Custom Title: Invalid amount of arguments for following property: "+value); + } + int titleId = Integer.valueOf(values[0]); + String maleTitle = values[1]; + String femaleTitle = values[2]; + int skillId = Integer.valueOf(values[3]); + String titleType = values[4]; + customTitles.add(new CustomTitle(titleId, maleTitle, femaleTitle, skillId, titleType)); + }else if (name.startsWith("awardTitle")) { + String[] values = value.split(","); + if(values.length < 2){ + logger.warning("Error parsing Award Title: Invalid amount of arguments for following property: "+value); + } + int titleId = Integer.valueOf(values[0]); + ArrayList playerList; + if (awardTitles.containsKey(titleId)){ + // Has an entry already, add to the existing list. + playerList = awardTitles.get(titleId); + }else{ + // No entry, should create a new array and add it to the map + playerList = new ArrayList<>(); + } + for (int i = 1; i < values.length; i++){ + if(playerList.contains(values[i])){ + logger.warning("Duplicate player entry for single title: "+values[i]+" for title "+titleId+"."); + }else{ + playerList.add(values[i]); + } + } + awardTitles.put(titleId, playerList); + } + } + } catch (Exception e) { + logger.severe("Error processing property " + name); + e.printStackTrace(); + } + } + + // -- Configuration Print -- // + logger.info("Miscellaneous Changes Module: "+enableMiscChangesModule); + if(enableMiscChangesModule) { + logger.info("Information Tab: " + enableInfoTab); + if (enableInfoTab) { + logger.info("> Information Tab Name: " + infoTabName); + for (String tabLine : infoTabLines) { + logger.info("> Information Tab Line: " + tabLine); + } + } + logger.info("Ignore Bridge Checks: " + ignoreBridgeChecks); + logger.info("Disable Mailbox Usage While Loaded: " + disableMailboxUsageWhileLoaded); + logger.info("Increased Legendary Creatures: " + increasedLegendaryCreatures); + logger.info("Increased Legendary Frequency: " + increasedLegendaryFrequency + "x"); + logger.info("Allow Facebreyker Natural Spawn: " + allowFacebreykerNaturalSpawn); + logger.info("Announce Player Titles: " + announcePlayerTitles); + logger.info("Improve Combined Leather: " + improveCombinedLeather); + logger.info("Allow Modded Improve Templates: " + allowModdedImproveTemplates); + logger.info("Fatigue Action Override: " + fatigueActionOverride); + logger.info("Fix Portal Issues: " + fixPortalIssues); + logger.info("Disable Minimum Shield Damage: " + disableMinimumShieldDamage); + logger.info("Disable GM Emote Limit: " + disableGMEmoteLimit); + logger.info("Creature Archery Wander: " + creatureArcheryWander); + logger.info("Global Death Tabs: " + globalDeathTabs); + logger.info("Disable PvP Only Death Tabs: " + disablePvPOnlyDeathTabs); + logger.info("Fix Libila Crossing Issues: " + fixLibilaCrossingIssues); + logger.info("Higher Food Affinities: " + higherFoodAffinities); + logger.info("Faster Charcoal Burn: " + fasterCharcoalBurn); + logger.info("Uncap Trader Item Count: " + uncapTraderItemCount); + logger.info("Log Excessive Actions: " + logExcessiveActions); + logger.info("Use Dynamic Skill Rate: " + useDynamicSkillRate); + logger.info("Reduce Lockpick Breaking: " + reduceLockpickBreaking); + logger.info("Allow Freedom Mycelium Absorb: " + allowFreedomMyceliumAbsorb); + logger.info("Larger Houses: " + largerHouses); + logger.info("Reduce Imbue Power: " + reduceImbuePower); + logger.info("Fix Vehicle Speeds: " + fixVehicleSpeeds); + logger.info("Reduce Mailing Costs: " + reduceMailingCosts); + logger.info("Guard Target Changes: " + guardTargetChanges); + logger.info("Enable Libila Strongwall on PvE: " + enableLibilaStrongwallPvE); + logger.info("Royal Cook No Food Decay: " + royalCookNoFoodDecay); + logger.info("Mayors Command Abandoned Vehicles: " + mayorsCommandAbandonedVehicles); + logger.info("Opulence Food Affinity Timer Increase: " + opulenceFoodAffinityTimerIncrease); + logger.info("Disable Food First Bite Bonus: " + disableFoodFirstBiteBonus); + logger.info("Bed Quality Sleep Bonus: " + bedQualitySleepBonus); + logger.info("Royal Smith Improve Faster: " + royalSmithImproveFaster); + logger.info("Fix Mounted Body Strength: " + fixMountedBodyStrength); + logger.info("Adjusted Food Bite Fill: " + adjustedFoodBiteFill); + logger.info("Rare Material Improve: " + rareMaterialImprove); + logger.info("Rarity Window Bad Luck Protection: " + rarityWindowBadLuckProtection); + logger.info("Rare Creation Adjustments: " + rareCreationAdjustments); + logger.info("Always Armour Title Benefits: " + alwaysArmourTitleBenefits); + logger.info("Tome Usage Any Altar: " + tomeUsageAnyAltar); + logger.info("Key Of Heavens Login Only: " + keyOfHeavensLoginOnly); + logger.info("Less Filling Drinks: " + lessFillingDrinks); + logger.info("Disable Help GM Commands: " + disableHelpGMCommands); + logger.info("Reduce Action Interrupt On Damage: " + reduceActionInterruptOnDamage); + logger.info("Fix Mission Null Pointer Exception: " + fixMissionNullPointerException); + logger.info("Disable Smelting Pots: " + disableSmeltingPots); + logger.info("Hide Sorcery Buff Bar: " + hideSorceryBuffBar); + logger.info("SQL Achievement Fix: " + sqlAchievementFix); + } + + logger.info("Arena Module: "+enableArenaModule); + if(enableArenaModule) { + logger.info("Equip Horse Gear By Leading: " + equipHorseGearByLeading); + logger.info("Lockpicking Improvements: "+lockpickingImprovements); + logger.info("Place Deeds Outside Kingdom Influence: "+placeDeedsOutsideKingdomInfluence); + logger.info("Disable PMK's: "+disablePMKs); + logger.info("Disable Player Champions: "+disablePlayerChampions); + logger.info("Arena Aggression: "+arenaAggression); + logger.info("Enemy Title Hook: "+enemyTitleHook); + logger.info("Enemy Presence On Aggression: "+enemyPresenceOnAggression); + logger.info("Disable Farwalker Items: "+disableFarwalkerItems); + logger.info("Always Allow Affinity Steal: "+alwaysAllowAffinitySteal); + logger.info("Adjust Fight Skill Gain: "+adjustFightSkillGain); + logger.info("Use Aggression For Nearby Enemies: "+useAggressionForNearbyEnemies); + logger.info("Disable PvP Corpse Protection: "+disablePvPCorpseProtection); + logger.info("Bypass House Permissions: "+bypassHousePermissions); + logger.info("Allow Stealing Against Deity Wishes: "+allowStealingAgainstDeityWishes); + logger.info("Same Kingdom Vehicle Theft: "+sameKingdomVehicleTheft); + logger.info("Adjust Mine Door Damage: "+adjustMineDoorDamage); + logger.info("Same Kingdom Permission Adjustments: "+sameKingdomPermissionsAdjustments); + logger.info("Disable CA Help On PvP: "+disableCAHelpOnPvP); + logger.info("Same Kingdom Village Warfare: "+sameKingdomVillageWarfare); + logger.info("Adjust HotA Rewards: "+adjustHotARewards); + logger.info("Cap Maximum Guards: "+capMaximumGuards); + logger.info("Disable Tower Construction: "+disableTowerConstruction); + logger.info("Adjust Local Range: "+adjustLocalRange); + logger.info("Disable Karma Teleport: "+disableKarmaTeleport); + logger.info("Limit Lead Creatures: "+limitLeadCreatures); + logger.info("Adjust Bash Timer: "+adjustBashTimer); + logger.info("Discord Relay HotA Messages: "+discordRelayHotAMessages); + logger.info("Allow Attacking Same Kingdom Guards: "+allowAttackingSameKingdomGuards); + logger.info("Fix Guards Attacking Themselves: "+fixGuardsAttackingThemselves); + logger.info("Reduced Mine Door Open Time: "+reducedMineDoorOpenTime); + logger.info("Allow Same Kingdom Fight Skill Gains: "+allowSameKingdomFightSkillGains); + logger.info("Allow Archering On Same Kingdom Deeds: "+allowArcheringOnSameKingdomDeeds); + logger.info("Send New Spawn Question On PvP: "+sendNewSpawnQuestionOnPvP); + logger.info("Send Artifact Digs To Discord: "+sendArtifactDigsToDiscord); + logger.info("Make Freedom Favored Kingdom: "+makeFreedomFavoredKingdom); + logger.info("Crown Influence On Aggression: "+crownInfluenceOnAggression); + logger.info("Disable Open World Full Loot: "+disableOWFL); + logger.info("Resurrection Stones Protect Skill: "+resurrectionStonesProtectSkill); + logger.info("Resurrection Stones Protect Fight Skill: "+resurrectionStonesProtectFightSkill); + logger.info("Resurrection Stones Protect Affinities: "+resurrectionStonesProtectAffinities); + logger.info("Bypass Planted Permission Checks: "+bypassPlantedPermissionChecks); + } + + logger.info("Custom Titles Module: "+enableCustomTitlesModule); + if (enableCustomTitlesModule){ + for (CustomTitle title : customTitles){ + logger.info(String.format("Custom Title ID #%d: %s / %s for skill ID #%d of type %s.", + title.getTitleId(), title.getMaleTitle(), title.getFemaleTitle(), title.getSkillId(), title.getType())); + } + for (int titleId : awardTitles.keySet()){ + logger.info(String.format("Awarding Title ID #%d to players: %s", + titleId, awardTitles.get(titleId).toString())); + } + } + + logger.info("Anti-Cheat Module: "+enableAntiCheatModule); + if (enableAntiCheatModule){ + logger.info("Spoof Hidden Ore: "+enableSpoofHiddenOre); + if (enableSpoofHiddenOre){ + logger.info("Prospecting Vision: "+prospectingVision); + } + logger.info("Map Steam IDs: "+mapSteamIds); + } + + logger.info("Quality Of Life Module: "+enableQualityOfLifeModule); + if (enableQualityOfLifeModule){ + logger.info("Mine Cave To Vehicle: "+mineCaveToVehicle); + logger.info("Mine Surface To Vehicle: "+mineSurfaceToVehicle); + logger.info("Chop Logs To Vehicle: "+chopLogsToVehicle); + logger.info("Statuette Any Material: "+statuetteAnyMaterial); + logger.info("Mine Gems To Vehicle: "+mineGemsToVehicle); + logger.info("Regenerate Stamina On Vehicle Any Slope: "+regenerateStaminaOnVehicleAnySlope); + } + + logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); + + //this.logger.log(Level.INFO, "Property: " + this.somevalue); } public static void handleExamine(Creature performer, Item target) { @@ -122,29 +570,54 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public void preInit() { logger.info("Pre-Initializing."); try { - ModActions.init(); - //Bounty.preInit(this); - TreasureChests.preInit(); - MiscChanges.preInit(); - Arena.preInit(); + ModActions.init(); // Initialize ModActions from Modloader + + // Misc Changes Module Pre-Init + if (enableMiscChangesModule) { + MiscChanges.preInit(); + } + + // Arena Module Pre-Init + if (enableArenaModule) { + Arena.preInit(); + } + + // Custom Titles Module Pre-Init + if (enableCustomTitlesModule) { + PlayerTitles.preInit(); + } + + // Anti-Cheat Module Pre-Init + if (enableAntiCheatModule) { + AntiCheat.preInit(); + } + + // Quality Of Life Module Pre-Init + if (enableQualityOfLifeModule) { + QualityOfLife.preInit(); + } + + // Treasure Chest Loot Module Pre-Init + if (enableTreasureChestLootModule) { + TreasureChests.preInit(); + } + Titans.preInit(); RareSpawns.preInit(); - PlayerTitles.preInit(); TeleportHandler.preInit(); MethodsBestiary.preInit(); MissionCreator.preInit(); - CombatChanges.preInit(); SkillChanges.preInit(); MeditationPerks.preInit(); MountedChanges.preInit(); EconomicChanges.preInit(); - QualityOfLife.preInit(); Bloodlust.preInit(); - AntiCheat.preInit(); Mastercraft.preInit(); - //Mastercraft.addNewTitles(); SupplyDepots.preInit(); KeyEvent.preInit(); + CombatChanges.preInit(); + + // Gem Augmentation is not complete. //GemAugmentation.preInit(); Class thisClass = WyvernMods.class; @@ -175,6 +648,9 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void init() { logger.info("Initializing."); + if (WyvernMods.enableCustomTitlesModule) { + PlayerTitles.init(); + } ModCreatures.init(); ModVehicleBehaviours.init(); @@ -247,7 +723,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea logger.info("Creating Cache items."); Caches.createItems(); logger.info("Initiating Title changes."); - PlayerTitles.onItemTemplatesCreated(); + //PlayerTitles.onItemTemplatesCreated(); try { logger.info("Editing existing item templates."); ItemMod.modifyItems(); diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java index 27cba1b..683cb25 100644 --- a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -10,6 +10,7 @@ import com.wurmonline.server.items.ItemFactory; import com.wurmonline.server.items.ItemTemplate; import com.wurmonline.server.items.NoSuchTemplateException; import com.wurmonline.server.players.Player; +import com.wurmonline.server.players.Titles; import mod.piddagoras.duskombat.DamageEngine; import mod.sin.armour.SpectralHide; import mod.sin.creatures.Reaper; @@ -106,7 +107,7 @@ public class PlayerBounty { fightStrength = "legendary"; } player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly."); - player.addTitle(PlayerTitles.getTitle(PlayerTitles.SPECTRAL)); + player.addTitle(Titles.Title.getTitle(PlayerTitles.SPECTRAL)); }catch (NoSuchTemplateException | FailedException e) { e.printStackTrace(); } @@ -145,7 +146,7 @@ public class PlayerBounty { player.getInventory().insertItem(riftCache, true); } if(Titans.isTitan(mob)){ - player.addTitle(PlayerTitles.getTitle(PlayerTitles.TITAN_SLAYER)); + player.addTitle(Titles.Title.getTitle(PlayerTitles.TITAN_SLAYER)); Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f, mob.getName()); player.getInventory().insertItem(affinityOrb, true); Item titanCache = ItemFactory.createItem(TitanCache.templateId, 99f, mob.getName()); From acf5d74a9c94faad53b0ab1a81578d84930b346d Mon Sep 17 00:00:00 2001 From: Sindusk Date: Mon, 6 May 2019 09:25:48 -0400 Subject: [PATCH 5/8] WyvernMods Configurable Phase 2 --- build.gradle | 2 +- mods/WyvernMods.properties | 248 +++++++++ .../java/mod/sin/wyvern/CombatChanges.java | 308 +++-------- src/main/java/mod/sin/wyvern/Mastercraft.java | 126 +++++ .../java/mod/sin/wyvern/MeditationPerks.java | 166 +++--- .../java/mod/sin/wyvern/PlayerTitles.java | 95 +--- .../java/mod/sin/wyvern/SkillChanges.java | 111 ++-- src/main/java/mod/sin/wyvern/WyvernMods.java | 287 +++++++++- .../sin/wyvern/mastercraft/BytecodeTools.java | 494 ------------------ .../wyvern/mastercraft/ExtendTitleEnum.java | 223 -------- .../sin/wyvern/mastercraft/Mastercraft.java | 203 ------- 11 files changed, 854 insertions(+), 1409 deletions(-) create mode 100644 src/main/java/mod/sin/wyvern/Mastercraft.java delete mode 100644 src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java delete mode 100644 src/main/java/mod/sin/wyvern/mastercraft/ExtendTitleEnum.java delete mode 100644 src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java diff --git a/build.gradle b/build.gradle index c5e79dc..5032b80 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ repositories { dependencies { compile 'org.gotti.wurmunlimited:server-modlauncher:0.43' - compile 'com.github.Sindusk:sindusklibrary:v2.2' + compile 'com.github.Sindusk:sindusklibrary:v2.3' compile 'com.github.bdew-wurm:bdew_server_mod_tools:v1.0.0' compile 'com.github.Sindusk:DiscordRelay:v1.2' compile 'com.github.Sindusk:DUSKombat:v1.0' diff --git a/mods/WyvernMods.properties b/mods/WyvernMods.properties index 5aa6675..b5cea90 100644 --- a/mods/WyvernMods.properties +++ b/mods/WyvernMods.properties @@ -515,6 +515,254 @@ regenerateStaminaOnVehicleAnySlope=true ## >> END QUALITY OF LIFE MODULE << ## +## >> COMBAT MODULE << ## +## The Combat Module offers options that affect the combat aspects of the game. +## This isn't restricted to simply the actual combat itself. It also includes some options to change combat-oriented spells and other mechanics. +enableCombatModule=true + +# > COMBAT RATING ADJUSTMENTS < # +# Combat Rating Adjustments involve some tweaks to how combat rating is calculated. +# There are two components: additive and multiplicative combat rating adjustments. +# Additive modifiers are always applied first. This creates a "base" combat rating that is then modified. +# Multiplicative modifiers apply after all additive combat rating adjustments, including vanilla ones. +enableCombatRatingAdjustments=true +#royalExecutionerBonus: Additive - Adds +2 CR against PvE targets while holding Royal Executioner kingdom title. +# The vanilla royal executioner bonus only applies to PvP combat. This option is meant to give it a PvE bonus as well. +royalExecutionerBonus=true +#TODO: Make this option a value instead and allow configuration of how much CR to grant. +#petSoulDepthScaling: Multiplicative - Scales the CR of pets with the Soul Depth of the owner/dominator. +# Applies a multiplier of Soul Depth * 0.02 to the pet's CR. This grants 40% CR at 20 Soul Depth and 200% CR at 100 Soul Depth. +# At 50 Soul Depth this modifier equates to 100%, resulting in no change to the pet's CR. +petSoulDepthScaling=true +#TODO: Make this option a value instead and allow configuration of the CR multiplier per soul depth. +#vehicleCombatRatingPenalty: Multiplicative - Reduces the CR of players on a vehicle by 25%. +# There is no significant offensive penalty for being the commander of a vehicle while in combat. +# This option is meant to encourage players to avoid fighting while on a vehicle. +vehicleCombatRatingPenalty=true +#TODO: Make this option a value instead and allow configuration of the CR multiplier while on a vehicle. +# > END COMBAT RATING ADJUSTMENTS < # + +#fixMagranonDamageStacking: In vanilla combat, Magranon/warrior damage bonus (+15% damage from deity) does not stack correctly. +# This applies only in aggressive stance, where the aggressive fighting skill calculations will adjust if the player has warrior bonus. +# When this occurs, it results in a loss of damage from the bonus, making the warrior passive effectively ~10-12% instead of the full 15%. +# This option adjusts the fight skill calculations and forces it to accurately apply the 15% damage bonus regardless of other factors. +fixMagranonDamageStacking=true +#adjustCombatRatingSpellPower: Adjusts the combat rating bonus from Truehit and Excel to 50% of their vanilla values. +adjustCombatRatingSpellPower=true +#TODO: Make this option a multiplier instead of a boolean. +#disableLegendaryRegeneration: Disables the natural healing/regeneration of legendary creatures (uniques). +disableLegendaryRegeneration=true +#useStaticLegendaryRegeneration: Applies a static healing over time to legendary creatures (uniques). +# This option is meant to be used in conjunction with the previous one to make legendaries able to be taken slowly. +# Instead of requiring their defeat in 10 minutes (where they would outheal their attackers), it now regenerates at a set rate. +# This allows players to take their time with uniques and use strategy, so long as the damage inflicted outpaces the natural static regeneration. +# The regeneration is set to 75 health per second (~0.1% maximim health per second). Requires ~874 seconds (14.5 minutes) to heal a full health bar. +useStaticLegendaryRegeneration=true +#TODO: Allow configuration of health regeneration per second. + +## >> END COMBAT MODULE << ## + +## >> MASTERCRAFT MODULE << ## +## The Mastercraft Module is a new series of systems designed to encourage players to explore end-game crafting further. +## Vanilla settings generally don't encourage players to skill past 90 or improve items past 90. +## The goals of this system, and the settings involved here, are to encourage players to strive for perfection instead of settling at "good enough." +enableMastercraftModule=true + +# > DIFFICULTY ADJUSTMENTS < # +# Difficulty Adjustments modify the difficulty when a skill check occurs based on the factors set here. +# This affects almost all systems in the game, from combat to improvement to creation chance to spell power. +# These configurations are aimed at increasing the ways a player can improve their results for any given action. +# By putting time and effort into one's craft, they can more easily improve items to higher levels or be more successful in their activities. +enableDifficultyAdjustments=true +#affinityDifficultyBonus: Reduces the difficulty of actions by 1 per affinity in the skill. +affinityDifficultyBonus=true +#TODO: Make this configuration able to be set to any amount of difficulty reduction. +#legendDifficultyBonus: Grants a reduction to difficulty for all skill over 99. +# Begins at 99.00 skill with no difficulty change, then maxes out at 100.00 skill granting -2 difficulty. +legendDifficultyBonus=true +#masterDifficultyBonus: Grants a reduction to difficulty for all skill over 90. +# Begins at 90.00 skill with no difficulty change, then maxes out at 100.00 skill granting -2 difficulty. +masterDifficultyBonus=true +#TODO: Make the skill scaling a multi-configuration where multiple thresholds can be set for a variety of scaling difficulty changes. +#itemRarityDifficultyBonus: Reduces the difficulty of an action depending on the rarity of the tool being used. +# Normal: No bonus, Rare: -1 difficulty, Supreme: -2 difficulty, Fantastic: -3 difficulty +itemRarityDifficultyBonus=true +#legendItemDifficultyBonus: Reduces the difficulty of an action for all quality over 99 of the tool being used. +# Begins at 99.00 QL with no difficulty change, then maxes out at 100.00 QL granting -1 difficulty. +legendItemDifficultyBonus=true +#masterItemDifficultyBonus: Reduces the difficulty of an action for all quality over 90 of the tool being used. +# Begins at 90.00 QL with no difficulty change, then maxes out at 100.00 QL granting -1 difficulty. +masterItemDifficultyBonus=true +#TODO: Allow further customization of the configurations for difficulty adjustments regarding items. + +# > END DIFFICULTY ADJUSTMENTS < # + +#empoweredChannelers: Empowers players with up to double the power on their casts based on their channeling skill and affinities. +# This grants +2 power to casts per affinity in channeling. +# Furthermore, it also rolls 4 times up to the value of their channeling skill. It then takes the lowest value and adds it to their cast power. +# !!! Be warned that enabling this option will allow players to perform natural casts of enchants up to roughly 200 power !!! +empoweredChannelers=true +#TODO: Expand on this option and enable more configuration of how the enchant power addition is calculated. +#channelSkillFavorReduction: Reduces the favor costs of spells based on channeling skill. +# Reduces favor cost by 2% per channeling affinity. +# Reduces favor cost by 10% per skill over 99. No bonus at 99.00, scaling to 10% at 100.00 channeling. +# Reduces favor cost by 1% per skill over 90. No bonus at 90.00, scaling to 10% at 100.00 channeling. +channelSkillFavorReduction=true +#TODO: Split up the favor cost reductions, then expand into a multi-configuration style to allow further customization. +#TODO: Also, the code that executes these configurations is old and should be updated with new priest rework code to make it cleaner. + +## >> END MASTERCRAFT MODULE << ## + +## >> SKILL MODULE << ## +## The Skill Module allows control over the components of skills, including skill gain adjustments. +enableSkillModule=true + +# > HYBRID SKILL GAIN < # +# Hybrid Skill Gain is the system which combines the vanilla Wurm Unlimited skill gain system with the classic Wurm Online model. +# In Wurm Unlimited, players gain skill for any successful action whether the result is 0.1 or 100. The skill tick size is the same every action. +# In Wurm Online, players gain skill for any successful action within the range 0 - 40. The skill tick size is based on the duration of the action. +# This new hybrid system makes it so players gain skill for any action, including mild failures (about -20), up to 100. +# However, the system also rewards more skill gain for actions with results closer to zero (if configured that way). +# This was done in order to discourage the "spam creation" skilling method. It is still effective, but improvement is now competitive. +# Visual graph that represents what this skill gain system looks like: https://i.imgur.com/9ykw5dJ.png +# Here is the formula which handles the multiplier for the new skill gain: +# valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate)); +# If you can't read/don't understand that, don't worry! Not many people can! However, if you can read or understand the function, +# you should be able to plug in a formula into Google Sheets, Wolfram Alpha, or Excel and create your own graph where you +# can adjust the following options and give the proper result that you're looking for. +# The default values listed here result in the visual graph represented above. +enableHybridSkillGain=true +#hybridNegativeDecayRate: [Limit: > 0] How fast the function decays past zero going negative. +# Higher values will cause the "midpoint" to move in a positive direction. It will also increase the sharpness of decline after the midpoint. +# Lower values will cause the "midpoint" to move in a negative direction. It will also decrease the sharpness of the decline after the midpoint, resulting a smoother curve. +hybridNegativeDecayRate=5 +#hybridPositiveDecayRate: [Limit: > 0] How quickly the function will decay past zero going positive. +# Higher values will result in a sharper curve to the 1.0 multiplier in values greater than zero. +# Lower values will result in a less sharp curve towards the 1.0 multiplier in values greater than zero. +hybridPositiveDecayRate=3 +#hybridValueAtZero: [Limit: > 0, must be greater than hybridValueAtOneHundred] What the multiplier should be be when an action results in zero. +hybridValueAtZero=3.74 +#hybridValueAtOneHundred: [Limit: > 0, must be less than hybridValueAtZero] What the multiplier should be when an action results in one hundred. +hybridValueAtOneHundred=0.9 + +# > END HYBRID SKILL GAIN < # + +#skillName-#: Changes the name of a skill. Format: skillName-#:skill,newName +# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg +# newName = The new name for the skill. Should be allowed to have spaces and other characters, but needs additional testing. +# - Case will carry to the in-game display, so keep that in mind. Making the new name fully lower case might make it look out of place among other skills. +# Set name of Preaching to Gem Augmentation +skillName-1:Preaching,Gem augmentation +# Set name of Stealing to Soulstealing +skillName-2:Stealing,Soulstealing + +#skillDifficulty-#: Changes the internal difficulty of a skill. Format: skillDifficulty-#:skill,difficulty +# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg +# difficulty = The new difficulty to set for the skill. Most skills default to 4000. This difficulty will affect the skill gain for that skill. +# - In the example of a 4000 difficulty skill: 2000 would double skill gain. 8000 would halve skill gain. 6000 would make it 1.5x slower. +# - For a full list of difficulty for each skill... I don't have one. Nevermind. +# Set mining to 3000 difficulty. Default is 8000. Makes it 2.66x higher skill gain. +skillDifficulty-1:Mining,3000 +# Set lockpicking to 700 difficulty. Default is 2000. Makes it 2.85x higher skill gain. +skillDifficulty-2:Lock Picking,700 +# Set meditating difficulty to 300. Default is 2000. Makes it 6.66x higher skill gain. Meditating is evil just like the increase. +skillDifficulty-3:Meditating,300 + +#skillTickTime-#: Changes the tick timer for skill gain on a skill. Format: skillTickTime-#:skill,tickTime +# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg +# tickTime = The interval (in milliseconds) before players can gain a skill tick for a skill. +# - Example: Lock picking has a default of 600000, or 600 seconds, for it's tick time. +# - This prevents players from being able to gain another skill tick of Lock picking until 600 seconds have passed (10 minutes). +# Set tick time of stealing to zero to remove the 10 minute interval. This is useful for Soulstealing. +skillTickTime-1:Stealing,0 +# Set tick time of meditating to 3600 seconds (1 hour). +skillTickTime-2:Meditating,3600000 + +#changePreachingLocation: Changes the dependencies of Preaching so that it moves under Masonry. +# Recommended to set to false. Option is here temporarily until further work can be done to customize dependencies. +changePreachingLocation=true +#TODO: Add multiple configuration settings to change the dependencies of skills and remove this hold-over option. + +## >> END SKILL MODULE << ## + +## >> MEDITATION MODULE << ## +## The Meditation Module enables adjustments to the meditation system of Wurm. +## It includes additions that make meditation perks more reasonable at lower levels and scale better as it increases. +enableMeditationModule=true + +#simplifyMeditationTerrain: Simplifies the terrain where players can meditate for a question. +# Instead of having to find specific tiles, any tile of the proper type will grant a question: +# - Insanity: Any cave tile +# - Love: Any grass, bush, or tree +# - Hate: Any mycelium, mycelium bush, or infected tree +# - Knowledge: Any sand +# - Power: Any rock or cliff tile (above ground). +simplifyMeditationTerrain=true +#removeInsanitySotG: Removes the Shield of the Gone bonus from Insanity. The buff will still show, but the effect will be gone. +removeInsanitySotG=true +#removeHateWarBonus: Removes the active effect to deal increased damage in combat from Path of Hate. Does not remove the structure damage version. +removeHateWarBonus=true +#insanitySpeedBonus: Adds new effect to Path of Insanity which grants 2% increased action speed per level starting at 7. +# At Insanity level 13, this bonus equates to 12% increased action speed. Does not affect weapon swing speed. +insanitySpeedBonus=true +#TODO: Allow configuration of the speed bonus and level it starts at. +#hateMovementBonus: Adds a new effect to Path of Hate which grants 1% increased movement speed (walking only) per level starting at 3. +# At Hate level 13, this bonus equates to 10% increased movement speed. Does not affect mounted or vehicle movement speed. +hateMovementBonus=true +#TODO: Allow configuration of the movement bonus and level it starts at. +#scalingPowerStaminaBonus: Scales the Path of Power stamina bonus from 30 at level 11 to start at 7 and increase with each level. +# Grants 5 bonus stamina at level 7, and adds 5 additional stamina per level afterwards. +# At Power level 13, this bonus equates to 30 additional Body Stamina. +scalingPowerStaminaBonus=true +#TODO: Allow configuration of the stamina bonus and level it starts at. +#scalingKnowledgeSkillGain: Scales the Path of Knowledge skill gain bonus from 25% at level 11 to start at 7 and increase with each level. +# Grants 5% increased skill gain at level 7, and adds 5% additional skill gain per level afterwards. +# At Knowledge level 13, this bonus grants 30% increased skill gain. +scalingKnowledgeSkillGain=true +#TODO: Allow configuration of the skill gain bonus and level it starts at. +#removeMeditationTickTimer: Removes the vanilla meditation tick timer which is not attached to the skill. +# This tick timer is coded differently from the skill system. It has to be removed like this in order to make the skill system version work. +# Enabling this option will allow you to configure the meditation tick timer using the Skills module. +# Without this enabled, this will override any settings from the Skills module and prevent skill gain unless the meditation system allows it. +removeMeditationTickTimer=true +#newMeditationBuffs: This option is meant to adjust the buff icons for meditation to coincide with all the options above. +# It's recommended to only allow this if all (or at least most) of the options above are enabled. +# Otherwise it probably wont display buffs correctly for some paths. +newMeditationBuffs=true +#TODO: Recode this to make it adjust properly to the configurations set throughout the rest of the module. + +# > MEDITATION ABILITY COOLDOWNS < # +# Meditation Ability Cooldowns allow you to set all of the cooldowns for meditation abilities. +# All cooldowns are set using milliseconds. A setting of 1000 means 1 second in this configuration. +enableMeditationAbilityCooldowns=true +#loveRefreshCooldown: Cooldown for Path of Love's Refresh ability. (Default: 64800000 [18 hours]) +loveRefreshCooldown=28800000 +#loveEnchantNatureCooldown: Cooldown for Path of Love's Enchant Nature ability. (Default: 64800000 [18 hours]) +loveEnchantNatureCooldown=28800000 +#loveLoveEffectCooldown: Cooldown for Path of Love's Love Effect ability. (Default: 64800000 [18 hours]) +loveLoveEffectCooldown=14400000 +#hateWarDamageCooldown: Cooldown for Path of Hate's War Damage ability. (Default: 64800000 [18 hours]) +hateWarDamageCooldown=21600000 +#hateStructureDamageCooldown: Cooldown for Path of Hate's Structure Damage ability. (Default: 64800000 [18 hours]) +hateStructureDamageCooldown=14400000 +#hateFearCooldown: Cooldown for Path of Hate's Fear ability. (Default: 64800000 [18 hours]) +hateFearCooldown=21600000 +#powerElementalImmunityCooldown: Cooldown of Path of Power's Elemental Immunity ability. (Default: 64800000 [18 hours]) +powerElementalImmunityCooldown=21600000 +#powerEruptFreezeCooldown: Cooldown of Path of Power's Erupt/Freeze abilities. (Default: 64800000 [18 hours]) +powerEruptFreezeCooldown=28800000 +#powerIgnoreTrapsCooldown: Cooldown of Path of Power's Ignore Traps ability. (Default: 64800000 [18 hours]) +powerIgnoreTrapsCooldown=14400000 +#knowledgeInfoCreatureCooldown: Cooldown of Path of Knowledge's Get Info (Creature) ability. (Default: 64800000 [18 hours]) +knowledgeInfoCreatureCooldown=14400000 +#knowledgeInfoTileCooldown: Cooldown of Path of Knowledge's Get Info (Tile) ability. (Default: 64800000 [18 hours]) +knowledgeInfoTileCooldown=14400000 +#TODO: Add the rest of the meditation abilites as configurable options. + +# > END MEDITATION ABILITY COOLDOWNS < # + +## >> END MEDITATION MODULE << ## + ## >> TREASURE CHEST LOOT MODULE << ## ## The Treasure Chest Loot Module affects the vanilla treasure chests. ## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them. diff --git a/src/main/java/mod/sin/wyvern/CombatChanges.java b/src/main/java/mod/sin/wyvern/CombatChanges.java index ad2478b..39a6ab2 100644 --- a/src/main/java/mod/sin/wyvern/CombatChanges.java +++ b/src/main/java/mod/sin/wyvern/CombatChanges.java @@ -24,23 +24,12 @@ import java.util.logging.Logger; public class CombatChanges { public static Logger logger = Logger.getLogger(CombatChanges.class.getName()); - // Added to CombatHandled - public static int getWeaponType(Item weapon){ - if(weapon.enchantment == Enchants.ACID_DAM){ - return Wound.TYPE_ACID; - }else if(weapon.enchantment == Enchants.FROST_DAM){ - return Wound.TYPE_COLD; - }else if(weapon.enchantment == Enchants.FIRE_DAM){ - return Wound.TYPE_BURN; - } - return -1; - } - public static float combatRatingAdditive(float combatRating, Creature cret, Creature opponent){ //logger.info("Checking additive ("+cret.getName()+" vs "+opponent.getName()+"), combatRating = "+combatRating); float add = 0.0f; if(cret != null && cret.isPlayer() && (opponent != null && !opponent.isPlayer())){ - if(cret.isRoyalExecutioner()){ + // 2 CR against non-players for Royal Executioner kingdom title. + if(WyvernMods.royalExecutionerBonus && cret.isRoyalExecutioner()){ add += 2.0f; } } @@ -51,7 +40,7 @@ public class CombatChanges { float mult = 1.0f; if(cret != null){ //logger.info("Cret is a pet."); - if(cret.isDominated() && cret.getDominator() != null) { + if(WyvernMods.petSoulDepthScaling && cret.isDominated() && cret.getDominator() != null) { if (cret.getDominator() instanceof Player) { Player owner = (Player) cret.getDominator(); double depth = owner.getSoulDepth().getKnowledge(); @@ -61,7 +50,7 @@ public class CombatChanges { logger.info("Somehow a pet is dominated by a non-player? (" + cret.getDominator().getName() + ")"); } } - if(QualityOfLife.getVehicleSafe(cret) != null){ + if(WyvernMods.vehicleCombatRatingPenalty && QualityOfLife.getVehicleSafe(cret) != null){ mult *= 0.75f; } } @@ -98,17 +87,6 @@ public class CombatChanges { } } - // Added (kind of) to CombatHandled - public static float getAdjustedOakshell(Creature defender, Item armour, float armourMod){ - if(defender != null && armour == null){ - float oakshellPower = defender.getBonusForSpellEffect(Enchants.CRET_OAKSHELL); - if(oakshellPower > 0f){ - return (float) (1-(0.8f*Math.pow((oakshellPower/(oakshellPower+80)), 0.5d))); - } - } - return armourMod; // Returns previous armourMod if the target has armour. - } - protected static ArrayList uniques = new ArrayList<>(); public static void pollUniqueCollection(){ for(Creature cret : Creatures.getInstance().getCreatures()){ @@ -151,114 +129,6 @@ public class CombatChanges { return damage > 1D; } - /* Disabled as of WU 1.9 - No longer necessary and no longer functions. - - 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(); - CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); - ConstPool constPool = codeAttribute.getConstPool(); - CodeIterator codeIterator = codeAttribute.iterator(); - - // Scan through all the bytecode - look for a multiplication followed by comparing - while (codeIterator.hasNext()) { - int pos = codeIterator.next(); - int op = codeIterator.byteAt(pos); - if (op != CodeIterator.DMUL) continue; // not multiplication - continue - op = codeIterator.byteAt(++pos); - if (op == CodeIterator.LDC2_W && codeIterator.byteAt(pos + 3) == CodeIterator.DCMPL) { - // found the pattern, check the value it's comparing to - int ref = codeIterator.u16bitAt(pos + 1); - double val = constPool.getDoubleInfo(ref); - if (val == 500.0) { - // here it is, generate new code to insert - // We'll be calling canDoDamage, the first parameter (damage) is already on the stack, prepare the rest - Bytecode newCode = new Bytecode(constPool); - newCode.add(Bytecode.ALOAD_0); // this - newCode.addGetfield(cls, "creature", "Lcom/wurmonline/server/creatures/Creature;"); // this.creature - newCode.add(Bytecode.ALOAD_1); // defender - first parameter of setDamage - - // 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); - } - } - } - }*/ - // Added to CombatHandled public static void pollCreatureActionStacks(){ for(Creature c : Creatures.getInstance().getCreatures()){ @@ -278,119 +148,73 @@ public class CombatChanges { final Class thisClass = CombatChanges.class; String replace; - Util.setReason("Make custom combat rating changes."); CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); - replace = "combatRating += "+CombatChanges.class.getName()+".combatRatingAdditive(combatRating, this.creature, $1);" + - "crmod *= "+CombatChanges.class.getName()+".combatRatingMultiplicative(combatRating, this.creature, $1);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getFlankingModifier", replace); - CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - - /* Disabled in Wurm Unlimited 1.9 - No longer necessary while using DUSKombat. - - Util.setReason("Increase unique damage to pets."); - 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); - replace = "if($2.isDominated() && $1 != null && $1.isUnique()){" + - //" logger.info(\"Detected unique hit on a pet. Adding damage.\");" + - " $5 = $5 * 2d;" + - "}" + - "if($2.isUnique() && $1 != null && $1.isDominated()){" + - " logger.info(\"Detected pet hit on a unique. Reducing damage.\");" + - " $5 = $5 * 0.5d;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ - - Util.setReason("Adjust weapon damage type based on the potion/salve applied."); - replace = "int wt = "+CombatChanges.class.getName()+".getWeaponType($1);" - + "if(wt != -1){" - + " type = wt;" - + " return wt;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace); - CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); - CtClass[] params2 = { - ctCreature, - ctItem, - ctCreature - }; - String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2); - - /* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way. - - Util.setReason("Adjust bloodthirst to epic settings."); - replace = "$_ = true;"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace);*/ - - Util.setReason("Fix magranon damage bonus stacking."); - replace = "if(mildStack){" + - " $_ = $proceed($$) * 8 / 5;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace); - CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction"); - CtClass[] params3 = { - ctCreature, - ctAttackAction, - ctCreature - }; - String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3); - /* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way. + if (WyvernMods.enableCombatRatingAdjustments) { + Util.setReason("Make custom combat rating changes."); + replace = "combatRating += " + CombatChanges.class.getName() + ".combatRatingAdditive(combatRating, this.creature, $1);" + + "crmod *= " + CombatChanges.class.getName() + ".combatRatingMultiplicative(combatRating, this.creature, $1);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getFlankingModifier", replace); + } - Util.setReason("Adjust bloodthirst to epic settings."); - replace = "$_ = true;"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace);*/ + if (WyvernMods.fixMagranonDamageStacking) { + // Normal combat version + CtClass[] params2 = { + ctCreature, + ctItem, + ctCreature + }; + String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2); - Util.setReason("Fix magranon damage bonus stacking."); - replace = "if(mildStack){" + - " $_ = $proceed($$) * 8 / 5;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace); + Util.setReason("Fix magranon damage bonus stacking."); + replace = "if(mildStack){" + + " $_ = $proceed($$) * 8 / 5;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace); - Util.setReason("Nerf truehit/excel."); - replace = "$_ = $proceed($$) * 0.5f;"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace); + // AttackAction version + CtClass[] params3 = { + ctCreature, + ctAttackAction, + ctCreature + }; + String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3); - Util.setReason("Nerf oakshell."); - replace = "if(defender.isPlayer() && defender.getBonusForSpellEffect((byte)22) > 0f){" + - " armourMod = "+CombatChanges.class.getName()+".getAdjustedOakshell(defender, armour, armourMod);" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getDamReductionBonusFor", replace); + Util.setReason("Fix magranon damage bonus stacking."); + replace = "if(mildStack){" + + " $_ = $proceed($$) * 8 / 5;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace); + } - Util.setReason("Disable natural regeneration on uniques."); - CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound"); - replace = "if(!this.creature.isUnique()){" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace); - Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace); - Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace); + if (WyvernMods.adjustCombatRatingSpellPower) { + Util.setReason("Nerf truehit/excel."); + replace = "$_ = $proceed($$) * 0.5f;"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace); + } + + if (WyvernMods.disableLegendaryRegeneration) { + Util.setReason("Disable natural regeneration on legendary creatures."); + CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound"); + replace = "if(!this.creature.isUnique()){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace); + Util.setReason("Disable natural regeneration on legendary creatures."); + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace); + Util.setReason("Disable natural regeneration on legendary creatures."); + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace); + } + + /* Disabled for now until it can be fixed for new Priest Update adjustments. Util.setReason("Allow Life Transfer to stack with Rotting Touch (Mechanics-Wise)."); replace = CombatChanges.class.getName()+".doLifeTransfer(this.creature, defender, attWeapon, defdamage, armourMod);" @@ -403,15 +227,7 @@ public class CombatChanges { 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); + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "modifySeverity", replace);*/ /*Util.setReason("Debug attack method"); CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); diff --git a/src/main/java/mod/sin/wyvern/Mastercraft.java b/src/main/java/mod/sin/wyvern/Mastercraft.java new file mode 100644 index 0000000..77b2486 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/Mastercraft.java @@ -0,0 +1,126 @@ +package mod.sin.wyvern; + +import com.wurmonline.server.Server; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Titles; +import com.wurmonline.server.skills.Skill; +import javassist.*; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; +import mod.sin.lib.Util; +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import java.util.Objects; +import java.util.logging.Logger; + +public class Mastercraft { + private static Logger logger = Logger.getLogger(Mastercraft.class.getName()); + public static double getNewDifficulty(Skill skill, double diff, Item item){ + if(WyvernMods.affinityDifficultyBonus && skill.affinity > 0){ + diff -= skill.affinity; + } + if(WyvernMods.legendDifficultyBonus && skill.getKnowledge() > 99.0d){ + diff -= 2d-((100d-skill.getKnowledge())*2d); + } + if(WyvernMods.masterDifficultyBonus && skill.getKnowledge() > 90.0d){ + diff -= 2d-((100d-skill.getKnowledge())*0.2d); + } + if(item != null){ + if(WyvernMods.itemRarityDifficultyBonus && item.getRarity() > 0){ + diff -= item.getRarity(); + } + if(WyvernMods.legendItemDifficultyBonus && item.getCurrentQualityLevel() > 99.0f){ + diff -= 1d-((100d-item.getCurrentQualityLevel())*1d); + } + if(WyvernMods.masterItemDifficultyBonus && item.getCurrentQualityLevel() > 90.0f){ + diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d); + } + } + return diff; + } + public static float getCastPowerIncrease(Skill skill){ + double addedPower = 0; + if(skill.affinity > 0){ + addedPower += 2*skill.affinity; + } + if(skill.getKnowledge() > 0){ + float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); + float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); + addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2); + }else{ + logger.warning("Error: Some player just tried casting with no channeling skill!"); + } + return (float) addedPower; + } + public static float getFavorCostMultiplier(Skill skill){ + float mult = 1f; + if(skill.affinity > 0){ + mult -= skill.affinity*0.02f; //2% reduction per affinity + } + if(skill.getKnowledge() > 90d){ + mult -= 0.1d-((100d-skill.getKnowledge())*0.01d); + } + if(skill.getKnowledge() > 99d){ + mult -= 0.1d-((100-skill.getKnowledge())*0.1d); + } + return mult; + } + + public static void changeExistingTitles(){ + for (Titles.Title title : Titles.Title.values()) { + if (Objects.equals("Pumpkin King", title.getFemaleName())){ + try { + ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen"); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + } + } + public static void preInit(){ + try { + ClassPool classPool = HookManager.getInstance().getClassPool(); + Class thisClass = Mastercraft.class; + + // - Reduce skill check difficulty with high skills or tools - // + CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + + if (WyvernMods.enableDifficultyAdjustments) { + Util.setReason("Modify difficulty for skill checks in MasterCraft."); + String replace = "$1 = " + Mastercraft.class.getName() + ".getNewDifficulty(this, $1, $2);"; + Util.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", replace); + } + + // - Increase spellcasting power for skilled channelers - // + CtClass ctSpell = classPool.get("com.wurmonline.server.spells.Spell"); + CtMethod[] ctRuns = ctSpell.getDeclaredMethods("run"); + for(CtMethod method : ctRuns){ + if (WyvernMods.empoweredChannelers) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("doEffect")) { + m.replace("$2 += " + Mastercraft.class.getName() + ".getCastPowerIncrease(castSkill);" + + "$_ = $proceed($$);"); + logger.info("Instrumented doEffect in run()"); + } + } + }); + } + if (WyvernMods.channelSkillFavorReduction) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("depleteFavor")) { + m.replace("$1 *= " + Mastercraft.class.getName() + ".getFavorCostMultiplier(castSkill);" + + "$_ = $proceed($$);"); + logger.info("Instrumented depleteFavor in run()"); + } + } + }); + } + } + } catch (CannotCompileException | NotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/MeditationPerks.java b/src/main/java/mod/sin/wyvern/MeditationPerks.java index 9c3c3f8..b12d8ca 100644 --- a/src/main/java/mod/sin/wyvern/MeditationPerks.java +++ b/src/main/java/mod/sin/wyvern/MeditationPerks.java @@ -60,7 +60,7 @@ public class MeditationPerks { if(path.getPath() == Cults.PATH_HATE){ byte level = path.getLevel(); if(level >= 3){ - float levelDiff = level-3f; + float levelDiff = level-2f; return 1.0f+(levelDiff*0.01f); } } @@ -156,36 +156,54 @@ public class MeditationPerks { final Class thisClass = MeditationPerks.class; String replace; - Util.setReason("Enable buff icons for meditation."); CtClass ctCultist = classPool.get("com.wurmonline.server.players.Cultist"); - replace = MeditationPerks.class.getName()+".sendPassiveBuffs($0);"; - Util.insertBeforeDeclared(thisClass, ctCultist, "sendPassiveBuffs", replace); - - Util.setReason("Make meditating paths more straightforward."); CtClass ctCults = classPool.get("com.wurmonline.server.players.Cults"); - replace = "{ return "+MeditationPerks.class.getName()+".getNewPathFor($1, $2, $3); }"; - Util.setBodyDeclared(thisClass, ctCults, "getPathFor", replace); - - Util.setReason("Replace stamina modifier for new Insanity ability."); CtClass ctActions = classPool.get("com.wurmonline.server.behaviours.Actions"); - replace = "{ return "+MeditationPerks.class.getName()+".newStaminaModifierFor($1, $2); }"; - Util.setBodyDeclared(thisClass, ctActions, "getStaminaModiferFor", replace); - - Util.setReason("Increase movement speed for Path of Hate users."); CtClass ctMovementScheme = classPool.get("com.wurmonline.server.creatures.MovementScheme"); - replace = "if($_ > 0){" + - " $_ = $_ * "+MeditationPerks.class.getName()+".getCultistSpeedMultiplier(this);" + - "}"; - Util.insertAfterDeclared(thisClass, ctMovementScheme, "getSpeedModifier", replace); - - Util.setReason("Scale path of power stamina bonus from level 7 onwards."); CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); - replace = "staminaMod += "+MeditationPerks.class.getName()+".getPowerStaminaBonus(this.statusHolder);" + - "$_ = false;"; - Util.instrumentDeclared(thisClass, ctCreatureStatus, "modifyStamina", "usesNoStamina", replace); - - Util.setReason("Scale path of knowledge skill gain from level 7 onwards."); CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + + if (WyvernMods.simplifyMeditationTerrain) { + Util.setReason("Make meditating paths more straightforward."); + replace = "{ return " + MeditationPerks.class.getName() + ".getNewPathFor($1, $2, $3); }"; + Util.setBodyDeclared(thisClass, ctCults, "getPathFor", replace); + } + + if (WyvernMods.removeInsanitySotG) { + Util.setReason("Remove shield of the gone effect."); + replace = "{ return 0.0f; }"; + Util.setBodyDeclared(thisClass, ctCultist, "getHalfDamagePercentage", replace); + } + + if (WyvernMods.removeHateWarBonus) { + Util.setReason("Remove hate war damage effect."); + replace = "{ return false; }"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace); + Util.setReason("Remove hate war damage effect."); + Util.setBodyDeclared(thisClass, ctCultist, "doubleWarDamage", replace); + } + + if (WyvernMods.insanitySpeedBonus) { + Util.setReason("Replace stamina modifier for new Insanity ability."); + replace = "{ return " + MeditationPerks.class.getName() + ".newStaminaModifierFor($1, $2); }"; + Util.setBodyDeclared(thisClass, ctActions, "getStaminaModiferFor", replace); + } + + if (WyvernMods.hateMovementBonus) { + Util.setReason("Increase movement speed for Path of Hate users."); + replace = "if($_ > 0){" + + " $_ = $_ * " + MeditationPerks.class.getName() + ".getCultistSpeedMultiplier(this);" + + "}"; + Util.insertAfterDeclared(thisClass, ctMovementScheme, "getSpeedModifier", replace); + } + + if (WyvernMods.scalingPowerStaminaBonus) { + Util.setReason("Scale path of power stamina bonus from level 7 onwards."); + replace = "staminaMod += " + MeditationPerks.class.getName() + ".getPowerStaminaBonus(this.statusHolder);" + + "$_ = false;"; + Util.instrumentDeclared(thisClass, ctCreatureStatus, "modifyStamina", "usesNoStamina", replace); + } + CtClass[] params1 = { CtClass.doubleType, CtClass.booleanType, @@ -194,57 +212,61 @@ public class MeditationPerks { CtClass.doubleType }; String desc1 = Descriptor.ofMethod(CtClass.voidType, params1); - replace = "staminaMod *= "+MeditationPerks.class.getName()+".getKnowledgeSkillGain(player);" + - "$_ = false;"; - Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc1, "levelElevenSkillgain", replace); - Util.setReason("Remove shield of the gone effect."); - replace = "{ return 0.0f; }"; - Util.setBodyDeclared(thisClass, ctCultist, "getHalfDamagePercentage", replace); - Util.setReason("Remove hate war damage effect."); - replace = "{ return false; }"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace); - Util.setBodyDeclared(thisClass, ctCultist, "doubleWarDamage", replace); + if (WyvernMods.scalingKnowledgeSkillGain) { + Util.setReason("Scale path of knowledge skill gain from level 7 onwards."); + replace = "staminaMod *= " + MeditationPerks.class.getName() + ".getKnowledgeSkillGain(player);" + + "$_ = false;"; + Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc1, "levelElevenSkillgain", replace); + } - Util.setReason("Remove artifical tick timer for meditation."); - replace = "$_ = 0;"; - Util.instrumentDeclared(thisClass, ctCults, "meditate", "getLastMeditated", replace); + if (WyvernMods.removeMeditationTickTimer) { + Util.setReason("Remove artifical tick timer for meditation."); + replace = "$_ = 0;"; + Util.instrumentDeclared(thisClass, ctCults, "meditate", "getLastMeditated", replace); + } - // - Reduce meditation cooldowns - // - replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*8)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace); - //ctCultist.getDeclaredMethod("mayRefresh").setBody("return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 28800000;"); - replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace); - //ctCultist.getDeclaredMethod("mayEnchantNature").setBody("return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;"); - replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace); - //ctCultist.getDeclaredMethod("mayStartLoveEffect").setBody("return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 14400000;"); - replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace); - //ctCultist.getDeclaredMethod("mayStartDoubleWarDamage").setBody("return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > 21600000;"); - replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace); - //ctCultist.getDeclaredMethod("mayStartDoubleStructDamage").setBody("return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > 14400000;"); - replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*6)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace); - //ctCultist.getDeclaredMethod("mayStartFearEffect").setBody("return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 21600000;"); - replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace); - //ctCultist.getDeclaredMethod("mayStartNoElementalDamage").setBody("return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > 21600000;"); - replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace); - //ctCultist.getDeclaredMethod("maySpawnVolcano").setBody("return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;"); - replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace); - //ctCultist.getDeclaredMethod("mayStartIgnoreTraps").setBody("return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > 14400000;"); - replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*4)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace); - //ctCultist.getDeclaredMethod("mayCreatureInfo").setBody("return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 14400000;"); - replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";"; - Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace); - //ctCultist.getDeclaredMethod("mayInfoLocal").setBody("return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 14400000;"); + if (WyvernMods.newMeditationBuffs) { + Util.setReason("Enable buff icons for meditation."); + replace = MeditationPerks.class.getName() + ".sendPassiveBuffs($0);"; + Util.insertBeforeDeclared(thisClass, ctCultist, "sendPassiveBuffs", replace); + } + if (WyvernMods.enableMeditationAbilityCooldowns) { + // - Adjust meditation ability cooldowns - // + replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.loveRefreshCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace); + + replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.loveEnchantNatureCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace); + + replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.loveLoveEffectCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace); + + replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.hateWarDamageCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace); + + replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.hateStructureDamageCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace); + + replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.hateFearCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace); + + replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.powerElementalImmunityCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace); + + replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.powerEruptFreezeCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace); + + replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.powerIgnoreTrapsCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace); + + replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.knowledgeInfoCreatureCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace); + + replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.knowledgeInfoTileCooldown) + ";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); } diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index 7bff2bb..da7e742 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -23,23 +23,6 @@ public class PlayerTitles { // Event Title ID's public static int TITAN_SLAYER = 10000; public static int SPECTRAL = 10001; - //public static int PASTAMANCER = 10002; - - // Player Donation Title ID's - /*public static int PATRON = 19999; - public static int DONATOR = 20000; - public static int PAZZA_FAVORITE_GM = 20001; - public static int WARRIORGEN_THAT_GUY = 20002; - public static int ETERNALLOVE_WARRIORGENS_WIFE = 20003; - public static int BAMBAM_THORN_ONE = 20004; - public static int SVENJA_CARE_DEPENDANT = 20005; - public static int ALEXIA_THE_TREASURING = 20006; - public static int REEVI_SCIENCE_GUY = 20007; - public static int GENOCIDE_GRAND_DESIGNER = 20008; - public static int SELEAS_CRAZY_CAT_LORD = 20009; - public static int PIRATEMAX_SLAVE = 20010; - public static int ELTACOLAD_TRUE_TACO = 20011; - public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012;*/ public static void init(){ for (WyvernMods.CustomTitle title : WyvernMods.customTitles){ @@ -48,28 +31,8 @@ public class PlayerTitles { // Event Titles createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, "NORMAL"); createTitle(SPECTRAL, "Spectral", "Spectral", -1, "NORMAL"); - //PlayerTitles.createTitle(buster, "Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, Titles.TitleType.NORMAL); - //PlayerTitles.createTitle(buster, "Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, Titles.TitleType.NORMAL); - //createTitle(PASTAMANCER, "Pastamancer", "Pastamancer", -1, "NORMAL"); - // Donation Titles - /* Moved to configuration - createTitle(PATRON, "Patron", "Patron", -1, "NORMAL"); - createTitle(DONATOR, "Donator", "Donator", -1, "NORMAL"); - createTitle(PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, "NORMAL"); - createTitle(WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, "NORMAL"); - createTitle(ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, "NORMAL"); - createTitle(BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, "NORMAL"); - createTitle(SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, "NORMAL"); - createTitle(ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, "NORMAL"); - createTitle(REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, "NORMAL"); - createTitle(GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, "NORMAL"); - createTitle(SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL"); - createTitle(PIRATEMAX_SLAVE, "Slave", "Slave", -1, "NORMAL"); - createTitle(ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, "NORMAL"); - createTitle(ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, "NORMAL");*/ - - // Supporter titles + // Display all existing titles logger.info(Arrays.toString(Titles.Title.values())); } @@ -105,61 +68,5 @@ public class PlayerTitles { logger.warning("Failed to get title with ID "+titleId); } } - /*if(donatorTitles.contains(name)){ - Titles.Title donator = Titles.Title.getTitle(DONATOR); - p.addTitle(donator); - } - if(patronTitles.contains(name)){ - Titles.Title patron = Titles.Title.getTitle(PATRON); - p.addTitle(patron); - } - if(customTitles.containsKey(name)){ - Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name)); - p.addTitle(customTitle); - }*/ - } - public static void preInit(){ - // Donations - /*donatorTitles.add("Pazza"); - customTitles.put("Pazza", PAZZA_FAVORITE_GM); // Sindusks Favorite GM - - donatorTitles.add("Warriorgen"); - customTitles.put("Warriorgen", WARRIORGEN_THAT_GUY); // That Guy - - donatorTitles.add("Eternallove"); - customTitles.put("Eternallove", ETERNALLOVE_WARRIORGENS_WIFE); // Warriorgens Wife - - donatorTitles.add("Bambam"); - customTitles.put("Bambam", BAMBAM_THORN_ONE); // Thorn One - - donatorTitles.add("Svenja"); - customTitles.put("Svenja", SVENJA_CARE_DEPENDANT); // The care-dependent - playerTitles.put("Svenja", "Akuma"); - - donatorTitles.add("Alexiaselena"); - customTitles.put("Alexiaselena", ALEXIA_THE_TREASURING); // The Treasuring - playerTitles.put("Alexiaselena", "Kami"); - - donatorTitles.add("Reevi"); - customTitles.put("Reevi", REEVI_SCIENCE_GUY); // Science Guy - - customTitles.put("Genocide", GENOCIDE_GRAND_DESIGNER); // Grand Designer - - donatorTitles.add("Seleas"); - customTitles.put("Seleas", SELEAS_CRAZY_CAT_LORD); // The Crazy Cat Lord - playerTitles.put("Seleas", "No, Really"); - - donatorTitles.add("Piratemax"); - customTitles.put("Piratemax", PIRATEMAX_SLAVE); // Slave - playerTitles.put("Piratemax", "Boy Next Door"); - - donatorTitles.add("Eltacolad"); - customTitles.put("Eltacolad", ELTACOLAD_TRUE_TACO); // The One True Taco - - patronTitles.add("Atticus"); - customTitles.put("Atticus", ATTICUS_THE_GREAT_ILLUMINATY); // The Great Illuminaty - - // Other rewards - customTitles.put("Critias", PASTAMANCER);*/ } } diff --git a/src/main/java/mod/sin/wyvern/SkillChanges.java b/src/main/java/mod/sin/wyvern/SkillChanges.java index ea286b1..b2bd2f9 100644 --- a/src/main/java/mod/sin/wyvern/SkillChanges.java +++ b/src/main/java/mod/sin/wyvern/SkillChanges.java @@ -37,10 +37,10 @@ public class SkillChanges { try { Skills parent = ReflectionUtil.getPrivateField(skill, ReflectionUtil.getField(skill.getClass(), "parent")); double advanceMultiplicator = (100.0 - skill.getKnowledge()) / (skill.getDifficulty(parent.priest) * skill.getKnowledge() * skill.getKnowledge()) * learnMod * bonus; - double negativeDecayRate = 5; - double positiveDecayRate = 3; - double valueAtZero = 3.74d; - double valueAtOneHundred = 0.9d; + double negativeDecayRate = (double) WyvernMods.hybridNegativeDecayRate; + double positiveDecayRate = (double) WyvernMods.hybridPositiveDecayRate; + double valueAtZero = (double) WyvernMods.hybridValueAtZero; + double valueAtOneHundred = (double) WyvernMods.hybridValueAtOneHundred; //advanceMultiplicator *= Math.pow(2, ((2-Math.pow((100/(100+power)), p))*(100-power)/100)); //double mult = Math.pow(2, (2-Math.pow(100/(100+power), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate)); double mult = valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate)); @@ -65,65 +65,52 @@ public class SkillChanges { return 0; } - public static void onServerStarted(){ - /*SkillTemplate exorcism = SkillSystem.templates.get(SkillList.EXORCISM); - int[] deps = {SkillList.GROUP_ALCHEMY}; + public static void setSkillName(int id, String newName){ + SkillTemplate skillTemplate = SkillSystem.templates.get(id); try { - String newName = "Crystal handling"; - ReflectionUtil.setPrivateField(exorcism, ReflectionUtil.getField(exorcism.getClass(), "name"), newName); - SkillSystem.skillNames.put(exorcism.getNumber(), newName); - SkillSystem.namesToSkill.put(newName, exorcism.getNumber()); - ReflectionUtil.setPrivateField(exorcism, ReflectionUtil.getField(exorcism.getClass(), "dependencies"), deps); + ReflectionUtil.setPrivateField(skillTemplate, ReflectionUtil.getField(skillTemplate.getClass(), "name"), newName); + SkillSystem.skillNames.put(skillTemplate.getNumber(), newName); + SkillSystem.namesToSkill.put(newName, skillTemplate.getNumber()); } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to rename exorcism!"); + logger.info("Failed to rename skill with ID "+id+"!"); e.printStackTrace(); } - SkillTemplate ballistae = SkillSystem.templates.get(SkillList.BALLISTA); - int[] deps2 = {SkillList.GROUP_ALCHEMY}; + } + public static void setSkillDifficulty(int id, float difficulty){ + SkillTemplate skillTemplate = SkillSystem.templates.get(id); + skillTemplate.setDifficulty(difficulty); + } + public static void setSkillTickTime(int id, long tickTime){ + SkillTemplate skillTemplate = SkillSystem.templates.get(id); try { - String newName = "Mystic components"; - ReflectionUtil.setPrivateField(ballistae, ReflectionUtil.getField(ballistae.getClass(), "name"), newName); - SkillSystem.skillNames.put(ballistae.getNumber(), newName); - SkillSystem.namesToSkill.put(newName, ballistae.getNumber()); - ReflectionUtil.setPrivateField(ballistae, ReflectionUtil.getField(ballistae.getClass(), "dependencies"), deps2); + ReflectionUtil.setPrivateField(skillTemplate, ReflectionUtil.getField(skillTemplate.getClass(), "tickTime"), tickTime); } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to rename ballistae!"); - e.printStackTrace(); - }*/ - SkillTemplate preaching = SkillSystem.templates.get(SkillList.PREACHING); - int[] deps3 = {SkillList.MASONRY}; - try { - String newName = "Gem augmentation"; - ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "name"), newName); - SkillSystem.skillNames.put(preaching.getNumber(), newName); - SkillSystem.namesToSkill.put(newName, preaching.getNumber()); - ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "dependencies"), deps3); - } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to rename preaching!"); + logger.info("Failed to set tickTime for skill with ID "+id+"!"); e.printStackTrace(); } - SkillTemplate stealing = SkillSystem.templates.get(SkillList.STEALING); - try { - ReflectionUtil.setPrivateField(stealing, ReflectionUtil.getField(stealing.getClass(), "tickTime"), 0); - } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to set tickTime for stealing!"); - e.printStackTrace(); - } - SkillTemplate meditating = SkillSystem.templates.get(SkillList.MEDITATING); - try { - ReflectionUtil.setPrivateField(meditating, ReflectionUtil.getField(meditating.getClass(), "tickTime"), TimeConstants.HOUR_MILLIS); - } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to set tickTime for meditating!"); - e.printStackTrace(); - } - meditating.setDifficulty(300f); + } - // Set mining difficulty down to be equivalent to digging. - SkillTemplate mining = SkillSystem.templates.get(SkillList.MINING); - mining.setDifficulty(3000f); - // Triple lockpicking skill - SkillTemplate lockpicking = SkillSystem.templates.get(SkillList.LOCKPICKING); - lockpicking.setDifficulty(700f); + public static void onServerStarted(){ + for (int skillId : WyvernMods.skillName.keySet()){ + setSkillName(skillId, WyvernMods.skillName.get(skillId)); + } + for (int skillId : WyvernMods.skillDifficulty.keySet()){ + setSkillDifficulty(skillId, WyvernMods.skillDifficulty.get(skillId)); + } + for (int skillId : WyvernMods.skillTickTime.keySet()){ + setSkillTickTime(skillId, WyvernMods.skillTickTime.get(skillId)); + } + + if (WyvernMods.changePreachingLocation) { + SkillTemplate preaching = SkillSystem.templates.get(SkillList.PREACHING); + int[] deps3 = {SkillList.MASONRY}; + try { + ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "dependencies"), deps3); + } catch (IllegalAccessException | NoSuchFieldException e) { + logger.info("Failed to rename preaching!"); + e.printStackTrace(); + } + } } public static void preInit(){ @@ -132,13 +119,15 @@ public class SkillChanges { final Class thisClass = SkillChanges.class; String replace; - Util.setReason("Allow skill check failures to add skill gain."); - CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); - replace = "{" + - " double advanceMultiplicator = "+SkillChanges.class.getName()+".newDoSkillGainNew($0, $1, $2, $3, $4, $5);" + - " $0.alterSkill(advanceMultiplicator, false, $4, true, $5);" + - "}"; - Util.setBodyDeclared(thisClass, ctSkill, "doSkillGainNew", replace); + if (WyvernMods.enableHybridSkillGain) { + Util.setReason("Add hybrid skill gain system hook."); + CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + replace = "{" + + " double advanceMultiplicator = " + SkillChanges.class.getName() + ".newDoSkillGainNew($0, $1, $2, $3, $4, $5);" + + " $0.alterSkill(advanceMultiplicator, false, $4, true, $5);" + + "}"; + Util.setBodyDeclared(thisClass, ctSkill, "doSkillGainNew", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 8910dad..375756c 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -16,9 +16,9 @@ import mod.sin.actions.items.SorcerySplitAction; import mod.sin.creatures.*; import mod.sin.creatures.titans.*; import mod.sin.lib.Prop; +import mod.sin.lib.SkillAssist; import mod.sin.lib.Util; import mod.sin.wyvern.bestiary.MethodsBestiary; -import mod.sin.wyvern.mastercraft.Mastercraft; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -161,6 +161,65 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static boolean mineGemsToVehicle = true; public static boolean regenerateStaminaOnVehicleAnySlope = true; + // Combat Module Configuration + public static boolean enableCombatModule = true; + public static boolean enableCombatRatingAdjustments = true; + public static boolean royalExecutionerBonus = true; + public static boolean petSoulDepthScaling = true; + public static boolean vehicleCombatRatingPenalty = true; + public static boolean fixMagranonDamageStacking = true; + public static boolean adjustCombatRatingSpellPower = true; + public static boolean disableLegendaryRegeneration = true; + public static boolean useStaticLegendaryRegeneration = true; + + // Mastercraft Module Configuration + public static boolean enableMastercraftModule = true; + public static boolean enableDifficultyAdjustments = true; + public static boolean affinityDifficultyBonus = true; + public static boolean legendDifficultyBonus = true; + public static boolean masterDifficultyBonus = true; + public static boolean itemRarityDifficultyBonus = true; + public static boolean legendItemDifficultyBonus = true; + public static boolean masterItemDifficultyBonus = true; + public static boolean empoweredChannelers = true; + public static boolean channelSkillFavorReduction = true; + + // Skill Module Configuration + public static boolean enableSkillModule = true; + public static boolean enableHybridSkillGain = true; + public static float hybridNegativeDecayRate = 5f; + public static float hybridPositiveDecayRate = 3f; + public static float hybridValueAtZero = 3.74f; + public static float hybridValueAtOneHundred = 0.9f; + public static HashMap skillName = new HashMap<>(); + public static HashMap skillDifficulty = new HashMap<>(); + public static HashMap skillTickTime = new HashMap<>(); + public static boolean changePreachingLocation = true; + + // Meditation Module Configuration + public static boolean enableMeditationModule = true; + public static boolean simplifyMeditationTerrain = true; + public static boolean removeInsanitySotG = true; + public static boolean removeHateWarBonus = true; + public static boolean insanitySpeedBonus = true; + public static boolean hateMovementBonus = true; + public static boolean scalingPowerStaminaBonus = true; + public static boolean scalingKnowledgeSkillGain = true; + public static boolean removeMeditationTickTimer = true; + public static boolean newMeditationBuffs = true; + public static boolean enableMeditationAbilityCooldowns = true; + public static long loveRefreshCooldown = 64800000L; // 18 hours default + public static long loveEnchantNatureCooldown = 64800000L; // 18 hours default + public static long loveLoveEffectCooldown = 64800000L; // 18 hours default + public static long hateWarDamageCooldown = 64800000L; // 18 hours default + public static long hateStructureDamageCooldown = 64800000L; // 18 hours default + public static long hateFearCooldown = 64800000L; // 18 hours default + public static long powerElementalImmunityCooldown = 64800000L; // 18 hours default + public static long powerEruptFreezeCooldown = 64800000L; // 18 hours default + public static long powerIgnoreTrapsCooldown = 64800000L; // 18 hours default + public static long knowledgeInfoCreatureCooldown = 64800000L; // 18 hours default + public static long knowledgeInfoTileCooldown = 64800000L; // 18 hours default + // Treasure Chest Loot Module Configuration public static boolean enableTreasureChestLootModule = true; @@ -345,6 +404,62 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea mineGemsToVehicle = Prop.getBooleanProperty("mineGemsToVehicle", mineGemsToVehicle); regenerateStaminaOnVehicleAnySlope = Prop.getBooleanProperty("regenerateStaminaOnVehicleAnySlope", regenerateStaminaOnVehicleAnySlope); + // Combat Module + enableCombatModule = Prop.getBooleanProperty("enableCombatModule", enableCombatModule); + enableCombatRatingAdjustments = Prop.getBooleanProperty("enableCombatRatingAdjustments", enableCombatRatingAdjustments); + royalExecutionerBonus = Prop.getBooleanProperty("royalExecutionerBonus", royalExecutionerBonus); + petSoulDepthScaling = Prop.getBooleanProperty("petSoulDepthScaling", petSoulDepthScaling); + vehicleCombatRatingPenalty = Prop.getBooleanProperty("vehicleCombatRatingPenalty", vehicleCombatRatingPenalty); + fixMagranonDamageStacking = Prop.getBooleanProperty("fixMagranonDamageStacking", fixMagranonDamageStacking); + adjustCombatRatingSpellPower = Prop.getBooleanProperty("adjustCombatRatingSpellPower", adjustCombatRatingSpellPower); + disableLegendaryRegeneration = Prop.getBooleanProperty("disableLegendaryRegeneration", disableLegendaryRegeneration); + useStaticLegendaryRegeneration = Prop.getBooleanProperty("useStaticLegendaryRegeneration", useStaticLegendaryRegeneration); + + // Mastercraft Module + enableMastercraftModule = Prop.getBooleanProperty("enableMastercraftModule", enableMastercraftModule); + enableDifficultyAdjustments = Prop.getBooleanProperty("enableDifficultyAdjustments", enableDifficultyAdjustments); + affinityDifficultyBonus = Prop.getBooleanProperty("affinityDifficultyBonus", affinityDifficultyBonus); + legendDifficultyBonus = Prop.getBooleanProperty("legendDifficultyBonus", legendDifficultyBonus); + masterDifficultyBonus = Prop.getBooleanProperty("masterDifficultyBonus", masterDifficultyBonus); + itemRarityDifficultyBonus = Prop.getBooleanProperty("itemRarityDifficultyBonus", itemRarityDifficultyBonus); + legendItemDifficultyBonus = Prop.getBooleanProperty("legendItemDifficultyBonus", legendItemDifficultyBonus); + masterItemDifficultyBonus = Prop.getBooleanProperty("masterItemDifficultyBonus", masterItemDifficultyBonus); + empoweredChannelers = Prop.getBooleanProperty("empoweredChannelers", empoweredChannelers); + channelSkillFavorReduction = Prop.getBooleanProperty("channelSkillFavorReduction", channelSkillFavorReduction); + + // Skill Module + enableSkillModule = Prop.getBooleanProperty("enableSkillModule", enableSkillModule); + enableHybridSkillGain = Prop.getBooleanProperty("enableHybridSkillGain", enableHybridSkillGain); + hybridNegativeDecayRate = Prop.getFloatProperty("hybridNegativeDecayRate", hybridNegativeDecayRate); + hybridPositiveDecayRate = Prop.getFloatProperty("hybridPositiveDecayRate", hybridPositiveDecayRate); + hybridValueAtZero = Prop.getFloatProperty("hybridValueAtZero", hybridValueAtZero); + hybridValueAtOneHundred = Prop.getFloatProperty("hybridValueAtOneHundred", hybridValueAtOneHundred); + changePreachingLocation = Prop.getBooleanProperty("changePreachingLocation", changePreachingLocation); + + // Meditation Module + enableMeditationModule = Prop.getBooleanProperty("enableMeditationModule", enableMeditationModule); + simplifyMeditationTerrain = Prop.getBooleanProperty("simplifyMeditationTerrain", simplifyMeditationTerrain); + removeInsanitySotG = Prop.getBooleanProperty("removeInsanitySotG", removeInsanitySotG); + removeHateWarBonus = Prop.getBooleanProperty("removeHateWarBonus", removeHateWarBonus); + insanitySpeedBonus = Prop.getBooleanProperty("insanitySpeedBonus", insanitySpeedBonus); + hateMovementBonus = Prop.getBooleanProperty("hateMovementBonus", hateMovementBonus); + scalingPowerStaminaBonus = Prop.getBooleanProperty("scalingPowerStaminaBonus", scalingPowerStaminaBonus); + scalingKnowledgeSkillGain = Prop.getBooleanProperty("scalingKnowledgeSkillGain", scalingKnowledgeSkillGain); + removeMeditationTickTimer = Prop.getBooleanProperty("removeMeditationTickTimer", removeMeditationTickTimer); + newMeditationBuffs = Prop.getBooleanProperty("newMeditationBuffs", newMeditationBuffs); + enableMeditationAbilityCooldowns = Prop.getBooleanProperty("enableMeditationAbilityCooldowns", enableMeditationAbilityCooldowns); + loveRefreshCooldown = Prop.getLongProperty("loveRefreshCooldown", loveRefreshCooldown); + loveEnchantNatureCooldown = Prop.getLongProperty("loveEnchantNatureCooldown", loveEnchantNatureCooldown); + loveLoveEffectCooldown = Prop.getLongProperty("loveLoveEffectCooldown", loveLoveEffectCooldown); + hateWarDamageCooldown = Prop.getLongProperty("hateWarDamageCooldown", hateWarDamageCooldown); + hateStructureDamageCooldown = Prop.getLongProperty("hateStructureDamageCooldown", hateStructureDamageCooldown); + hateFearCooldown = Prop.getLongProperty("hateFearCooldown", hateFearCooldown); + powerElementalImmunityCooldown = Prop.getLongProperty("powerElementalImmunityCooldown", powerElementalImmunityCooldown); + powerEruptFreezeCooldown = Prop.getLongProperty("powerEruptFreezeCooldown", powerEruptFreezeCooldown); + powerIgnoreTrapsCooldown = Prop.getLongProperty("powerIgnoreTrapsCooldown", powerIgnoreTrapsCooldown); + knowledgeInfoCreatureCooldown = Prop.getLongProperty("knowledgeInfoCreatureCooldown", knowledgeInfoCreatureCooldown); + knowledgeInfoTileCooldown = Prop.getLongProperty("knowledgeInfoTileCooldown", knowledgeInfoTileCooldown); + // Treasure Chest Loot Module enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule); @@ -398,6 +513,51 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea } } awardTitles.put(titleId, playerList); + }else if (name.startsWith("skillName")) { + String[] values = value.split(","); + if(values.length < 2 || values.length > 2){ + logger.warning("Error parsing Skill Name: Invalid amount of arguments for following property: "+value); + } + int skillId = SkillAssist.getSkill(values[0]); + if (skillId < 0){ + skillId = Integer.parseInt(values[0]); + } + if (skillName.containsKey(skillId)){ + logger.warning("Duplicate skill name configurations for skill id "+skillId); + }else{ + String newName = values[1]; + skillName.put(skillId, newName); + } + }else if (name.startsWith("skillDifficulty")) { + String[] values = value.split(","); + if(values.length < 2 || values.length > 2){ + logger.warning("Error parsing Skill Difficulty: Invalid amount of arguments for following property: "+value); + } + int skillId = SkillAssist.getSkill(values[0]); + if (skillId < 0){ + skillId = Integer.parseInt(values[0]); + } + if (skillDifficulty.containsKey(skillId)){ + logger.warning("Duplicate difficulty configurations for skill id "+skillId); + }else{ + float difficulty = Float.parseFloat(values[1]); + skillDifficulty.put(skillId, difficulty); + } + }else if (name.startsWith("skillTickTime")) { + String[] values = value.split(","); + if(values.length < 2 || values.length > 2){ + logger.warning("Error parsing Skill Tick Time: Invalid amount of arguments for following property: "+value); + } + int skillId = SkillAssist.getSkill(values[0]); + if (skillId < 0){ + skillId = Integer.parseInt(values[0]); + } + if (skillTickTime.containsKey(skillId)){ + logger.warning("Duplicate tick time configurations for skill id "+skillId); + }else{ + long difficulty = Long.parseLong(values[1]); + skillTickTime.put(skillId, difficulty); + } } } } catch (Exception e) { @@ -545,6 +705,86 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea logger.info("Regenerate Stamina On Vehicle Any Slope: "+regenerateStaminaOnVehicleAnySlope); } + logger.info("Combat Module: "+enableCombatModule); + if (enableCombatModule){ + logger.info("Combat Rating Adjustments: "+enableCombatRatingAdjustments); + if (enableCombatRatingAdjustments){ + logger.info("Royal Executioner Bonus: "+royalExecutionerBonus); + logger.info("Pet Soul Depth Scaling: "+petSoulDepthScaling); + logger.info("Vehicle Combat Rating Penalty: "+vehicleCombatRatingPenalty); + } + logger.info("Fix Magranon Damage Stacking: "+fixMagranonDamageStacking); + logger.info("Adjust Combat Rating Spell Power: "+adjustCombatRatingSpellPower); + logger.info("Disable Legendary Regeneration: "+disableLegendaryRegeneration); + logger.info("Use Static Legendary Regeneration: "+useStaticLegendaryRegeneration); + } + + logger.info("Mastercraft Module: "+enableMastercraftModule); + if (enableMastercraftModule){ + logger.info("Difficulty Adjustments: "+enableDifficultyAdjustments); + if (enableDifficultyAdjustments){ + logger.info("Affinity Difficulty Bonus: "+affinityDifficultyBonus); + logger.info("Legend Difficulty Bonus: "+legendDifficultyBonus); + logger.info("Master Difficulty Bonus: "+masterDifficultyBonus); + logger.info("Item Rarity Difficulty Bonus: "+itemRarityDifficultyBonus); + logger.info("Legend Item Difficulty Bonus: "+legendItemDifficultyBonus); + logger.info("Master Item Difficulty Bonus: "+masterItemDifficultyBonus); + } + logger.info("Empowered Channelers: "+empoweredChannelers); + logger.info("Channel Skill Favor Reduction: "+channelSkillFavorReduction); + } + + logger.info("Skill Module: "+enableSkillModule); + if (enableSkillModule){ + logger.info("Hybrid Skill Gain: "+enableHybridSkillGain); + if (enableHybridSkillGain){ + logger.info("Hybrid Negative Decay Rate: "+hybridNegativeDecayRate); + logger.info("Hybrid Positive Decay Rate: "+hybridPositiveDecayRate); + logger.info("Hybrid Value At Zero: "+hybridValueAtZero); + logger.info("Hybrid Value At One Hundred: "+hybridValueAtOneHundred); + } + for (int skillId : skillName.keySet()){ + logger.info(String.format("Changing name of skill %s to %s.", + SkillAssist.getSkill(skillId), skillName.get(skillId))); + } + for (int skillId : skillDifficulty.keySet()){ + logger.info(String.format("Setting difficulty of skill %s to %.2f.", + SkillAssist.getSkill(skillId), skillDifficulty.get(skillId))); + } + for (int skillId : skillTickTime.keySet()){ + logger.info(String.format("Setting tick time of skill %s to %d.", + SkillAssist.getSkill(skillId), skillTickTime.get(skillId))); + } + logger.info("Change Preaching Location: "+changePreachingLocation); + } + + logger.info("Meditation Module: "+enableMeditationModule); + if (enableMeditationModule){ + logger.info("Simplify Meditation Terrain: "+simplifyMeditationTerrain); + logger.info("Remove Insanity Shield of the Gone: "+removeInsanitySotG); + logger.info("Remove Hate War Bonus: "+removeHateWarBonus); + logger.info("Insanity Speed Bonus: "+insanitySpeedBonus); + logger.info("Hate Movement Bonus: "+hateMovementBonus); + logger.info("Scaling Power Stamina Bonus: "+scalingPowerStaminaBonus); + logger.info("Scaling Knowledge Skill Gain: "+scalingKnowledgeSkillGain); + logger.info("Remove Meditation Tick Timer: "+removeMeditationTickTimer); + logger.info("New Meditation Buffs: "+newMeditationBuffs); + logger.info("Meditation Ability Cooldowns: "+enableMeditationAbilityCooldowns); + if (enableMeditationAbilityCooldowns){ + logger.info("Love Refresh Cooldown: "+loveRefreshCooldown); + logger.info("Love Enchant Nature Cooldown: "+loveEnchantNatureCooldown); + logger.info("Love Love Effect Cooldown: "+loveLoveEffectCooldown); + logger.info("Hate War Bonus Cooldown: "+hateWarDamageCooldown); + logger.info("Hate Structure Damage Cooldown: "+hateStructureDamageCooldown); + logger.info("Hate Fear Cooldown: "+hateFearCooldown); + logger.info("Power Elemental Immunity Cooldown: "+powerElementalImmunityCooldown); + logger.info("Power Erupt/Freeze Cooldown: "+powerEruptFreezeCooldown); + logger.info("Power Ignore Traps Cooldown: "+powerIgnoreTrapsCooldown); + logger.info("Knowledge Info Creature Cooldown: "+knowledgeInfoCreatureCooldown); + logger.info("Knowledge Info Tile Cooldown: "+knowledgeInfoTileCooldown); + } + } + logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); //this.logger.log(Level.INFO, "Property: " + this.somevalue); @@ -582,11 +822,6 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Arena.preInit(); } - // Custom Titles Module Pre-Init - if (enableCustomTitlesModule) { - PlayerTitles.preInit(); - } - // Anti-Cheat Module Pre-Init if (enableAntiCheatModule) { AntiCheat.preInit(); @@ -597,6 +832,24 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea QualityOfLife.preInit(); } + // Combat Module Pre-Init + if (enableCombatModule) { + CombatChanges.preInit(); + } + + // Mastercraft Module Pre-Init + if (enableMastercraftModule) { + Mastercraft.preInit(); + } + + if (enableSkillModule) { + SkillChanges.preInit(); + } + + if (enableMeditationModule) { + MeditationPerks.preInit(); + } + // Treasure Chest Loot Module Pre-Init if (enableTreasureChestLootModule) { TreasureChests.preInit(); @@ -607,15 +860,13 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea TeleportHandler.preInit(); MethodsBestiary.preInit(); MissionCreator.preInit(); - SkillChanges.preInit(); - MeditationPerks.preInit(); MountedChanges.preInit(); EconomicChanges.preInit(); - Bloodlust.preInit(); - Mastercraft.preInit(); SupplyDepots.preInit(); KeyEvent.preInit(); - CombatChanges.preInit(); + + // Bloodlust might no longer be necessary. Code remains for reference. + //Bloodlust.preInit(); // Gem Augmentation is not complete. //GemAugmentation.preInit(); @@ -737,7 +988,11 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void onPlayerLogin(Player p) { DatabaseHelper.onPlayerLogin(p); - PlayerTitles.awardCustomTitles(p); + + // Award Custom Titles on player login + if(enableCustomTitlesModule) { + PlayerTitles.awardCustomTitles(p); + } } @Override @@ -778,7 +1033,9 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea //espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default. //espCounter = false; - SkillChanges.onServerStarted(); + if (enableSkillModule) { + SkillChanges.onServerStarted(); + } CreationEntry lockpicks = CreationMatrix.getInstance().getCreationEntry(ItemList.lockpick); try { @@ -847,11 +1104,11 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Bloodlust.pollLusts(); lastPolledBloodlust += pollBloodlustTime; } - if(lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){ + if(WyvernMods.useStaticLegendaryRegeneration && lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){ CombatChanges.pollUniqueRegeneration(); lastPolledUniqueRegeneration += pollUniqueRegenerationTime; } - if(lastPolledUniqueCollection + pollUniqueCollectionTime < System.currentTimeMillis()){ + if(WyvernMods.enableCombatModule && lastPolledUniqueCollection + pollUniqueCollectionTime < System.currentTimeMillis()){ CombatChanges.pollUniqueCollection(); lastPolledUniqueCollection += pollUniqueCollectionTime; } diff --git a/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java b/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java deleted file mode 100644 index ab7eaa7..0000000 --- a/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java +++ /dev/null @@ -1,494 +0,0 @@ -package mod.sin.wyvern.mastercraft; - -import javassist.bytecode.*; - -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Objects; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.IntStream; - - -public class BytecodeTools extends Bytecode { - - //private static final int EMPTY_INT = Integer.MAX_VALUE; - - BytecodeTools(ConstPool constPool){ - super(constPool); - } - - /** - * Look for a class in the constant pool. - * Throws NoMatchingConstPoolIndexException if the references isn't found. - * - * @param className String Object type. Full class name using periods. - * @return int primitive, index in constant pool table. - */ - int findClassIndex(String className){ - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - throw new RuntimeException("No matching class found."); - this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF); - return classReferenceIndex; - } - - int addClassIndex(String className){ - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - classReferenceIndex = this.getConstPool().addClassInfo(className); - this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF); - return classReferenceIndex; - } - - int findMethodIndex(int opcode, String name, String descriptor, String className){ - int methodReferenceIndex; - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - throw new RuntimeException("No matching class found."); - - methodReferenceIndex = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Methodref) - .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) - .filter(value -> Objects.equals(this.getConstPool().getMethodrefClass(value), classReferenceIndex)) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching method found.")); - this.addOpcode(opcode); - this.add((methodReferenceIndex >>> 8) & 0xFF, methodReferenceIndex & 0xFF); - - return methodReferenceIndex; - } - - int addMethodIndex(int opcode, String name, String methodDescriptor, String className){ - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - classReferenceIndex = this.getConstPool().addClassInfo(className); - int indexReference = this.getConstPool().addMethodrefInfo(classReferenceIndex, name, methodDescriptor); - this.addOpcode(opcode); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - return indexReference; - } - - int findFieldIndex(int opcode, String name, String descriptor, String className){ - int fieldReferenceIndex; - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - throw new RuntimeException("No matching class found."); - fieldReferenceIndex = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Fieldref) - .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) - .filter(value -> this.getConstPool().getFieldrefClass(value) == classReferenceIndex) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching field found.")); - this.addOpcode(opcode); - this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF); - return fieldReferenceIndex; - } - - int addFieldIndex(int opcode, String name, String descriptor, String className){ - int classReferenceIndex = getClassReferenceIndex(className); - if (classReferenceIndex == -1) - classReferenceIndex = this.getConstPool().addClassInfo(className); - int fieldReferenceIndex = this.getConstPool().addFieldrefInfo(classReferenceIndex, name, descriptor); - this.addOpcode(opcode); - this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF); - return fieldReferenceIndex; - } - - void findStringIndex(String string){ - int indexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_String) - .filter(value -> Objects.equals(this.getConstPool().getStringInfo(value), string)) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching string found.")); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void addStringIndex(String string){ - int indexReference = this.getConstPool().addStringInfo(string); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void findLongIndex(long longValue){ - int indexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Long) - .filter(value -> this.getConstPool().getLongInfo(value) == longValue) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching long found.")); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void addLongIndex(long longValue){ - int indexReference = this.getConstPool().addLongInfo(longValue); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void findFloatIndex(float floatValue){ - int indexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Float) - .filter(value -> this.getConstPool().getFloatInfo(value) == floatValue) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching float found.")); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void addFloatIndex(float floatValue){ - int indexReference = this.getConstPool().addFloatInfo(floatValue); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - /** - * a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double. - * - * @param doubleValue primitive double. - */ - void findDoubleIndex(double doubleValue){ - int indexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Double) - .filter(value -> this.getConstPool().getDoubleInfo(value) == doubleValue) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching double found.")); - this.addOpcode(Opcode.LDC2_W); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - /** - * a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double. - * - * @param doubleValue primitive double. - */ - void addDoubleIndex(double doubleValue){ - int indexReference = this.getConstPool().addDoubleInfo(doubleValue); - this.addOpcode(Opcode.LDC2_W); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - private boolean hasAClassDeclaringTag(int tag){ - return tag == ConstPool.CONST_Methodref || tag == ConstPool.CONST_Fieldref || tag == ConstPool.CONST_InterfaceMethodref; - } - - /** - * Often a class's name will appear twice in the constant pool. One of the occurrence is not used as a declaring class for anything. - * I have no idea why it's present but it can break looking up constant pool references if the unassociated one is picked. JA has a - * built in way of finding existent references but a underlying mechanic is that a hash map uses a string class name as a key - * in a hashMap. Two equal strings will overwrite each other in this case. This is part the the tools library to look for matches - * instead of relying on JA. - * - * 1. scan the constant pool and get the class references that match className. - * 2. scan again through the constant pool looking for class associations that use the references found in #1. One of the options - * will have no references and illuminate that one to return the one that should be used. - * - * @param className String type object, uses full class name and periods. - * @return int primitive, the address in constant pool for the class matching className. - */ - private int getClassReferenceIndex(String className){ - return IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class) - .filter(value -> Objects.equals(Descriptor.toClassName(this.getConstPool().getClassInfoByDescriptor(value)), className)) - .filter( verifyIndex -> - IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> hasAClassDeclaringTag(this.getConstPool().getTag(value))) - .filter(value -> { - boolean result = false; - switch (this.getConstPool().getTag(value)) { - case ConstPool.CONST_Methodref: - result = this.getConstPool().getMethodrefClass(value) == verifyIndex; - break; - case ConstPool.CONST_Fieldref: - result = this.getConstPool().getFieldrefClass(value) == verifyIndex; - break; - case ConstPool.CONST_InterfaceMethodref: - result = this.getConstPool().getInterfaceMethodrefClass(value) == verifyIndex; - break; - } - return result;}) - .count() > 0 - ) - .findFirst() - .orElse(-1); - } - - void findInterfaceMethodIndex(String name, String descriptor){ - if(IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref) - .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) - .count() != 1){ - throw new RuntimeException("No matching interface found."); - } - else { - int indexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref) - .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching interface found.")); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - } - - void addInterfaceMethodIndex(String name, String descriptor){ - int classIndexReference = IntStream.range(1, this.getConstPool().getSize()) - .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class) - .filter(value -> Objects.equals(this.getConstPool().getClassInfoByDescriptor(value), Descriptor.toClassName(descriptor))) - .findFirst() - .orElseThrow(() -> new RuntimeException("No matching class found.")); - int indexReference = this.getConstPool().addInterfaceMethodrefInfo(classIndexReference, name, descriptor); - this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); - } - - void codeBranching(int opcode, int branchCount){ - this.addOpcode(opcode); - this.add((branchCount >>> 8) & 0xFF, branchCount & 0xFF); - } - - void localVariableIndex(int opcode, int slot){ - this.addOpcode(opcode); - this.add(slot); - } - - void integerIndex(int opcode, int value){ - switch (opcode) { - case Opcode.BIPUSH : - this.addOpcode(Opcode.BIPUSH); - this.add((byte)value); - break; - case Opcode.SIPUSH : - this.addOpcode(Opcode.SIPUSH); - this.add((value >>> 8) & 0xFF, value & 0xFF); - } - } - - /** - * Encode the value for arg "integer" into the appropriate byteCode opCode + operand for the java-int. Add the - * encoded information to the byte code object "bytecode". - * - * @param integer int value. - */ - void addInteger(int integer) { - switch (integer) { - case -1: - this.add(Opcode.ICONST_M1); - break; - case 0: - this.add(Opcode.ICONST_0); - break; - case 1: - this.add(Opcode.ICONST_1); - break; - case 2: - this.add(Opcode.ICONST_2); - break; - case 3: - this.add(Opcode.ICONST_3); - break; - case 4: - this.add(Opcode.ICONST_4); - break; - case 5: - this.add(Opcode.ICONST_5); - break; - default: - if (integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) { - this.add(Opcode.BIPUSH); - // integer bound to byte size. - this.add(integer); - } else if (integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) { - this.add(Opcode.SIPUSH); - // Since byte code requires byte sized blocks, break up integer with bitmask and shift. - this.add((integer & 0xff00) >>> 8, integer & 0x00ff); - } else { - // Appends LDC or LDC_W depending on constant pool size. - this.addLdc(this.getConstPool().addIntegerInfo(integer)); - } - } - } - - /** - * Decode the byte code represented by a opCode + operand(s) at the position in arg "instructionIndex". Return - * decoded data as java-int. - * - * @param codeIterator JA CodeIterator object. - * @param instructionIndex int value, it is the codeIterator index of an opCode. - * @return int value. - */ - int getInteger(CodeIterator codeIterator, int instructionIndex) { - int opCode = codeIterator.byteAt(instructionIndex); - switch (opCode) { - case Opcode.ICONST_M1: - return -1; - case Opcode.ICONST_0: - return 0; - case Opcode.ICONST_1: - return 1; - case Opcode.ICONST_2: - return 2; - case Opcode.ICONST_3: - return 3; - case Opcode.ICONST_4: - return 4; - case Opcode.ICONST_5: - return 5; - case Opcode.BIPUSH: - return codeIterator.byteAt(instructionIndex + 1); - case Opcode.SIPUSH: - return codeIterator.s16bitAt(instructionIndex + 1); - case Opcode.LDC: - return this.getConstPool().getIntegerInfo(codeIterator.byteAt(instructionIndex + 1)); - case Opcode.LDC_W: - return this.getConstPool().getIntegerInfo(codeIterator.u16bitAt(instructionIndex + 1)); - default: - throw new RuntimeException(String.format("Failed to decode integer. Pos = %d, Bytecode = %d", instructionIndex, opCode)); - } - } - - static int findSlotInLocalVariableTable(CodeAttribute codeAttribute, String variableName){ - LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); - int tableOrdinal; - tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1); - if (tableOrdinal == -1){ - return -1; - } - return table.index(tableOrdinal); - } - - static int findLineNumberInLineNumberTable(CodeAttribute codeAttribute, String variableName){ - LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LineNumberAttribute.tag); - int tableOrdinal; - tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1); - if (tableOrdinal == -1){ - return -1; - } - return table.index(tableOrdinal); - } - - private static int[] getInstruction(int size, int index, CodeIterator codeIterator) { - int[] toReturn = null; - int bitLine; - int bitLine2; - switch (size) { - case 1: - bitLine = codeIterator.byteAt(index); - toReturn = new int[]{ - bitLine - }; - break; - case 2: - bitLine = codeIterator.s16bitAt(index); - toReturn = new int[]{ - (bitLine & 0xff00) >>> 8, - bitLine & 0x00ff - }; - break; - case 3: - bitLine = codeIterator.s32bitAt(index); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8 - // not using the last byte - }; - break; - case 4: - bitLine = codeIterator.s32bitAt(index); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8, - (bitLine & 0x000000ff) - }; - break; - case 5: - bitLine = codeIterator.s32bitAt(index); - bitLine2 = codeIterator.byteAt(index + 4); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8, - (bitLine & 0x000000ff), - bitLine2 - }; - break; - case 6: - bitLine = codeIterator.s32bitAt(index); - bitLine2 = codeIterator.s16bitAt(index + 4); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8, - (bitLine & 0x000000ff), - (bitLine2 & 0xff00) >>> 8, - (bitLine2 & 0x00ff) - }; - break; - case 7: - bitLine = codeIterator.s32bitAt(index); - bitLine2 = codeIterator.s32bitAt(index + 4); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8, - (bitLine & 0x000000ff), - (bitLine2 & 0xff000000) >>> 24, - (bitLine2 & 0x00ff0000) >>> 16, - (bitLine2 & 0x0000ff00) >>> 8 - // not using the last byte - }; - break; - case 8: - bitLine = codeIterator.s32bitAt(index); - bitLine2 = codeIterator.s32bitAt(index + 4); - toReturn = new int[]{ - (bitLine & 0xff000000) >>> 24, - (bitLine & 0x00ff0000) >>> 16, - (bitLine & 0x0000ff00) >>> 8, - (bitLine & 0x000000ff), - (bitLine2 & 0xff000000) >>> 24, - (bitLine2 & 0x00ff0000) >>> 16, - (bitLine2 & 0x0000ff00) >>> 8, - (bitLine2 & 0x000000ff) - }; - break; - } - return toReturn; - } - - public static void byteCodePrint(String destinationPath, CodeIterator codeIterator) throws FileNotFoundException, BadBytecode { - Path printPath = Paths.get(destinationPath); - PrintWriter out = new PrintWriter(printPath.toFile()); - final String[] instructionOut = {""}; - codeIterator.begin(); - while (codeIterator.hasNext()) { - int index = codeIterator.next(); - int[] instruction = getInstruction(codeIterator.lookAhead() - index, index, codeIterator); - instructionOut[0] += Integer.toString(index); - instructionOut[0] += " "; - instructionOut[0] += Mnemonic.OPCODE[instruction[0]]; - if (instruction.length > 1) { - instructionOut[0] += " "; - IntStream.range(1, instruction.length) - .forEach(value -> { - instructionOut[0] += Integer.toString(instruction[value]); - instructionOut[0] += " "; - }); - } - out.println(instructionOut[0]); - instructionOut[0] = ""; - } - out.close(); - } - - static void printArrayToHex(Object[] obj, String name, Logger logger){ - int length = obj.length; - int[] c = new int[length]; - for (int i=0;i toExtendEntries = new ArrayList<>(); - private static ExtendTitleEnum singletonInstance; - - private ExtendTitleEnum(String className, int valuesSizerIndex, int populateVALUESIndex, ConstPool constPool) { - this.className = className; - this.valuesSizerIndex = valuesSizerIndex; - this.populateVALUESIndex = populateVALUESIndex; - this.constPool = constPool; - } - - /** - * Goes through the enum class's initiator to find bytecode index positions. - * - * @throws BadBytecode forwarded, Javassist stuff. - */ - static void builder(String className) throws BadBytecode, NotFoundException { - int valuesSizerIndex = -1; - //int indexANEWARRAY = -1; - int populateVALUESIndex = -1; - CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(className); - ConstPool constPool = ctClassEnum.getClassFile().getConstPool(); - CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); - // Get the byte code instruction index for - // 1) size value for ANEWARRAY, - // 2) the VALUES array assignment or population. - BytecodeTools b = new BytecodeTools(constPool); - String valuesDescriptor = className.replace(".", "/"); - valuesDescriptor = "[L" + valuesDescriptor + ";"; - int constPoolValuesIndex = b.findFieldIndex(Opcode.PUTSTATIC, "$VALUES", - valuesDescriptor, className); - codeIterator.begin(); - int lastIndex = 0; - while (codeIterator.hasNext()){ - int instructionIndex = codeIterator.next(); - int opCode = codeIterator.byteAt(instructionIndex); - switch (opCode){ - case Opcode.ANEWARRAY : - valuesSizerIndex = lastIndex; - //indexANEWARRAY = instructionIndex; - break; - case Opcode.PUTSTATIC : - int cpAddress = codeIterator.u16bitAt(instructionIndex+1); - if (cpAddress == constPoolValuesIndex){ - populateVALUESIndex = instructionIndex; - } - break; - default: - break; - } - lastIndex = instructionIndex; - } - - synchronized (ExtendTitleEnum.class) { - singletonInstance = new ExtendTitleEnum(className, valuesSizerIndex, populateVALUESIndex, constPool); - } - } - - - static ExtendTitleEnum getSingletonInstance() { - return singletonInstance; - } - - /** - * A method to create data structures and add record a reference for that object. - * - * @param fieldName the name for the enum entry. - * @param titleId an ordinal for the Titles.Title enum. - * @param maleName in-game title name for male toons. - * @param femaleName in-game title name for femaleName toons. - * @param skillId A id number for the skill associated with the title, see {@link SkillList} - * @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In - * order to avoid premature class initialization for Javassist's bytecode stages we use a string - * instead of the WU object. The string must match one of the enum field names. - */ - synchronized void addExtendEntry(String fieldName, int titleId, String maleName, String femaleName, int skillId, String titleTypes) { - if (singletonInstance == null) { - throw new RuntimeException("ExtendTitleEnum instance is null, build it before addExtendEntry"); - } - EnumFields enumFields = new EnumFields(fieldName, titleId, maleName, femaleName, skillId, titleTypes); - toExtendEntries.add(enumFields); - } - - class EnumFields { - final String fieldName; - final int titleId; - final String maleName; - final String femaleName; - final int skillId; - final String titleTypes; - - /** - * @param fieldName the name for the enum entry. - * @param titleId an ordinal for the Titles.Title enum. - * @param maleName in-game title name for male toons. - * @param femaleName in-game title name for femaleName toons. - * @param skillId A id number for the skill associated with the title, see {@link SkillList} - * @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In - * order to avoid premature class initialization for Javassist's bytecode stages we use a string - * instead of the WU object. - **/ - EnumFields(String fieldName, int titleId, String maleName, String femaleName, - int skillId, String titleTypes){ - this.fieldName = fieldName; - this.titleId = titleId; - this.maleName = maleName; - this.femaleName = femaleName; - this.skillId = skillId; - this.titleTypes = titleTypes; - } - } - - /** - * Intended to be used in WurmServerMod-initiate section and it's for bytecode changes. This adds field objects to the enum class. - * - * @throws CannotCompileException forwarded, Javassist stuff. - */ - private synchronized void createFieldsInEnum() throws CannotCompileException, NotFoundException { - if (toExtendEntries.size() == 0){ - throw new RuntimeException("Can not extend an enum without values in toExtendEntries arrayList."); - } - - CtClass enumCtClass = HookManager.getInstance().getClassPool().get(this.className); - for (EnumFields enumData : toExtendEntries) { - CtField field = new CtField(enumCtClass, enumData.fieldName, enumCtClass); - field.setModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL | Modifier.ENUM); - enumCtClass.addField(field); - } - } - - /** - * This method uses JA bytecode to inject into the Enum's class initiator in order to expand the enum's $VALUES field. - * - * @throws BadBytecode forwarded, Javassist stuff. - */ - private void resizeEnumVALUES() throws BadBytecode, ClassNotFoundException, NotFoundException { - int expansion = toExtendEntries.size(); - CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className); - CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); - - BytecodeTools findBytecode = new BytecodeTools(this.constPool); - int currentSize = findBytecode.getInteger(codeIterator, this.valuesSizerIndex); - findBytecode.addInteger(currentSize); - findBytecode.addOpcode(Opcode.ANEWARRAY); - findBytecode.addClassIndex(this.className); - - BytecodeTools replaceBytecode = new BytecodeTools(this.constPool); - replaceBytecode.addInteger(currentSize + expansion); - replaceBytecode.addOpcode(Opcode.ANEWARRAY); - replaceBytecode.addClassIndex(this.className); - - CodeReplacer codeReplacer = new CodeReplacer(ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute()); - codeReplacer.replaceCode(findBytecode.get(), replaceBytecode.get()); - } - - /** - * This method builds bytecode to inject into the enum's initiator. The injected code initializes new enum entries and adds - * a reference of that new object to the $VALUES array. - * - * @throws BadBytecode forwarded, JA stuff. - * @throws ClassNotFoundException forwarded, JA stuff. - * @throws NotFoundException forwarded, JA stuff. - */ - synchronized void ExtendEnumEntries() throws BadBytecode, ClassNotFoundException, NotFoundException, CannotCompileException { - createFieldsInEnum(); - CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className); - CodeIterator initiatorCodeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); - - BytecodeTools enumInitiator = new BytecodeTools(ctClassEnum.getClassFile().getConstPool()); - BytecodeTools populateVALUES = new BytecodeTools(ctClassEnum.getClassFile().getConstPool()); - int extensionCounter = 0; - int valuesSize = enumInitiator.getInteger(initiatorCodeIterator, this.valuesSizerIndex); - // Construct the two bytecode objects to be inserted. The multiple enumData in toExtendEntries are combined into one - // long bytecode sequence and inserted at the proper point. - for (EnumFields enumData : toExtendEntries) { - enumInitiator.addOpcode(Opcode.NEW); - enumInitiator.findClassIndex(this.className); - enumInitiator.addOpcode(Opcode.DUP); - enumInitiator.addLdc(enumData.fieldName); - enumInitiator.addInteger(valuesSize + extensionCounter); - enumInitiator.addInteger(enumData.titleId); - enumInitiator.addLdc(enumData.maleName); - enumInitiator.addLdc(enumData.femaleName); - enumInitiator.addInteger(enumData.skillId); - enumInitiator.addFieldIndex(Opcode.GETSTATIC, enumData.titleTypes, - "Lcom/wurmonline/server/players/Titles$TitleType;", - "com/wurmonline/server/players/Titles$TitleType"); - enumInitiator.addMethodIndex(Opcode.INVOKESPECIAL, "", - "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ILcom/wurmonline/server/players/Titles$TitleType;)V", - this.className); - enumInitiator.addFieldIndex(Opcode.PUTSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;", - this.className); - - populateVALUES.addOpcode(Opcode.DUP); - populateVALUES.addInteger(valuesSize + extensionCounter); - extensionCounter++; - populateVALUES.findFieldIndex(Opcode.GETSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;", - this.className); - populateVALUES.addOpcode(Opcode.AASTORE); - } - // Do bytecode changes from the bottom up so bytecode indexes don't change after every insert. - initiatorCodeIterator.insert(populateVALUESIndex, populateVALUES.get()); - resizeEnumVALUES(); - initiatorCodeIterator.insert(valuesSizerIndex, enumInitiator.get()); - } -} \ No newline at end of file diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java deleted file mode 100644 index 512152c..0000000 --- a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java +++ /dev/null @@ -1,203 +0,0 @@ -package mod.sin.wyvern.mastercraft; - -import com.wurmonline.server.Server; -import com.wurmonline.server.items.Item; -import com.wurmonline.server.players.Titles; -import com.wurmonline.server.skills.Skill; -import com.wurmonline.server.skills.SkillList; -import javassist.*; -import javassist.bytecode.BadBytecode; -import javassist.expr.ExprEditor; -import javassist.expr.MethodCall; -import mod.sin.lib.Util; -import org.gotti.wurmunlimited.modloader.ReflectionUtil; -import org.gotti.wurmunlimited.modloader.classhooks.HookManager; - -import java.util.Objects; -import java.util.logging.Logger; - -public class Mastercraft { - private static Logger logger = Logger.getLogger(Mastercraft.class.getName()); - public static double getNewDifficulty(Skill skill, double diff, Item item){ - if(skill.affinity > 0){ - diff -= skill.affinity; - } - if(skill.getKnowledge() > 99.0d){ - diff -= 2d-((100d-skill.getKnowledge())*2d); - } - if(skill.getKnowledge() > 90.0d){ - diff -= 2d-((100d-skill.getKnowledge())*0.2d); - } - if(item != null){ - if(item.getRarity() > 0){ - diff -= item.getRarity(); - } - if(item.getCurrentQualityLevel() > 99.0f){ - diff -= 1d-((100d-item.getCurrentQualityLevel())*1d); - } - if(item.getCurrentQualityLevel() > 90.0f){ - diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d); - } - } - return diff; - } - public static float getCastPowerIncrease(Skill skill){ - double addedPower = 0; - if(skill.affinity > 0){ - addedPower += 2*skill.affinity; - } - if(skill.getKnowledge() > 0){ - float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); - float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); - addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2); - }else{ - logger.warning("Error: Some player just tried casting with no channeling skill!"); - } - return (float) addedPower; - } - public static float getFavorCostMultiplier(Skill skill){ - float mult = 1f; - if(skill.affinity > 0){ - mult -= skill.affinity*0.02f; //2% reduction per affinity - } - if(skill.getKnowledge() > 90d){ - mult -= 0.1d-((100d-skill.getKnowledge())*0.01d); - } - if(skill.getKnowledge() > 99d){ - mult -= 0.1d-((100-skill.getKnowledge())*0.1d); - } - return mult; - } - /*public static void addNewTitles(){ - try { - ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title"); - // GM/Developer Titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 2500, "Game Master", "Game Master", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Developer", 2501, "Developer", "Developer", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pet_Me", 2502, "Pet Me", "Pet Me", -1, "NORMAL"); - - // Troll Titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Macro_King", 550, "Macro King", "Macro King", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Drama_Queen", 551, "Drama Queen", "Drama Queen", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Zergling", 552, "Zergling", "Zergling", -1, "NORMAL"); - 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"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pizzamancer", 603, "Pizzamancer", "Pizzamancer", -1, "NORMAL"); - - // Special Event Titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Titan_Slayer", 700, "Titanslayer", "Titanslayer", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Spectral_Slayer", 701, "Spectral Warrior", "Spectral Warrior", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, "NORMAL"); - - // Donation titles - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Donator", 800, "Donator", "Donator", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pazza_FavoriteGM", 801, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Warriorgen_ThatGuy", 802, "That Guy", "That Guy", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eternallove_WarriorgensWife", 803, "Warriorgens Wife", "Warriorgens Wife", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Bambam_ThornOne", 804, "Thorn One", "Thorn One", -1, "NORMAL"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Svenja_CareDependant", 805, "The care-dependent", "The care-dependent", -1, "NORMAL"); - 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"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eltacolad_TrueTaco", 811, "The One True Taco", "The One True Taco", -1, "NORMAL"); - - // Skill Titles (100) - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archery_Legendary", 1500, "Legendary Marksman", "Legendary Marksman", 1030, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Body_Legendary", 1501, "Hercules", "Hercules", 1, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Axes_Legendary", 1502, "Viking", "Viking", 1003, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Baking_Legendary", 1503, "Patissier", "Patissier", 10039, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archaeology_Legendary", 1504, "Curator", "Curator", 10069, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("CarvingKnife_Legendary", 1505, "Woodsculptor", "Woodsculptor", 10007, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Taming_Legendary", 1506, "King of the Jungle", "Queen of the Jungle", 10078, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Climbing_Legendary", 1507, "Moonwalker", "Moonwalker", 10073, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Tracking_Legendary", 1508, "Bloodhound", "Bloodhound", 10018, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Clubs_Legendary", 1509, "Bam Bam", "Bam Bam", 1025, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Catapults_Legendary", 1510, "Castle Crasher", "Castle Crasher", 10077, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Firemaking_Legendary", 1511, "Incendiary", "Incendiary", 1010, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gardening_Legendary", 1512, "Earthbound", "Earthbound", 10045, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hammers_Legendary", 1513, "Doomhammer", "Doomhammer", 1027, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Locksmithing_Legendary", 1514, "Vault Smith", "Vault Smith", 10034, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Religion_Legendary", 1515, "Chosen", "Chosen", 1026, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Yoyo_Legendary", 1516, "String Theorist", "String Theorist", 10050, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Nature_Legendary", 1517, "Naturalist", "Naturalist", 1019, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mind_Legendary", 1518, "Enlightened", "Enlightened", 2, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mauls_Legendary", 1519, "Breaker", "Breaker", 1004, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Shipbuilding_Legendary", 1520, "Naval Engineer", "Naval Engineer", 10082, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("NaturalSubstances_Legendary", 1521, "Biochemist", "Biochemist", 10042, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("WarMachines_Legendary", 1522, "Eradicator", "Eradicator", 1029, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Thievery_Legendary", 1523, "Shadow", "Shadow", 1028, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Swords_Legendary", 1524, "Samurai", "Samurai", 1000, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().addExtendEntry("Forestry_Legendary", 1525, "Silvanus", "Mother Nature", 10048, "LEGENDARY"); - ExtendTitleEnum.getSingletonInstance().ExtendEnumEntries(); - - } catch (BadBytecode | ClassNotFoundException | NotFoundException | CannotCompileException e) { - logger.warning(e.getMessage()); - } - }*/ - - public static void changeExistingTitles(){ - for (Titles.Title title : Titles.Title.values()) { - if (Objects.equals("Pumpkin King", title.getFemaleName())){ - try { - ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen"); - } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { - e.printStackTrace(); - } - } - } - } - public static void preInit(){ - try { - ClassPool classPool = HookManager.getInstance().getClassPool(); - Class thisClass = Mastercraft.class; - - // - Reduce skill check difficulty with high skills or tools - // - CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); - - /*ctSkill.getDeclaredMethod("checkAdvance").insertBefore("" - + "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);");*/ - Util.setReason("Modify difficulty for skill checks in MasterCraft."); - String replace = "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);"; - Util.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", replace); - - // - Increase spellcasting power for skilled channelers - // - CtClass ctSpell = classPool.get("com.wurmonline.server.spells.Spell"); - CtMethod[] ctRuns = ctSpell.getDeclaredMethods("run"); - for(CtMethod method : ctRuns){ - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("doEffect")) { - m.replace("$2 += "+Mastercraft.class.getName()+".getCastPowerIncrease(castSkill);" - + "$_ = $proceed($$);"); - logger.info("Instrumented doEffect in run()"); - } - } - }); - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("depleteFavor")) { - m.replace("$1 *= "+Mastercraft.class.getName()+".getFavorCostMultiplier(castSkill);" - + "$_ = $proceed($$);"); - logger.info("Instrumented depleteFavor in run()"); - } - } - }); - } - } catch (CannotCompileException | NotFoundException e) { - e.printStackTrace(); - } - } -} From 17ddab37837bdaf50cdabe20921de0917ccbe6a7 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Wed, 8 May 2019 02:15:14 -0400 Subject: [PATCH 6/8] WyvernMods Configurable Phase 3 --- mods/WyvernMods.properties | 166 ++++++++++++++ src/main/java/mod/sin/wyvern/Bloodlust.java | 4 - src/main/java/mod/sin/wyvern/Bounty.java | 110 +++------ .../java/mod/sin/wyvern/EconomicChanges.java | 37 +-- .../java/mod/sin/wyvern/MissionCreator.java | 82 ++++--- .../java/mod/sin/wyvern/MountedChanges.java | 17 +- src/main/java/mod/sin/wyvern/RareSpawns.java | 56 ----- .../java/mod/sin/wyvern/SupplyDepots.java | 79 ++++--- .../java/mod/sin/wyvern/TeleportHandler.java | 19 +- src/main/java/mod/sin/wyvern/Titans.java | 75 +----- src/main/java/mod/sin/wyvern/WyvernMods.java | 215 ++++++++++++++++-- 11 files changed, 538 insertions(+), 322 deletions(-) diff --git a/mods/WyvernMods.properties b/mods/WyvernMods.properties index b5cea90..baa3cd3 100644 --- a/mods/WyvernMods.properties +++ b/mods/WyvernMods.properties @@ -763,6 +763,172 @@ knowledgeInfoTileCooldown=14400000 ## >> END MEDITATION MODULE << ## +## >> TITAN MODULE << ## +## The Titan Module handles the implementation of Titans, "raid boss" style creatures with unique mechanics. +## These titans are designed to be completely impossible by small groups of players and must be tackled in a sizable group. +enableTitanModule=true + +#disableTitanNaturalRegeneration: Disables the natural health regeneration of titans. +disableTitanNaturalRegeneration=true +#pollTitanSpawnTime: Amount of time, in milliseconds, to poll the new spawn of a titan. +# This is not the time for a new titan to spawn, just how frequently the server will check to see if a new one should spawn. +# Default is 120000, or 2 minutes. +pollTitanSpawnTime=120000 +#pollTitanTime: Amount of time, in milliseconds, to poll mechanics on the titan. +# This is how frequently it will check to do mechanics during a titan fight. The less frequent the polling, the less often mechanics will occur. +# Default is 1000, or 1 second. +pollTitanTime=1000 +#titanRespawnTime: Amount of time, in milliseconds, between spawns of new titans. +# There can only be one titan active on a server at a time. This timer will determine how long after the previous spawn a new one should be spawned. +# Default is 288000000, or 80 hours (3 days 8 hours) +titanRespawnTime=288000000 +#TODO: Add additional configurations for which titans should be allowed to spawn, their loot, mechanics, and more. + +## >> END TITAN MODULE << ## + +## >> RARE SPAWN MODULE << ## +## The Rare Spawn Module handles the spawning of new creatures which are designed to be stronger than trolls but weaker than legendary creatures. +## This helps fill the gap for small hunting parties, allowing groups of 2-5 slay challenging creatures. +enableRareSpawnModule=true + +#pollRareSpawnTime: Amount of time, in milliseconds, to check spawning of a new rare spawn. +# Rare spawns occur if no other rare spawn is found on the server. As soon as one dies, another replaces it. +pollRareSpawnTime=300000 +#TODO: Add additional configurations for which rare spawns should be allowed to spawn, their loot, additional creature spawns, and more. + +## >> END RARE SPAWN MODULE << ## + +## >> MISSION MODULE << ## +## The Mission Module adds additional features to the existing epic mission features. +## It also helps integrate them more easily into PvE environments by making them more frequent and rewarding. +## Finally, it also helps clear up some bugs which prevent them from occurring properly under some scenarios. +enableMissionModule=true + +# > NEW MISSION CREATOR < # +# New Mission Creator is a system that's independent of the natural mission creation system. +# This handles the creation of new missions in a more precise way than the vanilla handling, which sometimes doesn't function as intended. +# Instead of creation of a mission at random, it will always create a new mission on a timer (set below). +# The only case where it will not create a new missions is if there is already the maximum amount of missions available (1 per entity). +# When missions expire in the default system, there are generally issues with removal of those missions to make room for more. +# This system also double-checks all active missions when the poll occurs, removing any missions which have been expired or completed. +# The process helps open up new slots for missions to be created in a more timely and clean manner. +enableNewMissionCreator=true + +#pollMissionCreatorTime: Amount of time, in milliseconds, to poll the creation of new missions using the New Mission Creator. +# This handles how frequently new missions are added to the system. If you want a new mission every day, set to 1 day worth of milliseconds. +# Default is 14400000, or 4 hours. +pollMissionCreatorTime=14400000 +#useValreiEntities: Whether to use Valrei Entities as the creators for some missions. +# This option extends the default system to include entities such as Walnut, Jackal, and Scavenger to add new missions. +# Using the New Mission Creator, this will allow up to 11 missions to be active at a time instead of the default 4. +useValreiEntities=true +#TODO: Add additional options for control over what missions are created. + +# > END NEW MISSION CREATOR < # + +#addMissionCurrencyReward: Adds a 20-40 copper reward at random for players who participated in the completion of a mission. +addMissionCurrencyReward=true +#TODO: Allow configuration of the currency reward. +#preventMissionOceanSpawns: Prevents mission creatures from spawning in water. +preventMissionOceanSpawns=true +#additionalHerbivoreChecks: Adds additional checks when the system attempts to spawn a herbivore epic creature. +# This prevents legendary creatures, titans, and rare spawns from being used in epic missions which shouldn't allow them. +additionalHerbivoreChecks=true +#additionalMissionSlayableChecks: Adds additional checks when the system attempts to spawn an epic mission slayable creature. +# This prevents legendary creatures, titans, and rare spawns from being used in epic missions which shouldn't allow them. +additionalMissionSlayableChecks=true +#disableEpicMissionTypes: Disables the Ritual, Destroy Guard Tower, and Slay Tower Guards mission types from the system. +# This helps prevent missions from occurring which can be annoying or impossible to complete in some enviornments. +disableEpicMissionTypes=true +#TODO: Allow configuration of which types of missions to disable. + +## >> END MISSION MODULE << ## + +## >> MOUNTED MODULE << ## +## The Mounted Module handles various changes to mounts such as horses. +## It does not affect vehicle speeds, and strictly relates to creature mounts. +enableMountedModule=true +#newMountSpeedScaling: Changes the way hunger and health affects the mounted speed of a creature. Explanation: +# Mount speed has been completely redone from the ground up, using new formulas and different weights. +# Mount speed now scales from all the variables used to calculate speed. +# The thresholds for damage and hunger have been removed and replaced by a formula with a smoothed function to calculate the new speeds. +# Equipment on mounts now scale the speed multiplicatively instead of additively. +# - This means that well-equipped mounts will no longer be able to run decently fast when extremely hurt. +# - If they're low on health, they move slow, period. +# Barding now has a multiplicative speed reduction. Cloth offers the lowest penalty, while chain incurs the largest penalty. +# Traits remain additive to the hunger and health modifiers, but are now scaled multiplicatively by gear and other effects. +# Oakshell now has an slowing effect on the speed of a mount depending on power. +# - This effect is more severe than the epic iteration of the spell, applying a multiplicative slow to the creature. +# Old chart: https://i.imgur.com/bgVY8ne.png +# New chart: https://i.imgur.com/2IYEsA1.png +newMountSpeedScaling=true +#TODO: Add additional options for scaling of WoA/BoTD effects, QL scaling, etc. +#updateMountSpeedOnDamage: Forces a mount's speed to update instantaneously when it takes damage. +# In the vanilla system, there is a random factor where dealing damage to a mount can take a random amount of time to update. +# Through testing, this could take up to 20 seconds or even longer, since the update was random. +# This setting prevents that from happening, and hard-forces the server to update the mount speed immediately when the mount takes damage. +updateMountSpeedOnDamage=true +#allowBisonMounts: Allows Bison to be mounted, just like a horse. If it can pull a wagon, why not hold a person? +allowBisonMounts=true +#TODO: Enable configuration of bison mount speeds. In the meantime, might be able to be adjusted through bdew's movement mod. + +## >> END MOUNTED MODULE << ## + +## >> TELEPORT MODULE << ## +## The Teleport Module handles custom teleportation between two servers with additional features. +## Instead of requiring one server to always give the exact location where the player should arrive on the other side, +## the Teleport Module uses a new method which allows the player to land at either their village token or random location. +enableTeleportModule=true + +#useArenaTeleportMethod: Uses a special method when specific coordinates are given on a server to either randomize location +# place them at their village token on the new server. +# ! Most of this system is hardcoded and will not function well on a server that is not Revenant ! +useArenaTeleportMethod=true +#TODO: Expand this system and make it more configurable. Document more clearly. + +## >> END TELEPORT MODULE << ## + +## >> ECONOMY MODULE << ## +## The Economy Module handles pricing of items and various mechanics involving currency and traders. +enableEconomyModule=true + +#adjustSealedMapValue: The Sealed Map is a custom item which creates a Treasure Map (from TreasureHunting mod) when unsealed. +# This option adjusts their value so it is not static, and instead scaled based on the QL of the sealed map. +adjustSealedMapValue=true +#TODO: Add additional options to adjust the price of sealed maps. +#disableTraderRefill: Disables Traders from refilling their currency from the king's coffers at random. +# Other methods of refilling their currency will be required if you disable this. +disableTraderRefill=true +#voidTraderMoney: When players buy items from traders, by default all the money goes into the trader to be extracted again. +# This option voids 80% of the currency that gets traded to traders, preventing players from simply draining their spent currency out immediately. +voidTraderMoney=true + +## >> END ECONOMY MODULE << ## + +## >> SUPPLY DEPOT MODULE << ## +## The Supply Depot Module implements a new system where supply depots are spawned randomly on the map to be claimed by players. +## These depots will reward the player if they manage to stand near the depot without interruption for a certain amount of time. +## On PvP servers, these can create interesting combat scenarios in locations that are unexpected. +enableSupplyDepotModule=true + +#useSupplyDepotLights: Whether or not to use the "rift beam" light to mark the locations of depots for all players on the map. +useSupplyDepotLights=true +#pollDepotTime: Amount of time, in milliseconds, to poll supply depots. +# This is not the amount of time before new ones spawn, but just how often it checks if they should be spawned, cleared, and similar. +# Default is 60000, or 1 minute. +pollDepotTime=60000 +#captureMessageInterval: Amount of time, in milliseconds, to wait before allowing another global capture message to occur. +# This prevents players from spamming the capture action to create global messages for players. +# Default is 180000, or 3 minutes. +captureMessageInterval=180000 +#depotRespawnTime: Amount of time, in milliseconds, between spawns of depots. +# This is calculated from the last spawn of a depot, not the last capture. +# Default is 39600000, or 11 hours. +depotRespawnTime=39600000 +#TODO: Allow configuration of rewards from depots and other options. + +## >> END SUPPLY DEPOT MODULE << ## + ## >> TREASURE CHEST LOOT MODULE << ## ## The Treasure Chest Loot Module affects the vanilla treasure chests. ## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them. diff --git a/src/main/java/mod/sin/wyvern/Bloodlust.java b/src/main/java/mod/sin/wyvern/Bloodlust.java index 38299d7..6715968 100644 --- a/src/main/java/mod/sin/wyvern/Bloodlust.java +++ b/src/main/java/mod/sin/wyvern/Bloodlust.java @@ -5,10 +5,6 @@ import com.wurmonline.server.TimeConstants; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.creatures.Creatures; import javassist.ClassPool; -import javassist.CtClass; -import javassist.NotFoundException; -import javassist.bytecode.Descriptor; -import mod.sin.lib.Util; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java index 23b0e68..2b5ab5a 100644 --- a/src/main/java/mod/sin/wyvern/Bounty.java +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -91,34 +91,13 @@ public class Bounty { try { ClassPool classPool = HookManager.getInstance().getClassPool(); final Class thisClass = Bounty.class; + String replace; CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - /*CtMethod ctCheckBounty = CtMethod.make((String) - "public void checkBounty(com.wurmonline.server.players.Player player, com.wurmonline.server.creatures.Creature mob){" - + " if(!mod.sin.wyvernmods.bounty.MethodsBounty.isCombatant(this.attackers, player.getWurmId()) || mob.isPlayer() || mob.isReborn()){" - + " return;" - + " }" - + (mod.bDebug ? "logger.info(player.getName()+\" killed \"+mob.getName());" : "") - + " mod.sin.wyvernmods.bounty.MethodsBounty.checkPlayerReward(player, mob);" - + "}", ctCreature); - ctCreature.addMethod(ctCheckBounty);*/ - String replace; - replace = "" - //+ "mod.sin.wyvern.bounty.MethodsBounty.checkBounty(player, this);" - + PlayerBounty.class.getName()+".checkPlayerBounty(player, this);" + replace = PlayerBounty.class.getName()+".checkPlayerBounty(player, this);" + "$_ = $proceed($$);"; Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkCoinAward", replace); - /*ctCreature.getDeclaredMethod("modifyFightSkill").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("checkCoinAward")) { - m.replace("mod.sin.wyvern.bounty.MethodsBounty.checkBounty(player, this);" - + "$_ = $proceed($$);"); - logger.info("Instrumented checkCoinAward to call checkBounty as well."); - return; - } - } - });*/ // Die method description CtClass ctString = classPool.get("java.lang.String"); @@ -130,19 +109,8 @@ public class Bounty { String desc1 = Descriptor.ofMethod(CtClass.voidType, params1); replace = "$_ = $proceed($$);" - //+ "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);"; + LootBounty.class.getName()+".checkLootTable(this, corpse);"; Util.instrumentDescribed(thisClass, ctCreature, "die", desc1, "setRotation", replace); - /*ctCreature.getDeclaredMethod("die").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("setRotation")) { - m.replace("$_ = $proceed($$);" - + "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);"); - logger.info("Instrumented setRotation to call insertCorpseItems as well."); - return; - } - } - });*/ // doNew(int templateid, boolean createPossessions, float aPosX, float aPosY, float aRot, int layer, String name, byte gender, byte kingdom, byte ctype, boolean reborn, byte age) CtClass[] params2 = { @@ -161,56 +129,48 @@ public class Bounty { CtClass.intType }; String desc2 = Descriptor.ofMethod(ctCreature, params2); - Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); - // Debugging to show all new creatures created. - //CtMethod ctDoNew = ctCreature.getMethod("doNew", "(IZFFFILjava/lang/String;BBBZB)Lcom/wurmonline/server/creatures/Creature;"); - //ctDoNew.insertBefore("logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); - // Modify new creatures + + Util.setReason("Log new creature spawns."); + replace = "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"; + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, replace); + + Util.setReason("Modify newly created creatures."); replace = "$_ = $proceed($$);" //+ "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"; + MethodsBestiary.class.getName()+".modifyNewCreature($1);"; Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc2, "sendToWorld", replace); - /*ctDoNew.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("sendToWorld")) { - m.replace("$_ = $proceed($$);" - + "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"); - return; - } - } - });*/ - // -- Enable adjusting size for creatures -- // - CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); - Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", "{return "+MethodsBestiary.class.getName()+".getAdjustedSizeMod(this);}"); - //ctCreatureStatus.getDeclaredMethod("getSizeMod").setBody("{return mod.sin.wyvern.bestiary.MethodsBestiary.getAdjustedSizeMod(this);}"); + // -- Enable adjusting size for creatures -- // + CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); + Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", "{return "+MethodsBestiary.class.getName()+".getAdjustedSizeMod(this);}"); + //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"); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + // -- Enable adjusting color for creatures -- // + /*CtClass ctCreatureTemplate = classPool.get("com.wurmonline.server.creatures.CreatureTemplate"); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + " return "+MethodsBestiary.class.getName()+".getCreatureColorRed(this);" + "}"; - Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorRed", replace); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorRed", replace); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + " return "+MethodsBestiary.class.getName()+".getCreatureColorGreen(this);" + "}"; - Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorGreen", replace); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorGreen", replace); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + " return "+MethodsBestiary.class.getName()+".getCreatureColorBlue(this);" + "}"; - Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorBlue", replace);*/ - /*ctCreatureTemplate.getDeclaredMethod("getColorRed").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + 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);" + "}"); - ctCreatureTemplate.getDeclaredMethod("getColorGreen").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + ctCreatureTemplate.getDeclaredMethod("getColorGreen").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorGreen(this);" + "}"); - ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorBlue(this);" + "}");*/ - // -- When a creature takes damage, track the damage taken -- // - /*CtClass[] params2 = { + // -- When a creature takes damage, track the damage taken -- // + /*CtClass[] params2 = { ctCreature, ctCreature, CtClass.byteType, @@ -223,18 +183,18 @@ public class Bounty { CtClass.floatType, CtClass.booleanType, CtClass.booleanType - }; - String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); - CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine"); - replace = "if($1 != null && $2 != null){" + }; + String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); + CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine"); + replace = "if($1 != null && $2 != null){" + " "+Bounty.class.getName()+".addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);" + "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc2, replace);*/ - //ctCombatEngine.getMethod("addWound", desc2).insertBefore("if($1 != null && $2 != null){mod.sin.wyvern.bounty.MethodsBounty.addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);}"); + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc2, replace);*/ + //ctCombatEngine.getMethod("addWound", desc2).insertBefore("if($1 != null && $2 != null){mod.sin.wyvern.bounty.MethodsBounty.addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);}"); - } - catch (NotFoundException e) { - throw new HookException(e); - } + } + catch (NotFoundException e) { + throw new HookException(e); + } } } diff --git a/src/main/java/mod/sin/wyvern/EconomicChanges.java b/src/main/java/mod/sin/wyvern/EconomicChanges.java index c62fe88..94647e8 100644 --- a/src/main/java/mod/sin/wyvern/EconomicChanges.java +++ b/src/main/java/mod/sin/wyvern/EconomicChanges.java @@ -87,6 +87,10 @@ public class EconomicChanges { final Class thisClass = EconomicChanges.class; String replace; + CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); + CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + CtClass ctTrade = classPool.get("com.wurmonline.server.items.Trade"); + /* [2/4/19] Disabled - Likely causing issues with upkeep fluctuation. Util.setReason("Increase deed upkeep by modifying the amount of tiles it thinks it has."); CtClass ctGuardPlan = classPool.get("com.wurmonline.server.villages.GuardPlan"); @@ -107,23 +111,26 @@ public class EconomicChanges { replace = "{ return "+EconomicChanges.class.getName()+".getNewDisbandMoney(this, this.getVillage()); }"; Util.setBodyDeclared(thisClass, ctGuardPlan, "getDisbandMoneyLeft", replace);*/ - Util.setReason("Adjust value for certain items."); - CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); - replace = "int newVal = "+EconomicChanges.class.getName()+".getNewValue(this);" - + "if(newVal > 0){" - + " return newVal;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctItem, "getValue", replace); + if (WyvernMods.adjustSealedMapValue) { + Util.setReason("Adjust value for certain items."); + replace = "int newVal = " + EconomicChanges.class.getName() + ".getNewValue(this);" + + "if(newVal > 0){" + + " return newVal;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "getValue", replace); + } - Util.setReason("Remove trader refilling off kings coffers."); - CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - replace = "$_ = 1;"; - Util.instrumentDeclared(thisClass, ctCreature, "removeRandomItems", "nextInt", replace); + if (WyvernMods.disableTraderRefill) { + Util.setReason("Remove trader refilling off kings coffers."); + replace = "$_ = 1;"; + Util.instrumentDeclared(thisClass, ctCreature, "removeRandomItems", "nextInt", replace); + } - Util.setReason("Void 80% of all currency put into traders."); - CtClass ctTrade = classPool.get("com.wurmonline.server.items.Trade"); - replace = "$1 = "+EconomicChanges.class.getName()+".getNewShopDiff($0, $1, $0.shopDiff);"; - Util.insertBeforeDeclared(thisClass, ctTrade, "addShopDiff", replace); + if (WyvernMods.voidTraderMoney) { + Util.setReason("Void 80% of all currency put into traders."); + replace = "$1 = " + EconomicChanges.class.getName() + ".getNewShopDiff($0, $1, $0.shopDiff);"; + Util.insertBeforeDeclared(thisClass, ctTrade, "addShopDiff", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/MissionCreator.java b/src/main/java/mod/sin/wyvern/MissionCreator.java index 0aa658e..76b2097 100644 --- a/src/main/java/mod/sin/wyvern/MissionCreator.java +++ b/src/main/java/mod/sin/wyvern/MissionCreator.java @@ -23,8 +23,14 @@ public class MissionCreator { public static void pollMissions(){ int[] deityNums = { 1, 2, 3, 4, // Original Gods + }; + int[] epicEntityNums = { + 1, 2, 3, 4, // Original Gods 6, 7, 8, 9, 10, 11, 12 // Valrei Entities }; + if (WyvernMods.useValreiEntities){ + deityNums = epicEntityNums; + } EpicServerStatus es = new EpicServerStatus(); EpicMission[] missions = EpicServerStatus.getCurrentEpicMissions(); int i = 0; @@ -43,19 +49,18 @@ public class MissionCreator { i++; } if(EpicServerStatus.getCurrentEpicMissions().length >= deityNums.length){ - logger.info("All entities already have a mission. Aborting."); + logger.info("All entities already have a mission, so no new missions need to be created."); return; } i = 10; int number = 1; while(i > 0) { number = deityNums[Server.rand.nextInt(deityNums.length)]; - logger.info("Testing number "+number); if(EpicServerStatus.getEpicMissionForEntity(number) == null){ - logger.info("Has no mission, breaking loop."); + logger.info("Entity "+number+" has no mission, beginning to ."); break; }else{ - logger.info("Has mission, finding new number."); + logger.info("Entity "+number+" has a mission, finding new entity."); } i++; if(i == 0){ @@ -63,9 +68,8 @@ public class MissionCreator { return; } } - logger.info("Entity number = "+number); String entityName = Deities.getDeityName(number); - logger.info("Entity name = "+entityName); + logger.info("Creating new mission for entity "+entityName); int time = 604800; logger.info("Current epic missions: "+EpicServerStatus.getCurrentEpicMissions().length); if (EpicServerStatus.getCurrentScenario() != null) { @@ -118,35 +122,49 @@ public class MissionCreator { final Class thisClass = MissionCreator.class; String replace; - Util.setReason("Give players currency for completing a mission."); CtClass ctTriggerEffect = classPool.get("com.wurmonline.server.tutorial.TriggerEffect"); - replace = "$_ = $proceed($$);" + - MissionCreator.class.getName()+".awardMissionBonus($0);"; - Util.instrumentDeclared(thisClass, ctTriggerEffect, "effect", "addToSleep", replace); - - Util.setReason("Prevent mission creatures from spawning in water."); CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); - replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "spawnSingleCreature", "isSwimming", replace); - - Util.setReason("Modify which templates are allowed to spawn on herbivore-only epic missions."); - replace = "$_ = "+MissionCreator.class.getName()+".isMissionOkayHerbivore($0);"; - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayCreatureMission", "isHerbivore", replace); - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayTraitorMission", "isHerbivore", replace); - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSacrificeCreatureMission", "isHerbivore", replace); - - Util.setReason("Modify which templates are allowed to spawn on slay missions."); - replace = "$_ = "+MissionCreator.class.getName()+".isMissionOkaySlayable($0);"; - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayCreatureMission", "isEpicMissionSlayable", replace); - Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSacrificeCreatureMission", "isEpicMissionSlayable", replace); - - Util.setReason("Adjust which epic missions are available.."); CtClass ctEpicMissionEnum = classPool.get("com.wurmonline.server.epic.EpicMissionEnum"); - replace = "{ if($0.getMissionType() == 108 || $0.getMissionType() == 120 || $0.getMissionType() == 124){" + - " return 0;" + - "}" + - "return $0.missionChance; }"; - Util.setBodyDeclared(thisClass, ctEpicMissionEnum, "getMissionChance", replace); + + if (WyvernMods.addMissionCurrencyReward) { + Util.setReason("Give players currency for completing a mission."); + replace = "$_ = $proceed($$);" + + MissionCreator.class.getName() + ".awardMissionBonus($0);"; + Util.instrumentDeclared(thisClass, ctTriggerEffect, "effect", "addToSleep", replace); + } + + if (WyvernMods.preventMissionOceanSpawns) { + Util.setReason("Prevent mission creatures from spawning in water."); + replace = "$_ = false;"; + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "spawnSingleCreature", "isSwimming", replace); + } + + if (WyvernMods.additionalHerbivoreChecks) { + Util.setReason("Modify which templates are allowed to spawn on herbivore-only epic missions."); + replace = "$_ = " + MissionCreator.class.getName() + ".isMissionOkayHerbivore($0);"; + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayCreatureMission", "isHerbivore", replace); + Util.setReason("Modify which templates are allowed to spawn on herbivore-only epic missions."); + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayTraitorMission", "isHerbivore", replace); + Util.setReason("Modify which templates are allowed to spawn on herbivore-only epic missions."); + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSacrificeCreatureMission", "isHerbivore", replace); + } + + if (WyvernMods.additionalMissionSlayableChecks) { + Util.setReason("Modify which templates are allowed to spawn on slay missions."); + replace = "$_ = " + MissionCreator.class.getName() + ".isMissionOkaySlayable($0);"; + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSlayCreatureMission", "isEpicMissionSlayable", replace); + Util.setReason("Modify which templates are allowed to spawn on slay missions."); + Util.instrumentDeclared(thisClass, ctEpicServerStatus, "createSacrificeCreatureMission", "isEpicMissionSlayable", replace); + } + + if (WyvernMods.disableEpicMissionTypes) { + Util.setReason("Adjust which epic missions are available."); + replace = "{ if($0.getMissionType() == 108 || $0.getMissionType() == 120 || $0.getMissionType() == 124){" + + " return 0;" + + "}" + + "return $0.missionChance; }"; + Util.setBodyDeclared(thisClass, ctEpicMissionEnum, "getMissionChance", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/MountedChanges.java b/src/main/java/mod/sin/wyvern/MountedChanges.java index d3eeecb..62a40b6 100644 --- a/src/main/java/mod/sin/wyvern/MountedChanges.java +++ b/src/main/java/mod/sin/wyvern/MountedChanges.java @@ -114,14 +114,19 @@ public class MountedChanges { final Class thisClass = MountedChanges.class; String replace; - Util.setReason("Scaling horse speed."); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - replace = "{ return "+MountedChanges.class.getName()+".newMountSpeedMultiplier(this, $1); }"; - Util.setBodyDeclared(thisClass, ctCreature, "getMountSpeedPercent", replace); - Util.setReason("Force mount speed change check on damage."); - replace = "forceMountSpeedChange();"; - Util.insertBeforeDeclared(thisClass, ctCreature, "setWounded", replace); + if (WyvernMods.newMountSpeedScaling) { + Util.setReason("New mount speed scaling."); + replace = "{ return " + MountedChanges.class.getName() + ".newMountSpeedMultiplier(this, $1); }"; + Util.setBodyDeclared(thisClass, ctCreature, "getMountSpeedPercent", replace); + } + + if (WyvernMods.updateMountSpeedOnDamage) { + Util.setReason("Force mount speed change check on damage."); + replace = "forceMountSpeedChange();"; + Util.insertBeforeDeclared(thisClass, ctCreature, "setWounded", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/RareSpawns.java b/src/main/java/mod/sin/wyvern/RareSpawns.java index 8baa2c5..190a06a 100644 --- a/src/main/java/mod/sin/wyvern/RareSpawns.java +++ b/src/main/java/mod/sin/wyvern/RareSpawns.java @@ -99,60 +99,4 @@ public class RareSpawns { } } } - - public static void preInit(){ - try { - ClassPool classPool = HookManager.getInstance().getClassPool(); - Class thisClass = RareSpawns.class; - String replace; - - /*Util.setReason("Disable casting Smite on titans."); - CtClass ctSmite = classPool.get("com.wurmonline.server.spells.Smite"); - replace = "if("+RareSpawns.class.getName()+".isRareCreature($3)){" - + " $2.getCommunicator().sendNormalServerMessage(\"This creature is immune to Smite.\");" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctSmite, "precondition", replace);*/ - - Util.setReason("Disable casting Worm Brains on titans."); - CtClass ctWormBrains = classPool.get("com.wurmonline.server.spells.WormBrains"); - replace = "if("+RareSpawns.class.getName()+".isRareCreature($3)){" - + " $2.getCommunicator().sendNormalServerMessage(\"This creature is immune to Worm Brains.\");" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctWormBrains, "precondition", replace); - - /* Disabled in Wurm Unlimited 1.9 - No longer necessary while using DUSKombat. - - Util.setReason("Increase titan extra damage to pets."); - 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); - replace = "if($2.isDominated() && $1 != null && "+RareSpawns.class.getName()+".isRareCreature($1)){" + - //" logger.info(\"Detected rare spawn hit on a pet. Adding damage.\");" + - " $5 = $5 * 2d;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ - }catch (NotFoundException e) { - throw new HookException(e); - } - } } diff --git a/src/main/java/mod/sin/wyvern/SupplyDepots.java b/src/main/java/mod/sin/wyvern/SupplyDepots.java index 48b113f..b8f2390 100644 --- a/src/main/java/mod/sin/wyvern/SupplyDepots.java +++ b/src/main/java/mod/sin/wyvern/SupplyDepots.java @@ -1,5 +1,26 @@ package mod.sin.wyvern; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.*; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.Creatures; +import com.wurmonline.server.economy.Economy; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.zones.Zones; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import mod.sin.items.ArenaSupplyDepot; +import mod.sin.items.caches.*; +import mod.sin.lib.Util; +import mod.sin.wyvern.util.ItemUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; +import org.gotti.wurmunlimited.modsupport.ModSupportDb; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -7,41 +28,10 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.logging.Logger; -import com.wurmonline.server.economy.Economy; -import mod.sin.items.SorceryFragment; -import org.gotti.wurmunlimited.modloader.classhooks.HookException; -import org.gotti.wurmunlimited.modloader.classhooks.HookManager; - -import com.wurmonline.mesh.Tiles; -import com.wurmonline.server.FailedException; -import com.wurmonline.server.Items; -import com.wurmonline.server.Players; -import com.wurmonline.server.Server; -import com.wurmonline.server.Servers; -import com.wurmonline.server.TimeConstants; -import com.wurmonline.server.creatures.Creature; -import com.wurmonline.server.creatures.Creatures; -import com.wurmonline.server.items.Item; -import com.wurmonline.server.items.ItemFactory; -import com.wurmonline.server.items.ItemList; -import com.wurmonline.server.items.NoSuchTemplateException; -import com.wurmonline.server.players.Player; -import com.wurmonline.server.zones.Zones; - -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.NotFoundException; -import mod.sin.items.ArenaSupplyDepot; -import mod.sin.items.caches.*; -import mod.sin.wyvern.util.ItemUtil; -import org.gotti.wurmunlimited.modsupport.ModSupportDb; - public class SupplyDepots { private static Logger logger = Logger.getLogger(SupplyDepots.class.getName()); public static ArrayList depots = new ArrayList<>(); public static Creature host = null; - public static final long depotRespawnTime = TimeConstants.HOUR_MILLIS*11L; public static long lastSpawnedDepot = 0; protected static boolean initalizedSupplyDepot = false; @@ -90,6 +80,9 @@ public class SupplyDepots { } } public static void sendDepotEffect(Player player, Item depot){ + if (!WyvernMods.useSupplyDepotLights){ + return; + } player.getCommunicator().sendAddEffect(depot.getWurmId(), (byte) 25, depot.getPosX(), depot.getPosY(), depot.getPosZ(), (byte) 0); } public static void sendDepotEffectsToPlayer(Player player){ @@ -150,7 +143,7 @@ public class SupplyDepots { MiscChanges.sendGlobalFreedomChat(host, "Greetings! I'll be your host, informing you of the next depot to appear over here on the Arena!", 255, 128, 0); } } - if(System.currentTimeMillis() > lastSpawnedDepot + depotRespawnTime){ + if(System.currentTimeMillis() > lastSpawnedDepot + WyvernMods.depotRespawnTime){ logger.info("No Depots were found, and the timer has expired. Spawning a new one."); boolean spawned = false; int i = 0; @@ -191,7 +184,7 @@ public class SupplyDepots { logger.warning("Could not find a valid location within 20 tries for a supply depot."); } }else if(host != null){ - long timeleft = (lastSpawnedDepot + depotRespawnTime) - System.currentTimeMillis(); + long timeleft = (lastSpawnedDepot + WyvernMods.depotRespawnTime) - System.currentTimeMillis(); long minutesLeft = timeleft/TimeConstants.MINUTE_MILLIS; if(minutesLeft > 0){ if(minutesLeft == 4){ @@ -209,13 +202,12 @@ public class SupplyDepots { } public static long lastAttemptedDepotCapture = 0; - public static final long captureMessageInterval = TimeConstants.MINUTE_MILLIS*3L; public static void broadcastCapture(Creature performer){ MiscChanges.sendServerTabMessage("arena", performer.getName()+" has claimed an Arena depot!", 255, 128, 0); MiscChanges.sendGlobalFreedomChat(performer, performer.getName()+" has claimed an Arena depot!", 255, 128, 0); } public static void maybeBroadcastOpen(Creature performer){ - if(System.currentTimeMillis() > lastAttemptedDepotCapture + captureMessageInterval){ + if(System.currentTimeMillis() > lastAttemptedDepotCapture + WyvernMods.captureMessageInterval){ MiscChanges.sendServerTabMessage("arena", performer.getName()+" is beginning to capture an Arena depot!", 255, 128, 0); MiscChanges.sendGlobalFreedomChat(performer, performer.getName()+" is beginning to capture an Arena depot!", 255, 128, 0); lastAttemptedDepotCapture = System.currentTimeMillis(); @@ -285,13 +277,20 @@ public class SupplyDepots { public static void preInit(){ try{ ClassPool classPool = HookManager.getInstance().getClassPool(); - - // - Add light effects for the supply depots, since they are unique - // + Class thisClass = SupplyDepots.class; + String replace; + CtClass ctPlayers = classPool.get("com.wurmonline.server.Players"); - ctPlayers.getDeclaredMethod("sendAltarsToPlayer").insertBefore("mod.sin.wyvern.SupplyDepots.sendDepotEffectsToPlayer($1);"); + + if (WyvernMods.useSupplyDepotLights) { + Util.setReason("Add depot lights for players."); + replace = "mod.sin.wyvern.SupplyDepots.sendDepotEffectsToPlayer($1);"; + Util.insertBeforeDeclared(thisClass, ctPlayers, "sendAltarsToPlayer", replace); + //ctPlayers.getDeclaredMethod("sendAltarsToPlayer").insertBefore("mod.sin.wyvern.SupplyDepots.sendDepotEffectsToPlayer($1);"); + } - }catch (CannotCompileException | NotFoundException e) { - throw new HookException(e); + }catch (NotFoundException e) { + e.printStackTrace(); } } } diff --git a/src/main/java/mod/sin/wyvern/TeleportHandler.java b/src/main/java/mod/sin/wyvern/TeleportHandler.java index 7d213b5..e008c57 100644 --- a/src/main/java/mod/sin/wyvern/TeleportHandler.java +++ b/src/main/java/mod/sin/wyvern/TeleportHandler.java @@ -104,15 +104,18 @@ public class TeleportHandler { final Class thisClass = TeleportHandler.class; String replace; - Util.setReason("Custom teleportation system for Arena teleport/escape."); CtClass ctPlayerMetaData = classPool.get("com.wurmonline.server.players.PlayerMetaData"); - replace = "logger.info(\"posx = \"+this.posx+\", posy = \"+this.posy);" + - "if(this.posx >= 4000f && this.posx <= 4050f && this.posy >= 4000f && this.posy <= 4050f){" + - " this.posx = "+TeleportHandler.class.getName()+".getTeleportPosX(this.wurmid);" + - " this.posy = "+TeleportHandler.class.getName()+".getTeleportPosY(this.wurmid);" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctPlayerMetaData, "save", "getPosition", replace); + + if (WyvernMods.useArenaTeleportMethod) { + Util.setReason("Custom teleportation system for Arena teleport/escape."); + replace = "logger.info(\"posx = \"+this.posx+\", posy = \"+this.posy);" + + "if(this.posx >= 4000f && this.posx <= 4050f && this.posy >= 4000f && this.posy <= 4050f){" + + " this.posx = " + TeleportHandler.class.getName() + ".getTeleportPosX(this.wurmid);" + + " this.posy = " + TeleportHandler.class.getName() + ".getTeleportPosY(this.wurmid);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctPlayerMetaData, "save", "getPosition", replace); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/Titans.java b/src/main/java/mod/sin/wyvern/Titans.java index 1cf104f..aa6369a 100644 --- a/src/main/java/mod/sin/wyvern/Titans.java +++ b/src/main/java/mod/sin/wyvern/Titans.java @@ -716,9 +716,7 @@ public class Titans { } public static ArrayList titans = new ArrayList<>(); - public static long lastPolledTitanSpawn = 0; public static long lastSpawnedTitan = 0; - public static final long titanRespawnTime = TimeConstants.HOUR_MILLIS*80L; public static void addTitan(Creature mob){ if(isTitan(mob) && !titans.contains(mob)){ titans.add(mob); @@ -755,7 +753,7 @@ public class Titans { } } if(titans.isEmpty()){ - if(lastSpawnedTitan + titanRespawnTime < System.currentTimeMillis()){ + if(lastSpawnedTitan + WyvernMods.titanRespawnTime < System.currentTimeMillis()){ logger.info("No Titan was found, and the timer has expired. Spawning a new one."); boolean found = false; int spawnX = 2048; @@ -803,7 +801,6 @@ public class Titans { for(Creature c : titans){ c.healRandomWound(1000); } - lastPolledTitanSpawn = System.currentTimeMillis(); } } @@ -813,68 +810,20 @@ public class Titans { Class thisClass = Titans.class; String replace; - Util.setReason("Disable natural regeneration on titans."); CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound"); - replace = "if(!"+Titans.class.getName()+".isTitan(this.creature)){" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace); - Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace); - Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace); - - /*Util.setReason("Disable casting Smite on titans."); - CtClass ctSmite = classPool.get("com.wurmonline.server.spells.Smite"); - replace = "if("+Titans.class.getName()+".isTitan($3)){" - + " $2.getCommunicator().sendNormalServerMessage(\"You cannot smite a Titan!\");" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctSmite, "precondition", replace);*/ - - /* Disabled in Wurm Unlimited 1.9 - No longer necessary as spells are balanced. - - Util.setReason("Disable casting Worm Brains on titans."); - CtClass ctWormBrains = classPool.get("com.wurmonline.server.spells.WormBrains"); - replace = "if("+Titans.class.getName()+".isTitan($3)){" - + " $2.getCommunicator().sendNormalServerMessage(\"Titans are immune to that spell.\");" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctWormBrains, "precondition", replace);*/ - CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - Util.setReason("Add spell resistance to titans."); - replace = "if("+Titans.class.getName()+".isTitan(this)){" + - " return 0.05f;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "addSpellResistance", replace); - /* Disabled in Wurm Unlimited 1.9 - No longer needed while using DUSKombat. - - Util.setReason("Increase titan extra damage to pets."); - 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); - replace = "if($2.isDominated() && $1 != null && "+Titans.class.getName()+".isTitan($1)){" + - " logger.info(\"Detected titan hit on a pet. Adding damage.\");" + - " $5 = $5 * 2d;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/ + if (WyvernMods.disableTitanNaturalRegeneration) { + Util.setReason("Disable natural regeneration on titans."); + replace = "if(!" + Titans.class.getName() + ".isTitan(this.creature)){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace); + Util.setReason("Disable natural regeneration on titans."); + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace); + Util.setReason("Disable natural regeneration on titans."); + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace); + } }catch (NotFoundException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 375756c..924ba91 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -220,6 +220,51 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static long knowledgeInfoCreatureCooldown = 64800000L; // 18 hours default public static long knowledgeInfoTileCooldown = 64800000L; // 18 hours default + // Titan Module Configuration + public static boolean enableTitanModule = true; + public static boolean disableTitanNaturalRegeneration = true; + public static long pollTitanSpawnTime = TimeConstants.MINUTE_MILLIS*2; + public static long pollTitanTime = TimeConstants.SECOND_MILLIS; + public static long titanRespawnTime = TimeConstants.HOUR_MILLIS*80L; + + // Rare Spawn Module Configuration + public static boolean enableRareSpawnModule = true; + public static long pollRareSpawnTime = TimeConstants.MINUTE_MILLIS*5; + + // Mission Module Configuration + public static boolean enableMissionModule = true; + public static boolean enableNewMissionCreator = true; + public static long pollMissionCreatorTime = TimeConstants.HOUR_MILLIS*4; + public static boolean useValreiEntities = true; + public static boolean addMissionCurrencyReward = true; + public static boolean preventMissionOceanSpawns = true; + public static boolean additionalHerbivoreChecks = true; + public static boolean additionalMissionSlayableChecks = true; + public static boolean disableEpicMissionTypes = true; + + // Mounted Module Configuration + public static boolean enableMountedModule = true; + public static boolean newMountSpeedScaling = true; + public static boolean updateMountSpeedOnDamage = true; + public static boolean allowBisonMounts = true; + + // Teleport Module Configuration + public static boolean enableTeleportModule = true; + public static boolean useArenaTeleportMethod = true; + + // Economic Module Configuration + public static boolean enableEconomyModule = true; + public static boolean adjustSealedMapValue = true; + public static boolean disableTraderRefill = true; + public static boolean voidTraderMoney = true; + + // Supply Depot Module Configuration + public static boolean enableSupplyDepotModule = true; + public static boolean useSupplyDepotLights = true; + public static long pollDepotTime = TimeConstants.MINUTE_MILLIS; + public static long captureMessageInterval = TimeConstants.MINUTE_MILLIS*3L; + public static long depotRespawnTime = TimeConstants.HOUR_MILLIS*11L; + // Treasure Chest Loot Module Configuration public static boolean enableTreasureChestLootModule = true; @@ -460,6 +505,51 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea knowledgeInfoCreatureCooldown = Prop.getLongProperty("knowledgeInfoCreatureCooldown", knowledgeInfoCreatureCooldown); knowledgeInfoTileCooldown = Prop.getLongProperty("knowledgeInfoTileCooldown", knowledgeInfoTileCooldown); + // Titan Module + enableTitanModule = Prop.getBooleanProperty("enableTitanModule", enableTitanModule); + disableTitanNaturalRegeneration = Prop.getBooleanProperty("disableTitanNaturalRegeneration", disableTitanNaturalRegeneration); + pollTitanSpawnTime = Prop.getLongProperty("pollTitanSpawnTime", pollTitanSpawnTime); + pollTitanTime = Prop.getLongProperty("pollTitanTime", pollTitanTime); + titanRespawnTime = Prop.getLongProperty("titanRespawnTime", titanRespawnTime); + + // Rare Spawn Module + enableRareSpawnModule = Prop.getBooleanProperty("enableRareSpawnModule", enableRareSpawnModule); + pollRareSpawnTime = Prop.getLongProperty("pollRareSpawnTime", pollRareSpawnTime); + + // Mission Module + enableMissionModule = Prop.getBooleanProperty("enableMissionModule", enableMissionModule); + enableNewMissionCreator = Prop.getBooleanProperty("enableNewMissionCreator", enableNewMissionCreator); + pollMissionCreatorTime = Prop.getLongProperty("pollMissionCreatorTime", pollMissionCreatorTime); + useValreiEntities = Prop.getBooleanProperty("useValreiEntities", useValreiEntities); + addMissionCurrencyReward = Prop.getBooleanProperty("addMissionCurrencyReward", addMissionCurrencyReward); + preventMissionOceanSpawns = Prop.getBooleanProperty("preventMissionOceanSpawns", preventMissionOceanSpawns); + additionalHerbivoreChecks = Prop.getBooleanProperty("additionalHerbivoreChecks", additionalHerbivoreChecks); + additionalMissionSlayableChecks = Prop.getBooleanProperty("additionalMissionSlayableChecks", additionalMissionSlayableChecks); + disableEpicMissionTypes = Prop.getBooleanProperty("disableEpicMissionTypes", disableEpicMissionTypes); + + // Mounted Module + enableMountedModule = Prop.getBooleanProperty("enableMountedModule", enableMountedModule); + newMountSpeedScaling = Prop.getBooleanProperty("newMountSpeedScaling", newMountSpeedScaling); + updateMountSpeedOnDamage = Prop.getBooleanProperty("updateMountSpeedOnDamage", updateMountSpeedOnDamage); + allowBisonMounts = Prop.getBooleanProperty("allowBisonMounts", allowBisonMounts); + + // Teleport Module + enableTeleportModule = Prop.getBooleanProperty("enableTeleportModule", enableTeleportModule); + useArenaTeleportMethod = Prop.getBooleanProperty("useArenaTeleportMethod", useArenaTeleportMethod); + + // Economy Module + enableEconomyModule = Prop.getBooleanProperty("enableEconomyModule", enableEconomyModule); + adjustSealedMapValue = Prop.getBooleanProperty("adjustSealedMapValue", adjustSealedMapValue); + disableTraderRefill = Prop.getBooleanProperty("disableTraderRefill", disableTraderRefill); + voidTraderMoney = Prop.getBooleanProperty("voidTraderMoney", voidTraderMoney); + + // Supply Depot Module + enableSupplyDepotModule = Prop.getBooleanProperty("enableSupplyDepotModule", enableSupplyDepotModule); + useSupplyDepotLights = Prop.getBooleanProperty("useSupplyDepotLights", useSupplyDepotLights); + pollDepotTime = Prop.getLongProperty("pollDepotTime", pollDepotTime); + captureMessageInterval = Prop.getLongProperty("captureMessageInterval", captureMessageInterval); + depotRespawnTime = Prop.getLongProperty("depotRespawnTime", depotRespawnTime); + // Treasure Chest Loot Module enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule); @@ -785,9 +875,61 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea } } - logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); + logger.info("Titan Module: "+enableTitanModule); + if (enableTitanModule){ + logger.info("Disable Titan Natural Regeneration: "+disableTitanNaturalRegeneration); + logger.info("Poll Titan Spawn Timer: "+pollTitanSpawnTime); + logger.info("Poll Titan Timer: "+pollTitanTime); + logger.info("Titan Respawn Timer: "+titanRespawnTime); + } - //this.logger.log(Level.INFO, "Property: " + this.somevalue); + logger.info("Rare Spawn Module: "+enableRareSpawnModule); + if (enableRareSpawnModule){ + logger.info("Poll Rare Spawn Timer: "+pollRareSpawnTime); + } + + logger.info("Mission Module: "+enableMissionModule); + if (enableMissionModule){ + logger.info("New Mission Creator: "+enableNewMissionCreator); + if (enableNewMissionCreator){ + logger.info("New Mission Creator Timer: " + pollMissionCreatorTime); + logger.info("Use Valrei Entities: "+useValreiEntities); + } + logger.info("Add Mission Currency Reward: "+addMissionCurrencyReward); + logger.info("Prevent Ocean Mission Spawns: "+preventMissionOceanSpawns); + logger.info("Additional Herbivore Checks: "+additionalHerbivoreChecks); + logger.info("Additional Mission Slayable Checks: "+additionalMissionSlayableChecks); + logger.info("Disable Epic Mission Types: "+disableEpicMissionTypes); + } + + logger.info("Mounted Module: "+enableMountedModule); + if (enableMountedModule){ + logger.info("New Mount Speed Scaling: "+newMountSpeedScaling); + logger.info("Update Mount Speed On Damage: "+updateMountSpeedOnDamage); + logger.info("Allow Bison Mounts: "+allowBisonMounts); + } + + logger.info("Teleport Module: "+enableTeleportModule); + if (enableTeleportModule){ + logger.info("Use Arena Teleport Method: "+useArenaTeleportMethod); + } + + logger.info("Economy Module: "+enableEconomyModule); + if (enableEconomyModule){ + logger.info("Adjust Sealed Map Value: "+adjustSealedMapValue); + logger.info("Disable Trader Refill: "+disableTraderRefill); + logger.info("Void Trader Money: "+voidTraderMoney); + } + + logger.info("Supply Depot Module: "+enableSupplyDepotModule); + if (enableSupplyDepotModule){ + logger.info("Use Supply Depot Lights: "+useSupplyDepotLights); + logger.info("Poll Depot Timer: "+pollDepotTime); + logger.info("Capture Message Interval: "+captureMessageInterval); + logger.info("Depot Respawn Timer: "+depotRespawnTime); + } + + logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); } public static void handleExamine(Creature performer, Item target) { @@ -842,27 +984,54 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Mastercraft.preInit(); } + // Skill Module Pre-Init if (enableSkillModule) { SkillChanges.preInit(); } + // Meditation Module Pre-Init if (enableMeditationModule) { MeditationPerks.preInit(); } + // Titan Module Pre-Init + if (enableTitanModule) { + Titans.preInit(); + } + + // Mission Module Pre-Init + if (enableMissionModule) { + MissionCreator.preInit(); + } + + // Mounted Module Pre-Init + if (enableMountedModule) { + MountedChanges.preInit(); + } + + // Teleport Module Pre-Init + if (enableTeleportModule) { + TeleportHandler.preInit(); + } + + // Economy Module Pre-Init + if (enableEconomyModule) { + EconomicChanges.preInit(); + } + + // Supply Depot Module Pre-Init + if (enableSupplyDepotModule) { + SupplyDepots.preInit(); + } + // Treasure Chest Loot Module Pre-Init if (enableTreasureChestLootModule) { TreasureChests.preInit(); } - Titans.preInit(); - RareSpawns.preInit(); - TeleportHandler.preInit(); MethodsBestiary.preInit(); - MissionCreator.preInit(); - MountedChanges.preInit(); - EconomicChanges.preInit(); - SupplyDepots.preInit(); + + // Only clears responses, doesn't have any effect. Harmless to run even if key fragments are not used. KeyEvent.preInit(); // Bloodlust might no longer be necessary. Code remains for reference. @@ -907,7 +1076,10 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea // Vanilla: logger.info("Registering Vanilla creature changes."); - ModCreatures.addCreature(new Bison()); + if (enableMountedModule && allowBisonMounts) { + logger.info("Allowing Bison to be mounted."); + ModCreatures.addCreature(new Bison()); + } // Epic: logger.info("Registering Epic creatures."); @@ -1054,19 +1226,15 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static long lastSecondPolled = 0; public static long lastPolledTitanSpawn = 0; - public static final long pollTitanSpawnTime = TimeConstants.MINUTE_MILLIS*2; public static long lastPolledTitans = 0; - public static final long pollTitanTime = TimeConstants.SECOND_MILLIS; public static long lastPolledDepots = 0; - public static final long pollDepotTime = TimeConstants.MINUTE_MILLIS; public static long lastPolledRareSpawns = 0; - public static final long pollRareSpawnTime = TimeConstants.MINUTE_MILLIS*5; public static long lastPolledEternalReservoirs = 0; public static final long pollEternalReservoirTime = TimeConstants.MINUTE_MILLIS*10; public static long lastPolledMissionCreator = 0; - public static final long pollMissionCreatorTime = TimeConstants.HOUR_MILLIS*4; + /* Disabled for now, might need to be revisited. public static long lastPolledBloodlust = 0; - public static final long pollBloodlustTime = TimeConstants.MINUTE_MILLIS; + public static final long pollBloodlustTime = TimeConstants.MINUTE_MILLIS;*/ public static long lastPolledUniqueRegeneration = 0; public static final long pollUniqueRegenerationTime = TimeConstants.SECOND_MILLIS; public static long lastPolledUniqueCollection = 0; @@ -1076,19 +1244,19 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void onServerPoll() { if((lastSecondPolled + TimeConstants.SECOND_MILLIS) < System.currentTimeMillis()){ - if(lastPolledDepots + pollDepotTime < System.currentTimeMillis()){ + if(enableSupplyDepotModule && lastPolledDepots + pollDepotTime < System.currentTimeMillis()){ SupplyDepots.pollDepotSpawn(); lastPolledDepots += pollDepotTime; } - if(lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){ + if(enableTitanModule && lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){ Titans.pollTitanSpawn(); lastPolledTitanSpawn += pollTitanSpawnTime; } - if(lastPolledTitans + pollTitanTime < System.currentTimeMillis()){ + if(enableTitanModule && lastPolledTitans + pollTitanTime < System.currentTimeMillis()){ Titans.pollTitans(); lastPolledTitans += pollTitanTime; } - if(lastPolledRareSpawns + pollRareSpawnTime < System.currentTimeMillis()){ + if(enableRareSpawnModule && lastPolledRareSpawns + pollRareSpawnTime < System.currentTimeMillis()){ RareSpawns.pollRareSpawns(); lastPolledRareSpawns += pollRareSpawnTime; } @@ -1096,14 +1264,15 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Soulstealing.pollSoulForges(); lastPolledEternalReservoirs += pollEternalReservoirTime; } - if(lastPolledMissionCreator + pollMissionCreatorTime < System.currentTimeMillis()){ + if(enableMissionModule && enableNewMissionCreator && lastPolledMissionCreator + pollMissionCreatorTime < System.currentTimeMillis()){ MissionCreator.pollMissions(); lastPolledMissionCreator += pollMissionCreatorTime; } + /* Disabled for now, might need to be revisited. if(lastPolledBloodlust + pollBloodlustTime < System.currentTimeMillis()){ Bloodlust.pollLusts(); lastPolledBloodlust += pollBloodlustTime; - } + }*/ if(WyvernMods.useStaticLegendaryRegeneration && lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){ CombatChanges.pollUniqueRegeneration(); lastPolledUniqueRegeneration += pollUniqueRegenerationTime; @@ -1129,7 +1298,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea lastPolledRareSpawns = System.currentTimeMillis(); lastPolledEternalReservoirs = System.currentTimeMillis(); lastPolledMissionCreator = System.currentTimeMillis(); - lastPolledBloodlust = System.currentTimeMillis(); + //lastPolledBloodlust = System.currentTimeMillis(); lastPolledUniqueRegeneration = System.currentTimeMillis(); lastPolledUniqueCollection = System.currentTimeMillis(); lastPolledTerrainSmooth = System.currentTimeMillis(); From e865977407ae80d900264aec45d496ebbd9e4e91 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Tue, 14 May 2019 15:19:18 -0400 Subject: [PATCH 7/8] WyvernMods Configurable Final Phase --- mods/WyvernMods.properties | 317 +++++++++ .../java/mod/sin/creatures/WyvernBlack.java | 8 +- .../MethodsBestiary.java => Bestiary.java} | 401 +++++++----- src/main/java/mod/sin/wyvern/Bounty.java | 65 +- src/main/java/mod/sin/wyvern/ItemMod.java | 275 +++++--- src/main/java/mod/sin/wyvern/Mastercraft.java | 11 - src/main/java/mod/sin/wyvern/MiscChanges.java | 13 + src/main/java/mod/sin/wyvern/WyvernMods.java | 601 ++++++++++++++---- 8 files changed, 1243 insertions(+), 448 deletions(-) rename src/main/java/mod/sin/wyvern/{bestiary/MethodsBestiary.java => Bestiary.java} (74%) diff --git a/mods/WyvernMods.properties b/mods/WyvernMods.properties index baa3cd3..9cbd13f 100644 --- a/mods/WyvernMods.properties +++ b/mods/WyvernMods.properties @@ -242,6 +242,12 @@ disableSmeltingPots=true hideSorceryBuffBar=true #sqlAchievementFix: Fixes the errors that occur with achievements in SQL in WU 1.9. sqlAchievementFix=true +#changePumpkinKingTitle: Changes the Pumpkin King title (100 farming) for females from "Pumpkin King" to "Pumpkin Queen" +changePumpkinKingTitle=true +#changeDeityPassives: Changes some of the deity passives for demigods with ID 101 and 102. +# This option is specifically for compatibility to Revenant for the time being. +changeDeityPassives=true +#TODO: Remove this option and add deity passive configuration to Spellcraft. ## >> END MISCELLANEOUS CHANGES MODULE << ## @@ -929,6 +935,317 @@ depotRespawnTime=39600000 ## >> END SUPPLY DEPOT MODULE << ## +## >> BESTIARY MODULE << ## +## The Bestiary Module controls a variety of features regarding creatures in Wurm. +## This module includes options that controls creature attributes, changing their behavior, and additions of new creatures. +enableBestiaryModule=true + +#fixSacrificingStrongCreatures: Removes the ability to sacrifice strong modded creatures such as titans and rare spawns. +fixSacrificingStrongCreatures=true +#disableAfkTraining: Disables afk training by doing combat with a creature while not targeting it. +# This is usually called "shield training" when you engage in combat with a creature then target another to prevent attacking it back. +# With this enabled, it will prevent players from gaining skill from a creature unless they are targeting it as well. +# If DUSKombat is active, this is built into it. Probably not necessary to enable if you have DUSKombat installed, but will do no harm if enabled. +disableAfkTraining=true +#fixChargersWalkingThroughWalls: By default, since Chargers are considered ghost units like templars, they are allowed to walk through walls. +# This option will add a hard override to their pathing and prevent them from walking through walls despite being ghosts. +fixChargersWalkingThroughWalls=true +#conditionWildCreatures: Adds conditions randomly to creatures spawned naturally in the wild. +# By default, only creatures spawned from a den will have a condition (greenish, angry, etc.) +# This option will allow *any* natural spawn to have a condition. +# Will not affect creatures which cannot have a condition by default (such as horses, pigs, etc) +# Chance is 1/5 for a random condition, and 1/250 to be a champion. +conditionWildCreatures=true +#allowGhostArchery: Allows archery against targets marked as "ghosts" - including chargers and spirit templars. +# This is done to prevent players from mounting chargers and being immune to archery to dismount them. +allowGhostArchery=true +#disableArcheryOnStrongCreatures: Disables archery against strong creatures such as titans and rare spawns. +disableArcheryOnStrongCreatures=true +#genesisEnchantedGrassNewborns: When a new creature is born on enchanted grass, it will automatically remove a negative trait. +genesisEnchantedGrassNewborns=true +#useCustomCorpseSizes: Custom creatures can sometimes have poor corpse sizes when slain. +# This option fixes that issue by utilizing custom corpse sizes when they die and adjusting the size to be closer to their normal size. +useCustomCorpseSizes=true +#allowCustomCreatureBreedNames: Allows some custom creatures (Chargers) to have breeding names similar to horses. +allowCustomCreatureBreedNames=true +#allowGhostBreeding: Allows breeding of ghost creatures (such as Chargers). +allowGhostBreeding=true +#allowGhostCorpses: Allows ghost creatures (Chargers and Spirit Trolls) to drop corpses. +allowGhostCorpses=true +#useCustomCreatureSizes: Adjusts the size of creatures when they're alive. +# This makes wyverns smaller than drakes, forest spiders smaller than large spiders, etc. +useCustomCreatureSizes=true +#TODO: Allow custom settings for unit sizes. +#useCustomCreatureSFX: Uses special effects to augment some of the custom creatures (such as fire crabs). +useCustomCreatureSFX=true +#preventLegendaryHitching: When a player dominates a legendary creature such as a dragon, it can sometimes be hitched. +# When hitched, it uses the body strength of the creature to determine speed of the vehicle. +# This usually results in vehicles that go ~30-40kmh. This option prevents this instance from occurring. +preventLegendaryHitching=true +#modifyNewCreatures: Modifies custom creatures in a variety of ways to make sure they function properly. +# Also handles announcement of some custom creatures such as titans. +modifyNewCreatures=true +#logCreatureSpawns: Logs all spawns of creatures to the server log. This is purely informative and has no gameplay effect. +logCreatureSpawns=true +#allowEpicCreatureNaturalSpawns: Allows Sol Demons, Lava Fiends, and Worgs to spawn naturally in the world. +# Sol Demons and Lava Fiends spawn on sand. Worgs spawn on grass and steppe. +allowEpicCreatureNaturalSpawns=true +#TODO: Enable customization of the spawn rates for creatures individually. + +# > CUSTOM CREATURES < # +# Custom Creatures are new creatures independent from vanilla ones that are designed to add additional content for players. +enableCustomCreatures=true +#TODO: This module needs to be restructured to allow configuration of each creature independently. + +#enableWyverns: Enables the Black, Blue, Green, Red, and White Wyvern creatures. +# These are difficult creatures that spawn naturally on unique tilesets. +# All are able to be mounted and hitched. +# They are unable to spawn on PvP servers. +enableWyverns=true +#enableFlavorMobs: Enables the Avenger, Fire Crab, Forest Spider, Giant, Charger, Horned Pony, Large Boar, and Spirit Troll creatures. +# These creatures all spawn naturally. +# Giants and Avengers are unable to spawn on PvP servers. +enableFlavorMobs=true +#enableEventMobs: Enables the Ice Cat, Fire Giant, Terror, and Guardian of Magranon event creatures. +# These creatures do not spawn naturally. +enableEventMobs=true +#enableRareSpawns: Enables the Reaper and Spectral Drake creatures. +# These creatures only spawn naturally if using the Rare Spawns module. +enableRareSpawns=true +#enableCustomLegendaries: Enables the Facebreyker legendary creature. +# Only spawns naturally if using the Misc Changes addition to add to the spawn list. +enableCustomLegendaries=true +#enableTitans: Enables the Ifrit and Lilith titan creatures. Also includes their additional creatures. +# Only spawns naturally if configured to do so through the Titan module. +enableTitans=true + +# > END CUSTOM CREATURES < # + +## >> END BESTIARY MODULE << ## + +## >> BOUNTY MODULE << ## +## The Bounty Module handles effects and rewards that occur when a player slays a creature. +enableBountyModule=true +#TODO: This module needs to be restructured to give more options for what type of drops and rewards occur. + +#usePlayerBounty: Allows players to be rewarded directly when they slay a creature. +usePlayerBounty=true +#TODO: Give further options for player bounty. +#useLootTable: Allows creatures to drop rewards on their corpses. +useLootTable=true +#TODO: Give further options for loot tables. + +## >> END BOUNTY MODULE << ## + +## >> ITEM MODULE << ## +## The Item Module handles the implementation of new items and their effects. +## It also grants options that change default items in a variety of ways. +enableItemModule=true +#TODO: This module needs to be restructured to give more options regarding each individual item instead of using true/false. + +#combineLeather: Allows leather to be combined. +# Will prevent improvement with leather lower than item QL unless the Misc Changes configuration is enabled. +combineLeather=true +#combineLogs: Allows logs to be combined. +combineLogs=true +#reduceLogVolume: Reduces the volume of logs by 50%, making twice as many fit in bulk containers. +# This also makes them easier to fit into containers that otherwise would not hold them. +reduceLogVolume=true +#reduceKindlingVolume: Reduces the volume of kindling by 75%, preventing them from being technically larger than logs. +# In vanilla gameplay, turning logs into kindling would actually yield a higher volume of material... which doesn't make sense. +reduceKindlingVolume=true +#droppableSleepPowder: Allows sleep powder to be dropped. +# This will cause players to drop sleep powder if they die, but also makes them able to be mailed. +droppableSleepPowder=true +#setSilverMirrorPrice: Sets silver mirrors to cost 20 silver instead of 1 iron. This should allow them to be sold on traders. +setSilverMirrorPrice=true +#setGoldMirrorPrice: Sets gold mirrors to cost 1 gold instead of 1 iron. This should allow them to be sold on traders. +setGoldMirrorPrice=true +#setCreatureCratePrice: Sets creature cages to cost 10 silver. This allows them to be sold on traders. +setCreatureCratePrice=true +#setResurrectionStonePrice: Sets resurrection stones to cost 2 silver instead of 5 silver. +setResurrectionStonePrice=true +#loadableMailbox: Allows mailboxes (spirit cottage, spirit castle, etc) to be loaded into vehicles. +# Does not work on PvP servers even if enabled. +loadableMailbox=true +#loadableBellTower: Allows bell towers to be loaded into vehicles. +loadableBellTower=true +#loadableTrashBin: Allows trash bins to be loaded into vehicles. +loadableTrashBin=true +#loadableAltars: Allows altars (wood, stone, silver, gold) to be loaded into vehicles. +# Does not affect the huge altars (White Light and Black Light). +loadableAltars=true +#oneHandedLongSpear: Makes long spears one-handed, allowing them to be equipped in dual wield or with a shield. +oneHandedLongSpear=true +#reduceDirtDifficulty: Reduces the difficulty of crafting dirt from 99 to 50. +# Dirt by default has no crafting recipe so this does nothing on it's own. +reduceDirtDifficulty=true +#reduceSandDifficulty: Reduces the difficulty of crafting sand from 99 to 50. +# Sand by default has no crafting recipe so this does nothing on it's own. +reduceSandDifficulty=true +#reduceSandstoneDifficulty: Reduces the difficulty of crafting sandstone from 99 to 50. +# Sandstone by default has no crafting recipe so this does nothing on it's own. +reduceSandstoneDifficulty=true +#decorationStoneKeystone: Makes stone keystones into a decoration item. +# This prevents them from going into piles of items when dropped, allowing them to be used for decorative purposes. +decorationStoneKeystone=true +#decorationMarbleKeystone: Makes marble keystons into a decoration item. +# This prevents them from going into piles of items when dropped, allowing them to be used for decorative purposes. +decorationMarbleKeystone=true +#useCustomCacheFragments: Modifies the fragment count for archaeology with the custom caches from WyvernMods. +useCustomCacheFragments=true +#adjustStatueFragmentCount: Adjusts the fragment count for some statues in Archaeology. +# Worg and Eagle: 40 fragments. +# Hell Horse and Drake: 45 fragments. +# Fo, Magranon, Libila, and Vynora: 50 fragments. +adjustStatueFragmentCount=true +#removeLockpickSkillRequirement: Removes the 20 locksmithing requirement to begin crafting lockpicks. +# If the quality of materials is too low, players might still not be able to craft them with less than 20 skill. +removeLockpickSkillRequirement=true +#createCustomItemTemplates: Creates the item templates for the custom items from WyvernMods. +# This only initializes the item so it can be used on the server. Enabling this option does not make any items craftable. +# The ability to craft items is set in other configurations below this one. +# It is highly recommended to enable this and keep it enabled if you plan on using any of the custom items. +# If you want to remove an item, disabling this is not advised. Instead, remove the ability to craft that item in other configurations. +createCustomItemTemplates=true + +# > CUSTOM ITEM CREATION < # +# Custom Item Creation identifies which of the custom items you want to have be player-made. +# Each option will list the creation recipe and requirements. +enableCustomItemCreation=true +#TODO: Recode to allow custom recipes for both modded items and non-modded items. + +#craftHuntingArrowPacks: Creation Entry for Hunting Arrow Packs. +# Start with quiver + hunting arrow. Finish with 39 additional hunting arrows. +# Uses Fletching and requires 50 skill to begin. +craftHuntingArrowPacks=true +#craftWarArrowPacks: Creation Entry for War Arrow Packs. +# Start with quiver + war arrow. Finish with 39 additional war arrows. +# Uses Fletching and requires 50 skill to begin. +craftWarArrowPacks=true +#craftBattleYoyo: Creation Entry for Battle Yoyo. +# Crafted with a string of cloth and shaft. +# Uses Toymaking. +craftBattleYoyo=true +#craftClub: Creation Entry for Club. +# Crafted using a carving knife on a log. +# Uses Carpentry. +craftClub=true +#craftDepthDrill: Creation Entry for Depth Drill. +# Start with ribbon and shaft. Finish with a two wooden handles and a small nails. +# Uses Fine Carpentry. +craftDepthDrill=true +#craftEternalReservoir: Creation Entry for Eternal Reservoir. Used in Soulstealing. +# Start with a star diamond + dirt. Finish with 99 additional dirt, 200 pottery bricks, 30 chaos crystals, and 20 hearts. +# Uses Pottery. +craftEternalReservoir=true +#craftEviscerator: Creation Entry for Eviscerator. NOTE: This is meant to be a GM-only weapon. +# Crafted using a Wilhelm's Wrath on another Wilhelm's Wrath. This is not intended to be done. +# Uses Weapon Smithing. +# This creation entry is only made to enable the material functionality on the weapon. It is not meant to be used. +# The Eviscerator is a weapon designed to help with testing against tough targets (like titans) because it does insane damage. +craftEviscerator=true +#craftKnuckles: Creation Entry for Knuckles. +# Crafted using a lump of metal on a small anvil. +# Uses Weapon Heads Smithing. +craftKnuckles=true +#craftMassStorageUnit: Creation Entry for Mass Storage Unit. +# Start with wood beam + wood beam. Finish with 500 planks, 200 shafts, 50 ribbons, and 100 large nails. +# Uses Fine Carpentry and requires 70 skill to begin. +craftMassStorageUnit=true +#craftStatuetteDeities: Creation Entries for statuette of (Demigod). +# Created the same way normal statuettes are. +# The current statuettes are Thelastdab and Reevi. These are hardcoded. +craftStatuetteDeities=true +#TODO: Allow creation of new deity statuettes through configuration. +#craftWarhammer: Creation Entry for Warhammer and Warhammer Head. +# Warhammer Head is crafted using a lump of metal on a large anvil. +# Warhammer is crafted using a Warhammer Head on a shaft. +# Both use Weapon Heads Smithing. +craftWarhammer=true + +# > END CUSTOM ITEM CREATION < # + +## >> END ITEM MODULE << ## + +## >> SOULSTEALING MODULE << ## +## The Soulstealing Module is the implementation of a new skill, Soulstealing. This replaces the standard Stealing skill. +## When a creature dies, players can use a Sacrificial Knife to collect the creature's soul instead of butchering it. +## Stealing the soul will generate a small item, a soul, which can then be used for various purposes. +## When the soul is stolen, the corpse of the creature will be removed. This makes Soulstealing a handy skill for light hunting. +## Souls can be used in the Eternal Reservoir to charge it, which will automatically feed carnivore creatures nearby and keep forges and ovens lit. +enableSoulstealingModule=true +#TODO: This section needs more configurations for the eternal reservoir effects and how soulstealing functions. + +#pollEternalReservoirTime: Amount of time, in milliseconds, to poll Eternal Reservoirs for their effects. +# This will reduce their fuel and provide the effects of feeding nearby carnivores and lighting nearby forges and ovens. +# Default is 600000, or 10 minutes. +pollEternalReservoirTime=600000 + +## >> END SOULSTEALING MODULE << ## + +## >> ACTION MODULE << ## +## The Action Module handles new actions which are unrelated to other functions. Some serve as QoL and others as new features. +enableActionModule=true + +#actionUnequipAll: Provides an "Unequip All" action when players right-click an item they are wearing. +# This is slightly different than the body action for Unequip All that was added to the base game. It does not conflict with it. +actionUnequipAll=true +#actionReceiveAllMail: Provides a "Receive All Mail" action when players right-click a mailbox. +# This will not accept CoD items, and only accepts mail with no cost. +# It will accept up to 100 items at a time and place them in the mailbox upon action completion. +actionReceiveAllMail=true +#actionSplitSorcery: Provides a "Split Sorcery" action when players right-click any sorcery/tome. +# This allows them to split it into several tomes each with one charge. +# Amount of items granted is equivalent to the amount of charges in the original sorcery/tome. +actionSplitSorcery=true +#actionLeaderboard: Provides a "Leaderboard" action when players right-click their body. Also works when right-clicking skills. +# This opens up a full leaderboard dialogue where players can see the skill levels, achievements, and similar of other players. +# The system is opt-in, with each player opted out by default. +actionLeaderboard=true +#TODO: Allow customization of the leaderboard dialogue colors and similar. +#actionSorceryFragmentCombine: Allows sorcery fragments to be combined at a huge altar (White Light or Black Light). +actionSorceryFragmentCombine=true +#actionArenaTeleports: Provides the "Arena Teleport" and "Arena Escape" actions. +# These are hardcoded heavily for Revenant and likely will not work well on any other server. +actionArenaTeleports=true +#TODO: Expand on these actions to enable better teleportation options. +#actionAddMissionDev: Adds action "Add Mission" to the body of GM power 5 accounts. +# This adds a random mission using the custom Mission Creator. +actionAddMissionDev=true +#TODO: Allow configuration of power requirement. +#actionRemoveMissionDev: Adds action "Remove Mission" to the body of GM power 5 accounts. +# This removes a random active mission. +actionRemoveMissionDev=true +#TODO: Allow configuration of power requirement. +#actionCreatureReportDev: Adds action "Creature Report" to the body of GM power 5 accounts. +# This provides a list of current creatures on the server. +# Thanks to Bdew for providing the code to make this action work. +actionCreatureReportDev=true +#TODO: Allow configuration of power requirement. +#actionSmoothTerrainDev: Adds action "Smooth Terrain" when targeting a tile corner for GM power 5 accounts. +# This will enact "erosion" on the area and smooth the terrain by 1 step. +# Binding the action to a key and pressing it multiple times will demonstrate the effects of the Erosion system. +actionSmoothTerrainDev=true +#TODO: Allow configuration of the power requirement. + +## >> END ACTION MODULE << ## + +## >> EROSION MODULE << ## +## The Erosion Module handles a new system that helps smooth the terrain on otherwise bumpy maps. +## In some cases, the heightmap generation when making a new map is flawed and will create a very bumpy terrain. +## The erosion system is a slow but effective method by which to smooth the bumps in the terrain and make it more natural. +## This operation occurs on an interval, but is fairly expensive when it executes. +## If you notice laggspikes while this system is enabled, it is recommended that you either disable it or increase the interval. +enableErosionModule=true + +#pollTerrainSmoothTime: Amount of time, in milliseconds, between each terrain smoothing attempt. +# This operation selects a random spot on the map and smooths a 10x10 area. +# Default is 5000, or 5 seconds. +pollTerrainSmoothTime=5000 + +## >> END EROSION MODULE << ## + ## >> TREASURE CHEST LOOT MODULE << ## ## The Treasure Chest Loot Module affects the vanilla treasure chests. ## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them. diff --git a/src/main/java/mod/sin/creatures/WyvernBlack.java b/src/main/java/mod/sin/creatures/WyvernBlack.java index 9e0eb2c..315a0f8 100644 --- a/src/main/java/mod/sin/creatures/WyvernBlack.java +++ b/src/main/java/mod/sin/creatures/WyvernBlack.java @@ -124,14 +124,14 @@ public class WyvernBlack implements ModCreature, CreatureTypes { new EncounterBuilder(Tiles.Tile.TILE_SAND.id) .addCreatures(templateId, 1) .build(1); - //}else if(Servers.localServer.PVPSERVER){ - /*new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + }/*else if(Servers.localServer.PVPSERVER){ + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) .addCreatures(templateId, 1) .build(1); new EncounterBuilder(Tiles.Tile.TILE_TREE.id) .addCreatures(templateId, 1) - .build(1);*/ - } + .build(1); + }*/ } } diff --git a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java b/src/main/java/mod/sin/wyvern/Bestiary.java similarity index 74% rename from src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java rename to src/main/java/mod/sin/wyvern/Bestiary.java index b055928..23e719b 100644 --- a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java +++ b/src/main/java/mod/sin/wyvern/Bestiary.java @@ -1,11 +1,10 @@ -package mod.sin.wyvern.bestiary; +package mod.sin.wyvern; import java.lang.reflect.InvocationTargetException; import java.util.logging.Logger; import com.wurmonline.mesh.Tiles; import com.wurmonline.server.Servers; -import com.wurmonline.server.behaviours.AutoEquipMethods; import com.wurmonline.server.combat.Weapon; import com.wurmonline.server.creatures.*; import com.wurmonline.server.items.*; @@ -21,8 +20,6 @@ import javassist.expr.ExprEditor; import javassist.expr.MethodCall; import mod.sin.items.SealedMap; import mod.sin.lib.Util; -import mod.sin.wyvern.RareSpawns; -import mod.sin.wyvern.Titans; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import com.wurmonline.server.FailedException; @@ -38,12 +35,11 @@ import mod.sin.creatures.*; import mod.sin.creatures.titans.*; import mod.sin.weapons.Club; import mod.sin.weapons.titan.*; -import mod.sin.wyvern.MiscChanges; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; -public class MethodsBestiary { - protected static Logger logger = Logger.getLogger(MethodsBestiary.class.getName()); +public class Bestiary { + protected static Logger logger = Logger.getLogger(Bestiary.class.getName()); protected static boolean isUsuallyHitched(int templateId){ if(templateId == Charger.templateId){ @@ -701,55 +697,68 @@ public class MethodsBestiary { public static void preInit(){ try{ ClassPool classPool = HookManager.getInstance().getClassPool(); - final Class thisClass = MethodsBestiary.class; + final Class thisClass = Bestiary.class; String replace; - Util.setReason("Disable sacrificing strong creatures."); - CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); - CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); - CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); - CtClass[] params1 = { - ctCreature, - ctCreature, - ctItem, - ctAction, - CtClass.floatType - }; - String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); - replace = "if("+MethodsBestiary.class.getName()+".isSacrificeImmune($2)){" + - " performer.getCommunicator().sendNormalServerMessage(\"This creature cannot be sacrificed.\");" + - " return true;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctMethodsReligion, "sacrifice", desc1, replace); + CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); + CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); + CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); + CtClass ctPathFinder = classPool.get("com.wurmonline.server.creatures.ai.PathFinder"); + CtClass ctArchery = classPool.get("com.wurmonline.server.combat.Archery"); + CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); + CtClass ctVehicle = classPool.get("com.wurmonline.server.behaviours.Vehicle"); + CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); - Util.setReason("Disable afk training."); - CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); - replace = "if("+MethodsBestiary.class.getName()+".blockSkillFrom($1, $0)){"+//"if($1.isPlayer() && $1.getTarget() != $0){" + - //" logger.info(\"Non-targeted mob detected - \" + $1.getName());" + - " $_ = true;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isNoSkillFor", replace); - Util.instrumentDeclared(thisClass, ctCombatHandler, "checkDefenderParry", "isNoSkillFor", replace); - Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "isNoSkillFor", replace); - Util.instrumentDeclared(thisClass, ctCombatHandler, "setBonuses", "isNoSkillFor", replace); - CtMethod[] ctGetDamages = ctCombatHandler.getDeclaredMethods("getDamage"); - for(CtMethod method : ctGetDamages){ - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isNoSkillFor")) { - m.replace("if("+MethodsBestiary.class.getName()+".blockSkillFrom($1, $0)){" + //"if($1.isPlayer() && $1.getTarget() != $0){" + - //" logger.info(\"Non-targeted mob detected - \" + $1.getName());" + - " $_ = true;" + - "}else{" + - " $_ = $proceed($$);" + - "}"); - } - } - }); - } + if (WyvernMods.fixSacrificingStrongCreatures) { + Util.setReason("Disable sacrificing strong creatures."); + CtClass[] params1 = { + ctCreature, + ctCreature, + ctItem, + ctAction, + CtClass.floatType + }; + String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); + replace = "if(" + Bestiary.class.getName() + ".isSacrificeImmune($2)){" + + " performer.getCommunicator().sendNormalServerMessage(\"This creature cannot be sacrificed.\");" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctMethodsReligion, "sacrifice", desc1, replace); + } + + if (WyvernMods.disableAfkTraining) { + Util.setReason("Disable afk training."); + CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); + replace = "if(" + Bestiary.class.getName() + ".blockSkillFrom($1, $0)){" +//"if($1.isPlayer() && $1.getTarget() != $0){" + + //" logger.info(\"Non-targeted mob detected - \" + $1.getName());" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isNoSkillFor", replace); + Util.setReason("Disable afk training."); + Util.instrumentDeclared(thisClass, ctCombatHandler, "checkDefenderParry", "isNoSkillFor", replace); + Util.setReason("Disable afk training."); + Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "isNoSkillFor", replace); + Util.setReason("Disable afk training."); + Util.instrumentDeclared(thisClass, ctCombatHandler, "setBonuses", "isNoSkillFor", replace); + CtMethod[] ctGetDamages = ctCombatHandler.getDeclaredMethods("getDamage"); + for (CtMethod method : ctGetDamages) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isNoSkillFor")) { + m.replace("if(" + Bestiary.class.getName() + ".blockSkillFrom($1, $0)){" + //"if($1.isPlayer() && $1.getTarget() != $0){" + + //" logger.info(\"Non-targeted mob detected - \" + $1.getName());" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + } + } + }); + } + } // Die method description CtClass ctString = classPool.get("java.lang.String"); @@ -760,125 +769,203 @@ public class MethodsBestiary { }; String desc5 = Descriptor.ofMethod(CtClass.voidType, params5); - Util.setReason("Deny chargers walking through walls."); - CtClass ctPathFinder = classPool.get("com.wurmonline.server.creatures.ai.PathFinder"); - replace = "if("+MethodsBestiary.class.getName()+".denyPathingOverride($0)){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPathFinder, "canPass", "isGhost", replace); - Util.instrumentDeclared(thisClass, ctCreature, "setPathing", "isGhost", replace); - Util.instrumentDeclared(thisClass, ctCreature, "startPathingToTile", "isGhost", replace); - Util.instrumentDeclared(thisClass, ctCreature, "moveAlongPath", "isGhost", replace); - Util.instrumentDeclared(thisClass, ctCreature, "takeSimpleStep", "isGhost", replace); - Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); + if (WyvernMods.fixChargersWalkingThroughWalls) { + Util.setReason("Deny chargers walking through walls."); + replace = "if(" + Bestiary.class.getName() + ".denyPathingOverride($0)){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPathFinder, "canPass", "isGhost", replace); + Util.setReason("Deny chargers walking through walls."); + Util.instrumentDeclared(thisClass, ctCreature, "setPathing", "isGhost", replace); + Util.setReason("Deny chargers walking through walls."); + Util.instrumentDeclared(thisClass, ctCreature, "startPathingToTile", "isGhost", replace); + Util.setReason("Deny chargers walking through walls."); + Util.instrumentDeclared(thisClass, ctCreature, "moveAlongPath", "isGhost", replace); + Util.setReason("Deny chargers walking through walls."); + Util.instrumentDeclared(thisClass, ctCreature, "takeSimpleStep", "isGhost", replace); + Util.setReason("Deny chargers walking through walls."); + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); + } - Util.setReason("Apply random types to creatures in the wilderness."); - CtClass[] params2 = { - CtClass.intType, - CtClass.booleanType, - CtClass.floatType, - CtClass.floatType, - CtClass.floatType, - CtClass.intType, - classPool.get("java.lang.String"), - CtClass.byteType, - CtClass.byteType, - CtClass.byteType, - CtClass.booleanType, - CtClass.byteType, - CtClass.intType - }; - String desc2 = Descriptor.ofMethod(ctCreature, params2); - replace = "$10 = "+MethodsBestiary.class.getName()+".newCreatureType($1, $10);"; - Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, replace); + if (WyvernMods.conditionWildCreatures) { + Util.setReason("Apply random types to creatures in the wilderness."); + CtClass[] params2 = { + CtClass.intType, + CtClass.booleanType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType, + CtClass.intType, + classPool.get("java.lang.String"), + CtClass.byteType, + CtClass.byteType, + CtClass.byteType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType + }; + String desc2 = Descriptor.ofMethod(ctCreature, params2); + replace = "$10 = " + Bestiary.class.getName() + ".newCreatureType($1, $10);"; + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, replace); + } - Util.setReason("Enable archery against ghost targets."); - CtClass ctArchery = classPool.get("com.wurmonline.server.combat.Archery"); - CtMethod[] archeryAttacks = ctArchery.getDeclaredMethods("attack"); - for(CtMethod method : archeryAttacks){ - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isGhost")) { - m.replace("$_ = false;"); - logger.info("Enabled archery against ghost targets in archery attack method."); - } - } - }); - } + if (WyvernMods.allowGhostArchery) { + Util.setReason("Enable archery against ghost targets."); + CtMethod[] archeryAttacks = ctArchery.getDeclaredMethods("attack"); + for (CtMethod method : archeryAttacks) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isGhost")) { + m.replace("$_ = false;"); + logger.info("Enabled archery against ghost targets in archery attack method."); + } + } + }); + } + } - Util.setReason("Disable archery altogether against certain creatures."); - CtClass[] params3 = { - ctCreature, - ctCreature, - ctItem, - CtClass.floatType, - ctAction - }; - String desc3 = Descriptor.ofMethod(CtClass.booleanType, params3); - replace = "if("+MethodsBestiary.class.getName()+".isArcheryImmune($1, $2)){" - + " return true;" - + "}"; - Util.insertBeforeDescribed(thisClass, ctArchery, "attack", desc3, replace); + if (WyvernMods.disableArcheryOnStrongCreatures) { + Util.setReason("Disable archery altogether against certain creatures."); + CtClass[] params3 = { + ctCreature, + ctCreature, + ctItem, + CtClass.floatType, + ctAction + }; + String desc3 = Descriptor.ofMethod(CtClass.booleanType, params3); + replace = "if(" + Bestiary.class.getName() + ".isArcheryImmune($1, $2)){" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctArchery, "attack", desc3, replace); + } - Util.setReason("Auto-Genesis a creature born on enchanted grass"); - replace = MethodsBestiary.class.getName()+".checkEnchantedBreed(newCreature);" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "saveCreatureName", replace); + if (WyvernMods.genesisEnchantedGrassNewborns) { + Util.setReason("Auto-Genesis a creature born on enchanted grass"); + replace = Bestiary.class.getName() + ".checkEnchantedBreed(newCreature);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "saveCreatureName", replace); + } - Util.setReason("Set custom corpse sizes."); - replace = "$_ = $proceed($$);" - + "if("+MethodsBestiary.class.getName()+".hasCustomCorpseSize(this)){" - + " "+MethodsBestiary.class.getName()+".setCorpseSizes(this, corpse);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "addItem", replace); + if (WyvernMods.useCustomCorpseSizes) { + Util.setReason("Set custom corpse sizes."); + replace = "$_ = $proceed($$);" + + "if(" + Bestiary.class.getName() + ".hasCustomCorpseSize(this)){" + + " " + Bestiary.class.getName() + ".setCorpseSizes(this, corpse);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "addItem", replace); + } + /* Disabled for 1.9 - Probably not necessary anymore. Remains for reference or re-implementation. Util.setReason("Add spell resistance to custom creatures."); - replace = "float cResist = "+MethodsBestiary.class.getName()+".getCustomSpellResistance(this);" + + replace = "float cResist = "+Bestiary.class.getName()+".getCustomSpellResistance(this);" + "if(cResist >= 0f){" + " return cResist;" + "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "addSpellResistance", replace); + Util.insertBeforeDeclared(thisClass, ctCreature, "addSpellResistance", replace);*/ - Util.setReason("Allow custom creatures to have breeding names."); - replace = "$_ = "+MethodsBestiary.class.getName()+".shouldBreedName(this);"; - Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "isHorse", replace); + if (WyvernMods.allowCustomCreatureBreedNames) { + Util.setReason("Allow custom creatures to have breeding names."); + replace = "$_ = " + Bestiary.class.getName() + ".shouldBreedName(this);"; + Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "isHorse", replace); + } - Util.setReason("Allow ghost creatures to breed (Chargers)."); - CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); - replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctMethodsCreatures, "breed", "isGhost", replace); + if (WyvernMods.allowGhostBreeding) { + Util.setReason("Allow ghost creatures to breed (Chargers)."); + CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); + replace = "$_ = false;"; + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "breed", "isGhost", replace); + } - Util.setReason("Allow ghost creatures to drop corpses."); - replace = "if("+MethodsBestiary.class.getName()+".isGhostCorpse(this)){" - + " $_ = false;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); + if (WyvernMods.allowGhostCorpses) { + Util.setReason("Allow ghost creatures to drop corpses."); + replace = "if(" + Bestiary.class.getName() + ".isGhostCorpse(this)){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace); + } - Util.setReason("Attach special effects to creatures."); - CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); - CtClass[] params4 = { - CtClass.longType, - CtClass.booleanType, - CtClass.longType, - CtClass.floatType, - CtClass.floatType, - CtClass.floatType - }; - String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); - replace = "$_ = $proceed($$);" + - MethodsBestiary.class.getName()+".addCreatureSpecialEffect(copyId != -10 ? copyId : creatureId, $0, creature);"; - Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc4, "sendNewCreature", replace); + if (WyvernMods.useCustomCreatureSizes) { + Util.setReason("Enable custom sizes for creatures."); + replace = "{return " + Bestiary.class.getName() + ".getAdjustedSizeMod(this);}"; + Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", replace); + } - Util.setReason("Ensure unique creatures cannot be hitched to vehicles."); - CtClass ctVehicle = classPool.get("com.wurmonline.server.behaviours.Vehicle"); - replace = "if("+MethodsBestiary.class.getName()+".isNotHitchable($1)){" + - " return false;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctVehicle, "addDragger", replace); + CtClass[] params2 = { + CtClass.intType, + CtClass.booleanType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType, + CtClass.intType, + classPool.get("java.lang.String"), + CtClass.byteType, + CtClass.byteType, + CtClass.byteType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType + }; + String desc2 = Descriptor.ofMethod(ctCreature, params2); + + if (WyvernMods.modifyNewCreatures) { + Util.setReason("Modify newly created creatures."); + replace = "$_ = $proceed($$);" + + Bestiary.class.getName() + ".modifyNewCreature($1);"; + Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc2, "sendToWorld", replace); + } + + if (WyvernMods.useCustomCreatureSFX) { + Util.setReason("Attach special effects to creatures."); + CtClass[] params4 = { + CtClass.longType, + CtClass.booleanType, + CtClass.longType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType + }; + String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); + replace = "$_ = $proceed($$);" + + Bestiary.class.getName() + ".addCreatureSpecialEffect(copyId != -10 ? copyId : creatureId, $0, creature);"; + Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc4, "sendNewCreature", replace); + } + + if (WyvernMods.preventLegendaryHitching) { + Util.setReason("Ensure unique creatures cannot be hitched to vehicles."); + replace = "if(" + Bestiary.class.getName() + ".isNotHitchable($1)){" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctVehicle, "addDragger", replace); + } + + // doNew(int templateid, boolean createPossessions, float aPosX, float aPosY, float aRot, int layer, String name, byte gender, byte kingdom, byte ctype, boolean reborn, byte age) + CtClass[] params3 = { + CtClass.intType, + CtClass.booleanType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType, + CtClass.intType, + classPool.get("java.lang.String"), + CtClass.byteType, + CtClass.byteType, + CtClass.byteType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType + }; + String desc3 = Descriptor.ofMethod(ctCreature, params3); + + if (WyvernMods.logCreatureSpawns) { + Util.setReason("Log new creature spawns."); + replace = "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"; + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc3, replace); + } } catch ( CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java index 2b5ab5a..2eae02f 100644 --- a/src/main/java/mod/sin/wyvern/Bounty.java +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -17,7 +17,6 @@ import javassist.CtClass; import javassist.NotFoundException; import javassist.bytecode.Descriptor; import mod.sin.lib.Util; -import mod.sin.wyvern.bestiary.MethodsBestiary; import mod.sin.wyvern.bounty.LootBounty; import mod.sin.wyvern.bounty.PlayerBounty; @@ -95,9 +94,12 @@ public class Bounty { CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - replace = PlayerBounty.class.getName()+".checkPlayerBounty(player, this);" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkCoinAward", replace); + if (WyvernMods.usePlayerBounty) { + Util.setReason("Hook for Player Bounty."); + replace = PlayerBounty.class.getName() + ".checkPlayerBounty(player, this);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkCoinAward", replace); + } // Die method description CtClass ctString = classPool.get("java.lang.String"); @@ -113,60 +115,29 @@ public class Bounty { Util.instrumentDescribed(thisClass, ctCreature, "die", desc1, "setRotation", replace); // doNew(int templateid, boolean createPossessions, float aPosX, float aPosY, float aRot, int layer, String name, byte gender, byte kingdom, byte ctype, boolean reborn, byte age) - CtClass[] params2 = { - CtClass.intType, - CtClass.booleanType, - CtClass.floatType, - CtClass.floatType, - CtClass.floatType, - CtClass.intType, - classPool.get("java.lang.String"), - CtClass.byteType, - CtClass.byteType, - CtClass.byteType, - CtClass.booleanType, - CtClass.byteType, - CtClass.intType - }; - String desc2 = Descriptor.ofMethod(ctCreature, params2); - Util.setReason("Log new creature spawns."); - replace = "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"; - Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, replace); - - Util.setReason("Modify newly created creatures."); - replace = "$_ = $proceed($$);" - //+ "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"; - + MethodsBestiary.class.getName()+".modifyNewCreature($1);"; - Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc2, "sendToWorld", replace); - - // -- Enable adjusting size for creatures -- // - CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); - Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", "{return "+MethodsBestiary.class.getName()+".getAdjustedSizeMod(this);}"); - //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"); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" - + " return "+MethodsBestiary.class.getName()+".getCreatureColorRed(this);" + replace = "if("+Bestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+Bestiary.class.getName()+".getCreatureColorRed(this);" + "}"; Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorRed", replace); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" - + " return "+MethodsBestiary.class.getName()+".getCreatureColorGreen(this);" + replace = "if("+Bestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+Bestiary.class.getName()+".getCreatureColorGreen(this);" + "}"; Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorGreen", replace); - replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" - + " return "+MethodsBestiary.class.getName()+".getCreatureColorBlue(this);" + replace = "if("+Bestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+Bestiary.class.getName()+".getCreatureColorBlue(this);" + "}"; 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);" + /*ctCreatureTemplate.getDeclaredMethod("getColorRed").insertBefore("if(mod.sin.wyvern.Bestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.Bestiary.getCreatureColorRed(this);" + "}"); - ctCreatureTemplate.getDeclaredMethod("getColorGreen").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" - + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorGreen(this);" + ctCreatureTemplate.getDeclaredMethod("getColorGreen").insertBefore("if(mod.sin.wyvern.Bestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.Bestiary.getCreatureColorGreen(this);" + "}"); - ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" - + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorBlue(this);" + ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.Bestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.Bestiary.getCreatureColorBlue(this);" + "}");*/ // -- When a creature takes damage, track the damage taken -- // diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index 77ab7d7..b4e11fb 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -10,6 +10,7 @@ import java.util.logging.Logger; import com.wurmonline.server.Servers; import com.wurmonline.server.combat.ArmourTemplate; +import com.wurmonline.server.items.*; import mod.sin.items.caches.*; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -19,11 +20,6 @@ import org.gotti.wurmunlimited.modsupport.actions.ModActions; import com.wurmonline.server.behaviours.ActionEntry; import com.wurmonline.server.combat.Weapon; import com.wurmonline.server.creatures.Creature; -import com.wurmonline.server.items.Item; -import com.wurmonline.server.items.ItemList; -import com.wurmonline.server.items.ItemTemplate; -import com.wurmonline.server.items.ItemTemplateFactory; -import com.wurmonline.server.items.NoSuchTemplateException; import javassist.CtClass; import javassist.bytecode.Descriptor; import mod.sin.actions.items.*; @@ -52,6 +48,7 @@ public class ItemMod { //public static TitaniumLump ELECTRUM_LUMP = new TitaniumLump(); public static EnchantOrb ENCHANT_ORB = new EnchantOrb(); public static EternalOrb ETERNAL_ORB = new EternalOrb(); + public static EternalReservoir ETERNAL_RESERVOIR = new EternalReservoir(); public static Eviscerator EVISCERATOR = new Eviscerator(); public static FriyanTablet FRIYAN_TABLET = new FriyanTablet(); public static HugeCrate HUGE_CRATE = new HugeCrate(); @@ -60,7 +57,6 @@ public class ItemMod { public static SealedMap SEALED_MAP = new SealedMap(); public static SkeletonDecoration SKELETON_DECORATION = new SkeletonDecoration(); public static Soul SOUL = new Soul(); - public static EternalReservoir SOUL_FORGE = new EternalReservoir(); public static StatuetteBreyk STATUETTE_BREYK = new StatuetteBreyk(); public static StatuetteCyberhusky STATUETTE_CYBERHUSKY = new StatuetteCyberhusky(); public static TreasureBox TREASURE_BOX = new TreasureBox(); @@ -117,6 +113,7 @@ public class ItemMod { DISINTEGRATION_ROD.createTemplate(); ENCHANT_ORB.createTemplate(); ETERNAL_ORB.createTemplate(); + ETERNAL_RESERVOIR.createTemplate(); EVISCERATOR.createTemplate(); FRIYAN_TABLET.createTemplate(); HUGE_CRATE.createTemplate(); @@ -125,7 +122,6 @@ public class ItemMod { SEALED_MAP.createTemplate(); SKELETON_DECORATION.createTemplate(); SOUL.createTemplate(); - SOUL_FORGE.createTemplate(); STATUETTE_BREYK.createTemplate(); STATUETTE_CYBERHUSKY.createTemplate(); TREASURE_BOX.createTemplate(); @@ -190,23 +186,44 @@ public class ItemMod { } public static void initCreationEntries(){ - logger.info("initCreationEntries()"); - ARROW_PACK_HUNTING.initCreationEntry(); - ARROW_PACK_WAR.initCreationEntry(); - BATTLE_YOYO.initCreationEntry(); - CLUB.initCreationEntry(); + if (WyvernMods.craftHuntingArrowPacks) { + ARROW_PACK_HUNTING.initCreationEntry(); + } + if (WyvernMods.craftWarArrowPacks) { + ARROW_PACK_WAR.initCreationEntry(); + } + if (WyvernMods.craftBattleYoyo) { + BATTLE_YOYO.initCreationEntry(); + } + if (WyvernMods.craftClub) { + CLUB.initCreationEntry(); + } //COIN_DECORATION.initCreationEntry(); //CORPSE_DECORATION.initCreationEntry(); - DEPTH_DRILL.initCreationEntry(); - EVISCERATOR.initCreationEntry(); - KNUCKLES.initCreationEntry(); - MASS_STORAGE_UNIT.initCreationEntry(); + if (WyvernMods.craftDepthDrill) { + DEPTH_DRILL.initCreationEntry(); + } + if (WyvernMods.craftEternalReservoir) { + ETERNAL_RESERVOIR.initCreationEntry(); + } + if (WyvernMods.craftEviscerator) { + EVISCERATOR.initCreationEntry(); + } + if (WyvernMods.craftKnuckles) { + KNUCKLES.initCreationEntry(); + } + if (WyvernMods.craftMassStorageUnit) { + MASS_STORAGE_UNIT.initCreationEntry(); + } //SKELETON_DECORATION.initCreationEntry(); - SOUL_FORGE.initCreationEntry(); - STATUETTE_BREYK.initCreationEntry(); - STATUETTE_CYBERHUSKY.initCreationEntry(); - WARHAMMER.initCreationEntry(); - WARHAMMER_HEAD.initCreationEntry(); + if (WyvernMods.craftStatuetteDeities) { + STATUETTE_BREYK.initCreationEntry(); + STATUETTE_CYBERHUSKY.initCreationEntry(); + } + if (WyvernMods.craftWarhammer) { + WARHAMMER.initCreationEntry(); + WARHAMMER_HEAD.initCreationEntry(); + } // Spectral set /*SPECTRAL_BOOT.initCreationEntry(); @@ -310,45 +327,66 @@ public class ItemMod { public static void modifyItems() throws NoSuchTemplateException, IllegalArgumentException, IllegalAccessException, ClassCastException, NoSuchFieldException{ // Make leather able to be combined. - ItemTemplate leather = ItemTemplateFactory.getInstance().getTemplate(ItemList.leather); - ReflectionUtil.setPrivateField(leather, ReflectionUtil.getField(leather.getClass(), "combine"), true); + if (WyvernMods.combineLeather) { + ItemTemplate leather = ItemTemplateFactory.getInstance().getTemplate(ItemList.leather); + ReflectionUtil.setPrivateField(leather, ReflectionUtil.getField(leather.getClass(), "combine"), true); + } // Make logs able to be combined. Also reduce their volume. ItemTemplate log = ItemTemplateFactory.getInstance().getTemplate(ItemList.log); - ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "combine"), true); - ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "centimetersZ"), 50); - int newVolume = log.getSizeX()*log.getSizeY()*log.getSizeZ(); - ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "volume"), newVolume); + if (WyvernMods.combineLogs) { + ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "combine"), true); + } + if (WyvernMods.reduceLogVolume) { + ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "centimetersZ"), 50); + int newVolume = log.getSizeX() * log.getSizeY() * log.getSizeZ(); + ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "volume"), newVolume); + } // Reduce kindling volume as well to make sure they're not larger than logs. - ItemTemplate kindling = ItemTemplateFactory.getInstance().getTemplate(ItemList.kindling); - ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersY"), 10); - ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersZ"), 10); - int newKindlingVolume = kindling.getSizeX()*kindling.getSizeY()*kindling.getSizeZ(); - ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "volume"), newKindlingVolume); + if (WyvernMods.reduceKindlingVolume) { + ItemTemplate kindling = ItemTemplateFactory.getInstance().getTemplate(ItemList.kindling); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersY"), 10); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "centimetersZ"), 10); + int newKindlingVolume = kindling.getSizeX() * kindling.getSizeY() * kindling.getSizeZ(); + ReflectionUtil.setPrivateField(kindling, ReflectionUtil.getField(kindling.getClass(), "volume"), newKindlingVolume); + } // Allow sleep powder to be dropped. - ItemTemplate sleepPowder = ItemTemplateFactory.getInstance().getTemplate(ItemList.sleepPowder); - ReflectionUtil.setPrivateField(sleepPowder, ReflectionUtil.getField(sleepPowder.getClass(), "nodrop"), false); + if (WyvernMods.droppableSleepPowder) { + ItemTemplate sleepPowder = ItemTemplateFactory.getInstance().getTemplate(ItemList.sleepPowder); + ReflectionUtil.setPrivateField(sleepPowder, ReflectionUtil.getField(sleepPowder.getClass(), "nodrop"), false); + } - // Set silver mirror price to 10 silver instead of 1 iron. - ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror); - ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 200000); - ItemTemplate goldMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.goldenMirror); - ReflectionUtil.setPrivateField(goldMirror, ReflectionUtil.getField(goldMirror.getClass(), "value"), 1000000); + // Set silver mirror price to 20 silver instead of 1 iron. + if (WyvernMods.setSilverMirrorPrice) { + ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror); + ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 200000); + } + // Set golden mirror price to 1 gold instead of 1 iron. + if (WyvernMods.setGoldMirrorPrice) { + ItemTemplate goldMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.goldenMirror); + ReflectionUtil.setPrivateField(goldMirror, ReflectionUtil.getField(goldMirror.getClass(), "value"), 1000000); + } // Creature crates to 10 silver. - ItemTemplate creatureCage = ItemTemplateFactory.getInstance().getTemplate(ItemList.creatureCrate); - ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "value"), 100000); - ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "fullprice"), true); + if (WyvernMods.setCreatureCratePrice) { + ItemTemplate creatureCage = ItemTemplateFactory.getInstance().getTemplate(ItemList.creatureCrate); + ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "value"), 100000); + ReflectionUtil.setPrivateField(creatureCage, ReflectionUtil.getField(creatureCage.getClass(), "fullprice"), true); + } // Resurrection Stones to 2 silver instead of 5 silver. - ItemTemplate resurrectionStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.resurrectionStone); - ReflectionUtil.setPrivateField(resurrectionStone, ReflectionUtil.getField(resurrectionStone.getClass(), "value"), 20000); + if (WyvernMods.setResurrectionStonePrice) { + ItemTemplate resurrectionStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.resurrectionStone); + ReflectionUtil.setPrivateField(resurrectionStone, ReflectionUtil.getField(resurrectionStone.getClass(), "value"), 20000); + } // Shaker Orbs to 2 silver instead of 5 silver. - ItemTemplate shakerOrb = ItemTemplateFactory.getInstance().getTemplate(ItemList.shakerOrb); - ReflectionUtil.setPrivateField(shakerOrb, ReflectionUtil.getField(shakerOrb.getClass(), "value"), 20000); + if (WyvernMods.setShakerOrbPrice) { + ItemTemplate shakerOrb = ItemTemplateFactory.getInstance().getTemplate(ItemList.shakerOrb); + ReflectionUtil.setPrivateField(shakerOrb, ReflectionUtil.getField(shakerOrb.getClass(), "value"), 20000); + } // Set transmutation rod to 2 gold instead of 50 silver. //ItemTemplate transmutationRod = ItemTemplateFactory.getInstance().getTemplate(668); @@ -356,7 +394,7 @@ public class ItemMod { // " return this.isTransportable || (this.getTemplateId() >= 510 && this.getTemplateId() <= 513) || this.getTemplateId() == 722 || this.getTemplateId() == 670;" // Make mailboxes loadable (PvE Only) - if(!Servers.localServer.PVPSERVER) { + if(WyvernMods.loadableMailbox && !Servers.localServer.PVPSERVER) { ItemTemplate mailboxWood = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxWood); ReflectionUtil.setPrivateField(mailboxWood, ReflectionUtil.getField(mailboxWood.getClass(), "isTransportable"), true); ItemTemplate mailboxStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxStone); @@ -368,79 +406,118 @@ public class ItemMod { } // Make bell towers and trash bins loadable - ItemTemplate bellTower = ItemTemplateFactory.getInstance().getTemplate(ItemList.bellTower); - ReflectionUtil.setPrivateField(bellTower, ReflectionUtil.getField(bellTower.getClass(), "isTransportable"), true); - ItemTemplate trashBin = ItemTemplateFactory.getInstance().getTemplate(ItemList.trashBin); - ReflectionUtil.setPrivateField(trashBin, ReflectionUtil.getField(trashBin.getClass(), "isTransportable"), true); + if (WyvernMods.loadableBellTower) { + ItemTemplate bellTower = ItemTemplateFactory.getInstance().getTemplate(ItemList.bellTower); + ReflectionUtil.setPrivateField(bellTower, ReflectionUtil.getField(bellTower.getClass(), "isTransportable"), true); + } + if (WyvernMods.loadableTrashBin) { + ItemTemplate trashBin = ItemTemplateFactory.getInstance().getTemplate(ItemList.trashBin); + ReflectionUtil.setPrivateField(trashBin, ReflectionUtil.getField(trashBin.getClass(), "isTransportable"), true); + } // Make altars loadable - ItemTemplate stoneAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarStone); - ReflectionUtil.setPrivateField(stoneAltar, ReflectionUtil.getField(stoneAltar.getClass(), "isTransportable"), true); - ItemTemplate woodAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarWood); - ReflectionUtil.setPrivateField(woodAltar, ReflectionUtil.getField(woodAltar.getClass(), "isTransportable"), true); - ItemTemplate silverAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarSilver); - ReflectionUtil.setPrivateField(silverAltar, ReflectionUtil.getField(silverAltar.getClass(), "isTransportable"), true); - ItemTemplate goldAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarGold); - ReflectionUtil.setPrivateField(goldAltar, ReflectionUtil.getField(goldAltar.getClass(), "isTransportable"), true); + if (WyvernMods.loadableAltars) { + ItemTemplate stoneAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarStone); + ReflectionUtil.setPrivateField(stoneAltar, ReflectionUtil.getField(stoneAltar.getClass(), "isTransportable"), true); + ItemTemplate woodAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarWood); + ReflectionUtil.setPrivateField(woodAltar, ReflectionUtil.getField(woodAltar.getClass(), "isTransportable"), true); + ItemTemplate silverAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarSilver); + ReflectionUtil.setPrivateField(silverAltar, ReflectionUtil.getField(silverAltar.getClass(), "isTransportable"), true); + ItemTemplate goldAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarGold); + ReflectionUtil.setPrivateField(goldAltar, ReflectionUtil.getField(goldAltar.getClass(), "isTransportable"), true); + } // Make long spears one-handed. - ItemTemplate longSpear = ItemTemplateFactory.getInstance().getTemplate(ItemList.spearLong); - ReflectionUtil.setPrivateField(longSpear, ReflectionUtil.getField(longSpear.getClass(), "isTwohanded"), false); + if (WyvernMods.oneHandedLongSpear) { + ItemTemplate longSpear = ItemTemplateFactory.getInstance().getTemplate(ItemList.spearLong); + ReflectionUtil.setPrivateField(longSpear, ReflectionUtil.getField(longSpear.getClass(), "isTwohanded"), false); + } // Make dirt/sand difficulty easier - ItemTemplate dirt = ItemTemplateFactory.getInstance().getTemplate(ItemList.dirtPile); - ReflectionUtil.setPrivateField(dirt, ReflectionUtil.getField(dirt.getClass(), "difficulty"), 50.0f); + if (WyvernMods.reduceDirtDifficulty) { + ItemTemplate dirt = ItemTemplateFactory.getInstance().getTemplate(ItemList.dirtPile); + ReflectionUtil.setPrivateField(dirt, ReflectionUtil.getField(dirt.getClass(), "difficulty"), 50.0f); + } - ItemTemplate sand = ItemTemplateFactory.getInstance().getTemplate(ItemList.sand); - ReflectionUtil.setPrivateField(sand, ReflectionUtil.getField(sand.getClass(), "difficulty"), 50.0f); + if (WyvernMods.reduceSandDifficulty) { + ItemTemplate sand = ItemTemplateFactory.getInstance().getTemplate(ItemList.sand); + ReflectionUtil.setPrivateField(sand, ReflectionUtil.getField(sand.getClass(), "difficulty"), 50.0f); + } - ItemTemplate sandstone = ItemTemplateFactory.getInstance().getTemplate(ItemList.sandstone); - ReflectionUtil.setPrivateField(sandstone, ReflectionUtil.getField(sandstone.getClass(), "difficulty"), 50.0f); + if (WyvernMods.reduceSandstoneDifficulty) { + ItemTemplate sandstone = ItemTemplateFactory.getInstance().getTemplate(ItemList.sandstone); + ReflectionUtil.setPrivateField(sandstone, ReflectionUtil.getField(sandstone.getClass(), "difficulty"), 50.0f); + } // Make some useless items decorations for added interior design. - ItemTemplate stoneKeystone = ItemTemplateFactory.getInstance().getTemplate(ItemList.stoneKeystone); - ReflectionUtil.setPrivateField(stoneKeystone, ReflectionUtil.getField(stoneKeystone.getClass(), "decoration"), true); - ItemTemplate marbleKeystone = ItemTemplateFactory.getInstance().getTemplate(ItemList.marbleKeystone); - ReflectionUtil.setPrivateField(marbleKeystone, ReflectionUtil.getField(marbleKeystone.getClass(), "decoration"), true); - ItemTemplate skull = ItemTemplateFactory.getInstance().getTemplate(ItemList.skull); - ReflectionUtil.setPrivateField(skull, ReflectionUtil.getField(skull.getClass(), "decoration"), true); + if (WyvernMods.decorationStoneKeystone) { + ItemTemplate stoneKeystone = ItemTemplateFactory.getInstance().getTemplate(ItemList.stoneKeystone); + ReflectionUtil.setPrivateField(stoneKeystone, ReflectionUtil.getField(stoneKeystone.getClass(), "decoration"), true); + } + if (WyvernMods.decorationMarbleKeystone) { + ItemTemplate marbleKeystone = ItemTemplateFactory.getInstance().getTemplate(ItemList.marbleKeystone); + ReflectionUtil.setPrivateField(marbleKeystone, ReflectionUtil.getField(marbleKeystone.getClass(), "decoration"), true); + } + if (WyvernMods.decorationSkull) { + ItemTemplate skull = ItemTemplateFactory.getInstance().getTemplate(ItemList.skull); + ReflectionUtil.setPrivateField(skull, ReflectionUtil.getField(skull.getClass(), "decoration"), true); + } // Modify fragment counts - setFragments(ArmourCache.templateId, 18); - setFragments(ArtifactCache.templateId, 33); - setFragments(CrystalCache.templateId, 11); - setFragments(DragonCache.templateId, 19); - setFragments(GemCache.templateId, 7); - setFragments(MoonCache.templateId, 14); - setFragments(PotionCache.templateId, 18); - setFragments(RiftCache.templateId, 24); - setFragments(TitanCache.templateId, 100); - setFragments(ToolCache.templateId, 27); - setFragments(TreasureMapCache.templateId, 38); + if (WyvernMods.useCustomCacheFragments) { + setFragments(ArmourCache.templateId, 18); + setFragments(ArtifactCache.templateId, 33); + setFragments(CrystalCache.templateId, 11); + setFragments(DragonCache.templateId, 19); + setFragments(GemCache.templateId, 7); + setFragments(MoonCache.templateId, 14); + setFragments(PotionCache.templateId, 18); + setFragments(RiftCache.templateId, 24); + setFragments(TitanCache.templateId, 100); + setFragments(ToolCache.templateId, 27); + setFragments(TreasureMapCache.templateId, 38); - setFragments(AffinityOrb.templateId, 20); + setFragments(AffinityOrb.templateId, 20); + } - // Tier 4 - setFragments(ItemList.statueWorg, 40); - setFragments(ItemList.statueEagle, 40); + if (WyvernMods.adjustStatueFragmentCount) { + // Tier 4 + setFragments(ItemList.statueWorg, 40); + setFragments(ItemList.statueEagle, 40); - // Tier 5 - setFragments(ItemList.statueHellHorse, 45); - setFragments(ItemList.statueDrake, 45); + // Tier 5 + setFragments(ItemList.statueHellHorse, 45); + setFragments(ItemList.statueDrake, 45); - // Tier 6 - setFragments(ItemList.statueFo, 50); - setFragments(ItemList.statueMagranon, 50); - setFragments(ItemList.statueLibila, 50); - setFragments(ItemList.statueVynora, 50); - - createCustomWeapons(); - createCustomArmours(); + // Tier 6 + setFragments(ItemList.statueFo, 50); + setFragments(ItemList.statueMagranon, 50); + setFragments(ItemList.statueLibila, 50); + setFragments(ItemList.statueVynora, 50); + } + + if (WyvernMods.enableCustomItemCreation) { + createCustomWeapons(); + createCustomArmours(); + } // Make huge crates larger //ItemTemplate hugeCrate = ItemTemplateFactory.getInstance().getTemplate(HUGE_CRATE.getTemplateId()); //ReflectionUtil.setPrivateField(hugeCrate, ReflectionUtil.getField(hugeCrate.getClass(), "combine"), true); } + + public static void onServerStarted(){ + if (WyvernMods.removeLockpickSkillRequirement) { + CreationEntry lockpicks = CreationMatrix.getInstance().getCreationEntry(ItemList.lockpick); + try { + ReflectionUtil.setPrivateField(lockpicks, ReflectionUtil.getField(lockpicks.getClass(), "hasMinimumSkillRequirement"), false); + ReflectionUtil.setPrivateField(lockpicks, ReflectionUtil.getField(lockpicks.getClass(), "minimumSkill"), 0.0); + } catch (IllegalAccessException | NoSuchFieldException e) { + logger.info("Failed to set lockpick creation entry changes!"); + e.printStackTrace(); + } + } + } public static void registerPermissionsHook(){ try { diff --git a/src/main/java/mod/sin/wyvern/Mastercraft.java b/src/main/java/mod/sin/wyvern/Mastercraft.java index 77b2486..ac551f7 100644 --- a/src/main/java/mod/sin/wyvern/Mastercraft.java +++ b/src/main/java/mod/sin/wyvern/Mastercraft.java @@ -67,17 +67,6 @@ public class Mastercraft { return mult; } - public static void changeExistingTitles(){ - for (Titles.Title title : Titles.Title.values()) { - if (Objects.equals("Pumpkin King", title.getFemaleName())){ - try { - ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen"); - } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { - e.printStackTrace(); - } - } - } - } public static void preInit(){ try { ClassPool classPool = HookManager.getInstance().getClassPool(); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 65f9a76..6fd5b96 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -28,6 +28,7 @@ import javassist.expr.ExprEditor; import javassist.expr.FieldAccess; import javassist.expr.MethodCall; import mod.sin.lib.Util; +import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; import org.gotti.wurmunlimited.modsupport.ModSupportDb; @@ -326,6 +327,18 @@ public class MiscChanges { return true; } + public static void changeExistingTitles(){ + for (Titles.Title title : Titles.Title.values()) { + if (Objects.equals("Pumpkin King", title.getFemaleName())){ + try { + ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen"); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + } + } + public static void preInit(){ try{ ClassPool classPool = HookManager.getInstance().getClassPool(); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index 924ba91..a074bb3 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -3,7 +3,8 @@ package mod.sin.wyvern; import com.wurmonline.server.Message; import com.wurmonline.server.TimeConstants; import com.wurmonline.server.creatures.Creature; -import com.wurmonline.server.items.*; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.NoSuchTemplateException; import com.wurmonline.server.players.Player; import javassist.CannotCompileException; import javassist.ClassPool; @@ -18,8 +19,6 @@ import mod.sin.creatures.titans.*; import mod.sin.lib.Prop; import mod.sin.lib.SkillAssist; import mod.sin.lib.Util; -import mod.sin.wyvern.bestiary.MethodsBestiary; -import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; import org.gotti.wurmunlimited.modloader.interfaces.*; @@ -95,6 +94,8 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static boolean disableSmeltingPots = true; public static boolean hideSorceryBuffBar = true; public static boolean sqlAchievementFix = true; + public static boolean changePumpkinKingTitle = true; + public static boolean changeDeityPassives = true; // Arena Module Configuration public static boolean enableArenaModule = true; @@ -265,6 +266,99 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static long captureMessageInterval = TimeConstants.MINUTE_MILLIS*3L; public static long depotRespawnTime = TimeConstants.HOUR_MILLIS*11L; + // Bestiary Module Configuration + public static boolean enableBestiaryModule = true; + public static boolean fixSacrificingStrongCreatures = true; + public static boolean disableAfkTraining = true; + public static boolean fixChargersWalkingThroughWalls = true; + public static boolean conditionWildCreatures = true; + public static boolean allowGhostArchery = true; + public static boolean disableArcheryOnStrongCreatures = true; + public static boolean genesisEnchantedGrassNewborns = true; + public static boolean useCustomCorpseSizes = true; + public static boolean allowCustomCreatureBreedNames = true; + public static boolean allowGhostBreeding = true; + public static boolean allowGhostCorpses = true; + public static boolean useCustomCreatureSizes = true; + public static boolean useCustomCreatureSFX = true; + public static boolean preventLegendaryHitching = true; + public static boolean modifyNewCreatures = true; + public static boolean logCreatureSpawns = true; + public static boolean allowEpicCreatureNaturalSpawns = true; + public static boolean enableCustomCreatures = true; + public static boolean enableWyverns = true; + public static boolean enableFlavorMobs = true; + public static boolean enableEventMobs = true; + public static boolean enableRareSpawns = true; + public static boolean enableCustomLegendaries = true; + public static boolean enableTitans = true; + + // Bounty Module Configuration + public static boolean enableBountyModule = true; + public static boolean usePlayerBounty = true; + public static boolean useLootTable = true; + + // Item Module Configuration + public static boolean enableItemModule = true; + public static boolean combineLeather = true; + public static boolean combineLogs = true; + public static boolean reduceLogVolume = true; + public static boolean reduceKindlingVolume = true; + public static boolean droppableSleepPowder = true; + public static boolean setSilverMirrorPrice = true; + public static boolean setGoldMirrorPrice = true; + public static boolean setCreatureCratePrice = true; + public static boolean setResurrectionStonePrice = true; + public static boolean setShakerOrbPrice = true; + public static boolean loadableMailbox = true; + public static boolean loadableBellTower = true; + public static boolean loadableTrashBin = true; + public static boolean loadableAltars = true; + public static boolean oneHandedLongSpear = true; + public static boolean reduceDirtDifficulty = true; + public static boolean reduceSandDifficulty = true; + public static boolean reduceSandstoneDifficulty = true; + public static boolean decorationStoneKeystone = true; + public static boolean decorationMarbleKeystone = true; + public static boolean decorationSkull = true; + public static boolean useCustomCacheFragments = true; + public static boolean adjustStatueFragmentCount = true; + public static boolean removeLockpickSkillRequirement = true; + public static boolean createCustomItemTemplates = true; + public static boolean enableCustomItemCreation = true; + public static boolean craftHuntingArrowPacks = true; + public static boolean craftWarArrowPacks = true; + public static boolean craftBattleYoyo = true; + public static boolean craftClub = true; + public static boolean craftDepthDrill = true; + public static boolean craftEternalReservoir = true; + public static boolean craftEviscerator = true; + public static boolean craftKnuckles = true; + public static boolean craftMassStorageUnit = true; + public static boolean craftStatuetteDeities = true; + public static boolean craftWarhammer = true; + + // Soulstealing Module Configuration + public static boolean enableSoulstealingModule = true; + public static long pollEternalReservoirTime = TimeConstants.MINUTE_MILLIS*10; + + // Action Module Configuration + public static boolean enableActionModule = true; + public static boolean actionUnequipAll = true; + public static boolean actionReceiveAllMail = true; + public static boolean actionSplitSorcery = true; + public static boolean actionLeaderboard = true; + public static boolean actionSorceryFragmentCombine = true; + public static boolean actionArenaTeleports = true; + public static boolean actionAddMissionDev = true; + public static boolean actionRemoveMissionDev = true; + public static boolean actionCreatureReportDev = true; + public static boolean actionSmoothTerrainDev = true; + + // Erosion Module Configuration + public static boolean enableErosionModule = true; + public static long pollTerrainSmoothTime = TimeConstants.SECOND_MILLIS*5; + // Treasure Chest Loot Module Configuration public static boolean enableTreasureChestLootModule = true; @@ -385,6 +479,8 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea disableSmeltingPots = Prop.getBooleanProperty("disableSmeltingPots", disableSmeltingPots); hideSorceryBuffBar = Prop.getBooleanProperty("hideSorceryBuffBar", hideSorceryBuffBar); sqlAchievementFix = Prop.getBooleanProperty("sqlAchievementFix", sqlAchievementFix); + changePumpkinKingTitle = Prop.getBooleanProperty("changePumpkinKingTitle", changePumpkinKingTitle); + changeDeityPassives = Prop.getBooleanProperty("changeDeityPassives", changeDeityPassives); // Arena Module enableArenaModule = Prop.getBooleanProperty("enableArenaModule", enableArenaModule); @@ -550,6 +646,98 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea captureMessageInterval = Prop.getLongProperty("captureMessageInterval", captureMessageInterval); depotRespawnTime = Prop.getLongProperty("depotRespawnTime", depotRespawnTime); + // Bestiary Module + enableBestiaryModule = Prop.getBooleanProperty("enableBestiaryModule", enableBestiaryModule); + fixSacrificingStrongCreatures = Prop.getBooleanProperty("fixSacrificingStrongCreatures", fixSacrificingStrongCreatures); + disableAfkTraining = Prop.getBooleanProperty("disableAfkTraining", disableAfkTraining); + fixChargersWalkingThroughWalls = Prop.getBooleanProperty("fixChargersWalkingThroughWalls", fixChargersWalkingThroughWalls); + conditionWildCreatures = Prop.getBooleanProperty("conditionWildCreatures", conditionWildCreatures); + allowGhostArchery = Prop.getBooleanProperty("allowGhostArchery", allowGhostArchery); + disableArcheryOnStrongCreatures = Prop.getBooleanProperty("disableArcheryOnStrongCreatures", disableArcheryOnStrongCreatures); + genesisEnchantedGrassNewborns = Prop.getBooleanProperty("genesisEnchantedGrassNewborns", genesisEnchantedGrassNewborns); + useCustomCorpseSizes = Prop.getBooleanProperty("useCustomCorpseSizes", useCustomCorpseSizes); + allowCustomCreatureBreedNames = Prop.getBooleanProperty("allowCustomCreatureBreedNames", allowCustomCreatureBreedNames); + allowGhostBreeding = Prop.getBooleanProperty("allowGhostBreeding", allowGhostBreeding); + useCustomCreatureSizes = Prop.getBooleanProperty("useCustomCreatureSizes", useCustomCreatureSizes); + useCustomCreatureSFX = Prop.getBooleanProperty("useCustomCreatureSFX", useCustomCreatureSFX); + preventLegendaryHitching = Prop.getBooleanProperty("preventLegendaryHitching", preventLegendaryHitching); + modifyNewCreatures = Prop.getBooleanProperty("modifyNewCreatures", modifyNewCreatures); + logCreatureSpawns = Prop.getBooleanProperty("logCreatureSpawns", logCreatureSpawns); + allowEpicCreatureNaturalSpawns = Prop.getBooleanProperty("allowEpicCreatureNaturalSpawns", allowEpicCreatureNaturalSpawns); + enableCustomCreatures = Prop.getBooleanProperty("enableCustomCreatures", enableCustomCreatures); + enableWyverns = Prop.getBooleanProperty("enableWyverns", enableWyverns); + enableFlavorMobs = Prop.getBooleanProperty("enableFlavorMobs", enableFlavorMobs); + enableEventMobs = Prop.getBooleanProperty("enableEventMobs", enableEventMobs); + enableRareSpawns = Prop.getBooleanProperty("enableRareSpawns", enableRareSpawns); + enableCustomLegendaries = Prop.getBooleanProperty("enableCustomLegendaries", enableCustomLegendaries); + enableTitans = Prop.getBooleanProperty("enableTitans", enableTitans); + + // Bounty Module + enableBountyModule = Prop.getBooleanProperty("enableBountyModule", enableBountyModule); + usePlayerBounty = Prop.getBooleanProperty("usePlayerBounty", usePlayerBounty); + useLootTable = Prop.getBooleanProperty("useLootTable", useLootTable); + + // Item Module + enableItemModule = Prop.getBooleanProperty("enableItemModule", enableItemModule); + combineLeather = Prop.getBooleanProperty("combineLeather", combineLeather); + combineLogs = Prop.getBooleanProperty("combineLogs", combineLogs); + reduceLogVolume = Prop.getBooleanProperty("reduceLogVolume", reduceLogVolume); + reduceKindlingVolume = Prop.getBooleanProperty("reduceKindlingVolume", reduceKindlingVolume); + droppableSleepPowder = Prop.getBooleanProperty("droppableSleepPowder", droppableSleepPowder); + setSilverMirrorPrice = Prop.getBooleanProperty("setSilverMirrorPrice", setSilverMirrorPrice); + setGoldMirrorPrice = Prop.getBooleanProperty("setGoldMirrorPrice", setGoldMirrorPrice); + setCreatureCratePrice = Prop.getBooleanProperty("setCreatureCratePrice", setCreatureCratePrice); + setResurrectionStonePrice = Prop.getBooleanProperty("setResurrectionStonePrice", setResurrectionStonePrice); + setShakerOrbPrice = Prop.getBooleanProperty("setShakerOrbPrice", setShakerOrbPrice); + loadableMailbox = Prop.getBooleanProperty("loadableMailbox", loadableMailbox); + loadableBellTower = Prop.getBooleanProperty("loadableBellTower", loadableBellTower); + loadableTrashBin = Prop.getBooleanProperty("loadableTrashBin", loadableTrashBin); + loadableAltars = Prop.getBooleanProperty("loadableAltars", loadableAltars); + oneHandedLongSpear = Prop.getBooleanProperty("oneHandedLongSpear", oneHandedLongSpear); + reduceDirtDifficulty = Prop.getBooleanProperty("reduceDirtDifficulty", reduceDirtDifficulty); + reduceSandDifficulty = Prop.getBooleanProperty("reduceSandDifficulty", reduceSandDifficulty); + reduceSandstoneDifficulty = Prop.getBooleanProperty("reduceSandstoneDifficulty", reduceSandstoneDifficulty); + decorationStoneKeystone = Prop.getBooleanProperty("decorationStoneKeystone", decorationStoneKeystone); + decorationMarbleKeystone = Prop.getBooleanProperty("decorationMarbleKeystone", decorationMarbleKeystone); + decorationSkull = Prop.getBooleanProperty("decorationSkull", decorationSkull); + useCustomCacheFragments = Prop.getBooleanProperty("useCustomCacheFragments", useCustomCacheFragments); + adjustStatueFragmentCount = Prop.getBooleanProperty("adjustStatueFragmentCount", adjustStatueFragmentCount); + removeLockpickSkillRequirement = Prop.getBooleanProperty("removeLockpickSkillRequirement", removeLockpickSkillRequirement); + createCustomItemTemplates = Prop.getBooleanProperty("createCustomItemTemplates", createCustomItemTemplates); + enableCustomItemCreation = Prop.getBooleanProperty("enableCustomItemCreation", enableCustomItemCreation); + craftHuntingArrowPacks = Prop.getBooleanProperty("craftHuntingArrowPacks", craftHuntingArrowPacks); + craftWarArrowPacks = Prop.getBooleanProperty("craftWarArrowPacks", craftWarArrowPacks); + craftBattleYoyo = Prop.getBooleanProperty("craftBattleYoyo", craftBattleYoyo); + craftClub = Prop.getBooleanProperty("craftClub", craftClub); + craftDepthDrill = Prop.getBooleanProperty("craftDepthDrill", craftDepthDrill); + craftEternalReservoir = Prop.getBooleanProperty("craftEternalReservoir", craftEternalReservoir); + craftEviscerator = Prop.getBooleanProperty("craftEviscerator", craftEviscerator); + craftKnuckles = Prop.getBooleanProperty("craftKnuckles", craftKnuckles); + craftMassStorageUnit = Prop.getBooleanProperty("craftMassStorageUnit", craftMassStorageUnit); + craftStatuetteDeities = Prop.getBooleanProperty("craftStatuetteDeities", craftStatuetteDeities); + craftWarhammer = Prop.getBooleanProperty("craftWarhammer", craftWarhammer); + + // Soulstealing Module + enableSoulstealingModule = Prop.getBooleanProperty("enableSoulstealingModule", enableSoulstealingModule); + pollEternalReservoirTime = Prop.getLongProperty("pollEternalReservoirTime", pollEternalReservoirTime); + + // Action Module + enableActionModule = Prop.getBooleanProperty("enableActionModule", enableActionModule); + actionUnequipAll = Prop.getBooleanProperty("actionUnequipAll", actionUnequipAll); + actionReceiveAllMail = Prop.getBooleanProperty("actionReceiveAllMail", actionReceiveAllMail); + actionSplitSorcery = Prop.getBooleanProperty("actionSplitSorcery", actionSplitSorcery); + actionLeaderboard = Prop.getBooleanProperty("actionLeaderboard", actionLeaderboard); + actionSorceryFragmentCombine = Prop.getBooleanProperty("actionSorceryFragmentCombine", actionSorceryFragmentCombine); + actionArenaTeleports = Prop.getBooleanProperty("actionArenaTeleports", actionArenaTeleports); + actionAddMissionDev = Prop.getBooleanProperty("actionAddMissionDev", actionAddMissionDev); + actionRemoveMissionDev = Prop.getBooleanProperty("actionRemoveMissionDev", actionRemoveMissionDev); + actionCreatureReportDev = Prop.getBooleanProperty("actionCreatureReportDev", actionCreatureReportDev); + actionSmoothTerrainDev = Prop.getBooleanProperty("actionSmoothTerrainDev", actionSmoothTerrainDev); + + // Erosion Module + enableErosionModule = Prop.getBooleanProperty("enableErosionModule", enableErosionModule); + pollTerrainSmoothTime = Prop.getLongProperty("pollTerrainSmoothTime", pollTerrainSmoothTime); + // Treasure Chest Loot Module enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule); @@ -716,6 +904,8 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea logger.info("Disable Smelting Pots: " + disableSmeltingPots); logger.info("Hide Sorcery Buff Bar: " + hideSorceryBuffBar); logger.info("SQL Achievement Fix: " + sqlAchievementFix); + logger.info("Change Pumpkin King Title: "+changePumpkinKingTitle); + logger.info("Change Deity Passives: "+changeDeityPassives); } logger.info("Arena Module: "+enableArenaModule); @@ -929,6 +1119,109 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea logger.info("Depot Respawn Timer: "+depotRespawnTime); } + logger.info("Bestiary Module: "+enableBestiaryModule); + if (enableBestiaryModule){ + logger.info("Fix Sacrificing Strong Creatures: "+fixSacrificingStrongCreatures); + logger.info("Disable AFK Training: "+disableAfkTraining); + logger.info("Fix Chargers Walking Through Walls: "+fixChargersWalkingThroughWalls); + logger.info("Condition Wild Creatures: "+conditionWildCreatures); + logger.info("Allow Ghost Archery: "+allowGhostArchery); + logger.info("Disable Archery On Strong Creatures: "+disableArcheryOnStrongCreatures); + logger.info("Genesis Enchanted Grass Newborns: "+genesisEnchantedGrassNewborns); + logger.info("Use Custom Corpse Sizes: "+useCustomCorpseSizes); + logger.info("Allow Custom Creature Breed Names: "+allowCustomCreatureBreedNames); + logger.info("Allow Ghost Breeding: "+allowGhostBreeding); + logger.info("Allow Ghost Corpses: "+allowGhostCorpses); + logger.info("Use Custom Creature Sizes: "+useCustomCreatureSizes); + logger.info("Use Custom Creature SFX: "+useCustomCreatureSFX); + logger.info("Prevent Legendary Hitching: "+preventLegendaryHitching); + logger.info("Modify New Creatures: "+modifyNewCreatures); + logger.info("Log Creature Spawns: "+logCreatureSpawns); + logger.info("Enable Epic Creature Natural Spawns: "+allowEpicCreatureNaturalSpawns); + logger.info("Custom Creatures: "+enableCustomCreatures); + if (enableCustomCreatures){ + logger.info("Enable Wyverns: "+enableWyverns); + logger.info("Enable Flavor Mobs: "+enableFlavorMobs); + logger.info("Enable Event Mobs: "+enableEventMobs); + logger.info("Enable Rare Spawn Mobs: "+enableRareSpawns); + logger.info("Enable Custom Legendaries: "+enableCustomLegendaries); + logger.info("Enable Titans: "+enableTitans); + } + } + + logger.info("Bounty Module: "+enableBountyModule); + if (enableBountyModule){ + logger.info("Use Player Bounty: "+usePlayerBounty); + logger.info("Use Loot Table: "+useLootTable); + } + + logger.info("Item Module: "+enableItemModule); + if (enableItemModule){ + logger.info("Combine Leather: "+combineLeather); + logger.info("Combine Logs: "+combineLogs); + logger.info("Reduce Log Volume: "+reduceLogVolume); + logger.info("Reduce Kindling Volume: "+reduceKindlingVolume); + logger.info("Droppable Sleep Powder: "+droppableSleepPowder); + logger.info("Set Silver Mirror Price: "+setSilverMirrorPrice); + logger.info("Set Gold Mirror Price: "+setGoldMirrorPrice); + logger.info("Set Creature Crate Price: "+setCreatureCratePrice); + logger.info("Set Resurrection Stone Price: "+setResurrectionStonePrice); + logger.info("Set Shaker Orb Price: "+setShakerOrbPrice); + logger.info("Loadable Mailbox: "+loadableMailbox); + logger.info("Loadable Bell Tower: "+loadableBellTower); + logger.info("Loadable Trash Bin: "+loadableTrashBin); + logger.info("Loadable Altars: "+loadableAltars); + logger.info("One Handed Long Spear: "+oneHandedLongSpear); + logger.info("Reduce Dirt Difficulty: "+reduceDirtDifficulty); + logger.info("Reduce Sand Difficulty: "+reduceSandDifficulty); + logger.info("Reduce Sandstone Difficulty: "+reduceSandstoneDifficulty); + logger.info("Decoration Stone Keystone: "+decorationStoneKeystone); + logger.info("Decoration Marble Keystone: "+decorationMarbleKeystone); + logger.info("Decoration Skull: "+decorationSkull); + logger.info("Use Custom Cache Fragments: "+useCustomCacheFragments); + logger.info("Adjust Statue Fragment Count: "+adjustStatueFragmentCount); + logger.info("Remove Lockpick Skill Requirement: "+removeLockpickSkillRequirement); + logger.info("Create Custom Item Templates: "+createCustomItemTemplates); + logger.info("Custom Item Creation: "+enableCustomItemCreation); + if (enableCustomItemCreation){ + logger.info("Craft Hunting Arrow Packs: "+craftHuntingArrowPacks); + logger.info("Craft War Arrow Packs: "+craftWarArrowPacks); + logger.info("Craft Battle Yoyo: "+craftBattleYoyo); + logger.info("Craft Club: "+craftClub); + logger.info("Craft Depth Drill: "+craftDepthDrill); + logger.info("Craft Eternal Reservoir: "+craftEternalReservoir); + logger.info("Craft Eviscerator: "+craftEviscerator); + logger.info("Craft Knuckles: "+craftKnuckles); + logger.info("Craft Mass Storage Unit: "+craftMassStorageUnit); + logger.info("Craft Statuette Deities: "+craftStatuetteDeities); + logger.info("Craft Warhammer: "+craftWarhammer); + } + } + + logger.info("Soulstealing Module: "+enableSoulstealingModule); + if (enableSoulstealingModule){ + logger.info("Poll Eternal Reservoir Timer: "+pollEternalReservoirTime); + } + + logger.info("Action Module: "+enableActionModule); + if (enableActionModule){ + logger.info("Unequip All Action: "+actionUnequipAll); + logger.info("Receive All Mail Action: "+actionReceiveAllMail); + logger.info("Split Sorcery Action: "+actionSplitSorcery); + logger.info("Leaderboard Action: "+actionLeaderboard); + logger.info("Sorcery Fragment Combine Action: "+actionSorceryFragmentCombine); + logger.info("Arena Teleport Actions: "+actionArenaTeleports); + logger.info("Add Mission Dev Action: "+actionAddMissionDev); + logger.info("Remove Mission Dev Action: "+actionRemoveMissionDev); + logger.info("Creature Report Dev Action: "+actionCreatureReportDev); + logger.info("Smooth Terrain Dev Action: "+actionSmoothTerrainDev); + } + + logger.info("Erosion Module: "+enableErosionModule); + if (enableErosionModule){ + logger.info("Poll Terrain Smooth Timer: "+pollTerrainSmoothTime); + } + logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); } @@ -1024,13 +1317,16 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea SupplyDepots.preInit(); } + // Bestiary Module Pre-Init + if (enableBestiaryModule) { + Bestiary.preInit(); + } + // Treasure Chest Loot Module Pre-Init if (enableTreasureChestLootModule) { TreasureChests.preInit(); } - MethodsBestiary.preInit(); - // Only clears responses, doesn't have any effect. Harmless to run even if key fragments are not used. KeyEvent.preInit(); @@ -1068,92 +1364,113 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void init() { logger.info("Initializing."); + ModCreatures.init(); + ModVehicleBehaviours.init(); + if (WyvernMods.enableCustomTitlesModule) { PlayerTitles.init(); } - ModCreatures.init(); - ModVehicleBehaviours.init(); + + if (WyvernMods.enableMiscChangesModule) { + MiscChanges.changeExistingTitles(); + } + + if (WyvernMods.enableBountyModule) { + Bounty.init(); + } // Vanilla: - logger.info("Registering Vanilla creature changes."); - if (enableMountedModule && allowBisonMounts) { + if (WyvernMods.enableMountedModule && WyvernMods.allowBisonMounts) { logger.info("Allowing Bison to be mounted."); ModCreatures.addCreature(new Bison()); } // Epic: - logger.info("Registering Epic creatures."); - ModCreatures.addCreature(new LavaFiend()); - ModCreatures.addCreature(new SolDemon()); - ModCreatures.addCreature(new Worg()); - - // Wyverns: - logger.info("Registering Wyverns."); - ModCreatures.addCreature(new WyvernBlack()); - ModCreatures.addCreature(new WyvernGreen()); - ModCreatures.addCreature(new WyvernRed()); - ModCreatures.addCreature(new WyvernWhite()); - ModCreatures.addCreature(new WyvernBlue()); - - // Flavor Mobs: - logger.info("Registering Flavor creatures."); - ModCreatures.addCreature(new Avenger()); - ModCreatures.addCreature(new FireCrab()); - ModCreatures.addCreature(new ForestSpider()); - ModCreatures.addCreature(new Giant()); - ModCreatures.addCreature(new Charger()); - ModCreatures.addCreature(new HornedPony()); - ModCreatures.addCreature(new LargeBoar()); - ModCreatures.addCreature(new SpiritTroll()); + if (WyvernMods.enableBestiaryModule && WyvernMods.allowEpicCreatureNaturalSpawns) { + logger.info("Allowing epic creatures to spawn naturally."); + ModCreatures.addCreature(new LavaFiend()); + ModCreatures.addCreature(new SolDemon()); + ModCreatures.addCreature(new Worg()); + } - // Event Mobs: - logger.info("Registering Event creatures."); - ModCreatures.addCreature(new IceCat()); - ModCreatures.addCreature(new FireGiant()); - ModCreatures.addCreature(new GuardianMagranon()); - - // Bosses: - logger.info("Registering Custom Boss creatures."); - ModCreatures.addCreature(new Reaper()); - ModCreatures.addCreature(new SpectralDrake()); - // Uniques: - ModCreatures.addCreature(new Facebreyker()); - - // Titans: - ModCreatures.addCreature(new Ifrit()); - ModCreatures.addCreature(new Lilith()); - // Titan Spawns: - ModCreatures.addCreature(new IfritFiend()); - ModCreatures.addCreature(new IfritSpider()); - ModCreatures.addCreature(new LilithWraith()); - ModCreatures.addCreature(new LilithZombie()); - - // NPC's - logger.info("Registering Custom NPC creatures."); - //ModCreatures.addCreature(new RobZombie()); - //ModCreatures.addCreature(new MacroSlayer()); - ModCreatures.addCreature(new Terror()); - - Bounty.init(); - - Mastercraft.changeExistingTitles(); + if (WyvernMods.enableBestiaryModule && WyvernMods.enableCustomCreatures) { + // Wyverns: + if (WyvernMods.enableWyverns) { + logger.info("Registering Wyverns."); + ModCreatures.addCreature(new WyvernBlack()); + ModCreatures.addCreature(new WyvernGreen()); + ModCreatures.addCreature(new WyvernRed()); + ModCreatures.addCreature(new WyvernWhite()); + ModCreatures.addCreature(new WyvernBlue()); + } + + // Flavor Mobs: + if (WyvernMods.enableFlavorMobs) { + logger.info("Registering Flavor creatures."); + ModCreatures.addCreature(new Avenger()); + ModCreatures.addCreature(new FireCrab()); + ModCreatures.addCreature(new ForestSpider()); + ModCreatures.addCreature(new Giant()); + ModCreatures.addCreature(new Charger()); + ModCreatures.addCreature(new HornedPony()); + ModCreatures.addCreature(new LargeBoar()); + ModCreatures.addCreature(new SpiritTroll()); + } + + // Event Mobs: + if (WyvernMods.enableEventMobs) { + logger.info("Registering Event creatures."); + ModCreatures.addCreature(new IceCat()); + ModCreatures.addCreature(new FireGiant()); + ModCreatures.addCreature(new GuardianMagranon()); + ModCreatures.addCreature(new Terror()); + } + + // Rare Spawns: + if (WyvernMods.enableRareSpawns) { + logger.info("Registering Rare Spawn creatures."); + ModCreatures.addCreature(new Reaper()); + ModCreatures.addCreature(new SpectralDrake()); + } + + // Legendaries: + if (WyvernMods.enableCustomLegendaries) { + logger.info("Registering Legendary creatures."); + ModCreatures.addCreature(new Facebreyker()); + } + + // Titans: + if (WyvernMods.enableTitans) { + logger.info("Registering Titans."); + ModCreatures.addCreature(new Ifrit()); + ModCreatures.addCreature(new Lilith()); + // Titan Spawns: + logger.info("Register Titan Spawns."); + ModCreatures.addCreature(new IfritFiend()); + ModCreatures.addCreature(new IfritSpider()); + ModCreatures.addCreature(new LilithWraith()); + ModCreatures.addCreature(new LilithZombie()); + } + } } @Override public void onItemTemplatesCreated() { - logger.info("Creating Item Mod items."); - ItemMod.createItems(); - logger.info("Creating Cache items."); - Caches.createItems(); - logger.info("Initiating Title changes."); - //PlayerTitles.onItemTemplatesCreated(); - try { - logger.info("Editing existing item templates."); - ItemMod.modifyItems(); - logger.info("Registering permissions hook for custom items."); - ItemMod.registerPermissionsHook(); - } catch (NoSuchTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { - e.printStackTrace(); + if (WyvernMods.enableItemModule) { + if (WyvernMods.createCustomItemTemplates) { + logger.info("Creating Item Mod item templates."); + ItemMod.createItems(); + logger.info("Creating Cache item templates."); + Caches.createItems(); + } + try { + logger.info("Editing existing item templates."); + ItemMod.modifyItems(); + logger.info("Registering permissions hook for custom items."); + ItemMod.registerPermissionsHook(); + } catch (NoSuchTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } } } @@ -1170,52 +1487,78 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void onServerStarted() { try { - logger.info("Registering Item Mod creation entries."); - ItemMod.initCreationEntries(); - logger.info("Registering Item Mod actions."); - ItemMod.registerActions(); - logger.info("Registering Cache actions."); - Caches.registerActions(); - logger.info("Registering Soulstealer actions."); - Soulstealing.registerActions(); - logger.info("Registering Custom actions."); - ModActions.registerAction(new UnequipAllAction()); - ModActions.registerAction(new ReceiveMailAction()); - ModActions.registerAction(new LeaderboardAction()); - ModActions.registerAction(new AddSubGroupAction()); - ModActions.registerAction(new SorcerySplitAction()); - ModActions.registerAction(new LeaderboardSkillAction()); - logger.info("Registering Arena actions."); - ModActions.registerAction(new SorceryCombineAction()); - //ModActions.registerAction(new VillageTeleportAction()); // [3/28/18] Disabled - Highway Portals added instead. - ModActions.registerAction(new ArenaTeleportAction()); - ModActions.registerAction(new ArenaEscapeAction()); - logger.info("Registering Dev actions."); - ModActions.registerAction(new MissionAddAction()); - ModActions.registerAction(new MissionRemoveAction()); - ModActions.registerAction(new CreatureReportAction()); - ModActions.registerAction(new SmoothTerrainAction()); - logger.info("Setting custom creature corpse models."); - MethodsBestiary.setTemplateVariables(); - logger.info("Setting up Achievement templates."); - AchievementChanges.onServerStarted(); - - DeityChanges.onServerStarted(); - - //espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default. - //espCounter = false; - - if (enableSkillModule) { - SkillChanges.onServerStarted(); + if (WyvernMods.enableBestiaryModule) { + logger.info("Setting custom creature template variables."); + Bestiary.setTemplateVariables(); + } + if (WyvernMods.enableItemModule) { + ItemMod.onServerStarted(); + if (WyvernMods.enableCustomItemCreation) { + logger.info("Registering Item Mod creation entries."); + ItemMod.initCreationEntries(); + } + if (WyvernMods.createCustomItemTemplates) { + logger.info("Registering Item Mod actions."); + ItemMod.registerActions(); + logger.info("Registering Cache actions."); + Caches.registerActions(); + } + } + if (WyvernMods.enableSoulstealingModule) { + logger.info("Registering Soulstealer actions."); + Soulstealing.registerActions(); + } + if (WyvernMods.enableActionModule) { + logger.info("Registering Custom actions."); + if (WyvernMods.actionUnequipAll) { + ModActions.registerAction(new UnequipAllAction()); + } + if (WyvernMods.actionReceiveAllMail) { + ModActions.registerAction(new ReceiveMailAction()); + } + if (WyvernMods.actionSplitSorcery) { + ModActions.registerAction(new SorcerySplitAction()); + } + if (WyvernMods.actionLeaderboard) { + ModActions.registerAction(new LeaderboardAction()); + ModActions.registerAction(new LeaderboardSkillAction()); + } + //ModActions.registerAction(new AddSubGroupAction()); // [5/14/19] Disabled - Added to base game. + logger.info("Registering Arena actions."); + if (WyvernMods.actionSorceryFragmentCombine) { + ModActions.registerAction(new SorceryCombineAction()); + } + if (WyvernMods.actionArenaTeleports) { + ModActions.registerAction(new ArenaTeleportAction()); + ModActions.registerAction(new ArenaEscapeAction()); + } + logger.info("Registering Dev actions."); + if (WyvernMods.actionAddMissionDev) { + ModActions.registerAction(new MissionAddAction()); + } + if (WyvernMods.actionRemoveMissionDev) { + ModActions.registerAction(new MissionRemoveAction()); + } + if (WyvernMods.actionCreatureReportDev) { + ModActions.registerAction(new CreatureReportAction()); + } + if (WyvernMods.actionSmoothTerrainDev) { + ModActions.registerAction(new SmoothTerrainAction()); + } } - CreationEntry lockpicks = CreationMatrix.getInstance().getCreationEntry(ItemList.lockpick); - try { - ReflectionUtil.setPrivateField(lockpicks, ReflectionUtil.getField(lockpicks.getClass(), "hasMinimumSkillRequirement"), false); - ReflectionUtil.setPrivateField(lockpicks, ReflectionUtil.getField(lockpicks.getClass(), "minimumSkill"), 0.0); - } catch (IllegalAccessException | NoSuchFieldException e) { - logger.info("Failed to set lockpick creation entry changes!"); - e.printStackTrace(); + // Sets up achievement changes specifically for the Leaderboard system. + if (WyvernMods.enableActionModule && WyvernMods.actionLeaderboard) { + logger.info("Setting up Leaderboard Achievement templates."); + AchievementChanges.onServerStarted(); + } + + if (WyvernMods.enableMiscChangesModule && WyvernMods.changeDeityPassives) { + DeityChanges.onServerStarted(); + } + + if (WyvernMods.enableSkillModule) { + SkillChanges.onServerStarted(); } } catch (IllegalArgumentException | ClassCastException e) { @@ -1230,7 +1573,6 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static long lastPolledDepots = 0; public static long lastPolledRareSpawns = 0; public static long lastPolledEternalReservoirs = 0; - public static final long pollEternalReservoirTime = TimeConstants.MINUTE_MILLIS*10; public static long lastPolledMissionCreator = 0; /* Disabled for now, might need to be revisited. public static long lastPolledBloodlust = 0; @@ -1240,31 +1582,30 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public static long lastPolledUniqueCollection = 0; public static final long pollUniqueCollectionTime = TimeConstants.MINUTE_MILLIS*5; public static long lastPolledTerrainSmooth = 0; - public static final long pollTerrainSmoothTime = TimeConstants.SECOND_MILLIS*5; @Override public void onServerPoll() { if((lastSecondPolled + TimeConstants.SECOND_MILLIS) < System.currentTimeMillis()){ - if(enableSupplyDepotModule && lastPolledDepots + pollDepotTime < System.currentTimeMillis()){ + if(WyvernMods.enableSupplyDepotModule && lastPolledDepots + pollDepotTime < System.currentTimeMillis()){ SupplyDepots.pollDepotSpawn(); lastPolledDepots += pollDepotTime; } - if(enableTitanModule && lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){ + if(WyvernMods.enableTitanModule && lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){ Titans.pollTitanSpawn(); lastPolledTitanSpawn += pollTitanSpawnTime; } - if(enableTitanModule && lastPolledTitans + pollTitanTime < System.currentTimeMillis()){ + if(WyvernMods.enableTitanModule && lastPolledTitans + pollTitanTime < System.currentTimeMillis()){ Titans.pollTitans(); lastPolledTitans += pollTitanTime; } - if(enableRareSpawnModule && lastPolledRareSpawns + pollRareSpawnTime < System.currentTimeMillis()){ + if(WyvernMods.enableRareSpawnModule && lastPolledRareSpawns + pollRareSpawnTime < System.currentTimeMillis()){ RareSpawns.pollRareSpawns(); lastPolledRareSpawns += pollRareSpawnTime; } - if(lastPolledEternalReservoirs + pollEternalReservoirTime < System.currentTimeMillis()){ + if(WyvernMods.enableSoulstealingModule && lastPolledEternalReservoirs + pollEternalReservoirTime < System.currentTimeMillis()){ Soulstealing.pollSoulForges(); lastPolledEternalReservoirs += pollEternalReservoirTime; } - if(enableMissionModule && enableNewMissionCreator && lastPolledMissionCreator + pollMissionCreatorTime < System.currentTimeMillis()){ + if(WyvernMods.enableMissionModule && enableNewMissionCreator && lastPolledMissionCreator + pollMissionCreatorTime < System.currentTimeMillis()){ MissionCreator.pollMissions(); lastPolledMissionCreator += pollMissionCreatorTime; } @@ -1273,7 +1614,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea Bloodlust.pollLusts(); lastPolledBloodlust += pollBloodlustTime; }*/ - if(WyvernMods.useStaticLegendaryRegeneration && lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){ + if(WyvernMods.enableCombatModule && WyvernMods.useStaticLegendaryRegeneration && lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){ CombatChanges.pollUniqueRegeneration(); lastPolledUniqueRegeneration += pollUniqueRegenerationTime; } @@ -1281,7 +1622,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea CombatChanges.pollUniqueCollection(); lastPolledUniqueCollection += pollUniqueCollectionTime; } - if(lastPolledTerrainSmooth + pollTerrainSmoothTime < System.currentTimeMillis()){ + if(WyvernMods.enableErosionModule && lastPolledTerrainSmooth + pollTerrainSmoothTime < System.currentTimeMillis()){ SmoothTerrainAction.onServerPoll(); lastPolledTerrainSmooth += pollTerrainSmoothTime; } From bd37f68857fc3c98596553e73c1a5dc01678bf97 Mon Sep 17 00:00:00 2001 From: Sindusk Date: Tue, 14 May 2019 15:21:19 -0400 Subject: [PATCH 8/8] Update to Version 2.0: WyvernMods Configurable. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5032b80..e9af182 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' group "mod.sin" -version "1.4" +version "2.0" repositories { mavenCentral()