Initial Commit
This commit is contained in:
230
src/main/java/mod/sin/wyvern/AntiCheat.java
Normal file
230
src/main/java/mod/sin/wyvern/AntiCheat.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
244
src/main/java/mod/sin/wyvern/Bounty.java
Normal file
244
src/main/java/mod/sin/wyvern/Bounty.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
423
src/main/java/mod/sin/wyvern/Caches.java
Normal file
423
src/main/java/mod/sin/wyvern/Caches.java
Normal 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());
|
||||
}
|
||||
}
|
||||
130
src/main/java/mod/sin/wyvern/Crystals.java
Normal file
130
src/main/java/mod/sin/wyvern/Crystals.java
Normal 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;
|
||||
}
|
||||
}
|
||||
419
src/main/java/mod/sin/wyvern/ItemMod.java
Normal file
419
src/main/java/mod/sin/wyvern/ItemMod.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
943
src/main/java/mod/sin/wyvern/MiscChanges.java
Normal file
943
src/main/java/mod/sin/wyvern/MiscChanges.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
92
src/main/java/mod/sin/wyvern/Soulstealing.java
Normal file
92
src/main/java/mod/sin/wyvern/Soulstealing.java
Normal 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());
|
||||
}
|
||||
}
|
||||
382
src/main/java/mod/sin/wyvern/TreasureChests.java
Normal file
382
src/main/java/mod/sin/wyvern/TreasureChests.java
Normal 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));");*/
|
||||
}
|
||||
}
|
||||
322
src/main/java/mod/sin/wyvern/WyvernMods.java
Normal file
322
src/main/java/mod/sin/wyvern/WyvernMods.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1166
src/main/java/mod/sin/wyvern/arena/Arena.java
Normal file
1166
src/main/java/mod/sin/wyvern/arena/Arena.java
Normal file
File diff suppressed because it is too large
Load Diff
211
src/main/java/mod/sin/wyvern/arena/SupplyDepots.java
Normal file
211
src/main/java/mod/sin/wyvern/arena/SupplyDepots.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
470
src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java
Normal file
470
src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java
Normal 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);
|
||||
}
|
||||
}
|
||||
572
src/main/java/mod/sin/wyvern/bounty/LootBounty.java
Normal file
572
src/main/java/mod/sin/wyvern/bounty/LootBounty.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
221
src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java
Normal file
221
src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/main/java/mod/sin/wyvern/invasion/Invasion.java
Normal file
48
src/main/java/mod/sin/wyvern/invasion/Invasion.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java
Normal file
41
src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java
Normal 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
494
src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java
Normal file
494
src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java
Normal 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));
|
||||
}
|
||||
}
|
||||
223
src/main/java/mod/sin/wyvern/mastercraft/ExtendTitleEnum.java
Normal file
223
src/main/java/mod/sin/wyvern/mastercraft/ExtendTitleEnum.java
Normal 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());
|
||||
}
|
||||
}
|
||||
242
src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java
Normal file
242
src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
123
src/main/java/mod/sin/wyvern/util/ItemUtil.java
Normal file
123
src/main/java/mod/sin/wyvern/util/ItemUtil.java
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user