Initial Commit

This commit is contained in:
Sindusk
2018-03-31 13:23:16 -04:00
commit 7f3733295f
150 changed files with 16109 additions and 0 deletions

View File

@@ -0,0 +1,230 @@
package mod.sin.wyvern;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.mesh.Tiles;
import com.wurmonline.server.Constants;
import com.wurmonline.server.Features;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.Communicator;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.ai.NoPathException;
import com.wurmonline.server.creatures.ai.Path;
import com.wurmonline.server.creatures.ai.PathFinder;
import com.wurmonline.server.creatures.ai.PathTile;
import com.wurmonline.server.zones.Water;
import com.wurmonline.server.zones.Zones;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
public class AntiCheat {
private static Logger logger = Logger.getLogger(AntiCheat.class.getName());
private static final int emptyRock = Tiles.encode((short)-100, (byte)Tiles.Tile.TILE_CAVE_WALL.id, (byte)0);
private static boolean isCaveWall(int xx, int yy){
if (xx < 0 || xx >= Zones.worldTileSizeX || yy < 0 || yy >= Zones.worldTileSizeY) {
return true;
} else if (Tiles.isSolidCave((byte)Tiles.decodeType((int)Server.caveMesh.data[xx | yy << Constants.meshSize]))) {
return true;
}
return false;
}
private static boolean isSurroundedByCaveWalls(int tilex, int tiley){
int xx = tilex+1;
int yy = tiley;
if(!isCaveWall(xx, yy)){
return false;
}
xx = tilex-1;
if(!isCaveWall(xx, yy)){
return false;
}
xx = tilex;
yy = tiley+1;
if(!isCaveWall(xx, yy)){
return false;
}
yy = tiley-1;
if(!isCaveWall(xx, yy)){
return false;
}
return true;
}
private static int getDummyWallAntiCheat(int tilex, int tiley){
return Tiles.encode((short)Tiles.decodeHeight((int)Server.caveMesh.data[tilex | tiley << Constants.meshSize]), (byte)Tiles.Tile.TILE_CAVE_WALL.id, (byte)Tiles.decodeData((int)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()) {
try {
ByteBuffer bb = comm.getConnection().getBuffer();
bb.put((byte) 102);
bb.put((byte) (Features.Feature.CAVEWATER.isEnabled() ? 1 : 0));
bb.put((byte) (comm.player.isSendExtraBytes() ? 1 : 0));
bb.putShort(xStart);
bb.putShort(yStart);
bb.putShort((short)width);
bb.putShort((short)height);
boolean onSurface = comm.player.isOnSurface();
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
int xx = xStart + x;
int yy = yStart + y;
if (xx < 0 || xx >= Zones.worldTileSizeX || yy < 0 || yy >= Zones.worldTileSizeY) {
bb.putInt(emptyRock);
xx = 0;
yy = 0;
} else if (!onSurface) {
if(!(Tiles.decodeType((int)Server.caveMesh.getTile(xx, yy)) == Tiles.Tile.TILE_CAVE_EXIT.id) && isSurroundedByCaveWalls(xx, yy)){
bb.putInt(getDummyWallAntiCheat(xx, yy));
}else{
bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]);
}
} else if (Tiles.isSolidCave((byte)Tiles.decodeType((int)Server.caveMesh.data[xx | yy << Constants.meshSize]))) {
bb.putInt(getDummyWallAntiCheat(xx, yy));
} else {
bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]);
}
if (Features.Feature.CAVEWATER.isEnabled()) {
bb.putShort((short)Water.getCaveWater(xx, yy));
}
if (!comm.player.isSendExtraBytes()) continue;
bb.put(Server.getClientCaveFlags(xx, yy));
}
}
comm.getConnection().flush();
}
catch (Exception ex) {
comm.player.setLink(false);
}
}
}
public static boolean isVisibleThroughTerrain(Creature performer, Creature defender){
int trees = 0;
//int treetilex = -1;
//int treetiley = -1;
//int tileArrowDownX = -1;
//int tileArrowDownY = -1;
PathFinder pf = new PathFinder(true);
try {
Path path = pf.rayCast(performer.getCurrentTile().tilex, performer.getCurrentTile().tiley, defender.getCurrentTile().tilex, defender.getCurrentTile().tiley, performer.isOnSurface(), ((int)Creature.getRange(performer, defender.getPosX(), defender.getPosY()) >> 2) + 5);
float initialHeight = Math.max(-1.4f, performer.getPositionZ() + performer.getAltOffZ() + 1.4f);
float targetHeight = Math.max(-1.4f, defender.getPositionZ() + defender.getAltOffZ() + 1.4f);
double distx = Math.pow(performer.getCurrentTile().tilex - defender.getCurrentTile().tilex, 2.0);
double disty = Math.pow(performer.getCurrentTile().tiley - defender.getCurrentTile().tiley, 2.0);
double dist = Math.sqrt(distx + disty);
double dx = (double)(targetHeight - initialHeight) / dist;
while (!path.isEmpty()) {
PathTile p = path.getFirst();
if(Tiles.getTile((byte)Tiles.decodeType((int)p.getTile())).isTree()){
trees++;
}
/*if (Tiles.getTile((byte)Tiles.decodeType((int)p.getTile())).isTree() && treetilex == -1 && Server.rand.nextInt(10) < ++trees) {
treetilex = p.getTileX();
treetiley = p.getTileY();
}*/
distx = Math.pow(p.getTileX() - defender.getCurrentTile().tilex, 2.0);
disty = Math.pow(p.getTileY() - defender.getCurrentTile().tiley, 2.0);
double currdist = Math.sqrt(distx + disty);
float currHeight = Math.max(-1.4f, Zones.getLowestCorner(p.getTileX(), p.getTileY(), performer.getLayer()));
double distmod = currdist * dx;
if (dx < 0.0) {
if ((double)currHeight > (double)targetHeight - distmod) {
return false;
}
} else if ((double)currHeight > (double)targetHeight - distmod) {
return false;
}
/*if (tileArrowDownX == -1 && Server.rand.nextInt(15) == 0) {
tileArrowDownX = p.getTileX();
tileArrowDownY = p.getTileY();
}*/
path.removeFirst();
}
if(trees >= 8){
return false;
}
}
catch (NoPathException np) {
performer.getCommunicator().sendCombatNormalMessage("You fail to get a clear shot.");
return false;
}
return true;
}
public static boolean isVisibleToAntiCheat(Creature cret, Creature watcher) {
if (!cret.isVisible()) {
return cret.getPower() > 0 && cret.getPower() <= watcher.getPower();
}
if (cret.isStealth()) {
if (cret.getPower() > 0 && cret.getPower() <= watcher.getPower()) {
return true;
}
if (cret.getPower() < watcher.getPower()) {
return true;
}
if (watcher.isUnique() || watcher.isDetectInvis()) {
return true;
}
Set<Long> stealthBreakers = null;
try {
stealthBreakers = ReflectionUtil.getPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "stealthBreakers"));
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
logger.info("Failed to get stealthBreakers for creature "+cret.getName());
e.printStackTrace();
}
if (stealthBreakers != null && stealthBreakers.contains(watcher.getWurmId())) {
return true;
}
return false;
}
if(WyvernMods.espCounter && watcher.isPlayer()){
if(cret.isPlayer() || cret.getLeader() != null || cret.isRidden() || cret.isUnique()){
if(cret.isWithinDistanceTo(watcher, 120)){
return true;
}
if(isVisibleThroughTerrain(cret, watcher)){
return true;
}
return false;
}
}
return true;
}
public static void preInit(){
try{
ClassPool classPool = HookManager.getInstance().getClassPool();
// - Change the caveStrip method to the custom one, so we can edit what the clients see! - //
CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator");
ctCommunicator.getDeclaredMethod("sendCaveStrip").setBody("{"
+ " mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$);"
+ "}");
// - 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");
ctCreature.getDeclaredMethod("isVisibleTo").setBody("{"
+ " return mod.sin.wyvern.AntiCheat.isVisibleToAntiCheat(this, $$);"
+ "}");
// - Edit VirtualZone creature movement so that it removes units that the player cannot see - //
CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone");
ctVirtualZone.getDeclaredMethod("coversCreature").insertBefore(""
+ "if(!this.covers($1.getTileX(), $1.getTileY())){"
+ " return false;"
+ "}"
+ "if(!mod.sin.wyvern.AntiCheat.isVisibleToAntiCheat($1, this.watcher)){"
+ " return false;"
+ "}");
} catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) {
throw new HookException((Throwable)e);
}
}
}

View File

@@ -0,0 +1,244 @@
package mod.sin.wyvern;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.Creature;
import javassist.ClassPool;
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;
public class Bounty {
public static final Logger logger = Logger.getLogger(Bounty.class.getName());
//protected static WyvernMods mod;
public static HashMap<String, Integer> reward = new HashMap<String, Integer>();
// Using a hook in CombatEngine.addWound, we call this function to create a list of creatures that actually inflicted damage.
public static HashMap<Long, Map<Long, Double>> dealtDamage = new HashMap<Long, Map<Long, Double>>();
public static void addDealtDamage(long defender, long attacker, double damage){
if(dealtDamage.containsKey(defender)){
Map<Long, Double> dealers = dealtDamage.get(defender);
if(!dealers.containsKey(attacker)){
dealers.put(attacker, damage);
}else{
double newDam = dealers.get(attacker);
newDam += damage;
dealers.put(attacker, newDam);
}
}else{
Map<Long, Double> dealers = new HashMap<Long, Double>();
dealers.put(attacker, damage);
dealtDamage.put(defender, dealers);
}
}
public static long lastAttacked(Map<Long, Long> attackers, long playerId){
return System.currentTimeMillis()-attackers.get(playerId);
}
public static boolean isCombatant(Map<Long, Long> attackers, long playerId){
long now = System.currentTimeMillis();
long delta = now-attackers.get(playerId);
if(delta > 120000){
return false;
}
return true;
}
public static Map<Long, Long> getAttackers(Creature mob){
try {
return ReflectionUtil.getPrivateField(mob, ReflectionUtil.getField(mob.getClass(), "attackers"));
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
public static double getCreatureStrength(Creature mob){
float combatRating = mob.getBaseCombatRating() + mob.getBonusCombatRating();
float maxDmg = Math.max(mob.getTemplate().getBreathDamage(), mob.getHandDamage());
maxDmg = Math.max(maxDmg, mob.getBiteDamage());
maxDmg = Math.max(maxDmg, mob.getKickDamage());
maxDmg = Math.max(maxDmg, mob.getHeadButtDamage());
double fighting = mob.getFightingSkill().getKnowledge();
double weaponlessFighting = mob.getWeaponLessFightingSkill().getKnowledge();
double fs = Math.max(fighting, weaponlessFighting);
double bodyStr = mob.getBodyStrength().getKnowledge();
double cretStr = 2000D + ((double)combatRating*(double)maxDmg*Math.sqrt(fs)*bodyStr);
//logger.info("pre-armour: "+cretStr);
//cretStr /= Math.max(mob.getArmourMod(), 0.001d);
fs /= mob.getArmourMod();
cretStr = 500D + ((double)combatRating*Math.cbrt(maxDmg)*Math.sqrt(fs)*Math.cbrt(bodyStr));
cretStr *= 2d;
//logger.info("post-armour: "+cretStr);
//cretStr *= 1-(Math.min(Math.max(mob.getArmourMod(), 0.001d), 0.8f));
//cretStr = 2000D + ((double)combatRating*(double)maxDmg*Math.sqrt(fs)*bodyStr);
double k = 100000000d;
cretStr = (cretStr*Math.pow(2, (-(cretStr/k)))+k*(1-Math.pow(2, -cretStr/k)))/(1+Math.pow(2, -cretStr/k));
if(cretStr < 500D){
cretStr *= 1+(Server.rand.nextFloat()*0.2f);
cretStr = Math.max(cretStr, 500D);
}
//logger.info("capped: "+cretStr);
return cretStr;
}
/*public static void preInit(WyvernMods mod){
Bounty.mod = mod;
//reward.put("black wolf", 750);
}*/
public static void init(){
try {
ClassPool classPool = HookManager.getInstance().getClassPool();
final Class<Bounty> thisClass = Bounty.class;
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);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkCoinAward", replace);
/*ctCreature.getDeclaredMethod("modifyFightSkill").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("checkCoinAward")) {
m.replace("mod.sin.wyvern.bounty.MethodsBounty.checkBounty(player, this);"
+ "$_ = $proceed($$);");
logger.info("Instrumented checkCoinAward to call checkBounty as well.");
return;
}
}
});*/
replace = "$_ = $proceed($$);"
//+ "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);";
+ LootBounty.class.getName()+".checkLootTable(this, corpse);";
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;
}
}
});*/
// 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);"
+ "}";
Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorRed", replace);
replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){"
+ " return "+MethodsBestiary.class.getName()+".getCreatureColorGreen(this);"
+ "}";
Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorGreen", replace);
replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){"
+ " return "+MethodsBestiary.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("getColorGreen").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){"
+ " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorGreen(this);"
+ "}");
ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){"
+ " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorBlue(this);"
+ "}");*/
// -- When a creature takes damage, track the damage taken -- //
CtClass[] params2 = {
ctCreature,
ctCreature,
CtClass.byteType,
CtClass.intType,
CtClass.doubleType,
CtClass.floatType,
classPool.get("java.lang.String"),
classPool.get("com.wurmonline.server.combat.Battle"),
CtClass.floatType,
CtClass.floatType,
CtClass.booleanType,
CtClass.booleanType
};
String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2);
CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine");
replace = ""
+ "if($1 != null && $2 != null){"
+ " "+Bounty.class.getName()+".addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);"
+ "}";
Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc2, replace);
//ctCombatEngine.getMethod("addWound", desc2).insertBefore("if($1 != null && $2 != null){mod.sin.wyvern.bounty.MethodsBounty.addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);}");
}
catch (NotFoundException e) {
throw new HookException((Throwable)e);
}
}
}

View File

@@ -0,0 +1,423 @@
package mod.sin.wyvern;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modsupport.actions.ModActions;
import com.pveplands.treasurehunting.Treasuremap;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemFactory;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.items.ItemSpellEffects;
import com.wurmonline.server.items.Materials;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.items.WurmColor;
import com.wurmonline.server.spells.SpellEffect;
import com.wurmonline.shared.constants.Enchants;
import mod.sin.actions.items.TreasureCacheOpenAction;
import mod.sin.armour.*;
import mod.sin.items.*;
import mod.sin.items.caches.*;
import mod.sin.weapons.*;
public class Caches {
public static final Logger logger = Logger.getLogger(Caches.class.getName());
public static ArrayList<Integer> CACHE_IDS = new ArrayList<Integer>();
public static AnimalCache ANIMAL_CACHE = new AnimalCache();
public static ArmourCache ARMOUR_CACHE = new ArmourCache();
public static ArtifactCache ARTIFACT_CACHE = new ArtifactCache();
public static CrystalCache CRYSTAL_CACHE = new CrystalCache();
public static DragonCache DRAGON_CACHE = new DragonCache();
public static GemCache GEM_CACHE = new GemCache();
public static MoonCache MOON_CACHE = new MoonCache();
public static PotionCache POTION_CACHE = new PotionCache();
public static RiftCache RIFT_CACHE = new RiftCache();
public static ToolCache TOOL_CACHE = new ToolCache();
public static TreasureMapCache TREASUREMAP_CACHE = new TreasureMapCache();
public static WeaponCache WEAPON_CACHE = new WeaponCache();
public static boolean isTreasureCache(Item item){
int templateId = item.getTemplateId();
if(CACHE_IDS.contains(templateId)){
return true;
}
return false;
}
public static float getBaseQuality(float quality){
return quality*0.5f;
}
public static float getRandomQuality(float quality){
return quality*0.55f;
}
public static float getWeightMultiplier(int templateId, float quality){
if(templateId == DragonCache.templateId){
return (quality*0.005f)+(quality*0.001f*Server.rand.nextFloat());
}else if(templateId == MoonCache.templateId){
return 1f+(quality*0.05f)+(quality*0.05f*Server.rand.nextFloat());
}
return 1f+(quality*0.02f);
}
public static boolean adjustBasicWeight(int templateId){
if(templateId == DragonCache.templateId){
return true;
}else if(templateId == MoonCache.templateId){
return true;
}
return false;
}
public static void applyEnchant(Item item, byte enchant, float power){
ItemSpellEffects effs = item.getSpellEffects();
if(effs == null){
effs = new ItemSpellEffects(item.getWurmId());
}
SpellEffect eff = new SpellEffect(item.getWurmId(), enchant, power, 20000000);
effs.addSpellEffect(eff);
if(item.getDescription().length() > 0){
item.setDescription(item.getDescription()+" ");
}
item.setDescription(item.getDescription()+eff.getName().substring(0,1)+Math.round(power));
}
public static boolean createsCustomBasic(int templateId){
if(templateId == TreasureMapCache.templateId){
return true;
}
return false;
}
public static void getCustomBasic(Creature performer, Item cache){
int templateId = cache.getTemplateId();
if(templateId == TreasureMapCache.templateId){
Item map = Treasuremap.CreateTreasuremap(performer, cache, null, null, true);
map.setRarity(cache.getRarity());
performer.getInventory().insertItem(map, true);
}
}
public static int[] getBasicTemplates(int templateId){
if(templateId == ArmourCache.templateId){
return new int[]{
ItemList.clothGlove, ItemList.clothHood, ItemList.clothHose, ItemList.clothJacket, ItemList.clothJacket, ItemList.clothShirt, ItemList.clothShoes, ItemList.clothSleeve,
ItemList.leatherBoot, ItemList.leatherCap, ItemList.leatherGlove, ItemList.leatherHose, ItemList.leatherJacket, ItemList.leatherSleeve,
ItemList.studdedLeatherBoot, ItemList.studdedLeatherCap, ItemList.studdedLeatherGlove, ItemList.studdedLeatherHose, ItemList.studdedLeatherHose, ItemList.studdedLeatherJacket, ItemList.studdedLeatherSleeve,
ItemList.chainBoot, ItemList.chainCoif, ItemList.chainGlove, ItemList.chainHose, ItemList.chainJacket, ItemList.chainSleeve,
ItemList.plateBoot, ItemList.plateGauntlet, ItemList.plateHose, ItemList.plateJacket, ItemList.plateSleeve, ItemList.helmetGreat, ItemList.helmetBasinet, ItemList.helmetOpen
};
}else if(templateId == ArtifactCache.templateId){
return new int[]{
ItemList.swordShort, ItemList.swordLong, ItemList.swordTwoHander,
ItemList.axeSmall, ItemList.axeMedium, ItemList.axeHuge,
ItemList.maulSmall, ItemList.maulMedium, ItemList.maulLarge,
ItemList.spearLong, ItemList.staffSteel, ItemList.halberd,
Club.templateId, Knuckles.templateId, Warhammer.templateId
};
}else if(templateId == CrystalCache.templateId){
return new int[]{
ChaosCrystal.templateId, ChaosCrystal.templateId,
EnchantersCrystal.templateId
};
}else if(templateId == DragonCache.templateId){
return new int[]{
ItemList.drakeHide,
ItemList.drakeHide,
ItemList.dragonScale,
ItemList.dragonScale,
SpectralHide.templateId
};
}else if(templateId == GemCache.templateId){
return new int[]{
ItemList.diamond,
ItemList.emerald,
ItemList.opal,
ItemList.ruby,
ItemList.sapphire
};
}else if(templateId == MoonCache.templateId){
return new int[]{
ItemList.glimmerSteelBar,
ItemList.adamantineBar
};
}else if(templateId == PotionCache.templateId){
return new int[]{
ItemList.potionAcidDamage,
ItemList.potionArmourSmithing,
ItemList.potionBlacksmithing,
ItemList.potionCarpentry,
ItemList.potionFireDamage,
ItemList.potionFletching,
ItemList.potionFrostDamage,
ItemList.potionLeatherworking,
ItemList.potionMasonry,
ItemList.potionMining,
ItemList.potionRopemaking,
ItemList.potionShipbuilding,
ItemList.potionStonecutting,
ItemList.potionTailoring,
ItemList.potionWeaponSmithing,
ItemList.potionWoodcutting
};
}else if(templateId == RiftCache.templateId){
return new int[]{
ItemList.riftCrystal,
ItemList.riftWood,
ItemList.riftStone
};
}
return null;
}
public static void adjustBasicItem(int templateId, float quality, Item item){
if(templateId == ArmourCache.templateId){
if(quality > 50){
if(quality > 95 && Server.rand.nextBoolean()){
applyEnchant(item, Enchants.BUFF_SHARED_PAIN, quality*Server.rand.nextFloat()*1.2f);
applyEnchant(item, Enchants.BUFF_WEBARMOUR, quality*Server.rand.nextFloat()*1.2f);
}else if(Server.rand.nextBoolean()){
byte[] armourEnchants = {
Enchants.BUFF_SHARED_PAIN,
Enchants.BUFF_WEBARMOUR
};
applyEnchant(item, armourEnchants[Server.rand.nextInt(armourEnchants.length)], quality*Server.rand.nextFloat()*1.5f);
}
}
if(quality > 80 && Server.rand.nextInt(4) == 0){
byte[] materials = {
Materials.MATERIAL_ADAMANTINE,
Materials.MATERIAL_COTTON,
Materials.MATERIAL_GLIMMERSTEEL,
Materials.MATERIAL_IRON,
Materials.MATERIAL_LEATHER,
Materials.MATERIAL_SERYLL,
Materials.MATERIAL_STEEL
};
item.setMaterial(materials[Server.rand.nextInt(materials.length)]);
}else{
if(item.isMetal()){
item.setMaterial(Materials.MATERIAL_IRON);
}else if(item.isLeather()){
item.setMaterial(Materials.MATERIAL_LEATHER);
}
}
}else if(templateId == ArtifactCache.templateId){
byte[] materials = {
Materials.MATERIAL_ADAMANTINE,
Materials.MATERIAL_GLIMMERSTEEL,
Materials.MATERIAL_STEEL
};
item.setMaterial(materials[Server.rand.nextInt(materials.length)]);
float qualBoost = (100f-item.getQualityLevel())*Server.rand.nextFloat();
item.setQualityLevel(item.getQualityLevel()+qualBoost);
if(quality > 50 && Server.rand.nextInt(200) < quality){
if(item.getRarity() == 0){
if(Server.rand.nextInt(600) < quality){
item.setRarity((byte) 2);
}else{
item.setRarity((byte) 1);
}
}
}
if(quality > 70 && Server.rand.nextBoolean()){
if(Server.rand.nextBoolean()){
byte[] enchants = {
Enchants.BUFF_WIND_OF_AGES,
Enchants.BUFF_BLESSINGDARK
};
applyEnchant(item, enchants[Server.rand.nextInt(enchants.length)], quality*Server.rand.nextFloat()*0.9f);
applyEnchant(item, Enchants.BUFF_NIMBLENESS, quality*Server.rand.nextFloat()*1.2f);
}else{
applyEnchant(item, Enchants.BUFF_LIFETRANSFER, quality+(quality*Server.rand.nextFloat()));
}
}
}else if(templateId == CrystalCache.templateId){
item.setQualityLevel(Server.rand.nextFloat()*quality);
}
}
public static int getBasicNums(int templateId){
if(templateId == CrystalCache.templateId){
return 15;
}else if(templateId == GemCache.templateId){
return 2;
}
return 1;
}
public static int getExtraBasicNums(int templateId, float quality){
if(templateId == ArmourCache.templateId){
return Server.rand.nextInt(2);
}else if(templateId == CrystalCache.templateId){
return Server.rand.nextInt(Math.max((int) (quality*0.3f), 2));
}else if(templateId == DragonCache.templateId){
if(Server.rand.nextInt(200) <= quality){
return 1;
}
}else if(templateId == GemCache.templateId){
return Server.rand.nextInt(Math.max((int) (quality*0.03f), 2));
}else if(templateId == PotionCache.templateId){
if(Server.rand.nextInt(300) <= quality){
return 1;
}
}else if(templateId == RiftCache.templateId){
if(Server.rand.nextInt(300) <= quality){
return 2;
}else if(Server.rand.nextInt(100) <= quality){
return 1;
}
}
return 0;
}
public static int getExtraItemChance(int templateId){
if(templateId == ArmourCache.templateId){
return 1600;
}else if(templateId == DragonCache.templateId){
return 600;
}else if(templateId == GemCache.templateId){
return 200;
}
return -1;
}
public static int[] getExtraTemplates(int templateId){
if(templateId == ArmourCache.templateId){
return new int[]{
GlimmerscaleBoot.templateId,
GlimmerscaleGlove.templateId,
GlimmerscaleHelmet.templateId,
GlimmerscaleHose.templateId,
GlimmerscaleSleeve.templateId,
GlimmerscaleVest.templateId,
SpectralBoot.templateId,
SpectralCap.templateId,
SpectralGlove.templateId,
SpectralHose.templateId,
SpectralJacket.templateId,
SpectralSleeve.templateId
};
}else if(templateId == DragonCache.templateId){
return new int[]{
ItemList.dragonLeatherBoot,
ItemList.dragonLeatherCap,
ItemList.dragonLeatherGlove,
ItemList.dragonLeatherHose,
ItemList.dragonLeatherJacket,
ItemList.dragonLeatherSleeve,
ItemList.dragonScaleBoot,
ItemList.dragonScaleGauntlet,
ItemList.dragonScaleHose,
ItemList.dragonScaleJacket,
ItemList.dragonScaleSleeve
};
}else if(templateId == GemCache.templateId){
return new int[]{
ItemList.opalBlack,
ItemList.diamondStar,
ItemList.emeraldStar,
ItemList.rubyStar,
ItemList.sapphireStar
};
}
return null;
}
public static void adjustExtraItem(int templateId, Item item){
if(templateId == ArmourCache.templateId){
item.setColor(WurmColor.createColor(100, 100, 100));
}else if(templateId == DragonCache.templateId){
item.setMaterial(Materials.MATERIAL_LEATHER);
}
}
public static void openCache(Creature performer, Item cache){
int templateId = cache.getTemplateId();
Item inv = performer.getInventory();
float quality = cache.getCurrentQualityLevel();
float baseQL = getBaseQuality(quality);
float randQL = getRandomQuality(quality);
if(createsCustomBasic(templateId)){
getCustomBasic(performer, cache);
}else{
int[] basicTemplates = getBasicTemplates(templateId);
if(basicTemplates == null){
logger.warning("Error: Basic Templates are null for cache with template id "+templateId);
return;
}
int basicNums = getBasicNums(templateId);
basicNums += getExtraBasicNums(templateId, quality);
int i = 0;
while(i < basicNums){
try {
float basicQuality = Math.max(baseQL+(randQL*Server.rand.nextFloat()), baseQL+(randQL*Server.rand.nextFloat()));
basicQuality = Math.min(basicQuality, 100f);
Item basicItem = ItemFactory.createItem(basicTemplates[Server.rand.nextInt(basicTemplates.length)], basicQuality, "");
basicItem.setRarity(cache.getRarity());
adjustBasicItem(templateId, quality, basicItem);
if(adjustBasicWeight(templateId)){
float weightMult = getWeightMultiplier(templateId, quality);
basicItem.setWeight((int) (basicItem.getWeightGrams()*weightMult), true);
}
inv.insertItem(basicItem, true);
} catch (FailedException | NoSuchTemplateException e) {
logger.warning("Error: Failed to create item for cache with template id "+templateId);
e.printStackTrace();
}
i++;
}
}
int chance = getExtraItemChance(templateId);
if(chance > 0 && Server.rand.nextInt(chance) <= quality){
try {
int[] extraTemplates = getExtraTemplates(templateId);
if(extraTemplates != null){
float extraQuality = Math.max(baseQL+(randQL*Server.rand.nextFloat()), baseQL+(randQL*Server.rand.nextFloat()));
extraQuality = Math.min(extraQuality, 100f);
Item extraItem = ItemFactory.createItem(extraTemplates[Server.rand.nextInt(extraTemplates.length)], extraQuality, "");
extraItem.setRarity(cache.getRarity());
adjustExtraItem(templateId, extraItem);
inv.insertItem(extraItem, true);
}
} catch (FailedException | NoSuchTemplateException e) {
logger.warning("Error: Failed to create item for cache with template id "+templateId);
e.printStackTrace();
}
}
}
public static void createItems(){
try {
ANIMAL_CACHE.createTemplate();
//CACHE_IDS.add(AnimalCache.templateId);
ARMOUR_CACHE.createTemplate();
CACHE_IDS.add(ArmourCache.templateId);
ARTIFACT_CACHE.createTemplate();
CACHE_IDS.add(ArtifactCache.templateId);
CRYSTAL_CACHE.createTemplate();
CACHE_IDS.add(CrystalCache.templateId);
DRAGON_CACHE.createTemplate();
CACHE_IDS.add(DragonCache.templateId);
GEM_CACHE.createTemplate();
CACHE_IDS.add(GemCache.templateId);
MOON_CACHE.createTemplate();
CACHE_IDS.add(MoonCache.templateId);
POTION_CACHE.createTemplate();
CACHE_IDS.add(PotionCache.templateId);
RIFT_CACHE.createTemplate();
CACHE_IDS.add(RiftCache.templateId);
TOOL_CACHE.createTemplate();
//CACHE_IDS.add(ToolCache.templateId);
TREASUREMAP_CACHE.createTemplate();
CACHE_IDS.add(TreasureMapCache.templateId);
WEAPON_CACHE.createTemplate();
//CACHE_IDS.add(WeaponCache.templateId);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void registerActions(){
ModActions.registerAction(new TreasureCacheOpenAction());
}
}

View File

@@ -0,0 +1,130 @@
package mod.sin.wyvern;
import com.wurmonline.server.Server;
import com.wurmonline.server.Servers;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemSpellEffects;
import com.wurmonline.server.items.NotOwnedException;
import com.wurmonline.shared.constants.Enchants;
import mod.sin.items.ChaosCrystal;
import mod.sin.items.EnchantersCrystal;
public class Crystals {
public static byte[] enchs = { // Valid enchants to apply to an item with Enchanters Crystals
Enchants.BUFF_BLESSINGDARK,
Enchants.BUFF_BLOODTHIRST,
Enchants.BUFF_CIRCLE_CUNNING,
Enchants.BUFF_COURIER,
Enchants.BUFF_FLAMING_AURA,
Enchants.BUFF_FROSTBRAND,
Enchants.BUFF_LIFETRANSFER,
Enchants.BUFF_MINDSTEALER,
Enchants.BUFF_NIMBLENESS,
Enchants.BUFF_OPULENCE,
Enchants.BUFF_ROTTING_TOUCH,
Enchants.BUFF_SHARED_PAIN,
Enchants.BUFF_VENOM,
Enchants.BUFF_WEBARMOUR,
Enchants.BUFF_WIND_OF_AGES,
110, 111 // Harden and Phasing
};
public static byte getNewRandomEnchant(Item target){
int i = 0;
while(i < 10){
byte ench = enchs[Server.rand.nextInt(enchs.length)];
if(target.getBonusForSpellEffect(ench) == 0f){
return ench;
}
i++;
}
return -10;
}
public static double getInfusionDifficulty(Creature performer, Item source, Item target){
double diff = (Servers.localServer.PVPSERVER ? 150 : 120)-source.getCurrentQualityLevel();
diff += source.getRarity()*(Servers.localServer.PVPSERVER ? 50 : 30);
diff += 40f - (target.getCurrentQualityLevel()*0.4f);
diff -= performer.getSoulDepth().getKnowledge();
if(Servers.localServer.PVPSERVER){ // Added difficulty to account for PvP epic curve:
diff *= 1.4f;
}
return diff;
}
public static double getEnchantersInfusionDifficulty(Creature performer, Item source, Item target){
double diff = (Servers.localServer.PVPSERVER ? 220 : 180)-source.getCurrentQualityLevel();
diff += 40f - (target.getCurrentQualityLevel()*0.4f);
diff -= performer.getSoulDepth().getKnowledge();
if(Servers.localServer.PVPSERVER){ // Added difficulty to account for PvP epic curve:
diff *= 1.4f;
}
return diff;
}
public static boolean shouldCancelEnchantersInfusion(Creature performer, Item target){
if(target.getOwnerId() != performer.getWurmId() && target.getLastOwnerId() != performer.getWurmId()){
performer.getCommunicator().sendNormalServerMessage("You must own the item you wish to infuse.");
return true;
}
ItemSpellEffects effs = target.getSpellEffects();
if(effs == null || effs.getEffects().length == 0){
performer.getCommunicator().sendNormalServerMessage("The item must be enchanted to be infused.");
return true;
}
return false;
}
public static boolean shouldCancelInfusion(Creature performer, Item source, Item target){
if(target.getOwnerId() != performer.getWurmId() && target.getLastOwnerId() != performer.getWurmId()){
performer.getCommunicator().sendNormalServerMessage("You must own the item you wish to infuse.");
return true;
}
if(source.getRarity() > target.getRarity()+1){
performer.getCommunicator().sendNormalServerMessage("The "+source.getName()+" is too powerful, and would outright destroy the "+target.getName()+".");
return true;
}else if(source.getRarity() < target.getRarity()+1){
performer.getCommunicator().sendNormalServerMessage("The "+source.getName()+" is not powerful enough to have an effect on the "+target.getName()+". You will need to combine with other crystals first.");
return true;
}
return false;
}
public static boolean shouldCancelCombine(Creature performer, Item source, Item target){
if(source.getWurmId() == target.getWurmId()){
performer.getCommunicator().sendNormalServerMessage("You can't combine a crystal with itself, silly!");
return true;
}
if(!Crystals.isCrystal(source) || !Crystals.isCrystal(target)){
performer.getCommunicator().sendNormalServerMessage("Both objects must be Crystals to combine.");
return true;
}
if(source.getTemplateId() != target.getTemplateId()){
performer.getCommunicator().sendNormalServerMessage("Both crystals must be of the same type to combine.");
return true;
}
try {
if(source.getOwner() != performer.getWurmId() || target.getOwner() != performer.getWurmId()){
performer.getCommunicator().sendNormalServerMessage("You must hold both crystals in your hands to combine them.");
return true;
}
} catch (NotOwnedException e) {
e.printStackTrace();
}
if(source.getRarity() < target.getRarity()){
performer.getCommunicator().sendNormalServerMessage("That crystal is too potent for this combination.");
return true;
}else if(source.getRarity() > target.getRarity()){
performer.getCommunicator().sendNormalServerMessage("That crystal is not potent enough for this combination.");
return true;
}else if(source.getRarity() >= 3 && target.getRarity() >= 3 && source.getCurrentQualityLevel() + target.getCurrentQualityLevel() >= 100){
performer.getCommunicator().sendNormalServerMessage("Those crystals would be far too powerful if combined.");
return true;
}
return false;
}
public static boolean isCrystal(Item item){
if(item.getTemplateId() == ChaosCrystal.templateId){
return true;
}else if(item.getTemplateId() == EnchantersCrystal.templateId){
return true;
}
return false;
}
}

View File

@@ -0,0 +1,419 @@
package mod.sin.wyvern;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory;
import org.gotti.wurmunlimited.modsupport.actions.ModActions;
import com.wurmonline.server.behaviours.ActionEntry;
import com.wurmonline.server.combat.Armour;
import com.wurmonline.server.combat.Weapon;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.items.ItemTemplate;
import com.wurmonline.server.items.ItemTemplateFactory;
import com.wurmonline.server.items.NoSuchTemplateException;
import javassist.CtClass;
import javassist.bytecode.Descriptor;
import mod.sin.actions.items.*;
import mod.sin.armour.*;
import mod.sin.items.*;
import mod.sin.weapons.*;
import mod.sin.weapons.heads.*;
import mod.sin.weapons.titan.*;
public class ItemMod {
public static Logger logger = Logger.getLogger(ItemMod.class.getName());
public static AffinityOrb AFFINITY_ORB = new AffinityOrb();
public static ArenaCache ARENA_CACHE = new ArenaCache();
public static ArenaSupplyDepot ARENA_SUPPLY_DEPOT = new ArenaSupplyDepot();
public static ArrowPackHunting ARROW_PACK_HUNTING = new ArrowPackHunting();
public static ArrowPackWar ARROW_PACK_WAR = new ArrowPackWar();
public static BattleYoyo BATTLE_YOYO = new BattleYoyo();
public static Club CLUB = new Club();
public static CoinDecoration COIN_DECORATION = new CoinDecoration();
public static CorpseDecoration CORPSE_DECORATION = new CorpseDecoration();
public static DepthDrill DEPTH_DRILL = new DepthDrill();
public static DisintegrationRod DISINTEGRATION_ROD = new DisintegrationRod();
public static EnchantOrb ENCHANT_ORB = new EnchantOrb();
public static Eviscerator EVISCERATOR = new Eviscerator();
public static FriyanTablet FRIYAN_TABLET = new FriyanTablet();
public static HugeCrate HUGE_CRATE = new HugeCrate();
public static Knuckles KNUCKLES = new Knuckles();
public static MassStorageUnit MASS_STORAGE_UNIT = new MassStorageUnit();
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();
public static Warhammer WARHAMMER = new Warhammer();
public static WarhammerHead WARHAMMER_HEAD = new WarhammerHead();
// Crystals
public static ChaosCrystal CHAOS_CRYSTAL = new ChaosCrystal();
public static EnchantersCrystal ENCHANTERS_CRYSTAL = new EnchantersCrystal();
// Titan weaponry
public static MaartensMight MAARTENS_MIGHT = new MaartensMight();
public static RaffehsRage RAFFEHS_RAGE = new RaffehsRage();
public static VindictivesVengeance VINDICTIVES_VENGEANCE = new VindictivesVengeance();
public static WilhelmsWrath WILHELMS_WRATH = new WilhelmsWrath();
// Spectral set
public static SpectralHide SPECTRAL_HIDE = new SpectralHide();
public static SpectralBoot SPECTRAL_BOOT = new SpectralBoot();
public static SpectralCap SPECTRAL_CAP = new SpectralCap();
public static SpectralGlove SPECTRAL_GLOVE = new SpectralGlove();
public static SpectralHose SPECTRAL_HOSE = new SpectralHose();
public static SpectralJacket SPECTRAL_JACKET = new SpectralJacket();
public static SpectralSleeve SPECTRAL_SLEEVE = new SpectralSleeve();
// Glimmerscale set
public static Glimmerscale GLIMMERSCALE = new Glimmerscale();
public static GlimmerscaleBoot GLIMMERSCALE_BOOT = new GlimmerscaleBoot();
public static GlimmerscaleGlove GLIMMERSCALE_GLOVE = new GlimmerscaleGlove();
public static GlimmerscaleHelmet GLIMMERSCALE_HELMET = new GlimmerscaleHelmet();
public static GlimmerscaleHose GLIMMERSCALE_HOSE = new GlimmerscaleHose();
public static GlimmerscaleSleeve GLIMMERSCALE_SLEEVE = new GlimmerscaleSleeve();
public static GlimmerscaleVest GLIMMERSCALE_VEST = new GlimmerscaleVest();
public static void createItems(){
logger.info("createItems()");
try{
AFFINITY_ORB.createTemplate();
ARENA_CACHE.createTemplate();
ARENA_SUPPLY_DEPOT.createTemplate();
ARROW_PACK_HUNTING.createTemplate();
ARROW_PACK_WAR.createTemplate();
BATTLE_YOYO.createTemplate();
CLUB.createTemplate();
COIN_DECORATION.createTemplate();
CORPSE_DECORATION.createTemplate();
DEPTH_DRILL.createTemplate();
DISINTEGRATION_ROD.createTemplate();
ENCHANT_ORB.createTemplate();
EVISCERATOR.createTemplate();
FRIYAN_TABLET.createTemplate();
HUGE_CRATE.createTemplate();
KNUCKLES.createTemplate();
MASS_STORAGE_UNIT.createTemplate();
SEALED_MAP.createTemplate();
SKELETON_DECORATION.createTemplate();
SOUL.createTemplate();
SOUL_FORGE.createTemplate();
STATUETTE_BREYK.createTemplate();
STATUETTE_CYBERHUSKY.createTemplate();
TREASURE_BOX.createTemplate();
WARHAMMER.createTemplate();
WARHAMMER_HEAD.createTemplate();
// Crystals
CHAOS_CRYSTAL.createTemplate();
ENCHANTERS_CRYSTAL.createTemplate();
// Titan weaponry
MAARTENS_MIGHT.createTemplate();
RAFFEHS_RAGE.createTemplate();
VINDICTIVES_VENGEANCE.createTemplate();
WILHELMS_WRATH.createTemplate();
// Spectral set
SPECTRAL_HIDE.createTemplate();
SPECTRAL_BOOT.createTemplate();
SPECTRAL_CAP.createTemplate();
SPECTRAL_GLOVE.createTemplate();
SPECTRAL_HOSE.createTemplate();
SPECTRAL_JACKET.createTemplate();
SPECTRAL_SLEEVE.createTemplate();
// Glimmerscale set
GLIMMERSCALE.createTemplate();
GLIMMERSCALE_BOOT.createTemplate();
GLIMMERSCALE_GLOVE.createTemplate();
GLIMMERSCALE_HELMET.createTemplate();
GLIMMERSCALE_HOSE.createTemplate();
GLIMMERSCALE_SLEEVE.createTemplate();
GLIMMERSCALE_VEST.createTemplate();
}catch(IOException e){
e.printStackTrace();
}
}
public static void registerActions(){
ModActions.registerAction(new AffinityOrbAction());
ModActions.registerAction(new ArenaCacheOpenAction());
ModActions.registerAction(new ArrowPackUnpackAction());
ModActions.registerAction(new CrystalCombineAction());
ModActions.registerAction(new ChaosCrystalInfuseAction());
ModActions.registerAction(new DepthDrillAction());
ModActions.registerAction(new DisintegrationRodAction());
ModActions.registerAction(new EnchantersCrystalInfuseAction());
ModActions.registerAction(new EnchantOrbAction());
ModActions.registerAction(new FriyanTabletAction());
ModActions.registerAction(new SealedMapAction());
ModActions.registerAction(new SupplyDepotAction());
ModActions.registerAction(new TreasureBoxAction());
}
public static void initCreationEntries(){
logger.info("initCreationEntries()");
ARROW_PACK_HUNTING.initCreationEntry();
ARROW_PACK_WAR.initCreationEntry();
BATTLE_YOYO.initCreationEntry();
CLUB.initCreationEntry();
COIN_DECORATION.initCreationEntry();
CORPSE_DECORATION.initCreationEntry();
DEPTH_DRILL.initCreationEntry();
EVISCERATOR.initCreationEntry();
KNUCKLES.initCreationEntry();
MASS_STORAGE_UNIT.initCreationEntry();
SKELETON_DECORATION.initCreationEntry();
SOUL_FORGE.initCreationEntry();
STATUETTE_BREYK.initCreationEntry();
STATUETTE_CYBERHUSKY.initCreationEntry();
WARHAMMER.initCreationEntry();
WARHAMMER_HEAD.initCreationEntry();
// Spectral set
SPECTRAL_BOOT.initCreationEntry();
SPECTRAL_CAP.initCreationEntry();
SPECTRAL_GLOVE.initCreationEntry();
SPECTRAL_HOSE.initCreationEntry();
SPECTRAL_JACKET.initCreationEntry();
SPECTRAL_SLEEVE.initCreationEntry();
// Glimmerscale set
GLIMMERSCALE.initCreationEntry();
GLIMMERSCALE_BOOT.initCreationEntry();
GLIMMERSCALE_GLOVE.initCreationEntry();
GLIMMERSCALE_HELMET.initCreationEntry();
GLIMMERSCALE_HOSE.initCreationEntry();
GLIMMERSCALE_SLEEVE.initCreationEntry();
GLIMMERSCALE_VEST.initCreationEntry();
// Allow sickle heads from steel & moon metals:
// [3/28/18] Disabled: Implemented in WU 1.6.
/*CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.steelBar,
ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES);
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar,
ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES);
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar,
ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES);
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar,
ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES);
// Allow steel staff to be created from moon metals:
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar,
ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES);
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar,
ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES);
CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar,
ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES);*/
}
public static void createCustomArmours(){
try {
logger.info("Beginning custom armour creation.");
Map<Integer, Armour> armours = ReflectionUtil.getPrivateField(null, ReflectionUtil.getField(Armour.class, "armours"));
armours.put(SpectralBoot.templateId, new Armour(SpectralBoot.templateId, 0.002f, 0.3f));
armours.put(SpectralCap.templateId, new Armour(SpectralCap.templateId, 0.003f, 0.3f));
armours.put(SpectralGlove.templateId, new Armour(SpectralGlove.templateId, 0.002f, 0.3f));
armours.put(SpectralHose.templateId, new Armour(SpectralHose.templateId, 0.0075f, 0.3f));
armours.put(SpectralJacket.templateId, new Armour(SpectralJacket.templateId, 0.01f, 0.3f));
armours.put(SpectralSleeve.templateId, new Armour(SpectralSleeve.templateId, 0.004f, 0.3f));
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));
//ReflectionUtil.setPrivateField(null, ReflectionUtil.getField(Armour.class, "armours"), armours);
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
public static void createCustomWeapons(){
try {
logger.info("Beginning custom weapon creation.");
new Weapon(BattleYoyo.templateId, 7.75f, 3.5f, 0.008f, 2, 2, 0.0f, 0d);
new Weapon(Club.templateId, 8.5f, 4.1f, 0.002f, 3, 3, 0.4f, 0.5d);
new Weapon(Knuckles.templateId, 4.1f, 1f, 0.002f, 1, 1, 0.2f, 0.5d);
new Weapon(Warhammer.templateId, 9.75f, 5.2f, 0.008f, 4, 3, 1f, 0d);
// Titan weaponry
new Weapon(MaartensMight.templateId, 11, 5, 0.02f, 4, 4, 1.0f, 0d);
new Weapon(RaffehsRage.templateId, 9.5f, 4.25f, 0.02f, 3, 3, 1.0f, 0d);
new Weapon(VindictivesVengeance.templateId, 9, 4f, 0.02f, 3, 3, 0.5f, 0d);
new Weapon(WilhelmsWrath.templateId, 6f, 4.5f, 0.02f, 6, 6, 0.5f, 0d);
// Genocide weapon
new Weapon(Eviscerator.templateId, 11, 4.5f, 0.02f, 5, 5, 0.4f, 0.5d);
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
}
public static int getModdedImproveTemplateId(Item item){
if(item.getTemplateId() == SpectralBoot.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == SpectralCap.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == SpectralGlove.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == SpectralHose.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == SpectralJacket.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == SpectralSleeve.templateId){
return SpectralHide.templateId;
}else if(item.getTemplateId() == GlimmerscaleBoot.templateId){
return Glimmerscale.templateId;
}else if(item.getTemplateId() == GlimmerscaleGlove.templateId){
return Glimmerscale.templateId;
}else if(item.getTemplateId() == GlimmerscaleHelmet.templateId){
return Glimmerscale.templateId;
}else if(item.getTemplateId() == GlimmerscaleHose.templateId){
return Glimmerscale.templateId;
}else if(item.getTemplateId() == GlimmerscaleSleeve.templateId){
return Glimmerscale.templateId;
}else if(item.getTemplateId() == GlimmerscaleVest.templateId){
return Glimmerscale.templateId;
}
return -10;
}
public static void modifyItems() throws NoSuchTemplateException, IllegalArgumentException, IllegalAccessException, ClassCastException, NoSuchFieldException{
// Make leather able to be combined.
ItemTemplate leather = ItemTemplateFactory.getInstance().getTemplate(ItemList.leather);
ReflectionUtil.setPrivateField(leather, ReflectionUtil.getField(leather.getClass(), "combine"), true);
// Set silver mirror price to 10 silver instead of 1 iron.
ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror);
ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 500000);
ItemTemplate goldMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.goldenMirror);
ReflectionUtil.setPrivateField(goldMirror, ReflectionUtil.getField(goldMirror.getClass(), "value"), 3000000);
// Set transmutation rod to 2 gold instead of 50 silver.
//ItemTemplate transmutationRod = ItemTemplateFactory.getInstance().getTemplate(668);
//ReflectionUtil.setPrivateField(transmutationRod, ReflectionUtil.getField(transmutationRod.getClass(), "value"), 2000000);
// Make logs able to be combined.
ItemTemplate log = ItemTemplateFactory.getInstance().getTemplate(ItemList.log);
ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "combine"), true);
// " return this.isTransportable || (this.getTemplateId() >= 510 && this.getTemplateId() <= 513) || this.getTemplateId() == 722 || this.getTemplateId() == 670;"
// Make mailboxes loadable
ItemTemplate mailboxWood = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxWood);
ReflectionUtil.setPrivateField(mailboxWood, ReflectionUtil.getField(mailboxWood.getClass(), "isTransportable"), true);
ItemTemplate mailboxStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxStone);
ReflectionUtil.setPrivateField(mailboxStone, ReflectionUtil.getField(mailboxStone.getClass(), "isTransportable"), true);
ItemTemplate mailboxWood2 = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxWoodTwo);
ReflectionUtil.setPrivateField(mailboxWood2, ReflectionUtil.getField(mailboxWood2.getClass(), "isTransportable"), true);
ItemTemplate mailboxStone2 = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxStoneTwo);
ReflectionUtil.setPrivateField(mailboxStone2, ReflectionUtil.getField(mailboxStone2.getClass(), "isTransportable"), true);
// Make bell towers and trash bins loadable
ItemTemplate bellTower = ItemTemplateFactory.getInstance().getTemplate(ItemList.bellTower);
ReflectionUtil.setPrivateField(bellTower, ReflectionUtil.getField(bellTower.getClass(), "isTransportable"), true);
ItemTemplate trashBin = ItemTemplateFactory.getInstance().getTemplate(ItemList.trashBin);
ReflectionUtil.setPrivateField(trashBin, ReflectionUtil.getField(trashBin.getClass(), "isTransportable"), true);
// Make altars loadable
ItemTemplate stoneAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarStone);
ReflectionUtil.setPrivateField(stoneAltar, ReflectionUtil.getField(stoneAltar.getClass(), "isTransportable"), true);
ItemTemplate woodAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarWood);
ReflectionUtil.setPrivateField(woodAltar, ReflectionUtil.getField(woodAltar.getClass(), "isTransportable"), true);
ItemTemplate silverAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarSilver);
ReflectionUtil.setPrivateField(silverAltar, ReflectionUtil.getField(silverAltar.getClass(), "isTransportable"), true);
ItemTemplate goldAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarGold);
ReflectionUtil.setPrivateField(goldAltar, ReflectionUtil.getField(goldAltar.getClass(), "isTransportable"), true);
// Make long spears one-handed.
ItemTemplate longSpear = ItemTemplateFactory.getInstance().getTemplate(ItemList.spearLong);
ReflectionUtil.setPrivateField(longSpear, ReflectionUtil.getField(longSpear.getClass(), "isTwohanded"), false);
// Make dirt/sand difficulty easier
ItemTemplate dirt = ItemTemplateFactory.getInstance().getTemplate(ItemList.dirtPile);
ReflectionUtil.setPrivateField(dirt, ReflectionUtil.getField(dirt.getClass(), "difficulty"), 50.0f);
ItemTemplate sand = ItemTemplateFactory.getInstance().getTemplate(ItemList.sand);
ReflectionUtil.setPrivateField(sand, ReflectionUtil.getField(sand.getClass(), "difficulty"), 50.0f);
ItemTemplate sandstone = ItemTemplateFactory.getInstance().getTemplate(ItemList.sandstone);
ReflectionUtil.setPrivateField(sandstone, ReflectionUtil.getField(sandstone.getClass(), "difficulty"), 50.0f);
createCustomWeapons();
createCustomArmours();
// Make huge crates larger
//ItemTemplate hugeCrate = ItemTemplateFactory.getInstance().getTemplate(HUGE_CRATE.getTemplateId());
//ReflectionUtil.setPrivateField(hugeCrate, ReflectionUtil.getField(hugeCrate.getClass(), "combine"), true);
}
public static void registerPermissionsHook(){
try {
CtClass[] input = {
HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"),
HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item")
};
CtClass output = HookManager.getInstance().getClassPool().get("java.util.List");
HookManager.getInstance().registerHook("com.wurmonline.server.behaviours.VehicleBehaviour", "getVehicleBehaviours",
Descriptor.ofMethod(output, input), new InvocationHandlerFactory() {
@Override
public InvocationHandler createInvocationHandler() {
return new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
@SuppressWarnings("unchecked")
List<ActionEntry> original = (List<ActionEntry>) method.invoke(proxy, args);
Item item = (Item) args[1];
Creature performer = (Creature) args[0];
LinkedList<ActionEntry> permissions = new LinkedList<ActionEntry>();
if (item.mayManage(performer)) {
int itemId = item.getTemplateId();
if (itemId == MassStorageUnit.templateId) {
//debug("Adding manage permissions");
permissions.add(new ActionEntry((short)669, "Manage Storage Unit", "viewing"));
}
}
if (item.maySeeHistory(performer)) {
int itemId = item.getTemplateId();
if (itemId == MassStorageUnit.templateId) {
permissions.add(new ActionEntry((short)691, "History of Storage Unit", "viewing"));
}
}
if (!permissions.isEmpty()) {
if (permissions.size() > 1) {
Collections.sort(permissions);
original.add(new ActionEntry((short)(- permissions.size()), "Permissions", "viewing"));
}
original.addAll(permissions);
}
return original;
}
};
}
});
}
catch (Exception e) {
logger.info("Permission hook: " + e.toString());
}
}
}

View File

@@ -0,0 +1,943 @@
package mod.sin.wyvern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory;
import org.nyxcode.wurm.discordrelay.DiscordRelay;
import com.wurmonline.mesh.Tiles;
import com.wurmonline.server.Items;
import com.wurmonline.server.NoSuchItemException;
import com.wurmonline.server.NoSuchPlayerException;
import com.wurmonline.server.Players;
import com.wurmonline.server.Server;
import com.wurmonline.server.Servers;
import com.wurmonline.server.TimeConstants;
import com.wurmonline.server.WurmId;
import com.wurmonline.server.bodys.Wound;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
import com.wurmonline.server.creatures.MovementScheme;
import com.wurmonline.server.creatures.NoSuchCreatureException;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.modifiers.DoubleValueModifier;
import com.wurmonline.server.players.Player;
import com.wurmonline.server.skills.NoSuchSkillException;
import com.wurmonline.server.skills.Skill;
import com.wurmonline.server.webinterface.WcKingdomChat;
import com.wurmonline.server.zones.NoSuchZoneException;
import com.wurmonline.server.zones.Zone;
import com.wurmonline.server.zones.Zones;
import com.wurmonline.shared.constants.Enchants;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.Descriptor;
import javassist.expr.ExprEditor;
import javassist.expr.FieldAccess;
import javassist.expr.MethodCall;
import mod.sin.creatures.Avenger;
import mod.sin.creatures.Charger;
import mod.sin.creatures.SpiritTroll;
import mod.sin.creatures.WyvernBlack;
import mod.sin.creatures.WyvernGreen;
import mod.sin.creatures.WyvernRed;
import mod.sin.creatures.WyvernWhite;
import mod.sin.items.SealedMap;
import mod.sin.lib.Util;
import mod.sin.wyvern.arena.Arena;
import mod.sin.wyvern.bestiary.MethodsBestiary;
public class MiscChanges {
public static Logger logger = Logger.getLogger(MiscChanges.class.getName());
public static byte newCreatureType(int templateid, byte ctype) throws Exception{
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateid);
if(ctype == 0 && (template.isAggHuman() || template.getBaseCombatRating() > 10) && !template.isUnique() && !Arena.isTitan(templateid)){
if(Server.rand.nextInt(5) == 0){
ctype = (byte) (Server.rand.nextInt(11)+1);
if(Server.rand.nextInt(50) == 0){
ctype = 99;
}
}
}
return ctype;
}
protected static HashMap<Creature, Double> defDamage = new HashMap<Creature, Double>();
public static void setDefDamage(Creature cret, double damage){
defDamage.put(cret, damage);
}
public static double getDefDamage(Creature cret){
if(defDamage.containsKey(cret)){
double theDamage = defDamage.get(cret);
defDamage.remove(cret);
return theDamage;
}
logger.severe("Severe error: could not find defDamage for creature "+cret);
return 0d;
}
public static void sendRumour(Creature creature){
DiscordRelay.sendToDiscord("rumors", "Rumours of " + creature.getName() + " are starting to spread.");
}
public static int getNewVillageTiles(int tiles){
float power = 2f;
float changeRate = 1000;
float maxNumTiles = 50000;
float tilesFloat = tiles;
// =(C2) * (1-POW(C2/$C$16, $A$24)) + (SQRT(C2)*$A$26) * POW(C2/$C$16, $A$24)
int newTiles = (int) (tilesFloat * (1-Math.pow(tilesFloat/maxNumTiles, power)) + (Math.sqrt(tilesFloat)*changeRate) * Math.pow(tilesFloat/maxNumTiles, power));
return newTiles;
}
private static final float PRICE_MARKUP = 1f/1.4f;
public static int getNewValue(Item item){
if(item.getTemplateId() == SealedMap.templateId){
float qual = item.getQualityLevel();
float dam = item.getDamage();
// =($A$25*A2*A2 / 10000)
float initialValue = ((float)item.getTemplate().getValue())*qual*qual/10000f;
float baseCost = 100000f;
float power = 11.0f;
// =((10+B2/4.5)*(1-POW(A2/100, $A$27)) + B2*POW(A2/100, $A$27)) * ((100 - $A$29) / 100)
int newValue = (int) (((baseCost+(initialValue/4.5f)) * (1f-Math.pow(qual/100f, power)) + initialValue*Math.pow(qual/100f, power)) * ((100f-dam)/100f) * PRICE_MARKUP);
return newValue;
}
return -10;
}
public static void checkEnchantedBreed(Creature creature){
int tile = Server.surfaceMesh.getTile(creature.getTileX(), creature.getTileY());
byte type = Tiles.decodeType((int)tile);
if (type == Tiles.Tile.TILE_ENCHANTED_GRASS.id){
logger.info("Creature "+creature.getName()+" was born on enchanted grass, and has a negative trait removed!");
Server.getInstance().broadCastAction(creature.getName()+" was born on enchanted grass, and feels more healthy!", creature, 10);
creature.removeRandomNegativeTrait();
}
}
public static boolean hasCustomCorpseSize(Creature creature){
int templateId = creature.getTemplate().getTemplateId();
if(templateId == Avenger.templateId){
return true;
}else if(Arena.isTitan(creature)){
return true;
}
return false;
}
public static boolean insertItemIntoVehicle(Item item, Item vehicle, Creature performer) {
// If can put into crates, try that
if (item.getTemplate().isBulk() && item.getRarity() == 0) {
for (Item container : vehicle.getAllItems(true)) {
if(container.getTemplateId() == ItemList.bulkContainer){
if(container.getFreeVolume() >= item.getVolume()){
if (item.AddBulkItem(performer, container)) {
performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s in your %s.", item.getName(), container.getName(), vehicle.getName()));
return true;
}
}
}
if (container.isCrate() && container.canAddToCrate(item)) {
if (item.AddBulkItemToCrate(performer, container)) {
performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s in your %s.", item.getName(), container.getName(), vehicle.getName()));
return true;
}
}
}
}
// No empty crates or disabled, try the vehicle itself
if (vehicle.getNumItemsNotCoins() < 100 && vehicle.getFreeVolume() >= item.getVolume() && vehicle.insertItem(item)) {
performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s.", item.getName(), vehicle.getName()));
return true;
} else {
// Send message if the vehicle is too full
performer.getCommunicator().sendNormalServerMessage(String.format("The %s is too full to hold the %s.", vehicle.getName(), item.getName()));
return false;
}
}
public static Item getVehicleSafe(Creature pilot) {
try {
if (pilot.getVehicle() != -10)
return Items.getItem(pilot.getVehicle());
} catch (NoSuchItemException ignored) {
}
return null;
}
public static void miningHook(Creature performer, Item ore){
Item vehicleItem = getVehicleSafe(performer);
if(vehicleItem != null && vehicleItem.isHollow()){
if(insertItemIntoVehicle(ore, vehicleItem, performer)){
return;
}
}
// Last resort, if no suitable vehicle is found.
try {
ore.putItemInfrontof(performer);
} catch (NoSuchCreatureException | NoSuchItemException | NoSuchPlayerException | NoSuchZoneException e) {
e.printStackTrace();
}
}
public static void setCorpseSizes(Creature creature, Item corpse){
if(corpse.getTemplateId() != ItemList.corpse){
return;
}
int templateId = creature.getTemplate().getTemplateId();
boolean sendStatus = false;
int size = 50000;
if(templateId == Avenger.templateId){
size *= 1.2;
corpse.setSizes(size);
sendStatus = true;
}else if(Arena.isTitan(creature)){
size *= 1.5;
corpse.setSizes(size);
sendStatus = true;
}else{
corpse.setSizes((int)((float)(corpse.getSizeX() * (creature.getSizeModX() & 255)) / 64.0f), (int)((float)(corpse.getSizeY() * (creature.getSizeModY() & 255)) / 64.0f), (int)((float)(corpse.getSizeZ() * (creature.getSizeModZ() & 255)) / 64.0f));
}
if(sendStatus){
try {
Zone zone = Zones.getZone((int)corpse.getPosX() >> 2, (int)corpse.getPosY() >> 2, corpse.isOnSurface());
zone.removeItem(corpse, true, true);
zone.addItem(corpse, true, false, false);
} catch (NoSuchZoneException e) {
e.printStackTrace();
}
}
return;
}
public static void setNewMoveLimits(Creature cret){
try {
Skill strength = cret.getSkills().getSkill(102);
ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "moveslow"), strength.getKnowledge()*4000);
ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "encumbered"), strength.getKnowledge()*7000);
ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "cantmove"), strength.getKnowledge()*14000);
MovementScheme moveScheme = cret.getMovementScheme();
DoubleValueModifier stealthMod = ReflectionUtil.getPrivateField(moveScheme, ReflectionUtil.getField(moveScheme.getClass(), "stealthMod"));
if (stealthMod == null) {
stealthMod = new DoubleValueModifier((- 80.0 - Math.min(79.0, cret.getBodyControl())) / 100.0);
} else {
stealthMod.setModifier((- 80.0 - Math.min(79.0, cret.getBodyControl())) / 100.0);
}
ReflectionUtil.setPrivateField(moveScheme, ReflectionUtil.getField(moveScheme.getClass(), "stealthMod"), stealthMod);
}
catch (NoSuchSkillException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException nss) {
logger.log(Level.WARNING, "No strength skill for " + cret, (Throwable)((Object)nss));
}
}
public static boolean shouldBreedName(Creature creature){
if(creature.getTemplate().getTemplateId() == WyvernBlack.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == WyvernGreen.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == WyvernRed.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == WyvernWhite.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == Charger.templateId){
return true;
}
return creature.isHorse();
}
public static boolean isGhostCorpse(Creature creature){
if(creature.getTemplate().getTemplateId() == Avenger.templateId){
return true;
}else if(creature.getTemplate().getTemplateId() == SpiritTroll.templateId){
return true;
}
return false;
}
public static void doLifeTransfer(Creature creature, Item attWeapon, double defdamage, float armourMod){
Wound[] w;
if (attWeapon.getSpellLifeTransferModifier() > 0.0f && defdamage * (double)armourMod * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : 500.0f) > 500.0 && creature.getBody() != null && creature.getBody().getWounds() != null && (w = creature.getBody().getWounds().getWounds()).length > 0) {
w[0].modifySeverity(- (int)(defdamage * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : (creature.getCultist() != null && creature.getCultist().healsFaster() ? 250.0f : 500.0f))));
}
}
public static 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 void sendServerTabMessage(final String message, final int red, final int green, final int blue){
DiscordRelay.sendToDiscord("event", message);
Runnable r = new Runnable(){
public void run(){
com.wurmonline.server.Message mess;
for(Player rec : Players.getInstance().getPlayers()){
mess = new com.wurmonline.server.Message(rec, (byte)16, "Server", message, red, green, blue);
rec.getCommunicator().sendMessage(mess);
}
}
};
r.run();
}
public static void sendGlobalFreedomChat(final Creature sender, final String message, final int red, final int green, final int blue){
Runnable r = new Runnable(){
public void run(){
com.wurmonline.server.Message mess;
for(Player rec : Players.getInstance().getPlayers()){
mess = new com.wurmonline.server.Message(sender, (byte)10, "GL-Freedom", "<"+sender.getNameWithoutPrefixes()+"> "+message, red, green, blue);
rec.getCommunicator().sendMessage(mess);
}
if (message.trim().length() > 1) {
WcKingdomChat wc = new WcKingdomChat(WurmId.getNextWCCommandId(), sender.getWurmId(), sender.getNameWithoutPrefixes(), message, false, (byte) 4, red, green, blue);
if (!Servers.isThisLoginServer()) {
wc.sendToLoginServer();
} else {
wc.sendFromLoginServer();
}
}
}
};
r.run();
}
public static void sendImportantMessage(Creature sender, String message, int red, int green, int blue){
sendServerTabMessage("<"+sender.getNameWithoutPrefixes()+"> "+message, red, green, blue);
sendGlobalFreedomChat(sender, message, red, green, blue);
}
public static void broadCastDeaths(Creature player, String slayers){
sendGlobalFreedomChat(player, "slain by "+slayers, 200, 25, 25);
DiscordRelay.sendToDiscord("deaths", player+" slain by "+slayers);
}
public static void preInit(){
try{
ClassPool classPool = HookManager.getInstance().getClassPool();
final Class<MiscChanges> thisClass = MiscChanges.class;
String replace;
// - Create Server tab with initial messages - //
CtClass ctPlayers = classPool.get("com.wurmonline.server.Players");
CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat");
String infoTabTitle = "Server";
// Initial messages:
String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/155981-wyvern-reborn-modded-pve-pvp-3x5x/",
"Custom Server Data: https://goo.gl/QRVJyC",
"Server Discord: https://discordapp.com/invite/wxEeS7d",
"Server Maps: https://www.sarcasuals.com/"};
String str = "{"
+ " com.wurmonline.server.Message mess;";
for(int i = 0; i < infoTabLine.length; i++){
str = str + " mess = new com.wurmonline.server.Message(player, (byte)16, \"" + infoTabTitle + "\",\"" + infoTabLine[i] + "\", 0, 255, 0);"
+ " player.getCommunicator().sendMessage(mess);";
}
str = str + "}";
m.insertAfter(str);
// - Enable bridges to be built inside/over/through houses - //
CtClass ctPlanBridgeChecks = classPool.get("com.wurmonline.server.structures.PlanBridgeChecks");
replace = "{ return new com.wurmonline.server.structures.PlanBridgeCheckResult(false); }";
Util.setBodyDeclared(thisClass, ctPlanBridgeChecks, "checkForBuildings", replace);
/*ctPlanBridgeChecks.getDeclaredMethod("checkForBuildings").setBody("{"
+ " return new com.wurmonline.server.structures.PlanBridgeCheckResult(false);"
+ "}");*/
// - Allow mailboxes and bell towers to be loaded - //
// [Disabled 10/30 by Sindusk] - Added to ItemMod using reflection instead of editing the method.
/*CtClass ctItemTemplate = classPool.get("com.wurmonline.server.items.ItemTemplate");
ctItemTemplate.getDeclaredMethod("isTransportable").setBody("{"
+ " return this.isTransportable || (this.getTemplateId() >= 510 && this.getTemplateId() <= 513) || this.getTemplateId() == 722 || this.getTemplateId() == 670;"
+ "}");*/
// - Disable mailboxes from being used while loaded - //
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
replace = "$_ = $proceed($$);"
+ "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);"
+ "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){"
+ " if(theTarget.getTopParent() != theTarget.getWurmId()){"
+ " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");"
+ " return false;"
+ " }"
+ "}";
Util.instrumentDeclared(thisClass, ctItem, "moveToItem", "getOwnerId", replace);
/*ctItem.getDeclaredMethod("moveToItem").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("getOwnerId")) {
m.replace("$_ = $proceed($$);"
+ "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);"
+ "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){"
+ " if(theTarget.getTopParent() != theTarget.getWurmId()){"
+ " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");"
+ " return false;"
+ " }"
+ "}");
return;
}
}
});*/
// - Enable creature custom colors - (Used for creating custom color creatures eg. Lilith) - //
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
Util.setBodyDeclared(thisClass, ctCreature, "hasCustomColor", "{ return true; }");
//ctCreature.getDeclaredMethod("hasCustomColor").setBody("{ return true; }");
// - Increase the amount of checks for new unique spawns by 5x - //
CtClass ctServer = classPool.get("com.wurmonline.server.Server");
replace = "for(int i = 0; i < 5; i++){"
+ " $_ = $proceed($$);"
+ "}";
Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace);
/*ctServer.getDeclaredMethod("run").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("checkDens")) {
m.replace("for(int i = 0; i < 5; i++){$_ = $proceed($$);}");
return;
}
}
});*/
// - Change rarity odds when a player obtains a rarity window - //
// [3/27] Removed: Merged to ServerTweaks
/*CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player");
replace = "{ return "+MiscChanges.class.getName()+".newGetPlayerRarity(this); }";
Util.setBodyDeclared(thisClass, ctPlayer, "getRarity", replace);*/
//ctPlayer.getDeclaredMethod("getRarity").setBody("{ return mod.sin.wyvern.MiscChanges.newGetPlayerRarity(this); }");
// - Add Facebreyker to the list of spawnable uniques - //
CtClass ctDens = classPool.get("com.wurmonline.server.zones.Dens");
replace = "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);";
Util.insertBeforeDeclared(thisClass, ctDens, "checkDens", replace);
//ctDens.getDeclaredMethod("checkDens").insertAt(0, "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);");
// - Announce player titles in the Server tab - //
CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player");
replace = "$_ = $proceed($$);"
+ "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){"
+ " "+MiscChanges.class.getName()+".sendServerTabMessage(this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);"
+ "}";
Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace);
/*ctPlayer.getDeclaredMethod("addTitle").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("sendNormalServerMessage")) {
m.replace("$_ = $proceed($$);"
+ "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){"
+ " mod.sin.wyvern.MiscChanges.sendServerTabMessage(this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);"
+ "}");
return;
}
}
});*/
// - Make leather not suck even after it's able to be combined. - //
CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems");
replace = "if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){"
+ " $_ = $proceed($$);"
+ "}else{"
+ " $_ = false;"
+ "}";
Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace);
/*ctMethodsItems.getDeclaredMethod("improveItem").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isCombine")) {
m.replace("if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){"
+ " $_ = $proceed($$);"
+ "}else{"
+ " $_ = false;"
+ "}");
return;
}
}
});*/
// - Check new improve materials - //
replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);"
+ "if(temp != -10){"
+ " return temp;"
+ "}";
Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace);
/*ctMethodsItems.getDeclaredMethod("getImproveTemplateId").insertBefore(""
+ "int temp = mod.sin.wyvern.ItemMod.getModdedImproveTemplateId($1);"
+ "if(temp != -10){"
+ " return temp;"
+ "}");*/
// - Make food/drink affinities based on Item ID instead of creature ID - //
// [3/27] Removed: Merged to ServerTweaks
/*CtClass ctAffinitiesTimed = classPool.get("com.wurmonline.server.skills.AffinitiesTimed");
replace = "if(item.getCreatorName() != null){"
+ " $_ = $proceed("+MiscChanges.class.getName()+".getTimedAffinitySeed(item));"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}";
Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "getTimedAffinitySkill", "setSeed", replace);
CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour");
replace = "$_ = $proceed($1, $2, $3, $4, performer.getName());";
Util.instrumentDeclared(thisClass, ctItemBehaviour, "handleRecipe", "createItem", replace);
replace = "$_ = $proceed($1, $2, $3, $4, com.wurmonline.server.players.PlayerInfoFactory.getPlayerName(lastowner));";
Util.instrumentDeclared(thisClass, ctItem, "pollFermenting", "createItem", replace);
Util.instrumentDeclared(thisClass, ctItem, "pollDistilling", "createItem", replace);
CtClass ctTempStates = classPool.get("com.wurmonline.server.items.TempStates");
Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "createItem", replace);*/
// - Fix de-priesting when gaining faith below 30 - //
// [Disabled 10/30 Sindusk] - Added to SpellCraft.SpellcraftTweaks
/*CtClass ctDbPlayerInfo = classPool.get("com.wurmonline.server.players.DbPlayerInfo");
ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("min")) {
m.replace("if($2 == 20.0f && $1 < 30){"
+ " $_ = $proceed(30.0f, lFaith);"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}");
return;
}
}
});
ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("setPriest")) {
m.replace("$_ = $proceed(true);");
return;
}
}
});
ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("sendAlertServerMessage")) {
m.replace("$_ = null;");
return;
}
}
});*/
// - Removal of eye/face shots to headshots instead - //
HookManager.getInstance().registerHook("com.wurmonline.server.combat.Armour", "getArmourPosForPos", "(I)I", new InvocationHandlerFactory() {
@Override
public InvocationHandler createInvocationHandler() {
return new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
int pos = (int) args[0];
if (pos == 18 || pos == 19 || pos == 20 || pos == 17) {
args[0] = 34;
//System.out.println("changed eye or face shot into headshot");
}
return method.invoke(proxy, args);
}
};
}
});
// - Remove requirement to bless for Libila taming - //
CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures");
Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", "$_ = false;");
/*ctMethodsCreatures.getDeclaredMethod("tame").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isPriest")) {
m.replace("$_ = false;");
return;
}
}
});*/
// - Remove fatiguing actions requiring you to be on the ground - //
CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action");
CtConstructor[] ctActionConstructors = ctAction.getConstructors();
for(CtConstructor constructor : ctActionConstructors){
constructor.instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isFatigue")) {
m.replace("$_ = false;");
logger.info("Set isFatigue to false in action constructor.");
return;
}
}
});
}
// - Allow all creatures to be displayed in the Mission Ruler - //
CtClass ctMissionManager = classPool.get("com.wurmonline.server.questions.MissionManager");
ctMissionManager.getDeclaredMethod("dropdownCreatureTemplates").instrument(new ExprEditor() {
@Override
public void edit(FieldAccess fieldAccess) throws CannotCompileException {
if (Objects.equals("baseCombatRating", fieldAccess.getFieldName()))
fieldAccess.replace("$_ = 1.0f;");
//logger.info("Instrumented Mission Ruler to display all creatures.");
}
});
Util.setReason("Fix Portal Issues.");
CtClass ctPortal = classPool.get("com.wurmonline.server.questions.PortalQuestion");
Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "willLeaveServer", "$_ = true;");
Util.setReason("Fix Portal Issues.");
Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "getKnowledge", "$_ = true;");
Util.setReason("Disable the minimum 0.01 damage on shield damage, allowing damage modifiers to rule.");
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
replace = "if($1 < 0.5f){"
+ " $_ = $proceed((float) 0, (float) $2);"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}";
Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace);
Util.setReason("Allow ghost creatures to breed (Chargers).");
Util.instrumentDeclared(thisClass, ctMethodsCreatures, "breed", "isGhost", "$_ = false;");
Util.setReason("Allow Life Transfer to stack with Rotting Touch.");
replace = MiscChanges.class.getName()+".doLifeTransfer(this.creature, attWeapon, defdamage, armourMod);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isWeaponCrush", replace);
/* - REMOVED: Added to core game -
Util.setReason("Fix dragon armour dropping on logout.");
Util.instrumentDeclared(thisClass, ctItem, "sleep", "isDragonArmour", "$_ = false;");
Util.setReason("Fix dragon armour dropping on logout.");
Util.instrumentDeclared(thisClass, ctItem, "sleepNonRecursive", "isDragonArmour", "$_ = false;");*/
// - Type creatures randomly in the wild - //
CtClass[] params1 = {
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 desc1 = Descriptor.ofMethod(ctCreature, params1);
replace = "$10 = "+MiscChanges.class.getName()+".newCreatureType($1, $10);";
Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc1, replace);
// - Send rumour messages to discord - //
Util.setReason("Send rumour messages to Discord.");
replace = MiscChanges.class.getName()+".sendRumour(toReturn);"
+ "$proceed($$);";
Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc1, "broadCastSafe", replace);
// - Allow custom creatures to be given special names when bred - //
replace = "$_ = "+MiscChanges.class.getName()+".shouldBreedName(this);";
Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "isHorse", replace);
/*ctCreature.getDeclaredMethod("checkPregnancy").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isHorse")) {
m.replace("$_ = mod.sin.wyvern.MiscChanges.shouldBreedName(this);");
return;
}
}
});*/
// - Auto-Genesis a creature born on enchanted grass - //
Util.setReason("Auto-Genesis a creature born on enchanted grass");
replace = MiscChanges.class.getName()+".checkEnchantedBreed(newCreature);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "saveCreatureName", replace);
/*ctCreature.getDeclaredMethod("checkPregnancy").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("saveCreatureName")) {
m.replace("mod.sin.wyvern.MiscChanges.checkEnchantedBreed(newCreature);"
+ "$_ = $proceed($$);");
return;
}
}
});*/
// - Allow statuettes to be used for casting even when not silver/gold - //
String desc2 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{});
Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc2, "return this.template.holyItem;");
//ctItem.getMethod("isHolyItem", desc2).setBody("return this.template.holyItem;");
// - Allow GM's to bypass the 5 second emote sound limit. - //
replace = "if(this.getPower() > 0){"
+ " return true;"
+ "}";
Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace);
/*ctPlayer.getDeclaredMethod("mayEmote").insertBefore(""
+ "if(this.getPower() > 0){"
+ " return true;"
+ "}");*/
// - Allow archery against ghost targets - //
CtClass ctArchery = classPool.get("com.wurmonline.server.combat.Archery");
CtMethod[] archeryAttacks = ctArchery.getDeclaredMethods("attack");
for(CtMethod method : archeryAttacks){
method.instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("isGhost")) {
m.replace("$_ = false;");
logger.info("Enabled archery against ghost targets in archery attack method.");
return;
}
}
});
}
// - Prevent archery altogether against certain creatures - //
CtClass[] params3 = {
ctCreature,
ctCreature,
ctItem,
CtClass.floatType,
ctAction
};
String desc3 = Descriptor.ofMethod(CtClass.booleanType, params3);
replace = "if("+MethodsBestiary.class.getName()+".isArcheryImmune($1, $2)){"
+ " return true;"
+ "}";
Util.insertBeforeDescribed(thisClass, ctArchery, "attack", desc3, replace);
// - Make creatures wander slightly if they are shot from afar by an arrow - //
CtClass ctArrows = classPool.get("com.wurmonline.server.combat.Arrows");
replace = "if(!defender.isPathing()){"
+ " defender.startPathing(com.wurmonline.server.Server.rand.nextInt(100));"
+ "}"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctArrows, "addToHitCreature", "addAttacker", replace);
Util.setReason("Broadcast death tabs to GL-Freedom.");
Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", MiscChanges.class.getName()+".broadCastDeaths($1, $2);");
//ctPlayers.getDeclaredMethod("broadCastDeathInfo").insertBefore("mod.sin.wyvern.MiscChanges.broadCastDeaths($1, $2);");
// - Reduce meditation cooldowns - //
CtClass ctCultist = classPool.get("com.wurmonline.server.players.Cultist");
replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*8)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace);
//ctCultist.getDeclaredMethod("mayRefresh").setBody("return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 28800000;");
replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace);
//ctCultist.getDeclaredMethod("mayEnchantNature").setBody("return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;");
replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace);
//ctCultist.getDeclaredMethod("mayStartLoveEffect").setBody("return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 14400000;");
replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace);
//ctCultist.getDeclaredMethod("mayStartDoubleWarDamage").setBody("return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > 21600000;");
replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace);
//ctCultist.getDeclaredMethod("mayStartDoubleStructDamage").setBody("return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > 14400000;");
replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*6)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace);
//ctCultist.getDeclaredMethod("mayStartFearEffect").setBody("return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 21600000;");
replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace);
//ctCultist.getDeclaredMethod("mayStartNoElementalDamage").setBody("return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > 21600000;");
replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";";
Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace);
//ctCultist.getDeclaredMethod("maySpawnVolcano").setBody("return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;");
replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace);
//ctCultist.getDeclaredMethod("mayStartIgnoreTraps").setBody("return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > 14400000;");
replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*4)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace);
//ctCultist.getDeclaredMethod("mayCreatureInfo").setBody("return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 14400000;");
replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";";
Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace);
//ctCultist.getDeclaredMethod("mayInfoLocal").setBody("return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 14400000;");
Util.setReason("Adjust weapon damage type based on the potion/salve applied.");
replace = "int wt = mod.sin.wyvern.MiscChanges.getWeaponType($1);"
+ "if(wt != -1){"
+ " type = wt;"
+ " return wt;"
+ "}";
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace);
Util.setReason("Attempt to prevent libila from losing faith when crossing servers.");
CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection");
ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() {
@Override
public void edit(FieldAccess fieldAccess) throws CannotCompileException {
if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())){
fieldAccess.replace("$_ = false;");
logger.info("Instrumented PVPSERVER = false for Libila faith transfers.");
}
}
});
ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() {
@Override
public void edit(FieldAccess fieldAccess) throws CannotCompileException {
if (Objects.equals("HOMESERVER", fieldAccess.getFieldName())){
fieldAccess.replace("$_ = false;");
logger.info("Instrumented HOMESERVER = false for Libila faith transfers.");
}
}
});
Util.setReason("Increase food affinity to give 30% increased skillgain instead of 10%.");
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
CtClass[] params4 = {
CtClass.doubleType,
CtClass.booleanType,
CtClass.floatType,
CtClass.booleanType,
CtClass.doubleType
};
String desc4 = Descriptor.ofMethod(CtClass.voidType, params4);
replace = "int timedAffinity = (com.wurmonline.server.skills.AffinitiesTimed.isTimedAffinity(pid, this.getNumber()) ? 2 : 0);"
+ "advanceMultiplicator *= (double)(1.0f + (float)timedAffinity * 0.1f);"
+ "$_ = $proceed($$);";
Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc4, "hasSleepBonus", replace);
Util.setReason("Double the rate at which charcoal piles produce items.");
CtClass[] params5 = {
CtClass.booleanType,
CtClass.booleanType,
CtClass.longType
};
String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5);
replace = "this.createDaleItems();"
+ "decayed = this.setDamage(this.damage + 1.0f * this.getDamageModifier());"
+ "$_ = $proceed($$);";
Util.instrumentDescribed(thisClass, ctItem, "poll", desc5, "createDaleItems", replace);
Util.setReason("Allow traders to display more than 9 items of a single type.");
CtClass ctTradeHandler = classPool.get("com.wurmonline.server.creatures.TradeHandler");
ctTradeHandler.getDeclaredMethod("addItemsToTrade").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if(m.getMethodName().equals("size") && m.getLineNumber() > 200){ // I don't think the line number check matters, but I'm leaving it here anyway.
m.replace("$_ = 1;");
logger.info("Instrumented size for trades to allow traders to show more than 9 items at a time.");
}
}
});
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 = "$_ = "+MiscChanges.class.getName()+".getNewVillageTiles(vill.getNumTiles());";
Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "getNumTiles", replace);
Util.setReason("Adjust value for certain items.");
replace = "int newVal = "+MiscChanges.class.getName()+".getNewValue(this);"
+ "if(newVal > 0){"
+ " return newVal;"
+ "}";
Util.insertBeforeDeclared(thisClass, ctItem, "getValue", replace);
//Util.setReason("Fix Glimmersteel & Adamantine veins from being depleted rapidly.");
CtClass ctCaveWallBehaviour = classPool.get("com.wurmonline.server.behaviours.CaveWallBehaviour");
CtClass[] params6 = {
ctAction,
ctCreature,
ctItem,
CtClass.intType,
CtClass.intType,
CtClass.booleanType,
CtClass.intType,
CtClass.intType,
CtClass.intType,
CtClass.shortType,
CtClass.floatType
};
String desc6 = Descriptor.ofMethod(CtClass.booleanType, params6);
// [3/27] Removed: Merged to ServerTweaks.
/*replace = "resource = com.wurmonline.server.Server.getCaveResource(tilex, tiley);"
+ "if (resource == 65535) {"
+ " resource = com.wurmonline.server.Server.rand.nextInt(10000);"
+ "}"
+ "if (resource > 1000 && (itemTemplateCreated == 693 || itemTemplateCreated == 697)) {"
+ " resource = com.wurmonline.server.Server.rand.nextInt(1000);"
+ "}"
+ "$_ = $proceed($$);";
Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc6, "getDifficultyForTile", replace);*/
Util.setReason("Allow players to mine directly to BSB's in vehicles.");
replace = "$_ = null;"
+ MiscChanges.class.getName()+".miningHook(performer, newItem);";
Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc6, "putItemInfrontof", replace);
// -- Identify players making over 10 commands per second and causing the server log message -- //
CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator");
replace = "$_ = $proceed($$);"
+ "if(this.player != null){"
+ " logger.info(\"Potential player macro: \"+this.player.getName()+\" [\"+this.commandsThisSecond+\" commands]\");"
+ "}";
Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_ITEM_CREATION_LIST", "log", replace);
Util.setReason("Allow ghost creatures to drop corpses.");
replace = "if("+MiscChanges.class.getName()+".isGhostCorpse(this)){"
+ " $_ = false;"
+ "}else{"
+ " $_ = $proceed($$);"
+ "}";
Util.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace);
Util.setReason("Set custom corpse sizes.");
replace = "$_ = $proceed($$);"
+ "if("+MiscChanges.class.getName()+".hasCustomCorpseSize(this)){"
+ " "+MiscChanges.class.getName()+".setCorpseSizes(this, corpse);"
+ "}";
Util.instrumentDeclared(thisClass, ctCreature, "die", "addItem", replace);
Util.setReason("Fix permissions in structures so players cannot cast spells unless they have enter permission.");
CtClass ctStructure = classPool.get("com.wurmonline.server.structures.Structure");
replace = "if(com.wurmonline.server.behaviours.Actions.isActionDietySpell(action)){"
+ " return this.mayPass(performer);"
+ "}"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctStructure, "isActionAllowed", "isActionImproveOrRepair", replace);
//1f+0.5f*(1f-Math.pow(2, -Math.pow((eff-1f), pow1)/pow2))
Util.setReason("Fix 100+ quality or power making certain interaction broken.");
replace = "{"
+ "double pow1 = 1.0;"
+ "double pow2 = 3.0;"
+ "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.setReason("Fix Oakshell glance rates from going above 100% when cast power is above 100.");
replace = "if(defender.getBonusForSpellEffect((byte)22) >= 0.0f){"
+ " evasionChance = Math.min(0.4f, evasionChance);"
+ "}"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isTowerBasher", replace);*/
/*Util.setReason("Ensure players always deal a wound and are not limited by 'does no real damage' messages.");
replace = MiscChanges.class.getName()+".setDefDamage(this.creature, defdamage);"
+ "defdamage = 99999d;"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isTowerBasher", replace);
replace = "defdamage = "+MiscChanges.class.getName()+".getDefDamage(this.creature);"
+ "$_ = $proceed($$);";
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getBattle", replace);*/
} catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) {
throw new HookException((Throwable)e);
}
}
}

View File

@@ -0,0 +1,92 @@
package mod.sin.wyvern;
import java.util.ArrayList;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modsupport.actions.ModActions;
import com.wurmonline.server.Items;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.zones.VolaTile;
import com.wurmonline.server.zones.Zones;
import mod.sin.actions.items.EternalReservoirCheckFuelAction;
import mod.sin.actions.items.EternalReservoirRefuelAction;
import mod.sin.actions.items.SoulstealAction;
import mod.sin.items.EternalReservoir;
public class Soulstealing {
public static final Logger logger = Logger.getLogger(Soulstealing.class.getName());
public static ArrayList<Item> soulForges = new ArrayList<Item>();
public static void pollSoulForge(Item soulForge){
int tilex = soulForge.getTileX();
int tiley = soulForge.getTileY();
int range = (int) (soulForge.getCurrentQualityLevel()/10f);
int fuel = soulForge.getData1();
logger.info("Polling eternal reservoir at ("+tilex+", "+tiley+") [range "+range+"] <fuel "+fuel+">");
if(fuel > 15){
int sx = Zones.safeTileX(tilex - range);
int sy = Zones.safeTileY(tiley - range);
int ex = Zones.safeTileX(tilex + range);
int ey = Zones.safeTileY(tiley + range);
int x, y;
for (x = sx; x <= ex; ++x) {
for (y = sy; y <= ey; ++y) {
VolaTile t = Zones.getTileOrNull(x, y, soulForge.isOnSurface());
if (t == null){
continue;
}
Creature[] crets2 = t.getCreatures();
for (Creature lCret : crets2) {
if(lCret.isBranded() && lCret.isCarnivore()){
int hunger = lCret.getStatus().getHunger();
if(hunger > 10000 && fuel > 50){
logger.info("Detected branded carnivore "+lCret.getName()+" at "+lCret.getTileX()+", "+lCret.getTileY()+" with hunger "+hunger);
lCret.getStatus().modifyHunger(-10000, 1);
Server.getInstance().broadCastAction("The "+lCret.getName()+" is visited by an ethereal creature, and seems less hungry.", lCret, 10);
fuel -= 50;
}
}
}
Item[] items = t.getItems();
for(Item item : items){
if(item.isForgeOrOven()){
if(item.isOnFire()){
if(item.getTemperature() < 20000 && fuel > 15){
logger.info("Found lit container "+item.getName()+" at "+item.getTileX()+", "+item.getTileY()+" with temperature "+item.getTemperature());
item.setTemperature((short) (item.getTemperature()+10000));
Server.getInstance().broadCastMessage("The "+item.getName()+" is visited by an ethereal creature, and is refueled.", item.getTileX(), item.getTileY(), item.isOnSurface(), 10);
fuel -= 15;
}
}
}
}
}
}
soulForge.setData1(fuel);
}else{
logger.info("Eternal Reservoir is low on fuel, skipping the poll.");
}
}
public static void pollSoulForges(){
logger.info("Polling eternal reservoirs...");
for(Item item : Items.getAllItems()){
if(item.getTemplateId() == EternalReservoir.templateId){
if(!soulForges.contains(item)){
logger.info("Found eternal reservoir that was not in the list, adding it now...");
soulForges.add(item);
} // Need to check for culling after, don't know how
}
}
for(Item soulForge : soulForges){
pollSoulForge(soulForge);
}
}
public static void registerActions(){
ModActions.registerAction(new EternalReservoirCheckFuelAction());
ModActions.registerAction(new EternalReservoirRefuelAction());
ModActions.registerAction(new SoulstealAction());
}
}

View File

@@ -0,0 +1,382 @@
package mod.sin.wyvern;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Server;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateCreator;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
import com.wurmonline.server.creatures.CreatureTemplateIds;
import com.wurmonline.server.creatures.NoSuchCreatureTemplateException;
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 javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import mod.sin.items.AffinityOrb;
public class TreasureChests {
public static void doItemSpawn(Item inventory, int[] templateTypes, float startQl, float qlValRange, int maxNums) {
/*if (item.getOwnerId() != -10) {
return;
}*/
/*Item[] currentItems = item.getAllItems(true);
boolean[] hasTypes = new boolean[templateTypes.length];
block2 : for (Item it : currentItems) {
for (int x = 0; x < templateTypes.length; ++x) {
if (templateTypes[x] != it.getTemplateId()) continue;
hasTypes[x] = true;
continue block2;
}
}
for (int x = 0; x < hasTypes.length; ++x) {*/
for (int x = 0; x < templateTypes.length; ++x){
//if (hasTypes[x]) continue; // Disabled so it doesn't mess with my things
for (int nums = 0; nums < maxNums; ++nums) {
try{
byte rrarity;
int templateType = templateTypes[x];
/*if (onGround) {
ItemFactory.createItem(templateType, startQl + Server.rand.nextFloat() * qlValRange, item.getPosX() + 0.3f, item.getPosY() + 0.3f, 65.0f, item.isOnSurface(), (byte) 0, -10, "");
continue;
}*/
boolean isBoneCollar = templateType == 867;
rrarity = (byte) (Server.rand.nextInt(100) == 0 || isBoneCollar ? 1 : 0);
if (rrarity > 0) {
rrarity = (byte) (Server.rand.nextInt(100) == 0 && isBoneCollar ? 2 : 1);
}
if (rrarity > 1) {
rrarity = (byte) (Server.rand.nextInt(100) == 0 && isBoneCollar ? 3 : 2);
}
float newql = startQl + Server.rand.nextFloat() * qlValRange;
Item toInsert = ItemFactory.createItem(templateType, newql, rrarity, "");
if (templateType == ItemList.statueHota){
toInsert.setAuxData((byte)Server.rand.nextInt(10));
toInsert.setWeight(50000, true);
}
if (templateType == ItemList.eggLarge) {
toInsert.setData1(CreatureTemplateCreator.getRandomDragonOrDrakeId());
}
if (templateType == ItemList.drakeHide) {
int colorId = CreatureTemplateCreator.getRandomDrakeId();
toInsert.setData1(colorId);
CreatureTemplate cTemplate = CreatureTemplateFactory.getInstance().getTemplate(colorId);
String creatureName = cTemplate.getName().toLowerCase();
if (!toInsert.getName().contains(creatureName)){
toInsert.setName(creatureName.toLowerCase() + " " + toInsert.getTemplate().getName());
}
toInsert.setWeight(50+Server.rand.nextInt(100), true);
}
if (templateType == ItemList.dragonScale) {
int[] dragonIds = new int[]{CreatureTemplateIds.DRAGON_BLACK_CID, CreatureTemplateIds.DRAGON_BLUE_CID, CreatureTemplateIds.DRAGON_GREEN_CID,
CreatureTemplateIds.DRAGON_RED_CID, CreatureTemplateIds.DRAGON_WHITE_CID};
int colorId = dragonIds[Server.rand.nextInt(dragonIds.length)];
toInsert.setData1(colorId);
CreatureTemplate cTemplate = CreatureTemplateFactory.getInstance().getTemplate(colorId);
String creatureName = cTemplate.getName().toLowerCase();
if (!toInsert.getName().contains(creatureName)){
toInsert.setName(creatureName.toLowerCase() + " " + toInsert.getTemplate().getName());
}
toInsert.setWeight(100+Server.rand.nextInt(150), true);
} // if
if (templateType == ItemList.riftCrystal || templateType == ItemList.riftWood || templateType == ItemList.riftStone) {
toInsert.setHasNoDecay(true);
} // if
inventory.insertItem(toInsert, true);
continue;
} catch (NoSuchTemplateException | FailedException | NoSuchCreatureTemplateException e) {
e.printStackTrace();
}
}
}
}
public static void newFillTreasureChest(Item item, int auxdata) {
// AuxData = random value 0-99
// 0-59 = rare, 60-89 = supreme, 90-99 = fantastic
int[] normalGems = new int[]{ItemList.emerald, ItemList.ruby, ItemList.opal, ItemList.diamond, ItemList.sapphire};
int[] starGems = new int[]{375, 377, 379, 381, 383};
int[] lumps = new int[]{44, 45, 46, 47, 48, 49, 205, 220, 221, 223, 694, 698, 837};
int[] potions = new int[]{871, 874, 875, 876, 877, 878, 879, 881, 883};
/*int[] usefulItems = {ItemList.axeSmall, ItemList.shieldMedium, ItemList.hatchet, ItemList.knifeCarving,
ItemList.pickAxe, ItemList.swordLong, ItemList.saw, ItemList.shovel, ItemList.rake, ItemList.hammerMetal,
ItemList.hammerWood, ItemList.anvilSmall, ItemList.cheeseDrill, ItemList.swordShort, ItemList.swordTwoHander,
ItemList.shieldSmallWood, ItemList.shieldSmallMetal, ItemList.shieldMediumWood, ItemList.shieldLargeWood,
ItemList.shieldLargeMetal, ItemList.axeHuge, ItemList.axeMedium, ItemList.knifeButchering,
ItemList.fishingRodIronHook, ItemList.stoneChisel, ItemList.leatherGlove, ItemList.leatherJacket,
ItemList.leatherBoot, ItemList.leatherSleeve, ItemList.leatherCap, ItemList.leatherHose, ItemList.clothGlove,
ItemList.clothShirt, ItemList.clothSleeve, ItemList.clothJacket, ItemList.clothHose, ItemList.clothShoes,
ItemList.studdedLeatherSleeve, ItemList.studdedLeatherBoot, ItemList.studdedLeatherCap,
ItemList.studdedLeatherHose, ItemList.studdedLeatherGlove, ItemList.studdedLeatherJacket,
ItemList.spindle, ItemList.flintSteel, ItemList.fishingRodWoodenHook, ItemList.stoneOven, ItemList.forge,
ItemList.anvilLarge, ItemList.cartSmall, ItemList.needleIron, ItemList.loom, ItemList.sickle, ItemList.scythe,
ItemList.gloveSteel, ItemList.chainBoot, ItemList.chainHose, ItemList.chainJacket, ItemList.chainSleeve,
ItemList.chainGlove, ItemList.chainCoif, ItemList.plateBoot, ItemList.plateHose, ItemList.plateJacket,
ItemList.plateSleeve, ItemList.plateGauntlet, ItemList.helmetBasinet, ItemList.helmetGreat, ItemList.helmetOpen,
ItemList.maulLarge, ItemList.maulSmall, ItemList.maulMedium, ItemList.whetStone, ItemList.pelt, ItemList.ropeTool,
ItemList.guardTower, ItemList.file, ItemList.awl, ItemList.leatherKnife, ItemList.scissors, ItemList.clayShaper,
ItemList.spatula, ItemList.bowShort, ItemList.bowMedium, ItemList.bowLong, ItemList.dragonLeatherSleeve,
ItemList.dragonLeatherBoot, ItemList.dragonLeatherCap, ItemList.dragonLeatherHose, ItemList.dragonLeatherGlove,
ItemList.dragonLeatherJacket, ItemList.dragonScaleBoot, ItemList.dragonScaleHose, ItemList.dragonScaleJacket,
ItemList.dragonScaleSleeve, ItemList.dragonScaleGauntlet, ItemList.boatRowing, ItemList.boatSailing,
ItemList.trowel, ItemList.statuetteFo, ItemList.statuetteLibila, ItemList.statuetteMagranon,
ItemList.statuetteVynora, ItemList.cartLarge, ItemList.cog, ItemList.corbita, ItemList.knarr, ItemList.caravel,
ItemList.saddle, ItemList.horseShoe, ItemList.meditationRugOne, ItemList.meditationRugTwo,
ItemList.meditationRugThree, ItemList.meditationRugFour, ItemList.groomingBrush, ItemList.spearLong,
ItemList.halberd, ItemList.spearSteel, ItemList.clothHood, ItemList.wagon, ItemList.boneCollar,
ItemList.spinningWheel, ItemList.smelter, ItemList.halterRope};*/
// Generate Rare Chest
if (auxdata < 60) {
if(item.getTemplateId() == ItemList.treasureChest){
item.setRarity((byte)1);
}
// Generate source, addy / glimmer, gem
int[] templateTypes = new int[]{ItemList.sourceCrystal, ItemList.adamantineBar,
ItemList.glimmerSteelBar, normalGems[Server.rand.nextInt(5)]};
doItemSpawn(item, templateTypes, 70.0f, 30.0f, 1);
// Generate seryll
if (Server.rand.nextBoolean()) {
doItemSpawn(item, new int[]{ItemList.seryllBar}, 60.0f, 20.0f, 1);
} // if
/*// Generate meal
if (Server.rand.nextBoolean()) {
this.doItemSpawn(item, new int[]{ItemList.steak}, (float)auxdata, 60.0f-(float)auxdata, 1, false);
} // if*/
// Generate random lump
if (Server.rand.nextBoolean()) {
doItemSpawn(item, new int[]{lumps[Server.rand.nextInt(13)]}, 80.0f, 20.0f, 1);
} // if
// Generate yellow potion
if (Server.rand.nextInt(5) == 0) {
doItemSpawn(item, new int[]{ItemList.potionIllusion}, 10.0f, 90.0f, 1);
} // if
// Generate fireworks
if (Server.rand.nextInt(20) == 0) {
doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 60.0f-(float)auxdata, 1);
} // if
// Generate affinity orb
if (Server.rand.nextInt(200-auxdata) == 0){
doItemSpawn(item, new int[]{22767}, 80.0f, 10.0f, 1); // Affinity Orb
}
/*// Generate random tool
if (Server.rand.nextInt(4) == 0) {
// generate random tool thingy
this.doItemSpawn(item, templateTypes6, 25.0f, 50.0f, 1, false);
} // if*/
/*// Generate source
if (Server.rand.nextInt(4) == 0) {
int[] templateTypes7 = new int[]{ItemList.skinWater};
// put 0.1-0.2kg of source in the water skin
this.doItemSpawn(item, templateTypes7, 25.0f, 50.0f, 1, false);
} // if*/
// Generate random potion
if (Server.rand.nextInt(10) == 0) {
doItemSpawn(item, new int[]{potions[Server.rand.nextInt(potions.length)]}, 50.0f, 50.0f, 1);
} // if
// Generate rift items
switch (Server.rand.nextInt(3)) {
case 0:
doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1);
break;
case 1:
doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1);
break;
case 2:
doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1);
break;
} // switch
// Generate Supreme Chest
} else if (auxdata < 90) {
if(item.getTemplateId() == ItemList.treasureChest){
item.setRarity((byte)2);
}
// Generate source, gem
int[] templateTypes = new int[]{ItemList.sourceCrystal, 374 + Server.rand.nextInt(10)};
// vessel the gem
doItemSpawn(item, templateTypes, 80.0f, 20.0f, 1);
// Spawn addy / glimmer
int[] templateTypes2 = new int[]{ItemList.adamantineBar, ItemList.glimmerSteelBar};
doItemSpawn(item, templateTypes2, 80.0f, 20.0f, 2 + Server.rand.nextInt(2));
// Generate seryll
int[] templateTypes3 = new int[]{ItemList.seryllBar};
doItemSpawn(item, templateTypes3, 80.0f, 20.0f, 1 + Server.rand.nextInt(3));
/*// Generate meal
if (Server.rand.nextBoolean()) {
this.doItemSpawn(item, new int[]{ItemList.steak}, (float)auxdata, 90.0f-(float)auxdata, 2, false);
} // if*/
// Generate fireworks
if (Server.rand.nextInt(10) == 0) {
doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 90.0f-(float)auxdata, 1);
} // if
// Generate affinity orb
if (Server.rand.nextInt(150-auxdata) == 0){
doItemSpawn(item, new int[]{22767}, 90.0f, 5.0f, 1); // Affinity Orb
}
/*// Generate source
if (Server.rand.nextBoolean()) {
int[] templateTypes6 = new int[]{ItemList.skinWater};
// put 0.2-0.3kg of source in the water skin
this.doItemSpawn(item, templateTypes6, 25.0f, 50.0f, 1, false);
} // if*/
// Generate dragon hide / scale
if (Server.rand.nextInt(10) == 0) {
doItemSpawn(item, new int[]{371 + (Server.rand.nextBoolean() ? 0 : 1)}, 80.0f, 20.0f, 1);
} // if
// Generate rift items
doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1);
doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1);
doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1);
// Generate Fantastic Chest
} else {
if(item.getTemplateId() == ItemList.treasureChest){
item.setRarity((byte)3);
}
// Generate source, gem
int[] templateTypes = new int[]{ItemList.sourceCrystal, starGems[Server.rand.nextInt(starGems.length)]};
doItemSpawn(item, templateTypes, 90.0f, 10.0f, 1);
// Generate addy / glimmer
int[] templateTypes2 = new int[]{ItemList.adamantineBar, ItemList.glimmerSteelBar};
doItemSpawn(item, templateTypes2, 80.0f, 20.0f, 3 + Server.rand.nextInt(3));
// Generate seryll
int[] templateTypes3 = new int[]{ItemList.seryllBar};
doItemSpawn(item, templateTypes3, 80.0f, 20.0f, 2 + Server.rand.nextInt(3));
// Generate affinity orb
if(Server.rand.nextBoolean()){
doItemSpawn(item, new int[]{AffinityOrb.templateId}, 99.0f, 1.0f, 1); // Affinity Orb
}
/*// Generate source
if (Server.rand.nextInt(4) != 0) {
int[] templateTypes5 = new int[]{ItemList.skinWater};
// put 0.5-0.7kg of source in the water skin
this.doItemSpawn(item, templateTypes5, 25.0f, 50.0f, 1, false);
} // if*/
// Generate fireworks
if (Server.rand.nextInt(5) == 0) {
doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 100.0f-(float)auxdata, 1);
} // if
/*
// Generate inscriber
if (Server.rand.nextInt(4) == 0) {
int[] templateTypes7 = new int[]{ItemList.inscriber};
this.doItemSpawn(item, templateTypes7, 99.0f, 1.0f, 1, false);
} // if
*/
// Generate dragon hide / scale
if (Server.rand.nextInt(10) == 0) {
doItemSpawn(item, new int[]{371 + (Server.rand.nextBoolean() ? 0 : 1)}, 90.0f, 10.0f, 1);
} // if
// Generate spyglass
if (Server.rand.nextInt(100) == 0) {
doItemSpawn(item, new int[]{ItemList.spyglass}, 99.0f, 1.0f, 1);
} // if
// Generate BoK
if (Server.rand.nextInt(100) == 0) {
doItemSpawn(item, new int[]{ItemList.bagKeeping}, 99.0f, 1.0f, 1);
} // if
// Generate rift items
doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3));
doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3));
doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3));
// Generate OP items
int rand = Server.rand.nextInt(500);
int[] fantasticLoot = {};
int amount = 1;
if(rand < 249){
fantasticLoot = new int[]{ItemList.drakeHide};
amount = 3;
// Three chunks of random color dragon scale.
} else if(rand < 349){
fantasticLoot = new int[]{ItemList.dragonScale};
amount = 3;
// Random hota statue.
} else if(rand < 414){
fantasticLoot = new int[]{ItemList.statueHota};
// Rare Bone & Helmet
} else if (rand < 464) {
fantasticLoot = new int[]{ItemList.boneCollar/*, Server.rand.nextBoolean() ? ItemList.helmetBasinet : ItemList.helmetGreat*/};
// 1/100 chance of supreme, 1/10,000 of fantastic
// Sorcery
} else if (rand < 490) {
fantasticLoot = new int[]{795 + Server.rand.nextInt(16)};
// Dragon Egg
} else {
fantasticLoot = new int[]{ItemList.eggLarge};
} // else
doItemSpawn(item, fantasticLoot, 99.0f, 1.0f, amount);
}
} // fillTreasureChest
public static void preInit() throws NotFoundException, CannotCompileException{
ClassPool classPool = HookManager.getInstance().getClassPool();
CtClass ctZone = classPool.get("com.wurmonline.server.zones.Zone");
CtMethod ctCreateTreasureChest = ctZone.getDeclaredMethod("createTreasureChest");
// Increase treasure chest AuxData by 2.
ctCreateTreasureChest.instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("setAuxData")) {
m.replace("$_ = $proceed((byte)(com.wurmonline.server.Server.rand.nextInt(100)));");
return;
}
}
});
// New treasure chest fill.
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
ctItem.getDeclaredMethod("fillTreasureChest").setBody("{"
+ " mod.sin.wyvern.TreasureChests.newFillTreasureChest(this, this.getAuxData());"
+ " logger.info(\"Spawned treasure chest level \"+this.getAuxData()+\" at \"+(this.getPosX()/4)+\", \"+(this.getPosY()/4));"
+ "}");
// Add an Affinity Orb to the chest.
/*ctItem.getDeclaredMethod("fillTreasureChest").insertAfter(""
+ "if(this.getAuxData() >= 8){"
+ " int[] templateTypes8 = new int[]{22767};"
+ " this.spawnItemSpawn(templateTypes8, 99.0f, 1.0f, 1, false);"
+ "}"
+ "logger.info(\"Spawned treasure chest level \"+this.getAuxData()+\" at \"+(this.getPosX()/4)+\", \"+(this.getPosY()/4));");*/
}
}

View File

@@ -0,0 +1,322 @@
package mod.sin.wyvern;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
import org.gotti.wurmunlimited.modloader.interfaces.Configurable;
import org.gotti.wurmunlimited.modloader.interfaces.Initable;
import org.gotti.wurmunlimited.modloader.interfaces.ItemTemplatesCreatedListener;
import org.gotti.wurmunlimited.modloader.interfaces.PreInitable;
import org.gotti.wurmunlimited.modloader.interfaces.ServerPollListener;
import org.gotti.wurmunlimited.modloader.interfaces.ServerStartedListener;
import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod;
import org.gotti.wurmunlimited.modsupport.actions.ModActions;
import org.gotti.wurmunlimited.modsupport.creatures.ModCreatures;
import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviours;
import com.wurmonline.server.TimeConstants;
import com.wurmonline.server.deities.Deities;
import com.wurmonline.server.deities.Deity;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.players.Player;
import com.wurmonline.server.skills.SkillList;
import com.wurmonline.server.skills.SkillSystem;
import com.wurmonline.server.skills.SkillTemplate;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import mod.sin.actions.*;
import mod.sin.creatures.*;
import mod.sin.creatures.titans.*;
import mod.sin.wyvern.arena.Arena;
import mod.sin.wyvern.arena.SupplyDepots;
import mod.sin.wyvern.bestiary.MethodsBestiary;
import mod.sin.wyvern.mastercraft.Mastercraft;
public class WyvernMods
implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener {
private static Logger logger = Logger.getLogger(WyvernMods.class.getName());
public static boolean espCounter = false;
public static boolean enableDepots = false;
boolean bDebug = false;
public static boolean customCommandHandler(ByteBuffer byteBuffer, Player player) throws UnsupportedEncodingException{
byte[] tempStringArr = new byte[byteBuffer.get() & 255];
byteBuffer.get(tempStringArr);
String message = new String(tempStringArr, "UTF-8");
tempStringArr = new byte[byteBuffer.get() & 255];
byteBuffer.get(tempStringArr);
//String title = new String(tempStringArr, "UTF-8");
if(player.mayMute() && message.startsWith("!")){
logger.info("Player "+player.getName()+" used custom WyvernMods command: "+message);
if(message.startsWith("!toggleESP") && player.getPower() >= 5){
espCounter = !espCounter;
player.getCommunicator().sendSafeServerMessage("ESP counter for this server is now = "+espCounter);
}else if(message.startsWith("!toggleDepots") && player.getPower() >= 5){
enableDepots = !enableDepots;
player.getCommunicator().sendSafeServerMessage("Arena depots for this server is now = "+enableDepots);
}else{
player.getCommunicator().sendSafeServerMessage("Custom command not found: "+message);
}
return true;
}
return false;
}
public void configure(Properties properties) {
this.bDebug = Boolean.parseBoolean(properties.getProperty("debug", Boolean.toString(this.bDebug)));
try {
String logsPath = Paths.get("mods", new String[0]) + "/logs/";
File newDirectory = new File(logsPath);
if (!newDirectory.exists()) {
newDirectory.mkdirs();
}
FileHandler fh = new FileHandler(String.valueOf(String.valueOf(logsPath)) + this.getClass().getSimpleName() + ".log", 10240000, 200, true);
if (this.bDebug) {
fh.setLevel(Level.INFO);
} else {
fh.setLevel(Level.WARNING);
}
fh.setFormatter(new SimpleFormatter());
logger.addHandler(fh);
}
catch (IOException ie) {
System.err.println(String.valueOf(this.getClass().getName()) + ": Unable to add file handler to logger");
}
//this.logger.log(Level.INFO, "Property: " + this.somevalue);
this.Debug("Debugging messages are enabled.");
}
private void Debug(String x) {
if (this.bDebug) {
System.out.println(String.valueOf(this.getClass().getSimpleName()) + ": " + x);
System.out.flush();
logger.log(Level.INFO, x);
}
}
public void preInit() {
logger.info("Pre-Initializing.");
try {
ModActions.init();
//Bounty.preInit(this);
TreasureChests.preInit();
MiscChanges.preInit();
Arena.preInit();
AntiCheat.preInit();
Mastercraft.preInit();
Mastercraft.addNewTitles();
SupplyDepots.preInit();
ClassPool classPool = HookManager.getInstance().getClassPool();
// - Enable custom command handler - //
CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator");
ctCommunicator.getDeclaredMethod("reallyHandle").instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("reallyHandle_CMD_MESSAGE")) {
m.replace("java.nio.ByteBuffer tempBuffer = $1.duplicate();"
+ "if(!mod.sin.wyvern.WyvernMods.customCommandHandler($1, this.player)){"
+ " $_ = $proceed(tempBuffer);"
+ "}");
return;
}
}
});
} catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) {
throw new HookException((Throwable)e);
}
}
@Override
public void init() {
logger.info("Initializing.");
ModCreatures.init();
ModVehicleBehaviours.init();
// Vanilla:
logger.info("Registering Vanilla creature changes.");
ModCreatures.addCreature(new Bison());
// Epic:
logger.info("Registering Epic creatures.");
ModCreatures.addCreature(new LavaFiend());
ModCreatures.addCreature(new SolDemon());
ModCreatures.addCreature(new Worg());
// Wyverns:
ModCreatures.addCreature(new WyvernBlack());
ModCreatures.addCreature(new WyvernGreen());
ModCreatures.addCreature(new WyvernRed());
ModCreatures.addCreature(new WyvernWhite());
// Flavor Mobs:
ModCreatures.addCreature(new Avenger());
ModCreatures.addCreature(new Charger());
ModCreatures.addCreature(new ForestSpider());
ModCreatures.addCreature(new Giant());
ModCreatures.addCreature(new HornedPony());
ModCreatures.addCreature(new LargeBoar());
ModCreatures.addCreature(new SpiritTroll());
// Bosses:
logger.info("Registering Custom Boss creatures.");
ModCreatures.addCreature(new Reaper());
ModCreatures.addCreature(new SpectralDrake());
// Uniques:
ModCreatures.addCreature(new Facebreyker());
// Titans:
ModCreatures.addCreature(new Ifrit());
ModCreatures.addCreature(new Lilith());
// Titan Spawns:
ModCreatures.addCreature(new IfritFiend());
ModCreatures.addCreature(new IfritSpider());
ModCreatures.addCreature(new LilithWraith());
ModCreatures.addCreature(new LilithZombie());
// NPC's
logger.info("Registering Custom NPC creatures.");
ModCreatures.addCreature(new RobZombie());
ModCreatures.addCreature(new MacroSlayer());
Bounty.init();
Mastercraft.changeExistingTitles();
}
@Override
public void onItemTemplatesCreated() {
logger.info("Creating Item Mod items.");
ItemMod.createItems();
logger.info("Creating Cache items.");
Caches.createItems();
try {
logger.info("Editing existing item templates.");
ItemMod.modifyItems();
logger.info("Registering permissions hook for custom items.");
ItemMod.registerPermissionsHook();
} catch (NoSuchTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
@Override
public void onServerStarted() {
try {
logger.info("Registering Item Mod creation entries.");
ItemMod.initCreationEntries();
logger.info("Registering Item Mod actions.");
ItemMod.registerActions();
logger.info("Registering Cache actions.");
Caches.registerActions();
logger.info("Registering Soulstealer actions.");
Soulstealing.registerActions();
logger.info("Registering Custom actions.");
ModActions.registerAction(new UnequipAllAction());
ModActions.registerAction(new ReceiveMailAction());
logger.info("Registering Arena actions.");
//ModActions.registerAction(new VillageTeleportAction()); // [3/28/18] Disabled - Highway Portals added instead.
ModActions.registerAction(new ArenaTeleportAction());
ModActions.registerAction(new ArenaEscapeAction());
logger.info("Setting custom creature corpse models.");
MethodsBestiary.setTemplateVariables();
if(Deities.getDeity(101) != null){ // Edit Breyk player god
Deity breyk = Deities.getDeity(101);
// Add some defining affinities
breyk.repairer = true;
breyk.learner = true;
breyk.deathProtector = true;
breyk.befriendCreature = true;
// Remove some affinities
breyk.warrior = false;
breyk.healer = false;
breyk.clayAffinity = false;
}
if(Deities.getDeity(102) != null){ // Edit Cyberhusky player god
Deity cyberhusky = Deities.getDeity(102);
// Add some defining affinities
cyberhusky.hateGod = true;
cyberhusky.allowsButchering = true;
cyberhusky.warrior = true;
// Remove some affinities
cyberhusky.woodAffinity = false;
cyberhusky.befriendCreature = false;
}
//espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default.
//espCounter = false;
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();
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
}
public static long lastSecondPolled = 0;
public static long lastPolledTitanSpawn = 0;
public static final long pollTitanSpawnTime = TimeConstants.MINUTE_MILLIS*10;
public static long lastPolledTitans = 0;
public static final long pollTitanTime = TimeConstants.SECOND_MILLIS;
public static long lastPolledDepots = 0;
public static final long pollDepotTime = TimeConstants.MINUTE_MILLIS;
public static long lastPolledEternalReservoirs = 0;
public static final long pollEternalReservoirTime = TimeConstants.MINUTE_MILLIS*10;
@Override
public void onServerPoll() {
if((lastSecondPolled + TimeConstants.SECOND_MILLIS) < System.currentTimeMillis()){
if(lastPolledDepots + pollDepotTime < System.currentTimeMillis()){
SupplyDepots.pollDepotSpawn();
lastPolledDepots += pollDepotTime;
}
if(lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){
Arena.pollTitanSpawn();
lastPolledTitanSpawn += pollTitanSpawnTime;
}
if(lastPolledTitans + pollTitanTime < System.currentTimeMillis()){
Arena.pollTitans();
lastPolledTitans += pollTitanTime;
}
if(lastPolledEternalReservoirs + pollEternalReservoirTime < System.currentTimeMillis()){
Soulstealing.pollSoulForges();
lastPolledEternalReservoirs += pollEternalReservoirTime;
}
// Update counter
if(lastSecondPolled + TimeConstants.SECOND_MILLIS*10 > System.currentTimeMillis()){
lastSecondPolled += TimeConstants.SECOND_MILLIS;
}else{
logger.info("Time between last poll was greater than 10 seconds. Resetting all poll counters...");
lastSecondPolled = System.currentTimeMillis();
lastPolledTitanSpawn = System.currentTimeMillis();
lastPolledTitans = System.currentTimeMillis();
lastPolledDepots = System.currentTimeMillis();
lastPolledEternalReservoirs = System.currentTimeMillis();
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
package mod.sin.wyvern.arena;
import java.util.ArrayList;
import java.util.logging.Logger;
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.MiscChanges;
import mod.sin.wyvern.WyvernMods;
import mod.sin.wyvern.util.ItemUtil;
public class SupplyDepots {
private static Logger logger = Logger.getLogger(SupplyDepots.class.getName());
public static ArrayList<Item> depots = new ArrayList<Item>();
public static Creature host = null;
public static final long depotRespawnTime = TimeConstants.HOUR_MILLIS*7L;
public static long lastSpawnedDepot = 0;
public static void sendDepotEffect(Player player, Item depot){
player.getCommunicator().sendAddEffect(depot.getWurmId(), (byte) 25, depot.getPosX(), depot.getPosY(), depot.getPosZ(), (byte) 0);
}
public static void sendDepotEffectsToPlayer(Player player){
logger.info("Sending depot effects to player "+player.getName());
for(Item depot : depots){
sendDepotEffect(player, depot);
}
}
public static void sendDepotEffectsToPlayers(Item depot){
for(Player p : Players.getInstance().getPlayers()){
sendDepotEffect(p, depot);
}
}
public static void removeDepotEffect(Item depot){
for(Player player : Players.getInstance().getPlayers()){
player.getCommunicator().sendRemoveEffect(depot.getWurmId());
}
}
public static void removeSupplyDepot(Item depot){
if(depots.contains(depot)){
depots.remove(depot);
}
removeDepotEffect(depot);
}
private static boolean isSupplyDepot(Item item){
return item.getTemplateId() == ArenaSupplyDepot.templateId;
}
public static void pollDepotSpawn(){
if(!Servers.localServer.PVPSERVER && !WyvernMods.enableDepots){
return;
}
for(int i = 0; i < depots.size(); i++){
Item depot = depots.get(i);
if(!Items.exists(depot)){
logger.info("Supply depot was destroyed, removing from list.");
depots.remove(depot);
removeDepotEffect(depot);
}
}
for(Item item : Items.getAllItems()){
if(isSupplyDepot(item) && !depots.contains(item)){
logger.info("Found existing supply depots, adding to list and sending data to players.");
depots.add(item);
sendDepotEffectsToPlayers(item);
}
}
if(depots.isEmpty()){
if(host == null){
ArrayList<Creature> uniques = new ArrayList<Creature>();
for(Creature c : Creatures.getInstance().getCreatures()){
if(c.isUnique()){
uniques.add(c);
}
}
if(uniques.size() > 0){
host = uniques.get(Server.rand.nextInt(uniques.size()));
MiscChanges.sendImportantMessage(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){
logger.info("No Depots were found, and the timer has expired. Spawning a new one.");
boolean spawned = false;
int i = 0;
while(!spawned && i < 20){
float worldSizeX = Zones.worldTileSizeX;
float worldSizeY = Zones.worldTileSizeY;
float minX = worldSizeX*0.25f;
float minY = worldSizeY*0.25f;
int tilex = (int) (minX+(minX*2*Server.rand.nextFloat()));
int tiley = (int) (minY+(minY*2*Server.rand.nextFloat()));
int tile = Server.surfaceMesh.getTile(tilex, tiley);
try {
if(Tiles.decodeHeight((int)tile) > 0){
Item depot = ItemFactory.createItem(ArenaSupplyDepot.templateId, 50+Server.rand.nextFloat()*40f, (float)(tilex << 2) + 2.0f, (float)(tiley << 2) + 2.0f, Server.rand.nextFloat() * 360.0f, true, (byte) 0, -10, null);
depots.add(depot);
sendDepotEffectsToPlayers(depot);
if(host != null){
MiscChanges.sendImportantMessage(host, "A new depot has appeared on the Arena!", 255, 128, 0);
}
logger.info("New supply depot being placed at "+tilex+", "+tiley);
spawned = true;
host = null;
lastSpawnedDepot = System.currentTimeMillis();
}else{
logger.info("Position "+tilex+", "+tiley+" was invalid, attempting another spawn...");
i++;
}
} catch (Exception e) {
logger.severe("Failed to create Arena Depot.");
e.printStackTrace();
}
}
if(i >= 20){
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 minutesLeft = timeleft/TimeConstants.MINUTE_MILLIS;
if(minutesLeft > 0){
if(minutesLeft == 1){
MiscChanges.sendImportantMessage(host, "Come quickly! The next Arena depot will appear in 5 minutes!", 255, 128, 0);
}else if(minutesLeft == 19){
MiscChanges.sendImportantMessage(host, "Best start heading over, the next Arena depot will appear in 20 minutes!", 255, 128, 0);
}else if(minutesLeft == 59){
MiscChanges.sendImportantMessage(host, "Heads up! The next Arena depot will appear in 60 minutes!", 255, 128, 0);
}
}
}
}
}
public static long lastAttemptedDepotCapture = 0;
public static final long captureMessageInterval = TimeConstants.MINUTE_MILLIS*3L;
public static void maybeBroadcastOpen(Creature performer){
if(System.currentTimeMillis() > lastAttemptedDepotCapture + captureMessageInterval){
MiscChanges.sendImportantMessage(performer, performer.getName()+" is begnning to capture an Arena depot!", 255, 128, 0);
lastAttemptedDepotCapture = System.currentTimeMillis();
}
}
public static void giveCacheReward(Creature performer){
Item inv = performer.getInventory();
Item enchantOrb = ItemUtil.createEnchantOrb(130f+(Server.rand.nextFloat()*20));
inv.insertItem(enchantOrb);
try {
// Add a special caches as a reward.
int[] cacheIds = {
ArmourCache.templateId,
ArtifactCache.templateId,
CrystalCache.templateId,
DragonCache.templateId,
GemCache.templateId,
MoonCache.templateId,
RiftCache.templateId,
TreasureMapCache.templateId
};
int i = 1+Server.rand.nextInt(3); // 2-4 caches extra.
while(i >= 0){
Item cache = ItemFactory.createItem(cacheIds[Server.rand.nextInt(cacheIds.length)], 80f+(20f*Server.rand.nextFloat()), "");
inv.insertItem(cache, true);
i--;
}
if(Server.rand.nextFloat()*100f <= 10f){
Item hotaStatue = ItemFactory.createItem(ItemList.statueHota, 80f+(20f*Server.rand.nextFloat()), "");
hotaStatue.setAuxData((byte)Server.rand.nextInt(10));
hotaStatue.setWeight(50000, true);
inv.insertItem(hotaStatue, true);
}
if(Server.rand.nextFloat()*100f <= 3f){
Item sorcery = ItemFactory.createItem(ItemUtil.sorceryIds[Server.rand.nextInt(ItemUtil.sorceryIds.length)], 80f+(20f*Server.rand.nextFloat()), "");
sorcery.setAuxData((byte)2);
inv.insertItem(sorcery, true);
}
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
}
public static void preInit(){
try{
ClassPool classPool = HookManager.getInstance().getClassPool();
// - 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.arena.SupplyDepots.sendDepotEffectsToPlayer($1);");
}catch (CannotCompileException | NotFoundException e) {
throw new HookException((Throwable)e);
}
}
}

View File

@@ -0,0 +1,470 @@
package mod.sin.wyvern.bestiary;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Server;
import com.wurmonline.server.combat.Archery;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.CreatureStatus;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
import com.wurmonline.server.creatures.NoSuchCreatureTemplateException;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemFactory;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.items.ItemSpellEffects;
import com.wurmonline.server.items.Materials;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.skills.SkillList;
import com.wurmonline.server.skills.Skills;
import com.wurmonline.server.skills.SkillsFactory;
import com.wurmonline.server.spells.SpellEffect;
import com.wurmonline.shared.constants.Enchants;
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 mod.sin.wyvern.arena.Arena;
public class MethodsBestiary {
protected static Logger logger = Logger.getLogger(MethodsBestiary.class.getName());
public static boolean checkColorTemplate(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return true;
}else if(templateId == ForestSpider.templateId){
return true;
}else if(templateId == Avenger.templateId){
return true;
}else if(templateId == HornedPony.templateId){
return true;
}else if(templateId == LilithZombie.templateId){
return true;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return false;
}
public static byte getCreatureColorRed(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == ForestSpider.templateId){
return (byte)0;
}else if(templateId == Avenger.templateId){
return (byte)70;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
public static byte getCreatureColorGreen(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return (byte)0;
}else if(templateId == Avenger.templateId){
return (byte)70;
}else if(templateId == HornedPony.templateId){
return (byte)10;
}else if(templateId == LilithZombie.templateId){
return (byte)0;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
public static byte getCreatureColorBlue(CreatureTemplate template){
try {
int templateId = template.getTemplateId();
if(templateId == Lilith.templateId){
return (byte)0;
}else if(templateId == ForestSpider.templateId){
return (byte)0;
}else if(templateId == HornedPony.templateId){
return (byte)70;
}else if(templateId == LilithZombie.templateId){
return (byte)0;
}
} catch (IllegalArgumentException | ClassCastException e) {
e.printStackTrace();
}
return (byte)127;
}
public static float getAdjustedSizeMod(CreatureStatus status){
try {
float floatToRet = 1.0f;
Creature statusHolder = ReflectionUtil.getPrivateField(status, ReflectionUtil.getField(status.getClass(), "statusHolder"));
byte modtype = ReflectionUtil.getPrivateField(status, ReflectionUtil.getField(status.getClass(), "modtype"));
float ageSizeModifier = ReflectionUtil.callPrivateMethod(status, ReflectionUtil.getMethod(status.getClass(), "getAgeSizeModifier"));
if ((!statusHolder.isVehicle() || statusHolder.isDragon()) && modtype > 0) {
switch (modtype) {
case 3: {
floatToRet = 1.4f;
break;
}
case 4: {
floatToRet = 2.0f;
break;
}
case 6: {
floatToRet = 2.0f;
break;
}
case 7: {
floatToRet = 0.8f;
break;
}
case 8: {
floatToRet = 0.9f;
break;
}
case 9: {
floatToRet = 1.5f;
break;
}
case 10: {
floatToRet = 1.3f;
break;
}
case 99: {
floatToRet = 3.0f;
break;
}
default: {
//return floatToRet * ageSizeModifier;
}
}
}
int templateId = statusHolder.getTemplate().getTemplateId();
if(templateId == Lilith.templateId){
floatToRet *= 0.45f;
}else if(templateId == Ifrit.templateId){
floatToRet *= 0.15f; // The base model is way too big. I'm tilted.
}else if(templateId == WyvernBlack.templateId){
floatToRet *= 0.6f;
}else if(templateId == WyvernGreen.templateId){
floatToRet *= 0.6f;
}else if(templateId == WyvernRed.templateId){
floatToRet *= 0.6f;
}else if(templateId == WyvernWhite.templateId){
floatToRet *= 0.6f;
}else if(templateId == MacroSlayer.templateId){
floatToRet *= 1.5f;
}else if(templateId == ForestSpider.templateId){
floatToRet *= 0.4f;
}else if(templateId == Avenger.templateId){
floatToRet *= 0.35f;
}else if(templateId == LargeBoar.templateId){
floatToRet *= 1.8f;
}else if(templateId == SpiritTroll.templateId){
floatToRet *= 1.2f;
}else if(templateId == Giant.templateId){
floatToRet *= 0.75f;
}else if(templateId == LilithZombie.templateId){
floatToRet *= 0.75f;
}else if(templateId == Charger.templateId){
floatToRet *= 1.5f;
}
return floatToRet * ageSizeModifier;
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
return 1.0f;
}
public static Item createNewTitanWeapon(String name, int[] templates){
try {
Item titanWeapon;
int templateId = templates[Server.rand.nextInt(templates.length)];
titanWeapon = ItemFactory.createItem(templateId, 90f+(Server.rand.nextFloat()*5f), Materials.MATERIAL_ADAMANTINE, Server.rand.nextBoolean() ? (byte) 2 : (byte) 3, name);
ItemSpellEffects effs = titanWeapon.getSpellEffects();
if(effs == null){
effs = new ItemSpellEffects(titanWeapon.getWurmId());
}
if(templateId == MaartensMight.templateId){
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_NIMBLENESS, 250, 20000000));
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), (byte) 111, 200, 20000000)); // Phasing
}else if(templateId == RaffehsRage.templateId){
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_FLAMING_AURA, 150, 20000000));
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_FROSTBRAND, 150, 20000000));
}else if(templateId == VindictivesVengeance.templateId){
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_BLESSINGDARK, 300, 20000000));
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_NIMBLENESS, 200, 20000000));
}else if(templateId == WilhelmsWrath.templateId){
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_ROTTING_TOUCH, 300, 20000000));
effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_BLOODTHIRST, 100, 20000000));
}
if(titanWeapon != null){
return titanWeapon;
}
} catch (FailedException | NoSuchTemplateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static boolean isArcheryImmune(Creature performer, Creature defender){
if(Arena.isTitan(defender) || Arena.isTitanMinion(defender)){
performer.getCommunicator().sendCombatNormalMessage("You cannot archer "+defender.getName()+", as it is protected by a Titan.");
return true;
}
String message = "The "+defender.getName()+" would be unaffected by your arrows.";
boolean immune = false;
Item arrow = Archery.getArrow(performer);
if(arrow == null){ // Copied directly from the attack() method in Archery.
performer.getCommunicator().sendCombatNormalMessage("You have no arrows left to shoot!");
return true;
}
//int defenderTemplateId = defender.getTemplate().getTemplateId();
if(defender.isRegenerating() && arrow.getTemplateId() == ItemList.arrowShaft){
message = "The "+defender.getName()+" would be unaffected by the "+arrow.getName()+".";
immune = true;
}else if(defender.getTemplate().isNotRebirthable()){
immune = true;
}else if(defender.isUnique()){
immune = true;
}
if(immune){
performer.getCommunicator().sendCombatNormalMessage(message);
}
return immune;
}
public static void modifyNewCreature(Creature creature){
try{
if(Arena.isTitan(creature)){
Arena.addTitan(creature);
MiscChanges.sendGlobalFreedomChat(creature, "The titan "+creature.getName()+" has stepped into the mortal realm. Challenge "+creature.getHimHerItString()+" in the Arena if you dare.", 255, 105, 180);
if(creature.getTemplate().getTemplateId() == Lilith.templateId){
Item titanWeapon = createNewTitanWeapon(creature.getName(), new int[]{VindictivesVengeance.templateId, WilhelmsWrath.templateId});
creature.getInventory().insertItem(titanWeapon);
}else if(creature.getTemplate().getTemplateId() == Ifrit.templateId){
Item titanWeapon = createNewTitanWeapon(creature.getName(), new int[]{MaartensMight.templateId, RaffehsRage.templateId});
creature.getInventory().insertItem(titanWeapon);
}
}else if(creature.getTemplate().getTemplateId() == Facebreyker.templateId){
Item club = ItemFactory.createItem(Club.templateId, 80f+(Server.rand.nextFloat()*15f), Server.rand.nextBoolean() ? Materials.MATERIAL_GLIMMERSTEEL : Materials.MATERIAL_ADAMANTINE, Server.rand.nextBoolean() ? (byte) 1 : (byte) 2, "Facebreyker");
creature.getInventory().insertItem(club);
}
}catch(Exception e){
e.printStackTrace();
}
}
private static void setNaturalArmour(int templateId, float value){
try{
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
if(template != null){
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "naturalArmour"), value);
}
} catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
private static void setCorpseModel(int templateId, String model){
try{
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
if(template != null){
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "corpsename"), model);
}
} catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
private static void setGhost(int templateId){
try{
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
if(template != null){
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "ghost"), true);
}
} catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
private static void setGrazer(int templateId){
try{
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
if(template != null){
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "grazer"), true);
}
} catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
e.printStackTrace();
}
}
private static void setWorgFields(int templateId) {
try {
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId);
if(template != null) {
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isVehicle"), true);
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "dominatable"), true);
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isHorse"), true);
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isDetectInvis"), false);
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "monster"), true);
Skills skills = SkillsFactory.createSkills("Worg");
skills.learnTemp(SkillList.BODY_STRENGTH, 40.0f);
skills.learnTemp(SkillList.BODY_CONTROL, 25.0f);
skills.learnTemp(SkillList.BODY_STAMINA, 35.0f);
skills.learnTemp(SkillList.MIND_LOGICAL, 10.0f);
skills.learnTemp(SkillList.MIND_SPEED, 15.0f);
skills.learnTemp(SkillList.SOUL_STRENGTH, 20.0f);
skills.learnTemp(SkillList.SOUL_DEPTH, 12.0f);
skills.learnTemp(SkillList.WEAPONLESS_FIGHTING, 50.0f);
ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "skills"), skills);
} // if
} catch (Exception e) {
e.printStackTrace();
} // catch
} // setWorgFields
public static void setTemplateVariables(){
// Set corpse models
setCorpseModel(Avenger.templateId, "fogspider.");
setCorpseModel(SpiritTroll.templateId, "fogspider.");
setCorpseModel(SpectralDrake.templateId, "fogspider.");
/*CreatureTemplate spectralDrake = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId);
if(spectralDrake != null){
ReflectionUtil.setPrivateField(spectralDrake, ReflectionUtil.getField(spectralDrake.getClass(), "corpsename"), "fogspider.");
}*/
setCorpseModel(WyvernBlack.templateId, "blackdragonhatchling.");
/*CreatureTemplate blackWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernBlack.templateId);
if(blackWyvern != null){
ReflectionUtil.setPrivateField(blackWyvern, ReflectionUtil.getField(blackWyvern.getClass(), "corpsename"), "blackdragonhatchling.");
}*/
setCorpseModel(WyvernGreen.templateId, "greendragonhatchling.");
/*CreatureTemplate greenWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernGreen.templateId);
if(greenWyvern != null){
ReflectionUtil.setPrivateField(greenWyvern, ReflectionUtil.getField(greenWyvern.getClass(), "corpsename"), "greendragonhatchling.");
}*/
setCorpseModel(WyvernRed.templateId, "reddragonhatchling.");
/*CreatureTemplate redWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernRed.templateId);
if(redWyvern != null){
ReflectionUtil.setPrivateField(redWyvern, ReflectionUtil.getField(redWyvern.getClass(), "corpsename"), "reddragonhatchling.");
}*/
setCorpseModel(WyvernWhite.templateId, "whitedragonhatchling.");
/*CreatureTemplate whiteWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernWhite.templateId);
if(whiteWyvern != null){
ReflectionUtil.setPrivateField(whiteWyvern, ReflectionUtil.getField(whiteWyvern.getClass(), "corpsename"), "whitedragonhatchling.");
}*/
setCorpseModel(Facebreyker.templateId, "riftogre.");
/*CreatureTemplate facebreyker = CreatureTemplateFactory.getInstance().getTemplate(Facebreyker.templateId);
if(facebreyker != null){
ReflectionUtil.setPrivateField(facebreyker, ReflectionUtil.getField(facebreyker.getClass(), "corpsename"), "riftogre.");
}*/
setCorpseModel(ForestSpider.templateId, "hugespider.");
/*CreatureTemplate forestSpider = CreatureTemplateFactory.getInstance().getTemplate(ForestSpider.templateId);
if(forestSpider != null){
ReflectionUtil.setPrivateField(forestSpider, ReflectionUtil.getField(forestSpider.getClass(), "corpsename"), "hugespider.");
}*/
setCorpseModel(Giant.templateId, "forestgiant.");
/*CreatureTemplate giant = CreatureTemplateFactory.getInstance().getTemplate(Giant.templateId);
if(giant != null){
ReflectionUtil.setPrivateField(giant, ReflectionUtil.getField(giant.getClass(), "corpsename"), "forestgiant.");
}*/
setCorpseModel(LargeBoar.templateId, "wildboar.");
/*CreatureTemplate largeBoar = CreatureTemplateFactory.getInstance().getTemplate(LargeBoar.templateId);
if(largeBoar != null){
ReflectionUtil.setPrivateField(largeBoar, ReflectionUtil.getField(largeBoar.getClass(), "corpsename"), "wildboar.");
}*/
setCorpseModel(HornedPony.templateId, "unicorn.");
/*CreatureTemplate hornedPony = CreatureTemplateFactory.getInstance().getTemplate(HornedPony.templateId);
if(hornedPony != null){
ReflectionUtil.setPrivateField(hornedPony, ReflectionUtil.getField(hornedPony.getClass(), "corpsename"), "unicorn.");
}*/
setCorpseModel(IfritSpider.templateId, "lavaspider.");
/*CreatureTemplate ifritSpider = CreatureTemplateFactory.getInstance().getTemplate(IfritSpider.templateId);
if(ifritSpider != null){
ReflectionUtil.setPrivateField(ifritSpider, ReflectionUtil.getField(ifritSpider.getClass(), "corpsename"), "lavaspider.");
}*/
setCorpseModel(IfritFiend.templateId, "lavafiend.");
/*CreatureTemplate ifritFiend = CreatureTemplateFactory.getInstance().getTemplate(IfritFiend.templateId);
if(ifritFiend != null){
ReflectionUtil.setPrivateField(ifritFiend, ReflectionUtil.getField(ifritFiend.getClass(), "corpsename"), "lavafiend.");
}*/
// Also apply the ghost modifier
setGhost(SpiritTroll.templateId);
setGhost(Avenger.templateId);
setGhost(LilithWraith.templateId);
setGhost(Charger.templateId);
/*CreatureTemplate spiritTroll = CreatureTemplateFactory.getInstance().getTemplate(SpiritTroll.templateId);
if(spiritTroll != null){
ReflectionUtil.setPrivateField(spiritTroll, ReflectionUtil.getField(spiritTroll.getClass(), "ghost"), true);
}
CreatureTemplate avenger = CreatureTemplateFactory.getInstance().getTemplate(Avenger.templateId);
if(avenger != null){
ReflectionUtil.setPrivateField(avenger, ReflectionUtil.getField(avenger.getClass(), "ghost"), true);
}
CreatureTemplate lilithWight = CreatureTemplateFactory.getInstance().getTemplate(LilithWraith.templateId);
if(lilithWight != null){
ReflectionUtil.setPrivateField(lilithWight, ReflectionUtil.getField(lilithWight.getClass(), "ghost"), true);
}
CreatureTemplate charger = CreatureTemplateFactory.getInstance().getTemplate(Charger.templateId);
if(charger != null){
ReflectionUtil.setPrivateField(charger, ReflectionUtil.getField(charger.getClass(), "ghost"), true);
}*/
// Dragon natural armour increases:
setNaturalArmour(CreatureTemplate.DRAGON_BLUE_CID, 0.04f);
/*CreatureTemplate dragonBlue = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_BLUE_CID);
ReflectionUtil.setPrivateField(dragonBlue, ReflectionUtil.getField(dragonBlue.getClass(), "naturalArmour"), 0.05f);*/
setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.04f);
/*CreatureTemplate dragonGreen = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_WHITE_CID);
ReflectionUtil.setPrivateField(dragonGreen, ReflectionUtil.getField(dragonGreen.getClass(), "naturalArmour"), 0.05f);*/
setNaturalArmour(CreatureTemplate.DRAGON_BLACK_CID, 0.055f);
/*CreatureTemplate dragonBlack = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_BLACK_CID);
ReflectionUtil.setPrivateField(dragonBlack, ReflectionUtil.getField(dragonBlack.getClass(), "naturalArmour"), 0.07f);*/
setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.04f);
/*CreatureTemplate dragonWhite = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_WHITE_CID);
ReflectionUtil.setPrivateField(dragonWhite, ReflectionUtil.getField(dragonWhite.getClass(), "naturalArmour"), 0.05f);*/
// Drake natural armour increases:
setNaturalArmour(CreatureTemplate.DRAKE_RED_CID, 0.075f);
/*CreatureTemplate drakeRed = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_RED_CID);
ReflectionUtil.setPrivateField(drakeRed, ReflectionUtil.getField(drakeRed.getClass(), "naturalArmour"), 0.085f);*/
setNaturalArmour(CreatureTemplate.DRAKE_BLUE_CID, 0.075f);
/*CreatureTemplate drakeBlue = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_BLUE_CID);
ReflectionUtil.setPrivateField(drakeBlue, ReflectionUtil.getField(drakeBlue.getClass(), "naturalArmour"), 0.085f);*/
setNaturalArmour(CreatureTemplate.DRAKE_WHITE_CID, 0.085f);
/*CreatureTemplate drakeWhite = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_WHITE_CID);
ReflectionUtil.setPrivateField(drakeWhite, ReflectionUtil.getField(drakeWhite.getClass(), "naturalArmour"), 0.1f);*/
setNaturalArmour(CreatureTemplate.DRAKE_GREEN_CID, 0.075f);
/*CreatureTemplate drakeGreen = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_GREEN_CID);
ReflectionUtil.setPrivateField(drakeGreen, ReflectionUtil.getField(drakeGreen.getClass(), "naturalArmour"), 0.085f);*/
setNaturalArmour(CreatureTemplate.DRAKE_BLACK_CID, 0.065f);
/*CreatureTemplate drakeBlack = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_BLACK_CID);
ReflectionUtil.setPrivateField(drakeBlack, ReflectionUtil.getField(drakeBlack.getClass(), "naturalArmour"), 0.065f);*/
// Goblin leader natural armour increase:
setNaturalArmour(CreatureTemplate.GOBLIN_LEADER_CID, 0.075f);
/*CreatureTemplate goblinLeader = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.GOBLIN_LEADER_CID);
ReflectionUtil.setPrivateField(goblinLeader, ReflectionUtil.getField(goblinLeader.getClass(), "naturalArmour"), 0.085f);*/
// Set hens and roosters as grazers
setGrazer(CreatureTemplate.HEN_CID);
setGrazer(CreatureTemplate.CHICKEN_CID);
setGrazer(CreatureTemplate.ROOSTER_CID);
setGrazer(CreatureTemplate.PIG_CID);
// Set worg fields
setWorgFields(CreatureTemplate.WORG_CID);
}
}

View File

@@ -0,0 +1,572 @@
package mod.sin.wyvern.bounty;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Logger;
import com.wurmonline.mesh.Tiles;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.HistoryManager;
import com.wurmonline.server.Players;
import com.wurmonline.server.Server;
import com.wurmonline.server.Servers;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.creatures.CreatureTemplate;
import com.wurmonline.server.creatures.CreatureTemplateFactory;
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.ItemTemplate;
import com.wurmonline.server.items.ItemTemplateFactory;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.villages.Village;
import com.wurmonline.server.villages.Villages;
import mod.sin.armour.SpectralHide;
import mod.sin.creatures.Reaper;
import mod.sin.creatures.SpectralDrake;
import mod.sin.items.ChaosCrystal;
import mod.sin.items.EnchantersCrystal;
import mod.sin.items.FriyanTablet;
import mod.sin.wyvern.Bounty;
import mod.sin.wyvern.MiscChanges;
import mod.sin.wyvern.arena.Arena;
import mod.sin.wyvern.util.ItemUtil;
public class LootBounty {
public static final Logger logger = Logger.getLogger(LootBounty.class.getName());
protected static final Random random = new Random();
public static void displayLootAssistance(Creature mob){
if(Bounty.dealtDamage.containsKey(mob.getWurmId())){
logger.info("Found the damageDealt entry, parsing...");
ArrayList<String> names = new ArrayList<String>();
ArrayList<Double> damages = new ArrayList<Double>();
for(long creatureId : Bounty.dealtDamage.get(mob.getWurmId()).keySet()){
if(Players.getInstance().getPlayerOrNull(creatureId) != null){
names.add(Players.getInstance().getPlayerOrNull(creatureId).getName());
damages.add(Bounty.dealtDamage.get(mob.getWurmId()).get(creatureId));
}else{
if(Creatures.getInstance().getCreatureOrNull(creatureId) != null){
logger.info("Skipping creature "+Creatures.getInstance().getCreatureOrNull(creatureId).getName()+" in loot assistance.");
}
}
}
logger.info("Names have been added: "+names);
String strBuilder = "Loot Assistance <Damagers> ("+mob.getName()+"): ";
DecimalFormat formatter = new DecimalFormat("#,###,###");
while(names.size() > 0){
int index = Server.rand.nextInt(names.size());
strBuilder += names.get(index);
strBuilder += " ["+formatter.format(Math.round(damages.get(index)))+"]";
names.remove(index);
damages.remove(index);
if(names.size() > 0){
strBuilder += ", ";
}
}
MiscChanges.sendServerTabMessage(strBuilder, 0, 128, 255);
logger.info("Broadcast loot assistance message success [Damage].");
}else{
logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Damage].");
}
}
public static int doRollingCrystalReward(Creature mob, Item corpse, double cretStr, int templateId, int chance, double reductionPerRoll){
try {
double rollingCounter = cretStr;
int addedCrystals = 0;
/*if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well.
rollingCounter *= 3;
}else if(Servers.localServer.PVPSERVER){ // Arena gives double the amount of crystals.
rollingCounter *= 2;
}*/
while(rollingCounter > 0){
if(random.nextInt(chance+addedCrystals) == 0){ // Give a chance at a crystal, decreasing with the amount of crystals contained.
// The crystal quality is the cube root of the rolling counter, capped at 100 of course
Item chaosCrystal = ItemFactory.createItem(templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), "");
if(random.nextInt(40) == 0){
chaosCrystal.setRarity((byte) 1);
}else if(mob.isUnique() && random.nextInt(5) == 0){
if(random.nextInt(5) == 0){
chaosCrystal.setRarity((byte) 2);
}else{
chaosCrystal.setRarity((byte) 1);
}
}
corpse.insertItem(chaosCrystal);
addedCrystals++;
}
rollingCounter -= reductionPerRoll;
}
return addedCrystals;
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
return 0;
}
public static void blessWorldWithMoonVeins(Creature mob){
int i = 20;
while(i > 0){
int x = random.nextInt(Server.surfaceMesh.getSize());
int y = random.nextInt(Server.surfaceMesh.getSize());
short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y));
int type = Tiles.decodeType((int)Server.caveMesh.getTile(x, y));
if(height >= 100 && (type == Tiles.Tile.TILE_CAVE_WALL.id || type == Tiles.Tile.TILE_CAVE.id)){
Tiles.Tile tileType = random.nextBoolean() ? Tiles.Tile.TILE_CAVE_WALL_ORE_ADAMANTINE : Tiles.Tile.TILE_CAVE_WALL_ORE_GLIMMERSTEEL;
Server.caveMesh.setTile(x, y, Tiles.encode(Tiles.decodeHeight(Server.caveMesh.getTile(x, y)), tileType.id, Tiles.decodeData(Server.caveMesh.getTile(x, y))));
Players.getInstance().sendChangedTile(x, y, false, true);
Server.setCaveResource(x, y, 400+random.nextInt(600));
Village v = Villages.getVillage(x, y, true);
if (v == null) {
for (int vx = -50; vx < 50; vx += 5) {
for (int vy = -50; vy < 50 && (v = Villages.getVillage(x + vx, y + vy, true)) == null; vy += 5) {
}
}
}
if(v != null){
HistoryManager.addHistory(mob.getTemplate().getName(), "blesses the world with a "+tileType.getName()+" near "+v.getName()+"!");
}
logger.info("Placed a "+tileType.getName()+" at "+x+", "+y+" - "+height+" height");
i--;
}
}
Server.getInstance().broadCastAlert("The death of the "+mob.getTemplate().getName()+" has blessed the world with valuable ores!");
}
public static void spawnFriyanTablets(){
int i = 5+random.nextInt(5);
while(i > 0){
int x = random.nextInt(Server.surfaceMesh.getSize());
int y = random.nextInt(Server.surfaceMesh.getSize());
short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y));
if(height > 0 && height < 1000 && Creature.getTileSteepness(x, y, true)[1] < 30){
try {
ItemFactory.createItem(FriyanTablet.templateId, 80f+random.nextInt(20), (float)x*4, (float)y*4, random.nextFloat()*360f, true, (byte)0, -10, "Friyanouce");
logger.info("Created a Tablet of Friyan at "+x+", "+y+".");
} catch (NoSuchTemplateException | FailedException e) {
e.printStackTrace();
}
i--;
}
}
}
public static void handleDragonLoot(Creature mob, Item corpse){
try{
int mTemplate = mob.getTemplate().getTemplateId();
int lootTemplate = ItemList.drakeHide;
byte ctype = 0;
if(mTemplate == CreatureTemplateFactory.DRAGON_BLACK_CID || mTemplate == CreatureTemplateFactory.DRAGON_BLUE_CID || mTemplate == CreatureTemplateFactory.DRAGON_GREEN_CID
|| mTemplate == CreatureTemplateFactory.DRAGON_RED_CID || mTemplate == CreatureTemplateFactory.DRAGON_WHITE_CID){
//if(mTemplate == 16 || mTemplate == 89 || mTemplate == 91 || mTemplate == 90 || mTemplate == 92){
ctype = 99; // Champion creature type
lootTemplate = ItemList.dragonScale;
//lootTemplate = 372;
}else{
ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5);
}
float x = mob.getPosX();
float y = mob.getPosY();
// Spawn the spectral drake.
//logger.info("Spawning a spectral drake.");
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId); // Spectral Drake ID: 2147483646
Creature spectralDrake = Creature.doNew(template.getTemplateId(), true, x, y, random.nextFloat()*360.0f, mob.getLayer(),
template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150);
Server.getInstance().broadCastAction("The spirit of the "+mob.getTemplate().getName()+" is released into the world!", mob, 20);
Server.getInstance().broadCastAlert(spectralDrake.getName()+" is released from the soul of the "+mob.getTemplate().getName()+", seeking vengeance for its physical form!");
// Insert extra hide / scale
logger.info("Generating extra hide & scale to insert on the corpse of "+mob.getName()+".");
ItemTemplate itemTemplate = ItemTemplateFactory.getInstance().getTemplate(lootTemplate);
for(int i = 0; i < 2; i++){
Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), "");
String creatureName = mob.getTemplate().getName().toLowerCase();
if (!loot.getName().contains(creatureName)){
loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName());
}
loot.setData2(mTemplate);
int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1);
loot.setWeight((int)((weightGrams*0.1f)+(weightGrams*0.1f*random.nextFloat())), true);
corpse.insertItem(loot);
}
for(int i = 0; i < 4; i++){
Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), "");
String creatureName = mob.getTemplate().getName().toLowerCase();
if (!loot.getName().contains(creatureName)){
loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName());
}
loot.setData2(mTemplate);
int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1);
loot.setWeight((int)((weightGrams*0.05f)+(weightGrams*0.05f*random.nextFloat())), true);
spectralDrake.getInventory().insertItem(loot);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void handleChampionLoot(Item corpse){
try{
corpse.insertItem(ItemUtil.createRandomLootTool());
if(random.nextInt(100) < 75){
corpse.insertItem(ItemFactory.createItem((random.nextBoolean() ? 694 : 698), 30+(30*random.nextFloat()), ""));
}
if(random.nextInt(100) < 5){
//int[] maskTemplates = {973, 974, 975, 976, 977, 978, 1099};
int[] maskTemplates = {
ItemList.maskEnlightended,
ItemList.maskRavager,
ItemList.maskPale,
ItemList.maskShadow,
ItemList.maskChallenge,
ItemList.maskIsles,
ItemList.maskOfTheReturner
};
corpse.insertItem(ItemFactory.createItem(maskTemplates[random.nextInt(maskTemplates.length)], 90+(9*random.nextFloat()), ""));
}
if(random.nextInt(100) < 1){
Item bone = ItemFactory.createItem(867, 90+(10*random.nextFloat()), "");
bone.setRarity((byte)1);
if(random.nextInt(100) < 1){
bone.setRarity((byte)2);
}
corpse.insertItem(bone);
}
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
}
public static void checkLootTable(Creature mob, Item corpse){
double cretStr = Bounty.getCreatureStrength(mob);
int numCrystals = 0;
double crystalStr = cretStr;
if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well.
crystalStr *= 3;
}else if(Servers.localServer.PVPSERVER){ // Arena gives double the amount of crystals.
crystalStr *= 2.5;
}
// Award chaos crystals if the strength is high enough:
if(crystalStr > 3000){ // 30 copper
numCrystals += doRollingCrystalReward(mob, corpse, crystalStr, ChaosCrystal.templateId, 4, 5000);
/*double rollingCounter = cretStr;
int chance = 4;
int addedCrystals = 0;
if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well.
rollingCounter *= 3;
}else if(Servers.localServer.PVPSERVER){
rollingCounter *= 2;
}
while(rollingCounter > 0){
// For every 50,000 creature strength, give a 1/8 chance at a chaos crystal
if(random.nextInt(chance+addedCrystals) == 0){
// The crystal quality is the cube root of the rolling counter, capped at 100 of course
Item chaosCrystal = ItemFactory.createItem(ChaosCrystal.templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), "");
if(random.nextInt(40) == 0){
chaosCrystal.setRarity((byte) 1);
}else if(mob.isUnique() && random.nextInt(5) == 0){
if(random.nextInt(5) == 0){
chaosCrystal.setRarity((byte) 2);
}else{
chaosCrystal.setRarity((byte) 1);
}
}
corpse.insertItem(chaosCrystal);
addedCrystals++;
}
rollingCounter -= 5000;
}
if(addedCrystals > 0){
hasCrystals = true;
}*/
}
if(crystalStr > 10000){ // 1 silver
numCrystals += doRollingCrystalReward(mob, corpse, crystalStr, EnchantersCrystal.templateId, 5, 20000);
/*double rollingCounter = cretStr;
int chance = 5;
int addedCrystals = 0;
if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well.
rollingCounter *= 3;
}else if(Servers.localServer.PVPSERVER){
rollingCounter *= 2;
}
while(rollingCounter > 0){
// For every 200,000 creature strength, give a 1/8 chance at a enchanters crystal
if(random.nextInt(chance+addedCrystals) == 0){
// The crystal quality is the cube root of the rolling counter, capped at 100 of course
Item enchantersCrystal = ItemFactory.createItem(EnchantersCrystal.templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), "");
if(random.nextInt(40) == 0){
enchantersCrystal.setRarity((byte) 1);
}else if(mob.isUnique() && random.nextInt(5) == 0){
if(random.nextInt(5) == 0){
enchantersCrystal.setRarity((byte) 2);
}else{
enchantersCrystal.setRarity((byte) 1);
}
}
corpse.insertItem(enchantersCrystal);
addedCrystals++;
}
rollingCounter -= 20000;
}
if(addedCrystals > 0){
hasCrystals = true;
}*/
}
boolean sendLootHelp = false;
// Begin loot table drops
if(mob.getTemplate().getTemplateId() == Reaper.templateId){
Server.getInstance().broadCastNormal("The "+mob.getName()+" has been slain.");
sendLootHelp = true;
}else if(mob.getTemplate().getTemplateId() == SpectralDrake.templateId){
try{
logger.info("Generating spectral hide for the corpse of the "+mob.getName()+".");
for(int i = 0; i < 2; i++){
Item spectralHide = ItemFactory.createItem(SpectralHide.templateId, 50+(50*random.nextFloat()), "");
ItemTemplate itemTemplate = spectralHide.getTemplate();
int weightGrams = itemTemplate.getWeightGrams();
spectralHide.setWeight((int)((weightGrams*0.5f)+(weightGrams*0.5f*random.nextFloat())), true);
corpse.insertItem(spectralHide);
if(!mob.getStatus().isChampion()){
break;
}
}
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
Server.getInstance().broadCastNormal("The "+mob.getName()+" has been slain.");
sendLootHelp = true;
}else if(Arena.isTitan(mob)){
Server.getInstance().broadCastAlert("The Titan "+mob.getName()+" has been defeated!");
MiscChanges.sendGlobalFreedomChat(mob, "The Titan "+mob.getName()+" has been defeated!", 255, 105, 180);
MiscChanges.sendServerTabMessage("The Titan "+mob.getName()+" has been defeated!", 255, 105, 180);
Arena.removeTitan(mob);
sendLootHelp = true;
}
if(mob.getTemplate().getTemplateId() == CreatureTemplateFactory.GOBLIN_CID){
// Random lump of metal from goblins.
try{
int[] lumpIds = {
//44, 45, 46, 47, 48, 49, 205, 221, 223, 220
ItemList.adamantineBar,
ItemList.brassBar,
ItemList.bronzeBar,
ItemList.copperBar,
ItemList.glimmerSteelBar,
ItemList.goldBar,
ItemList.ironBar,
ItemList.leadBar,
ItemList.silverBar,
ItemList.steelBar,
ItemList.zincBar
};
Item randomLump = ItemFactory.createItem(lumpIds[random.nextInt(lumpIds.length)], 20+(60*random.nextFloat()), "");
corpse.insertItem(randomLump);
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
}
if(mob.isUnique()){
// Spawn random addy/glimmer veins throughout the world
blessWorldWithMoonVeins(mob);
/*int i = 20;
while(i > 0){
int x = random.nextInt(Server.surfaceMesh.getSize());
int y = random.nextInt(Server.surfaceMesh.getSize());
short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y));
int type = Tiles.decodeType((int)Server.caveMesh.getTile(x, y));
if(height >= 100 && (type == Tiles.Tile.TILE_CAVE_WALL.id || type == Tiles.Tile.TILE_CAVE.id)){
Tiles.Tile tileType = random.nextBoolean() ? Tiles.Tile.TILE_CAVE_WALL_ORE_ADAMANTINE : Tiles.Tile.TILE_CAVE_WALL_ORE_GLIMMERSTEEL;
Server.caveMesh.setTile(x, y, Tiles.encode(Tiles.decodeHeight(Server.caveMesh.getTile(x, y)), tileType.id, Tiles.decodeData(Server.caveMesh.getTile(x, y))));
Players.getInstance().sendChangedTile(x, y, false, true);
Server.setCaveResource(x, y, 400+random.nextInt(600));
Village v = Villages.getVillage(x, y, true);
if (v == null) {
for (int vx = -50; vx < 50; vx += 5) {
for (int vy = -50; vy < 50 && (v = Villages.getVillage(x + vx, y + vy, true)) == null; vy += 5) {
}
}
}
if(v != null){
HistoryManager.addHistory(mob.getTemplate().getName(), "blesses the world with a "+tileType.getName()+" near "+v.getName()+"!");
}
logger.info("Placed a "+tileType.getName()+" at "+x+", "+y+" - "+height+" height");
i--;
}
}
Server.getInstance().broadCastAlert("The death of the "+mob.getTemplate().getName()+" has blessed the world with valuable ores!");*/
// Spawn 5-10 friyan tablets throughout the world.
spawnFriyanTablets();
/*i = 5+random.nextInt(5);
while(i > 0){
int x = random.nextInt(Server.surfaceMesh.getSize());
int y = random.nextInt(Server.surfaceMesh.getSize());
short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y));
if(height > 0 && height < 1000 && Creature.getTileSteepness(x, y, true)[1] < 30){
ItemFactory.createItem(FriyanTablet.templateId, 80f+random.nextInt(20), (float)x*4, (float)y*4, random.nextFloat()*360f, true, (byte)0, -10, "Friyanouce");
logger.info("Created a Tablet of Friyan at "+x+", "+y+".");
i--;
}
}*/
// Spawn Spectral Drake
if (mob.isDragon()) { // Spawn the spectral drake and add extra hide/scale
handleDragonLoot(mob, corpse);
/*int mTemplate = mob.getTemplate().getTemplateId();
int lootTemplate = ItemList.drakeHide;
byte ctype = 0;
if(mTemplate == CreatureTemplateFactory.DRAGON_BLACK_CID || mTemplate == CreatureTemplateFactory.DRAGON_BLUE_CID || mTemplate == CreatureTemplateFactory.DRAGON_GREEN_CID
|| mTemplate == CreatureTemplateFactory.DRAGON_RED_CID || mTemplate == CreatureTemplateFactory.DRAGON_WHITE_CID){
//if(mTemplate == 16 || mTemplate == 89 || mTemplate == 91 || mTemplate == 90 || mTemplate == 92){
ctype = 99; // Champion creature type
lootTemplate = ItemList.dragonScale;
//lootTemplate = 372;
}else{
ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5);
}
float x = mob.getPosX();
float y = mob.getPosY();
// Spawn the spectral drake.
//logger.info("Spawning a spectral drake.");
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId); // Spectral Drake ID: 2147483646
Creature spectralDrake = Creature.doNew(template.getTemplateId(), true, x, y, random.nextFloat()*360.0f, mob.getLayer(),
template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150);
Server.getInstance().broadCastAction("The spirit of the "+mob.getTemplate().getName()+" is released into the world!", mob, 20);
Server.getInstance().broadCastAlert(spectralDrake.getName()+" is released from the soul of the "+mob.getTemplate().getName()+", seeking vengeance for its physical form!");
// Insert extra hide / scale
logger.info("Generating extra hide & scale to insert on the corpse of "+mob.getName()+".");
ItemTemplate itemTemplate = ItemTemplateFactory.getInstance().getTemplate(lootTemplate);
for(int i = 0; i < 2; i++){
Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), "");
String creatureName = mob.getTemplate().getName().toLowerCase();
if (!loot.getName().contains(creatureName)){
loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName());
}
loot.setData2(mTemplate);
int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1);
loot.setWeight((int)((weightGrams*0.1f)+(weightGrams*0.1f*random.nextFloat())), true);
corpse.insertItem(loot);
}
for(int i = 0; i < 4; i++){
Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), "");
String creatureName = mob.getTemplate().getName().toLowerCase();
if (!loot.getName().contains(creatureName)){
loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName());
}
loot.setData2(mTemplate);
int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1);
loot.setWeight((int)((weightGrams*0.05f)+(weightGrams*0.05f*random.nextFloat())), true);
spectralDrake.getInventory().insertItem(loot);
}*/
} else { // Spawn the reaper
try {
byte ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5);
CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(Reaper.templateId); // Reaper ID: 2147483647
Creature reaper = Creature.doNew(template.getTemplateId(), true, mob.getPosX(), mob.getPosY(), random.nextFloat()*360.0f, mob.getLayer(),
template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150);
Server.getInstance().broadCastAction("The death of the "+mob.getTemplate().getName()+" attracts a powerful being from below, seeking to claim it's soul.", mob, 20);
Server.getInstance().broadCastAlert(reaper.getName()+" is released from the underworld, seeking the soul of a powerful creature!");
} catch (Exception e) {
e.printStackTrace();
}
}
sendLootHelp = true;
}
if(mob.getStatus().isChampion()){
// Champion mob loot
handleChampionLoot(corpse);
/*corpse.insertItem(ItemUtil.createRandomLootTool());
if(random.nextInt(100) < 75){
corpse.insertItem(ItemFactory.createItem((random.nextBoolean() ? 694 : 698), 30+(30*random.nextFloat()), ""));
}
if(random.nextInt(100) < 5){
int[] maskTemplates = {973, 974, 975, 976, 977, 978, 1099};
corpse.insertItem(ItemFactory.createItem(maskTemplates[random.nextInt(maskTemplates.length)], 90+(9*random.nextFloat()), ""));
}
if(random.nextInt(100) < 1){
Item bone = ItemFactory.createItem(867, 90+(10*random.nextFloat()), "");
bone.setRarity((byte)1);
if(random.nextInt(100) < 1){
bone.setRarity((byte)2);
}
corpse.insertItem(bone);
}*/
}
if(sendLootHelp){
logger.info("Beginning loot assistance message generation...");
displayLootAssistance(mob);
/*ArrayList<String> atkNames = new ArrayList<String>();
Map<Long, Long> attackers = Bounty.getAttackers(mob);
if(attackers != null){
for(Long wid : attackers.keySet()){
Creature cret = Creatures.getInstance().getCreatureOrNull(wid);
if(cret != null && cret.isPlayer()){
atkNames.add(Players.getInstance().getPlayer(wid).getName());
}
}
if(atkNames.size() > 0){
String atkStrBuilder = "Loot Assistance <Attackers> ("+mob.getName()+"): ";
while(atkNames.size() > 0){
int index = Server.rand.nextInt(atkNames.size());
atkStrBuilder += atkNames.get(index);
atkNames.remove(index);
if(atkNames.size() > 0){
atkStrBuilder += ", ";
}
}
MiscChanges.sendServerTabMessage(atkStrBuilder, 0, 128, 255);
logger.info("Broadcast loot assistance message success [Attackers].");
}else{
logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Attackers].");
}
}else{
logger.warning("Attackers was null for creature "+mob.getName()+" [Attackers].");
}*/
/*if(Bounty.dealtDamage.containsKey(mob.getWurmId())){
logger.info("Found the damageDealt entry, parsing...");
ArrayList<String> names = new ArrayList<String>();
ArrayList<Double> damages = new ArrayList<Double>();
for(long creatureId : Bounty.dealtDamage.get(mob.getWurmId()).keySet()){
if(Players.getInstance().getPlayerOrNull(creatureId) != null){
names.add(Players.getInstance().getPlayerOrNull(creatureId).getName());
damages.add(Bounty.dealtDamage.get(mob.getWurmId()).get(creatureId));
}else{
if(Creatures.getInstance().getCreatureOrNull(creatureId) != null){
logger.info("Skipping creature "+Creatures.getInstance().getCreatureOrNull(creatureId).getName()+" in loot assistance.");
}
}
}
logger.info("Names have been added: "+names);
String strBuilder = "Loot Assistance <Damagers> ("+mob.getName()+"): ";
DecimalFormat formatter = new DecimalFormat("#,###,###");
while(names.size() > 0){
int index = Server.rand.nextInt(names.size());
strBuilder += names.get(index);
strBuilder += " ["+formatter.format(Math.round(damages.get(index)))+"]";
names.remove(index);
damages.remove(index);
if(names.size() > 0){
strBuilder += ", ";
}
}
MiscChanges.sendServerTabMessage(strBuilder, 0, 128, 255);
logger.info("Broadcast loot assistance message success [Damage].");
}else{
logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Damage].");
}*/
}
if(numCrystals > 0){
Server.getInstance().broadCastAction(mob.getName()+" had something of interest...", mob, 5);
}
}
}

View File

@@ -0,0 +1,221 @@
package mod.sin.wyvern.bounty;
import java.io.IOException;
import java.util.Map;
import java.util.Random;
import java.util.logging.Logger;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Servers;
import com.wurmonline.server.creatures.Creature;
import com.wurmonline.server.economy.Economy;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemFactory;
import com.wurmonline.server.items.ItemTemplate;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.players.Player;
import com.wurmonline.server.players.Titles.Title;
import com.wurmonline.server.skills.NoSuchSkillException;
import com.wurmonline.server.skills.SkillList;
import mod.sin.armour.SpectralHide;
import mod.sin.creatures.Reaper;
import mod.sin.creatures.SpectralDrake;
import mod.sin.items.AffinityOrb;
import mod.sin.wyvern.Bounty;
import mod.sin.wyvern.arena.Arena;
import mod.sin.wyvern.util.ItemUtil;
public class PlayerBounty {
public static final Logger logger = Logger.getLogger(PlayerBounty.class.getName());
protected static final Random random = new Random();
public static double getTypeBountyMod(Creature mob, String mobType){
if(!mob.isUnique()){
if (mobType.endsWith("fierce ")){
return 1.5;
}else if (mobType.endsWith("angry ")){
return 1.4;
}else if (mobType.endsWith("raging ")){
return 1.6;
}else if (mobType.endsWith("slow ")){
return 0.95;
}else if (mobType.endsWith("alert ")){
return 1.2;
}else if (mobType.endsWith("greenish ")){
return 1.7;
}else if (mobType.endsWith("lurking ")){
return 1.1;
}else if (mobType.endsWith("sly ")){
return 0.8;
}else if (mobType.endsWith("hardened ")){
return 1.3;
}else if (mobType.endsWith("scared ")){
return 0.85;
}else if (mobType.endsWith("diseased ")){
return 0.9;
}else if (mobType.endsWith("champion ")){
return 2.0;
}
}
return 1.0;
}
public static void rewardPowerfulLoot(Player player, Creature mob){
try{
// Affinity Orb:
Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f+(1f*random.nextFloat()), "");
player.getInventory().insertItem(affinityOrb);
// Enchant Orb:
float power;
if(mob.getStatus().isChampion()){
power = 100f+(random.nextFloat()*20f);
}else{
power = 90f+(random.nextFloat()*30f);
}
Item enchantOrb = ItemUtil.createEnchantOrb(power);
player.getInventory().insertItem(enchantOrb);
player.getCommunicator().sendSafeServerMessage("Libila takes the "+mob.getNameWithoutPrefixes()+"'s soul, but leaves something else behind...");
}catch (NoSuchTemplateException | FailedException e) {
e.printStackTrace();
}
}
public static void rewardSpectralLoot(Player player){
try{
double fightskill = player.getFightingSkill().getKnowledge();
Item spectralHide = ItemFactory.createItem(SpectralHide.templateId, 70+(30*random.nextFloat()), ""); // Spectral Hide ID: 22764
ItemTemplate itemTemplate = spectralHide.getTemplate();
int weightGrams = itemTemplate.getWeightGrams();
spectralHide.setWeight((int)((weightGrams*0.25f)+(weightGrams*0.25f*fightskill/100f*random.nextFloat())), true);
player.getInventory().insertItem(spectralHide);
String fightStrength = "strong";
if(fightskill >= 60){
fightStrength = "great";
}
if(fightskill >= 70){
fightStrength = "powerful";
}
if(fightskill >= 80){
fightStrength = "master";
}
if(fightskill >= 90){
fightStrength = "legendary";
}
player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly.");
player.addTitle(Title.getTitle(701));
}catch (NoSuchTemplateException | FailedException e) {
e.printStackTrace();
}
}
public static void checkPlayerReward(Player player, Creature mob){
try{
int mobTemplateId = mob.getTemplate().getTemplateId();
if(Bounty.dealtDamage.containsKey(mob.getWurmId()) && Bounty.dealtDamage.get(mob.getWurmId()).containsKey(player.getWurmId())){
// -- Damage Dealt Rewards -- //
if(mob.isUnique()){
// Treasure boxes awarded to players who deal damage:
Item treasureBox = ItemUtil.createTreasureBox();
if(treasureBox != null){
player.getInventory().insertItem(treasureBox);
}else{
logger.warning("Error: Treasure box was not created properly!");
}
}
if(Arena.isTitan(mob)){
player.addTitle(Title.getTitle(700));
}
double fightskill = player.getFightingSkill().getKnowledge();
if((mobTemplateId == Reaper.templateId || mobTemplateId == SpectralDrake.templateId) && fightskill >= 50){
rewardPowerfulLoot(player, mob); // Reward affinity orb and enchant orb:
if(mob.getTemplate().getTemplateId() == SpectralDrake.templateId){
rewardSpectralLoot(player); // Reward spectral hide for spectral drakes
}
return; // If the player receives powerful loot, break the method completely and skip bounty.
}
// -- End Damage Dealt Rewards -- //
}
String mobName = mob.getTemplate().getName().toLowerCase();
String mobType = mob.getPrefixes();
long iron;
double cretStr = Bounty.getCreatureStrength(mob);
if(Bounty.reward.containsKey(mobName)){
iron = Bounty.reward.get(mobName); // Prioritize hardcoded values in the Bounty.reward list first
}else{
iron = java.lang.Math.round(cretStr); // Calculate bounty from creature strength if they do not exist in the reward list.
}
if(Servers.localServer.PVPSERVER){
if(!mob.isUnique() && mob.getTemplate().getTemplateId() != SpectralDrake.templateId && mob.getTemplate().getTemplateId() != Reaper.templateId){
iron *= 2.5d;
}
try {
player.getSkills().getSkill(SkillList.MEDITATING).skillCheck(10, 0, false, 1); // Meditation skill gain
float faithMod = 1-(player.getFaith()/200f);
player.modifyFaith((((float)cretStr)*faithMod)/200000f); // Faith skill gain
} catch (NoSuchSkillException e) {
e.printStackTrace();
}
}
// Multiply bounty based on type
iron *= getTypeBountyMod(mob, mobType);
/*if(!mob.isUnique()){
if (mobType.endsWith("fierce ")){
iron *= 1.5;
}else if (mobType.endsWith("angry ")){
iron *= 1.4;
}else if (mobType.endsWith("raging ")){
iron *= 1.6;
}else if (mobType.endsWith("slow ")){
iron *= 0.95;
}else if (mobType.endsWith("alert ")){
iron *= 1.2;
}else if (mobType.endsWith("greenish ")){
iron *= 1.7;
}else if (mobType.endsWith("lurking ")){
iron *= 1.1;
}else if (mobType.endsWith("sly ")){
iron *= 0.8;
}else if (mobType.endsWith("hardened ")){
iron *= 1.3;
}else if (mobType.endsWith("scared ")){
iron *= 0.85;
}else if (mobType.endsWith("diseased ")){
iron *= 0.9;
}else if (mobType.endsWith("champion ")){
iron *= 2.0;
}
}*/
player.addMoney(iron);
Item inventory = player.getInventory();
String coinMessage = Economy.getEconomy().getChangeFor(iron).getChangeString();
String strBuilder = "You are awarded " + coinMessage;
if((mob.isAggHuman() || mob.isMonster()) && !mob.isUnique() && !Servers.localServer.PVPSERVER){
Item creatureToken = ItemFactory.createItem(22765, 1+(99*random.nextFloat()), ""); // Creature Token ID: 22765
inventory.insertItem(creatureToken);
strBuilder += " and a "+creatureToken.getTemplate().getName();
}
strBuilder += " for slaying the "+mob.getName()+".";
player.getCommunicator().sendSafeServerMessage(strBuilder);
}catch (NoSuchTemplateException | FailedException | IOException e) {
e.printStackTrace();
}
} // checkPlayerReward
public static void checkPlayerBounty(Player player, Creature creature){
try {
//Map<Long, Long> attackers = ReflectionUtil.getPrivateField(creature, ReflectionUtil.getField(creature.getClass(), "attackers"));
Map<Long, Long> attackers = Bounty.getAttackers(creature);
if(!Bounty.isCombatant(attackers, player.getWurmId()) || creature.isPlayer() || creature.isReborn()){
return;
}
logger.info(player.getName()+" killed "+creature.getName());
checkPlayerReward(player, creature);
} catch (IllegalArgumentException | ClassCastException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,48 @@
package mod.sin.wyvern.invasion;
import java.util.HashSet;
import java.util.Random;
import com.wurmonline.server.Server;
import com.wurmonline.server.villages.Village;
import com.wurmonline.server.villages.Villages;
public class Invasion {
public static boolean active = false;
public static long lastInvasionPoll = 0;
public static HashSet<InvasionEvent> invasion = new HashSet<>();
public static void pollInvasions(){
long now = System.currentTimeMillis();
if(now - lastInvasionPoll > 360000){ // 1 hour
Random rand = new Random();
Village v = null;
int startx = 0;
int starty = 0;
while(v == null){
startx = rand.nextInt(4000);
starty = rand.nextInt(4000);
v = Villages.getVillage(startx, starty, true);
if(v != null){ continue; }
for (int x = -50; x < 50; x += 5) {
for (int y = -50; y < 50 && (v = Villages.getVillage(startx + x, starty + y, true)) == null; y += 5) {
}
}
}
try {
int minion1Id = 555;
int minion2Id = 666;
int bossId = 777;
String villageName = v.getName();
InvasionEvent event;
event = new InvasionEvent(startx, starty, villageName, bossId, minion1Id, minion2Id, rand.nextFloat()*100f);
invasion.add(event);
Server.getInstance().broadCastNormal("Whispers of a "+event.getPowerString()+" Necromancer circulate the area around "+villageName+"...");
//HistoryManager.addHistory("A "+event.getPowerString()+" Necromancer", "invades the area surrounding "+villageName+"!");
active = true;
lastInvasionPoll = now;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,41 @@
package mod.sin.wyvern.invasion;
import java.util.HashSet;
import java.util.Random;
import com.wurmonline.server.creatures.Creature;
public class InvasionEvent{
protected Random rand = new Random();
protected String villageName;
protected float power;
protected Creature invasionBoss;
protected HashSet<Creature> minions = new HashSet<>();
public InvasionEvent(int x, int y, String villageName, int bossId, int templateId1, int templateId2, float power) throws Exception{
this.villageName = villageName;
this.power = power;
this.invasionBoss = Creature.doNew(bossId, x, y, rand.nextFloat()*360f, 0, "Necromancer", (rand.nextBoolean() ? (byte)0 : (byte)1));
float halfPower = power / 2f;
int minionCount = (int) ((halfPower+(rand.nextFloat()*halfPower))/5f);
for(int i = 0; i < minionCount; i++){
minions.add(Creature.doNew((rand.nextBoolean() ? templateId1 : templateId2), x, y, rand.nextFloat()*360f, 0, "Minion", (rand.nextBoolean() ? (byte)0 : (byte)1)));
}
}
public String getPowerString(){
if(power > 95){
return "Legendary";
}else if(power > 80){
return "Powerful";
}else if(power > 60){
return "Strong";
}else if(power > 40){
return "Mediocre";
}else if(power > 20){
return "Weak";
}else{
return "Pathetic";
}
}
}

View File

@@ -0,0 +1,494 @@
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));
}
}

View File

@@ -0,0 +1,223 @@
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());
}
}

View File

@@ -0,0 +1,242 @@
package mod.sin.wyvern.mastercraft;
import java.util.Objects;
import java.util.logging.Logger;
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
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.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.BadBytecode;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import mod.sin.lib.Util;
public class Mastercraft {
private static Logger logger = Logger.getLogger(Mastercraft.class.getName());
public static double getNewDifficulty(Skill skill, double diff, Item item){
if(skill.affinity > 0){
diff -= skill.affinity;
}
if(skill.getKnowledge() > 99.0d){
diff -= 2d-((100d-skill.getKnowledge())*2d);
}
if(skill.getKnowledge() > 90.0d){
diff -= 2d-((100d-skill.getKnowledge())*0.2d);
}
if(item != null){
if(item.getRarity() > 0){
diff -= item.getRarity();
}
if(item.getCurrentQualityLevel() > 99.0f){
diff -= 1d-((100d-item.getCurrentQualityLevel())*1d);
}
if(item.getCurrentQualityLevel() > 90.0f){
diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d);
}
}
return diff;
}
public static float getCastPowerIncrease(Skill skill){
double addedPower = 0;
if(skill.affinity > 0){
addedPower += 2*skill.affinity;
}
if(skill.getKnowledge() > 0){
float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2);
}else{
logger.warning("Error: Some player just tried casting with no channeling skill!");
}
return (float) addedPower;
}
public static float getFavorCostMultiplier(Skill skill){
float mult = 1f;
if(skill.affinity > 0){
mult -= skill.affinity*0.02f; //2% reduction per affinity
}
if(skill.getKnowledge() > 90d){
mult -= 0.1d-((100d-skill.getKnowledge())*0.01d);
}
if(skill.getKnowledge() > 99d){
mult -= 0.1d-((100-skill.getKnowledge())*0.1d);
}
return mult;
}
public static void addNewTitles(){
try {
ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title");
// GM/Developer Titles
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 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");
// 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");
// 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", 701, "Holdstrong Architect", "Holdstrong Architect", -1, "NORMAL");
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Stronghold_Architect", 701, "Stronghold Architect", "Stronghold Architect", -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");
// 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.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);");
// - 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()");
return;
}
}
});
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()");
return;
}
}
});
}
} catch (CannotCompileException | NotFoundException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,123 @@
package mod.sin.wyvern.util;
import java.util.Random;
import java.util.logging.Logger;
import com.wurmonline.server.FailedException;
import com.wurmonline.server.Server;
import com.wurmonline.server.items.Item;
import com.wurmonline.server.items.ItemFactory;
import com.wurmonline.server.items.ItemList;
import com.wurmonline.server.items.ItemSpellEffects;
import com.wurmonline.server.items.NoSuchTemplateException;
import com.wurmonline.server.spells.SpellEffect;
import com.wurmonline.shared.constants.Enchants;
import mod.sin.items.EnchantOrb;
import mod.sin.items.TreasureBox;
public class ItemUtil {
public static final Logger logger = Logger.getLogger(ItemUtil.class.getName());
protected static final Random random = new Random();
public static int[] sorceryIds = {
ItemList.bloodAngels,
ItemList.smokeSol,
ItemList.slimeUttacha,
ItemList.tomeMagicRed,
ItemList.scrollBinding,
ItemList.cherryWhite,
ItemList.cherryRed,
ItemList.cherryGreen,
ItemList.giantWalnut,
ItemList.tomeEruption,
ItemList.wandOfTheSeas,
ItemList.libramNight,
ItemList.tomeMagicGreen,
ItemList.tomeMagicBlack,
ItemList.tomeMagicBlue,
ItemList.tomeMagicWhite
};
public static Item createEnchantOrb(float power){
byte[] enchantOrbEnchants = {
Enchants.BUFF_CIRCLE_CUNNING,
Enchants.BUFF_FLAMING_AURA,
Enchants.BUFF_SHARED_PAIN,
Enchants.BUFF_ROTTING_TOUCH,
Enchants.BUFF_LIFETRANSFER, Enchants.BUFF_LIFETRANSFER, // 2 rolls for LT
Enchants.BUFF_NIMBLENESS,
Enchants.BUFF_FROSTBRAND,
Enchants.BUFF_WEBARMOUR,
Enchants.BUFF_BLESSINGDARK, Enchants.BUFF_BLESSINGDARK, // 2 rolls for BotD
Enchants.BUFF_VENOM,
Enchants.BUFF_WIND_OF_AGES
};
try {
Item enchantOrb = ItemFactory.createItem(EnchantOrb.templateId, 99+(1*Server.rand.nextFloat()), "");
ItemSpellEffects effs = enchantOrb.getSpellEffects();
if(effs == null){
effs = new ItemSpellEffects(enchantOrb.getWurmId());
}
byte enchant = enchantOrbEnchants[Server.rand.nextInt(enchantOrbEnchants.length)];
SpellEffect eff = new SpellEffect(enchantOrb.getWurmId(), enchant, power, 20000000);
effs.addSpellEffect(eff);
enchantOrb.setDescription(eff.getName()+" "+Math.round(power));
return enchantOrb;
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
return null;
}
public static Item createRandomLootTool(){
try{
int[] templates = {7, 8, 20, 24, 25, 27, 62, 93, 97};
int template = templates[random.nextInt(templates.length)];
float quality = 100;
for(int i = 0; i < 3; i++){
quality = java.lang.Math.min(quality, java.lang.Math.max((float)10, 90*random.nextFloat()));
}
byte[] materials = {7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 30, 30, 31, 31, 34, 34, 56, 57, 67};
byte material = materials[random.nextInt(materials.length)];
byte rarity = 0;
if(random.nextInt(50) <= 2){
rarity = 1;
}else if(random.nextInt(200) <= 2){
rarity = 2;
}
byte[] enchants = {13, 13, 16, 16, 47};
byte enchant = enchants[random.nextInt(enchants.length)];
float power = 130;
for(int i = 0; i < 2; i++){
power = java.lang.Math.min(power, 30+(100*random.nextFloat()));
}
Item tool = ItemFactory.createItem(template, quality, material, rarity, "");
ItemSpellEffects effs = tool.getSpellEffects();
if(effs == null){
effs = new ItemSpellEffects(tool.getWurmId());
}
SpellEffect eff = new SpellEffect(tool.getWurmId(), enchant, power, 20000000);
effs.addSpellEffect(eff);
tool.setDescription(eff.getName()+" "+String.valueOf((byte)power));
return tool;
} catch (FailedException | NoSuchTemplateException e) {
e.printStackTrace();
}
return null;
}
public static Item createTreasureBox(){
try {
Item treasureBox = ItemFactory.createItem(TreasureBox.templateId, 10f+(90f*random.nextFloat()), "");
if(Server.rand.nextInt(20) == 0){
treasureBox.setRarity((byte) 3);
}else if(Server.rand.nextInt(5) == 0){
treasureBox.setRarity((byte) 2);
}else if(Server.rand.nextBoolean()){
treasureBox.setRarity((byte) 1);
}
return treasureBox;
} catch (FailedException | NoSuchTemplateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}