Merged everything, should be stable
This commit is contained in:
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -41,7 +41,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()));
|
||||
|
||||
@@ -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()){
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.wurmonline.server.items.Item;
|
||||
import com.wurmonline.server.players.Player;
|
||||
import com.wurmonline.server.villages.Village;
|
||||
import mod.sin.items.StableContract;
|
||||
import mod.sin.wyvern.bestiary.MethodsBestiary;
|
||||
import mod.sin.wyvern.Bestiary;
|
||||
import org.gotti.wurmunlimited.modsupport.actions.*;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -85,7 +85,7 @@ public class StableContractAction implements ModAction, BehaviourProvider, Actio
|
||||
float x = performer.getPosX();
|
||||
float y = performer.getPosY();
|
||||
byte gender = (byte)new Random().nextInt(2);
|
||||
String name = "Stable master " + (gender == 0 ? MethodsBestiary.generateGuardMaleName() : MethodsBestiary.generateGuardFemaleName());
|
||||
String name = "Stable master " + (gender == 0 ? Bestiary.generateGuardMaleName() : Bestiary.generateGuardFemaleName());
|
||||
|
||||
|
||||
Creature stablemaster = Creature.doNew(stablemasterID, x, y, 180.0f, performer.getLayer(), name, gender, performer.getKingdomId());
|
||||
|
||||
@@ -93,7 +93,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());
|
||||
|
||||
@@ -31,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(ArmourTemplate.ARMOUR_TYPE_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);
|
||||
|
||||
|
||||
@@ -125,14 +125,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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,8 @@ 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_FULLPRICE,
|
||||
ItemTypes.ITEM_TYPE_NOSELLBACK,
|
||||
ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE
|
||||
ItemTypes.ITEM_TYPE_NOSELLBACK
|
||||
});
|
||||
itemBuilder.imageNumber((short) 919);
|
||||
itemBuilder.behaviourType((short) 1);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.wurmonline.server.players.AchievementTemplate;
|
||||
import com.wurmonline.server.players.Achievements;
|
||||
import com.wurmonline.server.players.Titles;
|
||||
import mod.sin.wyvern.mastercraft.CustomTitles;
|
||||
import mod.sin.wyvern.mastercraft.Mastercraft;
|
||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -316,7 +315,7 @@ public class AchievementChanges {
|
||||
if(a.getTemplate() == gremlinSlayer) {
|
||||
logger.info("Achievement at " + count);
|
||||
if(count >= 100) {
|
||||
return CustomTitles.GremlinSlayer;
|
||||
return Titles.Title.getTitle(CustomTitles.GREMLIN_SLAYER);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -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! - //
|
||||
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);
|
||||
/*ctCommunicator.getDeclaredMethod("sendCaveStrip").setBody("{"
|
||||
+ " mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$);"
|
||||
+ "}");*/
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@@ -24,6 +24,7 @@ import mod.sin.items.caches.*;
|
||||
import mod.sin.lib.Util;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
||||
import org.nyxcode.wurm.discordrelay.DiscordRelay;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -82,6 +83,12 @@ public class Arena {
|
||||
nsq.sendQuestion();
|
||||
}
|
||||
|
||||
public static void sendHotaMessage(String message){
|
||||
if (SupplyDepots.host != null) {
|
||||
MiscChanges.sendGlobalFreedomChat(SupplyDepots.host, message, 200, 200, 200);
|
||||
}
|
||||
DiscordRelay.sendToDiscord("arena", message, true);
|
||||
}
|
||||
|
||||
public static void createNewHotaPrize(Village v, int winStreak){
|
||||
try {
|
||||
@@ -110,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);
|
||||
@@ -176,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);
|
||||
@@ -218,6 +216,8 @@ 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");
|
||||
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){"
|
||||
@@ -226,23 +226,9 @@ public class Arena {
|
||||
+ " $_ = $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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// - Allow lockpicking on PvP server, as well as treasure chests on PvE - //
|
||||
CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour");
|
||||
@@ -258,6 +244,8 @@ public class Arena {
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
|
||||
CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems");
|
||||
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;"
|
||||
@@ -266,43 +254,43 @@ public class Arena {
|
||||
+ "}";
|
||||
Util.instrumentDescribed(thisClass, ctItemBehaviour, "action", desc1, "isInPvPZone", replace);
|
||||
|
||||
CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems");
|
||||
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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// - Disable villages and PMK's on the PvP server - //
|
||||
CtClass ctVillageFoundationQuestion = classPool.get("com.wurmonline.server.questions.VillageFoundationQuestion");
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
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);"
|
||||
+ "}";
|
||||
@@ -321,6 +309,7 @@ public class Arena {
|
||||
" }" +
|
||||
"}";
|
||||
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");
|
||||
@@ -333,6 +322,8 @@ public class Arena {
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2);
|
||||
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);" +
|
||||
@@ -344,55 +335,29 @@ public class Arena {
|
||||
+ "}"
|
||||
+ "$_ = $proceed($$);";
|
||||
Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "isChampion", replace);
|
||||
}
|
||||
|
||||
// - Modify when an enemy is present or not to use attitude instead of kingdom - //
|
||||
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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// - Block twigs and stones on the PvP server - //
|
||||
CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures");
|
||||
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);
|
||||
/*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;"
|
||||
+ "}");*/
|
||||
|
||||
// - Allow affinity stealing and battle rank changes - //
|
||||
if (WyvernMods.alwaysAllowAffinitySteal) {
|
||||
Util.setReason("Allow affinity stealing and battle rank changes.");
|
||||
replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){"
|
||||
+ " $_ = true;"
|
||||
@@ -400,72 +365,73 @@ public class Arena {
|
||||
+ " $_ = $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.");
|
||||
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 - //
|
||||
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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// 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 - //
|
||||
if (WyvernMods.disablePvPCorpseProtection) {
|
||||
Util.setReason("Ensure corpses are not loot protected.");
|
||||
replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){"
|
||||
+ " $_ = $proceed(false);"
|
||||
+ "}else{"
|
||||
+ " $_ = $proceed($$);"
|
||||
+ "}";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "die", "setProtected", replace);
|
||||
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.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");
|
||||
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");
|
||||
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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// - Allow taking ownership of vehicles on Arena - //
|
||||
// TODO: Fix.
|
||||
if (WyvernMods.sameKingdomVehicleTheft) {
|
||||
Util.setReason("Allow taking ownership of vehicles on Arena.");
|
||||
CtClass[] params3 = new CtClass[]{
|
||||
CtClass.longType,
|
||||
@@ -477,56 +443,42 @@ 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");
|
||||
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);
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
// - Prevent tons of errors for legality on Arena. - //
|
||||
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);
|
||||
/*ctCreature.getDeclaredMethod("isOkToKillBy").insertBefore(""
|
||||
+ "if(com.wurmonline.server.Servers.localServer.PVPSERVER){"
|
||||
+ " return true;"
|
||||
+ "}");*/
|
||||
Util.setReason("Adjust same-kingdom permissions on Arena.");
|
||||
Util.insertBeforeDeclared(thisClass, ctCreature, "hasBeenAttackedBy", replace);
|
||||
/*ctCreature.getDeclaredMethod("hasBeenAttackedBy").insertBefore(""
|
||||
+ "if(com.wurmonline.server.Servers.localServer.PVPSERVER){"
|
||||
+ " return true;"
|
||||
+ "}");*/
|
||||
}
|
||||
|
||||
// - Disable CA Help on Arena - //
|
||||
Util.setReason("Disable CA HELP on Arena.");
|
||||
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");
|
||||
if (WyvernMods.sameKingdomVillageWarfare) {
|
||||
Util.setReason("Make players who are non-allied enemies of villages.");
|
||||
CtClass[] params4 = new CtClass[]{
|
||||
ctCreature,
|
||||
CtClass.booleanType
|
||||
@@ -570,10 +522,13 @@ public class Arena {
|
||||
"}" +
|
||||
"return false; }";
|
||||
Util.setBodyDescribed(thisClass, ctVillage, "isEnemy", desc5, replace);
|
||||
}
|
||||
|
||||
Util.setReason("Change HotA reward");
|
||||
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[]{
|
||||
@@ -581,23 +536,29 @@ public class Arena {
|
||||
CtClass.intType
|
||||
};
|
||||
String desc6 = Descriptor.ofMethod(CtClass.intType, params6);
|
||||
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");
|
||||
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 for now. A new system is in progress.\");" +
|
||||
" 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);
|
||||
}
|
||||
|
||||
if (WyvernMods.adjustLocalRange) {
|
||||
Util.setReason("Reduce local range (player).");
|
||||
replace = "if($3 > 5){" +
|
||||
" $_ = $proceed($1, $2, 50);" +
|
||||
@@ -608,7 +569,9 @@ public class Arena {
|
||||
Util.setReason("Reduce local range (creature).");
|
||||
replace = "$_ = true;";
|
||||
Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isPlayer", 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){" +
|
||||
@@ -617,19 +580,25 @@ public class Arena {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctKarmaQuestion, "answer", "isInPvPZone", 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);
|
||||
}
|
||||
|
||||
if (WyvernMods.adjustBashTimer) {
|
||||
CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure");
|
||||
Util.setReason("Increase bash timer to 15 seconds.");
|
||||
Util.setReason("Increase bash timer.");
|
||||
replace = "time = 600;" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctMethodsStructure, "destroyWall", "getStructure", 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);" +
|
||||
@@ -644,8 +613,9 @@ public class Arena {
|
||||
" " + Arena.class.getName() + ".sendHotaMessage($1.getName() + \" conquers the \" + $2.getName() + \".\");" +
|
||||
"}";
|
||||
Util.insertBeforeDeclared(thisClass, ctHota, "addPillarConquered", replace);
|
||||
}
|
||||
|
||||
// handle_TARGET_and_TARGET_HOSTILE
|
||||
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){" +
|
||||
@@ -654,17 +624,23 @@ public class Arena {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctCreatureBehaviour, "handle_TARGET_and_TARGET_HOSTILE", "isFriendlyKingdom", 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.");
|
||||
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);
|
||||
}
|
||||
|
||||
if (WyvernMods.allowSameKingdomFightSkillGains) {
|
||||
Util.setReason("Fix fight skill gains against enemy players.");
|
||||
replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" +
|
||||
" if($0 == this){" +
|
||||
@@ -676,28 +652,15 @@ public class Arena {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "getKingdomId", 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.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);*/
|
||||
|
||||
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){" +
|
||||
@@ -705,6 +668,8 @@ public class Arena {
|
||||
"return;" +
|
||||
"}";
|
||||
Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace);
|
||||
}
|
||||
|
||||
CtClass ctMeshIO = classPool.get("com.wurmonline.mesh.MeshIO");
|
||||
CtClass[] params7 = new CtClass[]{
|
||||
ctCreature,
|
||||
@@ -718,20 +683,25 @@ public class Arena {
|
||||
CtClass.booleanType
|
||||
};
|
||||
String desc7 = Descriptor.ofMethod(CtClass.booleanType, params7);
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
@@ -760,26 +730,32 @@ 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);*/
|
||||
|
||||
if (WyvernMods.crownInfluenceOnAggression) {
|
||||
Util.setReason("Disable crown influence from spreading to enemies.");
|
||||
replace = "$_ = $0.getAttitude(this) == 1;";
|
||||
Util.instrumentDeclared(thisClass, ctPlayer, "spreadCrownInfluence", "isFriendlyKingdom", 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.instrumentDeclaredCount(thisClass, ctCreature, "die", "isOnCurrentServer", 1, replace);
|
||||
Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, 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.\");" +
|
||||
@@ -788,15 +764,19 @@ public class Arena {
|
||||
" 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.");
|
||||
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);
|
||||
}
|
||||
|
||||
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.\");" +
|
||||
@@ -805,6 +785,7 @@ public class Arena {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace);
|
||||
}
|
||||
|
||||
/*Util.setReason("Enable stealing from deeds.");
|
||||
replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" +
|
||||
@@ -814,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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package mod.sin.wyvern.bestiary;
|
||||
package mod.sin.wyvern;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Random;
|
||||
@@ -6,7 +6,6 @@ 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.*;
|
||||
@@ -22,8 +21,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;
|
||||
@@ -39,12 +36,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());
|
||||
|
||||
public static String generateGuardMaleName() {
|
||||
final int rand = Server.rand.nextInt(50);
|
||||
@@ -480,6 +476,17 @@ public class MethodsBestiary {
|
||||
}
|
||||
}
|
||||
|
||||
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{
|
||||
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
|
||||
@@ -547,6 +554,19 @@ public class MethodsBestiary {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
|
||||
@@ -616,18 +636,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) {
|
||||
@@ -652,6 +672,12 @@ public class MethodsBestiary {
|
||||
|
||||
// Set worg fields
|
||||
setWorgFields(CreatureTemplate.WORG_CID);
|
||||
|
||||
// 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){
|
||||
@@ -707,14 +733,21 @@ public class MethodsBestiary {
|
||||
public static void preInit(){
|
||||
try{
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
final Class<MethodsBestiary> thisClass = MethodsBestiary.class;
|
||||
final Class<Bestiary> 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 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");
|
||||
|
||||
if (WyvernMods.fixSacrificingStrongCreatures) {
|
||||
Util.setReason("Disable sacrificing strong creatures.");
|
||||
CtClass[] params1 = {
|
||||
ctCreature,
|
||||
ctCreature,
|
||||
@@ -723,30 +756,35 @@ public class MethodsBestiary {
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
|
||||
replace = "if("+MethodsBestiary.class.getName()+".isSacrificeImmune($2)){" +
|
||||
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("+MethodsBestiary.class.getName()+".blockSkillFrom($1, $0)){"+//"if($1.isPlayer() && $1.getTarget() != $0){" +
|
||||
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("+MethodsBestiary.class.getName()+".blockSkillFrom($1, $0)){" + //"if($1.isPlayer() && $1.getTarget() != $0){" +
|
||||
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{" +
|
||||
@@ -756,21 +794,38 @@ 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);
|
||||
|
||||
if (WyvernMods.fixChargersWalkingThroughWalls) {
|
||||
Util.setReason("Deny chargers walking through walls.");
|
||||
CtClass ctPathFinder = classPool.get("com.wurmonline.server.creatures.ai.PathFinder");
|
||||
replace = "if("+MethodsBestiary.class.getName()+".denyPathingOverride($0)){" +
|
||||
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.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace);
|
||||
Util.setReason("Deny chargers walking through walls.");
|
||||
Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.conditionWildCreatures) {
|
||||
Util.setReason("Apply random types to creatures in the wilderness.");
|
||||
CtClass[] params2 = {
|
||||
CtClass.intType,
|
||||
@@ -788,11 +843,12 @@ public class MethodsBestiary {
|
||||
CtClass.intType
|
||||
};
|
||||
String desc2 = Descriptor.ofMethod(ctCreature, params2);
|
||||
replace = "$10 = "+MethodsBestiary.class.getName()+".newCreatureType($1, $10);";
|
||||
replace = "$10 = " + Bestiary.class.getName() + ".newCreatureType($1, $10);";
|
||||
Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc2, replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.allowGhostArchery) {
|
||||
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() {
|
||||
@@ -804,7 +860,9 @@ public class MethodsBestiary {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (WyvernMods.disableArcheryOnStrongCreatures) {
|
||||
Util.setReason("Disable archery altogether against certain creatures.");
|
||||
CtClass[] params3 = {
|
||||
ctCreature,
|
||||
@@ -814,49 +872,91 @@ public class MethodsBestiary {
|
||||
ctAction
|
||||
};
|
||||
String desc3 = Descriptor.ofMethod(CtClass.booleanType, params3);
|
||||
replace = "if("+MethodsBestiary.class.getName()+".isArcheryImmune($1, $2)){"
|
||||
replace = "if(" + Bestiary.class.getName() + ".isArcheryImmune($1, $2)){"
|
||||
+ " return true;"
|
||||
+ "}";
|
||||
Util.insertBeforeDescribed(thisClass, ctArchery, "attack", desc3, replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.genesisEnchantedGrassNewborns) {
|
||||
Util.setReason("Auto-Genesis a creature born on enchanted grass");
|
||||
replace = MethodsBestiary.class.getName()+".checkEnchantedBreed(newCreature);"
|
||||
replace = Bestiary.class.getName() + ".checkEnchantedBreed(newCreature);"
|
||||
+ "$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "saveCreatureName", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.useCustomCorpseSizes) {
|
||||
Util.setReason("Set custom corpse sizes.");
|
||||
replace = "$_ = $proceed($$);"
|
||||
+ "if("+MethodsBestiary.class.getName()+".hasCustomCorpseSize(this)){"
|
||||
+ " "+MethodsBestiary.class.getName()+".setCorpseSizes(this, corpse);"
|
||||
+ "if(" + Bestiary.class.getName() + ".hasCustomCorpseSize(this)){"
|
||||
+ " " + Bestiary.class.getName() + ".setCorpseSizes(this, corpse);"
|
||||
+ "}";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "die", "addItem", replace);
|
||||
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);*/
|
||||
|
||||
if (WyvernMods.allowCustomCreatureBreedNames) {
|
||||
Util.setReason("Allow custom creatures to have breeding names.");
|
||||
replace = "$_ = "+MethodsBestiary.class.getName()+".shouldBreedName(this);";
|
||||
replace = "$_ = " + Bestiary.class.getName() + ".shouldBreedName(this);";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "isHorse", 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);
|
||||
}
|
||||
|
||||
if (WyvernMods.allowGhostCorpses) {
|
||||
Util.setReason("Allow ghost creatures to drop corpses.");
|
||||
replace = "if("+MethodsBestiary.class.getName()+".isGhostCorpse(this)){"
|
||||
replace = "if(" + Bestiary.class.getName() + ".isGhostCorpse(this)){"
|
||||
+ " $_ = false;"
|
||||
+ "}else{"
|
||||
+ " $_ = $proceed($$);"
|
||||
+ "}";
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace);
|
||||
Util.instrumentDescribed(thisClass, ctCreature, "die", desc5, "isGhost", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.useCustomCreatureSizes) {
|
||||
Util.setReason("Enable custom sizes for creatures.");
|
||||
replace = "{return " + Bestiary.class.getName() + ".getAdjustedSizeMod(this);}";
|
||||
Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", 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 ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone");
|
||||
CtClass[] params4 = {
|
||||
CtClass.longType,
|
||||
CtClass.booleanType,
|
||||
@@ -867,15 +967,41 @@ public class MethodsBestiary {
|
||||
};
|
||||
String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4);
|
||||
replace = "$_ = $proceed($$);" +
|
||||
MethodsBestiary.class.getName()+".addCreatureSpecialEffect(copyId != -10 ? copyId : creatureId, $0, creature);";
|
||||
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.");
|
||||
CtClass ctVehicle = classPool.get("com.wurmonline.server.behaviours.Vehicle");
|
||||
replace = "if("+MethodsBestiary.class.getName()+".isNotHitchable($1)){" +
|
||||
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);
|
||||
@@ -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;
|
||||
|
||||
@@ -67,6 +63,8 @@ public class Bloodlust {
|
||||
final Class<Bloodlust> 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 +95,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -91,114 +90,54 @@ public class Bounty {
|
||||
try {
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
final Class<Bounty> 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);"
|
||||
if (WyvernMods.usePlayerBounty) {
|
||||
Util.setReason("Hook for Player Bounty.");
|
||||
replace = PlayerBounty.class.getName() + ".checkPlayerBounty(player, this);"
|
||||
+ "$_ = $proceed($$);";
|
||||
Util.setReason("Inserting playerloot check");
|
||||
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");
|
||||
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.setReason("Inserting bodyloot check");
|
||||
Util.instrumentDeclared(thisClass, ctCreature, "die", "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;
|
||||
}
|
||||
}
|
||||
});*/
|
||||
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[] params = {
|
||||
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 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()+\"]\");");
|
||||
// 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
|
||||
replace = "$_ = $proceed($$);"
|
||||
//+ "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);";
|
||||
+ MethodsBestiary.class.getName()+".modifyNewCreature($1);";
|
||||
Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc, "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 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 -- //
|
||||
|
||||
@@ -9,38 +9,27 @@ 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 {
|
||||
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<Creature> uniques = new ArrayList<>();
|
||||
public static void pollUniqueCollection(){
|
||||
for(Creature cret : Creatures.getInstance().getCreatures()){
|
||||
@@ -151,112 +129,6 @@ public class CombatChanges {
|
||||
return damage > 1D;
|
||||
}
|
||||
|
||||
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()){
|
||||
@@ -276,70 +148,27 @@ public class CombatChanges {
|
||||
final Class<CombatChanges> thisClass = CombatChanges.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Make custom combat rating changes.");
|
||||
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
|
||||
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
||||
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
|
||||
CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction");
|
||||
|
||||
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("Increase unique 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 && $1.isUnique()){" +
|
||||
//" logger.info(\"Detected unique hit on a pet. Adding damage.\");" +
|
||||
" $5 = $5 * 2d;" +
|
||||
"}" +
|
||||
"if($2.isUnique() && $1 != null && $1.isDominated()){" +
|
||||
" logger.info(\"Detected pet hit on a unique. Reducing damage.\");" +
|
||||
" $5 = $5 * 0.5d;" +
|
||||
"}";
|
||||
Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);
|
||||
|
||||
Util.setReason("Adjust weapon damage type based on the potion/salve applied.");
|
||||
replace = "int wt = "+CombatChanges.class.getName()+".getWeaponType($1);"
|
||||
+ "if(wt != -1){"
|
||||
+ " type = wt;"
|
||||
+ " return wt;"
|
||||
+ "}";
|
||||
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace);
|
||||
|
||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
||||
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
|
||||
if (WyvernMods.fixMagranonDamageStacking) {
|
||||
// Normal combat version
|
||||
CtClass[] params2 = {
|
||||
ctCreature,
|
||||
ctItem,
|
||||
ctCreature
|
||||
};
|
||||
String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2);
|
||||
replace = "$_ = true;";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace);
|
||||
|
||||
CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction");
|
||||
|
||||
Util.setReason("Adjust bloodthirst cap up to 20k from 10k");
|
||||
replace = "$1 = 20000;" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclaredCount(thisClass, ctCombatHandler, "setDamage", "min", 5, replace);
|
||||
|
||||
Util.setReason("Fix magranon damage bonus stacking.");
|
||||
replace = "if(mildStack){" +
|
||||
@@ -349,15 +178,13 @@ public class CombatChanges {
|
||||
"}";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace);
|
||||
|
||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
||||
// AttackAction version
|
||||
CtClass[] params3 = {
|
||||
ctCreature,
|
||||
ctAttackAction,
|
||||
ctCreature
|
||||
};
|
||||
String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3);
|
||||
replace = "$_ = true;";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace);
|
||||
|
||||
Util.setReason("Fix magranon damage bonus stacking.");
|
||||
replace = "if(mildStack){" +
|
||||
@@ -366,26 +193,28 @@ public class CombatChanges {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.adjustCombatRatingSpellPower) {
|
||||
Util.setReason("Nerf truehit/excel.");
|
||||
replace = "$_ = $proceed($$) * 0.5f;";
|
||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace);
|
||||
}
|
||||
|
||||
Util.setReason("Nerf oakshell.");
|
||||
replace = "if(defender.isPlayer() && defender.getBonusForSpellEffect((byte)22) > 0f){" +
|
||||
" armourMod = "+CombatChanges.class.getName()+".getAdjustedOakshell(defender, armour, armourMod);" +
|
||||
"}" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getDamReductionBonusFor", replace);
|
||||
|
||||
Util.setReason("Disable natural regeneration on uniques.");
|
||||
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);"
|
||||
@@ -398,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");
|
||||
@@ -457,13 +278,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -11,18 +11,28 @@ 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.setTemplateDeity(Deities.DEITY_MAGRANON);
|
||||
thelastdab.setMountainGod(true);
|
||||
thelastdab.setHateGod(false); // Rolled Libila
|
||||
// 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){
|
||||
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);
|
||||
|
||||
@@ -44,7 +44,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);
|
||||
@@ -88,32 +88,50 @@ public class EconomicChanges {
|
||||
final Class<EconomicChanges> 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");
|
||||
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;"
|
||||
+ "}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);*/
|
||||
|
||||
if (WyvernMods.adjustSealedMapValue) {
|
||||
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.disableTraderRefill) {
|
||||
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.voidTraderMoney) {
|
||||
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);
|
||||
}
|
||||
|
||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||
throw new HookException(e);
|
||||
|
||||
@@ -25,6 +25,11 @@ public class GemAugmentation {
|
||||
Class<GemAugmentation> 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);";
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.wurmonline.server.items.*;
|
||||
import mod.sin.actions.items.magicitems.MagicItemMenuProvider;
|
||||
import mod.sin.actions.items.magicitems.MagicItemRechargeAction;
|
||||
import mod.sin.items.schematicitems.SchematicItems;
|
||||
import com.wurmonline.server.combat.ArmourTemplate;
|
||||
import com.wurmonline.server.items.*;
|
||||
import mod.sin.items.caches.*;
|
||||
import mod.sin.wyvern.util.ItemUtil;
|
||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||
@@ -52,6 +54,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 +63,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();
|
||||
@@ -127,9 +129,9 @@ public class ItemMod {
|
||||
CORPSE_DECORATION.createTemplate();
|
||||
DEPTH_DRILL.createTemplate();
|
||||
DISINTEGRATION_ROD.createTemplate();
|
||||
//ELECTRUM_LUMP.createTemplate();
|
||||
ENCHANT_ORB.createTemplate();
|
||||
ETERNAL_ORB.createTemplate();
|
||||
ETERNAL_RESERVOIR.createTemplate();
|
||||
EVISCERATOR.createTemplate();
|
||||
FRIYAN_TABLET.createTemplate();
|
||||
HUGE_CRATE.createTemplate();
|
||||
@@ -138,7 +140,6 @@ public class ItemMod {
|
||||
SEALED_MAP.createTemplate();
|
||||
SKELETON_DECORATION.createTemplate();
|
||||
SOUL.createTemplate();
|
||||
SOUL_FORGE.createTemplate();
|
||||
STATUETTE_BREYK.createTemplate();
|
||||
STATUETTE_CYBERHUSKY.createTemplate();
|
||||
TREASURE_BOX.createTemplate();
|
||||
@@ -221,20 +222,36 @@ public class ItemMod {
|
||||
}
|
||||
|
||||
public static void initCreationEntries(){
|
||||
logger.info("initCreationEntries()");
|
||||
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();
|
||||
if (WyvernMods.craftDepthDrill) {
|
||||
DEPTH_DRILL.initCreationEntry();
|
||||
//ELECTRUM_LUMP.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();
|
||||
@@ -247,6 +264,14 @@ public class ItemMod {
|
||||
CRYSTAL_PERMA_FROST.initCreationEntry();
|
||||
WAND_PERMA_FROST.initCreationEntry();
|
||||
|
||||
if (WyvernMods.craftStatuetteDeities) {
|
||||
STATUETTE_BREYK.initCreationEntry();
|
||||
STATUETTE_CYBERHUSKY.initCreationEntry();
|
||||
}
|
||||
if (WyvernMods.craftWarhammer) {
|
||||
WARHAMMER.initCreationEntry();
|
||||
WARHAMMER_HEAD.initCreationEntry();
|
||||
}
|
||||
|
||||
// Spectral set
|
||||
/*SPECTRAL_BOOT.initCreationEntry();
|
||||
@@ -264,58 +289,39 @@ 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(){
|
||||
public static void createCustomArmours(){
|
||||
try {
|
||||
logger.info("Beginning custom armour creation.");
|
||||
Map<Integer, Armour> armours = ReflectionUtil.getPrivateField(null, ReflectionUtil.getField(Armour.class, "armours"));
|
||||
|
||||
armours.put(SpectralBoot.templateId, new ArmourTemplate(SpectralBoot.templateId, ArmourTemplate.ARMOUR_TYPE_LEATHER_DRAGON., 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();
|
||||
}
|
||||
}**/
|
||||
}
|
||||
|
||||
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.6f, 2.1f, 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);
|
||||
@@ -369,28 +375,50 @@ public class ItemMod {
|
||||
|
||||
public static void modifyItems() throws NoSuchTemplateException, IllegalArgumentException, IllegalAccessException, ClassCastException, NoSuchFieldException{
|
||||
// Make leather able to be combined.
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
ItemTemplate acorn = ItemTemplateFactory.getInstance().getTemplate(ItemList.acorn);
|
||||
ReflectionUtil.setPrivateField(acorn, ReflectionUtil.getField(acorn.getClass(), "combine"), true);
|
||||
|
||||
// Reduce kindling volume as well to make sure they're not larger than logs.
|
||||
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);
|
||||
}
|
||||
|
||||
// Set silver mirror price to 10 silver instead of 1 iron.
|
||||
// Allow sleep powder to be dropped.
|
||||
if (WyvernMods.droppableSleepPowder) {
|
||||
ItemTemplate sleepPowder = ItemTemplateFactory.getInstance().getTemplate(ItemList.sleepPowder);
|
||||
ReflectionUtil.setPrivateField(sleepPowder, ReflectionUtil.getField(sleepPowder.getClass(), "nodrop"), false);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Set sculpting wand to be 25 silver
|
||||
ItemTemplate sculptingWand = ItemTemplateFactory.getInstance().getTemplate(ItemList.wandSculpting);
|
||||
@@ -408,9 +436,23 @@ public class ItemMod {
|
||||
ReflectionUtil.setPrivateField(transmutationRod, ReflectionUtil.getField(transmutationRod.getClass(), "value"), 2000000);
|
||||
|
||||
// Creature crates to 10 silver.
|
||||
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.
|
||||
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.
|
||||
if (WyvernMods.setShakerOrbPrice) {
|
||||
ItemTemplate shakerOrb = ItemTemplateFactory.getInstance().getTemplate(ItemList.shakerOrb);
|
||||
ReflectionUtil.setPrivateField(shakerOrb, ReflectionUtil.getField(shakerOrb.getClass(), "value"), 20000);
|
||||
}
|
||||
|
||||
// Make all tools/weapons dyable
|
||||
for(int template : ItemUtil.toolWeaponTemplates) {
|
||||
@@ -427,7 +469,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);
|
||||
@@ -439,12 +481,17 @@ public class ItemMod {
|
||||
}
|
||||
|
||||
// Make bell towers and trash bins loadable
|
||||
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
|
||||
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);
|
||||
@@ -453,30 +500,46 @@ public class ItemMod {
|
||||
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.
|
||||
if (WyvernMods.oneHandedLongSpear) {
|
||||
ItemTemplate longSpear = ItemTemplateFactory.getInstance().getTemplate(ItemList.spearLong);
|
||||
ReflectionUtil.setPrivateField(longSpear, ReflectionUtil.getField(longSpear.getClass(), "isTwohanded"), false);
|
||||
}
|
||||
|
||||
// Make dirt/sand difficulty easier
|
||||
if (WyvernMods.reduceDirtDifficulty) {
|
||||
ItemTemplate dirt = ItemTemplateFactory.getInstance().getTemplate(ItemList.dirtPile);
|
||||
ReflectionUtil.setPrivateField(dirt, ReflectionUtil.getField(dirt.getClass(), "difficulty"), 50.0f);
|
||||
}
|
||||
|
||||
if (WyvernMods.reduceSandDifficulty) {
|
||||
ItemTemplate sand = ItemTemplateFactory.getInstance().getTemplate(ItemList.sand);
|
||||
ReflectionUtil.setPrivateField(sand, ReflectionUtil.getField(sand.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.
|
||||
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
|
||||
if (WyvernMods.useCustomCacheFragments) {
|
||||
setFragments(ArmourCache.templateId, 18);
|
||||
setFragments(ArtifactCache.templateId, 33);
|
||||
setFragments(CrystalCache.templateId, 11);
|
||||
@@ -490,7 +553,9 @@ public class ItemMod {
|
||||
setFragments(TreasureMapCache.templateId, 38);
|
||||
|
||||
setFragments(AffinityOrb.templateId, 20);
|
||||
}
|
||||
|
||||
if (WyvernMods.adjustStatueFragmentCount) {
|
||||
// Tier 4
|
||||
setFragments(ItemList.statueWorg, 40);
|
||||
setFragments(ItemList.statueEagle, 40);
|
||||
@@ -504,16 +569,31 @@ public class ItemMod {
|
||||
setFragments(ItemList.statueMagranon, 50);
|
||||
setFragments(ItemList.statueLibila, 50);
|
||||
setFragments(ItemList.statueVynora, 50);
|
||||
// Still need to override the method for getting spaceLeft
|
||||
}
|
||||
|
||||
if (WyvernMods.enableCustomItemCreation) {
|
||||
createCustomWeapons();
|
||||
//createCustomArmours();
|
||||
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 {
|
||||
CtClass[] input = {
|
||||
|
||||
115
src/main/java/mod/sin/wyvern/Mastercraft.java
Normal file
115
src/main/java/mod/sin/wyvern/Mastercraft.java
Normal file
@@ -0,0 +1,115 @@
|
||||
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 preInit(){
|
||||
try {
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
Class<Mastercraft> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<MeditationPerks> 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");
|
||||
CtClass ctActions = classPool.get("com.wurmonline.server.behaviours.Actions");
|
||||
CtClass ctMovementScheme = classPool.get("com.wurmonline.server.creatures.MovementScheme");
|
||||
CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus");
|
||||
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.");
|
||||
CtClass ctActions = classPool.get("com.wurmonline.server.behaviours.Actions");
|
||||
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.");
|
||||
CtClass ctMovementScheme = classPool.get("com.wurmonline.server.creatures.MovementScheme");
|
||||
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.");
|
||||
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");
|
||||
CtClass[] params1 = {
|
||||
CtClass.doubleType,
|
||||
CtClass.booleanType,
|
||||
@@ -194,57 +212,61 @@ public class MeditationPerks {
|
||||
CtClass.doubleType
|
||||
};
|
||||
String desc1 = Descriptor.ofMethod(CtClass.voidType, params1);
|
||||
|
||||
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 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.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)+";";
|
||||
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);
|
||||
//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;");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.wurmonline.server.economy.Economy;
|
||||
import com.wurmonline.server.items.*;
|
||||
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;
|
||||
@@ -19,10 +20,12 @@ import com.wurmonline.server.players.Player;
|
||||
import com.wurmonline.server.players.PlayerInfo;
|
||||
import com.wurmonline.server.players.PlayerInfoFactory;
|
||||
import com.wurmonline.server.questions.GmSetEnchants;
|
||||
import com.wurmonline.server.players.Titles;
|
||||
import com.wurmonline.server.skills.Skill;
|
||||
import com.wurmonline.server.skills.SkillList;
|
||||
import com.wurmonline.server.spells.Spell;
|
||||
import com.wurmonline.server.spells.SpellEffect;
|
||||
import com.wurmonline.server.spells.SpellEffect;
|
||||
import com.wurmonline.server.villages.Village;
|
||||
import com.wurmonline.server.webinterface.WcKingdomChat;
|
||||
import com.wurmonline.server.zones.VolaTile;
|
||||
@@ -38,8 +41,8 @@ import mod.sin.items.ChaosCrystal;
|
||||
import mod.sin.items.EnchantersCrystal;
|
||||
import mod.sin.items.EternalOrb;
|
||||
import mod.sin.items.SealedMap;
|
||||
import mod.sin.kingdomoffices.ItemCreator;
|
||||
import mod.sin.lib.Util;
|
||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||
import mod.sin.wyvern.util.TraderItem;
|
||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
|
||||
@@ -51,12 +54,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
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.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MiscChanges {
|
||||
@@ -118,8 +116,10 @@ public class MiscChanges {
|
||||
}
|
||||
catch (NoSuchCreatureException ignored) {}
|
||||
}
|
||||
if(!attackerString.toString().isEmpty()) {
|
||||
Players.getInstance().broadCastDeathInfo(player, attackerString.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void broadCastDeaths(Creature player, String slayers){
|
||||
String slayMessage = "slain by ";
|
||||
@@ -396,6 +396,46 @@ public class MiscChanges {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static Titles.Title[] cleanTitles(Titles.Title[] titles){
|
||||
ArrayList<Titles.Title> 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 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 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();
|
||||
@@ -403,31 +443,38 @@ public class MiscChanges {
|
||||
String replace;
|
||||
|
||||
// - Create Server tab with initial messages - //
|
||||
CtClass ctVehicle = classPool.get("com.wurmonline.server.behaviours.Vehicle");
|
||||
CtClass ctPlayers = classPool.get("com.wurmonline.server.Players");
|
||||
if (WyvernMods.enableInfoTab) {
|
||||
CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat");
|
||||
String infoTabTitle = "Server";
|
||||
String infoTabTitle = WyvernMods.infoTabName;
|
||||
// Initial messages:
|
||||
String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/",
|
||||
//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/1GeaygilS-Z-d1TuGB7awOe9sJNV4o5BTZw_a2ATJy98"};
|
||||
StringBuilder str = new StringBuilder("{"
|
||||
+ " com.wurmonline.server.Message mess;");
|
||||
for (String anInfoTabLine : infoTabLine) {
|
||||
"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());
|
||||
}
|
||||
|
||||
// - Enable bridges to be built inside/over/through houses - //
|
||||
CtClass ctPlanBridgeChecks = classPool.get("com.wurmonline.server.structures.PlanBridgeChecks");
|
||||
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");
|
||||
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){"
|
||||
@@ -437,51 +484,64 @@ public class MiscChanges {
|
||||
+ " }"
|
||||
+ "}";
|
||||
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++){"
|
||||
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");
|
||||
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);
|
||||
//ctDens.getDeclaredMethod("checkDens").insertAt(0, "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);");
|
||||
}
|
||||
|
||||
// - Announce player titles in the Server tab - //
|
||||
CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player");
|
||||
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");
|
||||
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 - //
|
||||
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");
|
||||
if (WyvernMods.fatigueActionOverride) {
|
||||
CtConstructor[] ctActionConstructors = ctAction.getConstructors();
|
||||
for (CtConstructor constructor : ctActionConstructors) {
|
||||
constructor.instrument(new ExprEditor() {
|
||||
@@ -502,13 +562,17 @@ public class MiscChanges {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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){"
|
||||
@@ -517,33 +581,46 @@ public class MiscChanges {
|
||||
+ " $_ = $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);
|
||||
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() {
|
||||
@@ -564,8 +641,8 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -575,25 +652,32 @@ public class MiscChanges {
|
||||
CtClass.doubleType
|
||||
};
|
||||
String desc4 = Descriptor.ofMethod(CtClass.voidType, params4);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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");
|
||||
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.
|
||||
@@ -602,16 +686,21 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// -- Identify players making over 10 commands per second and causing the server log message -- //
|
||||
CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator");
|
||||
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;"
|
||||
@@ -619,7 +708,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 = {
|
||||
@@ -630,6 +719,8 @@ public class MiscChanges {
|
||||
CtClass.doubleType
|
||||
};
|
||||
String desc = Descriptor.ofMethod(CtClass.voidType, params);
|
||||
|
||||
if (WyvernMods.useDynamicSkillRate) {
|
||||
double minRate = 1.0D;
|
||||
double maxRate = 8.0D;
|
||||
double newPower = 2.5;
|
||||
@@ -640,13 +731,18 @@ public class MiscChanges {
|
||||
"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");
|
||||
if (WyvernMods.allowFreedomMyceliumAbsorb) {
|
||||
for (CtMethod method : ctGetBehavioursFors) {
|
||||
method.instrument(new ExprEditor() {
|
||||
public void edit(MethodCall m) throws CannotCompileException {
|
||||
@@ -655,9 +751,11 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure");
|
||||
if (WyvernMods.largerHouses) {
|
||||
Util.setReason("Allow players to construct larger houses.");
|
||||
float carpentryMultiplier = 2f;
|
||||
replace = "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" +
|
||||
@@ -668,11 +766,15 @@ public class MiscChanges {
|
||||
Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToExpandStructure", "getKnowledge", replace);
|
||||
Util.setReason("Allow players to construct larger houses.");
|
||||
Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToContractStructure", "getKnowledge", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.reduceImbuePower) {
|
||||
Util.setReason("Reduce power of imbues.");
|
||||
replace = "$_ = Math.max(-80d, -80d+$2);";
|
||||
Util.instrumentDeclared(thisClass, ctMethodsItems, "smear", "max", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.fixVehicleSpeeds) {
|
||||
Util.setReason("Update vehicle speeds reliably.");
|
||||
replace = "if($1 == 8){" +
|
||||
" $_ = 0;" +
|
||||
@@ -680,12 +782,16 @@ public class MiscChanges {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctPlayer, "checkVehicleSpeeds", "nextInt", 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);
|
||||
}
|
||||
|
||||
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)){" +
|
||||
@@ -694,9 +800,11 @@ public class MiscChanges {
|
||||
" $_ = $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");
|
||||
if (WyvernMods.enableLibilaStrongwallPvE) {
|
||||
ctSpellGenerator.getDeclaredMethod("createSpells").instrument(new ExprEditor() {
|
||||
@Override
|
||||
public void edit(FieldAccess fieldAccess) throws CannotCompileException {
|
||||
@@ -705,9 +813,12 @@ public class MiscChanges {
|
||||
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");
|
||||
|
||||
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());" +
|
||||
@@ -733,18 +844,25 @@ public class MiscChanges {
|
||||
" $_ = $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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (WyvernMods.disableFoodFirstBiteBonus) {
|
||||
Util.setReason("Food affinity timer normalization.");
|
||||
replace = "long time = " + WurmCalendar.class.getName() + ".getCurrentTime();" +
|
||||
"if($0.getExpires($1) == null){" +
|
||||
@@ -753,18 +871,15 @@ public class MiscChanges {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "add", "getExpires", replace);
|
||||
}
|
||||
|
||||
Util.setReason("Make weaponsmithing oils actually help with weaponsmithing");
|
||||
replace = "if($1 == 1016){" +
|
||||
"return $0.getSpellEffectPower((byte)77);" +
|
||||
"}";
|
||||
Util.insertBeforeDeclared(thisClass, ctItem, "getSkillSpellImprovement", replace);
|
||||
|
||||
if (WyvernMods.bedQualitySleepBonus) {
|
||||
Util.setReason("Make bed QL affect sleep bonus timer.");
|
||||
CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo");
|
||||
replace = "long secs2 = " + MiscChanges.class.getName() + ".getBedBonus(secs, this.bed);" +
|
||||
"$_ = $proceed((int)(this.sleep + secs2));";
|
||||
replace = "secs = " + MiscChanges.class.getName() + ".getBedBonus(secs, this.bed);" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace);
|
||||
}
|
||||
|
||||
Util.setReason("Allow GMs to set 5 digit enchants on all enchantments");
|
||||
CtClass ctGmSetEnchants = classPool.get("com.wurmonline.server.questions.GmSetEnchants");
|
||||
@@ -773,14 +888,7 @@ public class MiscChanges {
|
||||
" }";
|
||||
Util.setBodyDeclared(thisClass, ctGmSetEnchants, "sendQuestion", 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.royalSmithImproveFaster) {
|
||||
Util.setReason("Allow royal smith to improve smithing items faster.");
|
||||
replace = "if(" + MiscChanges.class.getName() + ".royalSmithImprove($1, improve)){" +
|
||||
" $_ = $proceed($$) * 0.9f;" +
|
||||
@@ -797,8 +905,10 @@ public class MiscChanges {
|
||||
" $_ = $proceed($1, target);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "getImproveActionTime", replace);
|
||||
}
|
||||
|
||||
// Fix for body strength not working properly when mounted. (Bdew)
|
||||
if (WyvernMods.fixMountedBodyStrength) {
|
||||
ctCreature.getMethod("getTraitMovePercent", "(Z)F").instrument(new ExprEditor() {
|
||||
private boolean first = true;
|
||||
|
||||
@@ -813,7 +923,9 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (WyvernMods.adjustedFoodBiteFill) {
|
||||
Util.setReason("Modify food fill percent.");
|
||||
CtClass[] params12 = {
|
||||
ctAction,
|
||||
@@ -824,8 +936,10 @@ public class MiscChanges {
|
||||
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;
|
||||
|
||||
@@ -840,7 +954,7 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
// How to add a skill!
|
||||
/*CtClass ctSkillSystem = classPool.get("com.wurmonline.server.skills.SkillSystem");
|
||||
@@ -848,13 +962,16 @@ 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));");*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (WyvernMods.rarityWindowBadLuckProtection) {
|
||||
Util.setReason("Bad luck protection on rarity windows.");
|
||||
replace = "if($1 == 3600){" +
|
||||
" $_ = " + MiscChanges.class.getName() + ".getRarityWindowChance(this.getWurmId());" +
|
||||
@@ -862,6 +979,7 @@ public class MiscChanges {
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDeclared(thisClass, ctPlayer, "poll", "nextInt", replace);
|
||||
}
|
||||
|
||||
CtClass ctShop = classPool.get("com.wurmonline.server.items.Trade");
|
||||
Util.setReason("Restock certain items after every trade with a trader");
|
||||
@@ -873,6 +991,8 @@ public class MiscChanges {
|
||||
//replace = "$_ = $proceed($1, $2 * " + MiscChanges.class.getName() + ".boatSpeedBonus(Players.getInstance().getPlayer(this.pilotId)));";
|
||||
|
||||
CtClass ctSimpleCreationEntry = classPool.get("com.wurmonline.server.items.SimpleCreationEntry");
|
||||
|
||||
if (WyvernMods.rareCreationAdjustments) {
|
||||
ctSimpleCreationEntry.getDeclaredMethod("run").instrument(new ExprEditor() {
|
||||
private boolean first = true;
|
||||
|
||||
@@ -891,80 +1011,84 @@ public class MiscChanges {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()+\" may not be used on Arena.\");" +
|
||||
" $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" must be used on the login server.\");" +
|
||||
" return false;" +
|
||||
"}";
|
||||
Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace);
|
||||
}
|
||||
|
||||
if (WyvernMods.lessFillingDrinks) {
|
||||
Util.setReason("Make drinks less filling.");
|
||||
CtClass[] params14 = {
|
||||
CtClass[] params13 = {
|
||||
ctAction,
|
||||
ctCreature,
|
||||
ctItem,
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14);
|
||||
String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13);
|
||||
replace = "if(template != 128){" +
|
||||
" $_ = $proceed($1, $2, $3*5);" +
|
||||
"}else{" +
|
||||
" $_ = $proceed($$);" +
|
||||
"}";
|
||||
Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc14, "sendActionControl", replace);
|
||||
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", desc14, "modifyThirst", 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.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", 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);
|
||||
}
|
||||
|
||||
if (WyvernMods.reduceActionInterruptOnDamage) {
|
||||
Util.setReason("Make damage less likely to interrupt actions during combat.");
|
||||
replace = "$1 = $1/2;";
|
||||
Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", 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[] params15 = {
|
||||
CtClass[] params14 = {
|
||||
ctAction,
|
||||
ctCreature,
|
||||
ctItem,
|
||||
@@ -972,26 +1096,47 @@ public class MiscChanges {
|
||||
CtClass.shortType,
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc15 = Descriptor.ofMethod(CtClass.booleanType, params15);
|
||||
String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14);
|
||||
replace = "if($5 == 519){" +
|
||||
" $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" +
|
||||
" return true;" +
|
||||
"}";
|
||||
Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc15, replace);
|
||||
**/
|
||||
Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace);
|
||||
}
|
||||
|
||||
Util.setReason("Change fantastic items to red.");
|
||||
CtClass ctManageObjectList = classPool.get("com.wurmonline.server.questions.ManageObjectList");
|
||||
/* This is for adding a new rarity!
|
||||
replace = "if (item.getRarity() == 4) {" +
|
||||
"return \"label{color=\\\"66,153,225\\\";text=\\\"rare \" + name + \"\\\"};\";" +
|
||||
"}";
|
||||
*/
|
||||
replace = "if (item.getRarity() == 3) {" +
|
||||
"return \"label{color=\\\"255,53,0\\\";text=\\\"fantastic \" + name + \"\\\"};\";" +
|
||||
"}";
|
||||
Util.insertBeforeDeclared(thisClass, ctManageObjectList, "addRariryColour", 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]
|
||||
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);
|
||||
|
||||
@@ -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<MissionCreator> thisClass = MissionCreator.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Give players currency for completing a mission.");
|
||||
CtClass ctTriggerEffect = classPool.get("com.wurmonline.server.tutorial.TriggerEffect");
|
||||
CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus");
|
||||
CtClass ctEpicMissionEnum = classPool.get("com.wurmonline.server.epic.EpicMissionEnum");
|
||||
|
||||
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.");
|
||||
CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus");
|
||||
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);
|
||||
}
|
||||
|
||||
Util.setReason("Adjust which epic missions are available..");
|
||||
CtClass ctEpicMissionEnum = classPool.get("com.wurmonline.server.epic.EpicMissionEnum");
|
||||
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);
|
||||
|
||||
@@ -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,27 +22,35 @@ public class MountedChanges {
|
||||
ArrayList<Item> gear = new ArrayList<>();
|
||||
try {
|
||||
Item leftFoot = creature.getEquippedItem(BodyPartConstants.LEFT_FOOT);
|
||||
if (leftFoot != null) {
|
||||
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);
|
||||
if (rightFoot != null) {
|
||||
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);
|
||||
if (leftHand != null) {
|
||||
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);
|
||||
if (rightHand != null) {
|
||||
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 +101,7 @@ public class MountedChanges {
|
||||
saddleFactor += saddle.getRarity() * 0.03f;
|
||||
factor *= saddleFactor;
|
||||
}
|
||||
} catch (NoSuchItemException | NoSpaceException ignored) {
|
||||
} catch (NoSpaceException ignored) {
|
||||
}
|
||||
factor *= creature.getMovementScheme().getSpeedModifier();
|
||||
}
|
||||
@@ -109,14 +114,19 @@ public class MountedChanges {
|
||||
final Class<MountedChanges> thisClass = MountedChanges.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Scaling horse speed.");
|
||||
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
||||
|
||||
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);
|
||||
|
||||
@@ -3,18 +3,44 @@ package mod.sin.wyvern;
|
||||
import com.wurmonline.server.creatures.Creature;
|
||||
import com.wurmonline.server.players.Player;
|
||||
import com.wurmonline.server.players.Titles;
|
||||
import net.bdew.wurm.tools.server.ModTitles;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PlayerTitles {
|
||||
public static Logger logger = Logger.getLogger(PlayerTitles.class.getName());
|
||||
|
||||
// Player Title Maps
|
||||
protected static ArrayList<String> donatorTitles = new ArrayList<>();
|
||||
protected static ArrayList<String> patronTitles = new ArrayList<>();
|
||||
protected static HashMap<String,Integer> customTitles = new HashMap<>();
|
||||
protected static HashMap<String,String> playerTitles = new HashMap<>();
|
||||
|
||||
// Event Title ID's
|
||||
public static int TITAN_SLAYER = 10000;
|
||||
public static int SPECTRAL = 10001;
|
||||
|
||||
public static void init(){
|
||||
for (WyvernMods.CustomTitle title : WyvernMods.customTitles){
|
||||
createTitle(title.getTitleId(), title.getMaleTitle(), title.getFemaleTitle(), title.getSkillId(), title.getType());
|
||||
}
|
||||
// Event Titles
|
||||
createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, "NORMAL");
|
||||
createTitle(SPECTRAL, "Spectral", "Spectral", -1, "NORMAL");
|
||||
|
||||
// Display all existing titles
|
||||
logger.info(Arrays.toString(Titles.Title.values()));
|
||||
}
|
||||
|
||||
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){
|
||||
if(creature instanceof Player){
|
||||
Player p = (Player) creature;
|
||||
@@ -31,59 +57,16 @@ public class PlayerTitles {
|
||||
}
|
||||
public static void awardCustomTitles(Player p){
|
||||
String name = p.getName();
|
||||
if(donatorTitles.contains(name)){
|
||||
Titles.Title donator = Titles.Title.getTitle(800);
|
||||
p.addTitle(donator);
|
||||
for (int titleId : WyvernMods.awardTitles.keySet()){
|
||||
try {
|
||||
Titles.Title theTitle = Titles.Title.getTitle(titleId);
|
||||
ArrayList<String> playerList = WyvernMods.awardTitles.get(titleId);
|
||||
if (playerList.contains(name)){
|
||||
p.addTitle(theTitle);
|
||||
}
|
||||
if(customTitles.containsKey(name)){
|
||||
Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name));
|
||||
p.addTitle(customTitle);
|
||||
}catch(Exception e){
|
||||
logger.warning("Failed to get title with ID "+titleId);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
donatorTitles.add("Warriorgen");
|
||||
customTitles.put("Warriorgen", 802); // That Guy
|
||||
|
||||
donatorTitles.add("Eternallove");
|
||||
customTitles.put("Eternallove", 803); // Warriorgens Wife
|
||||
|
||||
donatorTitles.add("Bambam");
|
||||
customTitles.put("Bambam", 804); // Thorn One
|
||||
|
||||
donatorTitles.add("Svenja");
|
||||
customTitles.put("Svenja", 805); // The care-dependent
|
||||
playerTitles.put("Svenja", "Akuma");
|
||||
|
||||
donatorTitles.add("Alexiaselena");
|
||||
customTitles.put("Alexiaselena", 806); // The Treasuring
|
||||
playerTitles.put("Alexiaselena", "Kami");
|
||||
|
||||
donatorTitles.add("Reevi");
|
||||
customTitles.put("Reevi", 807); // Science Guy
|
||||
|
||||
customTitles.put("Genocide", 808); // Grand Designer
|
||||
|
||||
donatorTitles.add("Seleas");
|
||||
customTitles.put("Seleas", 809); // The Crazy Cat Lord
|
||||
playerTitles.put("Seleas", "No, Really");
|
||||
|
||||
donatorTitles.add("Piratemax");
|
||||
customTitles.put("Piratemax", 810); // Slave
|
||||
playerTitles.put("Piratemax", "Boy Next Door");
|
||||
|
||||
donatorTitles.add("Eltacolad");
|
||||
customTitles.put("Eltacolad", 811); // The One True Taco
|
||||
|
||||
// Other rewards
|
||||
customTitles.put("Critias", 602);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ public class QualityOfLife {
|
||||
final Class<QualityOfLife> 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");
|
||||
@@ -108,63 +107,44 @@ public class QualityOfLife {
|
||||
CtClass.floatType
|
||||
};
|
||||
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
|
||||
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.");
|
||||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
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.setReason("Allow dirt to add up to 100 dirt to a container.");
|
||||
CtClass ctDirt = classPool.get("com.wurmonline.server.spells.Dirt");
|
||||
replace = "$1 = 100;"
|
||||
+ "$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctDirt, "doEffect", "min", replace);
|
||||
|
||||
Util.setReason("Rescale Wild Growth to work up to an 8x8 area");
|
||||
CtClass ctWildGrowth = classPool.get("com.wurmonline.server.spells.WildGrowth");
|
||||
replace = "$2 = (power / 10.0); $_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctWildGrowth, "doEffect", "max", replace);
|
||||
|
||||
Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", replace);*/
|
||||
|
||||
if (WyvernMods.mineGemsToVehicle) {
|
||||
Util.setReason("Send gems, source crystals, flint, etc. into vehicle.");
|
||||
CtClass[] params2 = {
|
||||
CtClass.intType,
|
||||
@@ -180,7 +160,19 @@ public class QualityOfLife {
|
||||
replace = "$_ = null;" +
|
||||
QualityOfLife.class.getName() + ".vehicleHook(performer, $0);";
|
||||
Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "createGem", desc2, "putItemInfrontof", replace);
|
||||
}
|
||||
Util.setReason("Allow dirt to add up to 100 dirt to a container.");
|
||||
CtClass ctDirt = classPool.get("com.wurmonline.server.spells.Dirt");
|
||||
replace = "$1 = 100;"
|
||||
+ "$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctDirt, "doEffect", "min", replace);
|
||||
|
||||
Util.setReason("Rescale Wild Growth to work up to an 8x8 area");
|
||||
CtClass ctWildGrowth = classPool.get("com.wurmonline.server.spells.WildGrowth");
|
||||
replace = "$2 = (power / 10.0); $_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctWildGrowth, "doEffect", "max", replace);
|
||||
|
||||
if (WyvernMods.regenerateStaminaOnVehicleAnySlope) {
|
||||
CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player");
|
||||
ctPlayer.getMethod("poll", "()Z").instrument(new ExprEditor() {
|
||||
@Override
|
||||
@@ -189,6 +181,7 @@ public class QualityOfLife {
|
||||
f.replace("$_ = -10L;");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||
throw new HookException(e);
|
||||
|
||||
@@ -99,58 +99,4 @@ public class RareSpawns {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void preInit(){
|
||||
try {
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
Class<RareSpawns> 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
logger.info("Failed to set tickTime for skill with ID "+id+"!");
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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!");
|
||||
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 preInit(){
|
||||
@@ -132,13 +119,15 @@ public class SkillChanges {
|
||||
final Class<SkillChanges> thisClass = SkillChanges.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Allow skill check failures to add skill gain.");
|
||||
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);
|
||||
|
||||
@@ -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<Item> 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();
|
||||
@@ -223,7 +215,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 +224,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--;
|
||||
}
|
||||
@@ -285,13 +277,20 @@ public class SupplyDepots {
|
||||
public static void preInit(){
|
||||
try{
|
||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||
Class<SupplyDepots> thisClass = SupplyDepots.class;
|
||||
String replace;
|
||||
|
||||
// - Add light effects for the supply depots, since they are unique - //
|
||||
CtClass ctPlayers = classPool.get("com.wurmonline.server.Players");
|
||||
ctPlayers.getDeclaredMethod("sendAltarsToPlayer").insertBefore("mod.sin.wyvern.SupplyDepots.sendDepotEffectsToPlayer($1);");
|
||||
|
||||
}catch (CannotCompileException | NotFoundException e) {
|
||||
throw new HookException(e);
|
||||
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 (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,10 @@ public class TeleportHandler {
|
||||
final Class<TeleportHandler> thisClass = TeleportHandler.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Custom teleportation system for Arena teleport/escape.");
|
||||
CtClass ctPlayerMetaData = classPool.get("com.wurmonline.server.players.PlayerMetaData");
|
||||
|
||||
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);" +
|
||||
@@ -113,6 +115,7 @@ public class TeleportHandler {
|
||||
"}" +
|
||||
"$_ = $proceed($$);";
|
||||
Util.instrumentDeclared(thisClass, ctPlayerMetaData, "save", "getPosition", replace);
|
||||
}
|
||||
|
||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||
throw new HookException(e);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -716,9 +716,7 @@ public class Titans {
|
||||
}
|
||||
|
||||
public static ArrayList<Creature> 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,64 +810,20 @@ public class Titans {
|
||||
Class<Titans> thisClass = Titans.class;
|
||||
String replace;
|
||||
|
||||
Util.setReason("Disable natural regeneration on titans.");
|
||||
CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound");
|
||||
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
||||
|
||||
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);
|
||||
|
||||
/*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);*/
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}catch (NotFoundException e) {
|
||||
throw new HookException(e);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -336,9 +336,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.");
|
||||
|
||||
@@ -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.Mailer;
|
||||
import com.wurmonline.server.Server;
|
||||
@@ -15,9 +8,7 @@ import com.wurmonline.server.creatures.Creature;
|
||||
import com.wurmonline.server.economy.Economy;
|
||||
import com.wurmonline.server.items.*;
|
||||
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 com.wurmonline.server.players.Titles;
|
||||
import mod.piddagoras.duskombat.DamageEngine;
|
||||
import mod.sin.armour.SpectralHide;
|
||||
import mod.sin.creatures.Gremlin;
|
||||
@@ -28,10 +19,16 @@ import mod.sin.items.EnchantersCrystal;
|
||||
import mod.sin.items.TreasureBox;
|
||||
import mod.sin.items.caches.RiftCache;
|
||||
import mod.sin.items.caches.TitanCache;
|
||||
import mod.sin.kingdomoffices.ItemCreator;
|
||||
import mod.sin.wyvern.*;
|
||||
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();
|
||||
@@ -111,7 +108,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(Titles.Title.getTitle(PlayerTitles.SPECTRAL));
|
||||
}catch (NoSuchTemplateException | FailedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -164,7 +161,7 @@ public class PlayerBounty {
|
||||
rewardRareLoot(player, mob);
|
||||
}
|
||||
if(Titans.isTitan(mob)){
|
||||
player.addTitle(Title.getTitle(700));
|
||||
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());
|
||||
|
||||
@@ -1,561 +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<length;i++){
|
||||
c[i]=(int)obj[i];
|
||||
}
|
||||
String[] a = new String[length];
|
||||
for (int i=0;i<length;i++){
|
||||
a[i]=String.format("%02X", c[i] & 0xff);
|
||||
}
|
||||
logger.log(Level.INFO,name + " : " + Arrays.toString(a));
|
||||
}
|
||||
|
||||
// BDEW EXTRAS
|
||||
public static void putInteger(ConstPool cp, Bytecode code, int val) {
|
||||
switch (val) {
|
||||
case -1:
|
||||
code.add(Bytecode.ICONST_M1);
|
||||
break;
|
||||
case 0:
|
||||
code.add(Bytecode.ICONST_0);
|
||||
break;
|
||||
case 1:
|
||||
code.add(Bytecode.ICONST_1);
|
||||
break;
|
||||
case 2:
|
||||
code.add(Bytecode.ICONST_2);
|
||||
break;
|
||||
case 3:
|
||||
code.add(Bytecode.ICONST_3);
|
||||
break;
|
||||
case 4:
|
||||
code.add(Bytecode.ICONST_4);
|
||||
break;
|
||||
case 5:
|
||||
code.add(Bytecode.ICONST_5);
|
||||
break;
|
||||
default:
|
||||
if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) {
|
||||
code.add(Bytecode.BIPUSH);
|
||||
code.add(val);
|
||||
} else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) {
|
||||
code.add(Bytecode.SIPUSH);
|
||||
code.add(val >> 8 & 0xFF, val & 0xFF);
|
||||
} else {
|
||||
code.addLdc(cp.addIntegerInfo(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInteger(ConstPool cp, CodeIterator iterator, int pos) {
|
||||
int op = iterator.byteAt(pos);
|
||||
switch (op) {
|
||||
case Bytecode.ICONST_M1:
|
||||
return -1;
|
||||
case Bytecode.ICONST_0:
|
||||
return 0;
|
||||
case Bytecode.ICONST_1:
|
||||
return 1;
|
||||
case Bytecode.ICONST_2:
|
||||
return 2;
|
||||
case Bytecode.ICONST_3:
|
||||
return 3;
|
||||
case Bytecode.ICONST_4:
|
||||
return 4;
|
||||
case Bytecode.ICONST_5:
|
||||
return 5;
|
||||
case Bytecode.BIPUSH:
|
||||
return iterator.byteAt(pos + 1);
|
||||
case Bytecode.SIPUSH:
|
||||
return iterator.s16bitAt(pos + 1);
|
||||
case Bytecode.LDC:
|
||||
return cp.getIntegerInfo(iterator.byteAt(pos + 1));
|
||||
case Bytecode.LDC_W:
|
||||
return cp.getIntegerInfo(iterator.u16bitAt(pos + 1));
|
||||
default:
|
||||
throw new RuntimeException(String.format("Failed to decode integer. Pos = %d, Bytecode = %d", pos, op));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.BadBytecode;
|
||||
import net.bdew.wurm.tools.server.ModTitles;
|
||||
|
||||
public class CustomTitles {
|
||||
public static Titles.Title GremlinSlayer;
|
||||
public static int GREMLIN_SLAYER = 704;
|
||||
public static void register(ClassPool cp) throws NotFoundException, BadBytecode, CannotCompileException {
|
||||
TitleInjector injector = new TitleInjector(cp);
|
||||
injector.addTitle("GremlinSlayer", 704, "Gremlin Slayer", "Gremlin Slayer", -1, "NORMAL");
|
||||
ModTitles.addTitle(GREMLIN_SLAYER, "Gremlin Slayer", "Gremlin Slayer", -1, "NORMAL");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
package mod.sin.wyvern.mastercraft;
|
||||
|
||||
import com.wurmonline.server.skills.SkillList;
|
||||
import javassist.*;
|
||||
import javassist.bytecode.*;
|
||||
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.CodeReplacer;
|
||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
class ExtendTitleEnum {
|
||||
|
||||
private final String className;
|
||||
private final int valuesSizerIndex; // the bytecode index which puts a size specifying value on the stack for anewarray.
|
||||
private final int populateVALUESIndex; // the bytecode index where references to various enum instances are put in the $VALUES array.
|
||||
private final ConstPool constPool;
|
||||
|
||||
private static ArrayList<EnumFields> 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, "<init>",
|
||||
"(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());
|
||||
}
|
||||
}
|
||||
@@ -1,271 +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 -= 8d-((100d-skill.getKnowledge())*8d);
|
||||
}
|
||||
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 -= 3d-((100d-item.getCurrentQualityLevel())*3d);
|
||||
}
|
||||
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", 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");
|
||||
|
||||
// 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");
|
||||
//ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gremlin_Slayer", 704, "Gremlin Slayer", "Gremlin Slayer", -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");
|
||||
|
||||
// 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");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hatchet_Normal", 1132, "Hatcheter", "Hatcheter", SkillList.HATCHET, "NORMAL");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hatchet_Minor", 1133, "Renowned Hatcheter", "Renowned Hatcheter", SkillList.HATCHET, "MINOR");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hatchet_Master", 1134, "Master Hatcheter", "Master Hatcheter", SkillList.HATCHET, "MASTER");
|
||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hatchet_Legendary", 1135, "Hatchslinging Slasher", "Hatchslinging Slasher", SkillList.HATCHET, "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");
|
||||
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<Mastercraft> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package mod.sin.wyvern.mastercraft;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.*;
|
||||
import javassist.bytecode.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TitleInjector {
|
||||
private final CtClass titleCls;
|
||||
private final ConstPool constPool;
|
||||
private final CodeIterator codeIterator;
|
||||
private int insertPos = -1;
|
||||
private int lastOrd = -1;
|
||||
private int arraySizePos = -1;
|
||||
|
||||
|
||||
public TitleInjector(ClassPool classPool) throws NotFoundException, BadBytecode {
|
||||
titleCls = classPool.getCtClass("com.wurmonline.server.players.Titles$Title");
|
||||
CtConstructor initializer = titleCls.getClassInitializer();
|
||||
CodeAttribute codeAttr = initializer.getMethodInfo().getCodeAttribute();
|
||||
constPool = codeAttr.getConstPool();
|
||||
codeIterator = codeAttr.iterator();
|
||||
|
||||
BytecodeTools b = new BytecodeTools(constPool);
|
||||
|
||||
// My code needs a bit more stack space than javac-generated one
|
||||
codeAttr.setMaxStack(codeAttr.getMaxStack() + 3);
|
||||
|
||||
while (codeIterator.hasNext()) {
|
||||
int pos = codeIterator.next();
|
||||
int op = codeIterator.byteAt(pos);
|
||||
if (op == Bytecode.AASTORE) {
|
||||
insertPos = codeIterator.next();
|
||||
} else if (op == Bytecode.ANEWARRAY) {
|
||||
arraySizePos = pos - 2;
|
||||
} else if (op == Bytecode.NEW) {
|
||||
pos = codeIterator.next(); // dup
|
||||
pos = codeIterator.next(); // ldc of ident
|
||||
pos = codeIterator.next(); // here's the ordinal
|
||||
lastOrd = BytecodeTools.getInteger(constPool, codeIterator, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (insertPos == -1) throw new RuntimeException("Failed to find AASTORE");
|
||||
if (lastOrd == -1) throw new RuntimeException("Failed to find ordinals");
|
||||
if (arraySizePos == -1) throw new RuntimeException("Failed to array size position");
|
||||
}
|
||||
|
||||
public void saveDebug() throws IOException, CannotCompileException, NotFoundException {
|
||||
titleCls.writeFile();
|
||||
}
|
||||
|
||||
|
||||
public void addTitle(String ident, int id, String name, String femaleName, int skillId, String type) throws BadBytecode, CannotCompileException {
|
||||
int ordinal = ++lastOrd;
|
||||
Bytecode code = new Bytecode(constPool);
|
||||
|
||||
// When starting the values array is on stack, dup it for later use
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put out ordinal, will be used by AASTORE
|
||||
BytecodeTools.putInteger(constPool, code, ordinal);
|
||||
|
||||
// Make new instance, and dupe that too
|
||||
code.addNew("com.wurmonline.server.players.Titles$Title");
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put constructor parameters into stack
|
||||
code.addLdc(ident);
|
||||
BytecodeTools.putInteger(constPool, code, ordinal);
|
||||
BytecodeTools.putInteger(constPool, code, id);
|
||||
code.addLdc(name);
|
||||
code.addLdc(femaleName);
|
||||
BytecodeTools.putInteger(constPool, code, skillId);
|
||||
code.addGetstatic("com.wurmonline.server.players.Titles$TitleType", type, "Lcom/wurmonline/server/players/Titles$TitleType;");
|
||||
|
||||
// Call constructor, this will use one copy of our instance duped above, we need 2 more so dup it again
|
||||
code.addInvokespecial("com.wurmonline.server.players.Titles$Title", "<init>", "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ILcom/wurmonline/server/players/Titles$TitleType;)V");
|
||||
code.add(Bytecode.DUP);
|
||||
|
||||
// Put instance into static field - this will use the second copy of our instance
|
||||
code.addPutstatic("mod.sin.wyvern.mastercraft.CustomTitles", ident, "Lcom/wurmonline/server/players/Titles$Title;");
|
||||
|
||||
// And finally stick it into values array, this will use the duped array, ordinal and the final copy of our instance
|
||||
code.add(Bytecode.AASTORE);
|
||||
|
||||
// End of bytecode gen, insert it into the initializer
|
||||
byte[] bytes = code.get();
|
||||
codeIterator.insertAt(insertPos, bytes);
|
||||
insertPos += bytes.length;
|
||||
|
||||
// And increase array size
|
||||
codeIterator.write16bit(codeIterator.u16bitAt(arraySizePos) + 1, arraySizePos);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user